@transitrix/diagrams 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +47 -47
  3. package/dist/__tests__/edge-path.test.js +8 -0
  4. package/dist/activity-card/__tests__/example.test.js +20 -1
  5. package/dist/activity-card/__tests__/layout.test.js +102 -11
  6. package/dist/activity-card/__tests__/resolver.test.js +139 -6
  7. package/dist/activity-card/index.d.ts +1 -1
  8. package/dist/activity-card/layout.d.ts +1 -1
  9. package/dist/activity-card/layout.js +220 -103
  10. package/dist/activity-card/resolver.js +107 -26
  11. package/dist/activity-card/types.d.ts +150 -27
  12. package/dist/activity-card/validate.js +3 -0
  13. package/dist/actor/__tests__/validate.test.js +63 -31
  14. package/dist/actor/index.d.ts +1 -1
  15. package/dist/actor/index.js +1 -1
  16. package/dist/actor/types.d.ts +7 -3
  17. package/dist/actor/types.js +17 -3
  18. package/dist/actor/validate.js +55 -26
  19. package/dist/assertion/types.d.ts +3 -1
  20. package/dist/assertion/types.js +1 -1
  21. package/dist/change/__tests__/validate.test.js +40 -34
  22. package/dist/change/index.d.ts +1 -0
  23. package/dist/change/types.d.ts +1 -1
  24. package/dist/change/types.js +2 -2
  25. package/dist/change/validate.d.ts +6 -1
  26. package/dist/change/validate.js +68 -41
  27. package/dist/compliance/__tests__/classify.test.js +34 -0
  28. package/dist/compliance/__tests__/coverage-metric.test.js +146 -46
  29. package/dist/compliance/__tests__/html.test.js +2 -2
  30. package/dist/compliance/__tests__/impact.test.js +311 -6
  31. package/dist/compliance/classify.d.ts +6 -0
  32. package/dist/compliance/classify.js +9 -1
  33. package/dist/compliance/coverage-metric.d.ts +31 -11
  34. package/dist/compliance/coverage-metric.js +149 -39
  35. package/dist/compliance/html.js +77 -74
  36. package/dist/compliance/impact.d.ts +77 -16
  37. package/dist/compliance/impact.js +193 -25
  38. package/dist/compliance/index.d.ts +2 -2
  39. package/dist/compliance/index.js +1 -1
  40. package/dist/compliance/markdown.js +1 -0
  41. package/dist/compliance/types.d.ts +25 -6
  42. package/dist/edge-path.d.ts +8 -4
  43. package/dist/edge-path.js +11 -6
  44. package/dist/factor/__tests__/validate.test.js +74 -45
  45. package/dist/factor/index.d.ts +3 -2
  46. package/dist/factor/index.js +1 -1
  47. package/dist/factor/types.d.ts +4 -7
  48. package/dist/factor/types.js +10 -5
  49. package/dist/factor/validate.d.ts +6 -1
  50. package/dist/factor/validate.js +68 -50
  51. package/dist/fgca/__tests__/resolver.test.js +185 -0
  52. package/dist/fgca/index.d.ts +2 -0
  53. package/dist/fgca/index.js +1 -0
  54. package/dist/fgca/resolver.d.ts +49 -0
  55. package/dist/fgca/resolver.js +124 -0
  56. package/dist/goals/index.d.ts +1 -1
  57. package/dist/index.d.ts +5 -0
  58. package/dist/index.js +5 -0
  59. package/dist/process-blueprint/__tests__/layout.test.js +37 -0
  60. package/dist/process-blueprint/layout.js +5 -1
  61. package/dist/process-blueprint/types.d.ts +22 -1
  62. package/dist/stakeholder/__tests__/validate.test.js +49 -47
  63. package/dist/stakeholder/index.d.ts +1 -0
  64. package/dist/stakeholder/types.d.ts +3 -4
  65. package/dist/stakeholder/types.js +2 -3
  66. package/dist/stakeholder/validate.d.ts +6 -1
  67. package/dist/stakeholder/validate.js +71 -50
  68. package/dist/target-state/__tests__/validate.test.js +43 -27
  69. package/dist/target-state/index.d.ts +2 -0
  70. package/dist/target-state/index.js +1 -0
  71. package/dist/target-state/types.d.ts +6 -1
  72. package/dist/target-state/types.js +8 -7
  73. package/dist/target-state/validate.d.ts +6 -1
  74. package/dist/target-state/validate.js +69 -45
  75. package/dist/theme/themes.js +69 -69
  76. package/dist/webview/__tests__/entry.test.js +11 -11
  77. package/dist/webview/render-activities.d.ts +3 -1
  78. package/dist/webview/render-activities.js +2 -2
  79. package/dist/webview/render-activity-card.js +104 -77
  80. package/dist/webview/render-fgca.d.ts +4 -0
  81. package/dist/webview/render-fgca.js +2 -5
  82. package/dist/webview/render-goals.d.ts +1 -0
  83. package/dist/webview/render-goals.js +15 -15
  84. package/dist/webview/render-process-blueprint.js +10 -10
  85. package/package.json +40 -40
  86. package/src/__tests__/edge-path.test.ts +58 -46
  87. package/src/__tests__/scope.test.ts +27 -27
  88. package/src/__tests__/yaml-normalize.test.ts +158 -158
  89. package/src/activities/__tests__/cpm.test.ts +164 -164
  90. package/src/activities/__tests__/gantt.test.ts +245 -245
  91. package/src/activities/__tests__/layout.test.ts +112 -112
  92. package/src/activities/__tests__/validate.test.ts +409 -409
  93. package/src/activities/cpm.ts +95 -95
  94. package/src/activities/gantt.ts +276 -276
  95. package/src/activities/index.ts +28 -28
  96. package/src/activities/layout.ts +112 -112
  97. package/src/activities/types.ts +148 -148
  98. package/src/activities/validate.ts +357 -357
  99. package/src/activity-card/__tests__/example.test.ts +85 -66
  100. package/src/activity-card/__tests__/layout.test.ts +169 -63
  101. package/src/activity-card/__tests__/resolver.test.ts +307 -161
  102. package/src/activity-card/__tests__/validate.test.ts +131 -131
  103. package/src/activity-card/index.ts +38 -32
  104. package/src/activity-card/layout.ts +324 -194
  105. package/src/activity-card/resolver.ts +415 -337
  106. package/src/activity-card/types.ts +376 -237
  107. package/src/activity-card/validate.ts +162 -158
  108. package/src/actor/__tests__/validate.test.ts +70 -31
  109. package/src/actor/index.ts +1 -1
  110. package/src/actor/types.ts +21 -7
  111. package/src/actor/validate.ts +59 -27
  112. package/src/applications/__tests__/validate.test.ts +256 -256
  113. package/src/applications/index.ts +11 -11
  114. package/src/applications/types.ts +43 -43
  115. package/src/applications/validate.ts +131 -131
  116. package/src/assertion/__tests__/example.test.ts +37 -37
  117. package/src/assertion/__tests__/validate.test.ts +142 -142
  118. package/src/assertion/index.ts +12 -12
  119. package/src/assertion/types.ts +60 -58
  120. package/src/assertion/validate.ts +145 -145
  121. package/src/blocks/__tests__/layout.test.ts +169 -169
  122. package/src/blocks/__tests__/validate.test.ts +260 -260
  123. package/src/blocks/index.ts +17 -17
  124. package/src/blocks/layout.ts +186 -186
  125. package/src/blocks/types.ts +62 -62
  126. package/src/blocks/validate.ts +206 -206
  127. package/src/capability-map/__tests__/validate.test.ts +238 -238
  128. package/src/capability-map/index.ts +8 -8
  129. package/src/capability-map/types.ts +29 -29
  130. package/src/capability-map/validate.ts +127 -127
  131. package/src/change/__tests__/validate.test.ts +43 -34
  132. package/src/change/index.ts +1 -0
  133. package/src/change/types.ts +5 -3
  134. package/src/change/validate.ts +75 -43
  135. package/src/compliance/__tests__/classify.test.ts +64 -27
  136. package/src/compliance/__tests__/confidence.test.ts +98 -98
  137. package/src/compliance/__tests__/coverage-metric.test.ts +300 -188
  138. package/src/compliance/__tests__/demo-scenario.test.ts +273 -273
  139. package/src/compliance/__tests__/example.test.ts +57 -57
  140. package/src/compliance/__tests__/gap-report.test.ts +128 -128
  141. package/src/compliance/__tests__/html.test.ts +141 -141
  142. package/src/compliance/__tests__/impact.test.ts +840 -481
  143. package/src/compliance/__tests__/markdown.test.ts +94 -94
  144. package/src/compliance/__tests__/views.test.ts +64 -64
  145. package/src/compliance/classify.ts +100 -84
  146. package/src/compliance/confidence.ts +69 -69
  147. package/src/compliance/coverage-metric.ts +404 -263
  148. package/src/compliance/gap-report.ts +94 -94
  149. package/src/compliance/html.ts +298 -295
  150. package/src/compliance/impact.ts +861 -677
  151. package/src/compliance/index.ts +57 -56
  152. package/src/compliance/markdown.ts +136 -135
  153. package/src/compliance/reverse-index.ts +33 -33
  154. package/src/compliance/types.ts +136 -120
  155. package/src/compliance/views.ts +46 -46
  156. package/src/compliance-matrix/__tests__/build.test.ts +200 -200
  157. package/src/compliance-matrix/__tests__/example.test.ts +57 -57
  158. package/src/compliance-matrix/index.ts +11 -11
  159. package/src/compliance-matrix/types.ts +102 -102
  160. package/src/edge-path.ts +50 -44
  161. package/src/factor/__tests__/validate.test.ts +80 -45
  162. package/src/factor/index.ts +3 -7
  163. package/src/factor/types.ts +14 -18
  164. package/src/factor/validate.ts +77 -51
  165. package/src/fgca/__tests__/chain-table.test.ts +172 -172
  166. package/src/fgca/__tests__/layout.test.ts +179 -179
  167. package/src/fgca/__tests__/parse-canonical.test.ts +248 -248
  168. package/src/fgca/__tests__/preview-layout.test.ts +124 -124
  169. package/src/fgca/__tests__/resolver.test.ts +209 -0
  170. package/src/fgca/__tests__/validate.test.ts +142 -142
  171. package/src/fgca/chain-table.ts +225 -225
  172. package/src/fgca/index.ts +47 -45
  173. package/src/fgca/layout.ts +204 -204
  174. package/src/fgca/nodeTypes.ts +11 -11
  175. package/src/fgca/nodes/FGCAActivityNode.tsx +65 -65
  176. package/src/fgca/nodes/FGCAChangeNode.tsx +64 -64
  177. package/src/fgca/nodes/FGCAFactorNode.tsx +64 -64
  178. package/src/fgca/nodes/FGCAGoalNode.tsx +72 -72
  179. package/src/fgca/parse-canonical.ts +400 -400
  180. package/src/fgca/preview-layout.ts +217 -217
  181. package/src/fgca/resolver.ts +157 -0
  182. package/src/fgca/types.ts +50 -50
  183. package/src/fgca/validate.ts +126 -126
  184. package/src/geometry.ts +9 -9
  185. package/src/goals/__tests__/layout.test.ts +175 -175
  186. package/src/goals/__tests__/mutations.test.ts +111 -111
  187. package/src/goals/__tests__/parse-canonical.test.ts +145 -145
  188. package/src/goals/__tests__/validate.test.ts +202 -202
  189. package/src/goals/index.ts +20 -21
  190. package/src/goals/layout.ts +172 -172
  191. package/src/goals/mutations.ts +123 -123
  192. package/src/goals/parse-canonical.ts +286 -286
  193. package/src/goals/types.ts +85 -85
  194. package/src/goals/validate.ts +136 -136
  195. package/src/index.ts +28 -23
  196. package/src/process-blueprint/__tests__/compliance-lane.test.ts +320 -320
  197. package/src/process-blueprint/__tests__/layout.test.ts +240 -195
  198. package/src/process-blueprint/__tests__/validate.test.ts +310 -310
  199. package/src/process-blueprint/index.ts +31 -31
  200. package/src/process-blueprint/layout.ts +535 -531
  201. package/src/process-blueprint/types.ts +263 -242
  202. package/src/process-blueprint/validate.ts +181 -181
  203. package/src/process-map/__tests__/validate.test.ts +223 -223
  204. package/src/process-map/index.ts +10 -10
  205. package/src/process-map/types.ts +36 -36
  206. package/src/process-map/validate.ts +135 -135
  207. package/src/products/__tests__/validate.test.ts +239 -239
  208. package/src/products/index.ts +9 -9
  209. package/src/products/types.ts +31 -31
  210. package/src/products/validate.ts +112 -112
  211. package/src/repo-validate/__tests__/validate-repo.test.ts +149 -149
  212. package/src/repo-validate/index.ts +2 -2
  213. package/src/repo-validate/types.ts +50 -50
  214. package/src/repo-validate/validate-repo.ts +196 -196
  215. package/src/requirement/__tests__/example.test.ts +24 -24
  216. package/src/requirement/__tests__/validate.test.ts +96 -96
  217. package/src/requirement/index.ts +4 -4
  218. package/src/requirement/types.ts +35 -35
  219. package/src/requirement/validate.ts +92 -92
  220. package/src/scenarios/__tests__/validate.test.ts +209 -209
  221. package/src/scenarios/index.ts +15 -15
  222. package/src/scenarios/types.ts +37 -37
  223. package/src/scenarios/validate.ts +122 -122
  224. package/src/schema-version.ts +16 -16
  225. package/src/scope.ts +46 -46
  226. package/src/stakeholder/__tests__/validate.test.ts +51 -47
  227. package/src/stakeholder/index.ts +1 -0
  228. package/src/stakeholder/types.ts +7 -7
  229. package/src/stakeholder/validate.ts +79 -52
  230. package/src/target-state/__tests__/validate.test.ts +48 -27
  231. package/src/target-state/index.ts +2 -0
  232. package/src/target-state/types.ts +11 -7
  233. package/src/target-state/validate.ts +76 -46
  234. package/src/theme/index.ts +4 -4
  235. package/src/theme/themes.ts +237 -237
  236. package/src/theme/tokens.ts +133 -133
  237. package/src/typed-id.ts +56 -56
  238. package/src/validation-types.ts +36 -36
  239. package/src/webview/__tests__/entry-notations.test.ts +77 -77
  240. package/src/webview/__tests__/entry.test.ts +64 -64
  241. package/src/webview/__tests__/render-goals.test.ts +72 -72
  242. package/src/webview/entry.ts +292 -292
  243. package/src/webview/render-activities.ts +5 -3
  244. package/src/webview/render-activity-card.ts +266 -234
  245. package/src/webview/render-fgca.ts +6 -5
  246. package/src/webview/render-goals.ts +111 -110
  247. package/src/webview/render-process-blueprint.ts +207 -207
  248. package/src/webview/styles.css +322 -323
  249. package/src/yaml-normalize.ts +56 -56
  250. package/dist/element-envelope.d.ts +0 -15
  251. package/dist/element-envelope.js +0 -55
  252. package/dist/issues/__tests__/layout.test.js +0 -62
  253. package/dist/issues/__tests__/validate.test.d.ts +0 -1
  254. package/dist/issues/__tests__/validate.test.js +0 -82
  255. package/dist/issues/index.d.ts +0 -4
  256. package/dist/issues/index.js +0 -2
  257. package/dist/issues/layout.d.ts +0 -10
  258. package/dist/issues/layout.js +0 -82
  259. package/dist/issues/types.d.ts +0 -61
  260. package/dist/issues/types.js +0 -6
  261. package/dist/issues/validate.d.ts +0 -3
  262. package/dist/issues/validate.js +0 -143
  263. package/dist/webview/transitrix-render.css +0 -323
  264. package/dist/webview/transitrix-render.js +0 -6452
  265. package/dist/webview/transitrix-render.js.map +0 -7
  266. package/src/element-envelope.ts +0 -76
  267. /package/dist/{issues/__tests__/layout.test.d.ts → fgca/__tests__/resolver.test.d.ts} +0 -0
