@diagrammo/dgmo 0.47.0 → 0.48.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 (319) hide show
  1. package/dist/auto.js +1 -1
  2. package/dist/auto.mjs +1 -1
  3. package/dist/element.js +1 -1
  4. package/dist/element.mjs +1 -1
  5. package/package.json +19 -70
  6. package/dist/advanced.cjs +0 -71648
  7. package/dist/advanced.d.cts +0 -5719
  8. package/dist/auto.cjs +0 -70648
  9. package/dist/auto.d.cts +0 -54
  10. package/dist/block.cjs +0 -70208
  11. package/dist/block.d.cts +0 -115
  12. package/dist/editor.cjs +0 -526
  13. package/dist/editor.d.cts +0 -26
  14. package/dist/element.cjs +0 -70530
  15. package/dist/element.d.cts +0 -62
  16. package/dist/highlight.cjs +0 -852
  17. package/dist/highlight.d.cts +0 -49
  18. package/dist/index.cjs +0 -70491
  19. package/dist/index.d.cts +0 -160
  20. package/dist/pert.cjs +0 -325
  21. package/dist/pert.d.cts +0 -559
  22. package/dist/themes-1-CuKpeH.d.cts +0 -908
  23. package/src/advanced.ts +0 -873
  24. package/src/arc/parser.ts +0 -15
  25. package/src/arc/renderer.ts +0 -633
  26. package/src/auto/index.ts +0 -621
  27. package/src/auto/shared.ts +0 -370
  28. package/src/auto/styles.ts +0 -73
  29. package/src/block/layout.ts +0 -198
  30. package/src/block/parser.ts +0 -427
  31. package/src/block/renderer.ts +0 -484
  32. package/src/block/types.ts +0 -67
  33. package/src/boxes-and-lines/collapse.ts +0 -96
  34. package/src/boxes-and-lines/focus.ts +0 -257
  35. package/src/boxes-and-lines/label-placement.ts +0 -339
  36. package/src/boxes-and-lines/layout-grouped.ts +0 -912
  37. package/src/boxes-and-lines/layout-layered.ts +0 -722
  38. package/src/boxes-and-lines/layout-search.ts +0 -1678
  39. package/src/boxes-and-lines/layout.ts +0 -398
  40. package/src/boxes-and-lines/parser.ts +0 -1181
  41. package/src/boxes-and-lines/renderer.ts +0 -1465
  42. package/src/boxes-and-lines/types.ts +0 -66
  43. package/src/c4/layout.ts +0 -2441
  44. package/src/c4/parser.ts +0 -1158
  45. package/src/c4/renderer.ts +0 -2008
  46. package/src/c4/types.ts +0 -89
  47. package/src/chart-type-registry.ts +0 -529
  48. package/src/chart-types.ts +0 -225
  49. package/src/chart.ts +0 -685
  50. package/src/charts-d3/bar.ts +0 -338
  51. package/src/charts-d3/chord.ts +0 -140
  52. package/src/charts-d3/function.ts +0 -147
  53. package/src/charts-d3/funnel.ts +0 -104
  54. package/src/charts-d3/heatmap.ts +0 -145
  55. package/src/charts-d3/index.ts +0 -337
  56. package/src/charts-d3/interactions.ts +0 -477
  57. package/src/charts-d3/line.ts +0 -344
  58. package/src/charts-d3/mount.ts +0 -151
  59. package/src/charts-d3/pie.ts +0 -117
  60. package/src/charts-d3/polar.ts +0 -89
  61. package/src/charts-d3/radar.ts +0 -0
  62. package/src/charts-d3/sankey.ts +0 -0
  63. package/src/charts-d3/scatter.ts +0 -185
  64. package/src/charts-d3/shared.ts +0 -208
  65. package/src/class/layout.ts +0 -326
  66. package/src/class/parser.ts +0 -635
  67. package/src/class/renderer.ts +0 -793
  68. package/src/class/types.ts +0 -58
  69. package/src/cli-banner.ts +0 -106
  70. package/src/cli.ts +0 -1080
  71. package/src/colors-diagnostics.ts +0 -35
  72. package/src/colors.ts +0 -379
  73. package/src/completion-types.ts +0 -27
  74. package/src/completion.ts +0 -2668
  75. package/src/cycle/layout.ts +0 -1026
  76. package/src/cycle/parser.ts +0 -387
  77. package/src/cycle/renderer.ts +0 -653
  78. package/src/cycle/types.ts +0 -101
  79. package/src/d3.ts +0 -1434
  80. package/src/data-chart-parser.ts +0 -1007
  81. package/src/dgmo-router.ts +0 -296
  82. package/src/diagnostics-registry.ts +0 -108
  83. package/src/diagnostics.ts +0 -0
  84. package/src/dimensions.ts +0 -20
  85. package/src/directives-registry.ts +0 -396
  86. package/src/editor/dgmo.grammar +0 -76
  87. package/src/editor/dgmo.grammar.d.ts +0 -2
  88. package/src/editor/dgmo.grammar.js +0 -18
  89. package/src/editor/dgmo.grammar.terms.d.ts +0 -5
  90. package/src/editor/dgmo.grammar.terms.js +0 -35
  91. package/src/editor/highlight-api.ts +0 -596
  92. package/src/editor/highlight.ts +0 -36
  93. package/src/editor/index.ts +0 -27
  94. package/src/editor/keywords.ts +0 -128
  95. package/src/editor/tokens.ts +0 -30
  96. package/src/element/index.ts +0 -432
  97. package/src/embed/css.ts +0 -312
  98. package/src/embed/escape.ts +0 -15
  99. package/src/embed/index.ts +0 -280
  100. package/src/er/classify.ts +0 -228
  101. package/src/er/layout.ts +0 -530
  102. package/src/er/parser.ts +0 -750
  103. package/src/er/renderer.ts +0 -725
  104. package/src/er/types.ts +0 -52
  105. package/src/error-card.ts +0 -269
  106. package/src/event-line/diagnostics.ts +0 -117
  107. package/src/event-line/parser.ts +0 -643
  108. package/src/event-line/renderer.ts +0 -1742
  109. package/src/event-line/types.ts +0 -74
  110. package/src/fonts.ts +0 -3
  111. package/src/gantt/calculator.ts +0 -979
  112. package/src/gantt/parser.ts +0 -1641
  113. package/src/gantt/renderer.ts +0 -3787
  114. package/src/gantt/resolver.ts +0 -172
  115. package/src/gantt/types.ts +0 -206
  116. package/src/graph/diagnostics.ts +0 -64
  117. package/src/graph/edge-spline.ts +0 -29
  118. package/src/graph/flowchart-parser.ts +0 -759
  119. package/src/graph/flowchart-renderer.ts +0 -817
  120. package/src/graph/layout.ts +0 -472
  121. package/src/graph/notes.ts +0 -21
  122. package/src/graph/state-collapse.ts +0 -78
  123. package/src/graph/state-parser.ts +0 -574
  124. package/src/graph/state-renderer.ts +0 -653
  125. package/src/graph/types.ts +0 -65
  126. package/src/index.ts +0 -261
  127. package/src/infra/compute.ts +0 -1385
  128. package/src/infra/layout.ts +0 -888
  129. package/src/infra/parser.ts +0 -1234
  130. package/src/infra/renderer.ts +0 -2534
  131. package/src/infra/roles.ts +0 -75
  132. package/src/infra/types.ts +0 -216
  133. package/src/infra/validation.ts +0 -201
  134. package/src/journey-map/layout.ts +0 -490
  135. package/src/journey-map/parser.ts +0 -557
  136. package/src/journey-map/renderer.ts +0 -1580
  137. package/src/journey-map/types.ts +0 -47
  138. package/src/kanban/mutations.ts +0 -175
  139. package/src/kanban/parser.ts +0 -509
  140. package/src/kanban/renderer.ts +0 -1449
  141. package/src/kanban/types.ts +0 -39
  142. package/src/label-layout.ts +0 -368
  143. package/src/map/colorize.ts +0 -54
  144. package/src/map/completion.ts +0 -316
  145. package/src/map/context-labels.ts +0 -609
  146. package/src/map/data/PROVENANCE.json +0 -1
  147. package/src/map/data/README.md +0 -40
  148. package/src/map/data/airport-collisions.json +0 -1
  149. package/src/map/data/airports.json +0 -1
  150. package/src/map/data/gazetteer.json +0 -1
  151. package/src/map/data/lakes.json +0 -1
  152. package/src/map/data/mountain-ranges.json +0 -1
  153. package/src/map/data/na-lakes.json +0 -1
  154. package/src/map/data/na-land.json +0 -1
  155. package/src/map/data/region-names.json +0 -1
  156. package/src/map/data/rivers.json +0 -1
  157. package/src/map/data/types.ts +0 -121
  158. package/src/map/data/us-states.json +0 -1
  159. package/src/map/data/water-bodies.json +0 -1
  160. package/src/map/data/world-coarse.json +0 -1
  161. package/src/map/data/world-detail.json +0 -1
  162. package/src/map/diagnostics.ts +0 -134
  163. package/src/map/dimensions.ts +0 -150
  164. package/src/map/geo-query.ts +0 -295
  165. package/src/map/geo.ts +0 -438
  166. package/src/map/invert.ts +0 -111
  167. package/src/map/layout.ts +0 -5069
  168. package/src/map/legend-band.ts +0 -127
  169. package/src/map/load-data.ts +0 -186
  170. package/src/map/parser.ts +0 -783
  171. package/src/map/renderer.ts +0 -1445
  172. package/src/map/resolved-types.ts +0 -160
  173. package/src/map/resolver.ts +0 -1146
  174. package/src/map/types.ts +0 -194
  175. package/src/mindmap/collapse.ts +0 -67
  176. package/src/mindmap/layout.ts +0 -649
  177. package/src/mindmap/parser.ts +0 -430
  178. package/src/mindmap/renderer.ts +0 -637
  179. package/src/mindmap/text-wrap.ts +0 -218
  180. package/src/mindmap/types.ts +0 -56
  181. package/src/org/collapse.ts +0 -151
  182. package/src/org/layout.ts +0 -1262
  183. package/src/org/parser.ts +0 -519
  184. package/src/org/renderer.ts +0 -866
  185. package/src/org/resolver.ts +0 -636
  186. package/src/palettes/atlas.ts +0 -77
  187. package/src/palettes/blueprint.ts +0 -73
  188. package/src/palettes/catppuccin.ts +0 -84
  189. package/src/palettes/color-utils.ts +0 -443
  190. package/src/palettes/index.ts +0 -67
  191. package/src/palettes/nord.ts +0 -67
  192. package/src/palettes/registry.ts +0 -114
  193. package/src/palettes/slate.ts +0 -73
  194. package/src/palettes/tidewater.ts +0 -73
  195. package/src/palettes/tokyo-night.ts +0 -86
  196. package/src/palettes/types.ts +0 -88
  197. package/src/pert/analyzer.ts +0 -1183
  198. package/src/pert/diagnostics.ts +0 -110
  199. package/src/pert/index.ts +0 -43
  200. package/src/pert/internal.ts +0 -252
  201. package/src/pert/layout.ts +0 -971
  202. package/src/pert/monte-carlo.ts +0 -446
  203. package/src/pert/parser.ts +0 -1606
  204. package/src/pert/renderer.ts +0 -4009
  205. package/src/pert/share-normalize.ts +0 -62
  206. package/src/pert/types.ts +0 -604
  207. package/src/pyramid/parser.ts +0 -185
  208. package/src/pyramid/renderer.ts +0 -768
  209. package/src/pyramid/types.ts +0 -28
  210. package/src/quadrant/parser.ts +0 -18
  211. package/src/quadrant/renderer.ts +0 -638
  212. package/src/raci/diagnostics.ts +0 -213
  213. package/src/raci/index.ts +0 -23
  214. package/src/raci/mutations.ts +0 -321
  215. package/src/raci/parser.ts +0 -699
  216. package/src/raci/renderer.ts +0 -1627
  217. package/src/raci/types.ts +0 -82
  218. package/src/raci/variants.ts +0 -320
  219. package/src/render.ts +0 -268
  220. package/src/ring/parser.ts +0 -212
  221. package/src/ring/renderer.ts +0 -490
  222. package/src/ring/types.ts +0 -27
  223. package/src/sequence/collapse.ts +0 -174
  224. package/src/sequence/parser.ts +0 -1596
  225. package/src/sequence/participant-inference.ts +0 -152
  226. package/src/sequence/renderer.ts +0 -3168
  227. package/src/sequence/tag-resolution.ts +0 -164
  228. package/src/sharing.ts +0 -211
  229. package/src/sitemap/collapse.ts +0 -100
  230. package/src/sitemap/layout.ts +0 -925
  231. package/src/sitemap/parser.ts +0 -755
  232. package/src/sitemap/renderer.ts +0 -828
  233. package/src/sitemap/types.ts +0 -42
  234. package/src/slope/parser.ts +0 -18
  235. package/src/slope/renderer.ts +0 -378
  236. package/src/swimlane/diagnostics.ts +0 -94
  237. package/src/swimlane/layout.ts +0 -597
  238. package/src/swimlane/parser.ts +0 -613
  239. package/src/swimlane/renderer.ts +0 -681
  240. package/src/swimlane/types.ts +0 -151
  241. package/src/tech-radar/interactive.ts +0 -1129
  242. package/src/tech-radar/layout.ts +0 -197
  243. package/src/tech-radar/parser.ts +0 -436
  244. package/src/tech-radar/renderer.ts +0 -1239
  245. package/src/tech-radar/shared.ts +0 -151
  246. package/src/tech-radar/types.ts +0 -86
  247. package/src/themes.ts +0 -22
  248. package/src/timeline/parser.ts +0 -472
  249. package/src/timeline/renderer.ts +0 -3024
  250. package/src/timeline/types.ts +0 -33
  251. package/src/timeline/viz-parser.ts +0 -21
  252. package/src/treemap/diagnostics.ts +0 -62
  253. package/src/treemap/layout-radial.ts +0 -233
  254. package/src/treemap/layout.ts +0 -189
  255. package/src/treemap/parser.ts +0 -463
  256. package/src/treemap/renderer-radial.ts +0 -438
  257. package/src/treemap/renderer.ts +0 -572
  258. package/src/treemap/treemap-shared.ts +0 -309
  259. package/src/treemap/types.ts +0 -60
  260. package/src/utils/arrow-markers.ts +0 -51
  261. package/src/utils/arrows-diagnostics.ts +0 -62
  262. package/src/utils/arrows.ts +0 -227
  263. package/src/utils/brand.ts +0 -61
  264. package/src/utils/card.ts +0 -183
  265. package/src/utils/collapse-engine/tree-edges.ts +0 -115
  266. package/src/utils/collapse-engine/tree.ts +0 -117
  267. package/src/utils/d3-helpers.ts +0 -219
  268. package/src/utils/d3-types.ts +0 -9
  269. package/src/utils/description-helpers.ts +0 -38
  270. package/src/utils/duration.ts +0 -312
  271. package/src/utils/export-container.ts +0 -41
  272. package/src/utils/expr-eval.ts +0 -27
  273. package/src/utils/fit-canvas.ts +0 -64
  274. package/src/utils/hover-styles.ts +0 -673
  275. package/src/utils/inline-markdown.ts +0 -96
  276. package/src/utils/legend-constants.ts +0 -48
  277. package/src/utils/legend-d3.ts +0 -618
  278. package/src/utils/legend-integration.ts +0 -107
  279. package/src/utils/legend-layout.ts +0 -776
  280. package/src/utils/legend-svg.ts +0 -214
  281. package/src/utils/legend-types.ts +0 -272
  282. package/src/utils/name-normalize.ts +0 -163
  283. package/src/utils/note-box/constants.ts +0 -25
  284. package/src/utils/note-box/index.ts +0 -11
  285. package/src/utils/note-box/metrics.ts +0 -90
  286. package/src/utils/note-box/svg.ts +0 -331
  287. package/src/utils/notes/bounds.ts +0 -30
  288. package/src/utils/notes/build.ts +0 -131
  289. package/src/utils/notes/index.ts +0 -18
  290. package/src/utils/notes/model.ts +0 -19
  291. package/src/utils/notes/parse.ts +0 -131
  292. package/src/utils/notes/place.ts +0 -177
  293. package/src/utils/notes/resolve.ts +0 -88
  294. package/src/utils/number-format.ts +0 -36
  295. package/src/utils/parsing.ts +0 -953
  296. package/src/utils/reserved-key-registry.ts +0 -239
  297. package/src/utils/safe-href.ts +0 -38
  298. package/src/utils/scaling.ts +0 -97
  299. package/src/utils/svg-embed.ts +0 -251
  300. package/src/utils/tag-groups.ts +0 -607
  301. package/src/utils/text-measure.ts +0 -122
  302. package/src/utils/time-ticks.ts +0 -253
  303. package/src/utils/title-constants.ts +0 -24
  304. package/src/utils/visual-conventions.ts +0 -61
  305. package/src/utils/wrapped-desc.ts +0 -87
  306. package/src/venn/parser.ts +0 -18
  307. package/src/venn/renderer.ts +0 -1047
  308. package/src/version-control/diagnostics.ts +0 -67
  309. package/src/version-control/parser.ts +0 -544
  310. package/src/version-control/renderer.ts +0 -724
  311. package/src/version-control/types.ts +0 -100
  312. package/src/visualizations/parse.ts +0 -1560
  313. package/src/visualizations/types.ts +0 -262
  314. package/src/wireframe/layout.ts +0 -479
  315. package/src/wireframe/parser.ts +0 -1114
  316. package/src/wireframe/renderer.ts +0 -1318
  317. package/src/wireframe/types.ts +0 -110
  318. package/src/wordcloud/parser.ts +0 -18
  319. package/src/wordcloud/renderer.ts +0 -357
