@bovinphang/craft-common 0.0.0-stage → 1.0.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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +12 -2
  3. package/dist/content/catalog.d.ts +4 -0
  4. package/dist/content/resources.d.ts +2 -0
  5. package/dist/content/types.d.ts +21 -0
  6. package/dist/index.d.ts +7 -0
  7. package/dist/index.js +668 -0
  8. package/dist/install/identity.d.ts +5 -0
  9. package/dist/install/planner.d.ts +6 -0
  10. package/dist/install/transaction.d.ts +7 -0
  11. package/dist/install/types.d.ts +44 -0
  12. package/docs/consuming-common.md +33 -0
  13. package/localized/zh-CN/methods/debug.md +13 -0
  14. package/localized/zh-CN/methods/doc-sync.md +12 -0
  15. package/localized/zh-CN/methods/refactoring.md +16 -0
  16. package/localized/zh-CN/methods/source-driven-development.md +19 -0
  17. package/localized/zh-CN/methods/tdd.md +13 -0
  18. package/localized/zh-CN/skills/cc-debug-methodology/SKILL.md +8 -0
  19. package/localized/zh-CN/skills/cc-debug-methodology/references/method.md +13 -0
  20. package/localized/zh-CN/skills/cc-doc-sync-core/SKILL.md +8 -0
  21. package/localized/zh-CN/skills/cc-doc-sync-core/references/method.md +12 -0
  22. package/localized/zh-CN/skills/cc-drawio-studio/SKILL.md +73 -0
  23. package/localized/zh-CN/skills/cc-drawio-studio/data/THIRD_PARTY_NOTICES.md +10 -0
  24. package/localized/zh-CN/skills/cc-drawio-studio/data/brand-icons.json +878 -0
  25. package/localized/zh-CN/skills/cc-drawio-studio/data/shape-index.json +83570 -0
  26. package/localized/zh-CN/skills/cc-drawio-studio/references/data-residency.md +27 -0
  27. package/localized/zh-CN/skills/cc-drawio-studio/references/diagram-patterns.md +60 -0
  28. package/localized/zh-CN/skills/cc-drawio-studio/references/flowchart-quality.md +49 -0
  29. package/localized/zh-CN/skills/cc-drawio-studio/references/layout-and-export.md +72 -0
  30. package/localized/zh-CN/skills/cc-drawio-studio/references/troubleshooting.md +29 -0
  31. package/localized/zh-CN/skills/cc-drawio-studio/references/xml-and-mermaid.md +58 -0
  32. package/localized/zh-CN/skills/cc-drawio-studio/scripts/brand-symbols.mjs +99 -0
  33. package/localized/zh-CN/skills/cc-drawio-studio/scripts/diagram-lint.mjs +205 -0
  34. package/localized/zh-CN/skills/cc-drawio-studio/scripts/diagram-url.mjs +102 -0
  35. package/localized/zh-CN/skills/cc-drawio-studio/scripts/drawio-export.mjs +134 -0
  36. package/localized/zh-CN/skills/cc-drawio-studio/scripts/layout-graph.mjs +107 -0
  37. package/localized/zh-CN/skills/cc-drawio-studio/scripts/png-embed-fix.mjs +26 -0
  38. package/localized/zh-CN/skills/cc-drawio-studio/scripts/scan-go-packages.mjs +36 -0
  39. package/localized/zh-CN/skills/cc-drawio-studio/scripts/scan-js-modules.mjs +52 -0
  40. package/localized/zh-CN/skills/cc-drawio-studio/scripts/scan-python-classes.mjs +30 -0
  41. package/localized/zh-CN/skills/cc-drawio-studio/scripts/scan-python-modules.mjs +55 -0
  42. package/localized/zh-CN/skills/cc-drawio-studio/scripts/scan-rust-modules.mjs +35 -0
  43. package/localized/zh-CN/skills/cc-drawio-studio/scripts/scan-ts-modules.mjs +7 -0
  44. package/localized/zh-CN/skills/cc-drawio-studio/scripts/shape-query.mjs +121 -0
  45. package/localized/zh-CN/skills/cc-drawio-studio/scripts/studio-core.mjs +139 -0
  46. package/localized/zh-CN/skills/cc-drawio-studio/styles/built-in/corporate.json +49 -0
  47. package/localized/zh-CN/skills/cc-drawio-studio/styles/built-in/default.json +49 -0
  48. package/localized/zh-CN/skills/cc-drawio-studio/styles/built-in/handdrawn.json +49 -0
  49. package/localized/zh-CN/skills/cc-drawio-studio/styles/schema.json +112 -0
  50. package/localized/zh-CN/skills/cc-refactoring-core/SKILL.md +8 -0
  51. package/localized/zh-CN/skills/cc-refactoring-core/references/method.md +16 -0
  52. package/localized/zh-CN/skills/cc-source-driven-development/SKILL.md +8 -0
  53. package/localized/zh-CN/skills/cc-source-driven-development/references/method.md +19 -0
  54. package/localized/zh-CN/skills/cc-tdd-methodology/SKILL.md +8 -0
  55. package/localized/zh-CN/skills/cc-tdd-methodology/references/method.md +13 -0
  56. package/localized/zh-CN/skills/cc-technical-diagrams/SKILL.md +34 -0
  57. package/localized/zh-CN/skills/cc-technical-diagrams/assets/interactive-diagram.html +371 -0
  58. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/README.md +14 -0
  59. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/architecture.json +121 -0
  60. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/invalid-explicit.json +41 -0
  61. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/sequence.json +53 -0
  62. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/sequence.mmd +21 -0
  63. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/workflow.json +98 -0
  64. package/localized/zh-CN/skills/cc-technical-diagrams/assets/quality-examples/workflow.mmd +7 -0
  65. package/localized/zh-CN/skills/cc-technical-diagrams/references/diagram-workflows.md +81 -0
  66. package/localized/zh-CN/skills/cc-technical-diagrams/references/html-technical-diagrams.md +243 -0
  67. package/localized/zh-CN/skills/cc-technical-diagrams/references/png-qa-autofix.md +37 -0
  68. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/diagram-browser.mjs +153 -0
  69. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/diagram-layout.mjs +176 -0
  70. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/export-diagram.mjs +332 -0
  71. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/interactive-diagram-server.mjs +654 -0
  72. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/mermaid-render.mjs +64 -0
  73. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/png-qa.mjs +462 -0
  74. package/localized/zh-CN/skills/cc-technical-diagrams/scripts/tech-diagram-render.mjs +1537 -0
  75. package/localized/zh-CN/skills/eval_queries.json +160 -0
  76. package/localized/zh-CN/skills/metadata.json +223 -0
  77. package/localized/zh-CN/skills/relations.json +53 -0
  78. package/methods/debug.md +13 -0
  79. package/methods/doc-sync.md +12 -0
  80. package/methods/refactoring.md +16 -0
  81. package/methods/source-driven-development.md +19 -0
  82. package/methods/tdd.md +13 -0
  83. package/package.json +51 -4
  84. package/skills/cc-debug-methodology/SKILL.md +8 -0
  85. package/skills/cc-debug-methodology/references/method.md +13 -0
  86. package/skills/cc-doc-sync-core/SKILL.md +8 -0
  87. package/skills/cc-doc-sync-core/references/method.md +12 -0
  88. package/skills/cc-drawio-studio/SKILL.md +73 -0
  89. package/skills/cc-drawio-studio/data/THIRD_PARTY_NOTICES.md +10 -0
  90. package/skills/cc-drawio-studio/data/brand-icons.json +878 -0
  91. package/skills/cc-drawio-studio/data/shape-index.json +83570 -0
  92. package/skills/cc-drawio-studio/references/data-residency.md +27 -0
  93. package/skills/cc-drawio-studio/references/diagram-patterns.md +60 -0
  94. package/skills/cc-drawio-studio/references/flowchart-quality.md +49 -0
  95. package/skills/cc-drawio-studio/references/layout-and-export.md +72 -0
  96. package/skills/cc-drawio-studio/references/troubleshooting.md +29 -0
  97. package/skills/cc-drawio-studio/references/xml-and-mermaid.md +58 -0
  98. package/skills/cc-drawio-studio/scripts/brand-symbols.mjs +99 -0
  99. package/skills/cc-drawio-studio/scripts/diagram-lint.mjs +205 -0
  100. package/skills/cc-drawio-studio/scripts/diagram-url.mjs +102 -0
  101. package/skills/cc-drawio-studio/scripts/drawio-export.mjs +134 -0
  102. package/skills/cc-drawio-studio/scripts/layout-graph.mjs +107 -0
  103. package/skills/cc-drawio-studio/scripts/png-embed-fix.mjs +26 -0
  104. package/skills/cc-drawio-studio/scripts/scan-go-packages.mjs +36 -0
  105. package/skills/cc-drawio-studio/scripts/scan-js-modules.mjs +52 -0
  106. package/skills/cc-drawio-studio/scripts/scan-python-classes.mjs +30 -0
  107. package/skills/cc-drawio-studio/scripts/scan-python-modules.mjs +55 -0
  108. package/skills/cc-drawio-studio/scripts/scan-rust-modules.mjs +35 -0
  109. package/skills/cc-drawio-studio/scripts/scan-ts-modules.mjs +7 -0
  110. package/skills/cc-drawio-studio/scripts/shape-query.mjs +121 -0
  111. package/skills/cc-drawio-studio/scripts/studio-core.mjs +139 -0
  112. package/skills/cc-drawio-studio/styles/built-in/corporate.json +49 -0
  113. package/skills/cc-drawio-studio/styles/built-in/default.json +49 -0
  114. package/skills/cc-drawio-studio/styles/built-in/handdrawn.json +49 -0
  115. package/skills/cc-drawio-studio/styles/schema.json +112 -0
  116. package/skills/cc-refactoring-core/SKILL.md +8 -0
  117. package/skills/cc-refactoring-core/references/method.md +16 -0
  118. package/skills/cc-source-driven-development/SKILL.md +8 -0
  119. package/skills/cc-source-driven-development/references/method.md +19 -0
  120. package/skills/cc-tdd-methodology/SKILL.md +8 -0
  121. package/skills/cc-tdd-methodology/references/method.md +13 -0
  122. package/skills/cc-technical-diagrams/SKILL.md +34 -0
  123. package/skills/cc-technical-diagrams/assets/interactive-diagram.html +371 -0
  124. package/skills/cc-technical-diagrams/assets/quality-examples/README.md +14 -0
  125. package/skills/cc-technical-diagrams/assets/quality-examples/architecture.json +121 -0
  126. package/skills/cc-technical-diagrams/assets/quality-examples/invalid-explicit.json +41 -0
  127. package/skills/cc-technical-diagrams/assets/quality-examples/sequence.json +53 -0
  128. package/skills/cc-technical-diagrams/assets/quality-examples/sequence.mmd +21 -0
  129. package/skills/cc-technical-diagrams/assets/quality-examples/workflow.json +98 -0
  130. package/skills/cc-technical-diagrams/assets/quality-examples/workflow.mmd +7 -0
  131. package/skills/cc-technical-diagrams/references/diagram-workflows.md +81 -0
  132. package/skills/cc-technical-diagrams/references/html-technical-diagrams.md +243 -0
  133. package/skills/cc-technical-diagrams/references/png-qa-autofix.md +37 -0
  134. package/skills/cc-technical-diagrams/scripts/diagram-browser.mjs +153 -0
  135. package/skills/cc-technical-diagrams/scripts/diagram-layout.mjs +176 -0
  136. package/skills/cc-technical-diagrams/scripts/export-diagram.mjs +332 -0
  137. package/skills/cc-technical-diagrams/scripts/interactive-diagram-server.mjs +654 -0
  138. package/skills/cc-technical-diagrams/scripts/mermaid-render.mjs +64 -0
  139. package/skills/cc-technical-diagrams/scripts/png-qa.mjs +462 -0
  140. package/skills/cc-technical-diagrams/scripts/tech-diagram-render.mjs +1537 -0
  141. package/skills/eval_queries.json +160 -0
  142. package/skills/metadata.json +223 -0
  143. package/skills/relations.json +53 -0
