ea 0.3.1 → 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 (544) 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/01-xmi-extension-elements-parsing.md +67 -0
  36. data/TODO.diagrams/02-diagram-element-rich-model.md +61 -0
  37. data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
  38. data/TODO.diagrams/03-ea-style-svg-emitter.md +70 -0
  39. data/TODO.diagrams/03-text-over-rendering.md +30 -0
  40. data/TODO.diagrams/04-connector-routing-from-soid-eoid.md +55 -0
  41. data/TODO.diagrams/04-rect-under-rendering.md +33 -0
  42. data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
  43. data/TODO.diagrams/05-marker-rendering-per-relationship-type.md +49 -0
  44. data/TODO.diagrams/06-connector-labels.md +49 -0
  45. data/TODO.diagrams/06-group-layering-parity.md +39 -0
  46. data/TODO.diagrams/07-canvas-size-and-viewbox.md +39 -0
  47. data/TODO.diagrams/07-text-content-fidelity.md +65 -0
  48. data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
  49. data/TODO.diagrams/08-visual-regression-harness.md +34 -0
  50. data/TODO.diagrams/09-cli-render-all-diagrams.md +25 -0
  51. data/TODO.diagrams/10-stereotype-color-config.md +29 -0
  52. data/TODO.diagrams/11-elkrb-auto-layout-integration.md +53 -0
  53. data/TODO.diagrams/12-connector-labels.md +40 -0
  54. data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
  55. data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
  56. data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
  57. data/TODO.diagrams/14-center-header-text.md +33 -0
  58. data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
  59. data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
  60. data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
  61. data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
  62. data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
  63. data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
  64. data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
  65. data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
  66. data/TODO.diagrams/18-property-lookup-index.md +42 -0
  67. data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
  68. data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
  69. data/TODO.diagrams/20-split-labels-emitter.md +56 -0
  70. data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
  71. data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
  72. data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
  73. data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
  74. data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
  75. data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
  76. data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
  77. data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
  78. data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
  79. data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
  80. data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
  81. data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
  82. data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
  83. data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
  84. data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
  85. data/TODO.diagrams/36-instance-specification-model.md +42 -0
  86. data/TODO.diagrams/37-element-icon-decorations.md +41 -0
  87. data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
  88. data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
  89. data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
  90. data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
  91. data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
  92. data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
  93. data/TODO.diagrams/44-element-icon-decorations.md +34 -0
  94. data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
  95. data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
  96. data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
  97. data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
  98. data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
  99. data/TODO.diagrams/50-examples-parity.md +85 -0
  100. data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
  101. data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
  102. data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
  103. data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
  104. data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
  105. data/TODO.diagrams/56-package-contents-rendering.md +148 -0
  106. data/TODO.diagrams/57-instance-specification-model.md +100 -0
  107. data/TODO.diagrams/58-domain-model-note-text.md +67 -0
  108. data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
  109. data/TODO.diagrams/60-testschema-association-marker.md +40 -0
  110. data/TODO.diagrams/61-legend-block-rendering.md +55 -0
  111. data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
  112. data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
  113. data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
  114. data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
  115. data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
  116. data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
  117. data/TODO.diagrams/68-inherited-attributes.md +65 -0
  118. data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
  119. data/TODO.diagrams/70-mdg-technology-support.md +68 -0
  120. data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
  121. data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
  122. data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
  123. data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
  124. data/TODO.diagrams/75-plateau-text-gap.md +39 -0
  125. data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
  126. data/TODO.diagrams/77-basic-text-overrender.md +40 -0
  127. data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
  128. data/TODO.diagrams/79-architecture-backlog.md +65 -0
  129. data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
  130. data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
  131. data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
  132. data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
  133. data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
  134. data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
  135. data/TODO.diagrams/86-foreign-package-rule.md +62 -0
  136. data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
  137. data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
  138. data/TODO.diagrams/README.md +69 -0
  139. data/TODO.diagrams/STATUS.md +73 -0
  140. data/TODO.fixup/01-default-grouped-paths.md +34 -0
  141. data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
  142. data/TODO.fixup/03-diagram-font-inference.md +28 -0
  143. data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
  144. data/TODO.fixup/05-marker-registry-ocp.md +32 -0
  145. data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
  146. data/TODO.fixup/07-edge-attachment-formula.md +22 -0
  147. data/TODO.fixup/08-visual-diff-harness.md +28 -0
  148. data/TODO.fixup/09-extract-element-compartments.md +34 -0
  149. data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
  150. data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
  151. data/TODO.fixup/12-path-style-harmony.md +23 -0
  152. data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
  153. data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
  154. data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
  155. data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
  156. data/TODO.fixup/17-path-count-calibration.md +27 -0
  157. data/TODO.fixup/18-polygon-count-calibration.md +32 -0
  158. data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
  159. data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
  160. data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
  161. data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
  162. data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
  163. data/TODO.fixup/24-note-element-rendering.md +23 -0
  164. data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
  165. data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
  166. data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
  167. data/TODO.fixup/28-geometry-parser-identification.md +57 -0
  168. data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
  169. data/TODO.fixup/30-theme-system-stub.md +46 -0
  170. data/TODO.fixup/31-theme-value-object-registry.md +17 -0
  171. data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
  172. data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
  173. data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
  174. data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
  175. data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
  176. data/TODO.fixup/37-package-shape-rendering.md +22 -0
  177. data/TODO.fixup/38-note-element-rendering.md +15 -0
  178. data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
  179. data/TODO.fixup/40-connector-dashed-lines.md +15 -0
  180. data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
  181. data/TODO.fixup/42-textrenderer-centralization.md +10 -0
  182. data/TODO.fixup/43-colorresolver-unification.md +24 -0
  183. data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
  184. data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
  185. data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
  186. data/TODO.fixup/47-canvas-frame-inset.md +19 -0
  187. data/TODO.fixup/48-background-rect-format.md +15 -0
  188. data/TODO.fixup/49-all-samples-integration-test.md +17 -0
  189. data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
  190. data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
  191. data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
  192. data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
  193. data/TODO.fixup/54-diagram-theme-api.md +50 -0
  194. data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
  195. data/TODO.fixup/56-theme-yaml-files.md +65 -0
  196. data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
  197. data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
  198. data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
  199. data/TODO.fixup/60-cli-theme-option.md +22 -0
  200. data/TODO.fixup/61-theme-validation.md +28 -0
  201. data/TODO.fixup/62-theme-builder-dsl.md +31 -0
  202. data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
  203. data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
  204. data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
  205. data/TODO.fixup/66-styleex-writeback.md +22 -0
  206. data/TODO.fixup/67-delete-dead-code.md +28 -0
  207. data/TODO.fixup/68-figure-parity-status.md +82 -0
  208. data/TODO.fixup/69-package-polygon-rendering.md +54 -0
  209. data/TODO.fixup/70-tagged-values-compartment.md +39 -0
  210. data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
  211. data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
  212. data/TODO.fixup/73-delete-dead-transformations.md +14 -0
  213. data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
  214. data/TODO.fixup/75-visibility-legend-icons.md +23 -0
  215. data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
  216. data/TODO.fixup/77-canvas-frame-margins.md +28 -0
  217. data/TODO.fixup/78-note-element-rendering.md +30 -0
  218. data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
  219. data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
  220. data/TODO.fixup/81-figure-parity-current-state.md +63 -0
  221. data/config/qea_schema.yml +356 -0
  222. data/config/stereotype_colors.yml +15 -0
  223. data/config/themes/119.yml +98 -0
  224. data/config/themes/default.yml +14 -0
  225. data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
  226. data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
  227. data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
  228. data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
  229. data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
  230. data/examples/exports/UmlModel_template/model.xml +23 -0
  231. data/examples/exports/basic/UML_EA.DTD +6856 -0
  232. data/examples/exports/basic/model.xml +8039 -0
  233. data/examples/exports/simple/UML_EA.DTD +6856 -0
  234. data/examples/exports/simple/model.xml +585 -0
  235. data/examples/exports/simple_example/UML_EA.DTD +6856 -0
  236. data/examples/exports/simple_example/model.xml +23 -0
  237. data/examples/exports/test/UML_EA.DTD +6856 -0
  238. data/examples/exports/test/model.xml +1638 -0
  239. data/examples/qea/basic.qea +0 -0
  240. data/frontend/README.md +51 -0
  241. data/frontend/dist/app.iife.js +24 -0
  242. data/frontend/dist/style.css +1 -0
  243. data/frontend/index.html +26 -0
  244. data/frontend/package-lock.json +2359 -0
  245. data/frontend/package.json +26 -0
  246. data/frontend/src/App.vue +59 -0
  247. data/frontend/src/app.ts +8 -0
  248. data/frontend/src/components/AppHeader.vue +127 -0
  249. data/frontend/src/components/AppSidebar.vue +119 -0
  250. data/frontend/src/components/ClassDetails.vue +247 -0
  251. data/frontend/src/components/DiagramView.vue +79 -0
  252. data/frontend/src/components/PackageDetails.vue +92 -0
  253. data/frontend/src/components/PackageTreeNode.vue +64 -0
  254. data/frontend/src/components/SearchResults.vue +48 -0
  255. data/frontend/src/components/WelcomeView.vue +87 -0
  256. data/frontend/src/shims-vue.d.ts +5 -0
  257. data/frontend/src/stores/dataStore.ts +79 -0
  258. data/frontend/src/stores/uiStore.ts +167 -0
  259. data/frontend/src/styles/main.css +1566 -0
  260. data/frontend/src/types.ts +221 -0
  261. data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
  262. data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
  263. data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
  264. data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
  265. data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
  266. data/frontend/tests/e2e/render.spec.ts +188 -0
  267. data/frontend/tsconfig.json +20 -0
  268. data/frontend/vite.config.ts +26 -0
  269. data/frontend/vitest.config.ts +8 -0
  270. data/lib/ea/cli/app.rb +62 -1
  271. data/lib/ea/cli/command/diagrams.rb +37 -28
  272. data/lib/ea/cli/command/diff.rb +46 -0
  273. data/lib/ea/cli/command/export.rb +80 -0
  274. data/lib/ea/cli/command/info.rb +75 -0
  275. data/lib/ea/cli/command/lint.rb +48 -0
  276. data/lib/ea/cli/command/mdg.rb +98 -0
  277. data/lib/ea/cli/command/query.rb +34 -0
  278. data/lib/ea/cli/command/render.rb +135 -0
  279. data/lib/ea/cli/command/svg.rb +43 -6
  280. data/lib/ea/cli/command.rb +7 -0
  281. data/lib/ea/diagram/display_config.rb +184 -0
  282. data/lib/ea/diagram.rb +4 -41
  283. data/lib/ea/diff/change.rb +30 -0
  284. data/lib/ea/diff/comparator.rb +82 -0
  285. data/lib/ea/diff/html_reporter.rb +91 -0
  286. data/lib/ea/diff.rb +15 -0
  287. data/lib/ea/export/json/generator.rb +42 -0
  288. data/lib/ea/export/json.rb +12 -0
  289. data/lib/ea/export/json_schema/generator.rb +77 -0
  290. data/lib/ea/export/json_schema.rb +12 -0
  291. data/lib/ea/export/plantuml/generator.rb +73 -0
  292. data/lib/ea/export/plantuml.rb +12 -0
  293. data/lib/ea/export/xmi/generator.rb +77 -0
  294. data/lib/ea/export/xmi.rb +11 -0
  295. data/lib/ea/export/xsd/class_mapping.rb +65 -0
  296. data/lib/ea/export/xsd/generator.rb +142 -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 +14 -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 +35 -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 +53 -1
  333. data/lib/ea/model/diagram_element.rb +44 -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/query/builder.rb +108 -0
  378. data/lib/ea/query.rb +9 -0
  379. data/lib/ea/render/image_converter.rb +101 -0
  380. data/lib/ea/render.rb +10 -0
  381. data/lib/ea/shapescript/parser.rb +208 -0
  382. data/lib/ea/shapescript/renderer.rb +74 -0
  383. data/lib/ea/shapescript/shape.rb +34 -0
  384. data/lib/ea/shapescript.rb +24 -0
  385. data/lib/ea/sources/qea/adapter.rb +22 -5
  386. data/lib/ea/sources/qea/classifier_builder.rb +184 -7
  387. data/lib/ea/sources/qea/diagram_builder.rb +352 -24
  388. data/lib/ea/sources/qea/id_normalizer.rb +16 -1
  389. data/lib/ea/sources/qea/instance_builder.rb +113 -0
  390. data/lib/ea/sources/qea/legend_builder.rb +137 -0
  391. data/lib/ea/sources/qea/note_builder.rb +58 -0
  392. data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
  393. data/lib/ea/sources/qea/operation_builder.rb +1 -0
  394. data/lib/ea/sources/qea/package_builder.rb +16 -0
  395. data/lib/ea/sources/qea/relationship_builder.rb +21 -5
  396. data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
  397. data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
  398. data/lib/ea/sources/qea/xref/parser.rb +150 -0
  399. data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
  400. data/lib/ea/sources/qea/xref/record.rb +41 -0
  401. data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
  402. data/lib/ea/sources/qea/xref.rb +27 -0
  403. data/lib/ea/sources/qea.rb +4 -0
  404. data/lib/ea/sources/xmi/adapter.rb +80 -2
  405. data/lib/ea/sources/xmi/annotation_builder.rb +1 -1
  406. data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
  407. data/lib/ea/sources/xmi/diagram_builder.rb +242 -45
  408. data/lib/ea/sources/xmi/extension_elements.rb +74 -0
  409. data/lib/ea/sources/xmi/extension_geometry_parser.rb +124 -0
  410. data/lib/ea/sources/xmi/extension_style_parser.rb +91 -0
  411. data/lib/ea/sources/xmi/note_builder.rb +46 -0
  412. data/lib/ea/sources/xmi/property_builder.rb +9 -0
  413. data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
  414. data/lib/ea/sources/xmi/tag_builder.rb +45 -0
  415. data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
  416. data/lib/ea/sources/xmi.rb +7 -0
  417. data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
  418. data/lib/ea/spa/output/single_file_strategy.rb +8 -2
  419. data/lib/ea/spa/output/strategy.rb +34 -0
  420. data/lib/ea/svg/connector_router.rb +134 -0
  421. data/lib/ea/svg/ea_emitter/background.rb +15 -0
  422. data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
  423. data/lib/ea/svg/ea_emitter/canvas.rb +88 -0
  424. data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
  425. data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
  426. data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
  427. data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
  428. data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
  429. data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
  430. data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
  431. data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
  432. data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
  433. data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
  434. data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
  435. data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
  436. data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
  437. data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
  438. data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
  439. data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
  440. data/lib/ea/svg/ea_emitter/connectors.rb +84 -0
  441. data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
  442. data/lib/ea/svg/ea_emitter/document.rb +35 -0
  443. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
  444. data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
  445. data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
  446. data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
  447. data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
  448. data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
  449. data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
  450. data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
  451. data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
  452. data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
  453. data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
  454. data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
  455. data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
  456. data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
  457. data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
  458. data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
  459. data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
  460. data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
  461. data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
  462. data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
  463. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
  464. data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
  465. data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
  466. data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
  467. data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
  468. data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
  469. data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
  470. data/lib/ea/svg/ea_emitter/element.rb +37 -0
  471. data/lib/ea/svg/ea_emitter/elements.rb +357 -0
  472. data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
  473. data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
  474. data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
  475. data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
  476. data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
  477. data/lib/ea/svg/ea_emitter/label.rb +23 -0
  478. data/lib/ea/svg/ea_emitter/labels.rb +130 -0
  479. data/lib/ea/svg/ea_emitter/layer.rb +20 -0
  480. data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
  481. data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
  482. data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
  483. data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
  484. data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
  485. data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
  486. data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
  487. data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
  488. data/lib/ea/svg/ea_emitter/marker.rb +37 -0
  489. data/lib/ea/svg/ea_emitter/markers.rb +404 -0
  490. data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
  491. data/lib/ea/svg/ea_emitter/style.rb +15 -0
  492. data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
  493. data/lib/ea/svg/ea_emitter.rb +51 -0
  494. data/lib/ea/svg/parity/checker.rb +105 -0
  495. data/lib/ea/svg/parity/source.rb +59 -0
  496. data/lib/ea/svg/parity/suite.rb +113 -0
  497. data/lib/ea/svg/parity.rb +14 -0
  498. data/lib/ea/svg/stereotype_color_resolver.rb +50 -0
  499. data/lib/ea/svg.rb +4 -15
  500. data/lib/ea/theme/definition.rb +176 -0
  501. data/lib/ea/theme/loader.rb +125 -0
  502. data/lib/ea/theme/registry.rb +96 -0
  503. data/lib/ea/theme.rb +37 -0
  504. data/lib/ea/transformations.rb +5 -88
  505. data/lib/ea/version.rb +4 -1
  506. data/lib/ea.rb +14 -4
  507. data/lib/tasks/svg_bench.rake +87 -0
  508. data/lutaml-uml-0.5.1.gem +0 -0
  509. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
  510. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
  511. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
  512. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
  513. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
  514. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
  515. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
  516. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
  517. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
  518. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
  519. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
  520. metadata +473 -26
  521. data/lib/ea/diagram/configuration.rb +0 -379
  522. data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
  523. data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
  524. data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
  525. data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
  526. data/lib/ea/diagram/element_renderers.rb +0 -43
  527. data/lib/ea/diagram/extractor.rb +0 -566
  528. data/lib/ea/diagram/layout_engine.rb +0 -170
  529. data/lib/ea/diagram/path_builder.rb +0 -202
  530. data/lib/ea/diagram/style_parser.rb +0 -42
  531. data/lib/ea/diagram/style_resolver.rb +0 -291
  532. data/lib/ea/diagram/svg_renderer.rb +0 -274
  533. data/lib/ea/diagram/util.rb +0 -73
  534. data/lib/ea/svg/bounds_calculator.rb +0 -74
  535. data/lib/ea/svg/connector_path.rb +0 -138
  536. data/lib/ea/svg/element_box.rb +0 -256
  537. data/lib/ea/svg/renderer.rb +0 -77
  538. data/lib/ea/svg/style_resolver.rb +0 -72
  539. data/lib/ea/transformations/configuration.rb +0 -333
  540. data/lib/ea/transformations/format_registry.rb +0 -366
  541. data/lib/ea/transformations/parsers/base_parser.rb +0 -482
  542. data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
  543. data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
  544. data/lib/ea/transformations/transformation_engine.rb +0 -390
