@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.
Files changed (541) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +47 -0
  3. package/dist/__tests__/edge-path.test.d.ts +1 -0
  4. package/dist/__tests__/edge-path.test.js +39 -0
  5. package/dist/__tests__/scope.test.d.ts +1 -0
  6. package/dist/__tests__/scope.test.js +23 -0
  7. package/dist/__tests__/yaml-normalize.test.d.ts +1 -0
  8. package/dist/__tests__/yaml-normalize.test.js +148 -0
  9. package/dist/activities/__tests__/cpm.test.d.ts +1 -0
  10. package/dist/activities/__tests__/cpm.test.js +146 -0
  11. package/dist/activities/__tests__/gantt.test.d.ts +1 -0
  12. package/dist/activities/__tests__/gantt.test.js +224 -0
  13. package/dist/activities/__tests__/layout.test.d.ts +1 -0
  14. package/dist/activities/__tests__/layout.test.js +98 -0
  15. package/dist/activities/__tests__/validate.test.d.ts +1 -0
  16. package/dist/activities/__tests__/validate.test.js +363 -0
  17. package/dist/activities/cpm.d.ts +2 -0
  18. package/dist/activities/cpm.js +86 -0
  19. package/dist/activities/gantt.d.ts +6 -0
  20. package/dist/activities/gantt.js +250 -0
  21. package/dist/activities/index.d.ts +5 -0
  22. package/dist/activities/index.js +4 -0
  23. package/dist/activities/layout.d.ts +2 -0
  24. package/dist/activities/layout.js +103 -0
  25. package/dist/activities/types.d.ts +125 -0
  26. package/dist/activities/types.js +1 -0
  27. package/dist/activities/validate.d.ts +2 -0
  28. package/dist/activities/validate.js +326 -0
  29. package/dist/activity-card/__tests__/example.test.d.ts +1 -0
  30. package/dist/activity-card/__tests__/example.test.js +56 -0
  31. package/dist/activity-card/__tests__/layout.test.d.ts +1 -0
  32. package/dist/activity-card/__tests__/layout.test.js +57 -0
  33. package/dist/activity-card/__tests__/resolver.test.d.ts +1 -0
  34. package/dist/activity-card/__tests__/resolver.test.js +146 -0
  35. package/dist/activity-card/__tests__/validate.test.d.ts +1 -0
  36. package/dist/activity-card/__tests__/validate.test.js +116 -0
  37. package/dist/activity-card/index.d.ts +5 -0
  38. package/dist/activity-card/index.js +3 -0
  39. package/dist/activity-card/layout.d.ts +7 -0
  40. package/dist/activity-card/layout.js +167 -0
  41. package/dist/activity-card/resolver.d.ts +7 -0
  42. package/dist/activity-card/resolver.js +310 -0
  43. package/dist/activity-card/types.d.ts +175 -0
  44. package/dist/activity-card/types.js +20 -0
  45. package/dist/activity-card/validate.d.ts +3 -0
  46. package/dist/activity-card/validate.js +145 -0
  47. package/dist/actor/__tests__/validate.test.d.ts +1 -0
  48. package/dist/actor/__tests__/validate.test.js +57 -0
  49. package/dist/actor/index.d.ts +3 -0
  50. package/dist/actor/index.js +2 -0
  51. package/dist/actor/types.d.ts +20 -0
  52. package/dist/actor/types.js +4 -0
  53. package/dist/actor/validate.d.ts +2 -0
  54. package/dist/actor/validate.js +34 -0
  55. package/dist/applications/__tests__/validate.test.d.ts +1 -0
  56. package/dist/applications/__tests__/validate.test.js +223 -0
  57. package/dist/applications/index.d.ts +2 -0
  58. package/dist/applications/index.js +1 -0
  59. package/dist/applications/types.d.ts +39 -0
  60. package/dist/applications/types.js +1 -0
  61. package/dist/applications/validate.d.ts +3 -0
  62. package/dist/applications/validate.js +109 -0
  63. package/dist/assertion/__tests__/example.test.d.ts +1 -0
  64. package/dist/assertion/__tests__/example.test.js +32 -0
  65. package/dist/assertion/__tests__/validate.test.d.ts +1 -0
  66. package/dist/assertion/__tests__/validate.test.js +130 -0
  67. package/dist/assertion/index.d.ts +4 -0
  68. package/dist/assertion/index.js +2 -0
  69. package/dist/assertion/types.d.ts +43 -0
  70. package/dist/assertion/types.js +7 -0
  71. package/dist/assertion/validate.d.ts +9 -0
  72. package/dist/assertion/validate.js +137 -0
  73. package/dist/blocks/__tests__/layout.test.d.ts +1 -0
  74. package/dist/blocks/__tests__/layout.test.js +153 -0
  75. package/dist/blocks/__tests__/validate.test.d.ts +1 -0
  76. package/dist/blocks/__tests__/validate.test.js +235 -0
  77. package/dist/blocks/index.d.ts +4 -0
  78. package/dist/blocks/index.js +2 -0
  79. package/dist/blocks/layout.d.ts +4 -0
  80. package/dist/blocks/layout.js +145 -0
  81. package/dist/blocks/types.d.ts +56 -0
  82. package/dist/blocks/types.js +1 -0
  83. package/dist/blocks/validate.d.ts +9 -0
  84. package/dist/blocks/validate.js +186 -0
  85. package/dist/capability-map/__tests__/validate.test.d.ts +1 -0
  86. package/dist/capability-map/__tests__/validate.test.js +212 -0
  87. package/dist/capability-map/index.d.ts +2 -0
  88. package/dist/capability-map/index.js +1 -0
  89. package/dist/capability-map/types.d.ts +26 -0
  90. package/dist/capability-map/types.js +1 -0
  91. package/dist/capability-map/validate.d.ts +3 -0
  92. package/dist/capability-map/validate.js +103 -0
  93. package/dist/change/__tests__/validate.test.d.ts +1 -0
  94. package/dist/change/__tests__/validate.test.js +73 -0
  95. package/dist/change/index.d.ts +2 -0
  96. package/dist/change/index.js +1 -0
  97. package/dist/change/types.d.ts +17 -0
  98. package/dist/change/types.js +3 -0
  99. package/dist/change/validate.d.ts +2 -0
  100. package/dist/change/validate.js +57 -0
  101. package/dist/compliance/__tests__/classify.test.d.ts +1 -0
  102. package/dist/compliance/__tests__/classify.test.js +24 -0
  103. package/dist/compliance/__tests__/confidence.test.d.ts +1 -0
  104. package/dist/compliance/__tests__/confidence.test.js +78 -0
  105. package/dist/compliance/__tests__/coverage-metric.test.d.ts +1 -0
  106. package/dist/compliance/__tests__/coverage-metric.test.js +164 -0
  107. package/dist/compliance/__tests__/demo-scenario.test.d.ts +1 -0
  108. package/dist/compliance/__tests__/demo-scenario.test.js +226 -0
  109. package/dist/compliance/__tests__/example.test.d.ts +1 -0
  110. package/dist/compliance/__tests__/example.test.js +51 -0
  111. package/dist/compliance/__tests__/gap-report.test.d.ts +1 -0
  112. package/dist/compliance/__tests__/gap-report.test.js +113 -0
  113. package/dist/compliance/__tests__/html.test.d.ts +1 -0
  114. package/dist/compliance/__tests__/html.test.js +122 -0
  115. package/dist/compliance/__tests__/impact.test.d.ts +1 -0
  116. package/dist/compliance/__tests__/impact.test.js +410 -0
  117. package/dist/compliance/__tests__/markdown.test.d.ts +1 -0
  118. package/dist/compliance/__tests__/markdown.test.js +85 -0
  119. package/dist/compliance/__tests__/views.test.d.ts +1 -0
  120. package/dist/compliance/__tests__/views.test.js +59 -0
  121. package/dist/compliance/classify.d.ts +27 -0
  122. package/dist/compliance/classify.js +60 -0
  123. package/dist/compliance/confidence.d.ts +27 -0
  124. package/dist/compliance/confidence.js +43 -0
  125. package/dist/compliance/coverage-metric.d.ts +74 -0
  126. package/dist/compliance/coverage-metric.js +181 -0
  127. package/dist/compliance/gap-report.d.ts +20 -0
  128. package/dist/compliance/gap-report.js +64 -0
  129. package/dist/compliance/html.d.ts +22 -0
  130. package/dist/compliance/html.js +256 -0
  131. package/dist/compliance/impact.d.ts +251 -0
  132. package/dist/compliance/impact.js +464 -0
  133. package/dist/compliance/index.d.ts +16 -0
  134. package/dist/compliance/index.js +9 -0
  135. package/dist/compliance/markdown.d.ts +18 -0
  136. package/dist/compliance/markdown.js +129 -0
  137. package/dist/compliance/reverse-index.d.ts +8 -0
  138. package/dist/compliance/reverse-index.js +30 -0
  139. package/dist/compliance/types.d.ts +98 -0
  140. package/dist/compliance/types.js +5 -0
  141. package/dist/compliance/views.d.ts +14 -0
  142. package/dist/compliance/views.js +35 -0
  143. package/dist/compliance-matrix/__tests__/build.test.d.ts +1 -0
  144. package/dist/compliance-matrix/__tests__/build.test.js +183 -0
  145. package/dist/compliance-matrix/__tests__/example.test.d.ts +1 -0
  146. package/dist/compliance-matrix/__tests__/example.test.js +49 -0
  147. package/dist/compliance-matrix/build.d.ts +18 -0
  148. package/dist/compliance-matrix/build.js +0 -0
  149. package/dist/compliance-matrix/index.d.ts +2 -0
  150. package/dist/compliance-matrix/index.js +1 -0
  151. package/dist/compliance-matrix/types.d.ts +86 -0
  152. package/dist/compliance-matrix/types.js +8 -0
  153. package/dist/confidence/__tests__/score.test.d.ts +1 -0
  154. package/dist/confidence/__tests__/score.test.js +188 -0
  155. package/dist/confidence/index.d.ts +2 -0
  156. package/dist/confidence/index.js +1 -0
  157. package/dist/confidence/score.d.ts +62 -0
  158. package/dist/confidence/score.js +215 -0
  159. package/dist/confidence/types.d.ts +79 -0
  160. package/dist/confidence/types.js +6 -0
  161. package/dist/edge-path.d.ts +18 -0
  162. package/dist/edge-path.js +35 -0
  163. package/dist/element-envelope.d.ts +15 -0
  164. package/dist/element-envelope.js +55 -0
  165. package/dist/factor/__tests__/validate.test.d.ts +1 -0
  166. package/dist/factor/__tests__/validate.test.js +83 -0
  167. package/dist/factor/index.d.ts +3 -0
  168. package/dist/factor/index.js +2 -0
  169. package/dist/factor/types.d.ts +23 -0
  170. package/dist/factor/types.js +6 -0
  171. package/dist/factor/validate.d.ts +2 -0
  172. package/dist/factor/validate.js +69 -0
  173. package/dist/fgca/__tests__/chain-table.test.d.ts +1 -0
  174. package/dist/fgca/__tests__/chain-table.test.js +158 -0
  175. package/dist/fgca/__tests__/layout.test.d.ts +1 -0
  176. package/dist/fgca/__tests__/layout.test.js +140 -0
  177. package/dist/fgca/__tests__/parse-canonical.test.d.ts +1 -0
  178. package/dist/fgca/__tests__/parse-canonical.test.js +224 -0
  179. package/dist/fgca/__tests__/preview-layout.test.d.ts +1 -0
  180. package/dist/fgca/__tests__/preview-layout.test.js +106 -0
  181. package/dist/fgca/__tests__/validate.test.d.ts +1 -0
  182. package/dist/fgca/__tests__/validate.test.js +125 -0
  183. package/dist/fgca/chain-table.d.ts +36 -0
  184. package/dist/fgca/chain-table.js +177 -0
  185. package/dist/fgca/index.d.ts +16 -0
  186. package/dist/fgca/index.js +11 -0
  187. package/dist/fgca/layout.d.ts +27 -0
  188. package/dist/fgca/layout.js +156 -0
  189. package/dist/fgca/nodeTypes.d.ts +6 -0
  190. package/dist/fgca/nodeTypes.js +10 -0
  191. package/dist/fgca/nodes/FGCAActivityNode.d.ts +13 -0
  192. package/dist/fgca/nodes/FGCAActivityNode.js +35 -0
  193. package/dist/fgca/nodes/FGCAChangeNode.d.ts +12 -0
  194. package/dist/fgca/nodes/FGCAChangeNode.js +35 -0
  195. package/dist/fgca/nodes/FGCAFactorNode.d.ts +12 -0
  196. package/dist/fgca/nodes/FGCAFactorNode.js +35 -0
  197. package/dist/fgca/nodes/FGCAGoalNode.d.ts +14 -0
  198. package/dist/fgca/nodes/FGCAGoalNode.js +40 -0
  199. package/dist/fgca/parse-canonical.d.ts +58 -0
  200. package/dist/fgca/parse-canonical.js +339 -0
  201. package/dist/fgca/preview-layout.d.ts +87 -0
  202. package/dist/fgca/preview-layout.js +122 -0
  203. package/dist/fgca/types.d.ts +39 -0
  204. package/dist/fgca/types.js +7 -0
  205. package/dist/fgca/validate.d.ts +14 -0
  206. package/dist/fgca/validate.js +108 -0
  207. package/dist/geometry.d.ts +7 -0
  208. package/dist/geometry.js +2 -0
  209. package/dist/goals/__tests__/layout.test.d.ts +1 -0
  210. package/dist/goals/__tests__/layout.test.js +153 -0
  211. package/dist/goals/__tests__/mutations.test.d.ts +1 -0
  212. package/dist/goals/__tests__/mutations.test.js +95 -0
  213. package/dist/goals/__tests__/parse-canonical.test.d.ts +1 -0
  214. package/dist/goals/__tests__/parse-canonical.test.js +129 -0
  215. package/dist/goals/__tests__/validate.test.d.ts +1 -0
  216. package/dist/goals/__tests__/validate.test.js +183 -0
  217. package/dist/goals/index.d.ts +6 -0
  218. package/dist/goals/index.js +4 -0
  219. package/dist/goals/layout.d.ts +11 -0
  220. package/dist/goals/layout.js +147 -0
  221. package/dist/goals/mutations.d.ts +6 -0
  222. package/dist/goals/mutations.js +116 -0
  223. package/dist/goals/parse-canonical.d.ts +29 -0
  224. package/dist/goals/parse-canonical.js +257 -0
  225. package/dist/goals/types.d.ts +71 -0
  226. package/dist/goals/types.js +1 -0
  227. package/dist/goals/validate.d.ts +2 -0
  228. package/dist/goals/validate.js +122 -0
  229. package/dist/index.d.ts +23 -0
  230. package/dist/index.js +23 -0
  231. package/dist/issues/__tests__/layout.test.d.ts +1 -0
  232. package/dist/issues/__tests__/layout.test.js +62 -0
  233. package/dist/issues/__tests__/validate.test.d.ts +1 -0
  234. package/dist/issues/__tests__/validate.test.js +82 -0
  235. package/dist/issues/index.d.ts +4 -0
  236. package/dist/issues/index.js +2 -0
  237. package/dist/issues/layout.d.ts +10 -0
  238. package/dist/issues/layout.js +82 -0
  239. package/dist/issues/types.d.ts +61 -0
  240. package/dist/issues/types.js +6 -0
  241. package/dist/issues/validate.d.ts +3 -0
  242. package/dist/issues/validate.js +143 -0
  243. package/dist/process-blueprint/__tests__/compliance-lane.test.d.ts +1 -0
  244. package/dist/process-blueprint/__tests__/compliance-lane.test.js +272 -0
  245. package/dist/process-blueprint/__tests__/layout.test.d.ts +1 -0
  246. package/dist/process-blueprint/__tests__/layout.test.js +159 -0
  247. package/dist/process-blueprint/__tests__/validate.test.d.ts +1 -0
  248. package/dist/process-blueprint/__tests__/validate.test.js +280 -0
  249. package/dist/process-blueprint/index.d.ts +4 -0
  250. package/dist/process-blueprint/index.js +2 -0
  251. package/dist/process-blueprint/layout.d.ts +2 -0
  252. package/dist/process-blueprint/layout.js +416 -0
  253. package/dist/process-blueprint/types.d.ts +220 -0
  254. package/dist/process-blueprint/types.js +1 -0
  255. package/dist/process-blueprint/validate.d.ts +3 -0
  256. package/dist/process-blueprint/validate.js +165 -0
  257. package/dist/process-map/__tests__/validate.test.d.ts +1 -0
  258. package/dist/process-map/__tests__/validate.test.js +199 -0
  259. package/dist/process-map/index.d.ts +2 -0
  260. package/dist/process-map/index.js +1 -0
  261. package/dist/process-map/types.d.ts +32 -0
  262. package/dist/process-map/types.js +1 -0
  263. package/dist/process-map/validate.d.ts +3 -0
  264. package/dist/process-map/validate.js +115 -0
  265. package/dist/products/__tests__/validate.test.d.ts +1 -0
  266. package/dist/products/__tests__/validate.test.js +210 -0
  267. package/dist/products/index.d.ts +2 -0
  268. package/dist/products/index.js +1 -0
  269. package/dist/products/types.d.ts +28 -0
  270. package/dist/products/types.js +1 -0
  271. package/dist/products/validate.d.ts +3 -0
  272. package/dist/products/validate.js +93 -0
  273. package/dist/repo-validate/__tests__/validate-repo.test.d.ts +1 -0
  274. package/dist/repo-validate/__tests__/validate-repo.test.js +132 -0
  275. package/dist/repo-validate/index.d.ts +2 -0
  276. package/dist/repo-validate/index.js +1 -0
  277. package/dist/repo-validate/types.d.ts +34 -0
  278. package/dist/repo-validate/types.js +14 -0
  279. package/dist/repo-validate/validate-repo.d.ts +8 -0
  280. package/dist/repo-validate/validate-repo.js +189 -0
  281. package/dist/requirement/__tests__/example.test.d.ts +1 -0
  282. package/dist/requirement/__tests__/example.test.js +21 -0
  283. package/dist/requirement/__tests__/validate.test.d.ts +1 -0
  284. package/dist/requirement/__tests__/validate.test.js +80 -0
  285. package/dist/requirement/index.d.ts +4 -0
  286. package/dist/requirement/index.js +2 -0
  287. package/dist/requirement/types.d.ts +25 -0
  288. package/dist/requirement/types.js +4 -0
  289. package/dist/requirement/validate.d.ts +7 -0
  290. package/dist/requirement/validate.js +81 -0
  291. package/dist/scenarios/__tests__/validate.test.d.ts +1 -0
  292. package/dist/scenarios/__tests__/validate.test.js +183 -0
  293. package/dist/scenarios/index.d.ts +2 -0
  294. package/dist/scenarios/index.js +1 -0
  295. package/dist/scenarios/types.d.ts +45 -0
  296. package/dist/scenarios/types.js +1 -0
  297. package/dist/scenarios/validate.d.ts +3 -0
  298. package/dist/scenarios/validate.js +110 -0
  299. package/dist/schema-version.d.ts +16 -0
  300. package/dist/schema-version.js +16 -0
  301. package/dist/scope.d.ts +23 -0
  302. package/dist/scope.js +38 -0
  303. package/dist/stakeholder/__tests__/validate.test.d.ts +1 -0
  304. package/dist/stakeholder/__tests__/validate.test.js +86 -0
  305. package/dist/stakeholder/index.d.ts +3 -0
  306. package/dist/stakeholder/index.js +2 -0
  307. package/dist/stakeholder/types.d.ts +24 -0
  308. package/dist/stakeholder/types.js +5 -0
  309. package/dist/stakeholder/validate.d.ts +2 -0
  310. package/dist/stakeholder/validate.js +58 -0
  311. package/dist/target-state/__tests__/validate.test.d.ts +1 -0
  312. package/dist/target-state/__tests__/validate.test.js +62 -0
  313. package/dist/target-state/index.d.ts +2 -0
  314. package/dist/target-state/index.js +1 -0
  315. package/dist/target-state/types.d.ts +18 -0
  316. package/dist/target-state/types.js +7 -0
  317. package/dist/target-state/validate.d.ts +2 -0
  318. package/dist/target-state/validate.js +61 -0
  319. package/dist/theme/index.d.ts +4 -0
  320. package/dist/theme/index.js +2 -0
  321. package/dist/theme/themes.d.ts +16 -0
  322. package/dist/theme/themes.js +213 -0
  323. package/dist/theme/tokens.d.ts +158 -0
  324. package/dist/theme/tokens.js +105 -0
  325. package/dist/typed-id.d.ts +20 -0
  326. package/dist/typed-id.js +38 -0
  327. package/dist/validation-types.d.ts +34 -0
  328. package/dist/validation-types.js +1 -0
  329. package/dist/webview/__tests__/entry-notations.test.d.ts +1 -0
  330. package/dist/webview/__tests__/entry-notations.test.js +62 -0
  331. package/dist/webview/__tests__/entry.test.d.ts +1 -0
  332. package/dist/webview/__tests__/entry.test.js +56 -0
  333. package/dist/webview/__tests__/render-goals.test.d.ts +1 -0
  334. package/dist/webview/__tests__/render-goals.test.js +65 -0
  335. package/dist/webview/entry.d.ts +38 -0
  336. package/dist/webview/entry.js +182 -0
  337. package/dist/webview/render-activities.d.ts +24 -0
  338. package/dist/webview/render-activities.js +127 -0
  339. package/dist/webview/render-activity-card.d.ts +5 -0
  340. package/dist/webview/render-activity-card.js +168 -0
  341. package/dist/webview/render-applications.d.ts +11 -0
  342. package/dist/webview/render-applications.js +105 -0
  343. package/dist/webview/render-blocks.d.ts +5 -0
  344. package/dist/webview/render-blocks.js +71 -0
  345. package/dist/webview/render-capability-map.d.ts +7 -0
  346. package/dist/webview/render-capability-map.js +88 -0
  347. package/dist/webview/render-fgca.d.ts +8 -0
  348. package/dist/webview/render-fgca.js +94 -0
  349. package/dist/webview/render-goals.d.ts +6 -0
  350. package/dist/webview/render-goals.js +92 -0
  351. package/dist/webview/render-process-blueprint.d.ts +5 -0
  352. package/dist/webview/render-process-blueprint.js +135 -0
  353. package/dist/webview/render-process-map.d.ts +7 -0
  354. package/dist/webview/render-process-map.js +82 -0
  355. package/dist/webview/render-products.d.ts +7 -0
  356. package/dist/webview/render-products.js +81 -0
  357. package/dist/webview/render-scenarios.d.ts +7 -0
  358. package/dist/webview/render-scenarios.js +75 -0
  359. package/dist/webview/render-util.d.ts +16 -0
  360. package/dist/webview/render-util.js +31 -0
  361. package/dist/webview/transitrix-render.css +323 -0
  362. package/dist/webview/transitrix-render.js +6452 -0
  363. package/dist/webview/transitrix-render.js.map +7 -0
  364. package/dist/yaml-normalize.d.ts +20 -0
  365. package/dist/yaml-normalize.js +57 -0
  366. package/package.json +40 -0
  367. package/src/__tests__/edge-path.test.ts +46 -0
  368. package/src/__tests__/scope.test.ts +27 -0
  369. package/src/__tests__/yaml-normalize.test.ts +158 -0
  370. package/src/activities/__tests__/cpm.test.ts +164 -0
  371. package/src/activities/__tests__/gantt.test.ts +245 -0
  372. package/src/activities/__tests__/layout.test.ts +112 -0
  373. package/src/activities/__tests__/validate.test.ts +409 -0
  374. package/src/activities/cpm.ts +95 -0
  375. package/src/activities/gantt.ts +276 -0
  376. package/src/activities/index.ts +28 -0
  377. package/src/activities/layout.ts +112 -0
  378. package/src/activities/types.ts +148 -0
  379. package/src/activities/validate.ts +357 -0
  380. package/src/activity-card/__tests__/example.test.ts +66 -0
  381. package/src/activity-card/__tests__/layout.test.ts +63 -0
  382. package/src/activity-card/__tests__/resolver.test.ts +161 -0
  383. package/src/activity-card/__tests__/validate.test.ts +131 -0
  384. package/src/activity-card/index.ts +32 -0
  385. package/src/activity-card/layout.ts +194 -0
  386. package/src/activity-card/resolver.ts +337 -0
  387. package/src/activity-card/types.ts +237 -0
  388. package/src/activity-card/validate.ts +158 -0
  389. package/src/actor/__tests__/validate.test.ts +67 -0
  390. package/src/actor/index.ts +3 -0
  391. package/src/actor/types.ts +29 -0
  392. package/src/actor/validate.ts +38 -0
  393. package/src/applications/__tests__/validate.test.ts +256 -0
  394. package/src/applications/index.ts +11 -0
  395. package/src/applications/types.ts +43 -0
  396. package/src/applications/validate.ts +131 -0
  397. package/src/assertion/__tests__/example.test.ts +37 -0
  398. package/src/assertion/__tests__/validate.test.ts +142 -0
  399. package/src/assertion/index.ts +12 -0
  400. package/src/assertion/types.ts +58 -0
  401. package/src/assertion/validate.ts +145 -0
  402. package/src/blocks/__tests__/layout.test.ts +169 -0
  403. package/src/blocks/__tests__/validate.test.ts +260 -0
  404. package/src/blocks/index.ts +17 -0
  405. package/src/blocks/layout.ts +186 -0
  406. package/src/blocks/types.ts +62 -0
  407. package/src/blocks/validate.ts +206 -0
  408. package/src/capability-map/__tests__/validate.test.ts +238 -0
  409. package/src/capability-map/index.ts +8 -0
  410. package/src/capability-map/types.ts +29 -0
  411. package/src/capability-map/validate.ts +127 -0
  412. package/src/change/__tests__/validate.test.ts +88 -0
  413. package/src/change/index.ts +2 -0
  414. package/src/change/types.ts +23 -0
  415. package/src/change/validate.ts +61 -0
  416. package/src/compliance/__tests__/classify.test.ts +27 -0
  417. package/src/compliance/__tests__/confidence.test.ts +98 -0
  418. package/src/compliance/__tests__/coverage-metric.test.ts +188 -0
  419. package/src/compliance/__tests__/demo-scenario.test.ts +273 -0
  420. package/src/compliance/__tests__/example.test.ts +57 -0
  421. package/src/compliance/__tests__/gap-report.test.ts +129 -0
  422. package/src/compliance/__tests__/html.test.ts +142 -0
  423. package/src/compliance/__tests__/impact.test.ts +482 -0
  424. package/src/compliance/__tests__/markdown.test.ts +95 -0
  425. package/src/compliance/__tests__/views.test.ts +64 -0
  426. package/src/compliance/classify.ts +84 -0
  427. package/src/compliance/confidence.ts +69 -0
  428. package/src/compliance/coverage-metric.ts +263 -0
  429. package/src/compliance/gap-report.ts +94 -0
  430. package/src/compliance/html.ts +295 -0
  431. package/src/compliance/impact.ts +677 -0
  432. package/src/compliance/index.ts +56 -0
  433. package/src/compliance/markdown.ts +135 -0
  434. package/src/compliance/reverse-index.ts +33 -0
  435. package/src/compliance/types.ts +120 -0
  436. package/src/compliance/views.ts +46 -0
  437. package/src/compliance-matrix/__tests__/build.test.ts +200 -0
  438. package/src/compliance-matrix/__tests__/example.test.ts +57 -0
  439. package/src/compliance-matrix/build.ts +0 -0
  440. package/src/compliance-matrix/index.ts +11 -0
  441. package/src/compliance-matrix/types.ts +102 -0
  442. package/src/confidence/__tests__/score.test.ts +254 -0
  443. package/src/confidence/index.ts +21 -0
  444. package/src/confidence/score.ts +243 -0
  445. package/src/confidence/types.ts +96 -0
  446. package/src/edge-path.ts +44 -0
  447. package/src/element-envelope.ts +76 -0
  448. package/src/factor/__tests__/validate.test.ts +98 -0
  449. package/src/factor/index.ts +8 -0
  450. package/src/factor/types.ts +41 -0
  451. package/src/factor/validate.ts +74 -0
  452. package/src/fgca/__tests__/chain-table.test.ts +172 -0
  453. package/src/fgca/__tests__/layout.test.ts +179 -0
  454. package/src/fgca/__tests__/parse-canonical.test.ts +248 -0
  455. package/src/fgca/__tests__/preview-layout.test.ts +124 -0
  456. package/src/fgca/__tests__/validate.test.ts +142 -0
  457. package/src/fgca/chain-table.ts +225 -0
  458. package/src/fgca/index.ts +45 -0
  459. package/src/fgca/layout.ts +204 -0
  460. package/src/fgca/nodeTypes.ts +11 -0
  461. package/src/fgca/nodes/FGCAActivityNode.tsx +65 -0
  462. package/src/fgca/nodes/FGCAChangeNode.tsx +64 -0
  463. package/src/fgca/nodes/FGCAFactorNode.tsx +64 -0
  464. package/src/fgca/nodes/FGCAGoalNode.tsx +72 -0
  465. package/src/fgca/parse-canonical.ts +400 -0
  466. package/src/fgca/preview-layout.ts +217 -0
  467. package/src/fgca/types.ts +50 -0
  468. package/src/fgca/validate.ts +126 -0
  469. package/src/geometry.ts +9 -0
  470. package/src/goals/__tests__/layout.test.ts +175 -0
  471. package/src/goals/__tests__/mutations.test.ts +111 -0
  472. package/src/goals/__tests__/parse-canonical.test.ts +145 -0
  473. package/src/goals/__tests__/validate.test.ts +202 -0
  474. package/src/goals/index.ts +21 -0
  475. package/src/goals/layout.ts +172 -0
  476. package/src/goals/mutations.ts +123 -0
  477. package/src/goals/parse-canonical.ts +286 -0
  478. package/src/goals/types.ts +85 -0
  479. package/src/goals/validate.ts +136 -0
  480. package/src/index.ts +23 -0
  481. package/src/process-blueprint/__tests__/compliance-lane.test.ts +320 -0
  482. package/src/process-blueprint/__tests__/layout.test.ts +195 -0
  483. package/src/process-blueprint/__tests__/validate.test.ts +310 -0
  484. package/src/process-blueprint/index.ts +31 -0
  485. package/src/process-blueprint/layout.ts +531 -0
  486. package/src/process-blueprint/types.ts +242 -0
  487. package/src/process-blueprint/validate.ts +181 -0
  488. package/src/process-map/__tests__/validate.test.ts +223 -0
  489. package/src/process-map/index.ts +10 -0
  490. package/src/process-map/types.ts +36 -0
  491. package/src/process-map/validate.ts +135 -0
  492. package/src/products/__tests__/validate.test.ts +239 -0
  493. package/src/products/index.ts +9 -0
  494. package/src/products/types.ts +31 -0
  495. package/src/products/validate.ts +112 -0
  496. package/src/repo-validate/__tests__/validate-repo.test.ts +149 -0
  497. package/src/repo-validate/index.ts +2 -0
  498. package/src/repo-validate/types.ts +50 -0
  499. package/src/repo-validate/validate-repo.ts +196 -0
  500. package/src/requirement/__tests__/example.test.ts +24 -0
  501. package/src/requirement/__tests__/validate.test.ts +96 -0
  502. package/src/requirement/index.ts +4 -0
  503. package/src/requirement/types.ts +35 -0
  504. package/src/requirement/validate.ts +92 -0
  505. package/src/scenarios/__tests__/validate.test.ts +209 -0
  506. package/src/scenarios/index.ts +15 -0
  507. package/src/scenarios/types.ts +37 -0
  508. package/src/scenarios/validate.ts +122 -0
  509. package/src/schema-version.ts +16 -0
  510. package/src/scope.ts +46 -0
  511. package/src/stakeholder/__tests__/validate.test.ts +101 -0
  512. package/src/stakeholder/index.ts +3 -0
  513. package/src/stakeholder/types.ts +33 -0
  514. package/src/stakeholder/validate.ts +63 -0
  515. package/src/target-state/__tests__/validate.test.ts +74 -0
  516. package/src/target-state/index.ts +2 -0
  517. package/src/target-state/types.ts +28 -0
  518. package/src/target-state/validate.ts +67 -0
  519. package/src/theme/index.ts +4 -0
  520. package/src/theme/themes.ts +237 -0
  521. package/src/theme/tokens.ts +133 -0
  522. package/src/typed-id.ts +56 -0
  523. package/src/validation-types.ts +36 -0
  524. package/src/webview/__tests__/entry-notations.test.ts +77 -0
  525. package/src/webview/__tests__/entry.test.ts +64 -0
  526. package/src/webview/__tests__/render-goals.test.ts +72 -0
  527. package/src/webview/entry.ts +292 -0
  528. package/src/webview/render-activities.ts +156 -0
  529. package/src/webview/render-activity-card.ts +234 -0
  530. package/src/webview/render-applications.ts +123 -0
  531. package/src/webview/render-blocks.ts +91 -0
  532. package/src/webview/render-capability-map.ts +98 -0
  533. package/src/webview/render-fgca.ts +122 -0
  534. package/src/webview/render-goals.ts +110 -0
  535. package/src/webview/render-process-blueprint.ts +207 -0
  536. package/src/webview/render-process-map.ts +93 -0
  537. package/src/webview/render-products.ts +91 -0
  538. package/src/webview/render-scenarios.ts +90 -0
  539. package/src/webview/render-util.ts +34 -0
  540. package/src/webview/styles.css +323 -0
  541. package/src/yaml-normalize.ts +56 -0
