@transitrix/diagrams 1.0.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.
- package/LICENSE +21 -0
- package/README.md +47 -0
- package/dist/__tests__/edge-path.test.d.ts +1 -0
- package/dist/__tests__/edge-path.test.js +39 -0
- package/dist/__tests__/scope.test.d.ts +1 -0
- package/dist/__tests__/scope.test.js +23 -0
- package/dist/__tests__/yaml-normalize.test.d.ts +1 -0
- package/dist/__tests__/yaml-normalize.test.js +148 -0
- package/dist/activities/__tests__/cpm.test.d.ts +1 -0
- package/dist/activities/__tests__/cpm.test.js +146 -0
- package/dist/activities/__tests__/gantt.test.d.ts +1 -0
- package/dist/activities/__tests__/gantt.test.js +224 -0
- package/dist/activities/__tests__/layout.test.d.ts +1 -0
- package/dist/activities/__tests__/layout.test.js +98 -0
- package/dist/activities/__tests__/validate.test.d.ts +1 -0
- package/dist/activities/__tests__/validate.test.js +363 -0
- package/dist/activities/cpm.d.ts +2 -0
- package/dist/activities/cpm.js +86 -0
- package/dist/activities/gantt.d.ts +6 -0
- package/dist/activities/gantt.js +250 -0
- package/dist/activities/index.d.ts +5 -0
- package/dist/activities/index.js +4 -0
- package/dist/activities/layout.d.ts +2 -0
- package/dist/activities/layout.js +103 -0
- package/dist/activities/types.d.ts +125 -0
- package/dist/activities/types.js +1 -0
- package/dist/activities/validate.d.ts +2 -0
- package/dist/activities/validate.js +326 -0
- package/dist/activity-card/__tests__/example.test.d.ts +1 -0
- package/dist/activity-card/__tests__/example.test.js +56 -0
- package/dist/activity-card/__tests__/layout.test.d.ts +1 -0
- package/dist/activity-card/__tests__/layout.test.js +57 -0
- package/dist/activity-card/__tests__/resolver.test.d.ts +1 -0
- package/dist/activity-card/__tests__/resolver.test.js +146 -0
- package/dist/activity-card/__tests__/validate.test.d.ts +1 -0
- package/dist/activity-card/__tests__/validate.test.js +116 -0
- package/dist/activity-card/index.d.ts +5 -0
- package/dist/activity-card/index.js +3 -0
- package/dist/activity-card/layout.d.ts +7 -0
- package/dist/activity-card/layout.js +167 -0
- package/dist/activity-card/resolver.d.ts +7 -0
- package/dist/activity-card/resolver.js +310 -0
- package/dist/activity-card/types.d.ts +175 -0
- package/dist/activity-card/types.js +20 -0
- package/dist/activity-card/validate.d.ts +3 -0
- package/dist/activity-card/validate.js +145 -0
- package/dist/actor/__tests__/validate.test.d.ts +1 -0
- package/dist/actor/__tests__/validate.test.js +57 -0
- package/dist/actor/index.d.ts +3 -0
- package/dist/actor/index.js +2 -0
- package/dist/actor/types.d.ts +20 -0
- package/dist/actor/types.js +4 -0
- package/dist/actor/validate.d.ts +2 -0
- package/dist/actor/validate.js +34 -0
- package/dist/applications/__tests__/validate.test.d.ts +1 -0
- package/dist/applications/__tests__/validate.test.js +223 -0
- package/dist/applications/index.d.ts +2 -0
- package/dist/applications/index.js +1 -0
- package/dist/applications/types.d.ts +39 -0
- package/dist/applications/types.js +1 -0
- package/dist/applications/validate.d.ts +3 -0
- package/dist/applications/validate.js +109 -0
- package/dist/assertion/__tests__/example.test.d.ts +1 -0
- package/dist/assertion/__tests__/example.test.js +32 -0
- package/dist/assertion/__tests__/validate.test.d.ts +1 -0
- package/dist/assertion/__tests__/validate.test.js +130 -0
- package/dist/assertion/index.d.ts +4 -0
- package/dist/assertion/index.js +2 -0
- package/dist/assertion/types.d.ts +43 -0
- package/dist/assertion/types.js +7 -0
- package/dist/assertion/validate.d.ts +9 -0
- package/dist/assertion/validate.js +137 -0
- package/dist/blocks/__tests__/layout.test.d.ts +1 -0
- package/dist/blocks/__tests__/layout.test.js +153 -0
- package/dist/blocks/__tests__/validate.test.d.ts +1 -0
- package/dist/blocks/__tests__/validate.test.js +235 -0
- package/dist/blocks/index.d.ts +4 -0
- package/dist/blocks/index.js +2 -0
- package/dist/blocks/layout.d.ts +4 -0
- package/dist/blocks/layout.js +145 -0
- package/dist/blocks/types.d.ts +56 -0
- package/dist/blocks/types.js +1 -0
- package/dist/blocks/validate.d.ts +9 -0
- package/dist/blocks/validate.js +186 -0
- package/dist/capability-map/__tests__/validate.test.d.ts +1 -0
- package/dist/capability-map/__tests__/validate.test.js +212 -0
- package/dist/capability-map/index.d.ts +2 -0
- package/dist/capability-map/index.js +1 -0
- package/dist/capability-map/types.d.ts +26 -0
- package/dist/capability-map/types.js +1 -0
- package/dist/capability-map/validate.d.ts +3 -0
- package/dist/capability-map/validate.js +103 -0
- package/dist/change/__tests__/validate.test.d.ts +1 -0
- package/dist/change/__tests__/validate.test.js +73 -0
- package/dist/change/index.d.ts +2 -0
- package/dist/change/index.js +1 -0
- package/dist/change/types.d.ts +17 -0
- package/dist/change/types.js +3 -0
- package/dist/change/validate.d.ts +2 -0
- package/dist/change/validate.js +57 -0
- package/dist/compliance/__tests__/classify.test.d.ts +1 -0
- package/dist/compliance/__tests__/classify.test.js +24 -0
- package/dist/compliance/__tests__/confidence.test.d.ts +1 -0
- package/dist/compliance/__tests__/confidence.test.js +78 -0
- package/dist/compliance/__tests__/coverage-metric.test.d.ts +1 -0
- package/dist/compliance/__tests__/coverage-metric.test.js +164 -0
- package/dist/compliance/__tests__/demo-scenario.test.d.ts +1 -0
- package/dist/compliance/__tests__/demo-scenario.test.js +226 -0
- package/dist/compliance/__tests__/example.test.d.ts +1 -0
- package/dist/compliance/__tests__/example.test.js +51 -0
- package/dist/compliance/__tests__/gap-report.test.d.ts +1 -0
- package/dist/compliance/__tests__/gap-report.test.js +113 -0
- package/dist/compliance/__tests__/html.test.d.ts +1 -0
- package/dist/compliance/__tests__/html.test.js +122 -0
- package/dist/compliance/__tests__/impact.test.d.ts +1 -0
- package/dist/compliance/__tests__/impact.test.js +410 -0
- package/dist/compliance/__tests__/markdown.test.d.ts +1 -0
- package/dist/compliance/__tests__/markdown.test.js +85 -0
- package/dist/compliance/__tests__/views.test.d.ts +1 -0
- package/dist/compliance/__tests__/views.test.js +59 -0
- package/dist/compliance/classify.d.ts +27 -0
- package/dist/compliance/classify.js +60 -0
- package/dist/compliance/confidence.d.ts +27 -0
- package/dist/compliance/confidence.js +43 -0
- package/dist/compliance/coverage-metric.d.ts +74 -0
- package/dist/compliance/coverage-metric.js +181 -0
- package/dist/compliance/gap-report.d.ts +20 -0
- package/dist/compliance/gap-report.js +64 -0
- package/dist/compliance/html.d.ts +22 -0
- package/dist/compliance/html.js +256 -0
- package/dist/compliance/impact.d.ts +251 -0
- package/dist/compliance/impact.js +464 -0
- package/dist/compliance/index.d.ts +16 -0
- package/dist/compliance/index.js +9 -0
- package/dist/compliance/markdown.d.ts +18 -0
- package/dist/compliance/markdown.js +129 -0
- package/dist/compliance/reverse-index.d.ts +8 -0
- package/dist/compliance/reverse-index.js +30 -0
- package/dist/compliance/types.d.ts +98 -0
- package/dist/compliance/types.js +5 -0
- package/dist/compliance/views.d.ts +14 -0
- package/dist/compliance/views.js +35 -0
- package/dist/compliance-matrix/__tests__/build.test.d.ts +1 -0
- package/dist/compliance-matrix/__tests__/build.test.js +183 -0
- package/dist/compliance-matrix/__tests__/example.test.d.ts +1 -0
- package/dist/compliance-matrix/__tests__/example.test.js +49 -0
- package/dist/compliance-matrix/build.d.ts +18 -0
- package/dist/compliance-matrix/build.js +0 -0
- package/dist/compliance-matrix/index.d.ts +2 -0
- package/dist/compliance-matrix/index.js +1 -0
- package/dist/compliance-matrix/types.d.ts +86 -0
- package/dist/compliance-matrix/types.js +8 -0
- package/dist/confidence/__tests__/score.test.d.ts +1 -0
- package/dist/confidence/__tests__/score.test.js +188 -0
- package/dist/confidence/index.d.ts +2 -0
- package/dist/confidence/index.js +1 -0
- package/dist/confidence/score.d.ts +62 -0
- package/dist/confidence/score.js +215 -0
- package/dist/confidence/types.d.ts +79 -0
- package/dist/confidence/types.js +6 -0
- package/dist/edge-path.d.ts +18 -0
- package/dist/edge-path.js +35 -0
- package/dist/element-envelope.d.ts +15 -0
- package/dist/element-envelope.js +55 -0
- package/dist/factor/__tests__/validate.test.d.ts +1 -0
- package/dist/factor/__tests__/validate.test.js +83 -0
- package/dist/factor/index.d.ts +3 -0
- package/dist/factor/index.js +2 -0
- package/dist/factor/types.d.ts +23 -0
- package/dist/factor/types.js +6 -0
- package/dist/factor/validate.d.ts +2 -0
- package/dist/factor/validate.js +69 -0
- package/dist/fgca/__tests__/chain-table.test.d.ts +1 -0
- package/dist/fgca/__tests__/chain-table.test.js +158 -0
- package/dist/fgca/__tests__/layout.test.d.ts +1 -0
- package/dist/fgca/__tests__/layout.test.js +140 -0
- package/dist/fgca/__tests__/parse-canonical.test.d.ts +1 -0
- package/dist/fgca/__tests__/parse-canonical.test.js +224 -0
- package/dist/fgca/__tests__/preview-layout.test.d.ts +1 -0
- package/dist/fgca/__tests__/preview-layout.test.js +106 -0
- package/dist/fgca/__tests__/validate.test.d.ts +1 -0
- package/dist/fgca/__tests__/validate.test.js +125 -0
- package/dist/fgca/chain-table.d.ts +36 -0
- package/dist/fgca/chain-table.js +177 -0
- package/dist/fgca/index.d.ts +16 -0
- package/dist/fgca/index.js +11 -0
- package/dist/fgca/layout.d.ts +27 -0
- package/dist/fgca/layout.js +156 -0
- package/dist/fgca/nodeTypes.d.ts +6 -0
- package/dist/fgca/nodeTypes.js +10 -0
- package/dist/fgca/nodes/FGCAActivityNode.d.ts +13 -0
- package/dist/fgca/nodes/FGCAActivityNode.js +35 -0
- package/dist/fgca/nodes/FGCAChangeNode.d.ts +12 -0
- package/dist/fgca/nodes/FGCAChangeNode.js +35 -0
- package/dist/fgca/nodes/FGCAFactorNode.d.ts +12 -0
- package/dist/fgca/nodes/FGCAFactorNode.js +35 -0
- package/dist/fgca/nodes/FGCAGoalNode.d.ts +14 -0
- package/dist/fgca/nodes/FGCAGoalNode.js +40 -0
- package/dist/fgca/parse-canonical.d.ts +58 -0
- package/dist/fgca/parse-canonical.js +339 -0
- package/dist/fgca/preview-layout.d.ts +87 -0
- package/dist/fgca/preview-layout.js +122 -0
- package/dist/fgca/types.d.ts +39 -0
- package/dist/fgca/types.js +7 -0
- package/dist/fgca/validate.d.ts +14 -0
- package/dist/fgca/validate.js +108 -0
- package/dist/geometry.d.ts +7 -0
- package/dist/geometry.js +2 -0
- package/dist/goals/__tests__/layout.test.d.ts +1 -0
- package/dist/goals/__tests__/layout.test.js +153 -0
- package/dist/goals/__tests__/mutations.test.d.ts +1 -0
- package/dist/goals/__tests__/mutations.test.js +95 -0
- package/dist/goals/__tests__/parse-canonical.test.d.ts +1 -0
- package/dist/goals/__tests__/parse-canonical.test.js +129 -0
- package/dist/goals/__tests__/validate.test.d.ts +1 -0
- package/dist/goals/__tests__/validate.test.js +183 -0
- package/dist/goals/index.d.ts +6 -0
- package/dist/goals/index.js +4 -0
- package/dist/goals/layout.d.ts +11 -0
- package/dist/goals/layout.js +147 -0
- package/dist/goals/mutations.d.ts +6 -0
- package/dist/goals/mutations.js +116 -0
- package/dist/goals/parse-canonical.d.ts +29 -0
- package/dist/goals/parse-canonical.js +257 -0
- package/dist/goals/types.d.ts +71 -0
- package/dist/goals/types.js +1 -0
- package/dist/goals/validate.d.ts +2 -0
- package/dist/goals/validate.js +122 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +23 -0
- package/dist/issues/__tests__/layout.test.d.ts +1 -0
- package/dist/issues/__tests__/layout.test.js +62 -0
- package/dist/issues/__tests__/validate.test.d.ts +1 -0
- package/dist/issues/__tests__/validate.test.js +82 -0
- package/dist/issues/index.d.ts +4 -0
- package/dist/issues/index.js +2 -0
- package/dist/issues/layout.d.ts +10 -0
- package/dist/issues/layout.js +82 -0
- package/dist/issues/types.d.ts +61 -0
- package/dist/issues/types.js +6 -0
- package/dist/issues/validate.d.ts +3 -0
- package/dist/issues/validate.js +143 -0
- package/dist/process-blueprint/__tests__/compliance-lane.test.d.ts +1 -0
- package/dist/process-blueprint/__tests__/compliance-lane.test.js +272 -0
- package/dist/process-blueprint/__tests__/layout.test.d.ts +1 -0
- package/dist/process-blueprint/__tests__/layout.test.js +159 -0
- package/dist/process-blueprint/__tests__/validate.test.d.ts +1 -0
- package/dist/process-blueprint/__tests__/validate.test.js +280 -0
- package/dist/process-blueprint/index.d.ts +4 -0
- package/dist/process-blueprint/index.js +2 -0
- package/dist/process-blueprint/layout.d.ts +2 -0
- package/dist/process-blueprint/layout.js +416 -0
- package/dist/process-blueprint/types.d.ts +220 -0
- package/dist/process-blueprint/types.js +1 -0
- package/dist/process-blueprint/validate.d.ts +3 -0
- package/dist/process-blueprint/validate.js +165 -0
- package/dist/process-map/__tests__/validate.test.d.ts +1 -0
- package/dist/process-map/__tests__/validate.test.js +199 -0
- package/dist/process-map/index.d.ts +2 -0
- package/dist/process-map/index.js +1 -0
- package/dist/process-map/types.d.ts +32 -0
- package/dist/process-map/types.js +1 -0
- package/dist/process-map/validate.d.ts +3 -0
- package/dist/process-map/validate.js +115 -0
- package/dist/products/__tests__/validate.test.d.ts +1 -0
- package/dist/products/__tests__/validate.test.js +210 -0
- package/dist/products/index.d.ts +2 -0
- package/dist/products/index.js +1 -0
- package/dist/products/types.d.ts +28 -0
- package/dist/products/types.js +1 -0
- package/dist/products/validate.d.ts +3 -0
- package/dist/products/validate.js +93 -0
- package/dist/repo-validate/__tests__/validate-repo.test.d.ts +1 -0
- package/dist/repo-validate/__tests__/validate-repo.test.js +132 -0
- package/dist/repo-validate/index.d.ts +2 -0
- package/dist/repo-validate/index.js +1 -0
- package/dist/repo-validate/types.d.ts +34 -0
- package/dist/repo-validate/types.js +14 -0
- package/dist/repo-validate/validate-repo.d.ts +8 -0
- package/dist/repo-validate/validate-repo.js +189 -0
- package/dist/requirement/__tests__/example.test.d.ts +1 -0
- package/dist/requirement/__tests__/example.test.js +21 -0
- package/dist/requirement/__tests__/validate.test.d.ts +1 -0
- package/dist/requirement/__tests__/validate.test.js +80 -0
- package/dist/requirement/index.d.ts +4 -0
- package/dist/requirement/index.js +2 -0
- package/dist/requirement/types.d.ts +25 -0
- package/dist/requirement/types.js +4 -0
- package/dist/requirement/validate.d.ts +7 -0
- package/dist/requirement/validate.js +81 -0
- package/dist/scenarios/__tests__/validate.test.d.ts +1 -0
- package/dist/scenarios/__tests__/validate.test.js +183 -0
- package/dist/scenarios/index.d.ts +2 -0
- package/dist/scenarios/index.js +1 -0
- package/dist/scenarios/types.d.ts +45 -0
- package/dist/scenarios/types.js +1 -0
- package/dist/scenarios/validate.d.ts +3 -0
- package/dist/scenarios/validate.js +110 -0
- package/dist/schema-version.d.ts +16 -0
- package/dist/schema-version.js +16 -0
- package/dist/scope.d.ts +23 -0
- package/dist/scope.js +38 -0
- package/dist/stakeholder/__tests__/validate.test.d.ts +1 -0
- package/dist/stakeholder/__tests__/validate.test.js +86 -0
- package/dist/stakeholder/index.d.ts +3 -0
- package/dist/stakeholder/index.js +2 -0
- package/dist/stakeholder/types.d.ts +24 -0
- package/dist/stakeholder/types.js +5 -0
- package/dist/stakeholder/validate.d.ts +2 -0
- package/dist/stakeholder/validate.js +58 -0
- package/dist/target-state/__tests__/validate.test.d.ts +1 -0
- package/dist/target-state/__tests__/validate.test.js +62 -0
- package/dist/target-state/index.d.ts +2 -0
- package/dist/target-state/index.js +1 -0
- package/dist/target-state/types.d.ts +18 -0
- package/dist/target-state/types.js +7 -0
- package/dist/target-state/validate.d.ts +2 -0
- package/dist/target-state/validate.js +61 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.js +2 -0
- package/dist/theme/themes.d.ts +16 -0
- package/dist/theme/themes.js +213 -0
- package/dist/theme/tokens.d.ts +158 -0
- package/dist/theme/tokens.js +105 -0
- package/dist/typed-id.d.ts +20 -0
- package/dist/typed-id.js +38 -0
- package/dist/validation-types.d.ts +34 -0
- package/dist/validation-types.js +1 -0
- package/dist/webview/__tests__/entry-notations.test.d.ts +1 -0
- package/dist/webview/__tests__/entry-notations.test.js +62 -0
- package/dist/webview/__tests__/entry.test.d.ts +1 -0
- package/dist/webview/__tests__/entry.test.js +56 -0
- package/dist/webview/__tests__/render-goals.test.d.ts +1 -0
- package/dist/webview/__tests__/render-goals.test.js +65 -0
- package/dist/webview/entry.d.ts +38 -0
- package/dist/webview/entry.js +182 -0
- package/dist/webview/render-activities.d.ts +24 -0
- package/dist/webview/render-activities.js +127 -0
- package/dist/webview/render-activity-card.d.ts +5 -0
- package/dist/webview/render-activity-card.js +168 -0
- package/dist/webview/render-applications.d.ts +11 -0
- package/dist/webview/render-applications.js +105 -0
- package/dist/webview/render-blocks.d.ts +5 -0
- package/dist/webview/render-blocks.js +71 -0
- package/dist/webview/render-capability-map.d.ts +7 -0
- package/dist/webview/render-capability-map.js +88 -0
- package/dist/webview/render-fgca.d.ts +8 -0
- package/dist/webview/render-fgca.js +94 -0
- package/dist/webview/render-goals.d.ts +6 -0
- package/dist/webview/render-goals.js +92 -0
- package/dist/webview/render-process-blueprint.d.ts +5 -0
- package/dist/webview/render-process-blueprint.js +135 -0
- package/dist/webview/render-process-map.d.ts +7 -0
- package/dist/webview/render-process-map.js +82 -0
- package/dist/webview/render-products.d.ts +7 -0
- package/dist/webview/render-products.js +81 -0
- package/dist/webview/render-scenarios.d.ts +7 -0
- package/dist/webview/render-scenarios.js +75 -0
- package/dist/webview/render-util.d.ts +16 -0
- package/dist/webview/render-util.js +31 -0
- package/dist/webview/transitrix-render.css +323 -0
- package/dist/webview/transitrix-render.js +6452 -0
- package/dist/webview/transitrix-render.js.map +7 -0
- package/dist/yaml-normalize.d.ts +20 -0
- package/dist/yaml-normalize.js +57 -0
- package/package.json +40 -0
- package/src/__tests__/edge-path.test.ts +46 -0
- package/src/__tests__/scope.test.ts +27 -0
- package/src/__tests__/yaml-normalize.test.ts +158 -0
- package/src/activities/__tests__/cpm.test.ts +164 -0
- package/src/activities/__tests__/gantt.test.ts +245 -0
- package/src/activities/__tests__/layout.test.ts +112 -0
- package/src/activities/__tests__/validate.test.ts +409 -0
- package/src/activities/cpm.ts +95 -0
- package/src/activities/gantt.ts +276 -0
- package/src/activities/index.ts +28 -0
- package/src/activities/layout.ts +112 -0
- package/src/activities/types.ts +148 -0
- package/src/activities/validate.ts +357 -0
- package/src/activity-card/__tests__/example.test.ts +66 -0
- package/src/activity-card/__tests__/layout.test.ts +63 -0
- package/src/activity-card/__tests__/resolver.test.ts +161 -0
- package/src/activity-card/__tests__/validate.test.ts +131 -0
- package/src/activity-card/index.ts +32 -0
- package/src/activity-card/layout.ts +194 -0
- package/src/activity-card/resolver.ts +337 -0
- package/src/activity-card/types.ts +237 -0
- package/src/activity-card/validate.ts +158 -0
- package/src/actor/__tests__/validate.test.ts +67 -0
- package/src/actor/index.ts +3 -0
- package/src/actor/types.ts +29 -0
- package/src/actor/validate.ts +38 -0
- package/src/applications/__tests__/validate.test.ts +256 -0
- package/src/applications/index.ts +11 -0
- package/src/applications/types.ts +43 -0
- package/src/applications/validate.ts +131 -0
- package/src/assertion/__tests__/example.test.ts +37 -0
- package/src/assertion/__tests__/validate.test.ts +142 -0
- package/src/assertion/index.ts +12 -0
- package/src/assertion/types.ts +58 -0
- package/src/assertion/validate.ts +145 -0
- package/src/blocks/__tests__/layout.test.ts +169 -0
- package/src/blocks/__tests__/validate.test.ts +260 -0
- package/src/blocks/index.ts +17 -0
- package/src/blocks/layout.ts +186 -0
- package/src/blocks/types.ts +62 -0
- package/src/blocks/validate.ts +206 -0
- package/src/capability-map/__tests__/validate.test.ts +238 -0
- package/src/capability-map/index.ts +8 -0
- package/src/capability-map/types.ts +29 -0
- package/src/capability-map/validate.ts +127 -0
- package/src/change/__tests__/validate.test.ts +88 -0
- package/src/change/index.ts +2 -0
- package/src/change/types.ts +23 -0
- package/src/change/validate.ts +61 -0
- package/src/compliance/__tests__/classify.test.ts +27 -0
- package/src/compliance/__tests__/confidence.test.ts +98 -0
- package/src/compliance/__tests__/coverage-metric.test.ts +188 -0
- package/src/compliance/__tests__/demo-scenario.test.ts +273 -0
- package/src/compliance/__tests__/example.test.ts +57 -0
- package/src/compliance/__tests__/gap-report.test.ts +129 -0
- package/src/compliance/__tests__/html.test.ts +142 -0
- package/src/compliance/__tests__/impact.test.ts +482 -0
- package/src/compliance/__tests__/markdown.test.ts +95 -0
- package/src/compliance/__tests__/views.test.ts +64 -0
- package/src/compliance/classify.ts +84 -0
- package/src/compliance/confidence.ts +69 -0
- package/src/compliance/coverage-metric.ts +263 -0
- package/src/compliance/gap-report.ts +94 -0
- package/src/compliance/html.ts +295 -0
- package/src/compliance/impact.ts +677 -0
- package/src/compliance/index.ts +56 -0
- package/src/compliance/markdown.ts +135 -0
- package/src/compliance/reverse-index.ts +33 -0
- package/src/compliance/types.ts +120 -0
- package/src/compliance/views.ts +46 -0
- package/src/compliance-matrix/__tests__/build.test.ts +200 -0
- package/src/compliance-matrix/__tests__/example.test.ts +57 -0
- package/src/compliance-matrix/build.ts +0 -0
- package/src/compliance-matrix/index.ts +11 -0
- package/src/compliance-matrix/types.ts +102 -0
- package/src/confidence/__tests__/score.test.ts +254 -0
- package/src/confidence/index.ts +21 -0
- package/src/confidence/score.ts +243 -0
- package/src/confidence/types.ts +96 -0
- package/src/edge-path.ts +44 -0
- package/src/element-envelope.ts +76 -0
- package/src/factor/__tests__/validate.test.ts +98 -0
- package/src/factor/index.ts +8 -0
- package/src/factor/types.ts +41 -0
- package/src/factor/validate.ts +74 -0
- package/src/fgca/__tests__/chain-table.test.ts +172 -0
- package/src/fgca/__tests__/layout.test.ts +179 -0
- package/src/fgca/__tests__/parse-canonical.test.ts +248 -0
- package/src/fgca/__tests__/preview-layout.test.ts +124 -0
- package/src/fgca/__tests__/validate.test.ts +142 -0
- package/src/fgca/chain-table.ts +225 -0
- package/src/fgca/index.ts +45 -0
- package/src/fgca/layout.ts +204 -0
- package/src/fgca/nodeTypes.ts +11 -0
- package/src/fgca/nodes/FGCAActivityNode.tsx +65 -0
- package/src/fgca/nodes/FGCAChangeNode.tsx +64 -0
- package/src/fgca/nodes/FGCAFactorNode.tsx +64 -0
- package/src/fgca/nodes/FGCAGoalNode.tsx +72 -0
- package/src/fgca/parse-canonical.ts +400 -0
- package/src/fgca/preview-layout.ts +217 -0
- package/src/fgca/types.ts +50 -0
- package/src/fgca/validate.ts +126 -0
- package/src/geometry.ts +9 -0
- package/src/goals/__tests__/layout.test.ts +175 -0
- package/src/goals/__tests__/mutations.test.ts +111 -0
- package/src/goals/__tests__/parse-canonical.test.ts +145 -0
- package/src/goals/__tests__/validate.test.ts +202 -0
- package/src/goals/index.ts +21 -0
- package/src/goals/layout.ts +172 -0
- package/src/goals/mutations.ts +123 -0
- package/src/goals/parse-canonical.ts +286 -0
- package/src/goals/types.ts +85 -0
- package/src/goals/validate.ts +136 -0
- package/src/index.ts +23 -0
- package/src/process-blueprint/__tests__/compliance-lane.test.ts +320 -0
- package/src/process-blueprint/__tests__/layout.test.ts +195 -0
- package/src/process-blueprint/__tests__/validate.test.ts +310 -0
- package/src/process-blueprint/index.ts +31 -0
- package/src/process-blueprint/layout.ts +531 -0
- package/src/process-blueprint/types.ts +242 -0
- package/src/process-blueprint/validate.ts +181 -0
- package/src/process-map/__tests__/validate.test.ts +223 -0
- package/src/process-map/index.ts +10 -0
- package/src/process-map/types.ts +36 -0
- package/src/process-map/validate.ts +135 -0
- package/src/products/__tests__/validate.test.ts +239 -0
- package/src/products/index.ts +9 -0
- package/src/products/types.ts +31 -0
- package/src/products/validate.ts +112 -0
- package/src/repo-validate/__tests__/validate-repo.test.ts +149 -0
- package/src/repo-validate/index.ts +2 -0
- package/src/repo-validate/types.ts +50 -0
- package/src/repo-validate/validate-repo.ts +196 -0
- package/src/requirement/__tests__/example.test.ts +24 -0
- package/src/requirement/__tests__/validate.test.ts +96 -0
- package/src/requirement/index.ts +4 -0
- package/src/requirement/types.ts +35 -0
- package/src/requirement/validate.ts +92 -0
- package/src/scenarios/__tests__/validate.test.ts +209 -0
- package/src/scenarios/index.ts +15 -0
- package/src/scenarios/types.ts +37 -0
- package/src/scenarios/validate.ts +122 -0
- package/src/schema-version.ts +16 -0
- package/src/scope.ts +46 -0
- package/src/stakeholder/__tests__/validate.test.ts +101 -0
- package/src/stakeholder/index.ts +3 -0
- package/src/stakeholder/types.ts +33 -0
- package/src/stakeholder/validate.ts +63 -0
- package/src/target-state/__tests__/validate.test.ts +74 -0
- package/src/target-state/index.ts +2 -0
- package/src/target-state/types.ts +28 -0
- package/src/target-state/validate.ts +67 -0
- package/src/theme/index.ts +4 -0
- package/src/theme/themes.ts +237 -0
- package/src/theme/tokens.ts +133 -0
- package/src/typed-id.ts +56 -0
- package/src/validation-types.ts +36 -0
- package/src/webview/__tests__/entry-notations.test.ts +77 -0
- package/src/webview/__tests__/entry.test.ts +64 -0
- package/src/webview/__tests__/render-goals.test.ts +72 -0
- package/src/webview/entry.ts +292 -0
- package/src/webview/render-activities.ts +156 -0
- package/src/webview/render-activity-card.ts +234 -0
- package/src/webview/render-applications.ts +123 -0
- package/src/webview/render-blocks.ts +91 -0
- package/src/webview/render-capability-map.ts +98 -0
- package/src/webview/render-fgca.ts +122 -0
- package/src/webview/render-goals.ts +110 -0
- package/src/webview/render-process-blueprint.ts +207 -0
- package/src/webview/render-process-map.ts +93 -0
- package/src/webview/render-products.ts +91 -0
- package/src/webview/render-scenarios.ts +90 -0
- package/src/webview/render-util.ts +34 -0
- package/src/webview/styles.css +323 -0
- package/src/yaml-normalize.ts +56 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { validateActivityCard } from '../validate.js';
|
|
3
|
+
const VALID = {
|
|
4
|
+
notation: 'activity-card',
|
|
5
|
+
spec_version: '0.1',
|
|
6
|
+
activity_card: {
|
|
7
|
+
id: 'ACTIVITY_CARD-EU-PROGRAMME-1',
|
|
8
|
+
project: 'ACTIVITY-EU-PROGRAMME-1',
|
|
9
|
+
description: 'Executive summary.',
|
|
10
|
+
milestones: [
|
|
11
|
+
{
|
|
12
|
+
id: 'MILESTONE-EU-CONFORMITY-CERT-1',
|
|
13
|
+
name: 'Certification obtained',
|
|
14
|
+
date: '2027-01-31',
|
|
15
|
+
delivers_changes: ['CHANGE-EU-COMPLIANCE-1'],
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
describe('validateActivityCard', () => {
|
|
21
|
+
it('accepts a well-formed card', () => {
|
|
22
|
+
const r = validateActivityCard(VALID);
|
|
23
|
+
expect(r.valid).toBe(true);
|
|
24
|
+
expect(r.errors).toHaveLength(0);
|
|
25
|
+
});
|
|
26
|
+
it('rejects non-object input', () => {
|
|
27
|
+
expect(validateActivityCard('x').valid).toBe(false);
|
|
28
|
+
expect(validateActivityCard(null).valid).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
it('HDR-001 on missing notation', () => {
|
|
31
|
+
const { notation: _drop, ...rest } = VALID;
|
|
32
|
+
const r = validateActivityCard(rest);
|
|
33
|
+
expect(r.valid).toBe(false);
|
|
34
|
+
expect(r.errors.some((e) => e.code === 'HDR-001')).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it('HDR-002 on wrong notation', () => {
|
|
37
|
+
const r = validateActivityCard({ ...VALID, notation: 'activities' });
|
|
38
|
+
expect(r.errors.some((e) => e.code === 'HDR-002')).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it('AC-001 on missing activity_card block', () => {
|
|
41
|
+
const r = validateActivityCard({ notation: 'activity-card' });
|
|
42
|
+
expect(r.valid).toBe(false);
|
|
43
|
+
expect(r.errors.some((e) => e.code === 'AC-001')).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
it('AC-002 on malformed card id', () => {
|
|
46
|
+
const r = validateActivityCard({ ...VALID, activity_card: { ...VALID.activity_card, id: 'CARD-1' } });
|
|
47
|
+
expect(r.errors.some((e) => e.code === 'AC-002')).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
it('PC-001 on missing project', () => {
|
|
50
|
+
const r = validateActivityCard({
|
|
51
|
+
...VALID,
|
|
52
|
+
activity_card: { ...VALID.activity_card, project: undefined },
|
|
53
|
+
});
|
|
54
|
+
expect(r.errors.some((e) => e.code === 'PC-001')).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
it('PC-001 on malformed project id', () => {
|
|
57
|
+
const r = validateActivityCard({
|
|
58
|
+
...VALID,
|
|
59
|
+
activity_card: { ...VALID.activity_card, project: 'GOAL-1' },
|
|
60
|
+
});
|
|
61
|
+
expect(r.errors.some((e) => e.code === 'PC-001')).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
it('AC-003 on milestone missing required fields', () => {
|
|
64
|
+
const r = validateActivityCard({
|
|
65
|
+
...VALID,
|
|
66
|
+
activity_card: { ...VALID.activity_card, milestones: [{ id: 'MILESTONE-X-1' }] },
|
|
67
|
+
});
|
|
68
|
+
expect(r.valid).toBe(false);
|
|
69
|
+
expect(r.errors.some((e) => e.code === 'AC-003')).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it('AC-004 on malformed milestone id', () => {
|
|
72
|
+
const r = validateActivityCard({
|
|
73
|
+
...VALID,
|
|
74
|
+
activity_card: {
|
|
75
|
+
...VALID.activity_card,
|
|
76
|
+
milestones: [{ id: 'MS-1', name: 'x', date: '2027-01-01' }],
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
expect(r.errors.some((e) => e.code === 'AC-004')).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it('AC-004 on duplicate milestone id', () => {
|
|
82
|
+
const m = { id: 'MILESTONE-X-1', name: 'x', date: '2027-01-01' };
|
|
83
|
+
const r = validateActivityCard({
|
|
84
|
+
...VALID,
|
|
85
|
+
activity_card: { ...VALID.activity_card, milestones: [m, { ...m }] },
|
|
86
|
+
});
|
|
87
|
+
expect(r.errors.some((e) => e.code === 'AC-004' && /Duplicate/.test(e.message))).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
it('AC-005 on bad milestone date format', () => {
|
|
90
|
+
const r = validateActivityCard({
|
|
91
|
+
...VALID,
|
|
92
|
+
activity_card: {
|
|
93
|
+
...VALID.activity_card,
|
|
94
|
+
milestones: [{ id: 'MILESTONE-X-1', name: 'x', date: '31/01/2027' }],
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
expect(r.errors.some((e) => e.code === 'AC-005')).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
it('AC-006 on malformed delivers_changes entry', () => {
|
|
100
|
+
const r = validateActivityCard({
|
|
101
|
+
...VALID,
|
|
102
|
+
activity_card: {
|
|
103
|
+
...VALID.activity_card,
|
|
104
|
+
milestones: [{ id: 'MILESTONE-X-1', name: 'x', date: '2027-01-01', delivers_changes: ['GOAL-1'] }],
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
expect(r.errors.some((e) => e.code === 'AC-006')).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
it('accepts a card with no milestones', () => {
|
|
110
|
+
const r = validateActivityCard({
|
|
111
|
+
...VALID,
|
|
112
|
+
activity_card: { id: 'ACTIVITY_CARD-X-1', project: 'ACTIVITY-X-1' },
|
|
113
|
+
});
|
|
114
|
+
expect(r.valid).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { RawMilestone, ActivityCardBlock, ActivityCardDoc, ActivityCardSources, ResolvedProject, ResolvedMilestone, ResolvedFactor, ResolvedGoal, ResolvedChange, ResolvedMotivation, ResolvedChildActivity, ResolvedActivityCard, DateField, MilestoneMarker, ChainNode, ChainEdge, ChildActivityRow, SectionHeader, ActivityCardLayoutOptions, ActivityCardLayout, ActivityCardValidationError, ActivityCardValidationWarning, ActivityCardValidationResult, } from './types.js';
|
|
2
|
+
export { validateActivityCard } from './validate.js';
|
|
3
|
+
export { resolveActivityCard } from './resolver.js';
|
|
4
|
+
export type { ActivityCardResolution } from './resolver.js';
|
|
5
|
+
export { layoutActivityCard, ARCHIMATE_CLASS } from './layout.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ActivityCardLayout, ActivityCardLayoutOptions, ResolvedActivityCard } from './types.js';
|
|
2
|
+
/** ArchiMate class per §5.1 — derived from element TYPE, never stored. */
|
|
3
|
+
export declare const ARCHIMATE_CLASS: {
|
|
4
|
+
readonly ACTIVITY: "Work Package";
|
|
5
|
+
readonly MILESTONE: "Implementation Event";
|
|
6
|
+
};
|
|
7
|
+
export declare function layoutActivityCard(card: ResolvedActivityCard, options?: ActivityCardLayoutOptions): ActivityCardLayout;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Activity Card — single-page layout (pure geometry; the preview paints SVG).
|
|
2
|
+
//
|
|
3
|
+
// Top-to-bottom card sections (spec §4 / §5):
|
|
4
|
+
// 1. Title — project name
|
|
5
|
+
// 2. Dates band — Initiation (valid_from) · Planned start · Planned end
|
|
6
|
+
// 3. Milestones — narrative timeline, markers left→right by date
|
|
7
|
+
// 4. Motivation — Factors → Goals → Changes columns with F→G→C edges
|
|
8
|
+
// 5. Child activities — activities whose parent = the project
|
|
9
|
+
//
|
|
10
|
+
// The §5.1 ArchiMate-class convention ("(Work Package)", "(Implementation
|
|
11
|
+
// Event)") is applied HERE, derived from element TYPE — there is no
|
|
12
|
+
// archimate_class data field.
|
|
13
|
+
const DEFAULTS = {
|
|
14
|
+
cardWidth: 780,
|
|
15
|
+
columnGap: 28,
|
|
16
|
+
rowGap: 12,
|
|
17
|
+
};
|
|
18
|
+
// Fixed metrics (px). Kept local — the card has no user-tunable spacing yet.
|
|
19
|
+
const PAD = 20;
|
|
20
|
+
const TITLE_H = 38;
|
|
21
|
+
const DATES_H = 56;
|
|
22
|
+
const SECTION_HEADER_H = 26;
|
|
23
|
+
const SECTION_GAP = 16;
|
|
24
|
+
const MILESTONE_W = 168;
|
|
25
|
+
const MILESTONE_H = 64;
|
|
26
|
+
const MILESTONE_GAP = 16;
|
|
27
|
+
const CHAIN_NODE_H = 46;
|
|
28
|
+
const CHILD_ROW_H = 42;
|
|
29
|
+
/** ArchiMate class per §5.1 — derived from element TYPE, never stored. */
|
|
30
|
+
export const ARCHIMATE_CLASS = {
|
|
31
|
+
ACTIVITY: 'Work Package',
|
|
32
|
+
MILESTONE: 'Implementation Event',
|
|
33
|
+
};
|
|
34
|
+
export function layoutActivityCard(card, options) {
|
|
35
|
+
const opts = { ...DEFAULTS, ...(options ?? {}) };
|
|
36
|
+
const contentX = PAD;
|
|
37
|
+
const contentW = opts.cardWidth - PAD * 2;
|
|
38
|
+
let cursorY = PAD;
|
|
39
|
+
// 1. Title
|
|
40
|
+
const title = { name: card.project.name, x: contentX, y: cursorY + TITLE_H / 2 };
|
|
41
|
+
cursorY += TITLE_H;
|
|
42
|
+
// 2. Dates band — three equal cells.
|
|
43
|
+
const dateDefs = [
|
|
44
|
+
{ label: 'Initiation', value: card.project.valid_from ?? '—' },
|
|
45
|
+
{ label: 'Planned start', value: card.project.start_date ?? '—' },
|
|
46
|
+
{ label: 'Planned end', value: card.project.end_date ?? '—' },
|
|
47
|
+
];
|
|
48
|
+
const dateGap = 12;
|
|
49
|
+
const dateCellW = (contentW - dateGap * (dateDefs.length - 1)) / dateDefs.length;
|
|
50
|
+
const dateFields = dateDefs.map((d, i) => ({
|
|
51
|
+
label: d.label,
|
|
52
|
+
value: d.value,
|
|
53
|
+
x: contentX + i * (dateCellW + dateGap),
|
|
54
|
+
y: cursorY,
|
|
55
|
+
width: dateCellW,
|
|
56
|
+
height: DATES_H,
|
|
57
|
+
}));
|
|
58
|
+
cursorY += DATES_H + SECTION_GAP;
|
|
59
|
+
const sectionHeaders = [];
|
|
60
|
+
const pushHeader = (label) => {
|
|
61
|
+
sectionHeaders.push({ label, x: contentX, y: cursorY, width: contentW, height: SECTION_HEADER_H });
|
|
62
|
+
cursorY += SECTION_HEADER_H + 8;
|
|
63
|
+
};
|
|
64
|
+
// 3. Milestones — timeline markers, wrapped left→right.
|
|
65
|
+
const milestones = [];
|
|
66
|
+
if (card.milestones.length > 0) {
|
|
67
|
+
pushHeader('Milestones');
|
|
68
|
+
const perRow = Math.max(1, Math.floor((contentW + MILESTONE_GAP) / (MILESTONE_W + MILESTONE_GAP)));
|
|
69
|
+
const rowStartY = cursorY;
|
|
70
|
+
card.milestones.forEach((m, i) => {
|
|
71
|
+
const col = i % perRow;
|
|
72
|
+
const row = Math.floor(i / perRow);
|
|
73
|
+
milestones.push({
|
|
74
|
+
id: m.id,
|
|
75
|
+
name: m.name,
|
|
76
|
+
date: m.date,
|
|
77
|
+
archimateClass: ARCHIMATE_CLASS.MILESTONE,
|
|
78
|
+
x: contentX + col * (MILESTONE_W + MILESTONE_GAP),
|
|
79
|
+
y: rowStartY + row * (MILESTONE_H + opts.rowGap),
|
|
80
|
+
width: MILESTONE_W,
|
|
81
|
+
height: MILESTONE_H,
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
const rows = Math.ceil(card.milestones.length / perRow);
|
|
85
|
+
cursorY = rowStartY + rows * (MILESTONE_H + opts.rowGap) - opts.rowGap + SECTION_GAP;
|
|
86
|
+
}
|
|
87
|
+
// 4. Motivation chain — Factors | Goals | Changes columns.
|
|
88
|
+
const chainEdges = [];
|
|
89
|
+
const factorsCol = [];
|
|
90
|
+
const goalsCol = [];
|
|
91
|
+
const changesCol = [];
|
|
92
|
+
const { factors, goals, changes } = card.motivation;
|
|
93
|
+
if (factors.length + goals.length + changes.length > 0) {
|
|
94
|
+
pushHeader('Motivation — Factors → Goals → Changes');
|
|
95
|
+
const colW = (contentW - opts.columnGap * 2) / 3;
|
|
96
|
+
const colX = [contentX, contentX + colW + opts.columnGap, contentX + (colW + opts.columnGap) * 2];
|
|
97
|
+
const colStartY = cursorY;
|
|
98
|
+
const stack = (items, colIndex, into) => {
|
|
99
|
+
items.forEach((it, i) => {
|
|
100
|
+
into.push({
|
|
101
|
+
id: it.id,
|
|
102
|
+
name: it.name,
|
|
103
|
+
x: colX[colIndex],
|
|
104
|
+
y: colStartY + i * (CHAIN_NODE_H + opts.rowGap),
|
|
105
|
+
width: colW,
|
|
106
|
+
height: CHAIN_NODE_H,
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
stack(factors, 0, factorsCol);
|
|
111
|
+
stack(goals, 1, goalsCol);
|
|
112
|
+
stack(changes, 2, changesCol);
|
|
113
|
+
// Edges: factor→goal (goal.factorIds), goal→change (change.goalIds).
|
|
114
|
+
const factorIds = new Set(factorsCol.map((n) => n.id));
|
|
115
|
+
const goalIds = new Set(goalsCol.map((n) => n.id));
|
|
116
|
+
for (const g of goals) {
|
|
117
|
+
for (const fid of g.factorIds) {
|
|
118
|
+
if (factorIds.has(fid))
|
|
119
|
+
chainEdges.push({ sourceId: fid, targetId: g.id });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const c of changes) {
|
|
123
|
+
for (const gid of c.goalIds) {
|
|
124
|
+
if (goalIds.has(gid))
|
|
125
|
+
chainEdges.push({ sourceId: gid, targetId: c.id });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const tallest = Math.max(factorsCol.length, goalsCol.length, changesCol.length);
|
|
129
|
+
cursorY = colStartY + tallest * (CHAIN_NODE_H + opts.rowGap) - opts.rowGap + SECTION_GAP;
|
|
130
|
+
}
|
|
131
|
+
// 5. Child activities — full-width rows.
|
|
132
|
+
const childActivities = [];
|
|
133
|
+
if (card.childActivities.length > 0) {
|
|
134
|
+
pushHeader('Child activities');
|
|
135
|
+
const rowStartY = cursorY;
|
|
136
|
+
card.childActivities.forEach((a, i) => {
|
|
137
|
+
const metaBits = [];
|
|
138
|
+
if (a.start_date || a.end_date)
|
|
139
|
+
metaBits.push(`${a.start_date ?? '?'} → ${a.end_date ?? '?'}`);
|
|
140
|
+
if (a.owner)
|
|
141
|
+
metaBits.push(a.owner);
|
|
142
|
+
childActivities.push({
|
|
143
|
+
id: a.id,
|
|
144
|
+
name: a.name,
|
|
145
|
+
archimateClass: ARCHIMATE_CLASS.ACTIVITY,
|
|
146
|
+
meta: metaBits.join(' · '),
|
|
147
|
+
x: contentX,
|
|
148
|
+
y: rowStartY + i * (CHILD_ROW_H + opts.rowGap),
|
|
149
|
+
width: contentW,
|
|
150
|
+
height: CHILD_ROW_H,
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
cursorY =
|
|
154
|
+
rowStartY + card.childActivities.length * (CHILD_ROW_H + opts.rowGap) - opts.rowGap + SECTION_GAP;
|
|
155
|
+
}
|
|
156
|
+
const totalHeight = cursorY - SECTION_GAP + PAD;
|
|
157
|
+
return {
|
|
158
|
+
bounds: { x: 0, y: 0, width: opts.cardWidth, height: Math.max(totalHeight, PAD * 2 + TITLE_H) },
|
|
159
|
+
title,
|
|
160
|
+
dateFields,
|
|
161
|
+
sectionHeaders,
|
|
162
|
+
milestones,
|
|
163
|
+
chainColumns: { factors: factorsCol, goals: goalsCol, changes: changesCol },
|
|
164
|
+
chainEdges,
|
|
165
|
+
childActivities,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ActivityCardDoc, ActivityCardSources, ResolvedActivityCard } from './types.js';
|
|
2
|
+
import type { ValidationResult } from '../validation-types.js';
|
|
3
|
+
export interface ActivityCardResolution extends ValidationResult {
|
|
4
|
+
/** Present only when resolution succeeded (project found + valid_from OK). */
|
|
5
|
+
resolved?: ResolvedActivityCard;
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveActivityCard(doc: ActivityCardDoc, sources: ActivityCardSources): ActivityCardResolution;
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
// Activity Card — cross-document resolver (the novel piece of this notation).
|
|
2
|
+
//
|
|
3
|
+
// Unlike every other Studio preview, the Activity Card is assembled from
|
|
4
|
+
// MULTIPLE documents. The card YAML names a project Activity; the resolver
|
|
5
|
+
// pulls the rest of the card's content BY REFERENCE from the canonical
|
|
6
|
+
// ELEMENT and RELATION store — never from other view documents (view-purity:
|
|
7
|
+
// a view is a projection over elements + relations, methodology
|
|
8
|
+
// ELEMENT_PRIMITIVES.md §1):
|
|
9
|
+
//
|
|
10
|
+
// canon/elements/** → one element per file. The project ACTIVITY (name,
|
|
11
|
+
// lifecycle + schedule dates, delivers_changes[],
|
|
12
|
+
// parent) and its child ACTIVITY elements (parent =
|
|
13
|
+
// project id); the FACTOR / GOAL / CHANGE elements that
|
|
14
|
+
// the motivation chain expands (goal.factors,
|
|
15
|
+
// change.goals carried inline on the elements).
|
|
16
|
+
// canon/relations/** → `notation: relation` files. The project's goals come
|
|
17
|
+
// from the first-class `activity_goal` REL (from =
|
|
18
|
+
// project id), preferred over the activity element's
|
|
19
|
+
// transitional inline `goals[]` when present
|
|
20
|
+
// (07-activities.md §"Time-aware relations").
|
|
21
|
+
//
|
|
22
|
+
// The extension reads + parses the element and relation files (walking the
|
|
23
|
+
// org's `canon/elements` and `canon/relations` trees) and hands the parsed
|
|
24
|
+
// docs in. This resolver is filesystem-free and pure so it stays unit-testable.
|
|
25
|
+
//
|
|
26
|
+
// Cross-document validation lives here (the rules that need the sibling docs):
|
|
27
|
+
// PC-001 project does not resolve to an admitted Activity
|
|
28
|
+
// PC-002 resolved Activity has activity_type other than "Project"
|
|
29
|
+
// PC-003 milestone.delivers_changes[] entry not in the project's own
|
|
30
|
+
// delivers_changes[]
|
|
31
|
+
// PC-004 (warning) milestone.date outside [valid_from, valid_to]
|
|
32
|
+
// LIFECYCLE-001 project valid_from missing / not a parseable ISO date
|
|
33
|
+
// LIFECYCLE-002 project valid_to present, not null, not a parseable date
|
|
34
|
+
// LIFECYCLE-003 project valid_to earlier than valid_from
|
|
35
|
+
//
|
|
36
|
+
// LIFECYCLE-* are scoped to the RESOLVED PROJECT Activity only — the card is
|
|
37
|
+
// built around the project's initiation date, so a missing valid_from there is
|
|
38
|
+
// a hard error. Child activities and FGCA elements are not lifecycle-checked
|
|
39
|
+
// here (out of this notation's scope; today's Studio activities docs may
|
|
40
|
+
// legitimately omit lifecycle fields).
|
|
41
|
+
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
42
|
+
function isObject(v) {
|
|
43
|
+
return !!v && typeof v === 'object' && !Array.isArray(v);
|
|
44
|
+
}
|
|
45
|
+
function str(v) {
|
|
46
|
+
return typeof v === 'string' && v.trim().length > 0 ? v : undefined;
|
|
47
|
+
}
|
|
48
|
+
function strArray(v) {
|
|
49
|
+
if (!Array.isArray(v))
|
|
50
|
+
return [];
|
|
51
|
+
return v.filter((x) => typeof x === 'string' && x.trim().length > 0);
|
|
52
|
+
}
|
|
53
|
+
/** A parseable quoted ISO 8601 date, calendar-checked (rejects 2026-13-40). */
|
|
54
|
+
function isIsoDate(v) {
|
|
55
|
+
if (typeof v !== 'string' || !DATE_RE.test(v))
|
|
56
|
+
return false;
|
|
57
|
+
const t = Date.parse(`${v}T00:00:00Z`);
|
|
58
|
+
if (Number.isNaN(t))
|
|
59
|
+
return false;
|
|
60
|
+
// Round-trip guard so 2026-02-30 (which Date.parse may roll forward) is rejected.
|
|
61
|
+
return new Date(t).toISOString().slice(0, 10) === v;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Index canon element documents of one `notation` by their `id`. Each element
|
|
65
|
+
* is its own single-element file (`notation: activity|factor|goal|change|…`
|
|
66
|
+
* with a top-level `id`); first definition wins.
|
|
67
|
+
*/
|
|
68
|
+
function collectByNotation(docs, notation) {
|
|
69
|
+
const out = new Map();
|
|
70
|
+
for (const doc of docs) {
|
|
71
|
+
if (!isObject(doc))
|
|
72
|
+
continue;
|
|
73
|
+
if (str(doc['notation']) !== notation)
|
|
74
|
+
continue;
|
|
75
|
+
const id = str(doc['id']);
|
|
76
|
+
if (!id)
|
|
77
|
+
continue;
|
|
78
|
+
if (!out.has(id))
|
|
79
|
+
out.set(id, doc); // first definition wins
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* GOAL ids reached by an *active* `activity_goal` relation originating at
|
|
85
|
+
* `fromId`. A relation with a non-null `valid_to` has ended (the activity was
|
|
86
|
+
* re-aimed) and is excluded — the card shows the currently-served goals.
|
|
87
|
+
*/
|
|
88
|
+
function activeActivityGoals(relations, fromId) {
|
|
89
|
+
const out = [];
|
|
90
|
+
for (const doc of relations) {
|
|
91
|
+
if (!isObject(doc))
|
|
92
|
+
continue;
|
|
93
|
+
if (str(doc['notation']) !== 'relation')
|
|
94
|
+
continue;
|
|
95
|
+
if (str(doc['type']) !== 'activity_goal')
|
|
96
|
+
continue;
|
|
97
|
+
if (str(doc['from']) !== fromId)
|
|
98
|
+
continue;
|
|
99
|
+
const to = str(doc['to']);
|
|
100
|
+
if (!to)
|
|
101
|
+
continue;
|
|
102
|
+
const validTo = doc['valid_to'];
|
|
103
|
+
if (validTo !== undefined && validTo !== null)
|
|
104
|
+
continue; // ended relation
|
|
105
|
+
if (!out.includes(to))
|
|
106
|
+
out.push(to);
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
export function resolveActivityCard(doc, sources) {
|
|
111
|
+
const errors = [];
|
|
112
|
+
const warnings = [];
|
|
113
|
+
const card = doc?.activity_card;
|
|
114
|
+
const projectId = str(card?.project);
|
|
115
|
+
if (!projectId) {
|
|
116
|
+
// Structural validator already flags this; nothing to resolve.
|
|
117
|
+
errors.push({ code: 'PC-001', message: 'activity_card.project is missing' });
|
|
118
|
+
return { valid: false, errors, warnings };
|
|
119
|
+
}
|
|
120
|
+
const activities = collectByNotation(sources.elements, 'activity');
|
|
121
|
+
const projectRec = activities.get(projectId);
|
|
122
|
+
// PC-001 — project must resolve to an admitted ACTIVITY element in canon.
|
|
123
|
+
if (!projectRec) {
|
|
124
|
+
errors.push({
|
|
125
|
+
code: 'PC-001',
|
|
126
|
+
message: `activity_card.project "${projectId}" does not resolve to an ACTIVITY element in the canon element store`,
|
|
127
|
+
});
|
|
128
|
+
return { valid: false, errors, warnings };
|
|
129
|
+
}
|
|
130
|
+
// PC-002 — the resolved Activity should be the project scale. In the element
|
|
131
|
+
// model all activity scales (initiative / programme / project / task) share
|
|
132
|
+
// one ACTIVITY TYPE and `activity_type` references an ActivityType element,
|
|
133
|
+
// so a missing/non-literal value is acceptable; only an explicit, clearly
|
|
134
|
+
// non-project marker is flagged. (Canonical project-identification semantics
|
|
135
|
+
// are tracked as a follow-up internally.)
|
|
136
|
+
const activityType = str(projectRec['activity_type']);
|
|
137
|
+
if (activityType !== undefined && activityType !== 'Project' && activityType !== 'project') {
|
|
138
|
+
errors.push({
|
|
139
|
+
code: 'PC-002',
|
|
140
|
+
message: `Activity "${projectId}" has activity_type "${activityType}", expected the project scale`,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// LIFECYCLE-001..003 on the project Activity.
|
|
144
|
+
const validFrom = projectRec['valid_from'];
|
|
145
|
+
const validToRaw = projectRec['valid_to'];
|
|
146
|
+
let validFromOk = false;
|
|
147
|
+
if (validFrom === undefined || validFrom === null) {
|
|
148
|
+
errors.push({ code: 'LIFECYCLE-001', message: `Activity "${projectId}" valid_from is required` });
|
|
149
|
+
}
|
|
150
|
+
else if (!isIsoDate(validFrom)) {
|
|
151
|
+
errors.push({
|
|
152
|
+
code: 'LIFECYCLE-001',
|
|
153
|
+
message: `Activity "${projectId}" valid_from "${String(validFrom)}" is not a parseable ISO 8601 date`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
validFromOk = true;
|
|
158
|
+
}
|
|
159
|
+
let validToOk = false;
|
|
160
|
+
const validToPresent = validToRaw !== undefined && validToRaw !== null;
|
|
161
|
+
if (validToPresent) {
|
|
162
|
+
if (!isIsoDate(validToRaw)) {
|
|
163
|
+
errors.push({
|
|
164
|
+
code: 'LIFECYCLE-002',
|
|
165
|
+
message: `Activity "${projectId}" valid_to "${String(validToRaw)}" is not a parseable ISO 8601 date`,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
validToOk = true;
|
|
170
|
+
if (validFromOk && validToRaw < validFrom) {
|
|
171
|
+
errors.push({
|
|
172
|
+
code: 'LIFECYCLE-003',
|
|
173
|
+
message: `Activity "${projectId}" valid_to "${String(validToRaw)}" is earlier than valid_from "${String(validFrom)}"`,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// A failed lifecycle/PC-001 stops us producing a card view-model, but we still
|
|
179
|
+
// return every error collected so the panel lists them all at once.
|
|
180
|
+
const projectChanges = new Set(strArray(projectRec['delivers_changes']));
|
|
181
|
+
// Project goals: prefer the first-class `activity_goal` relations (the
|
|
182
|
+
// canonical, time-aware home for an Activity→Goal link); fall back to the
|
|
183
|
+
// activity element's transitional inline `goals[]` when no relation exists
|
|
184
|
+
// (07-activities.md §"Time-aware relations").
|
|
185
|
+
const relGoalIds = activeActivityGoals(sources.relations, projectId);
|
|
186
|
+
const projectGoalIds = relGoalIds.length > 0 ? relGoalIds : strArray(projectRec['goals']);
|
|
187
|
+
// PC-003 — each milestone change must be a subset of the project's changes.
|
|
188
|
+
const rawMilestones = Array.isArray(card.milestones) ? card.milestones : [];
|
|
189
|
+
const milestones = [];
|
|
190
|
+
for (const m of rawMilestones) {
|
|
191
|
+
if (!isObject(m))
|
|
192
|
+
continue;
|
|
193
|
+
const mid = str(m['id']);
|
|
194
|
+
const mname = str(m['name']);
|
|
195
|
+
const mdate = str(m['date']);
|
|
196
|
+
if (!mid || !mname || !mdate)
|
|
197
|
+
continue; // structural validator already flagged
|
|
198
|
+
const deliversChanges = strArray(m['delivers_changes']);
|
|
199
|
+
for (const c of deliversChanges) {
|
|
200
|
+
if (!projectChanges.has(c)) {
|
|
201
|
+
errors.push({
|
|
202
|
+
code: 'PC-003',
|
|
203
|
+
message: `Milestone "${mid}" delivers_changes "${c}" is not in project "${projectId}" delivers_changes`,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// PC-004 — milestone date should fall within the project lifecycle window.
|
|
208
|
+
if (validFromOk && mdate < validFrom) {
|
|
209
|
+
warnings.push({
|
|
210
|
+
code: 'PC-004',
|
|
211
|
+
message: `Milestone "${mid}" date "${mdate}" is before project valid_from "${String(validFrom)}"`,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
if (validToOk && mdate > validToRaw) {
|
|
215
|
+
warnings.push({
|
|
216
|
+
code: 'PC-004',
|
|
217
|
+
message: `Milestone "${mid}" date "${mdate}" is after project valid_to "${String(validToRaw)}"`,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
milestones.push({
|
|
221
|
+
id: mid,
|
|
222
|
+
name: mname,
|
|
223
|
+
date: mdate,
|
|
224
|
+
description: str(m['description']),
|
|
225
|
+
deliversChanges,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
milestones.sort((a, b) => (a.date < b.date ? -1 : a.date > b.date ? 1 : 0));
|
|
229
|
+
// If we have hard errors, surface them without an assembled card.
|
|
230
|
+
if (errors.length > 0) {
|
|
231
|
+
return { valid: false, errors, warnings };
|
|
232
|
+
}
|
|
233
|
+
// ── Motivation chain — expand against canon FACTOR / GOAL / CHANGE elements ──
|
|
234
|
+
const factorElems = collectByNotation(sources.elements, 'factor');
|
|
235
|
+
const goalElems = collectByNotation(sources.elements, 'goal');
|
|
236
|
+
const changeElems = collectByNotation(sources.elements, 'change');
|
|
237
|
+
const changes = [];
|
|
238
|
+
for (const cid of projectChanges) {
|
|
239
|
+
const rec = changeElems.get(cid);
|
|
240
|
+
if (!rec) {
|
|
241
|
+
warnings.push({
|
|
242
|
+
code: 'PC-001',
|
|
243
|
+
message: `Project change "${cid}" not found as a CHANGE element in canon; omitted from the motivation chain`,
|
|
244
|
+
});
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
changes.push({ id: cid, name: str(rec['name']) ?? cid, goalIds: strArray(rec['goals']) });
|
|
248
|
+
}
|
|
249
|
+
// Goals shown = the project's declared goals ∪ goals referenced by in-scope
|
|
250
|
+
// changes (so the F→G→C chain stays connected).
|
|
251
|
+
const goalIdSet = new Set(projectGoalIds);
|
|
252
|
+
for (const ch of changes)
|
|
253
|
+
for (const g of ch.goalIds)
|
|
254
|
+
goalIdSet.add(g);
|
|
255
|
+
const goals = [];
|
|
256
|
+
for (const gid of goalIdSet) {
|
|
257
|
+
const rec = goalElems.get(gid);
|
|
258
|
+
if (!rec) {
|
|
259
|
+
warnings.push({
|
|
260
|
+
code: 'PC-001',
|
|
261
|
+
message: `Goal "${gid}" not found as a GOAL element in canon; omitted from the motivation chain`,
|
|
262
|
+
});
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
goals.push({ id: gid, name: str(rec['name']) ?? gid, factorIds: strArray(rec['factors']) });
|
|
266
|
+
}
|
|
267
|
+
// Factors shown = those referenced by the in-scope goals.
|
|
268
|
+
const factorIdSet = new Set();
|
|
269
|
+
for (const g of goals)
|
|
270
|
+
for (const f of g.factorIds)
|
|
271
|
+
factorIdSet.add(f);
|
|
272
|
+
const factors = [];
|
|
273
|
+
for (const fid of factorIdSet) {
|
|
274
|
+
const rec = factorElems.get(fid);
|
|
275
|
+
factors.push({ id: fid, name: rec ? str(rec['name']) ?? fid : fid });
|
|
276
|
+
}
|
|
277
|
+
// ── Child activities — parent = project id ──────────────────────────────────
|
|
278
|
+
const childActivities = [];
|
|
279
|
+
for (const [id, rec] of activities) {
|
|
280
|
+
if (str(rec['parent']) !== projectId)
|
|
281
|
+
continue;
|
|
282
|
+
childActivities.push({
|
|
283
|
+
id,
|
|
284
|
+
name: str(rec['name']) ?? id,
|
|
285
|
+
activity_type: str(rec['activity_type']),
|
|
286
|
+
start_date: str(rec['start_date']),
|
|
287
|
+
end_date: str(rec['end_date']),
|
|
288
|
+
owner: str(rec['owner']),
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
childActivities.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
292
|
+
const project = {
|
|
293
|
+
id: projectId,
|
|
294
|
+
name: str(projectRec['name']) ?? projectId,
|
|
295
|
+
description: str(projectRec['description']),
|
|
296
|
+
valid_from: validFromOk ? validFrom : undefined,
|
|
297
|
+
valid_to: validToOk ? validToRaw : undefined,
|
|
298
|
+
start_date: str(projectRec['start_date']),
|
|
299
|
+
end_date: str(projectRec['end_date']),
|
|
300
|
+
};
|
|
301
|
+
const resolved = {
|
|
302
|
+
cardId: str(card.id) ?? '',
|
|
303
|
+
cardDescription: str(card.description),
|
|
304
|
+
project,
|
|
305
|
+
milestones,
|
|
306
|
+
motivation: { factors, goals, changes },
|
|
307
|
+
childActivities,
|
|
308
|
+
};
|
|
309
|
+
return { valid: true, errors, warnings, resolved };
|
|
310
|
+
}
|