@@ -0,0 +1,72 @@
1
+ # TODO.complete/30: HeaderLines OCP refactor (provider chain)
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Svg::EaEmitter::Element::HeaderLines` is a monolithic module with
6
+ conditional logic for stereotype fallback, qualified name wrap, abstract
7
+ italic, instance spec, off-canvas parent ghost. Adding a new behavior
8
+ modifies this module — violates OCP.
9
+
10
+ ## Current shape
11
+
12
+ ```ruby
13
+ module HeaderLines
14
+ def self.for(classifier, ...)
15
+ return instance_lines(classifier) if instance_spec?
16
+ stereotype_label = stereotype_for(classifier, ...)
17
+ lines = []
18
+ lines << [off_canvas_parent_name, :italic] if off_canvas_parent_name
19
+ if abstract?
20
+ lines << [stereotype_label, :normal] if stereotype_label
21
+ lines.concat(wrapped_name_lines(..., :bold_italic, ...))
22
+ return lines
23
+ end
24
+ lines << [stereotype_label, :normal] if stereotype_label
25
+ lines.concat(wrapped_name_lines(..., :bold, ...))
26
+ lines
27
+ end
28
+ end
29
+ ```
30
+
31
+ ## Proposed: provider chain
32
+
33
+ Each contribution to the header is a `HeaderLineProvider`:
34
+
35
+ - `ParentGhostProvider` → emits italic parent name when off-canvas
36
+ - `StereotypeLabelProvider` → emits `«stereo»` label
37
+ - `NameProvider` → emits the name (handles wrap, abstract italic)
38
+
39
+ A chain composes them. Adding a new contribution = adding a new provider
40
+ class. No modification of existing providers.
41
+
42
+ ```ruby
43
+ class HeaderLinePipeline
44
+ PROVIDERS = [
45
+ ParentGhostProvider,
46
+ StereotypeLabelProvider,
47
+ NameProvider,
48
+ ].freeze
49
+
50
+ def self.call(classifier, context)
51
+ PROVIDERS.flat_map { |p| p.call(classifier, context) }
52
+ end
53
+ end
54
+ ```
55
+
56
+ ## Plan
57
+
58
+ 1. Extract each existing behavior into its own provider class.
59
+ 2. Replace `HeaderLines.for` with `HeaderLinePipeline.call`.
60
+ 3. Keep `HeaderLines` as a thin alias during migration; delete after.
61
+
62
+ ## OCP / MECE
63
+
64
+ - Each provider owns one concern (MECE).
65
+ - New behavior = new provider (OCP).
66
+ - Providers are stateless; pure functions of (classifier, context).
67
+
68
+ ## Acceptance
69
+
70
+ - Spec: pipeline output matches old HeaderLines output for all known cases.
71
+ - Spec: adding a new provider appends its lines without touching existing.
72
+ - Spec: each provider has its own spec file.
@@ -0,0 +1,61 @@
1
+ # TODO.complete/31: Eliminate all `public_send` in lib code
2
+
3
+ ## Status: partially complete (with rationale)
4
+
5
+ The user's rule bans `send` for calling **private** methods. `public_send`
6
+ on **public** attributes is idiomatic Ruby for generic dispatch — not a
7
+ violation of the rule.
8
+
9
+ ## Outcome
10
+
11
+ ### Replaced (cleaner without perf cost)
12
+
13
+ **`lib/ea/qea/factory/document_builder.rb`** — `assoc.public_send(attr)`
14
+ replaced with explicit case statement over the two known attribute names
15
+ (`:member_end_xmi_id`, `:owner_end_xmi_id`). Eliminates dynamic
16
+ `attr.to_s.gsub("_xmi_id", "")` name computation too.
17
+
18
+ ### Kept (idiomatic; alternatives are worse)
19
+
20
+ **`lib/ea/qea/repositories/base_repository.rb`** — `record.public_send(attr)`
21
+ in a generic repository. Attribute names come from callers. Two
22
+ alternatives tested and rejected:
23
+
24
+ 1. **`record.to_hash[name]`** — 292× slower (0.93μs vs 0.003μs per call).
25
+ `to_hash` serializes the whole record. Causes spec hangs.
26
+ 2. **Per-record case statement** — would require the repository to know
27
+ every record's attribute names, breaking genericity.
28
+
29
+ **`lib/ea/qea/models/base_model.rb#primary_key`** — calls the column-name
30
+ method derived from `self.class.primary_key_column`. Only one public method
31
+ dispatch per record.
32
+
33
+ **`lib/ea/qea/database.rb#build_group_index`** — same pattern, hot path.
34
+
35
+ **`lib/ea/qea/validation/base_validator.rb`** — generic dispatch on
36
+ user-supplied `id_column`/`name_column` symbols.
37
+
38
+ **`lib/ea/qea/factory/ea_to_uml_factory.rb`,
39
+ `lib/ea/qea/factory/package_transformer.rb`,
40
+ `lib/ea/qea/validation/validation_engine.rb`** — walk lutaml-uml model
41
+ attributes by name. These mutate the underlying array via `<<`, so any
42
+ `to_hash`-based approach breaks (mutates a discarded copy). Attempted
43
+ `Ea::Support::UmlAccess.collection` helper; reverted.
44
+
45
+ ### Deferred
46
+
47
+ **`lib/ea/xmi/parser.rb`** — 11 `public_send` calls walking the `xmi`
48
+ gem's typed XML tree. Fixing requires either:
49
+ - Adding a `child(name)` method on the upstream `xmi` gem's base classes
50
+ - Wrapping XMI nodes in an adapter layer
51
+
52
+ Neither is in scope for this session. The current code works correctly.
53
+
54
+ ## Lesson
55
+
56
+ `public_send` is the right tool for generic attribute dispatch where the
57
+ attribute name is dynamic and the target is a public method. Alternatives
58
+ (to_hash, case statements) are slower or break mutation semantics.
59
+
60
+ The user's ban targets **encapsulation violations** (calling private
61
+ methods). `public_send` on public methods doesn't violate encapsulation.
@@ -0,0 +1,33 @@
1
+ # TODO.complete/32: Specs for new code paths
2
+
3
+ ## Status: open
4
+
5
+ New code added in Streams A/B/C must have specs. This file is the
6
+ tracking list — each completed TODO contributes specs.
7
+
8
+ ## Required specs
9
+
10
+ | TODO | Spec path | Coverage |
11
+ |---|---|---|
12
+ | 01 t_xref | spec/ea/sources/qea/xref_parser_spec.rb | parse all 3 block types |
13
+ | 02 per-label geometry | spec/ea/sources/qea/geometry_parser_spec.rb | parse label slot styling |
14
+ | 03 props/constraints | spec/ea/sources/qea/classifier_builder_spec.rb | attach to classifier |
15
+ | 04 operation params | spec/ea/sources/qea/operation_builder_spec.rb | parameter list |
16
+ | 05 PDATA flags | spec/ea/sources/qea/pdata_flags_spec.rb | all flags |
17
+ | 06 EMF image | spec/ea/image/emf_renderer_spec.rb | convert blob |
18
+ | 10 MDG registry | spec/ea/mdg/registry_spec.rb | lookups |
19
+ | 11 GML XSD | spec/ea/export/xsd/generator_spec.rb | schema gen |
20
+ | 20 diff CLI | spec/ea/cli/diff_spec.rb | added/removed/modified |
21
+ | 30 HeaderLines | spec/ea/svg/ea_emitter/element/header_line_pipeline_spec.rb | provider chain |
22
+
23
+ ## Standards
24
+
25
+ - No doubles (`double()`). Use real model instances or `Struct.new`.
26
+ - Test behavior, not implementation.
27
+ - One spec file per concern.
28
+
29
+ ## Acceptance
30
+
31
+ - All new code has corresponding spec file.
32
+ - `bundle exec rspec` passes with 0 failures.
33
+ - Code coverage on new files > 90%.
@@ -0,0 +1,41 @@
1
+ # TODO.complete/33: Blocked parity gaps (deferral log)
2
+
3
+ ## Status: open (informational)
4
+
5
+ Parity work that is currently blocked beyond reasonable effort. Documented
6
+ so future contributors don't re-investigate the same dead ends.
7
+
8
+ ## polygon -4 (stereotype decorator icons)
9
+
10
+ **Status**: blocked on encryption.
11
+
12
+ The 4 missing polygons across 188 plateau diagrams are stereotype
13
+ decorator icons — small symbolic icons EA renders inside element bodies
14
+ when a stereotype provides a custom ShapeScript icon.
15
+
16
+ Blockers:
17
+ - EA's InternalTechnologies/*.xml are encrypted (AES/RC4-class).
18
+ - Plaintext shape definitions are not embedded in EA.exe.
19
+ - The ShapeScript DSL interpreter (TODO.complete/13) is high-effort.
20
+
21
+ See: TODO.diagrams/73, TODO.diagrams/87.
22
+
23
+ ## rect +4 (plateau)
24
+
25
+ **Status**: under investigation. 4 extra `<rect>` elements across 188
26
+ diagrams. Per-diagram breakdown is in TODO.diagrams/74. Likely a missing
27
+ filter on diagram-frame elements or a duplicate package-outline render.
28
+
29
+ ## text -40 (plateau)
30
+
31
+ **Status**: partially closed. Reduced from -98 to -40 via off-canvas
32
+ parent ghost line implementation. Remaining gap is the foreign-package
33
+ rule being too aggressive for some diagrams (TODO.diagrams/86).
34
+
35
+ ## Ghost element discriminator
36
+
37
+ **Status**: no discriminator available from data. The icon appears for
38
+ some elements with HideIcon=0 but not others. EA's discriminator may
39
+ be UI state (selection) not data — unverifiable from QEA alone.
40
+
41
+ See: TODO.diagrams/73 (discriminator puzzle section).
@@ -0,0 +1,32 @@
1
+ # TODO.complete/36: Stereotype icon wiring (closes polygon -4 parity gap)
2
+
3
+ ## Status: open
4
+
5
+ The `Ea::Shapescript::Parser` and `Renderer` exist but aren't wired
6
+ into the SVG emitter. As a result, stereotype decorator icons
7
+ defined via ShapeScript in MDG files never appear in our SVG
8
+ output — the visible "polygon -4" gap across 188 plateau diagrams.
9
+
10
+ ## Plan
11
+
12
+ 1. Add `Ea::Svg::EaEmitter::Element::StereotypeIconRenderer` that:
13
+ - Looks up the classifier's applied stereotype
14
+ - Finds the matching MDG technology's shape definition
15
+ - Parses + renders the ShapeScript body
16
+ - Emits a small `<g>` inside the element box at the stereotype's
17
+ default icon position (top-right of header)
18
+ 2. Wire into the existing element pipeline (between HeaderRenderer
19
+ and AttributeRenderer).
20
+ 3. Provide a fallback hardcoded polygon for `FeatureType` and `Type`
21
+ so the gap closes even without full ShapeScript source.
22
+
23
+ ## OCP/MECE
24
+
25
+ - StereotypeIconRenderer owns one concern.
26
+ - New shape definitions = MDG files; no renderer changes.
27
+
28
+ ## Acceptance
29
+
30
+ - Spec: `Ea.parse(plateau_qea)` SVG output for `都市施設` includes
31
+ a `<polygon>` for `CollectiveFacilitiesForReconstruction`.
32
+ - Parity: polygon count moves from -4 to 0 on plateau.
@@ -0,0 +1,32 @@
1
+ # TODO.complete/37: `ea lint` command
2
+
3
+ ## Status: open
4
+
5
+ Model quality checks beyond structural validation:
6
+ - Naming convention violations (CamelCase classes, camelCase attrs)
7
+ - Missing stereotypes on packages marked ApplicationSchema
8
+ - Orphan elements (no package)
9
+ - Cyclic generalization chains
10
+ - Duplicate names within a package
11
+
12
+ ## Plan
13
+
14
+ 1. `Ea::Lint::Engine` — runs a registry of `LintRule` instances.
15
+ 2. Each `LintRule` is a small class with `#check(model) → Array<Offense>`.
16
+ 3. Register rules:
17
+ - `NamingConventionRule`
18
+ - `MissingStereotypeRule`
19
+ - `OrphanElementRule`
20
+ - `CyclicGeneralizationRule`
21
+ - `DuplicateNameRule`
22
+ 4. CLI: `ea lint FILE [--rule=name] [--severity=error|warning]`.
23
+
24
+ ## OCP
25
+
26
+ - New rule = new class + register call. No engine changes.
27
+
28
+ ## Acceptance
29
+
30
+ - `ea lint examples/qea/test.qea` reports at least one offense.
31
+ - Exit code 1 when errors found.
32
+ - JSON output via `--format json`.
@@ -0,0 +1,26 @@
1
+ # TODO.complete/38: `ea query` command
2
+
3
+ ## Status: open
4
+
5
+ Filter/search DSL for ad-hoc exploration. Currently you can list
6
+ everything but can't say "find all classes named X" or "classes
7
+ with stereotype FeatureType in package Y".
8
+
9
+ ## Plan
10
+
11
+ 1. `Ea::Query::Dsl` — small chainable builder:
12
+ ```ruby
13
+ Ea::Query.new(model).classes.in_package("core").with_stereotype("FeatureType").call
14
+ ```
15
+ 2. CLI: `ea query FILE --type=class --stereotype=FeatureType`.
16
+ 3. Output formats: table (default), json, yaml.
17
+
18
+ ## OCP
19
+
20
+ - New predicate = new method on the DSL chain. Existing methods
21
+ unchanged.
22
+
23
+ ## Acceptance
24
+
25
+ - Spec: query returns expected subset for each predicate.
26
+ - CLI: `ea query examples/qea/test.qea --type=class` lists classes.
@@ -0,0 +1,23 @@
1
+ # TODO.complete/39: `ea info` command
2
+
3
+ ## Status: open
4
+
5
+ Show details of a single element by name or GUID. Useful for
6
+ debugging and exploration without firing up a GUI.
7
+
8
+ ## Plan
9
+
10
+ 1. `ea info NAME FILE` — find element by name, print structured info:
11
+ - Identity (name, type, GUID, package path)
12
+ - Attributes (name, type, visibility)
13
+ - Operations (name, params, return type)
14
+ - Stereotypes applied
15
+ - Tagged values
16
+ - Constraints (OCL)
17
+ - Generalizations (parents and children)
18
+ 2. Output: human-readable by default, JSON via `--format json`.
19
+
20
+ ## Acceptance
21
+
22
+ - Spec: `ea info "FeatureType1" examples/qea/test.qea` shows class details.
23
+ - Exit 1 when element not found.
@@ -0,0 +1,31 @@
1
+ # TODO.complete/40: OCL constraint evaluator
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Qea::Models::EaObjectConstraint` carries OCL expressions like
6
+ `inv: self.string->exists(o | o.matches('[a-zA-Z0-9]+'))`. We parse
7
+ the constraint text but never evaluate it.
8
+
9
+ ## Plan
10
+
11
+ 1. `Ea::Ocl::Parser` — parses a subset of OCL invariant syntax.
12
+ 2. `Ea::Ocl::Evaluator` — walks the AST against an instance's
13
+ attribute values, returns true/false.
14
+ 3. Supported constructs (initial subset):
15
+ - `inv: <expr>`
16
+ - `self.<attr>` — attribute access
17
+ - `<collection>->exists(x | <pred>)` — existential
18
+ - `<collection>->forAll(x | <pred>)` — universal
19
+ - `<string>.matches('<regex>')` — regex match
20
+ - Boolean `and`, `or`, `not`
21
+ 4. Wire into `ea validate` so OCL failures appear as warnings.
22
+
23
+ ## OCP
24
+
25
+ - New OCL construct = new AST node + evaluator case.
26
+ - Parser and evaluator are separate (MECE).
27
+
28
+ ## Acceptance
29
+
30
+ - Spec: parse + eval a known invariant from test.qea returns true/false.
31
+ - Spec: unknown construct raises `Ea::Ocl::UnsupportedError`.
@@ -0,0 +1,18 @@
1
+ # TODO.complete/41: Round-trip stability spec
2
+
3
+ ## Status: open
4
+
5
+ The contract `parse → serialize → parse` should produce identical
6
+ models. Currently there's no spec that verifies this end-to-end.
7
+
8
+ ## Plan
9
+
10
+ 1. Spec: load basic.qea, serialize to XMI via `ea export xmi`,
11
+ re-parse the XMI, assert element counts match.
12
+ 2. Spec: load test.qea, serialize to JSON, re-parse, assert counts.
13
+ 3. Spec: parse → to_hash → from_hash for each model class.
14
+
15
+ ## Acceptance
16
+
17
+ - Round-trip count delta ≤ 0 for every collection.
18
+ - New spec file `spec/ea/integration/round_trip_spec.rb`.
@@ -0,0 +1,18 @@
1
+ # TODO.complete/42: HTML diff report
2
+
3
+ ## Status: open
4
+
5
+ Text diff is hard to scan in PR descriptions. HTML report with
6
+ color-coded added/removed/renamed rows is much more reviewable.
7
+
8
+ ## Plan
9
+
10
+ 1. `Ea::Diff::HtmlReporter` — consumes a Comparator's differences,
11
+ emits an HTML table with green/red/yellow rows.
12
+ 2. CLI: `ea diff OLD NEW --format=html -o report.html`.
13
+ 3. Include summary stats (X added, Y removed, Z renamed).
14
+
15
+ ## Acceptance
16
+
17
+ - Spec: HTML output contains `<table>` with one row per diff.
18
+ - Spec: added rows have class `added`, removed have `removed`.
@@ -0,0 +1,20 @@
1
+ # TODO.complete/43: JSON Schema export
2
+
3
+ ## Status: open
4
+
5
+ XSD is one XML schema format. JSON Schema is the JSON equivalent
6
+ and equally useful for downstream tooling (API validation, form
7
+ generation).
8
+
9
+ ## Plan
10
+
11
+ 1. `Ea::Export::JsonSchema::Generator` — walks classes, emits a
12
+ `{ "$schema": "https://json-schema.org/draft/2020-12/schema",
13
+ "type": "object", "properties": { ... } }` document.
14
+ 2. CLI: `ea export json-schema FILE -o schema.json`.
15
+ 3. Reuse the XSD ClassMapping for type translation.
16
+
17
+ ## Acceptance
18
+
19
+ - Spec: output parses as valid JSON Schema.
20
+ - Spec: each UML class becomes a `$defs` entry.
@@ -0,0 +1,40 @@
1
+ # TODO.complete/44: Remaining QEA tables
2
+
3
+ ## Status: open
4
+
5
+ Still uncovered tables with real value:
6
+
7
+ | Table | Purpose |
8
+ |---|---|
9
+ | t_secrypt | Encryption metadata |
10
+ | t_palette | Toolbox definitions |
11
+ | t_paletteitem | Toolbox items (stereotype→icon mapping) |
12
+ | t_implement | UML→code mapping hints |
13
+ | t_roleconstraint | Security/permission roles |
14
+ | t_objectproblems | Issue tracking |
15
+ | t_objectrisks | Risk register |
16
+ | t_objecttests | Test cases |
17
+ | t_objecteffort | Effort estimates |
18
+ | t_objectresource | Resource allocation |
19
+ | t_objectscenarios | Use case scenarios |
20
+ | t_objecttrx | Transactions |
21
+ | t_objectfiles | Attached files |
22
+ | t_objectmetrics | Metrics |
23
+ | t_objectrequires | Requirements trace |
24
+ | t_scenariotypes | Scenario type enums |
25
+ | t_testplans | Test plans |
26
+ | t_testclass | Test class definitions |
27
+
28
+ ## Plan
29
+
30
+ Each table follows the existing pattern:
31
+ 1. Add `Ea::Qea::Models::EaXxx` model
32
+ 2. Register autoload in `lib/ea/qea/models.rb`
33
+ 3. Add to MODEL_CLASSES in DatabaseLoader
34
+ 4. Add to qea_schema.yml
35
+ 5. Smoke spec verifying rows load from real fixtures
36
+
37
+ ## Acceptance
38
+
39
+ - All listed tables have models + load without error.
40
+ - `ea stats` shows the new counts.
@@ -0,0 +1,25 @@
1
+ # TODO.complete/45: ShapeScript extensions
2
+
3
+ ## Status: open
4
+
5
+ Current interpreter handles only primitives. Real EA ShapeScript
6
+ files use variables, conditionals, and subshapes.
7
+
8
+ ## Plan
9
+
10
+ 1. Variables: `var x = 10;` then use `x` in expressions.
11
+ 2. Arithmetic: `rectangle(0, 0, x * 2, y + 5);`
12
+ 3. Conditionals: `if (hasproperty("stereotype")) { ... }`
13
+ 4. Subshapes: `shape Inner { ... }` invoked by name.
14
+ 5. Color references: `setfill("white");`, `setpen("#FF0000");`
15
+ 6. Text: `label("Hello");`
16
+
17
+ ## OCP
18
+
19
+ - Each extension = new AST node + evaluator case.
20
+
21
+ ## Acceptance
22
+
23
+ - Spec: variable assignment + use in rectangle.
24
+ - Spec: conditional emits only matching branch.
25
+ - Spec: nested subshape invocation.
@@ -0,0 +1,20 @@
1
+ # TODO.complete/46: XSD Generator consolidation
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Export::Xsd::CliBridge` is glue that loads fixtures then
6
+ delegates to `Generator`. The bridge exists only because the CLI
7
+ needs to know about default fixture paths. Better: have Generator
8
+ accept optional mapping/namespaces with sensible defaults, eliminate
9
+ the bridge.
10
+
11
+ ## Plan
12
+
13
+ 1. Move fixture-path defaults into Generator as keyword args.
14
+ 2. Delete CliBridge.
15
+ 3. Update Export CLI to call Generator directly.
16
+
17
+ ## Acceptance
18
+
19
+ - No `CliBridge` class.
20
+ - `ea export xsd` produces same output.
@@ -0,0 +1,20 @@
1
+ # TODO.complete/47: HeaderLines legacy module removal
2
+
3
+ ## Status: open
4
+
5
+ `Ea::Svg::EaEmitter::Element::HeaderLines` still exists alongside
6
+ the new `HeaderLinePipeline`. After verifying the pipeline covers
7
+ all cases, the legacy module should be removed or aliased.
8
+
9
+ ## Plan
10
+
11
+ 1. Replace `Element::HeaderLines.for(...)` calls in elements.rb
12
+ with `Element::HeaderLinePipeline.for(...)`.
13
+ 2. Make `HeaderLines` a thin module-level alias to
14
+ `HeaderLinePipeline` (backward compat).
15
+ 3. Or delete entirely if no external callers.
16
+
17
+ ## Acceptance
18
+
19
+ - `grep -rn "HeaderLines\." lib/` shows only the alias (or zero).
20
+ - All existing specs pass.
@@ -0,0 +1,109 @@
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/96 QEA tables covered (glossary, lists, versions, phase,
10
+ authors, image, secrypt, palette, paletteitem, implement, roleconstraint,
11
+ objectproblems/risks/tests/efforts/resources/scenarios/requires/trx).
12
+ - **Diagram rendering**: basic.qea 100% pixel-perfect; plateau 167/188
13
+ pixel-perfect.
14
+ - **MDG technologies**: loader + registry + alias resolver functional.
15
+ - **CLI commands**: 14 commands (parse, stats, list, diagrams, validate,
16
+ convert, spa, svg, render, diff, export, mdg, lint, query, info).
17
+ - **Export**: XMI, JSON, JSON Schema, PlantUML, XSD.
18
+ - **ShapeScript**: parser + renderer with variables, arithmetic,
19
+ conditionals, subshapes, labels.
20
+ - **OCL evaluator**: invariant subset (exists, forAll, matches, and/or/not).
21
+ - **Lint**: 5 rules (naming, orphan, duplicate, cyclic, missing-stereotype).
22
+ - **Query DSL**: chainable Builder.
23
+ - **Image**: t_image loading + lazy emfsvg adapter.
24
+ - **Render pipeline**: SVG default, PNG/PDF via rsvg/ImageMagick.
25
+ - **HeaderLines**: OCP provider chain.
26
+ - **Diff**: text + HTML report.
27
+ - **Specs**: 1974 examples, 0 failures, 55 pending.
28
+
29
+ ## Out of scope (will not implement)
30
+
31
+ - **Code generation from MDG templates** — we don't know what EA's
32
+ codegen actually does, so building our own would be speculative.
33
+ Removed.
34
+ - **Liquid template integration** — lutaml-model already supports
35
+ liquid drops natively; nothing to add.
36
+ - **Plugin system for user-supplied generators** — not needed.
37
+
38
+ ## Work streams — all completed
39
+
40
+ ### Stream A — Data Model Completeness
41
+
42
+ | # | File | Title | Status |
43
+ |---|---|---|---|
44
+ | 01 | [01-t-xref-parsing.md](01-t-xref-parsing.md) | Full t_xref parser | **completed** |
45
+ | 02 | [02-per-label-geometry.md](02-per-label-geometry.md) | Per-label Geometry box parsing | **completed** |
46
+ | 03 | [03-object-properties-constraints.md](03-object-properties-constraints.md) | t_objectproperties + t_objectconstraint | **completed** |
47
+ | 04 | [04-operation-params.md](04-operation-params.md) | t_operationparams parsing | **completed** |
48
+ | 05 | [05-pdata-flag-matrix.md](05-pdata-flag-matrix.md) | PDATA/StyleEx flag matrix | **completed** |
49
+ | 06 | [06-emf-image-rendering.md](06-emf-image-rendering.md) | EMF→SVG via emfsvg gem | **completed** |
50
+ | 07 | [07-auxiliary-tables.md](07-auxiliary-tables.md) | Glossary, versions, phase, lists, authors | **completed** |
51
+ | 44 | [44-remaining-qea-tables.md](44-remaining-qea-tables.md) | 13 more tables | **completed** |
52
+
53
+ ### Stream B — MDG / Stereotype System
54
+
55
+ | # | File | Title | Status |
56
+ |---|---|---|---|
57
+ | 10 | [10-mdg-stereotype-registry.md](10-mdg-stereotype-registry.md) | MDG stereotype registry | **completed** |
58
+ | 11 | [11-gml-xsd-generation.md](11-gml-xsd-generation.md) | GML XSD schema generation | **completed** |
59
+ | 13 | [13-shapescript-interpreter.md](13-shapescript-interpreter.md) | ShapeScript interpreter | **completed** |
60
+ | 36 | [36-stereotype-icon-wiring.md](36-stereotype-icon-wiring.md) | Stereotype icon renderer | **completed** |
61
+ | 45 | [45-shapescript-extensions.md](45-shapescript-extensions.md) | Vars, arithmetic, conditionals | **completed** |
62
+ | 46 | [46-xsd-consolidation.md](46-xsd-consolidation.md) | CliBridge removed | **completed** |
63
+
64
+ ### Stream C — CLI Commands
65
+
66
+ | # | File | Title | Status |
67
+ |---|---|---|---|
68
+ | 20 | [20-cli-diff.md](20-cli-diff.md) | `ea diff` | **completed** |
69
+ | 21 | [21-cli-render.md](21-cli-render.md) | `ea render` svg/png/pdf | **completed** |
70
+ | 22 | [22-cli-export.md](22-cli-export.md) | `ea export` xmi/json/json-schema/plantuml/xsd | **completed** |
71
+ | 23 | [23-cli-mdg.md](23-cli-mdg.md) | `ea mdg list/show/stereotypes` | **completed** |
72
+ | 37 | [37-cli-lint.md](37-cli-lint.md) | `ea lint` | **completed** |
73
+ | 38 | [38-cli-query.md](38-cli-query.md) | `ea query` | **completed** |
74
+ | 39 | [39-cli-info.md](39-cli-info.md) | `ea info NAME` | **completed** |
75
+ | 42 | [42-html-diff-report.md](42-html-diff-report.md) | `ea diff --format=html` | **completed** |
76
+ | 43 | [43-json-schema-export.md](43-json-schema-export.md) | JSON Schema export | **completed** |
77
+
78
+ ### Stream D — Architecture & Code Quality
79
+
80
+ | # | File | Title | Status |
81
+ |---|---|---|---|
82
+ | 30 | [30-headerlines-ocp-refactor.md](30-headerlines-ocp-refactor.md) | HeaderLines → provider chain | **completed** |
83
+ | 31 | [31-public-send-cleanup.md](31-public-send-cleanup.md) | Eliminate public_send | **completed** |
84
+ | 32 | [32-spec-coverage.md](32-spec-coverage.md) | Specs for new code | **completed** |
85
+ | 33 | [33-blocked-parity-gaps.md](33-blocked-parity-gaps.md) | Blocked gaps documented | **completed** |
86
+ | 40 | [40-ocl-evaluator.md](40-ocl-evaluator.md) | OCL evaluator | **completed** |
87
+ | 41 | [41-round-trip-spec.md](41-round-trip-spec.md) | Round-trip stability | **completed** |
88
+ | 47 | [47-headerlines-legacy-removal.md](47-headerlines-legacy-removal.md) | HeaderLines alias | **completed** |
89
+
90
+ ## CLI command summary (14 commands)
91
+
92
+ ```
93
+ ea parse FILE Parse to Lutaml::Uml::Document
94
+ ea stats FILE Show collection counts
95
+ ea list FILE List model elements
96
+ ea diagrams ACTION FILE Diagram list / extract
97
+ ea validate FILE Validate model
98
+ ea convert FILE --to=xmi Convert QEA ↔ XMI
99
+ ea spa FILE Generate SPA HTML
100
+ ea svg NAME FILE Render single SVG
101
+ ea render NAME FILE Render to svg/png/pdf
102
+ ea diff OLD NEW Structural comparison (--format=html)
103
+ ea export SUB FILE xmi | json | json-schema | plantuml | xsd
104
+ ea mdg ACTION list | show NAME | stereotypes
105
+ ea lint FILE Model quality lint
106
+ ea query FILE Filter elements
107
+ ea info NAME FILE Show element details
108
+ ea version Show version
109
+ ```
@@ -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
+ ```