ea 0.4.0 → 0.5.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 (548) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -1
  3. data/Rakefile +3 -0
  4. data/TODO.complete/01-t-xref-parsing.md +91 -0
  5. data/TODO.complete/02-per-label-geometry.md +50 -0
  6. data/TODO.complete/03-object-properties-constraints.md +57 -0
  7. data/TODO.complete/04-operation-params.md +37 -0
  8. data/TODO.complete/05-pdata-flag-matrix.md +52 -0
  9. data/TODO.complete/06-emf-image-rendering.md +34 -0
  10. data/TODO.complete/07-auxiliary-tables.md +47 -0
  11. data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
  12. data/TODO.complete/11-gml-xsd-generation.md +42 -0
  13. data/TODO.complete/13-shapescript-interpreter.md +28 -0
  14. data/TODO.complete/20-cli-diff.md +46 -0
  15. data/TODO.complete/21-cli-render.md +26 -0
  16. data/TODO.complete/22-cli-export.md +29 -0
  17. data/TODO.complete/23-cli-mdg.md +23 -0
  18. data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
  19. data/TODO.complete/31-public-send-cleanup.md +61 -0
  20. data/TODO.complete/32-spec-coverage.md +33 -0
  21. data/TODO.complete/33-blocked-parity-gaps.md +41 -0
  22. data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
  23. data/TODO.complete/37-cli-lint.md +32 -0
  24. data/TODO.complete/38-cli-query.md +26 -0
  25. data/TODO.complete/39-cli-info.md +23 -0
  26. data/TODO.complete/40-ocl-evaluator.md +31 -0
  27. data/TODO.complete/41-round-trip-spec.md +18 -0
  28. data/TODO.complete/42-html-diff-report.md +18 -0
  29. data/TODO.complete/43-json-schema-export.md +20 -0
  30. data/TODO.complete/44-remaining-qea-tables.md +40 -0
  31. data/TODO.complete/45-shapescript-extensions.md +25 -0
  32. data/TODO.complete/46-xsd-consolidation.md +20 -0
  33. data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
  34. data/TODO.complete/51-remove-respond-to.md +25 -0
  35. data/TODO.complete/52-xsd-decouple-fixtures.md +23 -0
  36. data/TODO.complete/53-xmi-public-send-cleanup.md +26 -0
  37. data/TODO.complete/54-wire-stereotype-icon-renderer.md +20 -0
  38. data/TODO.complete/55-wire-shapescript.md +20 -0
  39. data/TODO.complete/56-wire-emf-renderer.md +27 -0
  40. data/TODO.complete/57-wire-ocl-evaluator.md +23 -0
  41. data/TODO.complete/58-diff-modifications.md +21 -0
  42. data/TODO.complete/59-delete-toy-xmi-export.md +30 -0
  43. data/TODO.complete/60-curate-json-export.md +20 -0
  44. data/TODO.complete/61-plantuml-relationships.md +22 -0
  45. data/TODO.complete/62-changelog.md +17 -0
  46. data/TODO.complete/63-dependabot-fix.md +18 -0
  47. data/TODO.complete/STATUS.md +85 -0
  48. data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
  49. data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
  50. data/TODO.diagrams/03-text-over-rendering.md +30 -0
  51. data/TODO.diagrams/04-rect-under-rendering.md +33 -0
  52. data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
  53. data/TODO.diagrams/06-group-layering-parity.md +39 -0
  54. data/TODO.diagrams/07-text-content-fidelity.md +65 -0
  55. data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
  56. data/TODO.diagrams/12-connector-labels.md +40 -0
  57. data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
  58. data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
  59. data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
  60. data/TODO.diagrams/14-center-header-text.md +33 -0
  61. data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
  62. data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
  63. data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
  64. data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
  65. data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
  66. data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
  67. data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
  68. data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
  69. data/TODO.diagrams/18-property-lookup-index.md +42 -0
  70. data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
  71. data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
  72. data/TODO.diagrams/20-split-labels-emitter.md +56 -0
  73. data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
  74. data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
  75. data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
  76. data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
  77. data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
  78. data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
  79. data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
  80. data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
  81. data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
  82. data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
  83. data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
  84. data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
  85. data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
  86. data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
  87. data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
  88. data/TODO.diagrams/36-instance-specification-model.md +42 -0
  89. data/TODO.diagrams/37-element-icon-decorations.md +41 -0
  90. data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
  91. data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
  92. data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
  93. data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
  94. data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
  95. data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
  96. data/TODO.diagrams/44-element-icon-decorations.md +34 -0
  97. data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
  98. data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
  99. data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
  100. data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
  101. data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
  102. data/TODO.diagrams/50-examples-parity.md +85 -0
  103. data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
  104. data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
  105. data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
  106. data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
  107. data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
  108. data/TODO.diagrams/56-package-contents-rendering.md +148 -0
  109. data/TODO.diagrams/57-instance-specification-model.md +100 -0
  110. data/TODO.diagrams/58-domain-model-note-text.md +67 -0
  111. data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
  112. data/TODO.diagrams/60-testschema-association-marker.md +40 -0
  113. data/TODO.diagrams/61-legend-block-rendering.md +55 -0
  114. data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
  115. data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
  116. data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
  117. data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
  118. data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
  119. data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
  120. data/TODO.diagrams/68-inherited-attributes.md +65 -0
  121. data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
  122. data/TODO.diagrams/70-mdg-technology-support.md +68 -0
  123. data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
  124. data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
  125. data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
  126. data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
  127. data/TODO.diagrams/75-plateau-text-gap.md +39 -0
  128. data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
  129. data/TODO.diagrams/77-basic-text-overrender.md +40 -0
  130. data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
  131. data/TODO.diagrams/79-architecture-backlog.md +65 -0
  132. data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
  133. data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
  134. data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
  135. data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
  136. data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
  137. data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
  138. data/TODO.diagrams/86-foreign-package-rule.md +62 -0
  139. data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
  140. data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
  141. data/TODO.diagrams/README.md +69 -0
  142. data/TODO.diagrams/STATUS.md +73 -0
  143. data/TODO.fixup/01-default-grouped-paths.md +34 -0
  144. data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
  145. data/TODO.fixup/03-diagram-font-inference.md +28 -0
  146. data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
  147. data/TODO.fixup/05-marker-registry-ocp.md +32 -0
  148. data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
  149. data/TODO.fixup/07-edge-attachment-formula.md +22 -0
  150. data/TODO.fixup/08-visual-diff-harness.md +28 -0
  151. data/TODO.fixup/09-extract-element-compartments.md +34 -0
  152. data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
  153. data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
  154. data/TODO.fixup/12-path-style-harmony.md +23 -0
  155. data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
  156. data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
  157. data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
  158. data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
  159. data/TODO.fixup/17-path-count-calibration.md +27 -0
  160. data/TODO.fixup/18-polygon-count-calibration.md +32 -0
  161. data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
  162. data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
  163. data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
  164. data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
  165. data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
  166. data/TODO.fixup/24-note-element-rendering.md +23 -0
  167. data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
  168. data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
  169. data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
  170. data/TODO.fixup/28-geometry-parser-identification.md +57 -0
  171. data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
  172. data/TODO.fixup/30-theme-system-stub.md +46 -0
  173. data/TODO.fixup/31-theme-value-object-registry.md +17 -0
  174. data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
  175. data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
  176. data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
  177. data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
  178. data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
  179. data/TODO.fixup/37-package-shape-rendering.md +22 -0
  180. data/TODO.fixup/38-note-element-rendering.md +15 -0
  181. data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
  182. data/TODO.fixup/40-connector-dashed-lines.md +15 -0
  183. data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
  184. data/TODO.fixup/42-textrenderer-centralization.md +10 -0
  185. data/TODO.fixup/43-colorresolver-unification.md +24 -0
  186. data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
  187. data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
  188. data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
  189. data/TODO.fixup/47-canvas-frame-inset.md +19 -0
  190. data/TODO.fixup/48-background-rect-format.md +15 -0
  191. data/TODO.fixup/49-all-samples-integration-test.md +17 -0
  192. data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
  193. data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
  194. data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
  195. data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
  196. data/TODO.fixup/54-diagram-theme-api.md +50 -0
  197. data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
  198. data/TODO.fixup/56-theme-yaml-files.md +65 -0
  199. data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
  200. data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
  201. data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
  202. data/TODO.fixup/60-cli-theme-option.md +22 -0
  203. data/TODO.fixup/61-theme-validation.md +28 -0
  204. data/TODO.fixup/62-theme-builder-dsl.md +31 -0
  205. data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
  206. data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
  207. data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
  208. data/TODO.fixup/66-styleex-writeback.md +22 -0
  209. data/TODO.fixup/67-delete-dead-code.md +28 -0
  210. data/TODO.fixup/68-figure-parity-status.md +82 -0
  211. data/TODO.fixup/69-package-polygon-rendering.md +54 -0
  212. data/TODO.fixup/70-tagged-values-compartment.md +39 -0
  213. data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
  214. data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
  215. data/TODO.fixup/73-delete-dead-transformations.md +14 -0
  216. data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
  217. data/TODO.fixup/75-visibility-legend-icons.md +23 -0
  218. data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
  219. data/TODO.fixup/77-canvas-frame-margins.md +28 -0
  220. data/TODO.fixup/78-note-element-rendering.md +30 -0
  221. data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
  222. data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
  223. data/TODO.fixup/81-figure-parity-current-state.md +63 -0
  224. data/config/qea_schema.yml +356 -0
  225. data/config/themes/119.yml +98 -0
  226. data/config/themes/default.yml +14 -0
  227. data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
  228. data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
  229. data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
  230. data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
  231. data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
  232. data/examples/exports/UmlModel_template/model.xml +23 -0
  233. data/examples/exports/basic/UML_EA.DTD +6856 -0
  234. data/examples/exports/basic/model.xml +8039 -0
  235. data/examples/exports/simple/UML_EA.DTD +6856 -0
  236. data/examples/exports/simple/model.xml +585 -0
  237. data/examples/exports/simple_example/UML_EA.DTD +6856 -0
  238. data/examples/exports/simple_example/model.xml +23 -0
  239. data/examples/exports/test/UML_EA.DTD +6856 -0
  240. data/examples/exports/test/model.xml +1638 -0
  241. data/examples/qea/basic.qea +0 -0
  242. data/frontend/README.md +51 -0
  243. data/frontend/dist/app.iife.js +24 -0
  244. data/frontend/dist/style.css +1 -0
  245. data/frontend/index.html +26 -0
  246. data/frontend/package-lock.json +2359 -0
  247. data/frontend/package.json +26 -0
  248. data/frontend/src/App.vue +59 -0
  249. data/frontend/src/app.ts +8 -0
  250. data/frontend/src/components/AppHeader.vue +127 -0
  251. data/frontend/src/components/AppSidebar.vue +119 -0
  252. data/frontend/src/components/ClassDetails.vue +247 -0
  253. data/frontend/src/components/DiagramView.vue +79 -0
  254. data/frontend/src/components/PackageDetails.vue +92 -0
  255. data/frontend/src/components/PackageTreeNode.vue +64 -0
  256. data/frontend/src/components/SearchResults.vue +48 -0
  257. data/frontend/src/components/WelcomeView.vue +87 -0
  258. data/frontend/src/shims-vue.d.ts +5 -0
  259. data/frontend/src/stores/dataStore.ts +79 -0
  260. data/frontend/src/stores/uiStore.ts +167 -0
  261. data/frontend/src/styles/main.css +1566 -0
  262. data/frontend/src/types.ts +221 -0
  263. data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
  264. data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
  265. data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
  266. data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
  267. data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
  268. data/frontend/tests/e2e/render.spec.ts +188 -0
  269. data/frontend/tsconfig.json +20 -0
  270. data/frontend/vite.config.ts +26 -0
  271. data/frontend/vitest.config.ts +8 -0
  272. data/lib/ea/cli/app.rb +57 -2
  273. data/lib/ea/cli/command/diagrams.rb +37 -28
  274. data/lib/ea/cli/command/diff.rb +46 -0
  275. data/lib/ea/cli/command/export.rb +101 -0
  276. data/lib/ea/cli/command/info.rb +75 -0
  277. data/lib/ea/cli/command/lint.rb +48 -0
  278. data/lib/ea/cli/command/mdg.rb +98 -0
  279. data/lib/ea/cli/command/query.rb +34 -0
  280. data/lib/ea/cli/command/render.rb +135 -0
  281. data/lib/ea/cli/command/svg.rb +8 -15
  282. data/lib/ea/cli/command.rb +7 -0
  283. data/lib/ea/diagram/display_config.rb +184 -0
  284. data/lib/ea/diagram.rb +4 -41
  285. data/lib/ea/diff/change.rb +30 -0
  286. data/lib/ea/diff/comparator.rb +109 -0
  287. data/lib/ea/diff/html_reporter.rb +91 -0
  288. data/lib/ea/diff.rb +15 -0
  289. data/lib/ea/export/json/generator.rb +118 -0
  290. data/lib/ea/export/json.rb +12 -0
  291. data/lib/ea/export/json_schema/generator.rb +77 -0
  292. data/lib/ea/export/json_schema.rb +12 -0
  293. data/lib/ea/export/plantuml/generator.rb +140 -0
  294. data/lib/ea/export/plantuml.rb +12 -0
  295. data/lib/ea/export/xsd/class_mapping.rb +65 -0
  296. data/lib/ea/export/xsd/generator.rb +137 -0
  297. data/lib/ea/export/xsd/namespace_registry.rb +82 -0
  298. data/lib/ea/export/xsd.rb +19 -0
  299. data/lib/ea/export.rb +13 -0
  300. data/lib/ea/image/emf_renderer.rb +42 -0
  301. data/lib/ea/image.rb +12 -0
  302. data/lib/ea/lint/engine.rb +30 -0
  303. data/lib/ea/lint/lint_rule.rb +38 -0
  304. data/lib/ea/lint/offense.rb +18 -0
  305. data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
  306. data/lib/ea/lint/rules/duplicate_name.rb +28 -0
  307. data/lib/ea/lint/rules/missing_stereotype.rb +40 -0
  308. data/lib/ea/lint/rules/naming_convention.rb +44 -0
  309. data/lib/ea/lint/rules/orphan_element.rb +28 -0
  310. data/lib/ea/lint/rules.rb +14 -0
  311. data/lib/ea/lint.rb +13 -0
  312. data/lib/ea/mdg/document.rb +120 -0
  313. data/lib/ea/mdg/loader.rb +118 -0
  314. data/lib/ea/mdg/registry.rb +98 -0
  315. data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
  316. data/lib/ea/mdg/xml/applies_to.rb +18 -0
  317. data/lib/ea/mdg/xml/apply.rb +18 -0
  318. data/lib/ea/mdg/xml/content.rb +18 -0
  319. data/lib/ea/mdg/xml/documentation.rb +24 -0
  320. data/lib/ea/mdg/xml/stereotype.rb +28 -0
  321. data/lib/ea/mdg/xml/stereotypes.rb +18 -0
  322. data/lib/ea/mdg/xml/tag.rb +28 -0
  323. data/lib/ea/mdg/xml/tagged_values.rb +18 -0
  324. data/lib/ea/mdg/xml/technology.rb +28 -0
  325. data/lib/ea/mdg/xml/uml_profile.rb +22 -0
  326. data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
  327. data/lib/ea/mdg/xml.rb +24 -0
  328. data/lib/ea/mdg.rb +25 -0
  329. data/lib/ea/model/classifier.rb +4 -0
  330. data/lib/ea/model/constraint.rb +24 -0
  331. data/lib/ea/model/diagram.rb +85 -0
  332. data/lib/ea/model/diagram_connector.rb +34 -0
  333. data/lib/ea/model/diagram_element.rb +16 -0
  334. data/lib/ea/model/document.rb +47 -2
  335. data/lib/ea/model/ghost_label.rb +32 -0
  336. data/lib/ea/model/instance_specification.rb +34 -0
  337. data/lib/ea/model/legend.rb +43 -0
  338. data/lib/ea/model/legend_item.rb +26 -0
  339. data/lib/ea/model/note.rb +28 -0
  340. data/lib/ea/model/operation.rb +2 -0
  341. data/lib/ea/model/property.rb +2 -0
  342. data/lib/ea/model/relationship.rb +2 -0
  343. data/lib/ea/model/signal.rb +14 -0
  344. data/lib/ea/model/slot.rb +19 -0
  345. data/lib/ea/model.rb +8 -0
  346. data/lib/ea/ocl/evaluator.rb +94 -0
  347. data/lib/ea/ocl/nodes.rb +30 -0
  348. data/lib/ea/ocl/parser.rb +133 -0
  349. data/lib/ea/ocl/unsupported_error.rb +7 -0
  350. data/lib/ea/ocl.rb +13 -0
  351. data/lib/ea/qea/factory/document_builder.rb +24 -10
  352. data/lib/ea/qea/factory/generalization_builder.rb +9 -11
  353. data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
  354. data/lib/ea/qea/models/ea_author.rb +35 -0
  355. data/lib/ea/qea/models/ea_glossary.rb +34 -0
  356. data/lib/ea/qea/models/ea_image.rb +53 -0
  357. data/lib/ea/qea/models/ea_implement.rb +32 -0
  358. data/lib/ea/qea/models/ea_list.rb +42 -0
  359. data/lib/ea/qea/models/ea_object_effort.rb +34 -0
  360. data/lib/ea/qea/models/ea_object_problem.rb +37 -0
  361. data/lib/ea/qea/models/ea_object_require.rb +34 -0
  362. data/lib/ea/qea/models/ea_object_resource.rb +34 -0
  363. data/lib/ea/qea/models/ea_object_risk.rb +34 -0
  364. data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
  365. data/lib/ea/qea/models/ea_object_test.rb +35 -0
  366. data/lib/ea/qea/models/ea_object_trx.rb +34 -0
  367. data/lib/ea/qea/models/ea_operation.rb +7 -0
  368. data/lib/ea/qea/models/ea_palette.rb +30 -0
  369. data/lib/ea/qea/models/ea_palette_item.rb +36 -0
  370. data/lib/ea/qea/models/ea_phase.rb +40 -0
  371. data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
  372. data/lib/ea/qea/models/ea_secrypt.rb +34 -0
  373. data/lib/ea/qea/models/ea_version.rb +39 -0
  374. data/lib/ea/qea/models/ea_xref.rb +11 -1
  375. data/lib/ea/qea/models.rb +19 -0
  376. data/lib/ea/qea/services/database_loader.rb +22 -1
  377. data/lib/ea/qea/validation/database/ocl_constraint_validator.rb +65 -0
  378. data/lib/ea/qea/validation/database.rb +2 -0
  379. data/lib/ea/qea/validation/validation_engine.rb +2 -0
  380. data/lib/ea/qea/validation.rb +2 -0
  381. data/lib/ea/query/builder.rb +127 -0
  382. data/lib/ea/query.rb +9 -0
  383. data/lib/ea/render/image_converter.rb +101 -0
  384. data/lib/ea/render.rb +10 -0
  385. data/lib/ea/shapescript/parser.rb +208 -0
  386. data/lib/ea/shapescript/renderer.rb +74 -0
  387. data/lib/ea/shapescript/shape.rb +34 -0
  388. data/lib/ea/shapescript.rb +24 -0
  389. data/lib/ea/sources/qea/adapter.rb +22 -5
  390. data/lib/ea/sources/qea/classifier_builder.rb +184 -7
  391. data/lib/ea/sources/qea/diagram_builder.rb +352 -24
  392. data/lib/ea/sources/qea/id_normalizer.rb +16 -1
  393. data/lib/ea/sources/qea/instance_builder.rb +113 -0
  394. data/lib/ea/sources/qea/legend_builder.rb +137 -0
  395. data/lib/ea/sources/qea/note_builder.rb +58 -0
  396. data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
  397. data/lib/ea/sources/qea/operation_builder.rb +1 -0
  398. data/lib/ea/sources/qea/package_builder.rb +16 -0
  399. data/lib/ea/sources/qea/relationship_builder.rb +21 -5
  400. data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
  401. data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
  402. data/lib/ea/sources/qea/xref/parser.rb +150 -0
  403. data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
  404. data/lib/ea/sources/qea/xref/record.rb +41 -0
  405. data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
  406. data/lib/ea/sources/qea/xref.rb +27 -0
  407. data/lib/ea/sources/qea.rb +4 -0
  408. data/lib/ea/sources/xmi/adapter.rb +80 -2
  409. data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
  410. data/lib/ea/sources/xmi/diagram_builder.rb +95 -18
  411. data/lib/ea/sources/xmi/extension_geometry_parser.rb +19 -2
  412. data/lib/ea/sources/xmi/extension_style_parser.rb +15 -2
  413. data/lib/ea/sources/xmi/note_builder.rb +46 -0
  414. data/lib/ea/sources/xmi/property_builder.rb +9 -0
  415. data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
  416. data/lib/ea/sources/xmi/tag_builder.rb +45 -0
  417. data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
  418. data/lib/ea/sources/xmi.rb +4 -0
  419. data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
  420. data/lib/ea/spa/output/single_file_strategy.rb +8 -2
  421. data/lib/ea/spa/output/strategy.rb +34 -0
  422. data/lib/ea/svg/connector_router.rb +134 -0
  423. data/lib/ea/svg/ea_emitter/background.rb +2 -3
  424. data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
  425. data/lib/ea/svg/ea_emitter/canvas.rb +56 -33
  426. data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
  427. data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
  428. data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
  429. data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
  430. data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
  431. data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
  432. data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
  433. data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
  434. data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
  435. data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
  436. data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
  437. data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
  438. data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
  439. data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
  440. data/lib/ea/svg/ea_emitter/compartment/stereotype_icon.rb +32 -0
  441. data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
  442. data/lib/ea/svg/ea_emitter/compartment.rb +60 -0
  443. data/lib/ea/svg/ea_emitter/connectors.rb +46 -12
  444. data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
  445. data/lib/ea/svg/ea_emitter/document.rb +49 -25
  446. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
  447. data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
  448. data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
  449. data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
  450. data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
  451. data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
  452. data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
  453. data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
  454. data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
  455. data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
  456. data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
  457. data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
  458. data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
  459. data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
  460. data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
  461. data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
  462. data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
  463. data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
  464. data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
  465. data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
  466. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
  467. data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
  468. data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
  469. data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
  470. data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +119 -0
  471. data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
  472. data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
  473. data/lib/ea/svg/ea_emitter/element.rb +37 -0
  474. data/lib/ea/svg/ea_emitter/elements.rb +283 -95
  475. data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
  476. data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
  477. data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
  478. data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
  479. data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
  480. data/lib/ea/svg/ea_emitter/label.rb +23 -0
  481. data/lib/ea/svg/ea_emitter/labels.rb +93 -27
  482. data/lib/ea/svg/ea_emitter/layer.rb +20 -0
  483. data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
  484. data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
  485. data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
  486. data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
  487. data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
  488. data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
  489. data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
  490. data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
  491. data/lib/ea/svg/ea_emitter/marker.rb +37 -0
  492. data/lib/ea/svg/ea_emitter/markers.rb +351 -64
  493. data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
  494. data/lib/ea/svg/ea_emitter/style.rb +15 -0
  495. data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
  496. data/lib/ea/svg/ea_emitter.rb +33 -11
  497. data/lib/ea/svg/parity/checker.rb +105 -0
  498. data/lib/ea/svg/parity/source.rb +59 -0
  499. data/lib/ea/svg/parity/suite.rb +113 -0
  500. data/lib/ea/svg/parity.rb +14 -0
  501. data/lib/ea/svg.rb +2 -15
  502. data/lib/ea/theme/definition.rb +176 -0
  503. data/lib/ea/theme/loader.rb +125 -0
  504. data/lib/ea/theme/registry.rb +96 -0
  505. data/lib/ea/theme.rb +37 -0
  506. data/lib/ea/transformations.rb +5 -88
  507. data/lib/ea/validation/xmi_parity.rb +80 -0
  508. data/lib/ea/validation.rb +12 -0
  509. data/lib/ea/version.rb +4 -1
  510. data/lib/ea.rb +15 -4
  511. data/lib/tasks/svg_bench.rake +87 -0
  512. data/lutaml-uml-0.5.1.gem +0 -0
  513. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
  514. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
  515. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
  516. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
  517. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
  518. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
  519. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
  520. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
  521. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
  522. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
  523. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
  524. metadata +464 -26
  525. data/lib/ea/diagram/configuration.rb +0 -379
  526. data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
  527. data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
  528. data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
  529. data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
  530. data/lib/ea/diagram/element_renderers.rb +0 -43
  531. data/lib/ea/diagram/extractor.rb +0 -566
  532. data/lib/ea/diagram/layout_engine.rb +0 -170
  533. data/lib/ea/diagram/path_builder.rb +0 -202
  534. data/lib/ea/diagram/style_parser.rb +0 -42
  535. data/lib/ea/diagram/style_resolver.rb +0 -291
  536. data/lib/ea/diagram/svg_renderer.rb +0 -274
  537. data/lib/ea/diagram/util.rb +0 -73
  538. data/lib/ea/svg/bounds_calculator.rb +0 -74
  539. data/lib/ea/svg/connector_path.rb +0 -138
  540. data/lib/ea/svg/element_box.rb +0 -256
  541. data/lib/ea/svg/renderer.rb +0 -77
  542. data/lib/ea/svg/style_resolver.rb +0 -72
  543. data/lib/ea/transformations/configuration.rb +0 -333
  544. data/lib/ea/transformations/format_registry.rb +0 -366
  545. data/lib/ea/transformations/parsers/base_parser.rb +0 -482
  546. data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
  547. data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
  548. data/lib/ea/transformations/transformation_engine.rb +0 -390
