ea 0.4.0 → 0.5.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 (529) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -0
  3. data/TODO.complete/01-t-xref-parsing.md +91 -0
  4. data/TODO.complete/02-per-label-geometry.md +50 -0
  5. data/TODO.complete/03-object-properties-constraints.md +57 -0
  6. data/TODO.complete/04-operation-params.md +37 -0
  7. data/TODO.complete/05-pdata-flag-matrix.md +52 -0
  8. data/TODO.complete/06-emf-image-rendering.md +34 -0
  9. data/TODO.complete/07-auxiliary-tables.md +47 -0
  10. data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
  11. data/TODO.complete/11-gml-xsd-generation.md +42 -0
  12. data/TODO.complete/13-shapescript-interpreter.md +28 -0
  13. data/TODO.complete/20-cli-diff.md +46 -0
  14. data/TODO.complete/21-cli-render.md +26 -0
  15. data/TODO.complete/22-cli-export.md +29 -0
  16. data/TODO.complete/23-cli-mdg.md +23 -0
  17. data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
  18. data/TODO.complete/31-public-send-cleanup.md +61 -0
  19. data/TODO.complete/32-spec-coverage.md +33 -0
  20. data/TODO.complete/33-blocked-parity-gaps.md +41 -0
  21. data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
  22. data/TODO.complete/37-cli-lint.md +32 -0
  23. data/TODO.complete/38-cli-query.md +26 -0
  24. data/TODO.complete/39-cli-info.md +23 -0
  25. data/TODO.complete/40-ocl-evaluator.md +31 -0
  26. data/TODO.complete/41-round-trip-spec.md +18 -0
  27. data/TODO.complete/42-html-diff-report.md +18 -0
  28. data/TODO.complete/43-json-schema-export.md +20 -0
  29. data/TODO.complete/44-remaining-qea-tables.md +40 -0
  30. data/TODO.complete/45-shapescript-extensions.md +25 -0
  31. data/TODO.complete/46-xsd-consolidation.md +20 -0
  32. data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
  33. data/TODO.complete/STATUS.md +109 -0
  34. data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
  35. data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
  36. data/TODO.diagrams/03-text-over-rendering.md +30 -0
  37. data/TODO.diagrams/04-rect-under-rendering.md +33 -0
  38. data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
  39. data/TODO.diagrams/06-group-layering-parity.md +39 -0
  40. data/TODO.diagrams/07-text-content-fidelity.md +65 -0
  41. data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
  42. data/TODO.diagrams/12-connector-labels.md +40 -0
  43. data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
  44. data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
  45. data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
  46. data/TODO.diagrams/14-center-header-text.md +33 -0
  47. data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
  48. data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
  49. data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
  50. data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
  51. data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
  52. data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
  53. data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
  54. data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
  55. data/TODO.diagrams/18-property-lookup-index.md +42 -0
  56. data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
  57. data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
  58. data/TODO.diagrams/20-split-labels-emitter.md +56 -0
  59. data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
  60. data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
  61. data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
  62. data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
  63. data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
  64. data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
  65. data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
  66. data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
  67. data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
  68. data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
  69. data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
  70. data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
  71. data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
  72. data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
  73. data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
  74. data/TODO.diagrams/36-instance-specification-model.md +42 -0
  75. data/TODO.diagrams/37-element-icon-decorations.md +41 -0
  76. data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
  77. data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
  78. data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
  79. data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
  80. data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
  81. data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
  82. data/TODO.diagrams/44-element-icon-decorations.md +34 -0
  83. data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
  84. data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
  85. data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
  86. data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
  87. data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
  88. data/TODO.diagrams/50-examples-parity.md +85 -0
  89. data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
  90. data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
  91. data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
  92. data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
  93. data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
  94. data/TODO.diagrams/56-package-contents-rendering.md +148 -0
  95. data/TODO.diagrams/57-instance-specification-model.md +100 -0
  96. data/TODO.diagrams/58-domain-model-note-text.md +67 -0
  97. data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
  98. data/TODO.diagrams/60-testschema-association-marker.md +40 -0
  99. data/TODO.diagrams/61-legend-block-rendering.md +55 -0
  100. data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
  101. data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
  102. data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
  103. data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
  104. data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
  105. data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
  106. data/TODO.diagrams/68-inherited-attributes.md +65 -0
  107. data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
  108. data/TODO.diagrams/70-mdg-technology-support.md +68 -0
  109. data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
  110. data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
  111. data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
  112. data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
  113. data/TODO.diagrams/75-plateau-text-gap.md +39 -0
  114. data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
  115. data/TODO.diagrams/77-basic-text-overrender.md +40 -0
  116. data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
  117. data/TODO.diagrams/79-architecture-backlog.md +65 -0
  118. data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
  119. data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
  120. data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
  121. data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
  122. data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
  123. data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
  124. data/TODO.diagrams/86-foreign-package-rule.md +62 -0
  125. data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
  126. data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
  127. data/TODO.diagrams/README.md +69 -0
  128. data/TODO.diagrams/STATUS.md +73 -0
  129. data/TODO.fixup/01-default-grouped-paths.md +34 -0
  130. data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
  131. data/TODO.fixup/03-diagram-font-inference.md +28 -0
  132. data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
  133. data/TODO.fixup/05-marker-registry-ocp.md +32 -0
  134. data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
  135. data/TODO.fixup/07-edge-attachment-formula.md +22 -0
  136. data/TODO.fixup/08-visual-diff-harness.md +28 -0
  137. data/TODO.fixup/09-extract-element-compartments.md +34 -0
  138. data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
  139. data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
  140. data/TODO.fixup/12-path-style-harmony.md +23 -0
  141. data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
  142. data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
  143. data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
  144. data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
  145. data/TODO.fixup/17-path-count-calibration.md +27 -0
  146. data/TODO.fixup/18-polygon-count-calibration.md +32 -0
  147. data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
  148. data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
  149. data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
  150. data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
  151. data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
  152. data/TODO.fixup/24-note-element-rendering.md +23 -0
  153. data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
  154. data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
  155. data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
  156. data/TODO.fixup/28-geometry-parser-identification.md +57 -0
  157. data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
  158. data/TODO.fixup/30-theme-system-stub.md +46 -0
  159. data/TODO.fixup/31-theme-value-object-registry.md +17 -0
  160. data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
  161. data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
  162. data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
  163. data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
  164. data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
  165. data/TODO.fixup/37-package-shape-rendering.md +22 -0
  166. data/TODO.fixup/38-note-element-rendering.md +15 -0
  167. data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
  168. data/TODO.fixup/40-connector-dashed-lines.md +15 -0
  169. data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
  170. data/TODO.fixup/42-textrenderer-centralization.md +10 -0
  171. data/TODO.fixup/43-colorresolver-unification.md +24 -0
  172. data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
  173. data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
  174. data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
  175. data/TODO.fixup/47-canvas-frame-inset.md +19 -0
  176. data/TODO.fixup/48-background-rect-format.md +15 -0
  177. data/TODO.fixup/49-all-samples-integration-test.md +17 -0
  178. data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
  179. data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
  180. data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
  181. data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
  182. data/TODO.fixup/54-diagram-theme-api.md +50 -0
  183. data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
  184. data/TODO.fixup/56-theme-yaml-files.md +65 -0
  185. data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
  186. data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
  187. data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
  188. data/TODO.fixup/60-cli-theme-option.md +22 -0
  189. data/TODO.fixup/61-theme-validation.md +28 -0
  190. data/TODO.fixup/62-theme-builder-dsl.md +31 -0
  191. data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
  192. data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
  193. data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
  194. data/TODO.fixup/66-styleex-writeback.md +22 -0
  195. data/TODO.fixup/67-delete-dead-code.md +28 -0
  196. data/TODO.fixup/68-figure-parity-status.md +82 -0
  197. data/TODO.fixup/69-package-polygon-rendering.md +54 -0
  198. data/TODO.fixup/70-tagged-values-compartment.md +39 -0
  199. data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
  200. data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
  201. data/TODO.fixup/73-delete-dead-transformations.md +14 -0
  202. data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
  203. data/TODO.fixup/75-visibility-legend-icons.md +23 -0
  204. data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
  205. data/TODO.fixup/77-canvas-frame-margins.md +28 -0
  206. data/TODO.fixup/78-note-element-rendering.md +30 -0
  207. data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
  208. data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
  209. data/TODO.fixup/81-figure-parity-current-state.md +63 -0
  210. data/config/qea_schema.yml +356 -0
  211. data/config/themes/119.yml +98 -0
  212. data/config/themes/default.yml +14 -0
  213. data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
  214. data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
  215. data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
  216. data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
  217. data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
  218. data/examples/exports/UmlModel_template/model.xml +23 -0
  219. data/examples/exports/basic/UML_EA.DTD +6856 -0
  220. data/examples/exports/basic/model.xml +8039 -0
  221. data/examples/exports/simple/UML_EA.DTD +6856 -0
  222. data/examples/exports/simple/model.xml +585 -0
  223. data/examples/exports/simple_example/UML_EA.DTD +6856 -0
  224. data/examples/exports/simple_example/model.xml +23 -0
  225. data/examples/exports/test/UML_EA.DTD +6856 -0
  226. data/examples/exports/test/model.xml +1638 -0
  227. data/examples/qea/basic.qea +0 -0
  228. data/frontend/README.md +51 -0
  229. data/frontend/dist/app.iife.js +24 -0
  230. data/frontend/dist/style.css +1 -0
  231. data/frontend/index.html +26 -0
  232. data/frontend/package-lock.json +2359 -0
  233. data/frontend/package.json +26 -0
  234. data/frontend/src/App.vue +59 -0
  235. data/frontend/src/app.ts +8 -0
  236. data/frontend/src/components/AppHeader.vue +127 -0
  237. data/frontend/src/components/AppSidebar.vue +119 -0
  238. data/frontend/src/components/ClassDetails.vue +247 -0
  239. data/frontend/src/components/DiagramView.vue +79 -0
  240. data/frontend/src/components/PackageDetails.vue +92 -0
  241. data/frontend/src/components/PackageTreeNode.vue +64 -0
  242. data/frontend/src/components/SearchResults.vue +48 -0
  243. data/frontend/src/components/WelcomeView.vue +87 -0
  244. data/frontend/src/shims-vue.d.ts +5 -0
  245. data/frontend/src/stores/dataStore.ts +79 -0
  246. data/frontend/src/stores/uiStore.ts +167 -0
  247. data/frontend/src/styles/main.css +1566 -0
  248. data/frontend/src/types.ts +221 -0
  249. data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
  250. data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
  251. data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
  252. data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
  253. data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
  254. data/frontend/tests/e2e/render.spec.ts +188 -0
  255. data/frontend/tsconfig.json +20 -0
  256. data/frontend/vite.config.ts +26 -0
  257. data/frontend/vitest.config.ts +8 -0
  258. data/lib/ea/cli/app.rb +57 -2
  259. data/lib/ea/cli/command/diagrams.rb +37 -28
  260. data/lib/ea/cli/command/diff.rb +46 -0
  261. data/lib/ea/cli/command/export.rb +80 -0
  262. data/lib/ea/cli/command/info.rb +75 -0
  263. data/lib/ea/cli/command/lint.rb +48 -0
  264. data/lib/ea/cli/command/mdg.rb +98 -0
  265. data/lib/ea/cli/command/query.rb +34 -0
  266. data/lib/ea/cli/command/render.rb +135 -0
  267. data/lib/ea/cli/command/svg.rb +8 -15
  268. data/lib/ea/cli/command.rb +7 -0
  269. data/lib/ea/diagram/display_config.rb +184 -0
  270. data/lib/ea/diagram.rb +4 -41
  271. data/lib/ea/diff/change.rb +30 -0
  272. data/lib/ea/diff/comparator.rb +82 -0
  273. data/lib/ea/diff/html_reporter.rb +91 -0
  274. data/lib/ea/diff.rb +15 -0
  275. data/lib/ea/export/json/generator.rb +42 -0
  276. data/lib/ea/export/json.rb +12 -0
  277. data/lib/ea/export/json_schema/generator.rb +77 -0
  278. data/lib/ea/export/json_schema.rb +12 -0
  279. data/lib/ea/export/plantuml/generator.rb +73 -0
  280. data/lib/ea/export/plantuml.rb +12 -0
  281. data/lib/ea/export/xmi/generator.rb +77 -0
  282. data/lib/ea/export/xmi.rb +11 -0
  283. data/lib/ea/export/xsd/class_mapping.rb +65 -0
  284. data/lib/ea/export/xsd/generator.rb +142 -0
  285. data/lib/ea/export/xsd/namespace_registry.rb +82 -0
  286. data/lib/ea/export/xsd.rb +19 -0
  287. data/lib/ea/export.rb +14 -0
  288. data/lib/ea/image/emf_renderer.rb +42 -0
  289. data/lib/ea/image.rb +12 -0
  290. data/lib/ea/lint/engine.rb +30 -0
  291. data/lib/ea/lint/lint_rule.rb +38 -0
  292. data/lib/ea/lint/offense.rb +18 -0
  293. data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
  294. data/lib/ea/lint/rules/duplicate_name.rb +28 -0
  295. data/lib/ea/lint/rules/missing_stereotype.rb +35 -0
  296. data/lib/ea/lint/rules/naming_convention.rb +44 -0
  297. data/lib/ea/lint/rules/orphan_element.rb +28 -0
  298. data/lib/ea/lint/rules.rb +14 -0
  299. data/lib/ea/lint.rb +13 -0
  300. data/lib/ea/mdg/document.rb +120 -0
  301. data/lib/ea/mdg/loader.rb +118 -0
  302. data/lib/ea/mdg/registry.rb +98 -0
  303. data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
  304. data/lib/ea/mdg/xml/applies_to.rb +18 -0
  305. data/lib/ea/mdg/xml/apply.rb +18 -0
  306. data/lib/ea/mdg/xml/content.rb +18 -0
  307. data/lib/ea/mdg/xml/documentation.rb +24 -0
  308. data/lib/ea/mdg/xml/stereotype.rb +28 -0
  309. data/lib/ea/mdg/xml/stereotypes.rb +18 -0
  310. data/lib/ea/mdg/xml/tag.rb +28 -0
  311. data/lib/ea/mdg/xml/tagged_values.rb +18 -0
  312. data/lib/ea/mdg/xml/technology.rb +28 -0
  313. data/lib/ea/mdg/xml/uml_profile.rb +22 -0
  314. data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
  315. data/lib/ea/mdg/xml.rb +24 -0
  316. data/lib/ea/mdg.rb +25 -0
  317. data/lib/ea/model/classifier.rb +4 -0
  318. data/lib/ea/model/constraint.rb +24 -0
  319. data/lib/ea/model/diagram.rb +85 -0
  320. data/lib/ea/model/diagram_connector.rb +34 -0
  321. data/lib/ea/model/diagram_element.rb +16 -0
  322. data/lib/ea/model/document.rb +47 -2
  323. data/lib/ea/model/ghost_label.rb +32 -0
  324. data/lib/ea/model/instance_specification.rb +34 -0
  325. data/lib/ea/model/legend.rb +43 -0
  326. data/lib/ea/model/legend_item.rb +26 -0
  327. data/lib/ea/model/note.rb +28 -0
  328. data/lib/ea/model/operation.rb +2 -0
  329. data/lib/ea/model/property.rb +2 -0
  330. data/lib/ea/model/relationship.rb +2 -0
  331. data/lib/ea/model/signal.rb +14 -0
  332. data/lib/ea/model/slot.rb +19 -0
  333. data/lib/ea/model.rb +8 -0
  334. data/lib/ea/ocl/evaluator.rb +94 -0
  335. data/lib/ea/ocl/nodes.rb +30 -0
  336. data/lib/ea/ocl/parser.rb +133 -0
  337. data/lib/ea/ocl/unsupported_error.rb +7 -0
  338. data/lib/ea/ocl.rb +13 -0
  339. data/lib/ea/qea/factory/document_builder.rb +24 -10
  340. data/lib/ea/qea/factory/generalization_builder.rb +9 -11
  341. data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
  342. data/lib/ea/qea/models/ea_author.rb +35 -0
  343. data/lib/ea/qea/models/ea_glossary.rb +34 -0
  344. data/lib/ea/qea/models/ea_image.rb +53 -0
  345. data/lib/ea/qea/models/ea_implement.rb +32 -0
  346. data/lib/ea/qea/models/ea_list.rb +42 -0
  347. data/lib/ea/qea/models/ea_object_effort.rb +34 -0
  348. data/lib/ea/qea/models/ea_object_problem.rb +37 -0
  349. data/lib/ea/qea/models/ea_object_require.rb +34 -0
  350. data/lib/ea/qea/models/ea_object_resource.rb +34 -0
  351. data/lib/ea/qea/models/ea_object_risk.rb +34 -0
  352. data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
  353. data/lib/ea/qea/models/ea_object_test.rb +35 -0
  354. data/lib/ea/qea/models/ea_object_trx.rb +34 -0
  355. data/lib/ea/qea/models/ea_operation.rb +7 -0
  356. data/lib/ea/qea/models/ea_palette.rb +30 -0
  357. data/lib/ea/qea/models/ea_palette_item.rb +36 -0
  358. data/lib/ea/qea/models/ea_phase.rb +40 -0
  359. data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
  360. data/lib/ea/qea/models/ea_secrypt.rb +34 -0
  361. data/lib/ea/qea/models/ea_version.rb +39 -0
  362. data/lib/ea/qea/models/ea_xref.rb +11 -1
  363. data/lib/ea/qea/models.rb +19 -0
  364. data/lib/ea/qea/services/database_loader.rb +22 -1
  365. data/lib/ea/query/builder.rb +108 -0
  366. data/lib/ea/query.rb +9 -0
  367. data/lib/ea/render/image_converter.rb +101 -0
  368. data/lib/ea/render.rb +10 -0
  369. data/lib/ea/shapescript/parser.rb +208 -0
  370. data/lib/ea/shapescript/renderer.rb +74 -0
  371. data/lib/ea/shapescript/shape.rb +34 -0
  372. data/lib/ea/shapescript.rb +24 -0
  373. data/lib/ea/sources/qea/adapter.rb +22 -5
  374. data/lib/ea/sources/qea/classifier_builder.rb +184 -7
  375. data/lib/ea/sources/qea/diagram_builder.rb +352 -24
  376. data/lib/ea/sources/qea/id_normalizer.rb +16 -1
  377. data/lib/ea/sources/qea/instance_builder.rb +113 -0
  378. data/lib/ea/sources/qea/legend_builder.rb +137 -0
  379. data/lib/ea/sources/qea/note_builder.rb +58 -0
  380. data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
  381. data/lib/ea/sources/qea/operation_builder.rb +1 -0
  382. data/lib/ea/sources/qea/package_builder.rb +16 -0
  383. data/lib/ea/sources/qea/relationship_builder.rb +21 -5
  384. data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
  385. data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
  386. data/lib/ea/sources/qea/xref/parser.rb +150 -0
  387. data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
  388. data/lib/ea/sources/qea/xref/record.rb +41 -0
  389. data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
  390. data/lib/ea/sources/qea/xref.rb +27 -0
  391. data/lib/ea/sources/qea.rb +4 -0
  392. data/lib/ea/sources/xmi/adapter.rb +80 -2
  393. data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
  394. data/lib/ea/sources/xmi/diagram_builder.rb +95 -18
  395. data/lib/ea/sources/xmi/extension_geometry_parser.rb +19 -2
  396. data/lib/ea/sources/xmi/extension_style_parser.rb +15 -2
  397. data/lib/ea/sources/xmi/note_builder.rb +46 -0
  398. data/lib/ea/sources/xmi/property_builder.rb +9 -0
  399. data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
  400. data/lib/ea/sources/xmi/tag_builder.rb +45 -0
  401. data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
  402. data/lib/ea/sources/xmi.rb +4 -0
  403. data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
  404. data/lib/ea/spa/output/single_file_strategy.rb +8 -2
  405. data/lib/ea/spa/output/strategy.rb +34 -0
  406. data/lib/ea/svg/connector_router.rb +134 -0
  407. data/lib/ea/svg/ea_emitter/background.rb +2 -3
  408. data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
  409. data/lib/ea/svg/ea_emitter/canvas.rb +56 -33
  410. data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
  411. data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
  412. data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
  413. data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
  414. data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
  415. data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
  416. data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
  417. data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
  418. data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
  419. data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
  420. data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
  421. data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
  422. data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
  423. data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
  424. data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
  425. data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
  426. data/lib/ea/svg/ea_emitter/connectors.rb +46 -12
  427. data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
  428. data/lib/ea/svg/ea_emitter/document.rb +15 -24
  429. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
  430. data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
  431. data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
  432. data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
  433. data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
  434. data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
  435. data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
  436. data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
  437. data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
  438. data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
  439. data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
  440. data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
  441. data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
  442. data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
  443. data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
  444. data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
  445. data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
  446. data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
  447. data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
  448. data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
  449. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
  450. data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
  451. data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
  452. data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
  453. data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
  454. data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
  455. data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
  456. data/lib/ea/svg/ea_emitter/element.rb +37 -0
  457. data/lib/ea/svg/ea_emitter/elements.rb +283 -95
  458. data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
  459. data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
  460. data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
  461. data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
  462. data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
  463. data/lib/ea/svg/ea_emitter/label.rb +23 -0
  464. data/lib/ea/svg/ea_emitter/labels.rb +93 -27
  465. data/lib/ea/svg/ea_emitter/layer.rb +20 -0
  466. data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
  467. data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
  468. data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
  469. data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
  470. data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
  471. data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
  472. data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
  473. data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
  474. data/lib/ea/svg/ea_emitter/marker.rb +37 -0
  475. data/lib/ea/svg/ea_emitter/markers.rb +351 -64
  476. data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
  477. data/lib/ea/svg/ea_emitter/style.rb +15 -0
  478. data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
  479. data/lib/ea/svg/ea_emitter.rb +33 -11
  480. data/lib/ea/svg/parity/checker.rb +105 -0
  481. data/lib/ea/svg/parity/source.rb +59 -0
  482. data/lib/ea/svg/parity/suite.rb +113 -0
  483. data/lib/ea/svg/parity.rb +14 -0
  484. data/lib/ea/svg.rb +2 -15
  485. data/lib/ea/theme/definition.rb +176 -0
  486. data/lib/ea/theme/loader.rb +125 -0
  487. data/lib/ea/theme/registry.rb +96 -0
  488. data/lib/ea/theme.rb +37 -0
  489. data/lib/ea/transformations.rb +5 -88
  490. data/lib/ea/version.rb +4 -1
  491. data/lib/ea.rb +14 -4
  492. data/lib/tasks/svg_bench.rake +87 -0
  493. data/lutaml-uml-0.5.1.gem +0 -0
  494. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
  495. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
  496. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
  497. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
  498. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
  499. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
  500. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
  501. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
  502. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
  503. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
  504. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
  505. metadata +449 -26
  506. data/lib/ea/diagram/configuration.rb +0 -379
  507. data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
  508. data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
  509. data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
  510. data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
  511. data/lib/ea/diagram/element_renderers.rb +0 -43
  512. data/lib/ea/diagram/extractor.rb +0 -566
  513. data/lib/ea/diagram/layout_engine.rb +0 -170
  514. data/lib/ea/diagram/path_builder.rb +0 -202
  515. data/lib/ea/diagram/style_parser.rb +0 -42
  516. data/lib/ea/diagram/style_resolver.rb +0 -291
  517. data/lib/ea/diagram/svg_renderer.rb +0 -274
  518. data/lib/ea/diagram/util.rb +0 -73
  519. data/lib/ea/svg/bounds_calculator.rb +0 -74
  520. data/lib/ea/svg/connector_path.rb +0 -138
  521. data/lib/ea/svg/element_box.rb +0 -256
  522. data/lib/ea/svg/renderer.rb +0 -77
  523. data/lib/ea/svg/style_resolver.rb +0 -72
  524. data/lib/ea/transformations/configuration.rb +0 -333
  525. data/lib/ea/transformations/format_registry.rb +0 -366
  526. data/lib/ea/transformations/parsers/base_parser.rb +0 -482
  527. data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
  528. data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
  529. data/lib/ea/transformations/transformation_engine.rb +0 -390
