@lumenflow/core 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 (263) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +119 -0
  3. package/dist/active-wu-detector.d.ts +33 -0
  4. package/dist/active-wu-detector.js +106 -0
  5. package/dist/adapters/filesystem-metrics.adapter.d.ts +108 -0
  6. package/dist/adapters/filesystem-metrics.adapter.js +519 -0
  7. package/dist/adapters/terminal-renderer.adapter.d.ts +106 -0
  8. package/dist/adapters/terminal-renderer.adapter.js +337 -0
  9. package/dist/arg-parser.d.ts +63 -0
  10. package/dist/arg-parser.js +560 -0
  11. package/dist/backlog-editor.d.ts +98 -0
  12. package/dist/backlog-editor.js +179 -0
  13. package/dist/backlog-generator.d.ts +111 -0
  14. package/dist/backlog-generator.js +381 -0
  15. package/dist/backlog-parser.d.ts +45 -0
  16. package/dist/backlog-parser.js +102 -0
  17. package/dist/backlog-sync-validator.d.ts +78 -0
  18. package/dist/backlog-sync-validator.js +294 -0
  19. package/dist/branch-drift.d.ts +34 -0
  20. package/dist/branch-drift.js +51 -0
  21. package/dist/cleanup-install-config.d.ts +33 -0
  22. package/dist/cleanup-install-config.js +37 -0
  23. package/dist/cleanup-lock.d.ts +139 -0
  24. package/dist/cleanup-lock.js +313 -0
  25. package/dist/code-path-validator.d.ts +146 -0
  26. package/dist/code-path-validator.js +537 -0
  27. package/dist/code-paths-overlap.d.ts +55 -0
  28. package/dist/code-paths-overlap.js +245 -0
  29. package/dist/commands-logger.d.ts +77 -0
  30. package/dist/commands-logger.js +254 -0
  31. package/dist/commit-message-utils.d.ts +25 -0
  32. package/dist/commit-message-utils.js +41 -0
  33. package/dist/compliance-parser.d.ts +150 -0
  34. package/dist/compliance-parser.js +507 -0
  35. package/dist/constants/backlog-patterns.d.ts +20 -0
  36. package/dist/constants/backlog-patterns.js +23 -0
  37. package/dist/constants/dora-constants.d.ts +49 -0
  38. package/dist/constants/dora-constants.js +53 -0
  39. package/dist/constants/gate-constants.d.ts +15 -0
  40. package/dist/constants/gate-constants.js +15 -0
  41. package/dist/constants/linter-constants.d.ts +16 -0
  42. package/dist/constants/linter-constants.js +16 -0
  43. package/dist/constants/tokenizer-constants.d.ts +15 -0
  44. package/dist/constants/tokenizer-constants.js +15 -0
  45. package/dist/core/scope-checker.d.ts +97 -0
  46. package/dist/core/scope-checker.js +163 -0
  47. package/dist/core/tool-runner.d.ts +161 -0
  48. package/dist/core/tool-runner.js +393 -0
  49. package/dist/core/tool.constants.d.ts +105 -0
  50. package/dist/core/tool.constants.js +101 -0
  51. package/dist/core/tool.schemas.d.ts +226 -0
  52. package/dist/core/tool.schemas.js +226 -0
  53. package/dist/core/worktree-guard.d.ts +130 -0
  54. package/dist/core/worktree-guard.js +242 -0
  55. package/dist/coverage-gate.d.ts +108 -0
  56. package/dist/coverage-gate.js +196 -0
  57. package/dist/date-utils.d.ts +75 -0
  58. package/dist/date-utils.js +140 -0
  59. package/dist/dependency-graph.d.ts +142 -0
  60. package/dist/dependency-graph.js +550 -0
  61. package/dist/dependency-guard.d.ts +54 -0
  62. package/dist/dependency-guard.js +142 -0
  63. package/dist/dependency-validator.d.ts +105 -0
  64. package/dist/dependency-validator.js +154 -0
  65. package/dist/docs-path-validator.d.ts +36 -0
  66. package/dist/docs-path-validator.js +95 -0
  67. package/dist/domain/orchestration.constants.d.ts +99 -0
  68. package/dist/domain/orchestration.constants.js +97 -0
  69. package/dist/domain/orchestration.schemas.d.ts +280 -0
  70. package/dist/domain/orchestration.schemas.js +211 -0
  71. package/dist/domain/orchestration.types.d.ts +133 -0
  72. package/dist/domain/orchestration.types.js +12 -0
  73. package/dist/error-handler.d.ts +116 -0
  74. package/dist/error-handler.js +136 -0
  75. package/dist/file-classifiers.d.ts +62 -0
  76. package/dist/file-classifiers.js +108 -0
  77. package/dist/gates-agent-mode.d.ts +81 -0
  78. package/dist/gates-agent-mode.js +94 -0
  79. package/dist/generate-traceability.d.ts +107 -0
  80. package/dist/generate-traceability.js +411 -0
  81. package/dist/git-adapter.d.ts +395 -0
  82. package/dist/git-adapter.js +649 -0
  83. package/dist/git-staged-validator.d.ts +32 -0
  84. package/dist/git-staged-validator.js +48 -0
  85. package/dist/hardcoded-strings.d.ts +61 -0
  86. package/dist/hardcoded-strings.js +270 -0
  87. package/dist/incremental-lint.d.ts +78 -0
  88. package/dist/incremental-lint.js +129 -0
  89. package/dist/incremental-test.d.ts +39 -0
  90. package/dist/incremental-test.js +61 -0
  91. package/dist/index.d.ts +42 -0
  92. package/dist/index.js +61 -0
  93. package/dist/invariants/check-automated-tests.d.ts +50 -0
  94. package/dist/invariants/check-automated-tests.js +166 -0
  95. package/dist/invariants-runner.d.ts +103 -0
  96. package/dist/invariants-runner.js +527 -0
  97. package/dist/lane-checker.d.ts +50 -0
  98. package/dist/lane-checker.js +319 -0
  99. package/dist/lane-inference.d.ts +39 -0
  100. package/dist/lane-inference.js +195 -0
  101. package/dist/lane-lock.d.ts +211 -0
  102. package/dist/lane-lock.js +474 -0
  103. package/dist/lane-validator.d.ts +48 -0
  104. package/dist/lane-validator.js +114 -0
  105. package/dist/logs-lib.d.ts +104 -0
  106. package/dist/logs-lib.js +207 -0
  107. package/dist/lumenflow-config-schema.d.ts +272 -0
  108. package/dist/lumenflow-config-schema.js +207 -0
  109. package/dist/lumenflow-config.d.ts +95 -0
  110. package/dist/lumenflow-config.js +236 -0
  111. package/dist/manual-test-validator.d.ts +80 -0
  112. package/dist/manual-test-validator.js +200 -0
  113. package/dist/merge-lock.d.ts +115 -0
  114. package/dist/merge-lock.js +251 -0
  115. package/dist/micro-worktree.d.ts +159 -0
  116. package/dist/micro-worktree.js +427 -0
  117. package/dist/migration-deployer.d.ts +69 -0
  118. package/dist/migration-deployer.js +151 -0
  119. package/dist/orchestration-advisory-loader.d.ts +28 -0
  120. package/dist/orchestration-advisory-loader.js +87 -0
  121. package/dist/orchestration-advisory.d.ts +58 -0
  122. package/dist/orchestration-advisory.js +94 -0
  123. package/dist/orchestration-di.d.ts +48 -0
  124. package/dist/orchestration-di.js +57 -0
  125. package/dist/orchestration-rules.d.ts +57 -0
  126. package/dist/orchestration-rules.js +201 -0
  127. package/dist/orphan-detector.d.ts +131 -0
  128. package/dist/orphan-detector.js +226 -0
  129. package/dist/path-classifiers.d.ts +57 -0
  130. package/dist/path-classifiers.js +93 -0
  131. package/dist/piped-command-detector.d.ts +34 -0
  132. package/dist/piped-command-detector.js +64 -0
  133. package/dist/ports/dashboard-renderer.port.d.ts +112 -0
  134. package/dist/ports/dashboard-renderer.port.js +25 -0
  135. package/dist/ports/metrics-collector.port.d.ts +132 -0
  136. package/dist/ports/metrics-collector.port.js +26 -0
  137. package/dist/process-detector.d.ts +84 -0
  138. package/dist/process-detector.js +172 -0
  139. package/dist/prompt-linter.d.ts +72 -0
  140. package/dist/prompt-linter.js +312 -0
  141. package/dist/prompt-monitor.d.ts +15 -0
  142. package/dist/prompt-monitor.js +205 -0
  143. package/dist/rebase-artifact-cleanup.d.ts +145 -0
  144. package/dist/rebase-artifact-cleanup.js +433 -0
  145. package/dist/retry-strategy.d.ts +189 -0
  146. package/dist/retry-strategy.js +283 -0
  147. package/dist/risk-detector.d.ts +108 -0
  148. package/dist/risk-detector.js +252 -0
  149. package/dist/rollback-utils.d.ts +76 -0
  150. package/dist/rollback-utils.js +104 -0
  151. package/dist/section-headings.d.ts +43 -0
  152. package/dist/section-headings.js +49 -0
  153. package/dist/spawn-escalation.d.ts +90 -0
  154. package/dist/spawn-escalation.js +253 -0
  155. package/dist/spawn-monitor.d.ts +229 -0
  156. package/dist/spawn-monitor.js +672 -0
  157. package/dist/spawn-recovery.d.ts +82 -0
  158. package/dist/spawn-recovery.js +298 -0
  159. package/dist/spawn-registry-schema.d.ts +98 -0
  160. package/dist/spawn-registry-schema.js +108 -0
  161. package/dist/spawn-registry-store.d.ts +146 -0
  162. package/dist/spawn-registry-store.js +273 -0
  163. package/dist/spawn-tree.d.ts +121 -0
  164. package/dist/spawn-tree.js +285 -0
  165. package/dist/stamp-status-validator.d.ts +84 -0
  166. package/dist/stamp-status-validator.js +134 -0
  167. package/dist/stamp-utils.d.ts +100 -0
  168. package/dist/stamp-utils.js +229 -0
  169. package/dist/state-machine.d.ts +26 -0
  170. package/dist/state-machine.js +83 -0
  171. package/dist/system-map-validator.d.ts +80 -0
  172. package/dist/system-map-validator.js +272 -0
  173. package/dist/telemetry.d.ts +80 -0
  174. package/dist/telemetry.js +213 -0
  175. package/dist/token-counter.d.ts +51 -0
  176. package/dist/token-counter.js +145 -0
  177. package/dist/usecases/get-dashboard-data.usecase.d.ts +52 -0
  178. package/dist/usecases/get-dashboard-data.usecase.js +61 -0
  179. package/dist/usecases/get-suggestions.usecase.d.ts +100 -0
  180. package/dist/usecases/get-suggestions.usecase.js +153 -0
  181. package/dist/user-normalizer.d.ts +41 -0
  182. package/dist/user-normalizer.js +141 -0
  183. package/dist/validators/phi-constants.d.ts +97 -0
  184. package/dist/validators/phi-constants.js +152 -0
  185. package/dist/validators/phi-scanner.d.ts +58 -0
  186. package/dist/validators/phi-scanner.js +215 -0
  187. package/dist/worktree-ownership.d.ts +50 -0
  188. package/dist/worktree-ownership.js +74 -0
  189. package/dist/worktree-scanner.d.ts +103 -0
  190. package/dist/worktree-scanner.js +168 -0
  191. package/dist/worktree-symlink.d.ts +99 -0
  192. package/dist/worktree-symlink.js +359 -0
  193. package/dist/wu-backlog-updater.d.ts +17 -0
  194. package/dist/wu-backlog-updater.js +37 -0
  195. package/dist/wu-checkpoint.d.ts +124 -0
  196. package/dist/wu-checkpoint.js +233 -0
  197. package/dist/wu-claim-helpers.d.ts +26 -0
  198. package/dist/wu-claim-helpers.js +63 -0
  199. package/dist/wu-claim-resume.d.ts +106 -0
  200. package/dist/wu-claim-resume.js +276 -0
  201. package/dist/wu-consistency-checker.d.ts +95 -0
  202. package/dist/wu-consistency-checker.js +567 -0
  203. package/dist/wu-constants.d.ts +1275 -0
  204. package/dist/wu-constants.js +1382 -0
  205. package/dist/wu-create-validators.d.ts +42 -0
  206. package/dist/wu-create-validators.js +93 -0
  207. package/dist/wu-done-branch-only.d.ts +63 -0
  208. package/dist/wu-done-branch-only.js +191 -0
  209. package/dist/wu-done-messages.d.ts +119 -0
  210. package/dist/wu-done-messages.js +185 -0
  211. package/dist/wu-done-pr.d.ts +72 -0
  212. package/dist/wu-done-pr.js +174 -0
  213. package/dist/wu-done-retry-helpers.d.ts +85 -0
  214. package/dist/wu-done-retry-helpers.js +172 -0
  215. package/dist/wu-done-ui.d.ts +37 -0
  216. package/dist/wu-done-ui.js +69 -0
  217. package/dist/wu-done-validators.d.ts +411 -0
  218. package/dist/wu-done-validators.js +1229 -0
  219. package/dist/wu-done-worktree.d.ts +182 -0
  220. package/dist/wu-done-worktree.js +1097 -0
  221. package/dist/wu-helpers.d.ts +128 -0
  222. package/dist/wu-helpers.js +248 -0
  223. package/dist/wu-lint.d.ts +70 -0
  224. package/dist/wu-lint.js +234 -0
  225. package/dist/wu-paths.d.ts +171 -0
  226. package/dist/wu-paths.js +178 -0
  227. package/dist/wu-preflight-validators.d.ts +86 -0
  228. package/dist/wu-preflight-validators.js +251 -0
  229. package/dist/wu-recovery.d.ts +138 -0
  230. package/dist/wu-recovery.js +341 -0
  231. package/dist/wu-repair-core.d.ts +131 -0
  232. package/dist/wu-repair-core.js +669 -0
  233. package/dist/wu-schema-normalization.d.ts +17 -0
  234. package/dist/wu-schema-normalization.js +82 -0
  235. package/dist/wu-schema.d.ts +793 -0
  236. package/dist/wu-schema.js +881 -0
  237. package/dist/wu-spawn-helpers.d.ts +121 -0
  238. package/dist/wu-spawn-helpers.js +271 -0
  239. package/dist/wu-spawn.d.ts +158 -0
  240. package/dist/wu-spawn.js +1306 -0
  241. package/dist/wu-state-schema.d.ts +213 -0
  242. package/dist/wu-state-schema.js +156 -0
  243. package/dist/wu-state-store.d.ts +264 -0
  244. package/dist/wu-state-store.js +691 -0
  245. package/dist/wu-status-transition.d.ts +63 -0
  246. package/dist/wu-status-transition.js +382 -0
  247. package/dist/wu-status-updater.d.ts +25 -0
  248. package/dist/wu-status-updater.js +116 -0
  249. package/dist/wu-transaction-collectors.d.ts +116 -0
  250. package/dist/wu-transaction-collectors.js +272 -0
  251. package/dist/wu-transaction.d.ts +170 -0
  252. package/dist/wu-transaction.js +273 -0
  253. package/dist/wu-validation-constants.d.ts +60 -0
  254. package/dist/wu-validation-constants.js +66 -0
  255. package/dist/wu-validation.d.ts +118 -0
  256. package/dist/wu-validation.js +243 -0
  257. package/dist/wu-validator.d.ts +62 -0
  258. package/dist/wu-validator.js +325 -0
  259. package/dist/wu-yaml-fixer.d.ts +97 -0
  260. package/dist/wu-yaml-fixer.js +264 -0
  261. package/dist/wu-yaml.d.ts +86 -0
  262. package/dist/wu-yaml.js +222 -0
  263. package/package.json +114 -0
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Compliance Parser
3
+ *
4
+ * Parses markdown compliance documentation into structured data.
5
+ * Used by compliance-snapshot.mjs tool to create snapshots.
6
+ *
7
+ * @module tools/lib/compliance-parser
8
+ */
9
+ /** @typedef {'ISO27001' | 'NHS_DTAC' | 'NHS_DSPT' | 'GDPR' | 'FDA'} ComplianceFramework */
10
+ /** @typedef {'not_started' | 'in_progress' | 'completed' | 'blocked'} GapStatus */
11
+ /** @typedef {'critical' | 'high' | 'medium' | 'low'} GapPriority */
12
+ /** @typedef {'exists' | 'partial' | 'missing'} EvidenceStatus */
13
+ /** @typedef {'phase_1_critical_blockers' | 'phase_2_nhs_procurement_ready' | 'phase_3_enterprise_ready'} CompliancePhase */
14
+ /**
15
+ * @typedef {Object} ActionItem
16
+ * @property {string} id
17
+ * @property {string} description
18
+ * @property {string} owner
19
+ * @property {string|null} dueDate
20
+ * @property {GapStatus} status
21
+ */
22
+ /**
23
+ * @typedef {Object} GapItem
24
+ * @property {string} gapId
25
+ * @property {string} title
26
+ * @property {string} domain
27
+ * @property {GapPriority} priority
28
+ * @property {GapStatus} status
29
+ * @property {CompliancePhase} phase
30
+ * @property {string} owner
31
+ * @property {string|null} targetDate
32
+ * @property {ActionItem[]} actionItems
33
+ * @property {string[]} blockers
34
+ * @property {string[]} dependsOn
35
+ */
36
+ /**
37
+ * @typedef {Object} EvidenceItem
38
+ * @property {string} evidenceId
39
+ * @property {string} section
40
+ * @property {string} title
41
+ * @property {string} requirement
42
+ * @property {EvidenceStatus} status
43
+ * @property {string|null} location
44
+ * @property {string[]} auditNotes
45
+ * @property {string[]} relatedGaps
46
+ */
47
+ /**
48
+ * @typedef {Object} FrameworkMetrics
49
+ * @property {ComplianceFramework} framework
50
+ * @property {number} totalRequirements
51
+ * @property {number} evidenceExists
52
+ * @property {number} evidencePartial
53
+ * @property {number} evidenceMissing
54
+ * @property {number} completionPercentage
55
+ */
56
+ /**
57
+ * @typedef {Object} PhaseMetrics
58
+ * @property {CompliancePhase} phase
59
+ * @property {number} totalGaps
60
+ * @property {number} notStarted
61
+ * @property {number} inProgress
62
+ * @property {number} completed
63
+ * @property {number} blocked
64
+ * @property {number} completionPercentage
65
+ * @property {string|null} targetDate
66
+ */
67
+ export declare const COMPLIANCE_FRAMEWORKS: string[];
68
+ export declare const GAP_STATUSES: string[];
69
+ export declare const GAP_PRIORITIES: string[];
70
+ export declare const EVIDENCE_STATUSES: string[];
71
+ export declare const COMPLIANCE_PHASES: string[];
72
+ export declare class ComplianceParser {
73
+ /**
74
+ * Parse gap-analysis.md content into structured GapItems
75
+ * @param {string} markdown
76
+ * @returns {GapItem[]}
77
+ */
78
+ parseGapAnalysis(markdown: any): any[];
79
+ /**
80
+ * Parse evidence-registry.md content into structured EvidenceItems
81
+ * @param {string} markdown
82
+ * @returns {EvidenceItem[]}
83
+ */
84
+ parseEvidenceRegistry(markdown: any): any[];
85
+ /**
86
+ * Calculate framework metrics from evidence items
87
+ * @param {EvidenceItem[]} evidence
88
+ * @returns {FrameworkMetrics[]}
89
+ */
90
+ calculateFrameworkMetrics(evidence: any): {
91
+ framework: string;
92
+ totalRequirements: any;
93
+ evidenceExists: any;
94
+ evidencePartial: any;
95
+ evidenceMissing: any;
96
+ completionPercentage: number;
97
+ }[];
98
+ /**
99
+ * Calculate phase metrics from gap items
100
+ * @param {GapItem[]} gaps
101
+ * @returns {PhaseMetrics[]}
102
+ */
103
+ calculatePhaseMetrics(gaps: any): {
104
+ phase: string;
105
+ totalGaps: any;
106
+ notStarted: any;
107
+ inProgress: any;
108
+ completed: any;
109
+ blocked: any;
110
+ completionPercentage: number;
111
+ targetDate: string;
112
+ }[];
113
+ /** @private */
114
+ _parseStatus(text: any): string;
115
+ /** @private */
116
+ _parsePriority(text: any): string;
117
+ /** @private */
118
+ _parseEvidenceStatus(text: any): string;
119
+ /** @private */
120
+ _extractGapReferences(text: any): unknown[];
121
+ /** @private */
122
+ _detectFrameworks(requirement: any): any[];
123
+ /** @private */
124
+ _finalizeGap(partial: any, phase: any): {
125
+ gapId: any;
126
+ title: any;
127
+ domain: any;
128
+ priority: any;
129
+ status: any;
130
+ phase: any;
131
+ owner: any;
132
+ targetDate: any;
133
+ actionItems: any;
134
+ blockers: any;
135
+ dependsOn: any;
136
+ };
137
+ /** @private */
138
+ _finalizeEvidence(partial: any, section: any): {
139
+ evidenceId: any;
140
+ section: any;
141
+ title: any;
142
+ requirement: any;
143
+ status: any;
144
+ location: any;
145
+ auditNotes: any;
146
+ relatedGaps: any;
147
+ };
148
+ /** @private */
149
+ _getPhaseTargetDate(phase: any): "Month 3" | "Month 6" | "Month 12";
150
+ }
@@ -0,0 +1,507 @@
1
+ /**
2
+ * Compliance Parser
3
+ *
4
+ * Parses markdown compliance documentation into structured data.
5
+ * Used by compliance-snapshot.mjs tool to create snapshots.
6
+ *
7
+ * @module tools/lib/compliance-parser
8
+ */
9
+ /** @typedef {'ISO27001' | 'NHS_DTAC' | 'NHS_DSPT' | 'GDPR' | 'FDA'} ComplianceFramework */
10
+ /** @typedef {'not_started' | 'in_progress' | 'completed' | 'blocked'} GapStatus */
11
+ /** @typedef {'critical' | 'high' | 'medium' | 'low'} GapPriority */
12
+ /** @typedef {'exists' | 'partial' | 'missing'} EvidenceStatus */
13
+ /** @typedef {'phase_1_critical_blockers' | 'phase_2_nhs_procurement_ready' | 'phase_3_enterprise_ready'} CompliancePhase */
14
+ /**
15
+ * @typedef {Object} ActionItem
16
+ * @property {string} id
17
+ * @property {string} description
18
+ * @property {string} owner
19
+ * @property {string|null} dueDate
20
+ * @property {GapStatus} status
21
+ */
22
+ /**
23
+ * @typedef {Object} GapItem
24
+ * @property {string} gapId
25
+ * @property {string} title
26
+ * @property {string} domain
27
+ * @property {GapPriority} priority
28
+ * @property {GapStatus} status
29
+ * @property {CompliancePhase} phase
30
+ * @property {string} owner
31
+ * @property {string|null} targetDate
32
+ * @property {ActionItem[]} actionItems
33
+ * @property {string[]} blockers
34
+ * @property {string[]} dependsOn
35
+ */
36
+ /**
37
+ * @typedef {Object} EvidenceItem
38
+ * @property {string} evidenceId
39
+ * @property {string} section
40
+ * @property {string} title
41
+ * @property {string} requirement
42
+ * @property {EvidenceStatus} status
43
+ * @property {string|null} location
44
+ * @property {string[]} auditNotes
45
+ * @property {string[]} relatedGaps
46
+ */
47
+ /**
48
+ * @typedef {Object} FrameworkMetrics
49
+ * @property {ComplianceFramework} framework
50
+ * @property {number} totalRequirements
51
+ * @property {number} evidenceExists
52
+ * @property {number} evidencePartial
53
+ * @property {number} evidenceMissing
54
+ * @property {number} completionPercentage
55
+ */
56
+ /**
57
+ * @typedef {Object} PhaseMetrics
58
+ * @property {CompliancePhase} phase
59
+ * @property {number} totalGaps
60
+ * @property {number} notStarted
61
+ * @property {number} inProgress
62
+ * @property {number} completed
63
+ * @property {number} blocked
64
+ * @property {number} completionPercentage
65
+ * @property {string|null} targetDate
66
+ */
67
+ export const COMPLIANCE_FRAMEWORKS = ['ISO27001', 'NHS_DTAC', 'NHS_DSPT', 'GDPR', 'FDA'];
68
+ export const GAP_STATUSES = ['not_started', 'in_progress', 'completed', 'blocked'];
69
+ export const GAP_PRIORITIES = ['critical', 'high', 'medium', 'low'];
70
+ export const EVIDENCE_STATUSES = ['exists', 'partial', 'missing'];
71
+ export const COMPLIANCE_PHASES = [
72
+ 'phase_1_critical_blockers',
73
+ 'phase_2_nhs_procurement_ready',
74
+ 'phase_3_enterprise_ready',
75
+ ];
76
+ // Status emoji mappings
77
+ const STATUS_EMOJI_MAP = {
78
+ 'Not Started': 'not_started',
79
+ 'In Progress': 'in_progress',
80
+ Completed: 'completed',
81
+ Blocked: 'blocked',
82
+ };
83
+ const PRIORITY_EMOJI_MAP = {
84
+ CRITICAL: 'critical',
85
+ HIGH: 'high',
86
+ MEDIUM: 'medium',
87
+ LOW: 'low',
88
+ };
89
+ const EVIDENCE_STATUS_MAP = {
90
+ 'Evidence exists': 'exists',
91
+ 'Partial evidence': 'partial',
92
+ 'No evidence': 'missing',
93
+ };
94
+ const PHASE_HEADER_MAP = {
95
+ 'Phase 1': 'phase_1_critical_blockers',
96
+ 'Phase 2': 'phase_2_nhs_procurement_ready',
97
+ 'Phase 3': 'phase_3_enterprise_ready',
98
+ };
99
+ // Framework keyword mappings for evidence parsing
100
+ const FRAMEWORK_KEYWORDS = {
101
+ ISO27001: ['ISO 27001', 'ISO27001', 'SOC 2', 'SOC2'],
102
+ NHS_DTAC: ['NHS DTAC', 'DTAC'],
103
+ NHS_DSPT: ['NHS DSPT', 'DSPT'],
104
+ GDPR: ['GDPR', 'UK GDPR', 'Data Protection'],
105
+ FDA: ['FDA', '21 CFR', 'Medical Device'],
106
+ };
107
+ export class ComplianceParser {
108
+ /**
109
+ * Parse gap-analysis.md content into structured GapItems
110
+ * @param {string} markdown
111
+ * @returns {GapItem[]}
112
+ */
113
+ parseGapAnalysis(markdown) {
114
+ const gaps = [];
115
+ const lines = markdown.split('\n');
116
+ let currentPhase = 'phase_1_critical_blockers';
117
+ let currentGap = null;
118
+ let inActionItems = false;
119
+ let inBlockers = false;
120
+ let currentActionItem = null;
121
+ for (let i = 0; i < lines.length; i++) {
122
+ const line = lines[i];
123
+ const trimmedLine = line.trim();
124
+ // Detect phase headers
125
+ if (trimmedLine.startsWith('## Phase')) {
126
+ for (const [phaseKey, phaseValue] of Object.entries(PHASE_HEADER_MAP)) {
127
+ if (trimmedLine.includes(phaseKey)) {
128
+ currentPhase = phaseValue;
129
+ break;
130
+ }
131
+ }
132
+ continue;
133
+ }
134
+ // Detect GAP header
135
+ const gapMatch = trimmedLine.match(/^### (GAP-\d+):\s*(.+)$/);
136
+ if (gapMatch) {
137
+ // Save previous gap if exists
138
+ if (currentGap?.gapId) {
139
+ if (currentActionItem?.id) {
140
+ currentGap.actionItems.push(currentActionItem);
141
+ }
142
+ gaps.push(this._finalizeGap(currentGap, currentPhase));
143
+ }
144
+ currentGap = {
145
+ gapId: gapMatch[1],
146
+ title: gapMatch[2],
147
+ phase: currentPhase,
148
+ actionItems: [],
149
+ blockers: [],
150
+ dependsOn: [],
151
+ };
152
+ currentActionItem = null;
153
+ inActionItems = false;
154
+ inBlockers = false;
155
+ continue;
156
+ }
157
+ if (!currentGap)
158
+ continue;
159
+ // Parse fields
160
+ if (trimmedLine.startsWith('**Priority:**')) {
161
+ currentGap.priority = this._parsePriority(trimmedLine);
162
+ }
163
+ else if (trimmedLine.startsWith('**Domain:**')) {
164
+ currentGap.domain = trimmedLine.replace('**Domain:**', '').trim();
165
+ }
166
+ else if (trimmedLine.startsWith('**Status:**')) {
167
+ currentGap.status = this._parseStatus(trimmedLine);
168
+ }
169
+ else if (trimmedLine.startsWith('**Owner:**')) {
170
+ currentGap.owner = trimmedLine.replace('**Owner:**', '').trim();
171
+ }
172
+ else if (trimmedLine.startsWith('**Target Date:**')) {
173
+ currentGap.targetDate = trimmedLine.replace('**Target Date:**', '').trim() || null;
174
+ }
175
+ else if (trimmedLine.startsWith('**Depends On:**')) {
176
+ const deps = this._extractGapReferences(trimmedLine);
177
+ currentGap.dependsOn = deps;
178
+ }
179
+ // Detect sections
180
+ if (trimmedLine === '**Action Items:**') {
181
+ inActionItems = true;
182
+ inBlockers = false;
183
+ continue;
184
+ }
185
+ if (trimmedLine === '**Blockers:**') {
186
+ inActionItems = false;
187
+ inBlockers = true;
188
+ continue;
189
+ }
190
+ if (trimmedLine.startsWith('**') && trimmedLine.endsWith('**')) {
191
+ if (!trimmedLine.includes('Action Items') && !trimmedLine.includes('Blockers')) {
192
+ inActionItems = false;
193
+ inBlockers = false;
194
+ }
195
+ }
196
+ // Parse action items
197
+ if (inActionItems) {
198
+ const actionMatch = trimmedLine.match(/^- \[[ x]\] \*\*(\d+\.\d+)\*\*\s+(.+)$/);
199
+ if (actionMatch) {
200
+ if (currentActionItem?.id) {
201
+ currentGap.actionItems.push(currentActionItem);
202
+ }
203
+ const isCompleted = trimmedLine.includes('[x]');
204
+ currentActionItem = {
205
+ id: actionMatch[1],
206
+ description: actionMatch[2],
207
+ status: isCompleted ? 'completed' : 'not_started',
208
+ owner: null,
209
+ dueDate: null,
210
+ };
211
+ }
212
+ else if (currentActionItem && trimmedLine.startsWith('- Owner:')) {
213
+ currentActionItem.owner = trimmedLine.replace('- Owner:', '').trim();
214
+ }
215
+ else if (currentActionItem && trimmedLine.startsWith('- Due:')) {
216
+ currentActionItem.dueDate = trimmedLine.replace('- Due:', '').trim();
217
+ }
218
+ else if (currentActionItem && trimmedLine.startsWith('- Status:')) {
219
+ currentActionItem.status = this._parseStatus(trimmedLine);
220
+ }
221
+ }
222
+ // Parse blockers
223
+ if (inBlockers && trimmedLine.startsWith('-') && !trimmedLine.includes('None')) {
224
+ const blockerText = trimmedLine.replace(/^-\s*/, '').replace(/^[🔴🟡]\s*/, '');
225
+ if (blockerText.trim()) {
226
+ currentGap.blockers.push(blockerText.trim());
227
+ // Also extract any GAP references
228
+ const gapRefs = this._extractGapReferences(trimmedLine);
229
+ for (const ref of gapRefs) {
230
+ if (!currentGap.dependsOn.includes(ref)) {
231
+ currentGap.dependsOn.push(ref);
232
+ }
233
+ }
234
+ }
235
+ }
236
+ }
237
+ // Save final gap
238
+ if (currentGap?.gapId) {
239
+ if (currentActionItem?.id) {
240
+ currentGap.actionItems.push(currentActionItem);
241
+ }
242
+ gaps.push(this._finalizeGap(currentGap, currentPhase));
243
+ }
244
+ return gaps;
245
+ }
246
+ /**
247
+ * Parse evidence-registry.md content into structured EvidenceItems
248
+ * @param {string} markdown
249
+ * @returns {EvidenceItem[]}
250
+ */
251
+ parseEvidenceRegistry(markdown) {
252
+ const evidence = [];
253
+ const lines = markdown.split('\n');
254
+ let currentSection = '';
255
+ let currentEvidence = null;
256
+ let inAuditNotes = false;
257
+ for (let i = 0; i < lines.length; i++) {
258
+ const line = lines[i];
259
+ const trimmedLine = line.trim();
260
+ // Detect section headers (## N. Section Name)
261
+ const sectionMatch = trimmedLine.match(/^## \d+\.\s*(.+)$/);
262
+ if (sectionMatch) {
263
+ currentSection = sectionMatch[1];
264
+ continue;
265
+ }
266
+ // Detect evidence item header (### N.N Title)
267
+ const evidenceMatch = trimmedLine.match(/^### (\d+\.\d+)\s+(.+)$/);
268
+ if (evidenceMatch) {
269
+ // Save previous evidence if exists
270
+ if (currentEvidence?.evidenceId) {
271
+ evidence.push(this._finalizeEvidence(currentEvidence, currentSection));
272
+ }
273
+ currentEvidence = {
274
+ evidenceId: evidenceMatch[1],
275
+ title: evidenceMatch[2],
276
+ section: currentSection,
277
+ auditNotes: [],
278
+ relatedGaps: [],
279
+ };
280
+ inAuditNotes = false;
281
+ continue;
282
+ }
283
+ if (!currentEvidence)
284
+ continue;
285
+ // Parse fields
286
+ if (trimmedLine.startsWith('**Requirement**:')) {
287
+ currentEvidence.requirement = trimmedLine.replace('**Requirement**:', '').trim();
288
+ }
289
+ else if (trimmedLine.startsWith('**Status**:')) {
290
+ currentEvidence.status = this._parseEvidenceStatus(trimmedLine);
291
+ }
292
+ // Detect Evidence section with Location
293
+ if (trimmedLine.includes('**Location**:')) {
294
+ const locationMatch = trimmedLine.match(/\*\*Location\*\*:\s*\[?([^\]]+)\]?/);
295
+ if (locationMatch) {
296
+ currentEvidence.location = locationMatch[1].replace(/\(.*\)/, '').trim();
297
+ }
298
+ }
299
+ // Detect Audit Notes section
300
+ if (trimmedLine === '**Audit Notes**:') {
301
+ inAuditNotes = true;
302
+ continue;
303
+ }
304
+ // Parse audit notes
305
+ if (inAuditNotes && trimmedLine.startsWith('-')) {
306
+ const noteText = trimmedLine.replace(/^-\s*/, '').trim();
307
+ if (noteText) {
308
+ currentEvidence.auditNotes.push(noteText);
309
+ // Extract GAP references from notes
310
+ const gapRefs = this._extractGapReferences(trimmedLine);
311
+ for (const ref of gapRefs) {
312
+ if (!currentEvidence.relatedGaps.includes(ref)) {
313
+ currentEvidence.relatedGaps.push(ref);
314
+ }
315
+ }
316
+ }
317
+ }
318
+ // End audit notes on next section
319
+ if (inAuditNotes && trimmedLine.startsWith('---')) {
320
+ inAuditNotes = false;
321
+ }
322
+ }
323
+ // Save final evidence
324
+ if (currentEvidence?.evidenceId) {
325
+ evidence.push(this._finalizeEvidence(currentEvidence, currentSection));
326
+ }
327
+ return evidence;
328
+ }
329
+ /**
330
+ * Calculate framework metrics from evidence items
331
+ * @param {EvidenceItem[]} evidence
332
+ * @returns {FrameworkMetrics[]}
333
+ */
334
+ calculateFrameworkMetrics(evidence) {
335
+ const frameworkCounts = {};
336
+ // Initialize all frameworks
337
+ for (const framework of COMPLIANCE_FRAMEWORKS) {
338
+ frameworkCounts[framework] = { total: 0, exists: 0, partial: 0, missing: 0 };
339
+ }
340
+ // Count evidence per framework
341
+ for (const item of evidence) {
342
+ const frameworks = this._detectFrameworks(item.requirement);
343
+ for (const framework of frameworks) {
344
+ frameworkCounts[framework].total++;
345
+ if (item.status === 'exists') {
346
+ frameworkCounts[framework].exists++;
347
+ }
348
+ else if (item.status === 'partial') {
349
+ frameworkCounts[framework].partial++;
350
+ }
351
+ else {
352
+ frameworkCounts[framework].missing++;
353
+ }
354
+ }
355
+ }
356
+ // Calculate metrics
357
+ return COMPLIANCE_FRAMEWORKS.map((framework) => {
358
+ const counts = frameworkCounts[framework];
359
+ // Completion: exists = 100%, partial = 50%, missing = 0%
360
+ const completionPercentage = counts.total > 0
361
+ ? Math.round((counts.exists * 100 + counts.partial * 50) / counts.total)
362
+ : 0;
363
+ return {
364
+ framework,
365
+ totalRequirements: counts.total,
366
+ evidenceExists: counts.exists,
367
+ evidencePartial: counts.partial,
368
+ evidenceMissing: counts.missing,
369
+ completionPercentage,
370
+ };
371
+ });
372
+ }
373
+ /**
374
+ * Calculate phase metrics from gap items
375
+ * @param {GapItem[]} gaps
376
+ * @returns {PhaseMetrics[]}
377
+ */
378
+ calculatePhaseMetrics(gaps) {
379
+ const phaseCounts = {};
380
+ // Initialize all phases
381
+ for (const phase of COMPLIANCE_PHASES) {
382
+ phaseCounts[phase] = { total: 0, notStarted: 0, inProgress: 0, completed: 0, blocked: 0 };
383
+ }
384
+ // Count gaps per phase
385
+ for (const gap of gaps) {
386
+ const phase = gap.phase;
387
+ phaseCounts[phase].total++;
388
+ switch (gap.status) {
389
+ case 'not_started':
390
+ phaseCounts[phase].notStarted++;
391
+ break;
392
+ case 'in_progress':
393
+ phaseCounts[phase].inProgress++;
394
+ break;
395
+ case 'completed':
396
+ phaseCounts[phase].completed++;
397
+ break;
398
+ case 'blocked':
399
+ phaseCounts[phase].blocked++;
400
+ break;
401
+ }
402
+ }
403
+ // Calculate metrics
404
+ return COMPLIANCE_PHASES.map((phase) => {
405
+ const counts = phaseCounts[phase];
406
+ const completionPercentage = counts.total > 0 ? Math.round((counts.completed / counts.total) * 100 * 100) / 100 : 0;
407
+ return {
408
+ phase,
409
+ totalGaps: counts.total,
410
+ notStarted: counts.notStarted,
411
+ inProgress: counts.inProgress,
412
+ completed: counts.completed,
413
+ blocked: counts.blocked,
414
+ completionPercentage,
415
+ targetDate: this._getPhaseTargetDate(phase),
416
+ };
417
+ });
418
+ }
419
+ // Helper methods
420
+ /** @private */
421
+ _parseStatus(text) {
422
+ for (const [key, value] of Object.entries(STATUS_EMOJI_MAP)) {
423
+ if (text.includes(key)) {
424
+ return value;
425
+ }
426
+ }
427
+ return 'not_started';
428
+ }
429
+ /** @private */
430
+ _parsePriority(text) {
431
+ for (const [key, value] of Object.entries(PRIORITY_EMOJI_MAP)) {
432
+ if (text.toUpperCase().includes(key)) {
433
+ return value;
434
+ }
435
+ }
436
+ return 'medium';
437
+ }
438
+ /** @private */
439
+ _parseEvidenceStatus(text) {
440
+ for (const [key, value] of Object.entries(EVIDENCE_STATUS_MAP)) {
441
+ if (text.includes(key)) {
442
+ return value;
443
+ }
444
+ }
445
+ return 'missing';
446
+ }
447
+ /** @private */
448
+ _extractGapReferences(text) {
449
+ const matches = text.match(/GAP-\d+/g);
450
+ return matches ? [...new Set(matches)] : [];
451
+ }
452
+ /** @private */
453
+ _detectFrameworks(requirement) {
454
+ const frameworks = [];
455
+ for (const [framework, keywords] of Object.entries(FRAMEWORK_KEYWORDS)) {
456
+ for (const keyword of keywords) {
457
+ if (requirement.includes(keyword)) {
458
+ frameworks.push(framework);
459
+ break;
460
+ }
461
+ }
462
+ }
463
+ return frameworks;
464
+ }
465
+ /** @private */
466
+ _finalizeGap(partial, phase) {
467
+ return {
468
+ gapId: partial.gapId || 'UNKNOWN',
469
+ title: partial.title || 'Untitled',
470
+ domain: partial.domain || 'Unknown',
471
+ priority: partial.priority || 'medium',
472
+ status: partial.status || 'not_started',
473
+ phase: partial.phase || phase,
474
+ owner: partial.owner || 'Unassigned',
475
+ targetDate: partial.targetDate || null,
476
+ actionItems: partial.actionItems || [],
477
+ blockers: partial.blockers || [],
478
+ dependsOn: partial.dependsOn || [],
479
+ };
480
+ }
481
+ /** @private */
482
+ _finalizeEvidence(partial, section) {
483
+ return {
484
+ evidenceId: partial.evidenceId || 'UNKNOWN',
485
+ section: partial.section || section,
486
+ title: partial.title || 'Untitled',
487
+ requirement: partial.requirement || '',
488
+ status: partial.status || 'missing',
489
+ location: partial.location || null,
490
+ auditNotes: partial.auditNotes || [],
491
+ relatedGaps: partial.relatedGaps || [],
492
+ };
493
+ }
494
+ /** @private */
495
+ _getPhaseTargetDate(phase) {
496
+ switch (phase) {
497
+ case 'phase_1_critical_blockers':
498
+ return 'Month 3';
499
+ case 'phase_2_nhs_procurement_ready':
500
+ return 'Month 6';
501
+ case 'phase_3_enterprise_ready':
502
+ return 'Month 12';
503
+ default:
504
+ return null;
505
+ }
506
+ }
507
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Backlog Parsing Patterns
3
+ *
4
+ * Centralizes patterns for parsing status.md and backlog.md files.
5
+ * Used by lane-checker.mjs and related backlog utilities.
6
+ */
7
+ /** Markdown section header patterns for In Progress section */
8
+ export declare const IN_PROGRESS_HEADERS: string[];
9
+ /**
10
+ * Pattern for extracting WU ID from backlog links.
11
+ * Matches: [WU-123 — Title text](path/to/file.yaml)
12
+ * Captures: WU ID (e.g., "WU-123")
13
+ */
14
+ export declare const WU_LINK_PATTERN: RegExp;
15
+ /**
16
+ * Check if a line matches an In Progress section header.
17
+ * @param {string} line - Line to check (will be trimmed and lowercased)
18
+ * @returns {boolean} True if line is an In Progress header
19
+ */
20
+ export declare function isInProgressHeader(line: any): boolean;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Backlog Parsing Patterns
3
+ *
4
+ * Centralizes patterns for parsing status.md and backlog.md files.
5
+ * Used by lane-checker.mjs and related backlog utilities.
6
+ */
7
+ /** Markdown section header patterns for In Progress section */
8
+ export const IN_PROGRESS_HEADERS = ['## in progress', '## 🔧 in progress'];
9
+ /**
10
+ * Pattern for extracting WU ID from backlog links.
11
+ * Matches: [WU-123 — Title text](path/to/file.yaml)
12
+ * Captures: WU ID (e.g., "WU-123")
13
+ */
14
+ export const WU_LINK_PATTERN = /\[([A-Z]+-\d+)\s*—\s*[^\]]+\]\([^)]+\)/gi;
15
+ /**
16
+ * Check if a line matches an In Progress section header.
17
+ * @param {string} line - Line to check (will be trimmed and lowercased)
18
+ * @returns {boolean} True if line is an In Progress header
19
+ */
20
+ export function isInProgressHeader(line) {
21
+ const normalized = line.trim().toLowerCase();
22
+ return IN_PROGRESS_HEADERS.some((header) => normalized === header || normalized.startsWith(header));
23
+ }