@@ -1,237 +1,376 @@
1
- // Activity Card notation — single-project narrative view.
2
- //
3
- // Spec: transitrix/methodology `notations/views/18-activity-card.md` (v0.1).
4
- // Epic vkgeorgia/strategy#97, Studio track #134.
5
- //
6
- // The Activity Card is the first MULTI-DOCUMENT Studio notation. The card
7
- // YAML itself holds only `id`, `project` (an Activity ID), `description`,
8
- // and `milestones[]`. Everything painted on the card — the project name,
9
- // dates, motivation chain (Factors → Goals → Changes), and child activities
10
- // — is pulled BY REFERENCE at view time from the canonical ELEMENT and
11
- // RELATION store (`canon/elements/**`, `canon/relations/**`), never from
12
- // other view documents. This honours the view-purity invariant: a view is a
13
- // projection over elements + relations (methodology ELEMENT_PRIMITIVES.md §1).
14
- // See `resolver.ts`.
15
- //
16
- // This file declares two model layers:
17
- // 1. the RAW card document (what the YAML parses into), and
18
- // 2. the ASSEMBLED card view-model (what the resolver produces and the
19
- // layout consumes).
20
-
21
- import type {
22
- ValidationError as SharedValidationError,
23
- ValidationWarning as SharedValidationWarning,
24
- ValidationResult as SharedValidationResult,
25
- } from '../validation-types.js';
26
-
27
- // Keep PREFIXED aliases consistent with the other notation modules so
28
- // external consumers can name the activity-card result types directly.
29
- export type ActivityCardValidationError = SharedValidationError;
30
- export type ActivityCardValidationWarning = SharedValidationWarning;
31
- export type ActivityCardValidationResult = SharedValidationResult;
32
-
33
- // ── Raw card document (the `*.activity-card.transitrix.yaml` shape) ──────────
34
-
35
- export interface RawMilestone {
36
- id: string;
37
- name: string;
38
- /** Quoted ISO 8601 date (YYYY-MM-DD) when the milestone is reached. */
39
- date: string;
40
- description?: string;
41
- /** CHANGE-… IDs; each must be a subset of the project Activity's delivers_changes. */
42
- delivers_changes?: string[];
43
- }
44
-
45
- export interface ActivityCardBlock {
46
- id: string;
47
- /** Canonical ID of the referenced project Activity (ACTIVITY-…). */
48
- project: string;
49
- description?: string;
50
- milestones?: RawMilestone[];
51
- }
52
-
53
- export interface ActivityCardDoc {
54
- notation: string;
55
- spec_version?: string;
56
- activity_card: ActivityCardBlock;
57
- }
58
-
59
- // ── Canon sources consumed by the resolver ──────────────────────────────────
60
- //
61
- // View-purity invariant (methodology ELEMENT_PRIMITIVES.md §1): a view is a
62
- // projection over the canonical ELEMENTS + RELATIONS, never over other view
63
- // documents. The Activity Card therefore resolves its project, child
64
- // activities, and motivation chain from the canon element store
65
- // (`canon/elements/**` — one ACTIVITY / FACTOR / GOAL / CHANGE element per
66
- // file, each a `notation: <type>` document carrying its own `id`) and the
67
- // relation store (`canon/relations/**` — `notation: relation` files), NOT from
68
- // sibling `*.activities.*` / `*.fgca.*` view documents.
69
- //
70
- // The resolver is filesystem-free: the extension reads + parses the element and
71
- // relation files and hands the parsed objects in. We model them as `unknown[]`
72
- // at the boundary and narrow defensively inside the resolver, so a malformed
73
- // element / relation degrades to a resolution error rather than a crash.
74
-
75
- export interface ActivityCardSources {
76
- /** Parsed canon element documents — one element per file (`notation: activity|factor|goal|change|…`). */
77
- elements: unknown[];
78
- /** Parsed canon relation documents (`notation: relation`). */
79
- relations: unknown[];
80
- }
81
-
82
- // ── Assembled card view-model (resolver output → layout input) ───────────────
83
-
84
- export interface ResolvedProject {
85
- id: string;
86
- name: string;
87
- /** Full description from the Activity (the card's own `description` is separate). */
88
- description?: string;
89
- /** Lifecycle: decision-to-initiate date (CONTRACT.md §7). */
90
- valid_from?: string;
91
- /** Lifecycle: when the project ceased effect, or undefined if active. */
92
- valid_to?: string;
93
- /** Planned work range. */
94
- start_date?: string;
95
- end_date?: string;
96
- }
97
-
98
- export interface ResolvedMilestone {
99
- id: string;
100
- name: string;
101
- date: string;
102
- description?: string;
103
- /** CHANGE-… IDs this milestone delivers (subset of the project's). */
104
- deliversChanges: string[];
105
- }
106
-
107
- export interface ResolvedFactor {
108
- id: string;
109
- name: string;
110
- }
111
-
112
- export interface ResolvedGoal {
113
- id: string;
114
- name: string;
115
- /** FACTOR-… IDs that motivate this goal (canonical `goal.factors`). */
116
- factorIds: string[];
117
- }
118
-
119
- export interface ResolvedChange {
120
- id: string;
121
- name: string;
122
- /** GOAL-… IDs this change advances (canonical `change.goals`). */
123
- goalIds: string[];
124
- }
125
-
126
- /** Motivation chain: Factors → Goals → Changes, scoped to the project. */
127
- export interface ResolvedMotivation {
128
- factors: ResolvedFactor[];
129
- goals: ResolvedGoal[];
130
- changes: ResolvedChange[];
131
- }
132
-
133
- export interface ResolvedChildActivity {
134
- id: string;
135
- name: string;
136
- activity_type?: string;
137
- start_date?: string;
138
- end_date?: string;
139
- owner?: string;
140
- }
141
-
142
- export interface ResolvedActivityCard {
143
- cardId: string;
144
- /** The card's own executive-summary description (distinct from the project's). */
145
- cardDescription?: string;
146
- project: ResolvedProject;
147
- /** Sorted ascending by `date`. */
148
- milestones: ResolvedMilestone[];
149
- motivation: ResolvedMotivation;
150
- /** Activities whose `parent` = the project Activity id. */
151
- childActivities: ResolvedChildActivity[];
152
- }
153
-
154
- // ── Layout geometry (pure; the preview turns this into SVG) ───────────────────
155
-
156
- import type { LayoutBounds } from '../geometry.js';
157
- export type { LayoutBounds };
158
-
159
- /** A boxed value-pair shown in the dates band. */
160
- export interface DateField {
161
- label: string;
162
- value: string;
163
- x: number;
164
- y: number;
165
- width: number;
166
- height: number;
167
- }
168
-
169
- /** One milestone marker on the timeline. */
170
- export interface MilestoneMarker {
171
- id: string;
172
- name: string;
173
- date: string;
174
- /** ArchiMate class label appended by the renderer (§5.1). */
175
- archimateClass: string;
176
- x: number;
177
- y: number;
178
- width: number;
179
- height: number;
180
- }
181
-
182
- /** One node in a motivation-chain column. */
183
- export interface ChainNode {
184
- id: string;
185
- name: string;
186
- x: number;
187
- y: number;
188
- width: number;
189
- height: number;
190
- }
191
-
192
- /** An edge between two chain nodes (factor→goal or goal→change). */
193
- export interface ChainEdge {
194
- sourceId: string;
195
- targetId: string;
196
- }
197
-
198
- export interface ChildActivityRow {
199
- id: string;
200
- name: string;
201
- /** ArchiMate class label appended by the renderer (§5.1). */
202
- archimateClass: string;
203
- meta: string;
204
- x: number;
205
- y: number;
206
- width: number;
207
- height: number;
208
- }
209
-
210
- export interface SectionHeader {
211
- label: string;
212
- x: number;
213
- y: number;
214
- width: number;
215
- height: number;
216
- }
217
-
218
- export interface ActivityCardLayoutOptions {
219
- /** Outer card width (px). */
220
- cardWidth?: number;
221
- /** Horizontal gap (px) between the three motivation-chain columns. */
222
- columnGap?: number;
223
- /** Vertical gap (px) between stacked rows within a section. */
224
- rowGap?: number;
225
- }
226
-
227
- export interface ActivityCardLayout {
228
- bounds: LayoutBounds;
229
- title: { name: string; x: number; y: number };
230
- dateFields: DateField[];
231
- sectionHeaders: SectionHeader[];
232
- milestones: MilestoneMarker[];
233
- /** Three columns of the motivation chain, in F→G→C order. */
234
- chainColumns: { factors: ChainNode[]; goals: ChainNode[]; changes: ChainNode[] };
235
- chainEdges: ChainEdge[];
236
- childActivities: ChildActivityRow[];
237
- }
1
+ // Activity Card notation — single-project narrative view.
2
+ //
3
+ // Spec: transitrix/methodology `notations/views/18-activity-card.md` (v0.1).
4
+ // Epic vkgeorgia/strategy#97, Studio track #134.
5
+ //
6
+ // The Activity Card is the first MULTI-DOCUMENT Studio notation. The card
7
+ // YAML itself holds only `id`, `project` (an Activity ID), `description`,
8
+ // and `milestones[]`. Everything painted on the card — the project name,
9
+ // dates, motivation chain (Factors → Goals → Changes), and child activities
10
+ // — is pulled BY REFERENCE at view time from the canonical ELEMENT and
11
+ // RELATION store (`canon/elements/**`, `canon/relations/**`), never from
12
+ // other view documents. This honours the view-purity invariant: a view is a
13
+ // projection over elements + relations (methodology ELEMENT_PRIMITIVES.md §1).
14
+ // See `resolver.ts`.
15
+ //
16
+ // This file declares two model layers:
17
+ // 1. the RAW card document (what the YAML parses into), and
18
+ // 2. the ASSEMBLED card view-model (what the resolver produces and the
19
+ // layout consumes).
20
+
21
+ import type {
22
+ ValidationError as SharedValidationError,
23
+ ValidationWarning as SharedValidationWarning,
24
+ ValidationResult as SharedValidationResult,
25
+ } from '../validation-types.js';
26
+
27
+ // Keep PREFIXED aliases consistent with the other notation modules so
28
+ // external consumers can name the activity-card result types directly.
29
+ export type ActivityCardValidationError = SharedValidationError;
30
+ export type ActivityCardValidationWarning = SharedValidationWarning;
31
+ export type ActivityCardValidationResult = SharedValidationResult;
32
+
33
+ // ── Raw card document (the `*.activity-card.transitrix.yaml` shape) ──────────
34
+
35
+ export interface RawMilestone {
36
+ id: string;
37
+ name: string;
38
+ /** Quoted ISO 8601 date (YYYY-MM-DD) when the milestone is reached. */
39
+ date: string;
40
+ description?: string;
41
+ /** CHANGE-… IDs; each must be a subset of the project Activity's delivers_changes. */
42
+ delivers_changes?: string[];
43
+ }
44
+
45
+ export interface ActivityCardBlock {
46
+ id: string;
47
+ /** Canonical ID of the referenced project Activity (ACTIVITY-…). */
48
+ project: string;
49
+ description?: string;
50
+ milestones?: RawMilestone[];
51
+ /**
52
+ * Supplementary notes shown in the card footer. Free text; stored in the
53
+ * view file (not in canon elements) as report-level context.
54
+ */
55
+ notes?: string;
56
+ }
57
+
58
+ export interface ActivityCardDoc {
59
+ notation: string;
60
+ spec_version?: string;
61
+ activity_card: ActivityCardBlock;
62
+ }
63
+
64
+ // ── Canon sources consumed by the resolver ──────────────────────────────────
65
+ //
66
+ // View-purity invariant (methodology ELEMENT_PRIMITIVES.md §1): a view is a
67
+ // projection over the canonical ELEMENTS + RELATIONS, never over other view
68
+ // documents. The Activity Card therefore resolves its project, child
69
+ // activities, and motivation chain from the canon element store
70
+ // (`canon/elements/**` — one ACTIVITY / FACTOR / GOAL / CHANGE element per
71
+ // file, each a `notation: <type>` document carrying its own `id`) and the
72
+ // relation store (`canon/relations/**` — `notation: relation` files), NOT from
73
+ // sibling `*.activities.*` / `*.fgca.*` view documents.
74
+ //
75
+ // The resolver is filesystem-free: the extension reads + parses the element and
76
+ // relation files and hands the parsed objects in. We model them as `unknown[]`
77
+ // at the boundary and narrow defensively inside the resolver, so a malformed
78
+ // element / relation degrades to a resolution error rather than a crash.
79
+
80
+ export interface ActivityCardSources {
81
+ /** Parsed canon element documents — one element per file (`notation: activity|factor|goal|change|…`). */
82
+ elements: unknown[];
83
+ /** Parsed canon relation documents (`notation: relation`). */
84
+ relations: unknown[];
85
+ }
86
+
87
+ // ── Assembled card view-model (resolver output → layout input) ───────────────
88
+
89
+ export interface ResolvedProject {
90
+ id: string;
91
+ name: string;
92
+ /** Full description from the Activity (the card's own `description` is separate). */
93
+ description?: string;
94
+ /** Lifecycle: decision-to-initiate date (CONTRACT.md §7). */
95
+ valid_from?: string;
96
+ /** Lifecycle: when the project ceased effect, or undefined if active. */
97
+ valid_to?: string;
98
+ /** Planned work range. */
99
+ start_date?: string;
100
+ end_date?: string;
101
+ /**
102
+ * Activity scale: programme | project | workstream | task (or any custom
103
+ * value). Shown in the card header so the reader knows what level this card
104
+ * represents. Optional — card shows "—" when absent.
105
+ */
106
+ activity_type?: string;
107
+ /**
108
+ * Current execution state: planned | in_progress | on_track | at_risk |
109
+ * blocked | completed | cancelled. Optional — card shows "—" when absent.
110
+ */
111
+ status?: string;
112
+ }
113
+
114
+ export interface ResolvedMilestone {
115
+ id: string;
116
+ name: string;
117
+ date: string;
118
+ description?: string;
119
+ /** CHANGE-… IDs this milestone delivers (subset of the project's). */
120
+ deliversChanges: string[];
121
+ }
122
+
123
+ export interface ResolvedDriver {
124
+ id: string;
125
+ name: string;
126
+ }
127
+
128
+ /** @deprecated Use {@link ResolvedDriver}. */
129
+ export type ResolvedFactor = ResolvedDriver;
130
+
131
+ /**
132
+ * A dated finding about the current state of a Driver, answering the
133
+ * question "what specific problem are we solving?" (pain point).
134
+ * Resolved from ASSESSMENT elements whose `assesses` field points to a
135
+ * Driver that is in scope for this activity's motivation chain.
136
+ */
137
+ export interface ResolvedAssessment {
138
+ id: string;
139
+ name: string;
140
+ /** ID of the Driver this assessment observes. */
141
+ driverId: string;
142
+ description?: string;
143
+ /** ISO 8601 date when the finding was observed. */
144
+ observed_at?: string;
145
+ }
146
+
147
+ export interface ResolvedGoal {
148
+ id: string;
149
+ name: string;
150
+ /** DRIVER-… IDs that motivate this goal (canonical `goal.factors` YAML field). */
151
+ driverIds: string[];
152
+ }
153
+
154
+ export interface ResolvedChange {
155
+ id: string;
156
+ name: string;
157
+ /** GOAL-… IDs this change advances (canonical `change.goals`). */
158
+ goalIds: string[];
159
+ }
160
+
161
+ /** Motivation chain: Drivers → Goals → Changes, scoped to the project. */
162
+ export interface ResolvedMotivation {
163
+ drivers: ResolvedDriver[];
164
+ goals: ResolvedGoal[];
165
+ changes: ResolvedChange[];
166
+ }
167
+
168
+ export interface ResolvedChildActivity {
169
+ id: string;
170
+ name: string;
171
+ activity_type?: string;
172
+ start_date?: string;
173
+ end_date?: string;
174
+ owner?: string;
175
+ }
176
+
177
+ /** A STAKEHOLDER element linked to the project (via `activity_stakeholder`). */
178
+ export interface ResolvedStakeholder {
179
+ id: string;
180
+ name: string;
181
+ /** internal | external (STAKEHOLDER `type`). */
182
+ type?: string;
183
+ interest?: string;
184
+ influence?: string;
185
+ /**
186
+ * Project role from the `activity_stakeholder` relation:
187
+ * initiator | owner | sponsor | project_manager.
188
+ * Optional — card shows the name without a role badge when absent.
189
+ */
190
+ role?: string;
191
+ }
192
+
193
+ export interface ResolvedActivityCard {
194
+ cardId: string;
195
+ /** The card's own executive-summary description (distinct from the project's). */
196
+ cardDescription?: string;
197
+ project: ResolvedProject;
198
+ /** Sorted ascending by `date`. */
199
+ milestones: ResolvedMilestone[];
200
+ motivation: ResolvedMotivation;
201
+ /**
202
+ * Assessments (pain points) for the in-scope Drivers, sorted by
203
+ * `observed_at` ascending. Empty when no Assessment elements are found —
204
+ * the gap is intentionally visible on the card.
205
+ */
206
+ assessments: ResolvedAssessment[];
207
+ /** Activities whose `parent` = the project Activity id. */
208
+ childActivities: ResolvedChildActivity[];
209
+ /**
210
+ * Names of the GOALs the project DIRECTLY serves (the `activity_goal`
211
+ * targets, not the wider motivation chain) — painted as the "Project goal"
212
+ * text field. Empty when the project serves no goal.
213
+ */
214
+ goalNames?: string[];
215
+ /**
216
+ * Stakeholders linked to the project via active `activity_stakeholder`
217
+ * relations. Empty when none are linked (the card still shows the field
218
+ * with a "—" placeholder).
219
+ */
220
+ stakeholders?: ResolvedStakeholder[];
221
+ /**
222
+ * Supplementary notes for the card footer (from `activity_card.notes` in
223
+ * the view YAML). Not a canonical element field.
224
+ */
225
+ notes?: string;
226
+ }
227
+
228
+ // ── Layout geometry (pure; the preview turns this into SVG) ───────────────────
229
+
230
+ import type { LayoutBounds } from '../geometry.js';
231
+ export type { LayoutBounds };
232
+
233
+ /** A boxed value-pair shown in the dates band. */
234
+ export interface DateField {
235
+ label: string;
236
+ value: string;
237
+ x: number;
238
+ y: number;
239
+ width: number;
240
+ height: number;
241
+ }
242
+
243
+ /** A small badge shown in the header (activity type or status). */
244
+ export interface Badge {
245
+ label: string;
246
+ x: number;
247
+ y: number;
248
+ width: number;
249
+ height: number;
250
+ }
251
+
252
+ /** One stakeholder role slot in the header roles row. Always rendered; `name` is "—" when unfilled. */
253
+ export interface StakeholderRoleSlot {
254
+ /** Display label: "Initiator", "Owner", "Sponsor", "PM". */
255
+ role: string;
256
+ /** Stakeholder name or "—". */
257
+ name: string;
258
+ x: number;
259
+ y: number;
260
+ width: number;
261
+ height: number;
262
+ }
263
+
264
+ /** One node in a chain section (driver / assessment / goal / change). */
265
+ export interface ChainNode {
266
+ id: string;
267
+ name: string;
268
+ /** Supplementary text shown below the name (e.g. observed_at date for assessments). */
269
+ meta?: string;
270
+ x: number;
271
+ y: number;
272
+ width: number;
273
+ height: number;
274
+ }
275
+
276
+ /** An edge between two chain nodes (for SVG connectors). */
277
+ export interface ChainEdge {
278
+ sourceId: string;
279
+ targetId: string;
280
+ }
281
+
282
+ /**
283
+ * One vertical section of the body chain: Drivers | Assessments | Goals | Changes.
284
+ * When `isEmpty` is true the section has no nodes and renders a gap indicator
285
+ * so the author sees the missing data.
286
+ */
287
+ export interface ChainSectionLayout {
288
+ type: 'drivers' | 'assessments' | 'goals' | 'changes';
289
+ /** Section header label. */
290
+ label: string;
291
+ /** Short question answered by this section, shown in grey after the label. */
292
+ subtitle: string;
293
+ nodes: ChainNode[];
294
+ isEmpty: boolean;
295
+ x: number;
296
+ y: number;
297
+ width: number;
298
+ height: number;
299
+ }
300
+
301
+ /** One milestone marker. */
302
+ export interface MilestoneMarker {
303
+ id: string;
304
+ name: string;
305
+ date: string;
306
+ /** ArchiMate class label appended by the renderer (§5.1). */
307
+ archimateClass: string;
308
+ x: number;
309
+ y: number;
310
+ width: number;
311
+ height: number;
312
+ }
313
+
314
+ /**
315
+ * A labeled, full-width text row with wrapped value lines.
316
+ * Used for the Description (body) and Notes (footer).
317
+ */
318
+ export interface InfoRow {
319
+ label: string;
320
+ valueLines: string[];
321
+ x: number;
322
+ y: number;
323
+ width: number;
324
+ height: number;
325
+ }
326
+
327
+ export interface ChildActivityRow {
328
+ id: string;
329
+ name: string;
330
+ /** ArchiMate class label appended by the renderer (§5.1). */
331
+ archimateClass: string;
332
+ meta: string;
333
+ x: number;
334
+ y: number;
335
+ width: number;
336
+ height: number;
337
+ }
338
+
339
+ export interface ActivityCardLayoutOptions {
340
+ /** Outer card width (px). */
341
+ cardWidth?: number;
342
+ /** Vertical gap (px) between stacked rows within a section. */
343
+ rowGap?: number;
344
+ }
345
+
346
+ export interface ActivityCardLayout {
347
+ bounds: LayoutBounds;
348
+
349
+ // ── Header ────────────────────────────────────────────────────────────────
350
+ /** Project name, positioned in the title row. */
351
+ titleRow: { name: string; x: number; y: number };
352
+ /** Activity-type badge (programme / project / workstream / task). Absent when field is unset. */
353
+ activityTypeBadge?: Badge;
354
+ /** Status badge (planned / in_progress / on_track / …). Absent when field is unset. */
355
+ statusBadge?: Badge;
356
+ /** Three date cells: Initiation, Planned start, Planned end. */
357
+ dateFields: DateField[];
358
+ /** Four role slots always rendered: Initiator, Owner, Sponsor, PM. Name is "—" when unfilled. */
359
+ stakeholderRoleSlots: StakeholderRoleSlot[];
360
+
361
+ // ── Body ──────────────────────────────────────────────────────────────────
362
+ /** Executive-summary description row. Absent when `cardDescription` is empty. */
363
+ descriptionRow?: InfoRow;
364
+ /** Vertical chain: Drivers → Assessments → Goals → Changes. */
365
+ chainSections: ChainSectionLayout[];
366
+ /** Node-level edges within the chain (driver→assessment, driver→goal, goal→change). */
367
+ chainEdges: ChainEdge[];
368
+ /** Milestone markers below the chain, wrapped left→right by date. */
369
+ milestones: MilestoneMarker[];
370
+ /** Child activities below milestones. */
371
+ childActivities: ChildActivityRow[];
372
+
373
+ // ── Footer ────────────────────────────────────────────────────────────────
374
+ /** Notes row from `activity_card.notes`. Absent when empty. */
375
+ footerRow?: InfoRow;
376
+ }