@@ -1,213 +0,0 @@
1
- // ============================================================
2
- // RACI / RASCI / DACI Diagnostic Catalog
3
- // ============================================================
4
- //
5
- // Declarative `DiagnosticSpec` entries for every coded diagnostic the
6
- // RACI parser can emit. This is the single source of truth for wording:
7
- // the parser (`src/raci/parser.ts`) and rule set (`src/raci/variants.ts`)
8
- // emit through `emit(RACI_DX.<KEY>, line, params)` so catalog consumers
9
- // (CLI `diagnostics`, console error-review, MCP `validate_diagram`, spec
10
- // docs) can enumerate RACI diagnostics without re-typing wording at each
11
- // call site.
12
- //
13
- // Codes are also mirrored in `variants.ts` (`RACI_ERROR_CODES`,
14
- // `RACI_WARNING_CODES`) for downstream consumers/tests that key off the
15
- // code tables. Every message builder tolerates being called with `{}` so
16
- // the catalog can render a representative message without live params.
17
-
18
- import type { DiagnosticSpec } from '../diagnostics';
19
-
20
- /** Keyed specs — referenced by the parser's / rules' `emit()` call sites. */
21
- export const RACI_DX = {
22
- // ── Errors ──────────────────────────────────────────────────
23
-
24
- MULTI_ACCOUNTABLE: {
25
- code: 'E_RACI_MULTI_ACCOUNTABLE',
26
- severity: 'error',
27
- chartType: 'raci',
28
- title: 'Multiple Accountable',
29
- // variants.ts › multiAccountableRule
30
- message: (p) =>
31
- `Task '${(p.task as string) ?? 'Task'}' has more than one Accountable — RACI requires exactly one.`,
32
- hint: 'Assign the A marker to exactly one role per task; make the others Responsible or Consulted.',
33
- example: `raci\n\nTask\n Cap: A\n QM: A`,
34
- },
35
- DACI_MULTI_DRIVER: {
36
- code: 'E_DACI_MULTI_DRIVER',
37
- severity: 'error',
38
- chartType: 'raci',
39
- title: 'Multiple Driver (DACI)',
40
- // variants.ts › daciMultiDriverRule
41
- message: (p) =>
42
- `Task '${(p.task as string) ?? 'Task'}' has more than one Driver — DACI requires exactly one.`,
43
- hint: 'A DACI decision has a single Driver; give the extra D roles another marker.',
44
- example: `raci\n\nDecision\n PM: D\n Cap: D`,
45
- },
46
- DACI_MULTI_ACCOUNTABLE: {
47
- code: 'E_DACI_MULTI_ACCOUNTABLE',
48
- severity: 'error',
49
- chartType: 'raci',
50
- title: 'Multiple Approver (DACI)',
51
- // variants.ts › daciMultiAccountableRule
52
- message: (p) =>
53
- `Task '${(p.task as string) ?? 'Task'}' has more than one Approver — DACI requires exactly one.`,
54
- hint: 'A DACI decision has a single Approver (A); reduce to one.',
55
- example: `raci\n\nDecision\n Lead: D\n PM: A\n Cap: A`,
56
- },
57
- INVALID_MARKER: {
58
- code: 'E_RACI_INVALID_MARKER',
59
- severity: 'error',
60
- chartType: 'raci',
61
- // Two emit sites share this code: parser.ts first-pass (default form,
62
- // rejects letters outside the union alphabet) and parser.ts post-pass
63
- // (variant-aware form, passed `variant`+`alphabet`, rejects union
64
- // letters outside the resolved variant). The `{}` default renders the
65
- // first-pass wording.
66
- title: 'Invalid marker',
67
- // parser.ts first-pass tokenizer
68
- message: (p) =>
69
- p.variant !== undefined && p.variant !== null
70
- ? `Marker '${(p.marker as string) ?? 'X'}' is not in the ${p.variant} alphabet (${p.alphabet}).`
71
- : `Marker '${(p.marker as string) ?? 'X'}' is not a recognized RACI marker (R A S C I D).`,
72
- hint: 'Use only R, A, S, C, I (or D for DACI). Wrong-variant letters (e.g. S in a DACI chart) trigger the variant-alphabet form of this diagnostic.',
73
- example: `raci\n\nTask\n Cap: X`,
74
- },
75
- UNEXPECTED_LINE: {
76
- code: 'E_RACI_UNEXPECTED_LINE',
77
- severity: 'error',
78
- chartType: 'raci',
79
- title: 'Unexpected line under task',
80
- // parser.ts — free-text after first role assignment
81
- message: (p) =>
82
- `Unexpected line after role assignments under task '${(p.task as string) ?? 'Task'}'. Lines under a task must be either a description (before the first 'Role: markers' line) or another role assignment.`,
83
- hint: 'Put all description text before the first role assignment; nothing but assignments may follow.',
84
- example: `raci\n\nTask\n Cap: A\n This is an unexpected description.`,
85
- },
86
- MIXED_VARIANTS: {
87
- code: 'E_RACI_MIXED_VARIANTS',
88
- severity: 'error',
89
- chartType: 'raci',
90
- title: 'Mixed RASCI/DACI markers',
91
- // parser.ts — variant resolution, inferVariant() returned null
92
- message:
93
- "Chart uses both 'D' and 'S' markers but neither RASCI nor DACI covers both. Use only RACI/RASCI markers (R, A, S, C, I) or only DACI markers (D, A, C, I).",
94
- hint: 'Pick one convention: R/A/S/C/I (RACI/RASCI) or D/A/C/I (DACI). Do not mix D and S in one chart.',
95
- example: `raci\n\nTask\n Cap: D\n Crew: S`,
96
- },
97
-
98
- // ── Warnings ────────────────────────────────────────────────
99
-
100
- MISSING_ACCOUNTABLE: {
101
- code: 'W_RACI_MISSING_ACCOUNTABLE',
102
- severity: 'warning',
103
- chartType: 'raci',
104
- title: 'Missing Accountable',
105
- // variants.ts › missingAccountableRule
106
- message: (p) =>
107
- `Task '${(p.task as string) ?? 'Task'}' has no Accountable assigned.`,
108
- hint: 'Every RACI task should have exactly one Accountable (A).',
109
- example: `raci\n\nTask\n Cap: R`,
110
- },
111
- MISSING_RESPONSIBLE: {
112
- code: 'W_RACI_MISSING_RESPONSIBLE',
113
- severity: 'warning',
114
- chartType: 'raci',
115
- title: 'Missing Responsible',
116
- // variants.ts › missingResponsibleRule
117
- message: (p) =>
118
- `Task '${(p.task as string) ?? 'Task'}' has no Responsible assigned.`,
119
- hint: 'Assign at least one Responsible (R) — someone has to do the work.',
120
- example: `raci\n\nTask\n Cap: A`,
121
- },
122
- DACI_MISSING_DRIVER: {
123
- code: 'W_DACI_MISSING_DRIVER',
124
- severity: 'warning',
125
- chartType: 'raci',
126
- title: 'Missing Driver (DACI)',
127
- // variants.ts › daciMissingDriverRule
128
- message: (p) =>
129
- `Task '${(p.task as string) ?? 'Task'}' has no Driver assigned.`,
130
- hint: 'A DACI decision needs a Driver (D) to move it forward.',
131
- example: `raci\n\nPick Vendor\n Lead: D\n PM: A\nSign Off\n Cap: C`,
132
- },
133
- DACI_MISSING_ACCOUNTABLE: {
134
- code: 'W_DACI_MISSING_ACCOUNTABLE',
135
- severity: 'warning',
136
- chartType: 'raci',
137
- title: 'Missing Approver (DACI)',
138
- // variants.ts › daciMissingAccountableRule
139
- message: (p) =>
140
- `Task '${(p.task as string) ?? 'Task'}' has no Approver assigned.`,
141
- hint: 'A DACI decision needs an Approver (A) to sign off.',
142
- example: `raci\n\nPick Vendor\n Lead: D\n PM: A\nSign Off\n Cap: C`,
143
- },
144
- UNKNOWN_ROLE: {
145
- code: 'W_RACI_UNKNOWN_ROLE',
146
- severity: 'warning',
147
- chartType: 'raci',
148
- title: 'Undeclared role',
149
- // parser.ts — only when `roles:` is declared. Live message appends a
150
- // ` Did you mean 'X'?` suggestion when a near match exists.
151
- message: (p) => {
152
- const role = (p.role as string) ?? 'Role';
153
- const hint = (p.hint as string) ?? '';
154
- return `Role '${role}' is not declared in the 'roles:' directive.${hint ? ' ' + hint : ''}`;
155
- },
156
- hint: 'Add the role to the `roles` directive, or fix the typo to match a declared role.',
157
- example: `raci\nroles Cap, QM\n\nTask\n Cap: A\n Stranger: R`,
158
- },
159
- EMPTY_TASK: {
160
- code: 'W_RACI_EMPTY_TASK',
161
- severity: 'warning',
162
- chartType: 'raci',
163
- title: 'Empty task',
164
- // variants.ts › emptyTaskRule
165
- message: (p) =>
166
- `Task '${(p.task as string) ?? 'Task'}' has no role assignments.`,
167
- hint: 'Add at least one `Role: markers` line, or remove the empty task.',
168
- example: `raci\n\nTask\n Just a description with no assignments`,
169
- },
170
- CONFLICTING_MARKERS: {
171
- code: 'W_RACI_CONFLICTING_MARKERS',
172
- severity: 'warning',
173
- chartType: 'raci',
174
- title: 'Conflicting markers',
175
- // variants.ts › conflictingMarkersRule
176
- message: (p) => {
177
- const role = (p.role as string) ?? 'Role';
178
- const task = (p.task as string) ?? 'Task';
179
- const markers = (p.markers as string) ?? 'A C';
180
- return `Role '${role}' on task '${task}' has conflicting markers (${markers}). A role can be either active (R/A/D) or passive (C/I), not both.`;
181
- },
182
- hint: 'Give the role either an active marker (R/A/D) or a passive one (C/I), not both.',
183
- example: `raci\n\nTask\n Cap: A C`,
184
- },
185
- TOO_MANY_RESPONSIBLE: {
186
- code: 'W_RACI_TOO_MANY_RESPONSIBLE',
187
- severity: 'warning',
188
- chartType: 'raci',
189
- title: 'Too many Responsible',
190
- // variants.ts › tooManyResponsibleRule (threshold = 3)
191
- message: (p) => {
192
- const task = (p.task as string) ?? 'Task';
193
- const count = (p.count as number) ?? 4;
194
- const threshold = (p.threshold as number) ?? 3;
195
- return `Task '${task}' has ${count} Responsibles — more than ${threshold} dilutes ownership. Consider splitting the task or marking some as Consulted.`;
196
- },
197
- hint: 'Keep Responsibles at or below 3 — split the task or downgrade some roles to Consulted.',
198
- example: `raci\n\nTask\n W: R\n X: R\n Y: R\n Z: R\n Lead: A`,
199
- },
200
- ORPHAN_ROLE: {
201
- code: 'W_RACI_ORPHAN_ROLE',
202
- severity: 'warning',
203
- chartType: 'raci',
204
- title: 'Orphan role',
205
- // parser.ts — role declared/seen but never assigned any marker
206
- message: (p) =>
207
- `Role '${(p.role as string) ?? 'Role'}' is declared but never assigned to any task.`,
208
- hint: 'Assign the role a marker somewhere, or remove it from the `roles` directive.',
209
- example: `raci\nroles Cap, Ghost\n\nTask\n Cap: A R`,
210
- },
211
- } satisfies Record<string, DiagnosticSpec>;
212
-
213
- export const RACI_DIAGNOSTICS: DiagnosticSpec[] = Object.values(RACI_DX);
package/src/raci/index.ts DELETED
@@ -1,23 +0,0 @@
1
- // ============================================================
2
- // RACI / RASCI / DACI — public exports
3
- // ============================================================
4
-
5
- export { parseRaci, allTasks } from './parser';
6
- export { renderRaci, renderRaciForExport } from './renderer';
7
- export type { RaciDragSource, RaciInteractionHandlers } from './renderer';
8
- export {
9
- cellReplace,
10
- cellAppendMarker,
11
- cellRemove,
12
- cellCycle,
13
- } from './mutations';
14
- export { VARIANTS, RACI_ERROR_CODES, RACI_WARNING_CODES } from './variants';
15
- export type { ConstraintRule, VariantRuleSet } from './variants';
16
- export type {
17
- ParsedRaci,
18
- RaciMarker,
19
- RaciVariant,
20
- RaciTask,
21
- RaciPhase,
22
- RaciRoleAssignment,
23
- } from './types';
@@ -1,321 +0,0 @@
1
- // ============================================================
2
- // RACI mutation engine
3
- // ============================================================
4
- //
5
- // Greenfield, peer to `kanban/mutations.ts` (NOT extracted shared
6
- // utility — see Technical Decision #15 in the tech spec). All
7
- // mutations are pure functions that return a new DGMO source string,
8
- // or `null` for no-ops.
9
- //
10
- // Mutation flow (do not deviate):
11
- //
12
- // click / drop in RACIPreview
13
- // ─→ pure mutation here returns new content
14
- // ─→ Zustand stores updated (`useFileStore.setFileContent`,
15
- // `useEditorStore.setContent`)
16
- // ─→ `useCodeMirror` watcher dispatches a CM transaction
17
- //
18
- // Preview NEVER calls `view.dispatch()` directly. Same contract as
19
- // kanban — see `KanbanPreview.tsx:476-477` + `useCodeMirror.ts:269-283`.
20
- //
21
- // Indent preservation comes from operating on whole lines + matching
22
- // the indent of the task's existing role-assignment block. The parser
23
- // owns identity (taskId / roleId are normalized keys); mutations look
24
- // up by id pair.
25
-
26
- import { measureIndent } from '../utils/parsing';
27
- import type {
28
- ParsedRaci,
29
- RaciMarker,
30
- RaciRoleAssignment,
31
- RaciTask,
32
- } from './types';
33
- import { allTasks } from './parser';
34
-
35
- // ── Public surface ───────────────────────────────────────────
36
-
37
- /**
38
- * Set the markers on a cell to exactly `[marker]`, replacing whatever
39
- * was there. If `marker` is `null`, the cell is cleared (the role
40
- * assignment line is removed if it was the only marker; otherwise the
41
- * line stays with its other markers untouched — see `cellRemove` for
42
- * specific-marker removal semantics).
43
- *
44
- * Insertion point when the role assignment doesn't exist:
45
- * - After the last existing role assignment under the task, OR
46
- * - After the task's description block, OR
47
- * - Immediately after the task line.
48
- *
49
- * Returns `null` for no-ops (the cell already contains `[marker]`).
50
- */
51
- export function cellReplace(
52
- content: string,
53
- parsed: ParsedRaci,
54
- taskId: string,
55
- roleId: string,
56
- marker: RaciMarker | null
57
- ): string | null {
58
- const task = findTask(parsed, taskId);
59
- if (!task) return null;
60
-
61
- const lines = content.split('\n');
62
- const existing = task.roleAssignments.find((a) => a.id === roleId);
63
-
64
- if (existing) {
65
- // No-op short-circuit: cell already holds exactly one marker.
66
- if (
67
- marker !== null &&
68
- existing.markers.length === 1 &&
69
- existing.markers[0] === marker
70
- ) {
71
- return null;
72
- }
73
- // No-op short-circuit: clearing an already-empty cell.
74
- if (marker === null && existing.markers.length === 0) {
75
- return null;
76
- }
77
-
78
- if (marker === null) {
79
- // Drop the line entirely.
80
- lines.splice(existing.lineNumber - 1, 1);
81
- return lines.join('\n');
82
- }
83
-
84
- // In-bounds: existing.lineNumber refers to a valid line in lines.
85
- lines[existing.lineNumber - 1] = rewriteAssignmentLine(
86
- lines[existing.lineNumber - 1]!,
87
- existing.displayName,
88
- [marker]
89
- );
90
- return lines.join('\n');
91
- }
92
-
93
- // No existing role assignment for this role; insert one (unless null).
94
- if (marker === null) return null;
95
-
96
- const roleDisplay = lookupRoleDisplay(parsed, roleId);
97
- if (!roleDisplay) return null;
98
-
99
- const indent = inferAssignmentIndent(task, lines);
100
- const insertAt = insertionLineFor(task, roleId, parsed);
101
- const newLine = `${' '.repeat(indent)}${roleDisplay}: ${marker}`;
102
- lines.splice(insertAt, 0, newLine);
103
- return lines.join('\n');
104
- }
105
-
106
- /**
107
- * Append `marker` to the cell, producing a combined-marker string
108
- * like `A R`. Idempotent — if `marker` is already present, returns
109
- * `null`. If the cell is empty (no existing role assignment line),
110
- * behaves like `cellReplace(content, ..., marker)`.
111
- */
112
- export function cellAppendMarker(
113
- content: string,
114
- parsed: ParsedRaci,
115
- taskId: string,
116
- roleId: string,
117
- marker: RaciMarker
118
- ): string | null {
119
- const task = findTask(parsed, taskId);
120
- if (!task) return null;
121
-
122
- const existing = task.roleAssignments.find((a) => a.id === roleId);
123
- if (!existing) {
124
- return cellReplace(content, parsed, taskId, roleId, marker);
125
- }
126
- if (existing.markers.includes(marker)) return null;
127
-
128
- const lines = content.split('\n');
129
- // In-bounds: existing.lineNumber refers to a valid line in lines.
130
- lines[existing.lineNumber - 1] = rewriteAssignmentLine(
131
- lines[existing.lineNumber - 1]!,
132
- existing.displayName,
133
- [...existing.markers, marker]
134
- );
135
- return lines.join('\n');
136
- }
137
-
138
- /**
139
- * Remove a single `marker` from the cell, OR all markers when
140
- * `marker` is `undefined`. If the cell becomes empty as a result,
141
- * the entire role-assignment line is dropped.
142
- *
143
- * Returns `null` for no-ops (e.g. removing a marker that wasn't
144
- * there).
145
- */
146
- export function cellRemove(
147
- content: string,
148
- parsed: ParsedRaci,
149
- taskId: string,
150
- roleId: string,
151
- marker?: RaciMarker
152
- ): string | null {
153
- const task = findTask(parsed, taskId);
154
- if (!task) return null;
155
-
156
- const existing = task.roleAssignments.find((a) => a.id === roleId);
157
- if (!existing) return null;
158
-
159
- const lines = content.split('\n');
160
-
161
- let nextMarkers: RaciMarker[];
162
- if (marker === undefined) {
163
- nextMarkers = [];
164
- } else {
165
- if (!existing.markers.includes(marker)) return null;
166
- nextMarkers = existing.markers.filter((m) => m !== marker);
167
- }
168
-
169
- if (nextMarkers.length === 0) {
170
- lines.splice(existing.lineNumber - 1, 1);
171
- return lines.join('\n');
172
- }
173
-
174
- // In-bounds: existing.lineNumber refers to a valid line in lines.
175
- lines[existing.lineNumber - 1] = rewriteAssignmentLine(
176
- lines[existing.lineNumber - 1]!,
177
- existing.displayName,
178
- nextMarkers
179
- );
180
- return lines.join('\n');
181
- }
182
-
183
- /**
184
- * Cycle the cell's marker through the variant alphabet. Used by the
185
- * click-to-cycle interaction in `RACIPreview`. Cycle order:
186
- *
187
- * blank → alphabet[0] → alphabet[1] → … → alphabet[n-1] → blank → …
188
- *
189
- * If the cell currently has multiple markers (e.g. `A R`), cycling
190
- * collapses to a single marker chosen as the *next* one after the
191
- * first existing marker — interpretation: "cycle from the dominant
192
- * marker." This keeps the affordance simple; combined-markers stay
193
- * the territory of drag-from-palette (per TD #10).
194
- */
195
- export function cellCycle(
196
- content: string,
197
- parsed: ParsedRaci,
198
- taskId: string,
199
- roleId: string,
200
- alphabet: ReadonlyArray<RaciMarker>
201
- ): string | null {
202
- if (alphabet.length === 0) return null;
203
- const task = findTask(parsed, taskId);
204
- if (!task) return null;
205
-
206
- const existing = task.roleAssignments.find((a) => a.id === roleId);
207
- const current = existing?.markers ?? [];
208
-
209
- let next: RaciMarker | null;
210
- if (current.length === 0) {
211
- // In-bounds: alphabet.length > 0 guard at top of function.
212
- next = alphabet[0]!;
213
- } else {
214
- // In-bounds: current.length > 0 from condition above.
215
- const dominant = current[0]!;
216
- const idx = alphabet.indexOf(dominant);
217
- if (idx < 0) {
218
- // First marker is not in alphabet (shouldn't normally happen —
219
- // parser would have flagged it). Restart the cycle.
220
- // In-bounds: alphabet.length > 0 guard at top of function.
221
- next = alphabet[0]!;
222
- } else if (idx === alphabet.length - 1) {
223
- // Wrap → blank
224
- next = null;
225
- } else {
226
- // In-bounds: idx < alphabet.length - 1, so idx + 1 < alphabet.length.
227
- next = alphabet[idx + 1]!;
228
- }
229
- }
230
-
231
- return cellReplace(content, parsed, taskId, roleId, next);
232
- }
233
-
234
- // ── Internals ────────────────────────────────────────────────
235
-
236
- function findTask(parsed: ParsedRaci, taskId: string): RaciTask | null {
237
- for (const t of allTasks(parsed)) {
238
- if (t.id === taskId) return t;
239
- }
240
- return null;
241
- }
242
-
243
- function lookupRoleDisplay(parsed: ParsedRaci, roleId: string): string | null {
244
- const idx = parsed.roles.indexOf(roleId);
245
- if (idx < 0) return null;
246
- return parsed.roleDisplayNames[idx] ?? null;
247
- }
248
-
249
- /**
250
- * Build a fresh role-assignment line at `existing`'s indent and role
251
- * display, with the given markers. Preserves trailing whitespace /
252
- * comments after the markers? — no: we treat the value segment after
253
- * the colon as wholly owned by the markers. RACI does not currently
254
- * support trailing pipe metadata on role-assignment lines (per
255
- * Out-of-Scope), so this is safe.
256
- */
257
- function rewriteAssignmentLine(
258
- originalLine: string,
259
- displayName: string,
260
- markers: ReadonlyArray<RaciMarker>
261
- ): string {
262
- const indent = measureIndent(originalLine);
263
- return `${' '.repeat(indent)}${displayName}: ${markers.join(' ')}`;
264
- }
265
-
266
- /**
267
- * Indent for a NEW role-assignment line under `task`. Use the indent
268
- * of the first existing role assignment if any; otherwise infer from
269
- * a sibling task's role assignment; otherwise default to the task's
270
- * own indent + 2.
271
- */
272
- function inferAssignmentIndent(task: RaciTask, lines: string[]): number {
273
- if (task.roleAssignments.length > 0) {
274
- // In-bounds: roleAssignments[0] exists from length>0; lineNumber references a valid line.
275
- return measureIndent(lines[task.roleAssignments[0]!.lineNumber - 1]!);
276
- }
277
- // In-bounds: task.lineNumber references a valid line in the source.
278
- const taskIndent = measureIndent(lines[task.lineNumber - 1]!);
279
- return taskIndent + 2;
280
- }
281
-
282
- /**
283
- * 1-based line *index for splice*: the index BEFORE which the new
284
- * line is inserted. Returns the position immediately after the
285
- * task's last contentful line (description or role assignment) — or
286
- * directly after the task line when neither exists.
287
- */
288
- function insertionLineFor(
289
- task: RaciTask,
290
- roleId: string,
291
- parsed: ParsedRaci
292
- ): number {
293
- // No existing role assignments — insert directly after the task block
294
- // (after the task line and any description lines).
295
- if (task.roleAssignments.length === 0) {
296
- return task.endLineNumber;
297
- }
298
-
299
- // Match role-declaration order: insert before the first existing
300
- // role assignment whose role-index is greater than this role's. If
301
- // none has a higher index (i.e. this role belongs at the bottom of
302
- // the declared order), append after the last existing assignment.
303
- const targetIdx = parsed.roles.indexOf(roleId);
304
- const lastAssignmentLine = Math.max(
305
- ...task.roleAssignments.map((a: RaciRoleAssignment) => a.endLineNumber)
306
- );
307
- if (targetIdx < 0) {
308
- // Role not registered (shouldn't normally happen since callers
309
- // look up by parsed.roles index) — fall back to end-of-block.
310
- return lastAssignmentLine;
311
- }
312
- for (const a of task.roleAssignments) {
313
- const aIdx = parsed.roles.indexOf(a.id);
314
- if (aIdx > targetIdx) {
315
- // splice index = (1-based line) - 1 places the new line BEFORE
316
- // the existing line at `a.lineNumber`.
317
- return a.lineNumber - 1;
318
- }
319
- }
320
- return lastAssignmentLine;
321
- }