@@ -0,0 +1,98 @@
1
+ {
2
+ "schema_version": 1,
3
+ "diagram_type": "workflow",
4
+ "meta": {
5
+ "title": "Order approval and recovery"
6
+ },
7
+ "lanes": [
8
+ {
9
+ "id": "user",
10
+ "label": "User submission"
11
+ },
12
+ {
13
+ "id": "ops",
14
+ "label": "Approval and handling"
15
+ },
16
+ {
17
+ "id": "sys",
18
+ "label": "System execution"
19
+ }
20
+ ],
21
+ "nodes": [
22
+ {
23
+ "id": "start",
24
+ "lane": "user",
25
+ "col": 0,
26
+ "label": "Submit order request",
27
+ "type": "start"
28
+ },
29
+ {
30
+ "id": "check",
31
+ "lane": "ops",
32
+ "col": 1,
33
+ "label": "Check order completeness and approval eligibility",
34
+ "type": "decision"
35
+ },
36
+ {
37
+ "id": "approve",
38
+ "lane": "ops",
39
+ "col": 2,
40
+ "label": "Review manually and record the decision",
41
+ "type": "backend"
42
+ },
43
+ {
44
+ "id": "retry",
45
+ "lane": "user",
46
+ "col": 1,
47
+ "label": "Add missing evidence and resubmit",
48
+ "type": "waiting"
49
+ },
50
+ {
51
+ "id": "save",
52
+ "lane": "sys",
53
+ "col": 3,
54
+ "label": "Save approval and notify the applicant asynchronously",
55
+ "type": "database"
56
+ },
57
+ {
58
+ "id": "done",
59
+ "lane": "sys",
60
+ "col": 4,
61
+ "label": "Completed",
62
+ "type": "success"
63
+ }
64
+ ],
65
+ "edges": [
66
+ {
67
+ "from": "start",
68
+ "to": "check",
69
+ "label": "Submit for review"
70
+ },
71
+ {
72
+ "from": "check",
73
+ "to": "approve",
74
+ "label": "Complete information"
75
+ },
76
+ {
77
+ "from": "check",
78
+ "to": "retry",
79
+ "label": "More evidence needed",
80
+ "variant": "dashed"
81
+ },
82
+ {
83
+ "from": "retry",
84
+ "to": "check",
85
+ "label": "Review again"
86
+ },
87
+ {
88
+ "from": "approve",
89
+ "to": "save",
90
+ "label": "Approved"
91
+ },
92
+ {
93
+ "from": "save",
94
+ "to": "done",
95
+ "label": "Notification sent"
96
+ }
97
+ ]
98
+ }
@@ -0,0 +1,7 @@
1
+ flowchart TD
2
+ A([Submit order request]) --> B{Check order completeness and approval eligibility}
3
+ B -->|Complete information| C[Review manually and record the decision]
4
+ B -->|More evidence needed| D[Add missing evidence and resubmit]
5
+ D -->|Review again| B
6
+ C -->|Approved| E[(Save approval and notify the applicant asynchronously)]
7
+ E -->|Notification sent| F([Completed])
@@ -0,0 +1,81 @@
1
+ # Diagram Workflows
2
+
3
+ ## Source selection
4
+
5
+ | Diagram type | Preferred source | QA focus |
6
+ | ------------ | ---------------- | -------- |
7
+ | ER diagram | Mermaid ER, DBML, Graphviz, SVG | Cardinality labels, table names, key fields, crossing relations. |
8
+ | UML class | Mermaid class, PlantUML, Graphviz | Inheritance direction, method/property wrapping, package grouping. |
9
+ | Sequence | Mermaid sequence, PlantUML | Lifeline order, activation spans, async/return arrows, message text. |
10
+ | Technical architecture | draw.io, Mermaid/C4, HTML `architecture` IR, SVG/HTML | Layer grouping, trust boundaries, data flow direction, legends. |
11
+ | Agent / memory architecture | HTML `architecture` IR with semantic node types and flow arrows, SVG/HTML, draw.io | Read/write path separation, tool-call loops, memory tiers, retrieval labels, flow legend. |
12
+ | ML / deep learning | SVG/HTML/canvas | Tensor shapes, layer order, branch joins, repeated blocks, annotations. |
13
+ | Flowchart / process workflow | Mermaid flowchart, HTML `workflow` IR, SVG, draw.io | Decision labels, terminal states, loop-back readability, connector spacing, exception path clarity. |
14
+ | Live session sketch | Interactive local browser server | Incremental reveal, session isolation, readable labels after manual dragging, export handoff. |
15
+
16
+ ## Interactive live diagrams
17
+
18
+ Use the live route when the diagram is part of the conversation and the user benefits from seeing structure appear as it is generated. It is best for flow sketches, architecture drafts, short mind-map-like decompositions, and quick walkthroughs that may be dragged or relabeled before export.
19
+
20
+ Run the local server with:
21
+
22
+ ```bash
23
+ node skills/cc-technical-diagrams/scripts/interactive-diagram-server.mjs --port 6100
24
+ ```
25
+
26
+ Open `http://127.0.0.1:6100/?s=meaningful-session-id`, then send commands to `/cmd?s=meaningful-session-id`. Always use a unique session id for each diagram. Start with `init`, add nodes before edges, and keep each command small enough that the browser can update incrementally.
27
+
28
+ Supported commands are `init`, `node`, `edge`, `container`, `remove`, `clear`, `layout`, `title`, and `export`. Supported node types are `terminal`, `terminal-end`, `process`, `decision`, `service`, `database`, `success`, `error`, and `container`.
29
+
30
+ Use `/export?s=session-id&format=json`, `svg`, or `drawio` for server-side source handoff. Use the browser toolbar for PNG export. If the local server cannot start, use Mermaid, SVG, or HTML technical diagrams instead of blocking the user.
31
+
32
+ ## Minimum source manifest
33
+
34
+ When the rendering path allows it, save a layout manifest next to the PNG:
35
+
36
+ ```json
37
+ {
38
+ "canvas": { "width": 1280, "height": 720 },
39
+ "boxes": [
40
+ { "id": "api", "x": 80, "y": 120, "width": 220, "height": 96, "label": "API Gateway" }
41
+ ],
42
+ "connectors": [
43
+ { "id": "api-db", "from": "api", "to": "db", "points": [[300, 168], [560, 168]] }
44
+ ]
45
+ }
46
+ ```
47
+
48
+ Coordinates are PNG pixel coordinates after export. Boxes should cover visible label/node bounds, not just the center point.
49
+
50
+ ## Diagram repair playbook
51
+
52
+ - **Overlapping nodes:** increase rank/column spacing, split clusters, or move low-priority annotations into a legend.
53
+ - **Truncated labels:** widen the node, add manual line breaks, preserve the full text, and adjust source layout.
54
+ - **Connector through labels:** add waypoints, route orthogonally around boxes, or move labels above the segment.
55
+ - **Connector stacking:** separate parallel edges with different waypoints or bundle them with a shared labeled bus.
56
+ - **Edge clipping:** increase outer padding or export viewBox/canvas size.
57
+ - **Unreadable dense graph:** split into overview plus detail diagrams instead of shrinking everything.
58
+ - **Ambiguous arrow meaning:** add `flow` and a concise label rather than relying on color alone.
59
+
60
+ ## Architecture diagrams
61
+
62
+ Use HTML `architecture` IR when the user wants a browser-ready single file with explicit system topology, groups, trust boundaries, data flows, and PNG QA. Use draw.io when the diagram must preserve official vendor shapes, diagrams.net editing, or long-term manual ownership. Use Mermaid/C4 when the diagram should live primarily in Markdown or text documentation.
63
+
64
+ For agent, memory, RAG, tool-call, or multi-agent diagrams, use semantic architecture node types (`agent`, `model`, `memory`, `vectorstore`, `graphdb`, `tool`, `document`, `queue`, `browser`, `user`, `gateway`) instead of generic boxes when the shape helps explain the system. Use `flow` values (`control`, `data`, `read`, `write`, `async`, `feedback`) so read paths, write paths, events, and reasoning loops are visually distinct. Add `visual.style` only after the structure is clear.
65
+
66
+ For UML coverage, route class, ER, state-machine, activity, and sequence needs to deterministic sources first: Mermaid, PlantUML, HTML technical diagrams, SVG, or draw.io. Prefer draw.io when future manual editing or official notation libraries matter; prefer HTML/SVG when browser-ready handoff and PNG QA matter.
67
+
68
+ ## Process workflows
69
+
70
+ Use HTML `workflow` IR when the user wants a browser-ready process map, approval flow, automation runbook, incident workflow, or cyclical operating loop with lanes, numbered steps, actors, decisions, exception paths, and summary cards. Use `cc-drawio-studio` instead when the workflow must remain a `.drawio` file for diagrams.net editing, official shape libraries, manual swimlane maintenance, or stakeholder edits after handoff.
71
+
72
+ ## Export guidance
73
+
74
+ Prefer exporting at 2x scale for raster PNGs, then downsample only if text remains crisp. Keep the editable source committed or attached wherever future diagram changes are expected.
75
+
76
+
77
+ ## Quality delivery contract
78
+
79
+ Prefer local Mermaid for standard sequence/workflow diagrams, reuse cc-drawio-studio for manually editable architecture, and optionally use Graphviz for dense topology. Fall back to compatible JSON/HTML if local tools are missing, without automatic installation/downloads. Preview, standalone SVG and PNG share source theme styles; export with `--theme light|dark`. PNG export waits for fonts and measures text; use `--manifest source.layout.json --output-manifest image.actual.json` for scaled pixel coordinates. QA must read the actual manifest, not reuse estimated coordinates unchanged for a 2x PNG.
80
+
81
+ The extended manifest retains canvas/boxes/connectors and adds coordinateSpace, scale, measurement, groups, labels and issues. Group containment is not node overlap. New checks include node-text-overflow, label-content-loss, label-out-of-bounds, edge-label-collision, text-overlap and degenerate-connector. Legacy manifests retain estimated checks. Diagnose constrained explicit sizes/waypoints without dropping text, changing relationships or silently moving coordinates. Increasing export resolution cannot fix source overflow. Visually review the final PNG and record tool availability/version, theme, scale, repair rounds and remaining defects; report partial acceptance when unresolved.
@@ -0,0 +1,243 @@
1
+ # HTML Technical Diagrams
2
+
3
+ Use this route when a technical diagram should be easy to open in a browser, share as one file, switch dark/light themes, and export from the browser after visual QA.
4
+
5
+ This route complements, but does not replace, other diagram sources:
6
+
7
+ | Need | Prefer |
8
+ | ---- | ------ |
9
+ | Small markdown-maintained diagram | Mermaid, Graphviz, or SVG |
10
+ | Editable source for future manual changes | `cc-drawio-studio` and `.drawio` |
11
+ | Browser-ready themed technical diagram | HTML technical diagram route |
12
+ | Raster-first visual, poster, concept art, or image edit | Image generation or editing route |
13
+
14
+ ## Supported Diagram Intents
15
+
16
+ - `architecture`: system topology, system blueprints, deployment topology, cloud regions, trust boundaries, clients, gateways, services, data stores, event buses, auth flows, agent runtime maps, memory or recall overview diagrams, before/after architecture comparisons, and infrastructure overview diagrams.
17
+ - `workflow`: ownership lanes, process maps, approval gates, automation runs, exception paths, cyclical loops, runbooks, CI/CD, incident response, tool calls, and request lifecycles.
18
+ - `sequence`: participants over time, API call chains, cache fallback, auth checks, async traces, and return messages.
19
+ - `dataflow`: sources, ingest, processing, storage, consumers, PII boundaries, governance, analytics, and lineage.
20
+ - `lifecycle`: object states, terminal states, retries, waits, cancellation, timeout, deployment or order status transitions.
21
+
22
+ Use the `architecture` mode for browser-ready overview diagrams with explicit coordinates. Use `cc-drawio-studio` instead when the priority is `.drawio` source, official vendor icons, diagrams.net manual editing, or complex auto-layout.
23
+
24
+ ## Themed Semantic Diagrams
25
+
26
+ Use `visual.style` when the same JSON source needs a clearer delivery tone without changing its model: `default`, `terminal`, `blueprint`, `minimal`, `glass`, `warm`, `openai`, or `editorial-dark`.
27
+
28
+ For agent, memory, and AI workflow maps, prefer architecture nodes with semantic `type` values:
29
+
30
+ - Actors and entry points: `user`, `browser`, `gateway`.
31
+ - Intelligence and orchestration: `agent`, `model`, `tool`.
32
+ - Memory and knowledge: `memory`, `vectorstore`, `graphdb`, `document`.
33
+ - Runtime movement: `queue`, `messagebus`, `backend`, `external`.
34
+
35
+ Use connection `flow` values when arrows need meaning beyond visual direction:
36
+
37
+ - `control`: orchestration, policy, trigger, or command.
38
+ - `data`: request payloads, documents, embeddings, facts, or responses.
39
+ - `read`: retrieval from memory or stores.
40
+ - `write`: persistence, indexing, notes, or memory updates.
41
+ - `async`: evented or queued work.
42
+ - `feedback`: loops, retries, refinement, or reasoning cycles.
43
+
44
+ When two or more flow types are present, the renderer emits a flow legend automatically. Keep arrow labels short and use `waypoints` to route around dense groups, title labels, and node interiors.
45
+
46
+ ## System Blueprint Workflow
47
+
48
+ Use the architecture route for presentation-ready system blueprints, deployment topology, integration maps, agent runtime views, memory or recall maps, and before/after architecture comparisons. First extract a compact system model, then draw:
49
+
50
+ - Entry surfaces: browsers, mobile clients, CLIs, webhooks, schedulers, or agent/session entry points.
51
+ - Application layer: gateways, frontend apps, backend services, workers, orchestration, runtime hosts, and tool adapters.
52
+ - Data layer: databases, object stores, caches, vector stores, queues, event buses, logs, and analytics stores.
53
+ - External dependencies: identity providers, AI models, payment/email services, SaaS APIs, cloud services, design tools, or runtime connectors.
54
+ - Identity and trust boundaries: auth, permissions, PII zones, tenant boundaries, private networks, secret stores, and policy checks.
55
+ - Key flows: request/control flow, data flow, event flow, deployment flow, recall/memory flow, or before/after migration flow.
56
+
57
+ Keep the first blueprint readable:
58
+
59
+ - Show 4-10 primary nodes and collapse low-value files, classes, or endpoints into grouped nodes.
60
+ - Use 1-3 group boundaries for layers, trust zones, runtime environments, or ownership domains.
61
+ - Include a short title and subtitle that work when the file is shared outside the original conversation.
62
+ - Use a legend or up to three summary cards for runtime, data, trust, risks, inputs, or outcomes.
63
+ - Prefer semantic color roles over decorative styling, and split into multiple diagrams when connectors or labels become dense.
64
+
65
+ For README or stakeholder handoff, keep the JSON IR and HTML as the editable source, then export SVG/PNG/JPG artifacts:
66
+
67
+ ```bash
68
+ node skills/cc-technical-diagrams/scripts/export-diagram.mjs --input docs/architecture/system-blueprint.html --format svg
69
+ node skills/cc-technical-diagrams/scripts/export-diagram.mjs --input docs/architecture/system-blueprint.html --format png --scale 2
70
+ ```
71
+
72
+ Raster export uses an existing Chromium-family browser when available. If the environment cannot rasterize SVG, deliver the generated HTML/SVG and state that PNG/JPG export needs a local browser.
73
+
74
+ ## JSON IR
75
+
76
+ All modes require:
77
+
78
+ ```json
79
+ {
80
+ "schema_version": 1,
81
+ "diagram_type": "workflow",
82
+ "meta": {
83
+ "title": "Release Workflow",
84
+ "subtitle": "PR to production"
85
+ }
86
+ }
87
+ ```
88
+
89
+ Mode-specific minimum fields:
90
+
91
+ - `architecture`: `nodes`, `connections`; optional `groups`, `legend`, and `summary`.
92
+ - `workflow`: `lanes`, `nodes`, `edges`; optional `summary`.
93
+ - `sequence`: `participants`, `messages`.
94
+ - `dataflow`: `stages`, `nodes`, `flows`.
95
+ - `lifecycle`: `lanes`, `states`, `transitions`.
96
+
97
+ IDs must start with a letter and use only letters, numbers, `_`, and `-`. Keep labels short enough to read inside nodes; put long explanation in surrounding prose instead of the diagram.
98
+
99
+ ## Process Workflow IR
100
+
101
+ Workflow mode is for ordered processes where ownership, decisions, branches, and loop-backs matter more than exact infrastructure topology. Use lanes for actors or systems, nodes for steps, and edges for outcomes. Nodes still support explicit `col` placement so authors can control reading order without relying on a hidden auto-layout engine.
102
+
103
+ ```json
104
+ {
105
+ "schema_version": 1,
106
+ "diagram_type": "workflow",
107
+ "meta": {
108
+ "title": "Procurement Approval",
109
+ "subtitle": "Request to payment"
110
+ },
111
+ "lanes": [
112
+ { "id": "requester", "label": "Requester" },
113
+ { "id": "system", "label": "System" },
114
+ { "id": "manager", "label": "Manager" }
115
+ ],
116
+ "nodes": [
117
+ { "id": "start", "lane": "requester", "col": 0, "type": "start", "label": "Submit Request", "actor": "Employee" },
118
+ { "id": "classify", "lane": "system", "col": 1, "type": "active", "label": "Classify Spend", "actor": "Policy Engine", "sublabel": "auto rules" },
119
+ { "id": "review", "lane": "manager", "col": 2, "type": "decision", "label": "Approved?", "step": "A" },
120
+ { "id": "pay", "lane": "system", "col": 3, "type": "success", "label": "Issue Payment" },
121
+ { "id": "reject", "lane": "requester", "col": 3, "type": "failure", "label": "Return Request" }
122
+ ],
123
+ "edges": [
124
+ { "from": "start", "to": "classify", "label": "intake", "variant": "emphasis" },
125
+ { "from": "classify", "to": "review", "label": "policy result" },
126
+ { "from": "review", "to": "pay", "label": "yes", "variant": "emphasis" },
127
+ { "from": "review", "to": "reject", "label": "no", "variant": "return", "waypoints": [[650, 396], [520, 396]] }
128
+ ],
129
+ "summary": [
130
+ { "title": "Inputs", "type": "active", "items": ["Purchase request", "Policy threshold"] },
131
+ { "title": "Outcomes", "type": "success", "items": ["Payment issued", "Requester notified"] }
132
+ ]
133
+ }
134
+ ```
135
+
136
+ Workflow node fields:
137
+
138
+ - `type`: use `start`, `active`, `waiting`, `decision`, `success`, `failure`, or `external` for process semantics.
139
+ - `actor`: optional short owner or system label above the node.
140
+ - `step`: optional displayed step marker. If omitted, workflow nodes receive sequential markers automatically.
141
+ - `sublabel`, `width`, `height`, and `yOffset`: optional readability adjustments for dense lanes.
142
+
143
+ Workflow edge fields:
144
+
145
+ - `variant`: use `emphasis` for happy paths, `return` or `dashed` for loop-backs and rework, and `security` only for trust or policy checks.
146
+ - `waypoints`: optional `[x, y]` points for exception paths, cross-row links, or loops that should avoid labels and nodes.
147
+
148
+ Use `summary` for compact process metadata such as prerequisites, inputs/outputs, or tools. Keep long explanations outside the SVG so labels remain readable.
149
+
150
+ ## Architecture IR
151
+
152
+ Architecture mode uses explicit coordinates because system diagrams often need intentional placement, boundaries, and trust zones:
153
+
154
+ ```json
155
+ {
156
+ "schema_version": 1,
157
+ "diagram_type": "architecture",
158
+ "meta": {
159
+ "title": "SaaS Architecture",
160
+ "subtitle": "Browser-ready infrastructure overview"
161
+ },
162
+ "visual": {
163
+ "style": "blueprint"
164
+ },
165
+ "groups": [
166
+ { "id": "cloud", "label": "Cloud region", "type": "cloud", "x": 170, "y": 50, "width": 620, "height": 280 }
167
+ ],
168
+ "nodes": [
169
+ { "id": "web", "label": "Web App", "type": "frontend", "x": 48, "y": 160, "sublabel": "React" },
170
+ { "id": "api", "label": "API Gateway", "type": "cloud", "x": 230, "y": 160, "group": "cloud" },
171
+ { "id": "svc", "label": "App Service", "type": "backend", "x": 420, "y": 160, "group": "cloud" },
172
+ { "id": "db", "label": "PostgreSQL", "type": "database", "x": 620, "y": 160, "group": "cloud" }
173
+ ],
174
+ "connections": [
175
+ { "from": "web", "to": "api", "label": "HTTPS", "variant": "emphasis" },
176
+ { "from": "api", "to": "svc", "label": "REST" },
177
+ { "from": "svc", "to": "db", "label": "SQL" }
178
+ ],
179
+ "summary": [
180
+ { "title": "Runtime", "type": "backend", "items": ["API and worker services", "Managed relational data"] }
181
+ ]
182
+ }
183
+ ```
184
+
185
+ Supported node and group types include `frontend`, `backend`, `database`, `cloud`, `security`, `messagebus`, `external`, `agent`, `model`, `memory`, `vectorstore`, `graphdb`, `tool`, `document`, `queue`, `browser`, `user`, and `gateway`. Connections support the standard variants `default`, `emphasis`, `security`, `dashed`, and `return`; architecture connections may also include `flow`. Add `waypoints` as `[[x, y], ...]` when a connection needs to route around boundaries or labels.
186
+
187
+ Architecture output includes an automatic legend unless `legend` is set to `false`. A custom legend can be supplied as `{ "label": "...", "type": "..." }` items. `summary` renders up to three cards below the SVG and is not included in the layout manifest, so PNG QA focuses on the diagram itself.
188
+
189
+ ## Architecture Layout Rules
190
+
191
+ - Draw groups as broad boundaries around components, not as decorative panels.
192
+ - Keep legends below or outside all boundaries; increase the coordinates and view area rather than squeezing content.
193
+ - Use `messagebus` nodes for event buses and place them in the gap between services.
194
+ - Use `security` connections for auth, token, policy, or trust-boundary flows.
195
+ - Prefer `waypoints` over dense crossing lines when gateways fan out to several services.
196
+ - Split the diagram when the overview needs more than one dense cluster or when label readability depends on shrinking text.
197
+
198
+ ## Render Command
199
+
200
+ ```bash
201
+ node skills/cc-technical-diagrams/scripts/tech-diagram-render.mjs \
202
+ --input diagram.json \
203
+ --output diagram.html \
204
+ --type architecture \
205
+ --manifest diagram.layout.json
206
+ ```
207
+
208
+ The generated HTML is self-contained and includes:
209
+
210
+ - Inline SVG.
211
+ - CSS-variable dark/light theme.
212
+ - Browser controls for theme toggle, SVG download, and print/PDF.
213
+ - Optional layout manifest for PNG QA.
214
+
215
+ ## QA and Repair
216
+
217
+ After exporting a PNG from the browser, run:
218
+
219
+ ```bash
220
+ node skills/cc-technical-diagrams/scripts/png-qa.mjs \
221
+ --png diagram.png \
222
+ --manifest diagram.layout.json \
223
+ --format markdown
224
+ ```
225
+
226
+ Repair the source JSON or rendering dimensions rather than editing pixels:
227
+
228
+ - Overlap: split dense lanes or add rows/lanes/stages.
229
+ - Truncated label: wrap complete labels, preserve text, or widen nodes.
230
+ - Connector through label: reduce edge labels or separate nearby nodes.
231
+ - Dense flow: split into overview and detail diagrams.
232
+ - Edge clipping: increase output space or simplify the path.
233
+
234
+ ## Delivery Notes
235
+
236
+ Deliver the `.html` source together with any exported SVG/PNG/JPG requested by the user. Report the route used, source file, exported file, QA result, and any naming or domain assumptions that still need human confirmation.
237
+
238
+
239
+ ## Quality delivery contract
240
+
241
+ Prefer local Mermaid for standard sequence/workflow diagrams, reuse cc-drawio-studio for manually editable architecture, and optionally use Graphviz for dense topology. Fall back to compatible JSON/HTML if local tools are missing, without automatic installation/downloads. Preview, standalone SVG and PNG share source theme styles; export with `--theme light|dark`. PNG export waits for fonts and measures text; use `--manifest source.layout.json --output-manifest image.actual.json` for scaled pixel coordinates. QA must read the actual manifest, not reuse estimated coordinates unchanged for a 2x PNG.
242
+
243
+ The extended manifest retains canvas/boxes/connectors and adds coordinateSpace, scale, measurement, groups, labels and issues. Group containment is not node overlap. New checks include node-text-overflow, label-content-loss, label-out-of-bounds, edge-label-collision, text-overlap and degenerate-connector. Legacy manifests retain estimated checks. Diagnose constrained explicit sizes/waypoints without dropping text, changing relationships or silently moving coordinates. Increasing export resolution cannot fix source overflow. Visually review the final PNG and record tool availability/version, theme, scale, repair rounds and remaining defects; report partial acceptance when unresolved.
@@ -0,0 +1,37 @@
1
+ # PNG QA And Autofix
2
+
3
+ ## Loop
4
+
5
+ 1. Export PNG from the editable source or image workflow.
6
+ 2. Inspect the PNG visually.
7
+ 3. Run `png-qa.mjs` with a manifest when available.
8
+ 4. Convert each issue into source, prompt, or layout changes.
9
+ 5. Repeat for 2 rounds by default, up to 5 when the user asks for more repair attempts.
10
+
11
+ ## Issue mapping
12
+
13
+ | Issue | Repair |
14
+ | ----- | ------ |
15
+ | `blank-image` | Check export target, renderer errors, hidden layers, transparent fill, or failed image generation. |
16
+ | `edge-clipping` | Add canvas padding, expand SVG viewBox, reduce subject scale, or export a larger frame. |
17
+ | `box-overlap` | Increase spacing, reflow to grid/layers, split clusters, or wrap complete labels. |
18
+ | `box-out-of-bounds` | Move the node inside canvas or increase canvas dimensions. |
19
+ | `label-overflow` | Wrap text, widen the box, preserve complete copy, and increase font/container size together. |
20
+ | `connector-through-label` | Add waypoints around boxes, move labels, or use orthogonal routing. |
21
+ | `connector-stacking` | Offset parallel connectors or replace repeated lines with a labeled grouped path. |
22
+ | `manifest-canvas-mismatch` | Regenerate the manifest from final export dimensions. |
23
+
24
+ ## Manifest quality
25
+
26
+ The helper can only reason about overlaps and connectors when the manifest coordinates match the exported PNG. If the manifest is stale, repair the manifest first, then rerun QA.
27
+
28
+ ## Reporting
29
+
30
+ Report the number of QA rounds and the final issue list. If issues remain because the source renderer cannot expose layout coordinates, say which checks were image-only and which require manual visual review.
31
+
32
+
33
+ ## Quality delivery contract
34
+
35
+ Prefer local Mermaid for standard sequence/workflow diagrams, reuse cc-drawio-studio for manually editable architecture, and optionally use Graphviz for dense topology. Fall back to compatible JSON/HTML if local tools are missing, without automatic installation/downloads. Preview, standalone SVG and PNG share source theme styles; export with `--theme light|dark`. PNG export waits for fonts and measures text; use `--manifest source.layout.json --output-manifest image.actual.json` for scaled pixel coordinates. QA must read the actual manifest, not reuse estimated coordinates unchanged for a 2x PNG.
36
+
37
+ The extended manifest retains canvas/boxes/connectors and adds coordinateSpace, scale, measurement, groups, labels and issues. Group containment is not node overlap. New checks include node-text-overflow, label-content-loss, label-out-of-bounds, edge-label-collision, text-overlap and degenerate-connector. Legacy manifests retain estimated checks. Diagnose constrained explicit sizes/waypoints without dropping text, changing relationships or silently moving coordinates. Increasing export resolution cannot fix source overflow. Visually review the final PNG and record tool availability/version, theme, scale, repair rounds and remaining defects; report partial acceptance when unresolved.
@@ -0,0 +1,153 @@
1
+ // @ts-check
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { spawn, spawnSync } from "node:child_process";
6
+ import { pathToFileURL } from "node:url";
7
+
8
+ export function findBrowser() {
9
+ const candidates = [process.env.FEC_BROWSER_PATH,
10
+ "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe",
11
+ "C:/Program Files/Microsoft/Edge/Application/msedge.exe",
12
+ "C:/Program Files/Google/Chrome/Application/chrome.exe",
13
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
14
+ "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
15
+ "google-chrome", "chromium", "chromium-browser", "msedge", "brave-browser", "vivaldi"];
16
+ for (const candidate of candidates) {
17
+ if (!candidate) continue;
18
+ if (path.isAbsolute(candidate) ? fs.existsSync(candidate) : spawnSync(candidate, ["--version"], { timeout: 5000, windowsHide: true, stdio: "ignore" }).status === 0) return candidate;
19
+ }
20
+ return null;
21
+ }
22
+
23
+ /** @typedef {{evaluate:(expression:string)=>Promise<unknown>,screenshot:(width:number,height:number,scale?:number)=>Promise<Buffer>}} DiagramSession */
24
+
25
+ /**
26
+ * Export failures must stay within the wording callers match on, so CDP details are wrapped here.
27
+ * @param {string} detail @returns {Error}
28
+ */
29
+ const exportFailure = (detail) => new Error(`Browser raster export failed: ${detail}`);
30
+
31
+ /** @param {()=>string} read @param {number} deadline @returns {Promise<number>} */
32
+ export async function waitForDebuggingPort(read, deadline) {
33
+ while (Date.now() < deadline) {
34
+ try {
35
+ const value = read().split("\n")[0].trim();
36
+ const port = Number(value);
37
+ if (/^\d+$/.test(value) && Number.isInteger(port) && port > 0 && port <= 65535) return port;
38
+ } catch (error) {
39
+ const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
40
+ if (!["EBUSY", "ENOENT", "EPERM"].includes(code)) throw exportFailure(error instanceof Error ? error.message : String(error));
41
+ }
42
+ await new Promise((resolve) => setTimeout(resolve, Math.min(50, Math.max(0, deadline - Date.now()))));
43
+ }
44
+ throw exportFailure("browser debugging port did not become readable before the initialization deadline.");
45
+ }
46
+
47
+ /**
48
+ * The target URL can be advertised before its execution context has finished navigating.
49
+ * Retry only that initialization window; action failures must propagate without replaying exports.
50
+ * @param {DiagramSession['evaluate']} evaluate @param {string} url @param {number} deadline
51
+ */
52
+ export async function waitForDiagramReady(evaluate, url, deadline) {
53
+ while (Date.now() < deadline) {
54
+ try {
55
+ const ready = await evaluate(`(async()=>{if(location.href!==${JSON.stringify(url)})return false;if(document.readyState!=="complete")await new Promise(r=>window.addEventListener("load",r,{once:true}));await document.fonts.ready;await new Promise(r=>requestAnimationFrame(()=>requestAnimationFrame(r)));return true;})()`);
56
+ if (ready === true) return;
57
+ } catch (error) {
58
+ if (!(error instanceof Error) || !/^Browser raster export failed: (?:Execution context was destroyed|Cannot find default execution context)\.?$/.test(error.message)) throw error;
59
+ }
60
+ await new Promise((resolve) => setTimeout(resolve, Math.min(50, Math.max(0, deadline - Date.now()))));
61
+ }
62
+ throw exportFailure("diagram page did not become ready before the initialization deadline.");
63
+ }
64
+
65
+ /**
66
+ * Chromium keeps profile files locked until its whole process tree is gone, so cleanup waits for
67
+ * the process instead of sleeping a fixed amount. @param {ReturnType<typeof spawn>} child @param {number} ms @returns {Promise<void>}
68
+ */
69
+ const waitForExit = async (child, ms) => {
70
+ if (child.exitCode !== null) return;
71
+ /** @type {ReturnType<typeof setTimeout> | undefined} */
72
+ let timer;
73
+ await new Promise((resolve) => {
74
+ const finish = () => { if (timer) clearTimeout(timer); child.off("exit", finish); resolve(undefined); };
75
+ timer = setTimeout(finish, ms);
76
+ child.once("exit", finish);
77
+ });
78
+ };
79
+
80
+ /** @template T @param {string} html @param {{theme:'light'|'dark',timeoutMs:number}} options @param {(session:DiagramSession)=>Promise<T>} action @returns {Promise<T>} */
81
+ export async function withDiagramPage(html, options, action) {
82
+ const browser = findBrowser();
83
+ if (!browser) throw new Error("PNG/JPG export requires a local Chromium browser. Export SVG instead, or install a Chromium browser and rerun this command.");
84
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "fec-diagram-browser-"));
85
+ const page = path.join(dir, "diagram.html"), profile = path.join(dir, "profile");
86
+ fs.writeFileSync(page, html);
87
+ const child = spawn(browser, ["--headless=new", "--disable-gpu", "--no-first-run", "--no-default-browser-check", "--hide-scrollbars", "--remote-debugging-port=0", "--remote-allow-origins=http://localhost", `--user-data-dir=${profile}`, pathToFileURL(page).href], { windowsHide: true, stdio: "ignore" });
88
+ let childError = "";
89
+ child.on("error", (error) => { childError = error.message; });
90
+ /** @type {WebSocket | undefined} */
91
+ let socket;
92
+ /** @type {ReturnType<typeof setTimeout> | undefined} */
93
+ let timer;
94
+ try {
95
+ const work = async () => {
96
+ const deadline = Date.now() + Math.min(15000, options.timeoutMs);
97
+ const portFile = path.join(profile, "DevToolsActivePort");
98
+ while (!fs.existsSync(portFile) && Date.now() < deadline && (child.exitCode === null || child.exitCode === 0) && !childError) await new Promise((resolve) => setTimeout(resolve, 50));
99
+ if (!fs.existsSync(portFile)) throw exportFailure(`browser did not start a debugging session${childError ? ` (${childError})` : ""}.`);
100
+ const port = await waitForDebuggingPort(() => fs.readFileSync(portFile, "utf8"), deadline);
101
+ // Select the intended target first; the readiness handshake below also waits for its context.
102
+ /** @type {{webSocketDebuggerUrl?:string}|undefined} */
103
+ let target;
104
+ while (Date.now() < deadline) {
105
+ const pages = await (await fetch(`http://127.0.0.1:${port}/json/list`, { signal: AbortSignal.timeout(Math.min(5000, options.timeoutMs)) })).json();
106
+ target = pages.find(/** @param {{type:string,url:string}} p */ (p) => p.type === "page" && p.url === pathToFileURL(page).href);
107
+ if (target) break;
108
+ await new Promise((resolve) => setTimeout(resolve, 50));
109
+ }
110
+ if (!target?.webSocketDebuggerUrl) throw exportFailure("browser did not create a diagram page.");
111
+ socket = new WebSocket(target.webSocketDebuggerUrl);
112
+ await new Promise((resolve, reject) => { socket?.addEventListener("open", resolve, { once: true }); socket?.addEventListener("error", reject, { once: true }); });
113
+ /** @type {Map<number,{resolve:(value:Record<string,unknown>)=>void,reject:(reason:Error)=>void}>} */
114
+ const pending = new Map();
115
+ socket.addEventListener("close", () => { for (const entry of pending.values()) entry.reject(exportFailure("session closed before export completed.")); pending.clear(); });
116
+ let serial = 0;
117
+ socket.addEventListener("message", (event) => {
118
+ const message = JSON.parse(String(event.data));
119
+ const entry = pending.get(message.id);
120
+ if (!entry) return;
121
+ pending.delete(message.id);
122
+ if (message.error) entry.reject(exportFailure(message.error.message)); else entry.resolve(message.result ?? {});
123
+ });
124
+ /** @param {string} method @param {Record<string,unknown>} [params] @returns {Promise<Record<string,unknown>>} */
125
+ const call = (method, params = {}) => new Promise((resolve, reject) => { const id = ++serial; pending.set(id, { resolve, reject }); socket?.send(JSON.stringify({ id, method, params })); });
126
+ /** @param {string} expression */
127
+ const evaluate = async (expression) => {
128
+ const result = await call("Runtime.evaluate", { expression, awaitPromise: true, returnByValue: true });
129
+ if (result.exceptionDetails) throw new Error(`Diagram evaluation failed: ${JSON.stringify(result.exceptionDetails)}`);
130
+ return /** @type {{value?:unknown}} */ (result.result).value;
131
+ };
132
+ /** @type {DiagramSession} */
133
+ const session = { evaluate, screenshot: async (width, height, scale = 1) => {
134
+ await call("Emulation.setDeviceMetricsOverride", { width: Math.ceil(width), height: Math.ceil(height), deviceScaleFactor: scale, mobile: false });
135
+ const result = await call("Page.captureScreenshot", { format: "png", captureBeyondViewport: true, clip: { x: 0, y: 0, width, height, scale: 1 } });
136
+ return Buffer.from(String(result.data), "base64");
137
+ } };
138
+ await waitForDiagramReady(evaluate, pathToFileURL(page).href, deadline);
139
+ return await action(session);
140
+ };
141
+ return await Promise.race([work(), new Promise(/** @param {(reason:Error)=>void} reject */ (_, reject) => { timer = setTimeout(() => reject(exportFailure("export timed out.")), options.timeoutMs); })]);
142
+ } finally {
143
+ if (timer) clearTimeout(timer);
144
+ if (socket?.readyState === WebSocket.OPEN) socket.send(JSON.stringify({ id: 999999, method: "Browser.close" }));
145
+ // Browser.close is graceful, so wait for the process rather than guessing with a fixed sleep:
146
+ // Chromium's child processes keep profile files locked until the tree is gone.
147
+ await waitForExit(child, 2000);
148
+ socket?.close();
149
+ if (child.exitCode === null) child.kill();
150
+ // The Chromium profile is owned by this invocation only. Windows may release locks after exit.
151
+ try { fs.rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 200 }); } catch { /* A locked temporary profile can be removed by OS cleanup. */ }
152
+ }
153
+ }