@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,256 @@
|
|
|
1
|
+
// HTML renderers for the compliance views (vkgeorgia/strategy#84 Phase 5,
|
|
2
|
+
// PDF follow-on). Pure string builders — fed to WeasyPrint by the
|
|
3
|
+
// `transitrix export-compliance --format pdf` path in src/export-compliance.ts.
|
|
4
|
+
//
|
|
5
|
+
// Each entry point returns a complete, self-contained HTML document (no
|
|
6
|
+
// external assets) so WeasyPrint reads the whole brief on stdin. CSS is
|
|
7
|
+
// inlined; the page rules target A4 portrait with branded header and footer.
|
|
8
|
+
// Status colours mirror the Studio preview palette (see compliance-render.ts)
|
|
9
|
+
// so the export and the in-editor view stay visually consistent.
|
|
10
|
+
import { buildComplianceMatrix } from '../compliance-matrix/index.js';
|
|
11
|
+
import { buildComplianceIndex } from './reverse-index.js';
|
|
12
|
+
import { buildLawTree, buildProductView } from './views.js';
|
|
13
|
+
import { buildGapReport } from './gap-report.js';
|
|
14
|
+
const STATUS_LABELS = {
|
|
15
|
+
compliant: 'Compliant',
|
|
16
|
+
partial: 'Partial',
|
|
17
|
+
non_compliant: 'Non-compliant',
|
|
18
|
+
under_review: 'Under review',
|
|
19
|
+
n_a: 'N/A',
|
|
20
|
+
};
|
|
21
|
+
function escHtml(s) {
|
|
22
|
+
return s
|
|
23
|
+
.replace(/&/g, '&')
|
|
24
|
+
.replace(/</g, '<')
|
|
25
|
+
.replace(/>/g, '>')
|
|
26
|
+
.replace(/"/g, '"');
|
|
27
|
+
}
|
|
28
|
+
function badge(status) {
|
|
29
|
+
return `<span class="cmp-badge cmp-${status}">${escHtml(STATUS_LABELS[status])}</span>`;
|
|
30
|
+
}
|
|
31
|
+
// A4 portrait with 18mm margins — matches the WeasyPrint one-pager template
|
|
32
|
+
// the site uses. Brand colour `#004d67` mirrors `--ts-brand-primary` from
|
|
33
|
+
// extension/src/compliance-render.ts so the PDF and the Studio preview agree.
|
|
34
|
+
const CSS = `
|
|
35
|
+
@page {
|
|
36
|
+
size: A4 portrait;
|
|
37
|
+
margin: 18mm 16mm 22mm;
|
|
38
|
+
@bottom-left { content: "Transitrix — compliance report"; font: 9pt "Helvetica", "Arial", sans-serif; color: #475569; }
|
|
39
|
+
@bottom-right { content: "Page " counter(page) " / " counter(pages); font: 9pt "Helvetica", "Arial", sans-serif; color: #475569; }
|
|
40
|
+
}
|
|
41
|
+
html, body { margin: 0; padding: 0; }
|
|
42
|
+
body { font-family: "Helvetica", "Arial", sans-serif; font-size: 10pt; color: #0f172a; line-height: 1.4; }
|
|
43
|
+
.cmp-header { border-bottom: 2px solid #004d67; padding-bottom: 6pt; margin-bottom: 14pt; }
|
|
44
|
+
.cmp-header .cmp-eyebrow { font-size: 8.5pt; letter-spacing: 0.08em; text-transform: uppercase; color: #004d67; font-weight: 700; }
|
|
45
|
+
.cmp-header h1 { font-size: 17pt; margin: 2pt 0 4pt; color: #0f172a; }
|
|
46
|
+
.cmp-header .cmp-stamp { font-size: 9pt; color: #475569; }
|
|
47
|
+
h2 { font-size: 12pt; margin: 16pt 0 6pt; color: #0f172a; page-break-after: avoid; }
|
|
48
|
+
h2 .cmp-count { color: #64748b; font-weight: 400; font-size: 10pt; }
|
|
49
|
+
p.cmp-empty { color: #64748b; font-style: italic; }
|
|
50
|
+
table { border-collapse: collapse; width: 100%; font-size: 9.5pt; margin-bottom: 10pt; }
|
|
51
|
+
th, td { border: 0.5pt solid #cbd5e1; padding: 4pt 6pt; text-align: left; vertical-align: top; }
|
|
52
|
+
th { background: #f1f5f9; font-weight: 700; color: #0f172a; }
|
|
53
|
+
table.cmp-matrix th:first-child, table.cmp-matrix td:first-child { background: #f8fafc; font-weight: 600; }
|
|
54
|
+
code, .cmp-id { font-family: "Menlo", "Consolas", monospace; font-size: 9pt; color: #475569; }
|
|
55
|
+
.cmp-badge { display: inline-block; padding: 1pt 6pt; border-radius: 8pt; font-size: 8.5pt; font-weight: 700; }
|
|
56
|
+
.cmp-compliant { background: #d1fae5; color: #065f46; }
|
|
57
|
+
.cmp-partial { background: #fef9c3; color: #854d0e; }
|
|
58
|
+
.cmp-non_compliant { background: #fee2e2; color: #991b1b; }
|
|
59
|
+
.cmp-under_review { background: #e0f2fe; color: #0c4a6e; }
|
|
60
|
+
.cmp-n_a { background: #f1f5f9; color: #64748b; }
|
|
61
|
+
.cmp-cell-gap { color: #94a3b8; text-align: center; }
|
|
62
|
+
.cmp-req { border: 0.5pt solid #cbd5e1; border-radius: 3pt; margin-bottom: 8pt; page-break-inside: avoid; }
|
|
63
|
+
.cmp-req-head { background: #f1f5f9; padding: 5pt 8pt; }
|
|
64
|
+
.cmp-req-head .cmp-req-name { font-weight: 700; color: #0f172a; }
|
|
65
|
+
.cmp-req-head .cmp-req-id { margin-left: 6pt; color: #475569; font-size: 9pt; font-family: "Menlo", "Consolas", monospace; }
|
|
66
|
+
.cmp-sev { font-size: 8pt; text-transform: uppercase; letter-spacing: 0.06em; margin-left: 8pt; }
|
|
67
|
+
.cmp-sev-high { color: #b91c1c; }
|
|
68
|
+
.cmp-sev-medium { color: #b45309; }
|
|
69
|
+
.cmp-sev-low { color: #2563eb; }
|
|
70
|
+
.cmp-assertions { list-style: none; margin: 0; padding: 0; }
|
|
71
|
+
.cmp-assertions li { padding: 4pt 8pt 4pt 16pt; border-top: 0.5pt solid #e2e8f0; }
|
|
72
|
+
.cmp-assertions li .cmp-meta { color: #475569; font-size: 8.5pt; margin-left: 6pt; }
|
|
73
|
+
.cmp-section { margin-bottom: 12pt; }
|
|
74
|
+
.cmp-rows { list-style: none; margin: 0; padding: 0; }
|
|
75
|
+
.cmp-rows li { padding: 3pt 0 3pt 14pt; border-bottom: 0.5pt solid #e2e8f0; text-indent: -10pt; }
|
|
76
|
+
.cmp-rows li::before { content: "☐"; color: #94a3b8; margin-right: 6pt; }
|
|
77
|
+
.cmp-ok { color: #065f46; font-weight: 600; }
|
|
78
|
+
.cmp-summary { font-size: 9pt; color: #475569; }
|
|
79
|
+
`;
|
|
80
|
+
function htmlDoc(title, today, body) {
|
|
81
|
+
const stamp = today ? `Generated ${escHtml(today)}` : '';
|
|
82
|
+
return [
|
|
83
|
+
'<!doctype html>',
|
|
84
|
+
'<html lang="en">',
|
|
85
|
+
'<head>',
|
|
86
|
+
'<meta charset="utf-8"/>',
|
|
87
|
+
`<title>${escHtml(title)}</title>`,
|
|
88
|
+
`<style>${CSS}</style>`,
|
|
89
|
+
'</head>',
|
|
90
|
+
'<body>',
|
|
91
|
+
'<header class="cmp-header">',
|
|
92
|
+
'<div class="cmp-eyebrow">Transitrix · Compliance</div>',
|
|
93
|
+
`<h1>${escHtml(title)}</h1>`,
|
|
94
|
+
stamp ? `<div class="cmp-stamp">${stamp}</div>` : '',
|
|
95
|
+
'</header>',
|
|
96
|
+
body,
|
|
97
|
+
'</body>',
|
|
98
|
+
'</html>',
|
|
99
|
+
'',
|
|
100
|
+
].join('\n');
|
|
101
|
+
}
|
|
102
|
+
/** Renders the requested compliance view from a scanned canon to a complete HTML document. */
|
|
103
|
+
export function renderComplianceHtml(canon, scope, options = {}) {
|
|
104
|
+
switch (scope.mode) {
|
|
105
|
+
case 'matrix': {
|
|
106
|
+
const m = buildComplianceMatrix({ products: canon.products, requirements: canon.requirements, assertions: canon.assertions });
|
|
107
|
+
const title = options.title ?? 'Compliance Matrix';
|
|
108
|
+
const summary = `<p class="cmp-summary">${m.summary.products} products × ${m.summary.requirements} requirements · ${m.summary.gaps} gaps · ${m.summary.assertions} assertions</p>`;
|
|
109
|
+
if (m.products.length === 0 || m.requirements.length === 0) {
|
|
110
|
+
return htmlDoc(title, options.today, `${summary}<p class="cmp-empty">No products or requirements found in the scanned canon.</p>`);
|
|
111
|
+
}
|
|
112
|
+
const head = `<tr><th>Product \\ Requirement</th>${m.requirements.map(r => `<th>${escHtml(r.name)}</th>`).join('')}</tr>`;
|
|
113
|
+
const rows = m.products.map((p, ri) => {
|
|
114
|
+
const cells = m.requirements.map((_r, ci) => {
|
|
115
|
+
const c = m.cells[ri][ci];
|
|
116
|
+
return c.status ? `<td>${badge(c.status)}</td>` : '<td class="cmp-cell-gap">—</td>';
|
|
117
|
+
}).join('');
|
|
118
|
+
const name = escHtml(p.name) + (p.unresolved ? ' <span class="cmp-sev cmp-sev-high">unresolved</span>' : '');
|
|
119
|
+
return `<tr><td>${name}</td>${cells}</tr>`;
|
|
120
|
+
}).join('');
|
|
121
|
+
return htmlDoc(title, options.today, `${summary}<table class="cmp-matrix"><thead>${head}</thead><tbody>${rows}</tbody></table>`);
|
|
122
|
+
}
|
|
123
|
+
case 'law': {
|
|
124
|
+
const index = buildComplianceIndex({ requirements: canon.requirements, assertions: canon.assertions });
|
|
125
|
+
const tree = buildLawTree(scope.id, index);
|
|
126
|
+
const law = canon.codex.find(c => c.id === scope.id);
|
|
127
|
+
const title = options.title ?? `Compliance — ${law ? law.name : scope.id}`;
|
|
128
|
+
const summary = `<p class="cmp-summary"><code>${escHtml(scope.id)}</code> · ${tree.requirements.length} requirement(s)</p>`;
|
|
129
|
+
if (tree.requirements.length === 0) {
|
|
130
|
+
return htmlDoc(title, options.today, `${summary}<p class="cmp-empty">No requirements derive from <code>${escHtml(scope.id)}</code>.</p>`);
|
|
131
|
+
}
|
|
132
|
+
const blocks = tree.requirements.map(node => {
|
|
133
|
+
const sev = node.requirement.severity ? ` <span class="cmp-sev cmp-sev-${escHtml(node.requirement.severity)}">${escHtml(node.requirement.severity)}</span>` : '';
|
|
134
|
+
const head = `<div class="cmp-req-head"><span class="cmp-req-name">${escHtml(node.requirement.name)}</span><span class="cmp-req-id">${escHtml(node.requirement.id)}</span>${sev}</div>`;
|
|
135
|
+
if (node.assertions.length === 0) {
|
|
136
|
+
return `<section class="cmp-req">${head}<ul class="cmp-assertions"><li><em>No assertion — compliance gap.</em></li></ul></section>`;
|
|
137
|
+
}
|
|
138
|
+
const items = node.assertions.map(a => {
|
|
139
|
+
const metaParts = [];
|
|
140
|
+
if (a.assessed_at)
|
|
141
|
+
metaParts.push(`assessed ${escHtml(a.assessed_at)}`);
|
|
142
|
+
if (a.next_review_at)
|
|
143
|
+
metaParts.push(`review by ${escHtml(a.next_review_at)}`);
|
|
144
|
+
const meta = metaParts.length > 0 ? `<span class="cmp-meta">${metaParts.join(' · ')}</span>` : '';
|
|
145
|
+
return `<li>${badge(a.status)} <code>${escHtml(a.id)}</code> <span class="cmp-meta">subject <code>${escHtml(a.subject)}</code></span> ${meta}</li>`;
|
|
146
|
+
}).join('');
|
|
147
|
+
return `<section class="cmp-req">${head}<ul class="cmp-assertions">${items}</ul></section>`;
|
|
148
|
+
}).join('');
|
|
149
|
+
return htmlDoc(title, options.today, `${summary}${blocks}`);
|
|
150
|
+
}
|
|
151
|
+
case 'product': {
|
|
152
|
+
const index = buildComplianceIndex({ requirements: canon.requirements, assertions: canon.assertions });
|
|
153
|
+
const view = buildProductView(scope.id, index);
|
|
154
|
+
const product = canon.products.find(p => p.id === scope.id);
|
|
155
|
+
const title = options.title ?? `Compliance — ${product ? product.name : scope.id}`;
|
|
156
|
+
const summary = `<p class="cmp-summary"><code>${escHtml(scope.id)}</code> · ${view.requirements.length} requirement(s) asserted</p>`;
|
|
157
|
+
if (view.requirements.length === 0) {
|
|
158
|
+
return htmlDoc(title, options.today, `${summary}<p class="cmp-empty">No assertion names this product as its subject.</p>`);
|
|
159
|
+
}
|
|
160
|
+
const rows = view.requirements.map(({ requirement, assertion }) => (`<tr>` +
|
|
161
|
+
`<td>${escHtml(requirement.name)} <code>${escHtml(requirement.id)}</code></td>` +
|
|
162
|
+
`<td>${badge(assertion.status)}</td>` +
|
|
163
|
+
`<td><code>${escHtml(assertion.id)}</code></td>` +
|
|
164
|
+
`<td>${assertion.next_review_at ? escHtml(assertion.next_review_at) : '—'}</td>` +
|
|
165
|
+
`</tr>`)).join('');
|
|
166
|
+
const head = '<tr><th>Requirement</th><th>Status</th><th>Assertion</th><th>Next review</th></tr>';
|
|
167
|
+
return htmlDoc(title, options.today, `${summary}<table><thead>${head}</thead><tbody>${rows}</tbody></table>`);
|
|
168
|
+
}
|
|
169
|
+
case 'gap': {
|
|
170
|
+
const index = buildComplianceIndex({ requirements: canon.requirements, assertions: canon.assertions });
|
|
171
|
+
const report = buildGapReport(index, { today: options.today });
|
|
172
|
+
const title = options.title ?? 'Compliance Gap Dashboard';
|
|
173
|
+
const total = report.requirementsWithoutAssertions.length + report.assertionsWithoutEvidence.length + report.staleAssertions.length;
|
|
174
|
+
const summary = `<p class="cmp-summary">${total} gap(s)</p>`;
|
|
175
|
+
const section = (heading, count, items) => {
|
|
176
|
+
const body = items.length === 0
|
|
177
|
+
? '<p class="cmp-ok">✓ none</p>'
|
|
178
|
+
: `<ul class="cmp-rows">${items.join('')}</ul>`;
|
|
179
|
+
return `<section class="cmp-section"><h2>${escHtml(heading)} <span class="cmp-count">(${count})</span></h2>${body}</section>`;
|
|
180
|
+
};
|
|
181
|
+
const reqs = report.requirementsWithoutAssertions.map(r => (`<li><code>${escHtml(r.id)}</code> ${escHtml(r.name)}${r.severity ? ` <span class="cmp-meta">severity ${escHtml(r.severity)}</span>` : ''}${r.deadline ? ` <span class="cmp-meta">deadline ${escHtml(r.deadline)}</span>` : ''}</li>`));
|
|
182
|
+
const noEvidence = report.assertionsWithoutEvidence.map(a => (`<li><code>${escHtml(a.id)}</code> <span class="cmp-meta">about <code>${escHtml(a.about)}</code>, subject <code>${escHtml(a.subject)}</code>, status ${escHtml(a.status)}</span></li>`));
|
|
183
|
+
const stale = report.staleAssertions.map(a => (`<li><code>${escHtml(a.id)}</code> <span class="cmp-meta">review due ${a.next_review_at ? escHtml(a.next_review_at) : '—'}, subject <code>${escHtml(a.subject)}</code></span></li>`));
|
|
184
|
+
const pastDl = report.pastDeadlineRequirements.map(r => (`<li><code>${escHtml(r.id)}</code> ${escHtml(r.name)} <span class="cmp-meta">deadline ${r.deadline ? escHtml(r.deadline) : '—'}${r.severity ? `, severity ${escHtml(r.severity)}` : ''}</span></li>`));
|
|
185
|
+
const total4 = report.requirementsWithoutAssertions.length + report.assertionsWithoutEvidence.length + report.staleAssertions.length + report.pastDeadlineRequirements.length;
|
|
186
|
+
const body = [
|
|
187
|
+
`<p class="cmp-summary">${total4} gap(s) across 4 checks</p>`,
|
|
188
|
+
section('Requirements without assertions', report.requirementsWithoutAssertions.length, reqs),
|
|
189
|
+
section('Assertions without evidence — ASSERT-007', report.assertionsWithoutEvidence.length, noEvidence),
|
|
190
|
+
section('Stale assertions — ASSERT-008', report.staleAssertions.length, stale),
|
|
191
|
+
section('Past-deadline requirements (CV-5)', report.pastDeadlineRequirements.length, pastDl),
|
|
192
|
+
].join('');
|
|
193
|
+
return htmlDoc(title, options.today, body);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Renders an `ImpactMatrix` (from `buildImpactMatrix`) as a self-contained
|
|
199
|
+
* A4 HTML document suitable for WeasyPrint PDF output.
|
|
200
|
+
*
|
|
201
|
+
* Used by `cervin export-compliance --report <id> --format pdf`.
|
|
202
|
+
*/
|
|
203
|
+
export function renderImpactMatrixHtml(matrix, options = {}) {
|
|
204
|
+
const STATUS_GLYPH = {
|
|
205
|
+
compliant: 'OK', partial: 'PARTIAL', non_compliant: 'FAIL',
|
|
206
|
+
under_review: 'REVIEW', n_a: 'N/A',
|
|
207
|
+
};
|
|
208
|
+
const statusClass = (s) => s ?? 'gap';
|
|
209
|
+
const colHeaders = matrix.columns.map(c => `<th>${escHtml(c.label)}</th>`).join('');
|
|
210
|
+
const head = `<tr><th>Obligation</th>${colHeaders}</tr>`;
|
|
211
|
+
const rows = matrix.rows.map((req, ri) => {
|
|
212
|
+
const rowLabel = `${escHtml(req.id)}${req.name && req.name !== req.id ? ` — ${escHtml(req.name)}` : ''}`;
|
|
213
|
+
const cells = matrix.cells[ri].map(cell => {
|
|
214
|
+
if (cell.kind === 'gap')
|
|
215
|
+
return `<td class="cmp-gap">${escHtml(matrix.emptyLabels.no_obligation_label)}</td>`;
|
|
216
|
+
if (cell.kind === 'n_a_only')
|
|
217
|
+
return `<td class="cmp-na">${escHtml(matrix.emptyLabels.no_obligation_applies_label)}</td>`;
|
|
218
|
+
const glyph = STATUS_GLYPH[cell.status ?? ''] ?? String(cell.status);
|
|
219
|
+
return `<td class="cmp-${statusClass(cell.status)}">${escHtml(glyph)}</td>`;
|
|
220
|
+
}).join('');
|
|
221
|
+
const dlInfo = req.deadline ? ` <span class="cmp-dl">⚑ ${escHtml(req.deadline)}</span>` : '';
|
|
222
|
+
return `<tr><td class="cmp-row-label">${rowLabel}${dlInfo}</td>${cells}</tr>`;
|
|
223
|
+
}).join('');
|
|
224
|
+
const snapshotLine = matrix.snapshotAt ? `<span>Snapshot: ${escHtml(matrix.snapshotAt)}</span>` : '';
|
|
225
|
+
const desc = matrix.description ? `<p>${escHtml(matrix.description)}</p>` : '';
|
|
226
|
+
const extraCss = `
|
|
227
|
+
table { border-collapse: collapse; width: 100%; font-size: 9pt; }
|
|
228
|
+
th, td { border: 1px solid #cbd5e1; padding: 3pt 5pt; text-align: center; vertical-align: middle; }
|
|
229
|
+
td.cmp-row-label { text-align: left; font-size: 8.5pt; max-width: 180pt; white-space: normal; }
|
|
230
|
+
.cmp-compliant { background: #d1fae5; color: #065f46; font-weight: 700; }
|
|
231
|
+
.cmp-partial { background: #fef9c3; color: #854d0e; font-weight: 700; }
|
|
232
|
+
.cmp-non_compliant { background: #fee2e2; color: #991b1b; font-weight: 700; }
|
|
233
|
+
.cmp-under_review { background: #e0f2fe; color: #0c4a6e; }
|
|
234
|
+
.cmp-gap { background: #f8fafc; color: #94a3b8; font-size: 8pt; }
|
|
235
|
+
.cmp-na { background: #f1f5f9; color: #94a3b8; font-size: 8pt; }
|
|
236
|
+
.cmp-dl { color: #b45309; font-size: 8pt; }`;
|
|
237
|
+
return `<!DOCTYPE html>
|
|
238
|
+
<html lang="en">
|
|
239
|
+
<head>
|
|
240
|
+
<meta charset="UTF-8">
|
|
241
|
+
<style>
|
|
242
|
+
${CSS}
|
|
243
|
+
${extraCss}
|
|
244
|
+
</style>
|
|
245
|
+
</head>
|
|
246
|
+
<body>
|
|
247
|
+
<div class="cmp-header">
|
|
248
|
+
<div class="cmp-eyebrow">Compliance Impact Matrix</div>
|
|
249
|
+
<h1>${escHtml(matrix.viewName)}</h1>
|
|
250
|
+
<div class="cmp-stamp">View: <code>${escHtml(matrix.viewId)}</code> ${snapshotLine}${options.today ? ` · Generated: ${escHtml(options.today)}` : ''}</div>
|
|
251
|
+
</div>
|
|
252
|
+
${desc}
|
|
253
|
+
<table><thead>${head}</thead><tbody>${rows}</tbody></table>
|
|
254
|
+
</body>
|
|
255
|
+
</html>`;
|
|
256
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import type { AssertionStatus } from '../assertion/types.js';
|
|
2
|
+
import type { ComplianceCanon } from './classify.js';
|
|
3
|
+
import type { IndexAssertion, IndexRequirement, ObjectDetailInput, DeadlineStatus } from './types.js';
|
|
4
|
+
/** Filter selecting REQUIREMENTs by codex source (jurisdiction / regime keys
|
|
5
|
+
* are accepted for forward compatibility but not yet honoured — the canon
|
|
6
|
+
* projection does not carry those fields). */
|
|
7
|
+
export interface ImpactObligationFilter {
|
|
8
|
+
derived_from_codex?: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface ImpactSubjects {
|
|
11
|
+
products?: string[];
|
|
12
|
+
processes?: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface ImpactStatusDisplay {
|
|
15
|
+
show?: AssertionStatus[];
|
|
16
|
+
}
|
|
17
|
+
export interface ImpactEmptyCellLabels {
|
|
18
|
+
/** Label used when no admitted ASSERTION binds the cell (modelling gap). */
|
|
19
|
+
no_obligation_label?: string;
|
|
20
|
+
/** Label used when an admitted ASSERTION exists with status `n_a`
|
|
21
|
+
* (modelled fact: the obligation does not apply). */
|
|
22
|
+
no_obligation_applies_label?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A matrix column descriptor.
|
|
26
|
+
*
|
|
27
|
+
* At the coarsest grain (`grouping.columns: 'product'`) a column maps to a
|
|
28
|
+
* single subject: `{ subjectId, label: subjectId }`.
|
|
29
|
+
*
|
|
30
|
+
* At `grouping.columns: 'product-stage'` a column represents one (product,
|
|
31
|
+
* stage) pair: `{ subjectId: productId, stageId, label: productId + ':' + stageId }`.
|
|
32
|
+
* A cell is populated when an ASSERTION has `subject === subjectId` and
|
|
33
|
+
* `stageId ∈ assertion.realised_via` (or `realised_via` is absent, meaning
|
|
34
|
+
* the assertion covers the entire subject — it then contributes to every
|
|
35
|
+
* stage column for that subject).
|
|
36
|
+
*/
|
|
37
|
+
export interface ImpactColumn {
|
|
38
|
+
/** Subject (product / process / capability) the column belongs to. */
|
|
39
|
+
subjectId: string;
|
|
40
|
+
/** Stage ID — present only when grouping.columns is not 'product'. */
|
|
41
|
+
stageId?: string;
|
|
42
|
+
/** Human-readable column header. */
|
|
43
|
+
label: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Grouping options for matrix columns.
|
|
47
|
+
*
|
|
48
|
+
* `columns` controls the column grain:
|
|
49
|
+
* - `'product'` (default) — one column per subject.
|
|
50
|
+
* - `'product-stage'` — one column per (subject, stage) pair derived
|
|
51
|
+
* from `objectDetails` passed to `buildImpactMatrix`.
|
|
52
|
+
*/
|
|
53
|
+
export interface ImpactGrouping {
|
|
54
|
+
columns: 'object' | 'object-details';
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Named, versioned view-config — the report *definition*.
|
|
58
|
+
*
|
|
59
|
+
* A saved view config is the source of truth for a deterministic report run:
|
|
60
|
+
* given the same config + canon, `buildImpactMatrix` always produces the
|
|
61
|
+
* same matrix. Configs are stored in YAML files (top-level `view:` key) and
|
|
62
|
+
* referenced by `id`.
|
|
63
|
+
*
|
|
64
|
+
* `snapshot_at` (ISO 8601 date) records when the report was last generated.
|
|
65
|
+
* CV-3 blueprint-lane rendering uses it to mark obligations that appeared in
|
|
66
|
+
* the canon *after* the snapshot as "new" (dashed-border cell decoration).
|
|
67
|
+
*/
|
|
68
|
+
export interface ImpactViewConfig {
|
|
69
|
+
id: string;
|
|
70
|
+
name: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
/**
|
|
73
|
+
* ISO 8601 date of the last report snapshot (YYYY-MM-DD).
|
|
74
|
+
* Populated automatically by the CLI on each run and stored back to the
|
|
75
|
+
* view-config file, giving CV-3 its "new since last run" signal.
|
|
76
|
+
*/
|
|
77
|
+
snapshot_at?: string;
|
|
78
|
+
subjects: ImpactSubjects;
|
|
79
|
+
obligations: {
|
|
80
|
+
include?: string[];
|
|
81
|
+
filter?: ImpactObligationFilter;
|
|
82
|
+
};
|
|
83
|
+
status_display?: ImpactStatusDisplay;
|
|
84
|
+
empty_cells?: ImpactEmptyCellLabels;
|
|
85
|
+
order_rows_by?: 'id' | 'name';
|
|
86
|
+
/**
|
|
87
|
+
* Column grouping options. Omit (or set `columns: 'product'`) for the
|
|
88
|
+
* default single-column-per-subject behaviour. Set `columns: 'product-stage'`
|
|
89
|
+
* and pass `objectDetails` into `buildImpactMatrix` to expand each subject
|
|
90
|
+
* into per-stage sub-columns.
|
|
91
|
+
*/
|
|
92
|
+
grouping?: ImpactGrouping;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Explicit defaults for every optional field in ImpactViewConfig.
|
|
96
|
+
*
|
|
97
|
+
* When a view config omits a field, COMPLIANCE_IMPACT_DEFAULTS defines the
|
|
98
|
+
* assumed behaviour. The CLI prints these so re-runs without a full config
|
|
99
|
+
* are auditable ("what I assumed").
|
|
100
|
+
*/
|
|
101
|
+
export declare const COMPLIANCE_IMPACT_DEFAULTS: {
|
|
102
|
+
/** Accept all four active statuses + n_a in cell aggregation. */
|
|
103
|
+
readonly status_display: {
|
|
104
|
+
readonly show: AssertionStatus[];
|
|
105
|
+
};
|
|
106
|
+
/** Order rows by canonical REQUIREMENT ID (lexicographic). */
|
|
107
|
+
readonly order_rows_by: "id";
|
|
108
|
+
/** §5.3 empty-cell labels. */
|
|
109
|
+
readonly empty_cells: {
|
|
110
|
+
readonly no_obligation_label: "No mapped obligation (current model)";
|
|
111
|
+
readonly no_obligation_applies_label: "No obligation applies";
|
|
112
|
+
};
|
|
113
|
+
/** Obligation scope: all known REQUIREMENTs in the canon (no filter). */
|
|
114
|
+
readonly obligations: {
|
|
115
|
+
readonly include: string[] | undefined;
|
|
116
|
+
readonly filter: undefined;
|
|
117
|
+
};
|
|
118
|
+
/** Subjects: empty — must be supplied explicitly in the view config. */
|
|
119
|
+
readonly subjects: {
|
|
120
|
+
readonly products: string[];
|
|
121
|
+
readonly processes: string[];
|
|
122
|
+
};
|
|
123
|
+
/** Column grain: one column per business object (no stage decomposition). */
|
|
124
|
+
readonly grouping: {
|
|
125
|
+
readonly columns: "object";
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
export type ParseImpactViewConfigResult = {
|
|
129
|
+
ok: true;
|
|
130
|
+
config: ImpactViewConfig;
|
|
131
|
+
} | {
|
|
132
|
+
ok: false;
|
|
133
|
+
errors: string[];
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Validate and normalise a raw (YAML-parsed) value into an ImpactViewConfig.
|
|
137
|
+
*
|
|
138
|
+
* Accepts both the bare config object and the view-config file shape
|
|
139
|
+
* (`{ view: { id, name, … } }`) — the top-level `view:` wrapper is unwrapped
|
|
140
|
+
* automatically.
|
|
141
|
+
*
|
|
142
|
+
* Every optional field is filled from COMPLIANCE_IMPACT_DEFAULTS, so callers
|
|
143
|
+
* can rely on the returned config being complete without any `??` chains.
|
|
144
|
+
*
|
|
145
|
+
* Returns `{ ok: false, errors }` on schema violations rather than throwing,
|
|
146
|
+
* so the CLI can surface a clean error message without a stack trace.
|
|
147
|
+
*/
|
|
148
|
+
export declare function parseImpactViewConfig(raw: unknown): ParseImpactViewConfigResult;
|
|
149
|
+
/** A single cell of the rendered matrix. */
|
|
150
|
+
export interface ImpactCell {
|
|
151
|
+
/** Resolved status when an ASSERTION binds the cell, else null. */
|
|
152
|
+
status: AssertionStatus | null;
|
|
153
|
+
/** Empty-cell condition per §5.3 — one of:
|
|
154
|
+
* - `bound` : at least one admitted ASSERTION binds the cell; `status` is set.
|
|
155
|
+
* - `n_a_only`: every binding ASSERTION has status `n_a` (modelled fact).
|
|
156
|
+
* - `gap` : no admitted ASSERTION binds the cell (modelling gap). */
|
|
157
|
+
kind: 'bound' | 'n_a_only' | 'gap';
|
|
158
|
+
/** The assertions that contributed to this cell, id-sorted. */
|
|
159
|
+
assertions: IndexAssertion[];
|
|
160
|
+
/**
|
|
161
|
+
* CV-3 blueprint-lane decorations.
|
|
162
|
+
*
|
|
163
|
+
* `isNew` — the row's REQUIREMENT was admitted after the report
|
|
164
|
+
* `snapshot_at` date (dashed-border decoration).
|
|
165
|
+
* `isUrgent` — the cell is a gap AND the requirement has a deadline
|
|
166
|
+
* whose temporal status is `past_due` or `in_force`.
|
|
167
|
+
* `deadlineStatus` — temporal distance to the deadline (or `'none'`).
|
|
168
|
+
*/
|
|
169
|
+
decoration: {
|
|
170
|
+
isNew: boolean;
|
|
171
|
+
isUrgent: boolean;
|
|
172
|
+
deadlineStatus: DeadlineStatus;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
export interface ImpactMatrix {
|
|
176
|
+
viewId: string;
|
|
177
|
+
viewName: string;
|
|
178
|
+
description?: string;
|
|
179
|
+
/**
|
|
180
|
+
* ISO 8601 date of the last report snapshot, copied from the view config.
|
|
181
|
+
* CV-3 blueprint-lane rendering uses this to flag obligations that appeared
|
|
182
|
+
* after the snapshot as "new" (dashed-border cell decoration).
|
|
183
|
+
*/
|
|
184
|
+
snapshotAt?: string;
|
|
185
|
+
/** Row dimension — REQUIREMENT projections, in the configured order. */
|
|
186
|
+
rows: IndexRequirement[];
|
|
187
|
+
/**
|
|
188
|
+
* Column dimension.
|
|
189
|
+
*
|
|
190
|
+
* At `grouping.columns: 'product'` (default) each entry has only `subjectId`
|
|
191
|
+
* and `label`. At `'product-stage'` entries additionally carry `stageId`.
|
|
192
|
+
*/
|
|
193
|
+
columns: ImpactColumn[];
|
|
194
|
+
/** Cells, indexed as `cell[rowIdx][colIdx]`. */
|
|
195
|
+
cells: ImpactCell[][];
|
|
196
|
+
/** Canonical empty-cell labels actually used (after defaults applied). */
|
|
197
|
+
emptyLabels: Required<ImpactEmptyCellLabels>;
|
|
198
|
+
/**
|
|
199
|
+
* CV-3 derived obligations lane.
|
|
200
|
+
*
|
|
201
|
+
* For each column, the set of codex source IDs (`REQUIREMENT.derived_from`)
|
|
202
|
+
* that appear in at least one non-gap cell in that column. Renderers use
|
|
203
|
+
* this to display a "laws lane" header above or below the matrix columns.
|
|
204
|
+
* Empty array when no requirement in the column has a `derived_from`.
|
|
205
|
+
*/
|
|
206
|
+
obligationsLane: string[][];
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Classify a REQUIREMENT deadline relative to a reference date.
|
|
210
|
+
*
|
|
211
|
+
* @param deadline ISO 8601 date string (YYYY-MM-DD), or undefined.
|
|
212
|
+
* @param today Reference date string (YYYY-MM-DD); defaults to today.
|
|
213
|
+
*/
|
|
214
|
+
export declare function computeDeadlineStatus(deadline: string | undefined, today?: string): DeadlineStatus;
|
|
215
|
+
/**
|
|
216
|
+
* Build the matrix per §5.2.
|
|
217
|
+
*
|
|
218
|
+
* At the default `grouping.columns: 'product'` grain, one column per subject.
|
|
219
|
+
* At `grouping.columns: 'product-stage'`, pass `objectDetails` to expand each
|
|
220
|
+
* subject into per-stage sub-columns (typically extracted from a
|
|
221
|
+
* process-blueprint document via `extractObjectDetails`). Subjects with no
|
|
222
|
+
* stage mapping fall back to a single product-grain column automatically.
|
|
223
|
+
*
|
|
224
|
+
* Subjects are taken from `config.subjects.products` and
|
|
225
|
+
* `config.subjects.processes` (in that order). Subjects with no binding
|
|
226
|
+
* obligation still appear as columns so the gap is visible.
|
|
227
|
+
*/
|
|
228
|
+
export declare function buildImpactMatrix(canon: ComplianceCanon, config: ImpactViewConfig, objectDetails?: ObjectDetailInput[]): ImpactMatrix;
|
|
229
|
+
/**
|
|
230
|
+
* Extract `ObjectDetailInput` from a raw (YAML-parsed) process-blueprint document.
|
|
231
|
+
*
|
|
232
|
+
* Accepts both the bare document object and the wrapped form
|
|
233
|
+
* (`{ process_blueprint: { id, stages: […] } }`).
|
|
234
|
+
* Returns `null` when the document is not a recognisable process-blueprint or
|
|
235
|
+
* has no `id` / `stages` array so callers can skip unrecognised files safely.
|
|
236
|
+
*
|
|
237
|
+
* Pass the returned value into `buildImpactMatrix` as part of the
|
|
238
|
+
* `objectDetails` array when `grouping.columns: 'product-stage'` is configured.
|
|
239
|
+
*/
|
|
240
|
+
export declare function extractObjectDetails(doc: unknown): ObjectDetailInput | null;
|
|
241
|
+
/**
|
|
242
|
+
* Render the matrix as a GitHub-flavoured markdown table.
|
|
243
|
+
*
|
|
244
|
+
* Cell display:
|
|
245
|
+
* - `bound` → the §5.2 deterministic status label.
|
|
246
|
+
* - `n_a_only` → the "No obligation applies" label (or `view.empty_cells`
|
|
247
|
+
* override).
|
|
248
|
+
* - `gap` → the "No mapped obligation (current model)" label (or
|
|
249
|
+
* override).
|
|
250
|
+
*/
|
|
251
|
+
export declare function renderImpactMarkdown(matrix: ImpactMatrix): string;
|