@@ -0,0 +1,22 @@
1
+ # 66 - StyleEx Write-Back (to_style_ex) on Diagram
2
+
3
+ ## Status: DONE (2026-07-26)
4
+
5
+ ## Context
6
+
7
+ Diagram has `style_ex_flags` (parse) but no `to_style_ex`
8
+ (serialize). This prevents writing theme changes back to the
9
+ QEA database.
10
+
11
+ ## What needs to change
12
+
13
+ 1. `Diagram#to_style_ex` merges current style_ex_flags with
14
+ theme_override_id, producing a new StyleEx string.
15
+ 2. Round-trip: parse → modify → serialize → parse yields same result.
16
+
17
+ ## Acceptance
18
+
19
+ - to_style_ex produces valid "Key=Value;..." string
20
+ - Theme ID is included in output
21
+ - Existing flags preserved
22
+ - New spec covers round-trip
@@ -0,0 +1,28 @@
1
+ # 67 - Dead Code Deletion (Complete)
2
+
3
+ ## Status: DONE (2026-07-26)
4
+
5
+ ## Deleted files
6
+ - `lib/ea/svg/ea_emitter/theme.rb` (superseded by `Ea::Theme::Definition`)
7
+ - `lib/ea/svg/ea_emitter/theme_registry.rb` (superseded by `Ea::Theme::Registry`)
8
+ - `lib/ea/svg/ea_emitter/theme_colors.rb` (fills now in `Definition#fills`)
9
+
10
+ ## Removed from EaEmitter module
11
+ - `Theme = ::Ea::Theme::Definition` alias
12
+ - `ThemeRegistry = ::Ea::Theme::Registry` alias
13
+ - `ThemeColors` module
14
+
15
+ ## Removed from Style constants
16
+ - `CONNECTOR_LINE`, `DIAMOND_FILLED`, `TRIANGLE_OPEN` (Connectors/Markers use dynamic methods)
17
+ - `ELEMENT_SHAPE_STROKE`, `ELEMENT_SHAPE_STROKE_WIDTH` (Elements uses inline)
18
+ - `HEADER_TEXT_FILL`, `DIVIDER_STROKE_WIDTH`, `ATTRIBUTE_TEXT_FILL` (unused)
19
+ - `BACKGROUND` (Background renderer hardcodes its own)
20
+ - Kept: `TEXT_GROUP` (used by 4 text-emitting renderers)
21
+
22
+ ## Fixed references
23
+ - `ColorResolver`: uses `theme.fill_for(classifier)` instead of removed `ThemeColors`
24
+ - `Elements`: uses inline `#000000` / `2` instead of removed `Style::ELEMENT_SHAPE_*`
25
+
26
+ ## Verification
27
+ - All 2291 specs pass
28
+ - Zero dead code remaining in EaEmitter
@@ -0,0 +1,82 @@
1
+ # 68 - Figure Parity Status Report
2
+
3
+ ## Status: ANALYZED (2026-07-26)
4
+
5
+ ## Current parity (185 plateau diagrams)
6
+
7
+ | Metric | Within tolerance | Mean abs diff |
8
+ |---|---|---|
9
+ | rect count ±1 | 51% (95/185) | 1 |
10
+ | polygon count ±1 | 69% (128/185) | 2 |
11
+ | path count ±2 | 49% (92/185) | 4 |
12
+ | font family match | 71% (133/185) | — |
13
+ | text count | — | 7 |
14
+
15
+ ## What the emitter gets RIGHT (verified via disassembly + triple comparison)
16
+
17
+ - SVG format strings: byte-exact match against EA's templates
18
+ (UTF-16LE format table at EA.exe offset 0x477c000)
19
+ - Group style format: `stroke_style + fill + stroke_color`
20
+ - Color encoding: BGR → RGB hex, opacity as byte/255.0
21
+ - Coordinate formatting: integers when whole, %.2f when fractional
22
+ - Layer ordering: background → frame → elements → connectors → labels
23
+ - Marker shapes: diamond (polygon), open triangle (polygon),
24
+ navigability arrow (path)
25
+ - Font resolution: element → theme → diagram-default → locale fallback
26
+ - Theme system: Ea::Theme::Definition/Registry/Loader with YAML config
27
+ - DisplayConfig: SuppressFOC, AttPub/Pri/Pro, ShowNotes, ShowBorder
28
+ - DiagramFrame: outer border + tab + label text (opt-in)
29
+ - TextRenderer: decimal coords + rotation transform + XML escaping
30
+ - Per-type stereotype labels: «DataType», «dataType», «interface», etc.
31
+
32
+ ## What BLOCKS full parity (data gaps, not code gaps)
33
+
34
+ ### 1. Input XMI version drift (49% of rect diff)
35
+ The plateau XMI we parse is a DIFFERENT version from the one EA
36
+ used to generate the reference SVGs. Some elements moved between
37
+ versions. Verified by comparing element positions:
38
+ - Ours: element at (10, 144, 300, 292)
39
+ - Ref: element at (10, 180, 300, 292)
40
+ Same element, different y position. Cannot fix without the
41
+ exact original XMI.
42
+
43
+ ### 2. Connector y-attachment offset (~20px gap)
44
+ Our ConnectorRouter computes edge-center attachment.
45
+ EA uses a different attachment formula that adds ~9px for
46
+ top-edge and varies for other edges. The formula requires
47
+ runtime tracing to extract — EA's geometry parser (FUN_03720c40)
48
+ is 6700 bytes of compiled C++ too complex to fully RE.
49
+
50
+ ### 3. Visibility toggle icons (3 missing rects per diagram)
51
+ 78 diagrams are missing exactly 3 small 17×17 px icon rects
52
+ per diagram. These are "feature visibility toggle" indicators
53
+ shown on some EA configurations. Not implementing due to
54
+ complexity vs marginal benefit.
55
+
56
+ ### 4. StyleEx not exposed via XMI (font mismatch on 29%)
57
+ EA's XMI export omits `t_diagram.StyleEx` (which carries
58
+ `Theme=:NNN`). Without this, we can't detect which diagrams
59
+ use Carlito vs Calibri vs Yu Gothic UI. The QEA loader (when
60
+ wired) will provide this data.
61
+
62
+ ## What WOULD close remaining gaps
63
+
64
+ 1. **QEA loader wiring**: parse QEA directly (not via XMI) to
65
+ get StyleEx, exact element positions, and connector geometry.
66
+ This eliminates ALL input data drift.
67
+ 2. **EA COM automation**: use EA's API directly to render SVGs
68
+ programmatically, bypassing our emitter entirely.
69
+ 3. **EA PDB symbol file**: enables full disassembly of the
70
+ connector routing math.
71
+
72
+ ## Conclusion
73
+
74
+ The emitter's CODE is complete — all format strings, style
75
+ constants, layer ordering, theme system, and display config
76
+ match EA's rendering pipeline. The remaining parity gaps are
77
+ data-driven (input version mismatch) and cannot be closed
78
+ without the exact source data EA used.
79
+
80
+ ## Files changed
81
+
82
+ None — analysis report only.
@@ -0,0 +1,54 @@
1
+ # 69 - Package Diagram Elements Render as Polygons
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## What changed
6
+
7
+ 1. `lib/ea/svg/ea_emitter/element/package_shape_renderer.rb` (NEW) —
8
+ emits two polygons per Package element:
9
+ - Body: `(left, top)` to `(right, bottom - 20)` (full element
10
+ width, element height minus the tab strip)
11
+ - Tab: `(left, top - 20)` to `(left + tab_width, top)` (sits ABOVE
12
+ the element's logical top, 20px tall)
13
+
14
+ 2. `lib/ea/svg/ea_emitter/element/filter.rb` — Filter now only skips
15
+ Classifier placeholders with empty name+properties. Packages are
16
+ always rendered.
17
+
18
+ 3. `lib/ea/svg/ea_emitter/elements.rb` — Added `render_shape`
19
+ dispatch: when the model element is an `Ea::Model::Package`, calls
20
+ `PackageShapeRenderer`; otherwise `ShapeRenderer` (rect).
21
+
22
+ 4. `lib/ea/model/document.rb` — `index_by_id` now aliases packages
23
+ under both `EAPK_<guid>` (the uml:Model hierarchy id) and
24
+ `EAID_<guid>` (the diagram element `subject=` ref). EA's XMI uses
25
+ these two prefixes inconsistently — diagram elements always
26
+ reference via `EAID_`, but packages are stored under `EAPK_`.
27
+
28
+ 5. `lib/ea/svg/ea_emitter/bounds_calculator.rb` — Adds
29
+ `package_tab_points` source so the canvas reserves 20px above
30
+ each Package element for the tab polygon. Without this, tab
31
+ vertices dip into negative coordinates.
32
+
33
+ 6. `lib/ea/svg/ea_emitter/document.rb` — `frame:` now defaults to
34
+ `true` (every diagram has a frame in EA's output).
35
+
36
+ 7. `spec/ea/svg/ea_emitter/document_spec.rb` — New specs for the
37
+ EAPK↔EAID alias and the polygon body+tab emission.
38
+
39
+ ## Acceptance
40
+
41
+ - simple.qea "Package Contents" emits 11 polygons, matching the
42
+ reference SVG byte-for-byte in count and shape structure.
43
+ - basic.xmi "Package Dependencies" emits 10 polygons, matching.
44
+ - Logical/Class diagrams still emit rects for Classifiers (no
45
+ Package polygons).
46
+ - All 2285 specs pass.
47
+
48
+ ## Remaining gap (canvas size)
49
+
50
+ Our canvas is ~40px narrower and ~26px shorter than the reference.
51
+ EA appears to reserve extra margin around the frame outer border
52
+ (non-uniform: ~35px left, ~50px right, ~60px top, ~36px bottom).
53
+ Closing this requires either parsing t_diagram cx/cy fields or
54
+ hard-coding per-diagram-type insets. Tracked separately.
@@ -0,0 +1,39 @@
1
+ # 70 - Tagged Values Compartment Rendering
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## What changed
6
+
7
+ 1. `lib/ea/sources/xmi/tag_builder.rb` (NEW) — Parses
8
+ `<xmi:Extension>/<elements>/<element>/<tags>/<tag/>` blocks via
9
+ Nokogiri (the xmi gem doesn't expose Sparx tags directly).
10
+ Groups tags by their `modelElement` attribute and strips the
11
+ `#NOTES#...` suffix EA appends to the value attribute.
12
+
13
+ 2. `lib/ea/sources/xmi/adapter.rb` — Calls TagBuilder, attaches the
14
+ resulting TaggedValue arrays to the owning Classifier and
15
+ Package objects. Handles the EAPK_↔EAID_ alias for packages.
16
+
17
+ 3. `lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb` (NEW) —
18
+ Emits an italic "tags" header followed by `key = value` lines
19
+ for each tagged value, matching EA's encoding.
20
+
21
+ 4. `lib/ea/svg/ea_emitter/elements.rb` —
22
+ `groups_for` now invokes `TaggedValueRenderer` when the
23
+ classifier has tagged_values. `CompartmentGeometry` gains
24
+ `tagged_values_count` + `tagged_value_first_y`.
25
+ `has_content_below_header?` now treats tagged values as
26
+ content (so the divider renders).
27
+
28
+ 5. `lib/ea/svg/ea_emitter/element.rb` — autoload for
29
+ TaggedValueRenderer.
30
+
31
+ 6. `lib/ea/sources/xmi.rb` — autoload for TagBuilder.
32
+
33
+ ## Acceptance
34
+
35
+ - AcmeUmlClass in simple.xmi renders the "tags" header plus
36
+ isCollection and noPropertyType lines.
37
+ - Text count on diagrams with tagged classifiers increases
38
+ proportionally.
39
+ - All 2285 specs pass.
@@ -0,0 +1,37 @@
1
+ # 71 - Auto-Detect Theme from QEA StyleEx via XMI
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## What changed
6
+
7
+ `lib/ea/sources/xmi/diagram_builder.rb` — `build_one` now reads
8
+ `ext_diagram.style2.value` and assigns it to the Diagram's
9
+ `style_ex` attribute. EA stores StyleEx in the XMI's `<style2>`
10
+ element (alongside Style1 in `<style1>`). The value carries
11
+ `Theme=:119`, `SuppressFOC=1`, `AttPkg=1`, etc. — the same shape
12
+ the Diagram model already parses via `style_ex_flags` and
13
+ `display_config`.
14
+
15
+ This means: diagrams from sample XMI files now auto-resolve Theme
16
+ :119 (Carlito 7pt) without any manual theme setting.
17
+
18
+ ## What was wrong before
19
+
20
+ The Xmi adapter was dropping `style2` entirely, so `style_ex` was
21
+ always nil. The Theme system worked correctly given a StyleEx
22
+ string — there was just no code path populating StyleEx from XMI.
23
+
24
+ ## Acceptance
25
+
26
+ - simple.xmi "Package Contents" auto-detects Carlito 7pt without
27
+ any manual intervention (previously emitted Calibri 13px).
28
+ - New spec asserts that `diagram.style_ex` includes "Theme=:119"
29
+ and `diagram.theme.font_family` equals "Carlito".
30
+ - All 2286 specs pass.
31
+
32
+ ## Why Option A from the original TODO was wrong
33
+
34
+ The original TODO assumed XMI omitted StyleEx and proposed
35
+ heuristic detection from element styles. In reality, XMI DOES
36
+ carry StyleEx via the style2 element — the previous Xmi adapter
37
+ was simply dropping it.
@@ -0,0 +1,37 @@
1
+ # 72 - Use Sample Exports as Regression Specs
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## What changed
6
+
7
+ `spec/ea/svg/sample_exports_regression_spec.rb` (NEW) — renders
8
+ every diagram from `examples/exports/*/model.xml` (220 diagrams
9
+ across 5 sample projects) and compares total shape counts
10
+ (rect + polygon + path) against the corresponding reference SVG
11
+ in `examples/exports/*/images/`.
12
+
13
+ Two specs:
14
+ 1. "matches reference element counts within tolerance for most
15
+ diagrams" — asserts at least 60% of diagrams are within 20%
16
+ (or 5, whichever is larger) of the reference total.
17
+ 2. "renders every diagram without raising" — runs the emitter on
18
+ every diagram and asserts no exceptions.
19
+
20
+ ## Current parity (measured by this spec)
21
+
22
+ - 178/220 diagrams within tolerance (81%)
23
+ - 42 diagrams over tolerance (mostly plateau diagrams with 6-18
24
+ element delta)
25
+
26
+ ## Why combined rect+polygon+path
27
+
28
+ EA swaps rect↔polygon based on shape type (Classifier=rect,
29
+ Package=polygon). Comparing each shape count independently would
30
+ double-penalize shape-type swaps that are actually correct. The
31
+ combined total reflects "did we emit the right number of shapes?"
32
+
33
+ ## Acceptance
34
+
35
+ - Spec covers all 220 sample diagrams.
36
+ - Passes at >60% threshold (currently 81%).
37
+ - Reports first 5 failures when threshold not met.
@@ -0,0 +1,14 @@
1
+ # 73 - Delete dead Transformations subsystem
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ Removed `lib/ea/transformations/parsers/` (BaseParser, QeaParser,
6
+ XmiParser), `format_registry.rb`, `transformation_engine.rb`,
7
+ `configuration.rb`, plus their specs.
8
+
9
+ Production entry points (`Ea::Transformations.parse` and `.to_uml`)
10
+ already bypassed these wrappers and called `Ea::Qea.load`,
11
+ `Ea::Xmi.load`, and `Ea::Bridge::*` directly. The "engine" layer was
12
+ dead weight that only specs referenced.
13
+
14
+ Slimmed `lib/ea/transformations.rb` from 130 lines to 47.
@@ -0,0 +1,18 @@
1
+ # 74 - Delete dead Diagram legacy renderers
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ Removed `lib/ea/diagram/{svg_renderer, layout_engine, style_parser,
6
+ path_builder, style_resolver, configuration, util, element_renderers,
7
+ extractor}.rb` plus their specs. These served the legacy
8
+ lutaml-uml-backed rendering pipeline that was already replaced by
9
+ `Ea::Svg::EaEmitter`.
10
+
11
+ Kept:
12
+ - `lib/ea/diagram/display_config.rb` — used by `Ea::Model::Diagram`
13
+ - (extractor moved to modern pipeline; see below)
14
+
15
+ Rewrote `lib/ea/cli/command/diagrams.rb` `extract` action to use
16
+ `Ea::Sources::{Qea,Xmi}::Adapter` + `Ea::Svg::EaEmitter::Document`
17
+ directly, removing its dependency on lutaml-uml/Repository. The
18
+ `list` action now uses the same modern adapters.
@@ -0,0 +1,23 @@
1
+ # 75 - Visibility legend icons
2
+
3
+ ## Status: WONTFIX (2026-07-26)
4
+
5
+ ## Original hypothesis
6
+
7
+ 101 plateau diagrams were missing 3-4 small 17×17 rects per
8
+ diagram. Originally believed to be auto-generated visibility toggle
9
+ icons that EA emits as a column of color swatches.
10
+
11
+ ## Investigation finding
12
+
13
+ The 17×17 rects are actually manually-authored Note element content
14
+ (legend color swatches), not auto-generated UI elements. The Note
15
+ element's body text describes what each color represents (e.g.,
16
+ "GML classes", "CityGML classes"). Implementing this generically
17
+ would require parsing Note element intent, which is diagram-specific.
18
+
19
+ ## Resolution
20
+
21
+ Closed as wontfix. The Note element rendering (TODO 78) handles the
22
+ container; the legend swatches inside are user-authored content
23
+ that flows from the Note body via future layout work.
@@ -0,0 +1,27 @@
1
+ # 76 - Plateau text undershoot investigation
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## Root cause
6
+
7
+ `DisplayConfig` was mis-mapping `SuppressFOC=1` (suppress foreign
8
+ object content — embedded images/OLE) to "suppress feature
9
+ compartments" (attributes/operations). 60 percent of plateau
10
+ diagrams have `SuppressFOC=1` in their StyleEx, so they were
11
+ rendering without attribute compartments — losing 10-100+ text
12
+ elements per diagram.
13
+
14
+ ## Fix
15
+
16
+ Decoupled `show_attributes?` and `show_operations?` from
17
+ `SuppressFOC`. They now correctly check Style1 `HideAtts=1` and
18
+ `HideOps=1` (the actual EA UI flags for hiding compartments).
19
+
20
+ Restructured DisplayConfig to take both Style (style1) and StyleEx
21
+ (style2) since the visibility flags are split across both columns in
22
+ t_diagram.
23
+
24
+ ## Impact
25
+
26
+ Sample parity jumped from 178/220 (81 percent) to 193/220
27
+ (88 percent). The biggest single fix in this round.
@@ -0,0 +1,28 @@
1
+ # 77 - Canvas frame margins and connector Path= semantics
2
+
3
+ ## Status: PARTIAL (2026-07-26)
4
+
5
+ ## What changed
6
+
7
+ `ConnectorRouter#waypoints` was treating `Path=` values as relative
8
+ deltas from the source point, applying `src_pt + (dx, dy)`. The
9
+ `ExtensionGeometryParser` documentation says (and EA reference SVGs
10
+ confirm) these are ABSOLUTE pixel positions on the canvas.
11
+
12
+ Fixed by using bend points as-is. Plateau diagrams that had
13
+ connector endpoints at x=2700+ (vs element bounds max=1463) now
14
+ route correctly.
15
+
16
+ ## What remains
17
+
18
+ The canvas size still doesn't perfectly match the reference — EA
19
+ uses non-uniform frame margins (left=35, right=50, top=60,
20
+ bottom=36) plus a per-diagram "DocSize" override. Our
21
+ BoundsCalculator uses uniform 10px padding plus 20px reserved for
22
+ Package tabs.
23
+
24
+ Closing the remaining gap requires either:
25
+ 1. Parsing t_diagram.cx/cy fields for explicit canvas dimensions
26
+ 2. Hard-coding EA's non-uniform frame insets per diagram type
27
+
28
+ Deferred until more parity work justifies it.
@@ -0,0 +1,30 @@
1
+ # 78 - Note element rendering
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## What changed
6
+
7
+ - New `Ea::Model::Note` class (id, name, body, note_type)
8
+ - New `NoteBuilder` extracts Notes from `<xmi:Extension>/<elements>`
9
+ via `ext_element.type == "uml:Note"`. The note body comes from
10
+ `<properties documentation="..."/>`.
11
+ - `Document` gains a `notes` collection; `index_by_id` includes
12
+ them so diagram element `subject=EAID_...` refs resolve.
13
+ - New `Element::NoteShapeRenderer` emits:
14
+ - Folded-corner polygon (top-right corner cut)
15
+ - Diagonal fold line marking the dog-ear
16
+ - Body text with naive char-count-based word wrap
17
+ - `Elements#render_shape` dispatches to `NoteShapeRenderer` when
18
+ the model element `is_a?(Ea::Model::Note)`.
19
+
20
+ ## Acceptance
21
+
22
+ - Plateau document parses 27 Notes (was 0 before).
23
+ - 4 diagrams that place Notes on the canvas now render them.
24
+ - All 1596 specs pass.
25
+
26
+ ## Limitations
27
+
28
+ Text wrapping uses character count, not GDI text metrics. EA uses
29
+ the latter for accurate wrap points; matching it would require
30
+ platform-specific font metric tables.
@@ -0,0 +1,27 @@
1
+ # 79 - Operation compartment text rendering
2
+
3
+ ## Status: ANALYZED (2026-07-26)
4
+
5
+ ## Current state
6
+
7
+ `OperationRenderer` exists and emits operation signatures as text
8
+ lines. `Elements#groups_for` invokes it when the classifier has
9
+ operations AND `show_operations?` is true.
10
+
11
+ The Plateau parity failures showed large text over-rendering
12
+ (+68 on Tunnel diagram). Investigation revealed:
13
+
14
+ 1. We render `«DataType»` stereotype labels for every classifier
15
+ with a stereotype — ref SVGs only show stereotypes for some.
16
+ 2. We render the `tags` compartment + tagged value lines for every
17
+ classifier with tagged values — ref only shows them on 2/220
18
+ diagrams.
19
+
20
+ Both are visibility rule gaps, not Operation-specific bugs. The
21
+ OperationRenderer itself works correctly when invoked.
22
+
23
+ ## Why deferred
24
+
25
+ The actual rendering is correct; the gap is in WHEN to render.
26
+ Closing it requires understanding EA's stereotype-tagged-value
27
+ visibility rule (TODO 80).
@@ -0,0 +1,37 @@
1
+ # 80 - Tagged value and stereotype visibility rules
2
+
3
+ ## Status: TODO
4
+
5
+ ## Context
6
+
7
+ Only 2 of 220 reference SVGs in `examples/exports/` render a
8
+ "tags" header compartment, even though most plateau elements have
9
+ `Tag=1` in their per-element style and most classifiers have
10
+ tagged values from stereotype applications.
11
+
12
+ Likewise, the simple.xmi "Package A.1.1" reference shows
13
+ `«DataType»` for AcmeUmlClass, but the plateau Tunnel reference
14
+ does NOT show `«DataType»` for classifiers that also have
15
+ `stereotype="DataType"`.
16
+
17
+ ## What needs to change
18
+
19
+ 1. **Tagged value visibility rule**: Determine when EA actually
20
+ renders the tags compartment. Likely factors:
21
+ - Stereotype source (profile-applied vs user-defined tagged values)
22
+ - Element style `Tag=` flag semantics (currently parsed but unused)
23
+ - Diagram Style1 `ShowTags=` flag interaction
24
+
25
+ 2. **Stereotype label visibility rule**: Determine when EA renders
26
+ the `«Stereotype»` label. Hypotheses to verify:
27
+ - Ref SVGs show stereotypes only when the classifier is NOT
28
+ a "primitive" type or abstract base
29
+ - Show stereotypes only when they come from a non-default profile
30
+ - Show only when `HideElemStereo=0` AND the element is in a
31
+ specific diagram type
32
+
33
+ ## Acceptance
34
+
35
+ - Visibility rules documented with concrete EA behavior citations
36
+ - Implementation gates tagged value + stereotype rendering
37
+ - Sample parity improves from 88 percent toward 95 percent+
@@ -0,0 +1,63 @@
1
+ # 81 - Figure parity current state and roadmap
2
+
3
+ ## Status: LIVING DOCUMENT (2026-07-26)
4
+
5
+ ## Where we are
6
+
7
+ - **193/220 sample diagrams (88%)** render within shape-count
8
+ tolerance of EA's reference SVGs.
9
+ - **1596 specs, all passing.**
10
+ - **Major code cleanup**: removed 695 legacy spec examples and
11
+ ~3000 lines of dead production code (Transformations engine,
12
+ Diagram legacy renderers).
13
+
14
+ ## What's working
15
+
16
+ - Theme system auto-detects Theme=:119 (Carlito 7pt) from XMI
17
+ style2 attribute.
18
+ - DisplayConfig correctly reads HideAtts/HideOps (Style1) and
19
+ SuppressFOC/AttPub (StyleEx) as separate concerns.
20
+ - Packages render as polygon body+tab (matching EA folder shape).
21
+ - Notes render as folded-corner rect with body text.
22
+ - Tagged values render when classifier has them.
23
+ - Connector Path= coordinates treated as absolute (matching EA
24
+ reference SVG geometry).
25
+ - Per-element Tag flag, EAPK↔EAID alias for package lookups,
26
+ frame border+tab always rendered.
27
+
28
+ ## What's still off (and where the 12% gap lives)
29
+
30
+ ### 1. Stereotype label visibility (TODO 80)
31
+ We render `«DataType»` for every classifier with a stereotype,
32
+ but reference SVGs only render some. The rule appears to be
33
+ profile-specific (GML stereotypes shown, others hidden) but not
34
+ yet characterized.
35
+
36
+ ### 2. Tagged value visibility (TODO 80)
37
+ Only 2/220 reference diagrams show the "tags" compartment, but
38
+ we render it on every classifier with tagged values. Likely
39
+ tied to the same stereotype visibility rule.
40
+
41
+ ### 3. Canvas size non-parity (TODO 77)
42
+ Our canvas is ~40px narrower and ~26px shorter than reference
43
+ due to non-uniform EA frame margins (left=35, right=50, top=60,
44
+ bottom=36). Functional but visually offset.
45
+
46
+ ### 4. Visibility toggle icons (TODO 75 — wontfix)
47
+ 3-4 small 17×17 colored rects appear on a few diagrams as
48
+ manually-authored Note element legend content. Not a generic
49
+ feature; closed as wontfix.
50
+
51
+ ## Next high-value investigations
52
+
53
+ 1. **Compare ref SVGs element-by-element** to characterize the
54
+ stereotype visibility rule. Likely factors: element style
55
+ `Tag=`, HideElemStereo, stereotype FQName prefix.
56
+
57
+ 2. **Parse t_diagram.cx/cy** (canvas dimensions stored in QEA,
58
+ lost in XMI export) for exact canvas sizing. XMI uses DocSize
59
+ which is paper-size, not pixel-canvas.
60
+
61
+ 3. **Wire QEA loader to skip XMI** — parsing QEA directly gives
62
+ StyleEx, exact element positions, and tagged value scopes
63
+ that the XMI export loses.