@@ -0,0 +1,10 @@
1
+ import type { IssuesFile, IssuesLayout, IssuesLayoutOptions } from './types.js';
2
+ /**
3
+ * Lays an Issues document out as a nested outline: one row per issue, in
4
+ * pre-order, with x indented by nesting depth and y stacked top-to-bottom.
5
+ *
6
+ * Robust to malformed input — a broken `parent` reference is treated as a
7
+ * root, and a `parent` cycle cannot stack-overflow or drop nodes (a
8
+ * `placed` guard ensures every issue is laid out exactly once).
9
+ */
10
+ export declare function layoutIssues(file: IssuesFile, options?: IssuesLayoutOptions): IssuesLayout;
@@ -0,0 +1,82 @@
1
+ const DEFAULTS = {
2
+ rowHeight: 44,
3
+ rowGap: 10,
4
+ indentWidth: 32,
5
+ nodeWidth: 460,
6
+ paddingX: 0,
7
+ paddingY: 0,
8
+ };
9
+ /**
10
+ * Lays an Issues document out as a nested outline: one row per issue, in
11
+ * pre-order, with x indented by nesting depth and y stacked top-to-bottom.
12
+ *
13
+ * Robust to malformed input — a broken `parent` reference is treated as a
14
+ * root, and a `parent` cycle cannot stack-overflow or drop nodes (a
15
+ * `placed` guard ensures every issue is laid out exactly once).
16
+ */
17
+ export function layoutIssues(file, options = {}) {
18
+ const o = { ...DEFAULTS, ...options };
19
+ const issues = file?.issues_catalogue?.issues ?? [];
20
+ const byId = new Map();
21
+ for (const it of issues) {
22
+ if (it && typeof it.issue_id === 'string')
23
+ byId.set(it.issue_id, it);
24
+ }
25
+ const childrenOf = new Map();
26
+ const roots = [];
27
+ for (const it of issues) {
28
+ if (!it || typeof it.issue_id !== 'string')
29
+ continue;
30
+ const parent = it.parent;
31
+ if (typeof parent === 'string' && byId.has(parent) && parent !== it.issue_id) {
32
+ const arr = childrenOf.get(parent) ?? [];
33
+ arr.push(it.issue_id);
34
+ childrenOf.set(parent, arr);
35
+ }
36
+ else {
37
+ roots.push(it.issue_id);
38
+ }
39
+ }
40
+ const rows = [];
41
+ const placed = new Set();
42
+ let y = o.paddingY;
43
+ function place(id, depth) {
44
+ if (placed.has(id))
45
+ return; // cycle / duplicate guard
46
+ const issue = byId.get(id);
47
+ if (!issue)
48
+ return;
49
+ placed.add(id);
50
+ const kids = childrenOf.get(id) ?? [];
51
+ rows.push({
52
+ issue_id: id,
53
+ depth,
54
+ x: o.paddingX + depth * o.indentWidth,
55
+ y,
56
+ width: o.nodeWidth,
57
+ height: o.rowHeight,
58
+ data: issue,
59
+ hasChildren: kids.length > 0,
60
+ });
61
+ y += o.rowHeight + o.rowGap;
62
+ for (const childId of kids)
63
+ place(childId, depth + 1);
64
+ }
65
+ for (const rootId of roots)
66
+ place(rootId, 0);
67
+ // Any issue not reached above (e.g. trapped inside a parent cycle) is
68
+ // still laid out, at the root level, so nothing silently disappears.
69
+ for (const it of issues) {
70
+ if (it && typeof it.issue_id === 'string' && !placed.has(it.issue_id)) {
71
+ place(it.issue_id, 0);
72
+ }
73
+ }
74
+ if (rows.length === 0) {
75
+ return { rows: [], bounds: { x: 0, y: 0, width: 0, height: 0 } };
76
+ }
77
+ const minX = Math.min(...rows.map((r) => r.x));
78
+ const minY = Math.min(...rows.map((r) => r.y));
79
+ const maxX = Math.max(...rows.map((r) => r.x + r.width));
80
+ const maxY = Math.max(...rows.map((r) => r.y + r.height));
81
+ return { rows, bounds: { x: minX, y: minY, width: maxX - minX, height: maxY - minY } };
82
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Issues notation — a text-native register of issues (problems, defects,
3
+ * open questions) with parent/child nesting. See methodology spec
4
+ * `notations/12-issues.md`.
5
+ */
6
+ export type IssueStatus = 'open' | 'in_progress' | 'blocked' | 'resolved' | 'closed';
7
+ export interface Issue {
8
+ issue_id: string;
9
+ name: string;
10
+ status: IssueStatus;
11
+ /** issue_id of the parent issue — the nesting mechanism. */
12
+ parent?: string;
13
+ description?: string;
14
+ /** Typed IDs of ACTIVITY / GOAL elements this issue concerns. */
15
+ relates_to?: string[];
16
+ /** ROLE element ID of the role accountable for the issue. */
17
+ owner_role?: string;
18
+ }
19
+ export interface IssuesCatalogue {
20
+ id: string;
21
+ name: string;
22
+ description?: string;
23
+ version?: string;
24
+ updated_at: string;
25
+ issues: Issue[];
26
+ }
27
+ export interface IssuesFile {
28
+ notation: string;
29
+ spec_version?: string;
30
+ issues_catalogue: IssuesCatalogue;
31
+ }
32
+ export interface IssuesLayoutOptions {
33
+ rowHeight?: number;
34
+ rowGap?: number;
35
+ indentWidth?: number;
36
+ nodeWidth?: number;
37
+ paddingX?: number;
38
+ paddingY?: number;
39
+ }
40
+ export interface LaidOutIssue {
41
+ issue_id: string;
42
+ /** 0 for a root issue, +1 per nesting level. */
43
+ depth: number;
44
+ x: number;
45
+ y: number;
46
+ width: number;
47
+ height: number;
48
+ data: Issue;
49
+ hasChildren: boolean;
50
+ }
51
+ export interface IssuesLayoutBounds {
52
+ x: number;
53
+ y: number;
54
+ width: number;
55
+ height: number;
56
+ }
57
+ export interface IssuesLayout {
58
+ rows: LaidOutIssue[];
59
+ bounds: IssuesLayoutBounds;
60
+ }
61
+ export type { ValidationError, ValidationWarning, ValidationResult } from '../validation-types.js';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Issues notation — a text-native register of issues (problems, defects,
3
+ * open questions) with parent/child nesting. See methodology spec
4
+ * `notations/12-issues.md`.
5
+ */
6
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { ValidationError, ValidationWarning, ValidationResult } from './types.js';
2
+ export type { ValidationError, ValidationWarning, ValidationResult };
3
+ export declare function validateIssues(input: unknown): ValidationResult;
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Validates an Issues document against `notations/12-issues.md`.
3
+ *
4
+ * Error codes:
5
+ * - ISS-000 structural / header problem (not an object, wrong notation,
6
+ * missing issues_catalogue, missing catalogue fields)
7
+ * - ISS-001 duplicate issue_id
8
+ * - ISS-002 status outside the vocabulary
9
+ * - ISS-003 issue_id or name missing or empty
10
+ * - ISS-004 parent references a missing issue (warning)
11
+ * - ISS-005 cycle in the parent chain
12
+ * - ISS-006 relates_to entry is not an ACTIVITY- / GOAL- id
13
+ */
14
+ const STATUS_VALUES = ['open', 'in_progress', 'blocked', 'resolved', 'closed'];
15
+ const RELATES_TO_RE = /^(ACTIVITY|GOAL)(-[A-Z0-9][A-Z0-9_]*)*-\d+$/;
16
+ function isNonEmptyString(v) {
17
+ return typeof v === 'string' && v.trim().length > 0;
18
+ }
19
+ export function validateIssues(input) {
20
+ const errors = [];
21
+ const warnings = [];
22
+ if (!input || typeof input !== 'object') {
23
+ return { valid: false, errors: [{ code: 'ISS-000', message: 'Input must be an object' }], warnings };
24
+ }
25
+ const raw = input;
26
+ if ('notation' in raw && raw['notation'] !== 'issues') {
27
+ errors.push({ code: 'ISS-000', message: `notation must be "issues", got "${String(raw['notation'])}"` });
28
+ }
29
+ const catRaw = raw['issues_catalogue'];
30
+ if (!catRaw || typeof catRaw !== 'object') {
31
+ errors.push({ code: 'ISS-000', message: 'Missing required root key: issues_catalogue' });
32
+ return { valid: false, errors, warnings };
33
+ }
34
+ const cat = catRaw;
35
+ if (!isNonEmptyString(cat['id'])) {
36
+ errors.push({ code: 'ISS-000', message: 'issues_catalogue.id is required', path: 'issues_catalogue.id' });
37
+ }
38
+ if (!isNonEmptyString(cat['name'])) {
39
+ errors.push({ code: 'ISS-000', message: 'issues_catalogue.name is required', path: 'issues_catalogue.name' });
40
+ }
41
+ if (!isNonEmptyString(cat['updated_at'])) {
42
+ errors.push({ code: 'ISS-000', message: 'issues_catalogue.updated_at is required', path: 'issues_catalogue.updated_at' });
43
+ }
44
+ const issuesRaw = cat['issues'];
45
+ if (!Array.isArray(issuesRaw)) {
46
+ errors.push({ code: 'ISS-000', message: 'issues_catalogue.issues must be an array', path: 'issues_catalogue.issues' });
47
+ return { valid: false, errors, warnings };
48
+ }
49
+ const idSet = new Set();
50
+ for (let i = 0; i < issuesRaw.length; i++) {
51
+ const it = issuesRaw[i];
52
+ const path = `issues_catalogue.issues[${i}]`;
53
+ if (!it || typeof it !== 'object') {
54
+ errors.push({ code: 'ISS-003', message: `${path} must be an object`, path });
55
+ continue;
56
+ }
57
+ const issue = it;
58
+ const idOk = isNonEmptyString(issue['issue_id']);
59
+ if (!idOk) {
60
+ errors.push({ code: 'ISS-003', message: `${path}.issue_id is missing or empty`, path });
61
+ }
62
+ if (!isNonEmptyString(issue['name'])) {
63
+ errors.push({ code: 'ISS-003', message: `${path}.name is missing or empty`, path });
64
+ }
65
+ if (idOk) {
66
+ const id = issue['issue_id'].trim();
67
+ if (idSet.has(id)) {
68
+ errors.push({ code: 'ISS-001', message: `Duplicate issue_id: "${id}"`, path });
69
+ }
70
+ else {
71
+ idSet.add(id);
72
+ }
73
+ }
74
+ const status = issue['status'];
75
+ if (!STATUS_VALUES.includes(status)) {
76
+ errors.push({
77
+ code: 'ISS-002',
78
+ message: `${path}.status "${String(status)}" must be one of: ${STATUS_VALUES.join(', ')}`,
79
+ path,
80
+ });
81
+ }
82
+ const relates = issue['relates_to'];
83
+ if (relates !== undefined) {
84
+ if (!Array.isArray(relates)) {
85
+ errors.push({ code: 'ISS-006', message: `${path}.relates_to must be an array`, path });
86
+ }
87
+ else {
88
+ for (let j = 0; j < relates.length; j++) {
89
+ const ref = relates[j];
90
+ if (typeof ref !== 'string' || !RELATES_TO_RE.test(ref)) {
91
+ errors.push({
92
+ code: 'ISS-006',
93
+ message: `${path}.relates_to[${j}] "${String(ref)}" must be an ACTIVITY- or GOAL- id`,
94
+ path,
95
+ });
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ // parent reference + cycle checks — run once all ids are collected.
102
+ const parentOf = new Map();
103
+ for (let i = 0; i < issuesRaw.length; i++) {
104
+ const it = issuesRaw[i];
105
+ if (!it || typeof it !== 'object')
106
+ continue;
107
+ const issue = it;
108
+ const parent = issue['parent'];
109
+ const path = `issues_catalogue.issues[${i}]`;
110
+ if (parent === undefined)
111
+ continue;
112
+ if (typeof parent !== 'string' || !idSet.has(parent.trim())) {
113
+ warnings.push({
114
+ code: 'ISS-004',
115
+ message: `${path}.parent "${String(parent)}" does not resolve to a known issue — rendered at the root`,
116
+ path,
117
+ });
118
+ continue;
119
+ }
120
+ if (isNonEmptyString(issue['issue_id'])) {
121
+ parentOf.set(issue['issue_id'].trim(), parent.trim());
122
+ }
123
+ }
124
+ let cycleNode;
125
+ for (const start of parentOf.keys()) {
126
+ if (cycleNode)
127
+ break;
128
+ const seen = new Set();
129
+ let cur = start;
130
+ while (cur !== undefined) {
131
+ if (seen.has(cur)) {
132
+ cycleNode = cur;
133
+ break;
134
+ }
135
+ seen.add(cur);
136
+ cur = parentOf.get(cur);
137
+ }
138
+ }
139
+ if (cycleNode) {
140
+ errors.push({ code: 'ISS-005', message: `Cycle detected in the parent chain involving issue "${cycleNode}"` });
141
+ }
142
+ return { valid: errors.length === 0, errors, warnings };
143
+ }
@@ -0,0 +1,272 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { layoutProcessBlueprint } from '../layout.js';
3
+ // ── fixtures ────────────────────────────────────────────────────────────────
4
+ const STAGES = [
5
+ { id: 'STAGE-1', name: 'Receive', goal: 'g1', result: 'r1' },
6
+ { id: 'STAGE-2', name: 'Process', goal: 'g2', result: 'r2' },
7
+ { id: 'STAGE-3', name: 'Ship', goal: 'g3', result: 'r3' },
8
+ ];
9
+ function buildFile(overrides = {}) {
10
+ return {
11
+ notation: 'process-blueprint',
12
+ process_blueprint: { id: 'PROCESS_BLUEPRINT-T-1', name: 'Test', stages: STAGES, ...overrides },
13
+ };
14
+ }
15
+ const REQ_A = { id: 'REQ-1', derived_from: ['LAW-GDPR-1'] };
16
+ const REQ_B = { id: 'REQ-2', derived_from: ['LAW-GDPR-1', 'LAW-SOX-2'] };
17
+ const REQ_DEADLINE = {
18
+ id: 'REQ-3',
19
+ derived_from: ['LAW-PCI-3'],
20
+ deadline: '2020-01-01', // past_due
21
+ };
22
+ // ── helpers ─────────────────────────────────────────────────────────────────
23
+ function makeAssertion(about, status, realisedVia) {
24
+ return { about, status, realised_via: realisedVia };
25
+ }
26
+ function layout(file, input, overrides = {}) {
27
+ return layoutProcessBlueprint(file, {
28
+ complianceLane: { enabled: true, ...overrides },
29
+ complianceInput: input,
30
+ });
31
+ }
32
+ // ── tests ───────────────────────────────────────────────────────────────────
33
+ describe('compliance lane derivation', () => {
34
+ it('returns no complianceRow when lane is disabled (default)', () => {
35
+ const l = layoutProcessBlueprint(buildFile(), {});
36
+ expect(l.complianceRow).toBeUndefined();
37
+ });
38
+ it('returns no complianceRow when enabled but no input provided', () => {
39
+ const l = layoutProcessBlueprint(buildFile(), { complianceLane: { enabled: true } });
40
+ expect(l.complianceRow).toBeUndefined();
41
+ });
42
+ it('returns no complianceRow when assertions have no realised_via matching stage IDs', () => {
43
+ const input = {
44
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STEP-99'])],
45
+ requirements: [REQ_A],
46
+ };
47
+ const l = layout(buildFile(), input);
48
+ expect(l.complianceRow).toBeUndefined();
49
+ });
50
+ it('derives a chip for each law-stage pair', () => {
51
+ const input = {
52
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STAGE-1'])],
53
+ requirements: [REQ_A],
54
+ };
55
+ const l = layout(buildFile(), input);
56
+ expect(l.complianceRow).toBeDefined();
57
+ const chips = l.complianceRow.chips;
58
+ expect(chips).toHaveLength(1);
59
+ expect(chips[0].lawId).toBe('LAW-GDPR-1');
60
+ expect(chips[0].stageIndex).toBe(0);
61
+ });
62
+ it('produces one chip per law per stage (same law, two stages → two chips)', () => {
63
+ const input = {
64
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STAGE-1', 'STAGE-2'])],
65
+ requirements: [REQ_A],
66
+ };
67
+ const l = layout(buildFile(), input);
68
+ const chips = l.complianceRow.chips;
69
+ expect(chips).toHaveLength(2);
70
+ expect(chips.map(c => c.stageIndex).sort()).toEqual([0, 1]);
71
+ expect(chips.every(c => c.lawId === 'LAW-GDPR-1')).toBe(true);
72
+ });
73
+ it('merges multiple assertions for the same law-stage into one chip', () => {
74
+ const input = {
75
+ assertions: [
76
+ makeAssertion('REQ-1', 'compliant', ['STAGE-1']),
77
+ makeAssertion('REQ-1', 'partial', ['STAGE-1']),
78
+ ],
79
+ requirements: [REQ_A],
80
+ };
81
+ const l = layout(buildFile(), input);
82
+ expect(l.complianceRow.chips).toHaveLength(1);
83
+ });
84
+ describe('decoration: new', () => {
85
+ it('marks chip as new when law is not in previous snapshot', () => {
86
+ const input = {
87
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STAGE-1'])],
88
+ requirements: [REQ_A],
89
+ };
90
+ const l = layout(buildFile(), input, { previousSnapshot: { 'STAGE-1': [] } });
91
+ expect(l.complianceRow.chips[0].decorations).toContain('new');
92
+ });
93
+ it('does not mark chip as new when law is in previous snapshot', () => {
94
+ const input = {
95
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STAGE-1'])],
96
+ requirements: [REQ_A],
97
+ };
98
+ const l = layout(buildFile(), input, { previousSnapshot: { 'STAGE-1': ['LAW-GDPR-1'] } });
99
+ expect(l.complianceRow.chips[0].decorations).not.toContain('new');
100
+ });
101
+ });
102
+ describe('decoration: gap', () => {
103
+ it('marks chip as gap when assertion status is non_compliant', () => {
104
+ const input = {
105
+ assertions: [makeAssertion('REQ-1', 'non_compliant', ['STAGE-1'])],
106
+ requirements: [REQ_A],
107
+ };
108
+ const l = layout(buildFile(), input);
109
+ expect(l.complianceRow.chips[0].decorations).toContain('gap');
110
+ });
111
+ it('marks chip as gap when assertion status is partial', () => {
112
+ const input = {
113
+ assertions: [makeAssertion('REQ-1', 'partial', ['STAGE-2'])],
114
+ requirements: [REQ_A],
115
+ };
116
+ const l = layout(buildFile(), input);
117
+ expect(l.complianceRow.chips[0].decorations).toContain('gap');
118
+ });
119
+ it('does not mark chip as gap for compliant assertion', () => {
120
+ const input = {
121
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STAGE-1'])],
122
+ requirements: [REQ_A],
123
+ };
124
+ const l = layout(buildFile(), input);
125
+ expect(l.complianceRow.chips[0].decorations).not.toContain('gap');
126
+ });
127
+ it('propagates gap if any assertion for the same law-stage is non-compliant', () => {
128
+ const input = {
129
+ assertions: [
130
+ makeAssertion('REQ-1', 'compliant', ['STAGE-1']),
131
+ makeAssertion('REQ-1', 'non_compliant', ['STAGE-1']),
132
+ ],
133
+ requirements: [REQ_A],
134
+ };
135
+ const l = layout(buildFile(), input);
136
+ expect(l.complianceRow.chips[0].decorations).toContain('gap');
137
+ });
138
+ });
139
+ describe('decoration: deadline', () => {
140
+ it('marks chip as deadline when gap exists and requirement deadline is past_due', () => {
141
+ const input = {
142
+ assertions: [makeAssertion('REQ-3', 'non_compliant', ['STAGE-1'])],
143
+ requirements: [REQ_DEADLINE],
144
+ };
145
+ const l = layout(buildFile(), input);
146
+ const d = l.complianceRow.chips[0].decorations;
147
+ expect(d).toContain('gap');
148
+ expect(d).toContain('deadline');
149
+ });
150
+ it('does not mark deadline when gap is absent even if deadline is past_due', () => {
151
+ const input = {
152
+ assertions: [makeAssertion('REQ-3', 'compliant', ['STAGE-1'])],
153
+ requirements: [REQ_DEADLINE],
154
+ };
155
+ const l = layout(buildFile(), input);
156
+ expect(l.complianceRow.chips[0].decorations).not.toContain('deadline');
157
+ });
158
+ it('does not mark deadline when no deadline on requirement', () => {
159
+ const input = {
160
+ assertions: [makeAssertion('REQ-1', 'non_compliant', ['STAGE-1'])],
161
+ requirements: [REQ_A],
162
+ };
163
+ const l = layout(buildFile(), input);
164
+ expect(l.complianceRow.chips[0].decorations).not.toContain('deadline');
165
+ });
166
+ it('all three decorations can stack on the same chip', () => {
167
+ const input = {
168
+ assertions: [makeAssertion('REQ-3', 'non_compliant', ['STAGE-1'])],
169
+ requirements: [REQ_DEADLINE],
170
+ };
171
+ const l = layout(buildFile(), input, { previousSnapshot: { 'STAGE-1': [] } });
172
+ const d = l.complianceRow.chips[0].decorations;
173
+ expect(d).toContain('new');
174
+ expect(d).toContain('gap');
175
+ expect(d).toContain('deadline');
176
+ });
177
+ });
178
+ describe('jurisdiction filter', () => {
179
+ it('passes through all laws when no jurisdictions filter', () => {
180
+ const input = {
181
+ assertions: [makeAssertion('REQ-2', 'compliant', ['STAGE-1'])],
182
+ requirements: [REQ_B], // derived_from: [LAW-GDPR-1, LAW-SOX-2]
183
+ codexJurisdictions: { 'LAW-GDPR-1': 'EU', 'LAW-SOX-2': 'US' },
184
+ };
185
+ const l = layout(buildFile(), input, { jurisdictions: [] });
186
+ expect(l.complianceRow.chips).toHaveLength(2);
187
+ });
188
+ it('filters to only the selected jurisdictions', () => {
189
+ const input = {
190
+ assertions: [makeAssertion('REQ-2', 'compliant', ['STAGE-1'])],
191
+ requirements: [REQ_B],
192
+ codexJurisdictions: { 'LAW-GDPR-1': 'EU', 'LAW-SOX-2': 'US' },
193
+ };
194
+ const l = layout(buildFile(), input, { jurisdictions: ['EU'] });
195
+ expect(l.complianceRow.chips).toHaveLength(1);
196
+ expect(l.complianceRow.chips[0].lawId).toBe('LAW-GDPR-1');
197
+ });
198
+ it('returns no row when jurisdiction filter excludes all laws', () => {
199
+ const input = {
200
+ assertions: [makeAssertion('REQ-2', 'compliant', ['STAGE-1'])],
201
+ requirements: [REQ_B],
202
+ codexJurisdictions: { 'LAW-GDPR-1': 'EU', 'LAW-SOX-2': 'US' },
203
+ };
204
+ const l = layout(buildFile(), input, { jurisdictions: ['AU'] });
205
+ expect(l.complianceRow).toBeUndefined();
206
+ });
207
+ });
208
+ describe('null-guards', () => {
209
+ it('tolerates null assertion entries without throwing', () => {
210
+ const input = {
211
+ assertions: [null, makeAssertion('REQ-1', 'compliant', ['STAGE-1'])],
212
+ requirements: [REQ_A],
213
+ };
214
+ expect(() => layout(buildFile(), input)).not.toThrow();
215
+ });
216
+ it('skips assertions with no realised_via', () => {
217
+ const input = {
218
+ assertions: [{ about: 'REQ-1', status: 'compliant' }],
219
+ requirements: [REQ_A],
220
+ };
221
+ const l = layout(buildFile(), input);
222
+ expect(l.complianceRow).toBeUndefined();
223
+ });
224
+ it('skips assertions whose requirement is not in the input', () => {
225
+ const input = {
226
+ assertions: [makeAssertion('REQ-MISSING', 'non_compliant', ['STAGE-1'])],
227
+ requirements: [REQ_A],
228
+ };
229
+ const l = layout(buildFile(), input);
230
+ expect(l.complianceRow).toBeUndefined();
231
+ });
232
+ });
233
+ describe('legend', () => {
234
+ it('adds a compliance legend entry when the row is present', () => {
235
+ const input = {
236
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STAGE-1'])],
237
+ requirements: [REQ_A],
238
+ };
239
+ const l = layout(buildFile(), input);
240
+ const complianceLegend = l.legend.find(entry => entry.kind === 'compliance');
241
+ expect(complianceLegend).toBeDefined();
242
+ expect(complianceLegend.label).toBe('Compliance');
243
+ });
244
+ it('does not add compliance legend when row is absent', () => {
245
+ const l = layoutProcessBlueprint(buildFile(), {});
246
+ expect(l.legend.some(e => e.kind === 'compliance')).toBe(false);
247
+ });
248
+ });
249
+ describe('layout geometry', () => {
250
+ it('total height grows by the compliance row height', () => {
251
+ const withoutLane = layoutProcessBlueprint(buildFile(), {});
252
+ const input = {
253
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STAGE-1'])],
254
+ requirements: [REQ_A],
255
+ };
256
+ const withLane = layout(buildFile(), input);
257
+ expect(withLane.bounds.height).toBeGreaterThan(withoutLane.bounds.height);
258
+ expect(withLane.bounds.height).toBe(withoutLane.bounds.height + withLane.complianceRow.height);
259
+ });
260
+ it('chip x aligns to the stage column', () => {
261
+ const input = {
262
+ assertions: [makeAssertion('REQ-1', 'compliant', ['STAGE-2'])],
263
+ requirements: [REQ_A],
264
+ };
265
+ const l = layout(buildFile(), input);
266
+ const chip = l.complianceRow.chips[0];
267
+ // Chip x must be at the start of stage-2's column (index 1) + cellPadding.
268
+ const expectedX = l.legendColumnWidth + 1 * l.stageColumnWidth + 8; // default cellPadding = 8
269
+ expect(chip.x).toBe(expectedX);
270
+ });
271
+ });
272
+ });
@@ -0,0 +1 @@
1
+ export {};