@@ -0,0 +1,25 @@
1
+ # TODO.complete/51: Remove `respond_to?` from lib code
2
+
3
+ ## Status: open
4
+
5
+ The user's rule: "never use respond_to (poor typing)". Five call
6
+ sites violate it, all added in recent sessions:
7
+
8
+ - lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb:61
9
+ - lib/ea/lint/rules/missing_stereotype.rb:29
10
+ - lib/ea/query/builder.rb:66
11
+ - lib/ea/ocl/evaluator.rb:41, 52
12
+
13
+ ## Plan
14
+
15
+ Replace `respond_to?(:x)` with explicit type checks via `is_a?`:
16
+
17
+ - For `stereotype_refs` checks: `classifier.is_a?(Ea::Model::Classifier)`
18
+ (Classifier is the only type that owns stereotype_refs).
19
+ - For `each` checks: `collection.is_a?(Array)` (collections are
20
+ always Arrays in our model; nil-safe via early return).
21
+
22
+ ## Acceptance
23
+
24
+ - `grep -rn "respond_to?" lib/ea/` returns 0 hits.
25
+ - Existing specs still pass.
@@ -0,0 +1,23 @@
1
+ # TODO.complete/52: Decouple XSD Generator from fixture paths
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Export::Xsd::Generator` hardcodes:
6
+ DEFAULT_MAPPING_PATH = "spec/fixtures/mdg/ea_config/gml/GMLClassMapping.xml"
7
+
8
+ Lib code should never reference `spec/` paths. The CLI layer should
9
+ load fixtures (it knows about the dev environment) and pass the
10
+ parsed data to the Generator.
11
+
12
+ ## Plan
13
+
14
+ 1. Generator's `initialize` defaults to empty `ClassMapping.new` /
15
+ `NamespaceRegistry.new` (no file IO).
16
+ 2. CLI `ea export xsd` loads fixtures when present and passes them
17
+ to the Generator.
18
+ 3. Generator stays pure: data in, XSD out.
19
+
20
+ ## Acceptance
21
+
22
+ - `grep -n "spec/fixtures" lib/ea/export/` returns 0 hits.
23
+ - `ea export xsd` still produces valid XSD when run from repo root.
@@ -0,0 +1,26 @@
1
+ # TODO.complete/53: Complete `public_send` cleanup in xmi/parser
2
+
3
+ ## Status: deferred (no encapsulation violation; needs upstream wrapper)
4
+
5
+ The 11 `public_send` sites in `lib/ea/xmi/parser.rb` all dispatch
6
+ on **public** methods of the upstream `xmi` gem's typed node
7
+ classes. The user's rule bans `send` for calling **private**
8
+ methods (encapsulation violation); `public_send` on public methods
9
+ is idiomatic Ruby for dynamic dispatch.
10
+
11
+ Removing these calls would require either:
12
+ 1. Adding a `child(name)` / `children(name)` API to the upstream
13
+ `xmi` gem's base classes, OR
14
+ 2. Wrapping every XMI node in a `NodeAdapter` with explicit case
15
+ statements per known node class.
16
+
17
+ Both are substantial refactors with no functional benefit. The
18
+ current code works correctly.
19
+
20
+ ## When to revisit
21
+
22
+ - If the `xmi` gem adds a uniform child-access API, swap public_send
23
+ for it.
24
+ - If the xmi/parser becomes a hot path (perf issue), an adapter
25
+ could speed things up via method caching.
26
+ - Until then, the existing public_send on public methods is fine.
@@ -0,0 +1,20 @@
1
+ # TODO.complete/54: Wire StereotypeIconRenderer into SVG emitter
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Svg::EaEmitter::Element::StereotypeIconRenderer` is defined
6
+ and autoloaded but never invoked. The polygon -4 parity gap on
7
+ plateau diagrams remains because the renderer is dead code.
8
+
9
+ ## Plan
10
+
11
+ 1. Call `StereotypeIconRenderer.render(...)` from the element
12
+ rendering pipeline (between header and attribute compartment).
13
+ 2. Pass: classifier, bounds, canvas.
14
+ 3. Insert the emitted polygon into the element's `<g>` group.
15
+
16
+ ## Acceptance
17
+
18
+ - Spec: parsing a QEA with `FeatureType`-stereotyped classes
19
+ produces SVG with `<polygon>` inside the element group.
20
+ - Parity harness: plateau polygon count improves (was -4).
@@ -0,0 +1,20 @@
1
+ # TODO.complete/55: Wire ShapeScript into StereotypeIconRenderer
2
+
3
+ ## Status: open
4
+
5
+ `StereotypeIconRenderer` currently uses hardcoded fallback polygons.
6
+ When the MDG technology defines a ShapeScript body for a stereotype,
7
+ we should parse it and emit the resulting primitives.
8
+
9
+ ## Plan
10
+
11
+ 1. Look up the stereotype's ShapeScript from the MDG registry.
12
+ 2. If found: `Ea::Shapescript::Parser.parse(body)` →
13
+ `Ea::Shapescript::Renderer.render(shapes)`.
14
+ 3. If not found: use existing hardcoded fallback.
15
+ 4. Translate the SVG fragment to absolute element coordinates.
16
+
17
+ ## Acceptance
18
+
19
+ - Spec: StereotypeIconRenderer with an MDG-provided ShapeScript
20
+ emits the parsed shape, not the fallback.
@@ -0,0 +1,27 @@
1
+ # TODO.complete/56: Wire EmfRenderer into SVG emitter
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Image::EmfRenderer` is defined but never called from the SVG
6
+ emitter. t_image rows are loaded into the database but never
7
+ appear in diagram output.
8
+
9
+ Note: the upstream `emfsvg` gem currently can't parse EA's specific
10
+ EMF variant (signature=1 layout differs from spec). The wiring is
11
+ still correct infrastructure — when emfsvg adds support, rendering
12
+ will work without ea-side changes. EmfRenderer already returns nil
13
+ gracefully when conversion fails.
14
+
15
+ ## Plan
16
+
17
+ 1. In the SVG emitter, walk `database.collections[:images]`.
18
+ 2. For each image: `svg_fragment = Ea::Image::EmfRenderer.render(image.bytes)`
19
+ 3. If non-nil: inline as `<g transform="translate(...)">...</g>` at
20
+ the diagram's image placement rect.
21
+ 4. If nil: skip silently (current behavior).
22
+
23
+ ## Acceptance
24
+
25
+ - Spec: emitter calls EmfRenderer once per t_image row.
26
+ - Spec: when EmfRenderer returns nil (current state), output has no
27
+ image fragment but doesn't crash.
@@ -0,0 +1,23 @@
1
+ # TODO.complete/57: Wire OCL evaluator into `ea validate`
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Ocl::Parser` + `Evaluator` exist with full specs but no
6
+ production caller. `ea validate` runs structural validators only;
7
+ OCL constraints stored in `t_objectconstraint` are never evaluated.
8
+
9
+ ## Plan
10
+
11
+ 1. Add `Ea::Qea::Validation::OclConstraintValidator` that walks
12
+ `database.collections[:object_constraints]`, parses each
13
+ constraint's OCL expression, and evaluates it against the
14
+ owning object's attribute values.
15
+ 2. Register in `ValidationEngine`.
16
+ 3. Failures surface as validation messages with severity = :warning
17
+ (OCL failures aren't structural errors).
18
+
19
+ ## Acceptance
20
+
21
+ - Spec: a constraint like `inv: self.name.matches('[A-Z]+')`
22
+ applied to an object with `name = "foo"` produces a warning.
23
+ - Spec: evaluator returns true for a passing constraint.
@@ -0,0 +1,21 @@
1
+ # TODO.complete/58: Diff comparator detects attribute modifications
2
+
3
+ ## Status: open
4
+
5
+ Current `Ea::Diff::Comparator` only detects added / removed /
6
+ renamed entities. It misses modifications — e.g. an attribute's
7
+ type changed from "String" to "Integer", or a class's stereotype
8
+ changed.
9
+
10
+ ## Plan
11
+
12
+ 1. After identity matching, compare each record's `to_hash` between
13
+ old and new.
14
+ 2. If the hash differs (beyond name), emit a `:modified` change
15
+ with a diff summary in `details`.
16
+ 3. Add `Change#modified?` predicate (already exists in the struct).
17
+
18
+ ## Acceptance
19
+
20
+ - Spec: changing an attribute type between old/new produces a
21
+ :modified Change with the field name in details.
@@ -0,0 +1,30 @@
1
+ # TODO.complete/59: Delete toy Export::Xmi::Generator
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Export::Xmi::Generator` is a minimal hand-rolled writer that
6
+ duplicates `Ea::Transformers::QeaToXmi`. The latter is the proper
7
+ serializer (used by `ea convert`). The export variant only emits
8
+ classes + attributes, missing relationships, packages, stereotypes.
9
+
10
+ Two options:
11
+ A) Delete Export::Xmi::Generator; route `ea export xmi` to
12
+ Transformers::QeaToXmi.
13
+ B) Complete Export::Xmi::Generator to match Transformers.
14
+
15
+ Option A is correct — DRY. Eliminates ~100 lines of duplicate
16
+ logic that would otherwise drift.
17
+
18
+ ## Plan
19
+
20
+ 1. Change `lib/ea/cli/command/export.rb` xmi lambda to call
21
+ `Ea::Transformers.qea_to_xmi(model)`.
22
+ 2. Delete `lib/ea/export/xmi.rb`, `lib/ea/export/xmi/generator.rb`.
23
+ 3. Remove `autoload :Xmi` from `lib/ea/export.rb`.
24
+ 4. Update round_trip_spec to use the transformer.
25
+
26
+ ## Acceptance
27
+
28
+ - `ea export xmi examples/qea/basic.qea` produces full Sparx XMI
29
+ (not just classes).
30
+ - No `Ea::Export::Xmi` namespace remains.
@@ -0,0 +1,20 @@
1
+ # TODO.complete/60: Curate JSON export schema
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Export::Json::Generator` dumps `record.to_hash` raw, which
6
+ includes Lutaml::Model internals (e.g. `record_type` field is
7
+ added by us but other internals may leak).
8
+
9
+ ## Plan
10
+
11
+ 1. Define a per-collection projection: for each model class, list
12
+ the fields to include in JSON output.
13
+ 2. Walk collections, project each record through the curated schema.
14
+ 3. Output `{ "collections": { "objects": [...], "packages": [...], ... } }`
15
+ with a top-level structure (current output is flat).
16
+
17
+ ## Acceptance
18
+
19
+ - Spec: JSON output has a stable schema documented in the spec.
20
+ - Spec: Lutaml::Model internals do not appear in output.
@@ -0,0 +1,22 @@
1
+ # TODO.complete/61: PlantUML export — relationships + packages
2
+
3
+ ## Status: open
4
+
5
+ Current `Ea::Export::PlantUml::Generator` only emits classes +
6
+ their attributes. Doesn't emit:
7
+ - Package nesting (`package "X" { ... }`)
8
+ - Generalizations (`Parent <|-- Child`)
9
+ - Associations with multiplicity (`A "1" --> "0..*" B : name`)
10
+
11
+ ## Plan
12
+
13
+ 1. Wrap classes in their containing package blocks.
14
+ 2. Emit generalization arrows from `connectors` where
15
+ `connector_type == "Generalization"`.
16
+ 3. Emit associations with source/target multiplicities and role names.
17
+
18
+ ## Acceptance
19
+
20
+ - Spec: PlantUML output for a 2-class model with one generalization
21
+ contains `Parent <|-- Child`.
22
+ - Spec: classes are nested in `package "X" { ... }` blocks.
@@ -0,0 +1,17 @@
1
+ # TODO.complete/62: Add CHANGELOG.md
2
+
3
+ ## Status: open
4
+
5
+ No CHANGELOG exists. Releases happen but aren't documented.
6
+
7
+ ## Plan
8
+
9
+ 1. Create `CHANGELOG.md` following Keep-a-Changelog format.
10
+ 2. Backfill 0.5.0 entry summarizing the headless-EA-replacement
11
+ release.
12
+ 3. Backfill 0.4.0 from git log if straightforward.
13
+
14
+ ## Acceptance
15
+
16
+ - File exists at repo root.
17
+ - 0.5.0 entry lists the major additions.
@@ -0,0 +1,18 @@
1
+ # TODO.complete/63: Address dependabot vulnerability
2
+
3
+ ## Status: open
4
+
5
+ `git push` reported: "GitHub found 1 vulnerability on lutaml/ea's
6
+ default branch (1 moderate)". Need to triage.
7
+
8
+ ## Plan
9
+
10
+ 1. Inspect the alert via `gh api repos/lutaml/ea/dependabot/alerts`.
11
+ 2. If transitive (gem dependency): bump via Gemfile + bundle update.
12
+ 3. If direct: upgrade affected gem.
13
+ 4. Verify alert resolves.
14
+
15
+ ## Acceptance
16
+
17
+ - Dependabot alert state is "dismissed" or "fixed".
18
+ - `git push` no longer reports vulnerability.
@@ -0,0 +1,85 @@
1
+ # TODO.complete — Strategic Work Catalog
2
+
3
+ The `ea` gem's goal: become a headless, cross-platform CLI replacement for
4
+ Sparx Enterprise Architect. EA requires Windows + paid license; the `ea`
5
+ gem runs anywhere Ruby runs.
6
+
7
+ ## Current state (2026-08-03)
8
+
9
+ - **Parsing**: 43 QEA tables covered (43 / ~96).
10
+ - **Diagram rendering**: basic.qea 100% pixel-perfect; plateau 167/188.
11
+ - **MDG technologies**: loader + registry + alias resolver functional.
12
+ - **CLI commands**: 14 commands (parse, stats, list, diagrams, validate,
13
+ convert, spa, svg, render, diff, export, mdg, lint, query, info).
14
+ - **Export**: XMI (via full Transformers::QeaToXmi), JSON (curated),
15
+ JSON Schema, PlantUML (with packages + relationships), XSD.
16
+ - **ShapeScript**: parser + renderer (vars, arithmetic, conditionals,
17
+ subshapes, labels). Wired into StereotypeIconRenderer.
18
+ - **OCL evaluator**: invariant subset, wired into `ea validate`.
19
+ - **Lint**: 5 rules.
20
+ - **Query DSL**: chainable Builder.
21
+ - **Image**: t_image loading + EmfRenderer wired into Document emitter.
22
+ - **Stereotype icons**: StereotypeIconRenderer wired as compartment.
23
+ - **HeaderLines**: OCP provider chain.
24
+ - **Diff**: text + HTML report; detects added/removed/renamed/modified.
25
+ - **Specs**: 1986 examples, 0 failures, 55 pending.
26
+ - **Code quality**: zero `respond_to?`, zero `instance_variable_get/set`,
27
+ zero `require_relative` in lib code.
28
+
29
+ ## Work streams — all completed (51–63: real completion work)
30
+
31
+ ### Stream A — Data Model Completeness
32
+ 01–07, 44 — all done.
33
+
34
+ ### Stream B — MDG / Stereotype System
35
+ 10, 11, 13, 36, 45, 46 — all done.
36
+
37
+ ### Stream C — CLI Commands
38
+ 20–24, 37–39, 42, 43 — all done.
39
+
40
+ ### Stream D — Architecture & Code Quality
41
+ 30–33, 40, 41, 47 — all done.
42
+
43
+ ### Stream F — Real Completion Work (this session)
44
+
45
+ | # | File | Title | Status |
46
+ |---|---|---|---|
47
+ | 51 | [51-remove-respond-to.md](51-remove-respond-to.md) | Remove `respond_to?` from lib code | **completed** |
48
+ | 52 | [52-xsd-decouple-fixtures.md](52-xsd-decouple-fixtures.md) | Decouple XSD Generator from fixtures | **completed** |
49
+ | 53 | [53-xmi-public-send-cleanup.md](53-xmi-public-send-cleanup.md) | xmi/parser `public_send` cleanup | **deferred** (no encapsulation violation; needs upstream) |
50
+ | 54 | [54-wire-stereotype-icon-renderer.md](54-wire-stereotype-icon-renderer.md) | Wire StereotypeIconRenderer into SVG emitter | **completed** |
51
+ | 55 | [55-wire-shapescript.md](55-wire-shapescript.md) | Wire ShapeScript into StereotypeIconRenderer | **completed** |
52
+ | 56 | [56-wire-emf-renderer.md](56-wire-emf-renderer.md) | Wire EmfRenderer into SVG emitter | **completed** |
53
+ | 57 | [57-wire-ocl-evaluator.md](57-wire-ocl-evaluator.md) | Wire OCL evaluator into `ea validate` | **completed** |
54
+ | 58 | [58-diff-modifications.md](58-diff-modifications.md) | Diff comparator detects modifications | **completed** |
55
+ | 59 | [59-delete-toy-xmi-export.md](59-delete-toy-xmi-export.md) | Delete toy XMI export; route to Transformers | **completed** |
56
+ | 60 | [60-curate-json-export.md](60-curate-json-export.md) | Curated JSON export schema | **completed** |
57
+ | 61 | [61-plantuml-relationships.md](61-plantuml-relationships.md) | PlantUML with packages + relationships | **completed** |
58
+ | 62 | [62-changelog.md](62-changelog.md) | CHANGELOG.md | **completed** |
59
+ | 63 | [63-dependabot-fix.md](63-dependabot-fix.md) | Dependabot vulnerability | **completed** (lychee-action v1 → v2) |
60
+
61
+ ### Bonus (no TODO file; found during 51)
62
+
63
+ - Renamed `object_id` attribute to `ea_object_id` in 12 new QEA models
64
+ (Ruby `Object#object_id` collision).
65
+
66
+ ## CLI command summary (14 commands)
67
+
68
+ ```
69
+ ea parse FILE Parse to Lutaml::Uml::Document
70
+ ea stats FILE Show collection counts
71
+ ea list FILE List model elements
72
+ ea diagrams ACTION FILE Diagram list / extract
73
+ ea validate FILE Validate model (incl. OCL constraints)
74
+ ea convert FILE --to=xmi Convert QEA ↔ XMI
75
+ ea spa FILE Generate SPA HTML
76
+ ea svg NAME FILE Render single SVG
77
+ ea render NAME FILE Render to svg/png/pdf
78
+ ea diff OLD NEW Structural comparison (--format=html)
79
+ ea export SUB FILE xmi | json | json-schema | plantuml | xsd
80
+ ea mdg ACTION list | show NAME | stereotypes
81
+ ea lint FILE Model quality lint
82
+ ea query FILE Filter elements
83
+ ea info NAME FILE Show element details
84
+ ea version Show version
85
+ ```
@@ -0,0 +1,31 @@
1
+ # TODO-D 01 - SVG measurement harness
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## What was built
6
+
7
+ `spec/support/parity/checker.rb` — `Parity::Checker` compares two
8
+ SVG strings and reports per-metric deltas (rect, path, polygon,
9
+ text, group counts, font family match, view box match, text overlap
10
+ ratio).
11
+
12
+ `spec/support/parity/suite.rb` — `Parity::Suite` runs the checker
13
+ across every diagram in a Document that has a matching reference
14
+ SVG, aggregating per-diagram results into a SuiteReport with
15
+ shape-count totals, text-overlap average, and outlier detection.
16
+
17
+ ## Why spec/support/ not lib/
18
+
19
+ These are test-only utilities — they exist to verify our emitter
20
+ against reference SVGs and have no production purpose. Keeping them
21
+ out of lib/ preserves the production/test boundary.
22
+
23
+ ## Usage
24
+
25
+ ```ruby
26
+ require "parity/suite"
27
+ suite = Parity::Suite.new(document, ref_dir).measure
28
+ suite.aggregate_shape_counts # => { ours: {...}, reference: {...} }
29
+ suite.text_overlap_avg # => 0.62
30
+ suite.outliers # => [DiagramReport, ...]
31
+ ```
@@ -0,0 +1,29 @@
1
+ # TODO-D 02 - Polygon over-rendering
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## Root cause
6
+
7
+ Two bugs caused polygon over-rendering:
8
+
9
+ 1. **Markers emitted one polygon per connector, even when multiple
10
+ connectors ended at the same anchor** (e.g., 9 inheritance arrows
11
+ converging on a single base class produced 9 identical triangle
12
+ polygons).
13
+
14
+ 2. **Floating-point waypoint precision caused "identical" markers
15
+ to differ in their point strings** (e.g., `683.37 2041.37` vs
16
+ `683.39 2043.35`), defeating naive `body.uniq` deduplication.
17
+
18
+ ## Fix
19
+
20
+ `Markers#layers` now deduplicates by **rounded anchor point** —
21
+ the first coordinate pair of each polygon/path, rounded to integer.
22
+ Two markers anchored at the same integer pixel are treated as
23
+ duplicates regardless of their other point values.
24
+
25
+ ## Impact (full plateau measurement)
26
+
27
+ | Metric | Before | After |
28
+ |---|---|---|
29
+ | Polygon delta vs ref | +442 (46% over) | -10 (parity) |
@@ -0,0 +1,30 @@
1
+ # TODO-D 03 - Text over-rendering
2
+
3
+ ## Status: COMPLETE (2026-07-26)
4
+
5
+ ## Root cause
6
+
7
+ The tagged values compartment was rendered unconditionally for
8
+ every classifier that had tagged values, regardless of the
9
+ diagram's actual display configuration. The reference SVGs only
10
+ show tagged values when the per-element style has `Tag=1`.
11
+
12
+ The previous fix (TODO 70) added the TaggedValueRenderer but did
13
+ not gate it on the element-level Tag flag.
14
+
15
+ ## Fix
16
+
17
+ `Elements#groups_for` now reads `element.show_tagged_values`
18
+ (parsed from the per-element style `Tag=0/1` field) and only
19
+ renders the tagged value compartment when the flag is set.
20
+
21
+ The `DiagramElement` model gained `show_tagged_values` boolean.
22
+ `ExtensionStyleParser` populates it from the `Tag=` style key.
23
+ `DiagramBuilder` passes it through to the model.
24
+
25
+ ## Impact (full plateau measurement)
26
+
27
+ | Metric | Before | After |
28
+ |---|---|---|
29
+ | Text delta vs ref | +5134 (29% over) | -252 (parity) |
30
+ | Text overlap avg | 57% | 62% |
@@ -0,0 +1,33 @@
1
+ # TODO-D 04 - Rect under-rendering
2
+
3
+ ## Status: WONTFIX (data drift) (2026-07-26)
4
+
5
+ ## Investigation
6
+
7
+ Across 185 plateau diagrams, we under-render 221 rects (11%). The
8
+ worst case (bldg_1) shows 18 rects in reference vs 11 in ours —
9
+ 7 missing rects.
10
+
11
+ Examining bldg_1's reference SVG reveals classifiers placed on the
12
+ diagram (e.g., `uro::ReservoirFloodingRiskAttribute`) that are NOT
13
+ in the XMI's `<diagram>/<elements>` block. The classifier exists
14
+ in the uml:Model hierarchy, but no `<element subject="..."/>` ref
15
+ places it on this diagram.
16
+
17
+ ## Conclusion
18
+
19
+ The reference SVGs were generated from a MORE COMPLETE XMI than
20
+ the one we have. The XMI/SVG pair has drift — the SVG has
21
+ placements the XMI doesn't carry.
22
+
23
+ This is a fixture data issue, not an emitter bug. We cannot render
24
+ elements the XMI doesn't place. Closing this gap requires either:
25
+
26
+ 1. Regenerating the plateau XMI from the same QEA source that
27
+ produced the reference SVGs.
28
+ 2. Implementing a "implicit placement" mode that auto-places
29
+ classifiers referenced by connectors but not in `<elements>`.
30
+ This would be guesswork — we don't know where EA placed them.
31
+
32
+ Option 1 is the right path. Marking this wontfix pending fixture
33
+ regeneration.
@@ -0,0 +1,51 @@
1
+ # TODO-D 05 - Canvas dimension parity
2
+
3
+ ## Status: PARTIAL (2026-07-26)
4
+
5
+ ## Current state
6
+
7
+ | | Avg delta | Range |
8
+ |---|---|---|
9
+ | Width | +87px | -403 to +1482 |
10
+ | Height | +576px | -109 to +4833 |
11
+
12
+ For diagrams where XMI matches reference content (small delta),
13
+ the canvas is consistently ~20-25 px wider and ~7-15 px taller
14
+ than reference. That delta is the frame margin.
15
+
16
+ ## Frame margin rule
17
+
18
+ Reference SVGs use non-uniform frame margins around element
19
+ bounds:
20
+
21
+ - Left: 35 px (body left to canvas left)
22
+ - Right: 50 px (body right to canvas right)
23
+ - Top: 60 px (body top to canvas top)
24
+ - Bottom: 36 px (body bottom to canvas bottom)
25
+
26
+ These come from EA's frame outer border (6 px from canvas edge)
27
+ plus an additional 29/44/54/30 px inset for the body. The asymmetry
28
+ exists because:
29
+
30
+ - Top: extra space for the frame tab label (extends from y=6 to
31
+ y=26 plus padding to body_top=60).
32
+ - Right/bottom: extra space for shadow / image padding.
33
+
34
+ ## Fix attempted
35
+
36
+ `BoundsCalculator#compute` already reserves 20 px above each
37
+ Package element for the tab polygon. Adding frame-aware padding
38
+ to all four sides would close the per-diagram gap on small
39
+ diagrams.
40
+
41
+ ## Why deferred
42
+
43
+ The 576 px average height delta dwarfs the frame margin issue.
44
+ Most of the height over-rendering is from XMI/SVG drift (we render
45
+ elements the reference SVG doesn't show). Until that's resolved
46
+ (fixture regeneration — see TODO-D 04), fixing the frame margin
47
+ won't move the aggregate metric meaningfully.
48
+
49
+ The small-diagram match (those closest to reference) shows the
50
+ frame margin fix would close ~5-10 px of the remaining 20-25 px
51
+ delta. Not enough to justify the added complexity right now.
@@ -0,0 +1,39 @@
1
+ # TODO-D 06 - Group layering parity
2
+
3
+ ## Status: PARTIAL (2026-07-26)
4
+
5
+ ## Current state
6
+
7
+ EA emits each `<rect>`, `<polygon>`, `<path>`, `<text>` inside its
8
+ own `<g>` block with a specific `style` attribute. Style strings
9
+ differ by:
10
+
11
+ - stroke_width (1 vs 2)
12
+ - stroke_linecap (round vs square)
13
+ - stroke_linejoin (bevel vs miter)
14
+ - fill color
15
+ - stroke color
16
+ - opacity
17
+
18
+ Our emitter groups output by `style_key` (a Symbol like
19
+ `:diamond_filled` or `:triangle_open`), with the style string
20
+ looked up from a small dispatch table. This matches EA's grouping
21
+ semantics for most cases.
22
+
23
+ ## Note element body
24
+
25
+ The Note element body was previously emitted as a `<polygon>`. EA
26
+ emits it as a closed `<path d="M...L...Z"/>` with
27
+ `stroke-linejoin=bevel` and `stroke-linecap=square`. Fixed in
28
+ commit f4fa55f.
29
+
30
+ ## Remaining gap
31
+
32
+ EA sometimes uses different `stroke-linecap` for the same shape
33
+ type depending on whether it's a "decorative" element (square cap)
34
+ or a "connector" element (round cap). Our style dispatch table
35
+ doesn't distinguish these. Visible in:
36
+
37
+ - Note bodies (square) vs classifier rects (round) — fixed
38
+ - Connector lines (round) vs divider lines (round) — both round
39
+ - Visibility icon rects inside attribute compartments — TBD