@transitrix/diagrams 1.0.0 → 1.1.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 -21
- package/README.md +47 -47
- package/dist/__tests__/edge-path.test.js +8 -0
- package/dist/activities/cpm.js +11 -2
- package/dist/activities/gantt.js +6 -3
- package/dist/activities/types.d.ts +1 -0
- package/dist/activities/validate.js +3 -3
- package/dist/activity-card/__tests__/example.test.js +20 -1
- package/dist/activity-card/__tests__/layout.test.js +102 -11
- package/dist/activity-card/__tests__/resolver.test.js +161 -7
- package/dist/activity-card/index.d.ts +1 -1
- package/dist/activity-card/layout.d.ts +1 -1
- package/dist/activity-card/layout.js +220 -103
- package/dist/activity-card/resolver.js +115 -28
- package/dist/activity-card/types.d.ts +150 -27
- package/dist/activity-card/validate.js +3 -0
- package/dist/actor/__tests__/validate.test.js +63 -31
- package/dist/actor/index.d.ts +1 -1
- package/dist/actor/index.js +1 -1
- package/dist/actor/types.d.ts +7 -3
- package/dist/actor/types.js +17 -3
- package/dist/actor/validate.js +55 -26
- package/dist/assertion/types.d.ts +3 -1
- package/dist/assertion/types.js +1 -1
- package/dist/change/__tests__/validate.test.js +40 -34
- package/dist/change/index.d.ts +1 -0
- package/dist/change/types.d.ts +1 -1
- package/dist/change/types.js +2 -2
- package/dist/change/validate.d.ts +6 -1
- package/dist/change/validate.js +68 -41
- package/dist/compliance/__tests__/classify.test.js +34 -0
- package/dist/compliance/__tests__/coverage-metric.test.js +146 -46
- package/dist/compliance/__tests__/html.test.js +2 -2
- package/dist/compliance/__tests__/impact.test.js +509 -6
- package/dist/compliance/classify.d.ts +6 -0
- package/dist/compliance/classify.js +9 -1
- package/dist/compliance/coverage-metric.d.ts +31 -11
- package/dist/compliance/coverage-metric.js +149 -39
- package/dist/compliance/html.js +78 -81
- package/dist/compliance/impact.d.ts +100 -16
- package/dist/compliance/impact.js +272 -28
- package/dist/compliance/index.d.ts +2 -2
- package/dist/compliance/index.js +1 -1
- package/dist/compliance/markdown.js +1 -0
- package/dist/compliance/types.d.ts +25 -6
- package/dist/edge-path.d.ts +8 -4
- package/dist/edge-path.js +11 -6
- package/dist/factor/__tests__/validate.test.js +75 -46
- package/dist/factor/index.d.ts +3 -2
- package/dist/factor/index.js +1 -1
- package/dist/factor/types.d.ts +5 -8
- package/dist/factor/types.js +10 -5
- package/dist/factor/validate.d.ts +6 -1
- package/dist/factor/validate.js +68 -50
- package/dist/fgca/__tests__/chain-table.test.js +2 -2
- package/dist/fgca/__tests__/layout.test.js +11 -11
- package/dist/fgca/__tests__/preview-layout.test.js +7 -7
- package/dist/fgca/__tests__/resolver.test.js +185 -0
- package/dist/fgca/chain-table.d.ts +1 -1
- package/dist/fgca/chain-table.js +4 -4
- package/dist/fgca/index.d.ts +4 -2
- package/dist/fgca/index.js +2 -1
- package/dist/fgca/layout.d.ts +2 -2
- package/dist/fgca/layout.js +9 -9
- package/dist/fgca/nodeTypes.d.ts +1 -1
- package/dist/fgca/nodeTypes.js +2 -2
- package/dist/fgca/nodes/FGCAFactorNode.d.ts +3 -3
- package/dist/fgca/nodes/FGCAFactorNode.js +5 -5
- package/dist/fgca/parse-canonical.js +15 -10
- package/dist/fgca/preview-layout.d.ts +1 -1
- package/dist/fgca/preview-layout.js +4 -4
- package/dist/fgca/resolver.d.ts +49 -0
- package/dist/fgca/resolver.js +126 -0
- package/dist/fgca/types.d.ts +11 -11
- package/dist/fgca/types.js +2 -2
- package/dist/fgca/validate.d.ts +2 -2
- package/dist/fgca/validate.js +17 -14
- package/dist/goals/index.d.ts +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/process-blueprint/__tests__/layout.test.js +37 -0
- package/dist/process-blueprint/index.d.ts +1 -1
- package/dist/process-blueprint/layout.js +66 -35
- package/dist/process-blueprint/types.d.ts +36 -1
- package/dist/scenarios/index.d.ts +1 -1
- package/dist/scenarios/types.d.ts +4 -4
- package/dist/stakeholder/__tests__/validate.test.js +49 -47
- package/dist/stakeholder/index.d.ts +1 -0
- package/dist/stakeholder/types.d.ts +3 -4
- package/dist/stakeholder/types.js +2 -3
- package/dist/stakeholder/validate.d.ts +6 -1
- package/dist/stakeholder/validate.js +71 -50
- package/dist/target-state/__tests__/validate.test.js +43 -27
- package/dist/target-state/index.d.ts +2 -0
- package/dist/target-state/index.js +1 -0
- package/dist/target-state/types.d.ts +6 -1
- package/dist/target-state/types.js +8 -7
- package/dist/target-state/validate.d.ts +6 -1
- package/dist/target-state/validate.js +69 -45
- package/dist/theme/themes.js +71 -69
- package/dist/theme/tokens.d.ts +7 -1
- package/dist/theme/tokens.js +3 -1
- package/dist/webview/__tests__/entry-notations.test.js +2 -0
- package/dist/webview/__tests__/entry.test.js +11 -11
- package/dist/webview/__tests__/render-process.test.js +463 -0
- package/dist/webview/__tests__/render-util.test.d.ts +1 -0
- package/dist/webview/__tests__/render-util.test.js +54 -0
- package/dist/webview/entry.d.ts +1 -1
- package/dist/webview/entry.js +9 -5
- package/dist/webview/render-activities.d.ts +24 -2
- package/dist/webview/render-activities.js +92 -57
- package/dist/webview/render-activity-card.d.ts +11 -1
- package/dist/webview/render-activity-card.js +115 -79
- package/dist/webview/render-blocks.d.ts +24 -1
- package/dist/webview/render-blocks.js +58 -24
- package/dist/webview/render-fgca.d.ts +31 -0
- package/dist/webview/render-fgca.js +30 -19
- package/dist/webview/render-goals.d.ts +27 -1
- package/dist/webview/render-goals.js +42 -32
- package/dist/webview/render-process-blueprint.d.ts +11 -1
- package/dist/webview/render-process-blueprint.js +118 -53
- package/dist/webview/render-process.d.ts +95 -0
- package/dist/webview/render-process.js +392 -0
- package/dist/webview/render-scenarios.js +2 -2
- package/dist/webview/render-util.d.ts +19 -6
- package/dist/webview/render-util.js +23 -15
- package/package.json +54 -40
- package/src/__tests__/edge-path.test.ts +58 -46
- package/src/__tests__/scope.test.ts +27 -27
- package/src/__tests__/yaml-normalize.test.ts +158 -158
- package/src/activities/__tests__/cpm.test.ts +164 -164
- package/src/activities/__tests__/gantt.test.ts +245 -245
- package/src/activities/__tests__/layout.test.ts +112 -112
- package/src/activities/__tests__/validate.test.ts +409 -409
- package/src/activities/cpm.ts +107 -95
- package/src/activities/gantt.ts +277 -276
- package/src/activities/index.ts +28 -28
- package/src/activities/layout.ts +112 -112
- package/src/activities/types.ts +149 -148
- package/src/activities/validate.ts +357 -357
- package/src/activity-card/__tests__/example.test.ts +85 -66
- package/src/activity-card/__tests__/layout.test.ts +169 -63
- package/src/activity-card/__tests__/resolver.test.ts +330 -161
- package/src/activity-card/__tests__/validate.test.ts +131 -131
- package/src/activity-card/index.ts +38 -32
- package/src/activity-card/layout.ts +324 -194
- package/src/activity-card/resolver.ts +422 -337
- package/src/activity-card/types.ts +376 -237
- package/src/activity-card/validate.ts +162 -158
- package/src/actor/__tests__/validate.test.ts +70 -31
- package/src/actor/index.ts +1 -1
- package/src/actor/types.ts +21 -7
- package/src/actor/validate.ts +59 -27
- package/src/applications/__tests__/validate.test.ts +256 -256
- package/src/applications/index.ts +11 -11
- package/src/applications/types.ts +43 -43
- package/src/applications/validate.ts +131 -131
- package/src/assertion/__tests__/example.test.ts +37 -37
- package/src/assertion/__tests__/validate.test.ts +142 -142
- package/src/assertion/index.ts +12 -12
- package/src/assertion/types.ts +60 -58
- package/src/assertion/validate.ts +145 -145
- package/src/blocks/__tests__/layout.test.ts +169 -169
- package/src/blocks/__tests__/validate.test.ts +260 -260
- package/src/blocks/index.ts +17 -17
- package/src/blocks/layout.ts +186 -186
- package/src/blocks/types.ts +62 -62
- package/src/blocks/validate.ts +206 -206
- package/src/capability-map/__tests__/validate.test.ts +238 -238
- package/src/capability-map/index.ts +8 -8
- package/src/capability-map/types.ts +29 -29
- package/src/capability-map/validate.ts +127 -127
- package/src/change/__tests__/validate.test.ts +43 -34
- package/src/change/index.ts +1 -0
- package/src/change/types.ts +5 -3
- package/src/change/validate.ts +75 -43
- package/src/compliance/__tests__/classify.test.ts +64 -27
- package/src/compliance/__tests__/confidence.test.ts +98 -98
- package/src/compliance/__tests__/coverage-metric.test.ts +300 -188
- package/src/compliance/__tests__/demo-scenario.test.ts +273 -273
- package/src/compliance/__tests__/example.test.ts +57 -57
- package/src/compliance/__tests__/gap-report.test.ts +128 -128
- package/src/compliance/__tests__/html.test.ts +141 -141
- package/src/compliance/__tests__/impact.test.ts +1059 -481
- package/src/compliance/__tests__/markdown.test.ts +94 -94
- package/src/compliance/__tests__/views.test.ts +64 -64
- package/src/compliance/classify.ts +100 -84
- package/src/compliance/confidence.ts +69 -69
- package/src/compliance/coverage-metric.ts +404 -263
- package/src/compliance/gap-report.ts +94 -94
- package/src/compliance/html.ts +291 -295
- package/src/compliance/impact.ts +979 -677
- package/src/compliance/index.ts +57 -56
- package/src/compliance/markdown.ts +136 -135
- package/src/compliance/reverse-index.ts +33 -33
- package/src/compliance/types.ts +136 -120
- package/src/compliance/views.ts +46 -46
- package/src/compliance-matrix/__tests__/build.test.ts +200 -200
- package/src/compliance-matrix/__tests__/example.test.ts +57 -57
- package/src/compliance-matrix/index.ts +11 -11
- package/src/compliance-matrix/types.ts +102 -102
- package/src/edge-path.ts +50 -44
- package/src/factor/__tests__/validate.test.ts +81 -46
- package/src/factor/index.ts +3 -7
- package/src/factor/types.ts +15 -19
- package/src/factor/validate.ts +77 -51
- package/src/fgca/__tests__/chain-table.test.ts +172 -172
- package/src/fgca/__tests__/layout.test.ts +179 -179
- package/src/fgca/__tests__/parse-canonical.test.ts +248 -248
- package/src/fgca/__tests__/preview-layout.test.ts +124 -124
- package/src/fgca/__tests__/resolver.test.ts +209 -0
- package/src/fgca/__tests__/validate.test.ts +142 -142
- package/src/fgca/chain-table.ts +225 -225
- package/src/fgca/index.ts +47 -45
- package/src/fgca/layout.ts +204 -204
- package/src/fgca/nodeTypes.ts +11 -11
- package/src/fgca/nodes/FGCAActivityNode.tsx +65 -65
- package/src/fgca/nodes/FGCAChangeNode.tsx +64 -64
- package/src/fgca/nodes/FGCAFactorNode.tsx +64 -64
- package/src/fgca/nodes/FGCAGoalNode.tsx +72 -72
- package/src/fgca/parse-canonical.ts +405 -400
- package/src/fgca/preview-layout.ts +217 -217
- package/src/fgca/resolver.ts +159 -0
- package/src/fgca/types.ts +50 -50
- package/src/fgca/validate.ts +129 -126
- package/src/geometry.ts +9 -9
- package/src/goals/__tests__/layout.test.ts +175 -175
- package/src/goals/__tests__/mutations.test.ts +111 -111
- package/src/goals/__tests__/parse-canonical.test.ts +145 -145
- package/src/goals/__tests__/validate.test.ts +202 -202
- package/src/goals/index.ts +20 -21
- package/src/goals/layout.ts +172 -172
- package/src/goals/mutations.ts +123 -123
- package/src/goals/parse-canonical.ts +286 -286
- package/src/goals/types.ts +85 -85
- package/src/goals/validate.ts +136 -136
- package/src/index.ts +28 -23
- package/src/process-blueprint/__tests__/compliance-lane.test.ts +320 -320
- package/src/process-blueprint/__tests__/layout.test.ts +240 -195
- package/src/process-blueprint/__tests__/validate.test.ts +310 -310
- package/src/process-blueprint/index.ts +32 -31
- package/src/process-blueprint/layout.ts +564 -531
- package/src/process-blueprint/types.ts +278 -242
- package/src/process-blueprint/validate.ts +181 -181
- package/src/process-map/__tests__/validate.test.ts +223 -223
- package/src/process-map/index.ts +10 -10
- package/src/process-map/types.ts +36 -36
- package/src/process-map/validate.ts +135 -135
- package/src/products/__tests__/validate.test.ts +239 -239
- package/src/products/index.ts +9 -9
- package/src/products/types.ts +31 -31
- package/src/products/validate.ts +112 -112
- package/src/repo-validate/__tests__/validate-repo.test.ts +149 -149
- package/src/repo-validate/index.ts +2 -2
- package/src/repo-validate/types.ts +50 -50
- package/src/repo-validate/validate-repo.ts +196 -196
- package/src/requirement/__tests__/example.test.ts +24 -24
- package/src/requirement/__tests__/validate.test.ts +96 -96
- package/src/requirement/index.ts +4 -4
- package/src/requirement/types.ts +35 -35
- package/src/requirement/validate.ts +92 -92
- package/src/scenarios/__tests__/validate.test.ts +209 -209
- package/src/scenarios/index.ts +15 -15
- package/src/scenarios/types.ts +37 -37
- package/src/scenarios/validate.ts +122 -122
- package/src/schema-version.ts +16 -16
- package/src/scope.ts +46 -46
- package/src/stakeholder/__tests__/validate.test.ts +51 -47
- package/src/stakeholder/index.ts +1 -0
- package/src/stakeholder/types.ts +7 -7
- package/src/stakeholder/validate.ts +79 -52
- package/src/target-state/__tests__/validate.test.ts +48 -27
- package/src/target-state/index.ts +2 -0
- package/src/target-state/types.ts +11 -7
- package/src/target-state/validate.ts +76 -46
- package/src/theme/index.ts +4 -4
- package/src/theme/themes.ts +239 -237
- package/src/theme/tokens.ts +135 -133
- package/src/typed-id.ts +56 -56
- package/src/validation-types.ts +36 -36
- package/src/webview/__tests__/entry-notations.test.ts +79 -77
- package/src/webview/__tests__/entry.test.ts +64 -64
- package/src/webview/__tests__/render-goals.test.ts +72 -72
- package/src/webview/__tests__/render-process.test.ts +538 -0
- package/src/webview/__tests__/render-util.test.ts +66 -0
- package/src/webview/entry.ts +298 -292
- package/src/webview/render-activities.ts +111 -69
- package/src/webview/render-activity-card.ts +275 -234
- package/src/webview/render-blocks.ts +78 -28
- package/src/webview/render-fgca.ts +53 -28
- package/src/webview/render-goals.ts +133 -110
- package/src/webview/render-process-blueprint.ts +281 -207
- package/src/webview/render-process.ts +507 -0
- package/src/webview/render-scenarios.ts +3 -3
- package/src/webview/render-util.ts +27 -14
- package/src/webview/styles.css +322 -323
- package/src/yaml-normalize.ts +56 -56
- package/dist/element-envelope.d.ts +0 -15
- package/dist/element-envelope.js +0 -55
- package/dist/issues/__tests__/layout.test.js +0 -62
- package/dist/issues/__tests__/validate.test.js +0 -82
- package/dist/issues/index.d.ts +0 -4
- package/dist/issues/index.js +0 -2
- package/dist/issues/layout.d.ts +0 -10
- package/dist/issues/layout.js +0 -82
- package/dist/issues/types.d.ts +0 -61
- package/dist/issues/types.js +0 -6
- package/dist/issues/validate.d.ts +0 -3
- package/dist/issues/validate.js +0 -143
- package/dist/webview/transitrix-render.css +0 -323
- package/dist/webview/transitrix-render.js +0 -6452
- package/dist/webview/transitrix-render.js.map +0 -7
- package/src/element-envelope.ts +0 -76
- /package/dist/{issues/__tests__/layout.test.d.ts → fgca/__tests__/resolver.test.d.ts} +0 -0
- /package/dist/{issues/__tests__/validate.test.d.ts → webview/__tests__/render-process.test.d.ts} +0 -0
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
// Compliance matrix model (vkgeorgia/strategy#84 Phase 2).
|
|
2
|
-
//
|
|
3
|
-
// The matrix is Products × Requirements. Each cell is the status of the
|
|
4
|
-
// (Product, Requirement) ASSERTION when one exists, or a gap when none does.
|
|
5
|
-
// Pure data — the layout is computed by `build.ts`; the Studio preview renders
|
|
6
|
-
// it. Non-product-subject assertions (CAPABILITY / PROCESS) belong to the
|
|
7
|
-
// single-product / single-law views (Phase 3) and are ignored here.
|
|
8
|
-
|
|
9
|
-
import type { AssertionStatus } from '../assertion/types.js';
|
|
10
|
-
|
|
11
|
-
/** A row of the matrix — a discovered PRODUCT element. */
|
|
12
|
-
export interface MatrixProduct {
|
|
13
|
-
id: string;
|
|
14
|
-
name: string;
|
|
15
|
-
/** True when the product was discovered only as an assertion subject (no
|
|
16
|
-
* product element file resolves it) — a dangling subject reference. */
|
|
17
|
-
unresolved?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** A column of the matrix — a discovered REQUIREMENT. */
|
|
21
|
-
export interface MatrixRequirement {
|
|
22
|
-
id: string;
|
|
23
|
-
name: string;
|
|
24
|
-
/** Organisation-defined priority (high | medium | low), used by the filter. */
|
|
25
|
-
severity?: string;
|
|
26
|
-
/** Typed IDs of the codex sources this requirement derives from (verbatim
|
|
27
|
-
* from `derived_from`). Carried so the renderer can surface provenance and
|
|
28
|
-
* resolve jurisdictions without re-scanning. */
|
|
29
|
-
derived_from?: string[];
|
|
30
|
-
/** Jurisdictions resolved by walking `derived_from` → codex artefacts and
|
|
31
|
-
* collecting their `jurisdiction` (Codex §1.1). Unique, sorted. Empty when
|
|
32
|
-
* no codex source resolves with a jurisdiction (internal-only requirements,
|
|
33
|
-
* or codex artefacts the scan did not find / has no jurisdiction). The
|
|
34
|
-
* toolbar jurisdiction filter (F16) keys on this set. */
|
|
35
|
-
jurisdictions?: string[];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** A codex source document the matrix uses to resolve `Requirement.jurisdictions`. */
|
|
39
|
-
export interface MatrixCodexDoc {
|
|
40
|
-
id: string;
|
|
41
|
-
jurisdiction?: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** The assertion fields the matrix needs (a projection of the full Assertion). */
|
|
45
|
-
export interface MatrixAssertionRef {
|
|
46
|
-
id: string;
|
|
47
|
-
about: string;
|
|
48
|
-
subject: string;
|
|
49
|
-
status: AssertionStatus;
|
|
50
|
-
assessed_at?: string;
|
|
51
|
-
next_review_at?: string;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** One grid cell. `status === undefined` is a gap (no assertion for the pair). */
|
|
55
|
-
export interface MatrixCell {
|
|
56
|
-
productId: string;
|
|
57
|
-
requirementId: string;
|
|
58
|
-
/** The assertion filling this cell, when one exists. */
|
|
59
|
-
assertionId?: string;
|
|
60
|
-
status?: AssertionStatus;
|
|
61
|
-
assessed_at?: string;
|
|
62
|
-
next_review_at?: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface ComplianceMatrix {
|
|
66
|
-
/** Rows, sorted by id. */
|
|
67
|
-
products: MatrixProduct[];
|
|
68
|
-
/** Columns, sorted by id. */
|
|
69
|
-
requirements: MatrixRequirement[];
|
|
70
|
-
/** `cells[rowIndex][colIndex]`, aligned to `products` × `requirements`. */
|
|
71
|
-
cells: MatrixCell[][];
|
|
72
|
-
/** Counts for the summary strip. */
|
|
73
|
-
summary: {
|
|
74
|
-
products: number;
|
|
75
|
-
requirements: number;
|
|
76
|
-
assertions: number;
|
|
77
|
-
/** Cells with no assertion (compliance gaps). */
|
|
78
|
-
gaps: number;
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface ComplianceMatrixInput {
|
|
83
|
-
products: MatrixProduct[];
|
|
84
|
-
requirements: MatrixRequirement[];
|
|
85
|
-
assertions: MatrixAssertionRef[];
|
|
86
|
-
/** Codex source documents — used to resolve each Requirement's jurisdictions
|
|
87
|
-
* by walking `derived_from`. Optional: when omitted the builder still works
|
|
88
|
-
* and every requirement's `jurisdictions` is left empty. */
|
|
89
|
-
codex?: MatrixCodexDoc[];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Toolbar filter — empty/omitted fields mean "no filter on that dimension". */
|
|
93
|
-
export interface MatrixFilter {
|
|
94
|
-
/** Keep only requirement columns whose severity is in this set. */
|
|
95
|
-
severities?: string[];
|
|
96
|
-
/** Keep only the cell status badges in this set; others render as filtered. */
|
|
97
|
-
statuses?: AssertionStatus[];
|
|
98
|
-
/** Keep only requirement columns whose resolved jurisdictions intersect this
|
|
99
|
-
* set. Requirements with no resolved jurisdiction are filtered out when this
|
|
100
|
-
* is non-empty (F16, epic #84). */
|
|
101
|
-
jurisdictions?: string[];
|
|
102
|
-
}
|
|
1
|
+
// Compliance matrix model (vkgeorgia/strategy#84 Phase 2).
|
|
2
|
+
//
|
|
3
|
+
// The matrix is Products × Requirements. Each cell is the status of the
|
|
4
|
+
// (Product, Requirement) ASSERTION when one exists, or a gap when none does.
|
|
5
|
+
// Pure data — the layout is computed by `build.ts`; the Studio preview renders
|
|
6
|
+
// it. Non-product-subject assertions (CAPABILITY / PROCESS) belong to the
|
|
7
|
+
// single-product / single-law views (Phase 3) and are ignored here.
|
|
8
|
+
|
|
9
|
+
import type { AssertionStatus } from '../assertion/types.js';
|
|
10
|
+
|
|
11
|
+
/** A row of the matrix — a discovered PRODUCT element. */
|
|
12
|
+
export interface MatrixProduct {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
/** True when the product was discovered only as an assertion subject (no
|
|
16
|
+
* product element file resolves it) — a dangling subject reference. */
|
|
17
|
+
unresolved?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** A column of the matrix — a discovered REQUIREMENT. */
|
|
21
|
+
export interface MatrixRequirement {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
/** Organisation-defined priority (high | medium | low), used by the filter. */
|
|
25
|
+
severity?: string;
|
|
26
|
+
/** Typed IDs of the codex sources this requirement derives from (verbatim
|
|
27
|
+
* from `derived_from`). Carried so the renderer can surface provenance and
|
|
28
|
+
* resolve jurisdictions without re-scanning. */
|
|
29
|
+
derived_from?: string[];
|
|
30
|
+
/** Jurisdictions resolved by walking `derived_from` → codex artefacts and
|
|
31
|
+
* collecting their `jurisdiction` (Codex §1.1). Unique, sorted. Empty when
|
|
32
|
+
* no codex source resolves with a jurisdiction (internal-only requirements,
|
|
33
|
+
* or codex artefacts the scan did not find / has no jurisdiction). The
|
|
34
|
+
* toolbar jurisdiction filter (F16) keys on this set. */
|
|
35
|
+
jurisdictions?: string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A codex source document the matrix uses to resolve `Requirement.jurisdictions`. */
|
|
39
|
+
export interface MatrixCodexDoc {
|
|
40
|
+
id: string;
|
|
41
|
+
jurisdiction?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The assertion fields the matrix needs (a projection of the full Assertion). */
|
|
45
|
+
export interface MatrixAssertionRef {
|
|
46
|
+
id: string;
|
|
47
|
+
about: string;
|
|
48
|
+
subject: string;
|
|
49
|
+
status: AssertionStatus;
|
|
50
|
+
assessed_at?: string;
|
|
51
|
+
next_review_at?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** One grid cell. `status === undefined` is a gap (no assertion for the pair). */
|
|
55
|
+
export interface MatrixCell {
|
|
56
|
+
productId: string;
|
|
57
|
+
requirementId: string;
|
|
58
|
+
/** The assertion filling this cell, when one exists. */
|
|
59
|
+
assertionId?: string;
|
|
60
|
+
status?: AssertionStatus;
|
|
61
|
+
assessed_at?: string;
|
|
62
|
+
next_review_at?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface ComplianceMatrix {
|
|
66
|
+
/** Rows, sorted by id. */
|
|
67
|
+
products: MatrixProduct[];
|
|
68
|
+
/** Columns, sorted by id. */
|
|
69
|
+
requirements: MatrixRequirement[];
|
|
70
|
+
/** `cells[rowIndex][colIndex]`, aligned to `products` × `requirements`. */
|
|
71
|
+
cells: MatrixCell[][];
|
|
72
|
+
/** Counts for the summary strip. */
|
|
73
|
+
summary: {
|
|
74
|
+
products: number;
|
|
75
|
+
requirements: number;
|
|
76
|
+
assertions: number;
|
|
77
|
+
/** Cells with no assertion (compliance gaps). */
|
|
78
|
+
gaps: number;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ComplianceMatrixInput {
|
|
83
|
+
products: MatrixProduct[];
|
|
84
|
+
requirements: MatrixRequirement[];
|
|
85
|
+
assertions: MatrixAssertionRef[];
|
|
86
|
+
/** Codex source documents — used to resolve each Requirement's jurisdictions
|
|
87
|
+
* by walking `derived_from`. Optional: when omitted the builder still works
|
|
88
|
+
* and every requirement's `jurisdictions` is left empty. */
|
|
89
|
+
codex?: MatrixCodexDoc[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Toolbar filter — empty/omitted fields mean "no filter on that dimension". */
|
|
93
|
+
export interface MatrixFilter {
|
|
94
|
+
/** Keep only requirement columns whose severity is in this set. */
|
|
95
|
+
severities?: string[];
|
|
96
|
+
/** Keep only the cell status badges in this set; others render as filtered. */
|
|
97
|
+
statuses?: AssertionStatus[];
|
|
98
|
+
/** Keep only requirement columns whose resolved jurisdictions intersect this
|
|
99
|
+
* set. Requirements with no resolved jurisdiction are filtered out when this
|
|
100
|
+
* is non-empty (F16, epic #84). */
|
|
101
|
+
jurisdictions?: string[];
|
|
102
|
+
}
|
package/src/edge-path.ts
CHANGED
|
@@ -1,44 +1,50 @@
|
|
|
1
|
-
// Shared edge geometry for the static notation previews (Goals, FGCA, FGA,
|
|
2
|
-
// Activities). All four render dependency/relationship edges as a single cubic
|
|
3
|
-
// Bézier with horizontal control handles: each control point shares its
|
|
4
|
-
// endpoint's Y, so the tangent is horizontal at both ends and the marker-end
|
|
5
|
-
// arrow reads as perpendicular to the node's vertical edge.
|
|
6
|
-
//
|
|
7
|
-
// Pulling the path math here (rather than duplicating it inline in each
|
|
8
|
-
// preview) makes the configurable-curvature behaviour (vkgeorgia/strategy#76)
|
|
9
|
-
// unit-testable — the extension has no test harness.
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Base handle length floor + span factors. The handle grows with both the
|
|
13
|
-
* horizontal and vertical span so the curve stays visibly horizontal long
|
|
14
|
-
* enough for the arrowhead to sit flush against the line.
|
|
15
|
-
*/
|
|
16
|
-
export const EDGE_MIN_HANDLE = 64;
|
|
17
|
-
const DX_FACTOR = 0.5;
|
|
18
|
-
const DY_FACTOR = 0.8;
|
|
19
|
-
|
|
20
|
-
/** Multiplier applied to the base handle length. 1 = historical appearance. */
|
|
21
|
-
export const DEFAULT_EDGE_CURVATURE = 1;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Builds the SVG `d` for a horizontal-tangent cubic Bézier from (sx,sy) to
|
|
25
|
-
* (tx,ty).
|
|
26
|
-
*
|
|
27
|
-
* `curvature` scales the control-handle
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
1
|
+
// Shared edge geometry for the static notation previews (Goals, FGCA, FGA,
|
|
2
|
+
// Activities). All four render dependency/relationship edges as a single cubic
|
|
3
|
+
// Bézier with horizontal control handles: each control point shares its
|
|
4
|
+
// endpoint's Y, so the tangent is horizontal at both ends and the marker-end
|
|
5
|
+
// arrow reads as perpendicular to the node's vertical edge.
|
|
6
|
+
//
|
|
7
|
+
// Pulling the path math here (rather than duplicating it inline in each
|
|
8
|
+
// preview) makes the configurable-curvature behaviour (vkgeorgia/strategy#76)
|
|
9
|
+
// unit-testable — the extension has no test harness.
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base handle length floor + span factors. The handle grows with both the
|
|
13
|
+
* horizontal and vertical span so the curve stays visibly horizontal long
|
|
14
|
+
* enough for the arrowhead to sit flush against the line.
|
|
15
|
+
*/
|
|
16
|
+
export const EDGE_MIN_HANDLE = 64;
|
|
17
|
+
const DX_FACTOR = 0.5;
|
|
18
|
+
const DY_FACTOR = 0.8;
|
|
19
|
+
|
|
20
|
+
/** Multiplier applied to the base handle length. 1 = historical appearance. */
|
|
21
|
+
export const DEFAULT_EDGE_CURVATURE = 1;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Builds the SVG `d` for a horizontal-tangent cubic Bézier from (sx,sy) to
|
|
25
|
+
* (tx,ty).
|
|
26
|
+
*
|
|
27
|
+
* `curvature` scales the exit control-handle (departure from source).
|
|
28
|
+
* `entryCurvature` scales the entry control-handle (arrival at target);
|
|
29
|
+
* defaults to `curvature` when omitted so callers that pass one value get
|
|
30
|
+
* symmetric handles (the historical behaviour).
|
|
31
|
+
*
|
|
32
|
+
* - 0 → handle collapses onto its endpoint ⇒ straight at that end.
|
|
33
|
+
* - 1 → the historical curve (no visual change from before #76).
|
|
34
|
+
* - >1 → progressively stronger arc at that end.
|
|
35
|
+
*/
|
|
36
|
+
export function horizontalCubicEdgePath(
|
|
37
|
+
sx: number,
|
|
38
|
+
sy: number,
|
|
39
|
+
tx: number,
|
|
40
|
+
ty: number,
|
|
41
|
+
curvature: number = DEFAULT_EDGE_CURVATURE,
|
|
42
|
+
entryCurvature?: number,
|
|
43
|
+
): string {
|
|
44
|
+
const dx = tx - sx;
|
|
45
|
+
const dy = ty - sy;
|
|
46
|
+
const baseHandle = Math.max(EDGE_MIN_HANDLE, Math.abs(dx) * DX_FACTOR, Math.abs(dy) * DY_FACTOR);
|
|
47
|
+
const exitHandle = baseHandle * curvature;
|
|
48
|
+
const entryHandle = baseHandle * (entryCurvature ?? curvature);
|
|
49
|
+
return `M${sx},${sy} C${sx + exitHandle},${sy} ${tx - entryHandle},${ty} ${tx},${ty}`;
|
|
50
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import { validateFactor } from '../validate.js';
|
|
3
|
+
import type { CanonCatalog } from '../../typed-id.js';
|
|
3
4
|
|
|
4
|
-
function
|
|
5
|
+
function validExternal(): Record<string, unknown> {
|
|
5
6
|
return {
|
|
6
|
-
notation: '
|
|
7
|
+
notation: 'driver',
|
|
7
8
|
id: 'FACTOR-EU-REG-1',
|
|
8
|
-
name: 'EU regulatory window
|
|
9
|
+
name: 'EU regulatory window',
|
|
9
10
|
type: 'external',
|
|
10
11
|
category: 'legal',
|
|
11
12
|
description: 'Standing external driver — the EU regulatory regime.',
|
|
@@ -19,80 +20,114 @@ function valid(): Record<string, unknown> {
|
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
function validInternal(): Record<string, unknown> {
|
|
24
|
+
return {
|
|
25
|
+
notation: 'driver',
|
|
26
|
+
id: 'FACTOR-COMP-1',
|
|
27
|
+
name: 'Support response time',
|
|
28
|
+
type: 'internal',
|
|
29
|
+
description: 'Standing internal driver.',
|
|
30
|
+
zone: 'canon',
|
|
31
|
+
admitted_at: '2026-05-29',
|
|
32
|
+
admitted_by: 'v.korobeinikov',
|
|
33
|
+
gate_checks: { uniqueness: 'pass', consistency: 'pass', completeness: 'pass' },
|
|
34
|
+
valid_from: '2026-05-26',
|
|
35
|
+
valid_to: null,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const codes = (input: unknown, opts?: Parameters<typeof validateFactor>[1]): string[] =>
|
|
40
|
+
validateFactor(input, opts).errors.map(e => e.code);
|
|
24
41
|
|
|
25
42
|
describe('validateFactor — positive', () => {
|
|
26
|
-
it('accepts
|
|
27
|
-
const r = validateFactor(
|
|
43
|
+
it('accepts a well-formed external PESTLE factor', () => {
|
|
44
|
+
const r = validateFactor(validExternal());
|
|
28
45
|
expect(r.valid, JSON.stringify(r.errors)).toBe(true);
|
|
29
|
-
expect(r.errors).toHaveLength(0);
|
|
30
46
|
});
|
|
31
47
|
|
|
32
|
-
it('accepts a
|
|
33
|
-
|
|
34
|
-
delete r.type;
|
|
35
|
-
delete r.category;
|
|
36
|
-
delete r.references_constraint;
|
|
37
|
-
expect(validateFactor(r).valid).toBe(true);
|
|
48
|
+
it('accepts a well-formed internal factor (no PESTLE category)', () => {
|
|
49
|
+
expect(validateFactor(validInternal()).valid).toBe(true);
|
|
38
50
|
});
|
|
39
|
-
});
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
it('accepts a minimal factor with no optional fields', () => {
|
|
53
|
+
const f = validInternal();
|
|
54
|
+
delete f.type;
|
|
55
|
+
delete f.description;
|
|
56
|
+
expect(validateFactor(f).valid).toBe(true);
|
|
45
57
|
});
|
|
58
|
+
});
|
|
46
59
|
|
|
47
|
-
|
|
48
|
-
|
|
60
|
+
describe('validateFactor — FACTOR-001 (shape / id grammar)', () => {
|
|
61
|
+
it('flags a missing required envelope field', () => {
|
|
62
|
+
const f = validExternal();
|
|
63
|
+
delete f.admitted_by;
|
|
64
|
+
expect(codes(f)).toContain('FACTOR-001');
|
|
49
65
|
});
|
|
50
66
|
|
|
51
|
-
it('flags an id
|
|
52
|
-
expect(codes({ ...
|
|
67
|
+
it('flags an id that violates the grammar', () => {
|
|
68
|
+
expect(codes({ ...validExternal(), id: 'FACTOR-EU-REG-001' })).toContain('FACTOR-001');
|
|
69
|
+
expect(codes({ ...validExternal(), id: 'FAC-1' })).toContain('FACTOR-001');
|
|
70
|
+
expect(codes({ ...validExternal(), id: 'factor-1' })).toContain('FACTOR-001');
|
|
53
71
|
});
|
|
54
72
|
|
|
55
|
-
it('flags
|
|
56
|
-
expect(codes({ ...
|
|
73
|
+
it('flags a wrong notation tag and a non-canon zone', () => {
|
|
74
|
+
expect(codes({ ...validExternal(), notation: 'factor' })).toContain('FACTOR-001');
|
|
75
|
+
expect(codes({ ...validExternal(), zone: 'sandbox' })).toContain('FACTOR-001');
|
|
57
76
|
});
|
|
58
77
|
|
|
59
78
|
it('flags a missing valid_to key (distinct from a null value)', () => {
|
|
60
|
-
const
|
|
61
|
-
delete
|
|
62
|
-
expect(codes(
|
|
63
|
-
expect(validateFactor({ ...valid(), valid_to: null }).valid).toBe(true);
|
|
79
|
+
const f = validExternal();
|
|
80
|
+
delete f.valid_to;
|
|
81
|
+
expect(codes(f)).toContain('FACTOR-001');
|
|
64
82
|
});
|
|
65
83
|
|
|
66
|
-
it('
|
|
67
|
-
expect(codes(
|
|
68
|
-
expect(codes(
|
|
84
|
+
it('rejects a non-object', () => {
|
|
85
|
+
expect(codes(null)).toEqual(['FACTOR-001']);
|
|
86
|
+
expect(codes(['a'])).toEqual(['FACTOR-001']);
|
|
69
87
|
});
|
|
70
88
|
});
|
|
71
89
|
|
|
72
90
|
describe('validateFactor — FACTOR-002 (type enum)', () => {
|
|
73
|
-
it('flags a type outside external
|
|
74
|
-
expect(codes({ ...
|
|
91
|
+
it('flags a type value outside {external, internal}', () => {
|
|
92
|
+
expect(codes({ ...validExternal(), type: 'driver' })).toContain('FACTOR-002');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('validateFactor — FACTOR-003 (PESTLE category)', () => {
|
|
97
|
+
it('flags a category outside PESTLE', () => {
|
|
98
|
+
expect(codes({ ...validExternal(), category: 'cosmic' })).toContain('FACTOR-003');
|
|
75
99
|
});
|
|
76
100
|
|
|
77
|
-
it('
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
it('flags PESTLE category on an internal factor', () => {
|
|
102
|
+
const f = validInternal();
|
|
103
|
+
f.category = 'legal';
|
|
104
|
+
expect(codes(f)).toContain('FACTOR-003');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('accepts each permitted PESTLE category on an external factor', () => {
|
|
108
|
+
for (const cat of ['political', 'economic', 'social', 'technological', 'legal', 'environmental']) {
|
|
109
|
+
const f = validExternal();
|
|
110
|
+
f.category = cat;
|
|
111
|
+
expect(codes(f)).not.toContain('FACTOR-003');
|
|
80
112
|
}
|
|
81
113
|
});
|
|
82
114
|
});
|
|
83
115
|
|
|
84
|
-
describe('validateFactor — FACTOR-
|
|
85
|
-
it('flags a
|
|
86
|
-
expect(codes({ ...
|
|
116
|
+
describe('validateFactor — FACTOR-004 (references_constraint)', () => {
|
|
117
|
+
it('flags a malformed references_constraint entry', () => {
|
|
118
|
+
expect(codes({ ...validExternal(), references_constraint: ['not an id'] })).toContain('FACTOR-004');
|
|
87
119
|
});
|
|
88
120
|
|
|
89
|
-
it('
|
|
90
|
-
expect(
|
|
121
|
+
it('flags a references_constraint entry of the wrong TYPE', () => {
|
|
122
|
+
expect(codes({ ...validExternal(), references_constraint: ['GOAL-X-1'] })).toContain('FACTOR-004');
|
|
91
123
|
});
|
|
92
124
|
|
|
93
|
-
it('
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
125
|
+
it('flags an unresolved id when a catalog is supplied', () => {
|
|
126
|
+
const catalog: CanonCatalog = { typeOf: () => undefined };
|
|
127
|
+
expect(codes(validExternal(), { catalog })).toContain('FACTOR-004');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('does not flag without a catalog for a well-formed CONSTRAINT id', () => {
|
|
131
|
+
expect(codes(validExternal())).not.toContain('FACTOR-004');
|
|
97
132
|
});
|
|
98
133
|
});
|
package/src/factor/index.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// `Factor` shape exported from `./goals/index` (a v0.x view shape with
|
|
4
|
-
// numeric ids — distinct from this element primitive). Both types remain
|
|
5
|
-
// importable from their module subpaths.
|
|
6
|
-
export type { Factor as FactorPrimitive, FactorType, FactorCategory } from './types.js';
|
|
7
|
-
export { FACTOR_TYPES, FACTOR_CATEGORIES } from './types.js';
|
|
1
|
+
export type { Factor, FactorType, FactorPestleCategory } from './types.js';
|
|
2
|
+
export { FACTOR_PESTLE_CATEGORIES } from './types.js';
|
|
8
3
|
export { validateFactor } from './validate.js';
|
|
4
|
+
export type { FactorValidateOptions } from './validate.js';
|
package/src/factor/types.ts
CHANGED
|
@@ -1,41 +1,37 @@
|
|
|
1
|
-
// FACTOR — motivation-layer
|
|
2
|
-
// Schema: methodology notations/ELEMENT_PRIMITIVES.md §7.1
|
|
1
|
+
// FACTOR — motivation-layer Driver (ArchiMate).
|
|
2
|
+
// Schema: methodology notations/ELEMENT_PRIMITIVES.md §7.1.
|
|
3
3
|
|
|
4
4
|
import type { GateChecks } from '../requirement/types.js';
|
|
5
5
|
|
|
6
|
-
/** Optional subtype — internal/external organisation force. */
|
|
7
6
|
export type FactorType = 'external' | 'internal';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
| 'technological'
|
|
18
|
-
| 'legal'
|
|
19
|
-
| 'environmental';
|
|
20
|
-
|
|
21
|
-
export const FACTOR_CATEGORIES = [
|
|
22
|
-
'political', 'economic', 'social', 'technological', 'legal', 'environmental',
|
|
8
|
+
/** PESTLE sub-classification — external factors only (§7.1). */
|
|
9
|
+
export const FACTOR_PESTLE_CATEGORIES = [
|
|
10
|
+
'political',
|
|
11
|
+
'economic',
|
|
12
|
+
'social',
|
|
13
|
+
'technological',
|
|
14
|
+
'legal',
|
|
15
|
+
'environmental',
|
|
23
16
|
] as const;
|
|
17
|
+
export type FactorPestleCategory = typeof FACTOR_PESTLE_CATEGORIES[number];
|
|
24
18
|
|
|
25
19
|
export interface Factor {
|
|
26
|
-
notation: '
|
|
20
|
+
notation: 'driver';
|
|
27
21
|
id: string;
|
|
28
22
|
name: string;
|
|
29
23
|
type?: FactorType;
|
|
30
|
-
category?:
|
|
24
|
+
category?: FactorPestleCategory;
|
|
31
25
|
description?: string;
|
|
32
26
|
references_constraint?: string[];
|
|
33
27
|
|
|
28
|
+
// Admission record (CONTRACT.md §6).
|
|
34
29
|
zone: 'canon';
|
|
35
30
|
admitted_at: string;
|
|
36
31
|
admitted_by: string;
|
|
37
32
|
gate_checks: GateChecks;
|
|
38
33
|
|
|
34
|
+
// Primitive lifecycle (CONTRACT.md §7).
|
|
39
35
|
valid_from: string;
|
|
40
36
|
valid_to: string | null;
|
|
41
37
|
}
|