ea 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +3 -0
- data/TODO.complete/01-t-xref-parsing.md +91 -0
- data/TODO.complete/02-per-label-geometry.md +50 -0
- data/TODO.complete/03-object-properties-constraints.md +57 -0
- data/TODO.complete/04-operation-params.md +37 -0
- data/TODO.complete/05-pdata-flag-matrix.md +52 -0
- data/TODO.complete/06-emf-image-rendering.md +34 -0
- data/TODO.complete/07-auxiliary-tables.md +47 -0
- data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
- data/TODO.complete/11-gml-xsd-generation.md +42 -0
- data/TODO.complete/13-shapescript-interpreter.md +28 -0
- data/TODO.complete/20-cli-diff.md +46 -0
- data/TODO.complete/21-cli-render.md +26 -0
- data/TODO.complete/22-cli-export.md +29 -0
- data/TODO.complete/23-cli-mdg.md +23 -0
- data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
- data/TODO.complete/31-public-send-cleanup.md +61 -0
- data/TODO.complete/32-spec-coverage.md +33 -0
- data/TODO.complete/33-blocked-parity-gaps.md +41 -0
- data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
- data/TODO.complete/37-cli-lint.md +32 -0
- data/TODO.complete/38-cli-query.md +26 -0
- data/TODO.complete/39-cli-info.md +23 -0
- data/TODO.complete/40-ocl-evaluator.md +31 -0
- data/TODO.complete/41-round-trip-spec.md +18 -0
- data/TODO.complete/42-html-diff-report.md +18 -0
- data/TODO.complete/43-json-schema-export.md +20 -0
- data/TODO.complete/44-remaining-qea-tables.md +40 -0
- data/TODO.complete/45-shapescript-extensions.md +25 -0
- data/TODO.complete/46-xsd-consolidation.md +20 -0
- data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
- data/TODO.complete/STATUS.md +109 -0
- data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
- data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
- data/TODO.diagrams/03-text-over-rendering.md +30 -0
- data/TODO.diagrams/04-rect-under-rendering.md +33 -0
- data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
- data/TODO.diagrams/06-group-layering-parity.md +39 -0
- data/TODO.diagrams/07-text-content-fidelity.md +65 -0
- data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
- data/TODO.diagrams/12-connector-labels.md +40 -0
- data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
- data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
- data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
- data/TODO.diagrams/14-center-header-text.md +33 -0
- data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
- data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
- data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
- data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
- data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
- data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
- data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
- data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
- data/TODO.diagrams/18-property-lookup-index.md +42 -0
- data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
- data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
- data/TODO.diagrams/20-split-labels-emitter.md +56 -0
- data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
- data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
- data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
- data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
- data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
- data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
- data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
- data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
- data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
- data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
- data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
- data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
- data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
- data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
- data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
- data/TODO.diagrams/36-instance-specification-model.md +42 -0
- data/TODO.diagrams/37-element-icon-decorations.md +41 -0
- data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
- data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
- data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
- data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
- data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
- data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
- data/TODO.diagrams/44-element-icon-decorations.md +34 -0
- data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
- data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
- data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
- data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
- data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
- data/TODO.diagrams/50-examples-parity.md +85 -0
- data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
- data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
- data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
- data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
- data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
- data/TODO.diagrams/56-package-contents-rendering.md +148 -0
- data/TODO.diagrams/57-instance-specification-model.md +100 -0
- data/TODO.diagrams/58-domain-model-note-text.md +67 -0
- data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
- data/TODO.diagrams/60-testschema-association-marker.md +40 -0
- data/TODO.diagrams/61-legend-block-rendering.md +55 -0
- data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
- data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
- data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
- data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
- data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
- data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
- data/TODO.diagrams/68-inherited-attributes.md +65 -0
- data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
- data/TODO.diagrams/70-mdg-technology-support.md +68 -0
- data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
- data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
- data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
- data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
- data/TODO.diagrams/75-plateau-text-gap.md +39 -0
- data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
- data/TODO.diagrams/77-basic-text-overrender.md +40 -0
- data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
- data/TODO.diagrams/79-architecture-backlog.md +65 -0
- data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
- data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
- data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
- data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
- data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
- data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
- data/TODO.diagrams/86-foreign-package-rule.md +62 -0
- data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
- data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
- data/TODO.diagrams/README.md +69 -0
- data/TODO.diagrams/STATUS.md +73 -0
- data/TODO.fixup/01-default-grouped-paths.md +34 -0
- data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
- data/TODO.fixup/03-diagram-font-inference.md +28 -0
- data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
- data/TODO.fixup/05-marker-registry-ocp.md +32 -0
- data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
- data/TODO.fixup/07-edge-attachment-formula.md +22 -0
- data/TODO.fixup/08-visual-diff-harness.md +28 -0
- data/TODO.fixup/09-extract-element-compartments.md +34 -0
- data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
- data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
- data/TODO.fixup/12-path-style-harmony.md +23 -0
- data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
- data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
- data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
- data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
- data/TODO.fixup/17-path-count-calibration.md +27 -0
- data/TODO.fixup/18-polygon-count-calibration.md +32 -0
- data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
- data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
- data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
- data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
- data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
- data/TODO.fixup/24-note-element-rendering.md +23 -0
- data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
- data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
- data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
- data/TODO.fixup/28-geometry-parser-identification.md +57 -0
- data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
- data/TODO.fixup/30-theme-system-stub.md +46 -0
- data/TODO.fixup/31-theme-value-object-registry.md +17 -0
- data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
- data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
- data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
- data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
- data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
- data/TODO.fixup/37-package-shape-rendering.md +22 -0
- data/TODO.fixup/38-note-element-rendering.md +15 -0
- data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
- data/TODO.fixup/40-connector-dashed-lines.md +15 -0
- data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
- data/TODO.fixup/42-textrenderer-centralization.md +10 -0
- data/TODO.fixup/43-colorresolver-unification.md +24 -0
- data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
- data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
- data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
- data/TODO.fixup/47-canvas-frame-inset.md +19 -0
- data/TODO.fixup/48-background-rect-format.md +15 -0
- data/TODO.fixup/49-all-samples-integration-test.md +17 -0
- data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
- data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
- data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
- data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
- data/TODO.fixup/54-diagram-theme-api.md +50 -0
- data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
- data/TODO.fixup/56-theme-yaml-files.md +65 -0
- data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
- data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
- data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
- data/TODO.fixup/60-cli-theme-option.md +22 -0
- data/TODO.fixup/61-theme-validation.md +28 -0
- data/TODO.fixup/62-theme-builder-dsl.md +31 -0
- data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
- data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
- data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
- data/TODO.fixup/66-styleex-writeback.md +22 -0
- data/TODO.fixup/67-delete-dead-code.md +28 -0
- data/TODO.fixup/68-figure-parity-status.md +82 -0
- data/TODO.fixup/69-package-polygon-rendering.md +54 -0
- data/TODO.fixup/70-tagged-values-compartment.md +39 -0
- data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
- data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
- data/TODO.fixup/73-delete-dead-transformations.md +14 -0
- data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
- data/TODO.fixup/75-visibility-legend-icons.md +23 -0
- data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
- data/TODO.fixup/77-canvas-frame-margins.md +28 -0
- data/TODO.fixup/78-note-element-rendering.md +30 -0
- data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
- data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
- data/TODO.fixup/81-figure-parity-current-state.md +63 -0
- data/config/qea_schema.yml +356 -0
- data/config/themes/119.yml +98 -0
- data/config/themes/default.yml +14 -0
- data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
- data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
- data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
- data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
- data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
- data/examples/exports/UmlModel_template/model.xml +23 -0
- data/examples/exports/basic/UML_EA.DTD +6856 -0
- data/examples/exports/basic/model.xml +8039 -0
- data/examples/exports/simple/UML_EA.DTD +6856 -0
- data/examples/exports/simple/model.xml +585 -0
- data/examples/exports/simple_example/UML_EA.DTD +6856 -0
- data/examples/exports/simple_example/model.xml +23 -0
- data/examples/exports/test/UML_EA.DTD +6856 -0
- data/examples/exports/test/model.xml +1638 -0
- data/examples/qea/basic.qea +0 -0
- data/frontend/README.md +51 -0
- data/frontend/dist/app.iife.js +24 -0
- data/frontend/dist/style.css +1 -0
- data/frontend/index.html +26 -0
- data/frontend/package-lock.json +2359 -0
- data/frontend/package.json +26 -0
- data/frontend/src/App.vue +59 -0
- data/frontend/src/app.ts +8 -0
- data/frontend/src/components/AppHeader.vue +127 -0
- data/frontend/src/components/AppSidebar.vue +119 -0
- data/frontend/src/components/ClassDetails.vue +247 -0
- data/frontend/src/components/DiagramView.vue +79 -0
- data/frontend/src/components/PackageDetails.vue +92 -0
- data/frontend/src/components/PackageTreeNode.vue +64 -0
- data/frontend/src/components/SearchResults.vue +48 -0
- data/frontend/src/components/WelcomeView.vue +87 -0
- data/frontend/src/shims-vue.d.ts +5 -0
- data/frontend/src/stores/dataStore.ts +79 -0
- data/frontend/src/stores/uiStore.ts +167 -0
- data/frontend/src/styles/main.css +1566 -0
- data/frontend/src/types.ts +221 -0
- data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
- data/frontend/tests/e2e/render.spec.ts +188 -0
- data/frontend/tsconfig.json +20 -0
- data/frontend/vite.config.ts +26 -0
- data/frontend/vitest.config.ts +8 -0
- data/lib/ea/cli/app.rb +57 -2
- data/lib/ea/cli/command/diagrams.rb +37 -28
- data/lib/ea/cli/command/diff.rb +46 -0
- data/lib/ea/cli/command/export.rb +80 -0
- data/lib/ea/cli/command/info.rb +75 -0
- data/lib/ea/cli/command/lint.rb +48 -0
- data/lib/ea/cli/command/mdg.rb +98 -0
- data/lib/ea/cli/command/query.rb +34 -0
- data/lib/ea/cli/command/render.rb +135 -0
- data/lib/ea/cli/command/svg.rb +8 -15
- data/lib/ea/cli/command.rb +7 -0
- data/lib/ea/diagram/display_config.rb +184 -0
- data/lib/ea/diagram.rb +4 -41
- data/lib/ea/diff/change.rb +30 -0
- data/lib/ea/diff/comparator.rb +82 -0
- data/lib/ea/diff/html_reporter.rb +91 -0
- data/lib/ea/diff.rb +15 -0
- data/lib/ea/export/json/generator.rb +42 -0
- data/lib/ea/export/json.rb +12 -0
- data/lib/ea/export/json_schema/generator.rb +77 -0
- data/lib/ea/export/json_schema.rb +12 -0
- data/lib/ea/export/plantuml/generator.rb +73 -0
- data/lib/ea/export/plantuml.rb +12 -0
- data/lib/ea/export/xmi/generator.rb +77 -0
- data/lib/ea/export/xmi.rb +11 -0
- data/lib/ea/export/xsd/class_mapping.rb +65 -0
- data/lib/ea/export/xsd/generator.rb +142 -0
- data/lib/ea/export/xsd/namespace_registry.rb +82 -0
- data/lib/ea/export/xsd.rb +19 -0
- data/lib/ea/export.rb +14 -0
- data/lib/ea/image/emf_renderer.rb +42 -0
- data/lib/ea/image.rb +12 -0
- data/lib/ea/lint/engine.rb +30 -0
- data/lib/ea/lint/lint_rule.rb +38 -0
- data/lib/ea/lint/offense.rb +18 -0
- data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
- data/lib/ea/lint/rules/duplicate_name.rb +28 -0
- data/lib/ea/lint/rules/missing_stereotype.rb +35 -0
- data/lib/ea/lint/rules/naming_convention.rb +44 -0
- data/lib/ea/lint/rules/orphan_element.rb +28 -0
- data/lib/ea/lint/rules.rb +14 -0
- data/lib/ea/lint.rb +13 -0
- data/lib/ea/mdg/document.rb +120 -0
- data/lib/ea/mdg/loader.rb +118 -0
- data/lib/ea/mdg/registry.rb +98 -0
- data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
- data/lib/ea/mdg/xml/applies_to.rb +18 -0
- data/lib/ea/mdg/xml/apply.rb +18 -0
- data/lib/ea/mdg/xml/content.rb +18 -0
- data/lib/ea/mdg/xml/documentation.rb +24 -0
- data/lib/ea/mdg/xml/stereotype.rb +28 -0
- data/lib/ea/mdg/xml/stereotypes.rb +18 -0
- data/lib/ea/mdg/xml/tag.rb +28 -0
- data/lib/ea/mdg/xml/tagged_values.rb +18 -0
- data/lib/ea/mdg/xml/technology.rb +28 -0
- data/lib/ea/mdg/xml/uml_profile.rb +22 -0
- data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
- data/lib/ea/mdg/xml.rb +24 -0
- data/lib/ea/mdg.rb +25 -0
- data/lib/ea/model/classifier.rb +4 -0
- data/lib/ea/model/constraint.rb +24 -0
- data/lib/ea/model/diagram.rb +85 -0
- data/lib/ea/model/diagram_connector.rb +34 -0
- data/lib/ea/model/diagram_element.rb +16 -0
- data/lib/ea/model/document.rb +47 -2
- data/lib/ea/model/ghost_label.rb +32 -0
- data/lib/ea/model/instance_specification.rb +34 -0
- data/lib/ea/model/legend.rb +43 -0
- data/lib/ea/model/legend_item.rb +26 -0
- data/lib/ea/model/note.rb +28 -0
- data/lib/ea/model/operation.rb +2 -0
- data/lib/ea/model/property.rb +2 -0
- data/lib/ea/model/relationship.rb +2 -0
- data/lib/ea/model/signal.rb +14 -0
- data/lib/ea/model/slot.rb +19 -0
- data/lib/ea/model.rb +8 -0
- data/lib/ea/ocl/evaluator.rb +94 -0
- data/lib/ea/ocl/nodes.rb +30 -0
- data/lib/ea/ocl/parser.rb +133 -0
- data/lib/ea/ocl/unsupported_error.rb +7 -0
- data/lib/ea/ocl.rb +13 -0
- data/lib/ea/qea/factory/document_builder.rb +24 -10
- data/lib/ea/qea/factory/generalization_builder.rb +9 -11
- data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
- data/lib/ea/qea/models/ea_author.rb +35 -0
- data/lib/ea/qea/models/ea_glossary.rb +34 -0
- data/lib/ea/qea/models/ea_image.rb +53 -0
- data/lib/ea/qea/models/ea_implement.rb +32 -0
- data/lib/ea/qea/models/ea_list.rb +42 -0
- data/lib/ea/qea/models/ea_object_effort.rb +34 -0
- data/lib/ea/qea/models/ea_object_problem.rb +37 -0
- data/lib/ea/qea/models/ea_object_require.rb +34 -0
- data/lib/ea/qea/models/ea_object_resource.rb +34 -0
- data/lib/ea/qea/models/ea_object_risk.rb +34 -0
- data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
- data/lib/ea/qea/models/ea_object_test.rb +35 -0
- data/lib/ea/qea/models/ea_object_trx.rb +34 -0
- data/lib/ea/qea/models/ea_operation.rb +7 -0
- data/lib/ea/qea/models/ea_palette.rb +30 -0
- data/lib/ea/qea/models/ea_palette_item.rb +36 -0
- data/lib/ea/qea/models/ea_phase.rb +40 -0
- data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
- data/lib/ea/qea/models/ea_secrypt.rb +34 -0
- data/lib/ea/qea/models/ea_version.rb +39 -0
- data/lib/ea/qea/models/ea_xref.rb +11 -1
- data/lib/ea/qea/models.rb +19 -0
- data/lib/ea/qea/services/database_loader.rb +22 -1
- data/lib/ea/query/builder.rb +108 -0
- data/lib/ea/query.rb +9 -0
- data/lib/ea/render/image_converter.rb +101 -0
- data/lib/ea/render.rb +10 -0
- data/lib/ea/shapescript/parser.rb +208 -0
- data/lib/ea/shapescript/renderer.rb +74 -0
- data/lib/ea/shapescript/shape.rb +34 -0
- data/lib/ea/shapescript.rb +24 -0
- data/lib/ea/sources/qea/adapter.rb +22 -5
- data/lib/ea/sources/qea/classifier_builder.rb +184 -7
- data/lib/ea/sources/qea/diagram_builder.rb +352 -24
- data/lib/ea/sources/qea/id_normalizer.rb +16 -1
- data/lib/ea/sources/qea/instance_builder.rb +113 -0
- data/lib/ea/sources/qea/legend_builder.rb +137 -0
- data/lib/ea/sources/qea/note_builder.rb +58 -0
- data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
- data/lib/ea/sources/qea/operation_builder.rb +1 -0
- data/lib/ea/sources/qea/package_builder.rb +16 -0
- data/lib/ea/sources/qea/relationship_builder.rb +21 -5
- data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
- data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
- data/lib/ea/sources/qea/xref/parser.rb +150 -0
- data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
- data/lib/ea/sources/qea/xref/record.rb +41 -0
- data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
- data/lib/ea/sources/qea/xref.rb +27 -0
- data/lib/ea/sources/qea.rb +4 -0
- data/lib/ea/sources/xmi/adapter.rb +80 -2
- data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
- data/lib/ea/sources/xmi/diagram_builder.rb +95 -18
- data/lib/ea/sources/xmi/extension_geometry_parser.rb +19 -2
- data/lib/ea/sources/xmi/extension_style_parser.rb +15 -2
- data/lib/ea/sources/xmi/note_builder.rb +46 -0
- data/lib/ea/sources/xmi/property_builder.rb +9 -0
- data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
- data/lib/ea/sources/xmi/tag_builder.rb +45 -0
- data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
- data/lib/ea/sources/xmi.rb +4 -0
- data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
- data/lib/ea/spa/output/single_file_strategy.rb +8 -2
- data/lib/ea/spa/output/strategy.rb +34 -0
- data/lib/ea/svg/connector_router.rb +134 -0
- data/lib/ea/svg/ea_emitter/background.rb +2 -3
- data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
- data/lib/ea/svg/ea_emitter/canvas.rb +56 -33
- data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
- data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
- data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
- data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
- data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
- data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
- data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
- data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
- data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
- data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
- data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
- data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
- data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
- data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
- data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
- data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
- data/lib/ea/svg/ea_emitter/connectors.rb +46 -12
- data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
- data/lib/ea/svg/ea_emitter/document.rb +15 -24
- data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
- data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
- data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
- data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
- data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
- data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
- data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
- data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
- data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
- data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
- data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
- data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
- data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
- data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
- data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
- data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
- data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
- data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
- data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
- data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
- data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
- data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
- data/lib/ea/svg/ea_emitter/element.rb +37 -0
- data/lib/ea/svg/ea_emitter/elements.rb +283 -95
- data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
- data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
- data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
- data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
- data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
- data/lib/ea/svg/ea_emitter/label.rb +23 -0
- data/lib/ea/svg/ea_emitter/labels.rb +93 -27
- data/lib/ea/svg/ea_emitter/layer.rb +20 -0
- data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
- data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
- data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
- data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
- data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
- data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
- data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
- data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
- data/lib/ea/svg/ea_emitter/marker.rb +37 -0
- data/lib/ea/svg/ea_emitter/markers.rb +351 -64
- data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
- data/lib/ea/svg/ea_emitter/style.rb +15 -0
- data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
- data/lib/ea/svg/ea_emitter.rb +33 -11
- data/lib/ea/svg/parity/checker.rb +105 -0
- data/lib/ea/svg/parity/source.rb +59 -0
- data/lib/ea/svg/parity/suite.rb +113 -0
- data/lib/ea/svg/parity.rb +14 -0
- data/lib/ea/svg.rb +2 -15
- data/lib/ea/theme/definition.rb +176 -0
- data/lib/ea/theme/loader.rb +125 -0
- data/lib/ea/theme/registry.rb +96 -0
- data/lib/ea/theme.rb +37 -0
- data/lib/ea/transformations.rb +5 -88
- data/lib/ea/version.rb +4 -1
- data/lib/ea.rb +14 -4
- data/lib/tasks/svg_bench.rake +87 -0
- data/lutaml-uml-0.5.1.gem +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
- metadata +449 -26
- data/lib/ea/diagram/configuration.rb +0 -379
- data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
- data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
- data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
- data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
- data/lib/ea/diagram/element_renderers.rb +0 -43
- data/lib/ea/diagram/extractor.rb +0 -566
- data/lib/ea/diagram/layout_engine.rb +0 -170
- data/lib/ea/diagram/path_builder.rb +0 -202
- data/lib/ea/diagram/style_parser.rb +0 -42
- data/lib/ea/diagram/style_resolver.rb +0 -291
- data/lib/ea/diagram/svg_renderer.rb +0 -274
- data/lib/ea/diagram/util.rb +0 -73
- data/lib/ea/svg/bounds_calculator.rb +0 -74
- data/lib/ea/svg/connector_path.rb +0 -138
- data/lib/ea/svg/element_box.rb +0 -256
- data/lib/ea/svg/renderer.rb +0 -77
- data/lib/ea/svg/style_resolver.rb +0 -72
- data/lib/ea/transformations/configuration.rb +0 -333
- data/lib/ea/transformations/format_registry.rb +0 -366
- data/lib/ea/transformations/parsers/base_parser.rb +0 -482
- data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
- data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
- 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
|
+
```
|