@wundr.io/cli 1.0.1 → 1.0.4

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 (249) hide show
  1. package/dist/ai/ai-service.d.ts +152 -0
  2. package/dist/ai/ai-service.d.ts.map +1 -0
  3. package/dist/ai/ai-service.js +430 -0
  4. package/dist/ai/ai-service.js.map +1 -0
  5. package/dist/ai/claude-client.d.ts +130 -0
  6. package/dist/ai/claude-client.d.ts.map +1 -0
  7. package/dist/ai/claude-client.js +340 -0
  8. package/dist/ai/claude-client.js.map +1 -0
  9. package/dist/ai/conversation-manager.d.ts +164 -0
  10. package/dist/ai/conversation-manager.d.ts.map +1 -0
  11. package/dist/ai/conversation-manager.js +614 -0
  12. package/dist/ai/conversation-manager.js.map +1 -0
  13. package/dist/ai/index.d.ts +5 -0
  14. package/dist/ai/index.d.ts.map +1 -0
  15. package/dist/ai/index.js +8 -0
  16. package/dist/ai/index.js.map +1 -0
  17. package/dist/cli.d.ts +36 -0
  18. package/dist/cli.d.ts.map +1 -0
  19. package/dist/cli.js +192 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/commands/ai.d.ts +89 -0
  22. package/dist/commands/ai.d.ts.map +1 -0
  23. package/dist/commands/ai.js +799 -0
  24. package/dist/commands/ai.js.map +1 -0
  25. package/dist/commands/alignment.d.ts +78 -0
  26. package/dist/commands/alignment.d.ts.map +1 -0
  27. package/dist/commands/alignment.js +817 -0
  28. package/dist/commands/alignment.js.map +1 -0
  29. package/dist/commands/analyze-optimized.d.ts +14 -0
  30. package/dist/commands/analyze-optimized.d.ts.map +1 -0
  31. package/dist/commands/analyze-optimized.js +600 -0
  32. package/dist/commands/analyze-optimized.js.map +1 -0
  33. package/dist/commands/analyze.d.ts +65 -0
  34. package/dist/commands/analyze.d.ts.map +1 -0
  35. package/dist/commands/analyze.js +435 -0
  36. package/dist/commands/analyze.js.map +1 -0
  37. package/dist/commands/batch.d.ts +71 -0
  38. package/dist/commands/batch.d.ts.map +1 -0
  39. package/dist/commands/batch.js +738 -0
  40. package/dist/commands/batch.js.map +1 -0
  41. package/dist/commands/chat.d.ts +71 -0
  42. package/dist/commands/chat.d.ts.map +1 -0
  43. package/dist/commands/chat.js +674 -0
  44. package/dist/commands/chat.js.map +1 -0
  45. package/dist/commands/claude-init.d.ts +28 -0
  46. package/dist/commands/claude-init.d.ts.map +1 -0
  47. package/dist/commands/claude-init.js +591 -0
  48. package/dist/commands/claude-init.js.map +1 -0
  49. package/dist/commands/claude-setup.d.ts +119 -0
  50. package/dist/commands/claude-setup.d.ts.map +1 -0
  51. package/dist/commands/claude-setup.js +1073 -0
  52. package/dist/commands/claude-setup.js.map +1 -0
  53. package/dist/commands/computer-setup-commands.d.ts +53 -0
  54. package/dist/commands/computer-setup-commands.d.ts.map +1 -0
  55. package/dist/commands/computer-setup-commands.js +705 -0
  56. package/dist/commands/computer-setup-commands.js.map +1 -0
  57. package/dist/commands/computer-setup.d.ts +7 -0
  58. package/dist/commands/computer-setup.d.ts.map +1 -0
  59. package/dist/commands/computer-setup.js +849 -0
  60. package/dist/commands/computer-setup.js.map +1 -0
  61. package/dist/commands/create-command.d.ts +7 -0
  62. package/dist/commands/create-command.d.ts.map +1 -0
  63. package/dist/commands/create-command.js +158 -0
  64. package/dist/commands/create-command.js.map +1 -0
  65. package/dist/commands/create.d.ts +74 -0
  66. package/dist/commands/create.d.ts.map +1 -0
  67. package/dist/commands/create.js +556 -0
  68. package/dist/commands/create.js.map +1 -0
  69. package/dist/commands/dashboard.d.ts +91 -0
  70. package/dist/commands/dashboard.d.ts.map +1 -0
  71. package/dist/commands/dashboard.js +538 -0
  72. package/dist/commands/dashboard.js.map +1 -0
  73. package/dist/commands/govern.d.ts +70 -0
  74. package/dist/commands/govern.d.ts.map +1 -0
  75. package/dist/commands/govern.js +481 -0
  76. package/dist/commands/govern.js.map +1 -0
  77. package/dist/commands/governance.d.ts +17 -0
  78. package/dist/commands/governance.d.ts.map +1 -0
  79. package/dist/commands/governance.js +703 -0
  80. package/dist/commands/governance.js.map +1 -0
  81. package/dist/commands/guardian.d.ts +20 -0
  82. package/dist/commands/guardian.d.ts.map +1 -0
  83. package/dist/commands/guardian.js +597 -0
  84. package/dist/commands/guardian.js.map +1 -0
  85. package/dist/commands/init.d.ts +59 -0
  86. package/dist/commands/init.d.ts.map +1 -0
  87. package/dist/commands/init.js +650 -0
  88. package/dist/commands/init.js.map +1 -0
  89. package/dist/commands/performance-optimizer.d.ts +30 -0
  90. package/dist/commands/performance-optimizer.d.ts.map +1 -0
  91. package/dist/commands/performance-optimizer.js +650 -0
  92. package/dist/commands/performance-optimizer.js.map +1 -0
  93. package/dist/commands/plugins.d.ts +87 -0
  94. package/dist/commands/plugins.d.ts.map +1 -0
  95. package/dist/commands/plugins.js +685 -0
  96. package/dist/commands/plugins.js.map +1 -0
  97. package/dist/commands/rag.d.ts +7 -0
  98. package/dist/commands/rag.d.ts.map +1 -0
  99. package/dist/commands/rag.js +748 -0
  100. package/dist/commands/rag.js.map +1 -0
  101. package/dist/commands/session.d.ts +41 -0
  102. package/dist/commands/session.d.ts.map +1 -0
  103. package/dist/commands/session.js +441 -0
  104. package/dist/commands/session.js.map +1 -0
  105. package/dist/commands/setup.d.ts +29 -0
  106. package/dist/commands/setup.d.ts.map +1 -0
  107. package/dist/commands/setup.js +397 -0
  108. package/dist/commands/setup.js.map +1 -0
  109. package/dist/commands/test-init.d.ts +9 -0
  110. package/dist/commands/test-init.d.ts.map +1 -0
  111. package/dist/commands/test-init.js +222 -0
  112. package/dist/commands/test-init.js.map +1 -0
  113. package/dist/commands/test.d.ts +25 -0
  114. package/dist/commands/test.d.ts.map +1 -0
  115. package/dist/commands/test.js +217 -0
  116. package/dist/commands/test.js.map +1 -0
  117. package/dist/commands/vp.d.ts +7 -0
  118. package/dist/commands/vp.d.ts.map +1 -0
  119. package/dist/commands/vp.js +571 -0
  120. package/dist/commands/vp.js.map +1 -0
  121. package/dist/commands/watch.d.ts +76 -0
  122. package/dist/commands/watch.d.ts.map +1 -0
  123. package/dist/commands/watch.js +613 -0
  124. package/dist/commands/watch.js.map +1 -0
  125. package/dist/commands/worktree.d.ts +63 -0
  126. package/dist/commands/worktree.d.ts.map +1 -0
  127. package/dist/commands/worktree.js +774 -0
  128. package/dist/commands/worktree.js.map +1 -0
  129. package/dist/context/context-manager.d.ts +155 -0
  130. package/dist/context/context-manager.d.ts.map +1 -0
  131. package/dist/context/context-manager.js +383 -0
  132. package/dist/context/context-manager.js.map +1 -0
  133. package/dist/context/index.d.ts +3 -0
  134. package/dist/context/index.d.ts.map +1 -0
  135. package/dist/context/index.js +6 -0
  136. package/dist/context/index.js.map +1 -0
  137. package/dist/context/session-manager.d.ts +207 -0
  138. package/dist/context/session-manager.d.ts.map +1 -0
  139. package/dist/context/session-manager.js +686 -0
  140. package/dist/context/session-manager.js.map +1 -0
  141. package/dist/index.d.ts +8 -0
  142. package/dist/index.d.ts.map +1 -0
  143. package/dist/index.js +51 -0
  144. package/dist/index.js.map +1 -0
  145. package/dist/interactive/interactive-mode.d.ts +76 -0
  146. package/dist/interactive/interactive-mode.d.ts.map +1 -0
  147. package/dist/interactive/interactive-mode.js +732 -0
  148. package/dist/interactive/interactive-mode.js.map +1 -0
  149. package/dist/nlp/command-mapper.d.ts +174 -0
  150. package/dist/nlp/command-mapper.d.ts.map +1 -0
  151. package/dist/nlp/command-mapper.js +624 -0
  152. package/dist/nlp/command-mapper.js.map +1 -0
  153. package/dist/nlp/command-parser.d.ts +106 -0
  154. package/dist/nlp/command-parser.d.ts.map +1 -0
  155. package/dist/nlp/command-parser.js +417 -0
  156. package/dist/nlp/command-parser.js.map +1 -0
  157. package/dist/nlp/index.d.ts +5 -0
  158. package/dist/nlp/index.d.ts.map +1 -0
  159. package/dist/nlp/index.js +8 -0
  160. package/dist/nlp/index.js.map +1 -0
  161. package/dist/nlp/intent-classifier.d.ts +59 -0
  162. package/dist/nlp/intent-classifier.d.ts.map +1 -0
  163. package/dist/nlp/intent-classifier.js +384 -0
  164. package/dist/nlp/intent-classifier.js.map +1 -0
  165. package/dist/nlp/intent-parser.d.ts +152 -0
  166. package/dist/nlp/intent-parser.d.ts.map +1 -0
  167. package/dist/nlp/intent-parser.js +744 -0
  168. package/dist/nlp/intent-parser.js.map +1 -0
  169. package/dist/plugins/plugin-manager.d.ts +120 -0
  170. package/dist/plugins/plugin-manager.d.ts.map +1 -0
  171. package/dist/plugins/plugin-manager.js +595 -0
  172. package/dist/plugins/plugin-manager.js.map +1 -0
  173. package/dist/types/index.d.ts +224 -0
  174. package/dist/types/index.d.ts.map +1 -0
  175. package/dist/types/index.js +3 -0
  176. package/dist/types/index.js.map +1 -0
  177. package/dist/utils/backup-rollback-manager.d.ts +72 -0
  178. package/dist/utils/backup-rollback-manager.d.ts.map +1 -0
  179. package/dist/utils/backup-rollback-manager.js +289 -0
  180. package/dist/utils/backup-rollback-manager.js.map +1 -0
  181. package/dist/utils/claude-config-installer.d.ts +94 -0
  182. package/dist/utils/claude-config-installer.d.ts.map +1 -0
  183. package/dist/utils/claude-config-installer.js +628 -0
  184. package/dist/utils/claude-config-installer.js.map +1 -0
  185. package/dist/utils/config-manager.d.ts +73 -0
  186. package/dist/utils/config-manager.d.ts.map +1 -0
  187. package/dist/utils/config-manager.js +339 -0
  188. package/dist/utils/config-manager.js.map +1 -0
  189. package/dist/utils/error-handler.d.ts +46 -0
  190. package/dist/utils/error-handler.d.ts.map +1 -0
  191. package/dist/utils/error-handler.js +169 -0
  192. package/dist/utils/error-handler.js.map +1 -0
  193. package/dist/utils/logger.d.ts +25 -0
  194. package/dist/utils/logger.d.ts.map +1 -0
  195. package/dist/utils/logger.js +105 -0
  196. package/dist/utils/logger.js.map +1 -0
  197. package/package.json +6 -4
  198. package/src/ai/ai-service.ts +22 -19
  199. package/src/ai/claude-client.ts +20 -16
  200. package/src/ai/conversation-manager.ts +37 -30
  201. package/src/cli.ts +46 -17
  202. package/src/commands/ai.ts +196 -88
  203. package/src/commands/alignment.ts +1212 -0
  204. package/src/commands/analyze-optimized.ts +394 -89
  205. package/src/commands/analyze.ts +22 -20
  206. package/src/commands/batch.ts +41 -38
  207. package/src/commands/chat.ts +37 -34
  208. package/src/commands/claude-init.ts +38 -30
  209. package/src/commands/claude-setup.ts +692 -97
  210. package/src/commands/computer-setup-commands.ts +45 -39
  211. package/src/commands/computer-setup.ts +490 -20
  212. package/src/commands/create-command.ts +7 -7
  213. package/src/commands/create.ts +36 -33
  214. package/src/commands/dashboard.ts +33 -28
  215. package/src/commands/govern.ts +34 -29
  216. package/src/commands/governance.ts +1005 -0
  217. package/src/commands/guardian.ts +887 -0
  218. package/src/commands/init.ts +112 -22
  219. package/src/commands/performance-optimizer.ts +48 -42
  220. package/src/commands/plugins.ts +35 -32
  221. package/src/commands/project-update.ts +1053 -0
  222. package/src/commands/rag.ts +904 -0
  223. package/src/commands/session.ts +631 -0
  224. package/src/commands/setup.ts +35 -31
  225. package/src/commands/test-init.ts +6 -5
  226. package/src/commands/test.ts +7 -6
  227. package/src/commands/vp.ts +762 -0
  228. package/src/commands/watch.ts +44 -33
  229. package/src/commands/worktree.ts +1057 -0
  230. package/src/context/context-manager.ts +15 -12
  231. package/src/context/session-manager.ts +51 -40
  232. package/src/index.ts +7 -6
  233. package/src/interactive/interactive-mode.ts +25 -18
  234. package/src/lib/conflict-resolution.ts +28 -0
  235. package/src/lib/merge-strategy.ts +28 -0
  236. package/src/lib/safety-mechanisms.ts +47 -0
  237. package/src/lib/state-detection.ts +28 -0
  238. package/src/nlp/command-mapper.ts +35 -30
  239. package/src/nlp/command-parser.ts +20 -17
  240. package/src/nlp/intent-classifier.ts +7 -7
  241. package/src/nlp/intent-parser.ts +61 -49
  242. package/src/plugins/plugin-manager.ts +27 -23
  243. package/src/types/index.ts +1 -1
  244. package/src/types/modules.d.ts +1 -0
  245. package/src/utils/backup-rollback-manager.ts +13 -11
  246. package/src/utils/claude-config-installer.ts +18 -16
  247. package/src/utils/config-manager.ts +12 -9
  248. package/src/utils/error-handler.ts +5 -3
  249. package/src/utils/logger.ts +35 -12
@@ -0,0 +1,1005 @@
1
+ /**
2
+ * Governance CLI Commands - IPRE Compliance
3
+ *
4
+ * Implements governance commands from Appendix B:
5
+ * - wundr governance check - Run IPRE compliance check
6
+ * - wundr governance report - Generate alignment debt report
7
+ * - wundr governance status - Show current governance status
8
+ * - wundr governance validate <file> - Validate IPRE config file
9
+ */
10
+
11
+ import path from 'path';
12
+
13
+ import chalk from 'chalk';
14
+ import { Command } from 'commander';
15
+ import fs from 'fs-extra';
16
+ import YAML from 'yaml';
17
+
18
+ import {
19
+ createEvaluator,
20
+ createEvaluatorSuite,
21
+ runEvaluatorSuite,
22
+ PolicyEngine,
23
+ type EvaluationContext,
24
+ type EvaluationResult,
25
+ type ComplianceResult,
26
+ type IPREConfig,
27
+ } from '@wundr.io/governance';
28
+
29
+ import { errorHandler } from '../utils/error-handler';
30
+ import { logger } from '../utils/logger';
31
+
32
+ // ============================================================================
33
+ // Types
34
+ // ============================================================================
35
+
36
+ interface CheckOptions {
37
+ session?: string;
38
+ verbose?: boolean;
39
+ }
40
+
41
+ interface ReportOptions {
42
+ session?: string;
43
+ output?: string;
44
+ format?: 'md' | 'json';
45
+ }
46
+
47
+ interface GovernanceStatus {
48
+ alignmentScore: number;
49
+ policyViolations: number;
50
+ recentInterventions: Intervention[];
51
+ lastCheck: Date | null;
52
+ driftIndicators: DriftIndicator[];
53
+ }
54
+
55
+ interface Intervention {
56
+ id: string;
57
+ type: string;
58
+ timestamp: Date;
59
+ description: string;
60
+ resolved: boolean;
61
+ }
62
+
63
+ interface DriftIndicator {
64
+ pattern: string;
65
+ baseline: number;
66
+ current: number;
67
+ change: number;
68
+ severity: 'low' | 'medium' | 'high' | 'critical';
69
+ }
70
+
71
+ interface AlignmentDebtReport {
72
+ generatedAt: string;
73
+ sessionId: string | null;
74
+ summary: {
75
+ totalDebt: number;
76
+ criticalIssues: number;
77
+ highPriorityItems: number;
78
+ alignmentScore: number;
79
+ complianceScore: number;
80
+ driftScore: number;
81
+ };
82
+ policyViolations: PolicyViolationDetail[];
83
+ alignmentGaps: AlignmentGapDetail[];
84
+ driftAlerts: DriftAlertDetail[];
85
+ recommendations: string[];
86
+ }
87
+
88
+ interface PolicyViolationDetail {
89
+ policyId: string;
90
+ policyName: string;
91
+ severity: string;
92
+ description: string;
93
+ location?: string;
94
+ suggestedFix?: string;
95
+ }
96
+
97
+ interface AlignmentGapDetail {
98
+ dimension: string;
99
+ expected: number;
100
+ actual: number;
101
+ gap: number;
102
+ priority: string;
103
+ }
104
+
105
+ interface DriftAlertDetail {
106
+ pattern: string;
107
+ baselineValue: number;
108
+ currentValue: number;
109
+ changePercent: number;
110
+ direction: string;
111
+ severity: string;
112
+ }
113
+
114
+ // ============================================================================
115
+ // Governance Command Factory
116
+ // ============================================================================
117
+
118
+ /**
119
+ * Creates the governance command with all subcommands
120
+ */
121
+ export function createGovernanceCommand(): Command {
122
+ const governance = new Command('governance')
123
+ .alias('gov')
124
+ .description('IPRE governance and compliance tools');
125
+
126
+ // Check subcommand
127
+ governance
128
+ .command('check')
129
+ .description('Run IPRE compliance check')
130
+ .option('-s, --session <id>', 'Session ID to check')
131
+ .option('-v, --verbose', 'Enable verbose output')
132
+ .action(async (options: CheckOptions) => {
133
+ await runComplianceCheck(options);
134
+ });
135
+
136
+ // Report subcommand
137
+ governance
138
+ .command('report')
139
+ .description('Generate alignment debt report')
140
+ .option('-s, --session <id>', 'Session ID for the report')
141
+ .option('-o, --output <file>', 'Output file path')
142
+ .option('-f, --format <format>', 'Output format (md|json)', 'md')
143
+ .action(async (options: ReportOptions) => {
144
+ await generateAlignmentReport(options);
145
+ });
146
+
147
+ // Status subcommand
148
+ governance
149
+ .command('status')
150
+ .description('Show current governance status')
151
+ .action(async () => {
152
+ await showGovernanceStatus();
153
+ });
154
+
155
+ // Validate subcommand
156
+ governance
157
+ .command('validate <file>')
158
+ .description('Validate IPRE config file')
159
+ .action(async (file: string) => {
160
+ await validateIPREConfig(file);
161
+ });
162
+
163
+ return governance;
164
+ }
165
+
166
+ // Re-export the full-featured alignment command from the dedicated module
167
+ // This provides: report, score, history, and dimensions subcommands
168
+ export { createAlignmentCommand } from './alignment';
169
+
170
+ // ============================================================================
171
+ // Command Implementations
172
+ // ============================================================================
173
+
174
+ /**
175
+ * Run IPRE compliance check
176
+ */
177
+ async function runComplianceCheck(options: CheckOptions): Promise<void> {
178
+ try {
179
+ logger.info('Running IPRE compliance check...');
180
+
181
+ const sessionId = options.session || `session-${Date.now()}`;
182
+ const verbose = options.verbose || false;
183
+
184
+ // Create evaluation context
185
+ const context: EvaluationContext = {
186
+ evaluationId: `eval-${Date.now()}`,
187
+ timestamp: new Date(),
188
+ source: 'manual',
189
+ repository: process.cwd(),
190
+ metadata: {
191
+ sessionId,
192
+ },
193
+ };
194
+
195
+ // Create evaluator suite
196
+ const suite = createEvaluatorSuite();
197
+
198
+ // Run policy compliance check
199
+ console.log(chalk.blue('\n--- Policy Compliance ---'));
200
+ const complianceResult =
201
+ await suite.policyCompliance.checkPolicyCompliance(context);
202
+ displayComplianceResult(complianceResult, verbose);
203
+
204
+ // Run reward alignment check
205
+ console.log(chalk.blue('\n--- Reward Alignment ---'));
206
+ const alignmentEvaluator = createEvaluator('reward_alignment');
207
+ const alignmentResult = await alignmentEvaluator.evaluate(context);
208
+ displayAlignmentResult(alignmentResult, verbose);
209
+
210
+ // Run drift detection
211
+ console.log(chalk.blue('\n--- Drift Detection ---'));
212
+ const driftEvaluator = createEvaluator('drift_detection');
213
+ const driftResult = await driftEvaluator.evaluate(context);
214
+ displayDriftResult(driftResult, verbose);
215
+
216
+ // Run full suite and show summary
217
+ console.log(chalk.blue('\n--- Overall Summary ---'));
218
+ const evaluators = [
219
+ suite.policyCompliance,
220
+ suite.rewardAlignment,
221
+ suite.driftDetection,
222
+ ];
223
+ const suiteResult = await runEvaluatorSuite(evaluators, context);
224
+
225
+ displaySummary(suiteResult);
226
+
227
+ // Save state for future checks
228
+ await saveGovernanceState(sessionId, {
229
+ complianceResult,
230
+ alignmentResult,
231
+ driftResult,
232
+ suiteResult,
233
+ });
234
+
235
+ if (suiteResult.passed) {
236
+ logger.success('IPRE compliance check passed');
237
+ } else {
238
+ logger.warn('IPRE compliance check found issues');
239
+ process.exitCode = 1;
240
+ }
241
+ } catch (error) {
242
+ throw errorHandler.createError(
243
+ 'WUNDR_GOV_CHECK_FAILED',
244
+ 'Failed to run IPRE compliance check',
245
+ { options },
246
+ true,
247
+ );
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Generate alignment debt report
253
+ */
254
+ async function generateAlignmentReport(options: ReportOptions): Promise<void> {
255
+ try {
256
+ logger.info('Generating alignment debt report...');
257
+
258
+ const sessionId = options.session || null;
259
+ const format = options.format || 'md';
260
+ const outputPath =
261
+ options.output || `alignment-report-${Date.now()}.${format}`;
262
+
263
+ // Create evaluation context
264
+ const context: EvaluationContext = {
265
+ evaluationId: `eval-${Date.now()}`,
266
+ timestamp: new Date(),
267
+ source: 'manual',
268
+ repository: process.cwd(),
269
+ };
270
+
271
+ // Run all evaluations
272
+ const suite = createEvaluatorSuite();
273
+ const complianceResult =
274
+ await suite.policyCompliance.checkPolicyCompliance(context);
275
+
276
+ // Get alignment gaps
277
+ const alignmentEvaluator = createEvaluator('reward_alignment');
278
+ const alignmentEvalResult = await alignmentEvaluator.evaluate(context);
279
+
280
+ // Get drift indicators
281
+ const driftEvaluator = createEvaluator('drift_detection');
282
+ const driftEvalResult = await driftEvaluator.evaluate(context);
283
+
284
+ // Build report
285
+ const report: AlignmentDebtReport = {
286
+ generatedAt: new Date().toISOString(),
287
+ sessionId,
288
+ summary: {
289
+ totalDebt: calculateAlignmentDebt(
290
+ complianceResult,
291
+ alignmentEvalResult,
292
+ driftEvalResult,
293
+ ),
294
+ criticalIssues: countCriticalIssues(complianceResult),
295
+ highPriorityItems: countHighPriorityItems(alignmentEvalResult),
296
+ alignmentScore: alignmentEvalResult.score,
297
+ complianceScore: complianceResult.score,
298
+ driftScore: 1 - driftEvalResult.score, // Invert since lower drift is better
299
+ },
300
+ policyViolations: complianceResult.violations.map(v => ({
301
+ policyId: v.policyId,
302
+ policyName: v.policyName,
303
+ severity: v.severity,
304
+ description: v.description,
305
+ location: v.location,
306
+ suggestedFix: v.suggestedFix,
307
+ })),
308
+ alignmentGaps: extractAlignmentGaps(alignmentEvalResult),
309
+ driftAlerts: extractDriftAlerts(driftEvalResult),
310
+ recommendations: generateRecommendations(
311
+ complianceResult,
312
+ alignmentEvalResult,
313
+ driftEvalResult,
314
+ ),
315
+ };
316
+
317
+ // Output report
318
+ if (format === 'json') {
319
+ await fs.writeJson(outputPath, report, { spaces: 2 });
320
+ } else {
321
+ const markdown = formatReportAsMarkdown(report);
322
+ await fs.writeFile(outputPath, markdown, 'utf-8');
323
+ }
324
+
325
+ logger.success(`Alignment debt report generated: ${outputPath}`);
326
+
327
+ // Display summary
328
+ console.log(chalk.blue('\n--- Report Summary ---'));
329
+ console.log(
330
+ `Total Alignment Debt: ${chalk.yellow(report.summary.totalDebt.toFixed(2))}`,
331
+ );
332
+ console.log(`Critical Issues: ${chalk.red(report.summary.criticalIssues)}`);
333
+ console.log(
334
+ `High Priority Items: ${chalk.yellow(report.summary.highPriorityItems)}`,
335
+ );
336
+ console.log(
337
+ `Alignment Score: ${colorScore(report.summary.alignmentScore)}`,
338
+ );
339
+ console.log(
340
+ `Compliance Score: ${colorScore(report.summary.complianceScore)}`,
341
+ );
342
+ console.log(`Drift Score: ${colorScore(1 - report.summary.driftScore)}`);
343
+ } catch (error) {
344
+ throw errorHandler.createError(
345
+ 'WUNDR_GOV_REPORT_FAILED',
346
+ 'Failed to generate alignment debt report',
347
+ { options },
348
+ true,
349
+ );
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Show current governance status
355
+ */
356
+ async function showGovernanceStatus(): Promise<void> {
357
+ try {
358
+ logger.info('Fetching governance status...');
359
+
360
+ // Load saved state if available
361
+ const state = await loadGovernanceState();
362
+
363
+ // Create policy engine and get stats
364
+ const policyEngine = new PolicyEngine();
365
+ const violationStats = policyEngine.getViolationStats();
366
+
367
+ const status: GovernanceStatus = {
368
+ alignmentScore: state?.suiteResult?.overallScore ?? 0,
369
+ policyViolations: violationStats.total,
370
+ recentInterventions: await loadRecentInterventions(),
371
+ lastCheck: state?.timestamp ? new Date(state.timestamp) : null,
372
+ driftIndicators: extractDriftIndicatorsFromState(state),
373
+ };
374
+
375
+ // Display status
376
+ console.log(chalk.cyan('\n===================================='));
377
+ console.log(chalk.cyan(' GOVERNANCE STATUS'));
378
+ console.log(chalk.cyan('====================================\n'));
379
+
380
+ // Alignment Score
381
+ console.log(chalk.bold('Alignment Score:'));
382
+ displayProgressBar(status.alignmentScore);
383
+ console.log(
384
+ ` ${colorScore(status.alignmentScore)} (${(status.alignmentScore * 100).toFixed(1)}%)\n`,
385
+ );
386
+
387
+ // Policy Violations
388
+ console.log(chalk.bold('Policy Violations:'));
389
+ if (status.policyViolations === 0) {
390
+ console.log(chalk.green(' No active violations'));
391
+ } else {
392
+ console.log(chalk.red(` ${status.policyViolations} active violations`));
393
+ console.log(` - Security: ${violationStats.byCategory.security}`);
394
+ console.log(` - Compliance: ${violationStats.byCategory.compliance}`);
395
+ console.log(
396
+ ` - Operational: ${violationStats.byCategory.operational}`,
397
+ );
398
+ }
399
+ console.log();
400
+
401
+ // Recent Interventions
402
+ console.log(chalk.bold('Recent Interventions:'));
403
+ if (status.recentInterventions.length === 0) {
404
+ console.log(chalk.green(' No recent interventions'));
405
+ } else {
406
+ for (const intervention of status.recentInterventions.slice(0, 5)) {
407
+ const statusIcon = intervention.resolved
408
+ ? chalk.green('[RESOLVED]')
409
+ : chalk.yellow('[OPEN]');
410
+ console.log(
411
+ ` ${statusIcon} ${intervention.type}: ${intervention.description}`,
412
+ );
413
+ }
414
+ }
415
+ console.log();
416
+
417
+ // Drift Indicators
418
+ console.log(chalk.bold('Drift Indicators:'));
419
+ if (status.driftIndicators.length === 0) {
420
+ console.log(chalk.green(' No significant drift detected'));
421
+ } else {
422
+ for (const indicator of status.driftIndicators) {
423
+ const severityColor = getSeverityColor(indicator.severity);
424
+ const direction = indicator.change > 0 ? '+' : '';
425
+ console.log(
426
+ ` ${severityColor(`[${indicator.severity.toUpperCase()}]`)} ` +
427
+ `${indicator.pattern}: ${direction}${(indicator.change * 100).toFixed(1)}%`,
428
+ );
429
+ }
430
+ }
431
+ console.log();
432
+
433
+ // Last Check
434
+ if (status.lastCheck) {
435
+ console.log(
436
+ chalk.gray(`Last check: ${status.lastCheck.toLocaleString()}`),
437
+ );
438
+ } else {
439
+ console.log(
440
+ chalk.gray(
441
+ 'No previous checks found. Run "wundr governance check" to start.',
442
+ ),
443
+ );
444
+ }
445
+ } catch (error) {
446
+ throw errorHandler.createError(
447
+ 'WUNDR_GOV_STATUS_FAILED',
448
+ 'Failed to fetch governance status',
449
+ {},
450
+ true,
451
+ );
452
+ }
453
+ }
454
+
455
+ /**
456
+ * Validate IPRE config file
457
+ */
458
+ async function validateIPREConfig(file: string): Promise<void> {
459
+ try {
460
+ const filePath = path.isAbsolute(file)
461
+ ? file
462
+ : path.join(process.cwd(), file);
463
+
464
+ logger.info(`Validating IPRE config: ${filePath}`);
465
+
466
+ // Check file exists
467
+ if (!(await fs.pathExists(filePath))) {
468
+ logger.error(`File not found: ${filePath}`);
469
+ process.exitCode = 1;
470
+ return;
471
+ }
472
+
473
+ // Read and parse file
474
+ const content = await fs.readFile(filePath, 'utf-8');
475
+ let config: unknown;
476
+
477
+ const ext = path.extname(file).toLowerCase();
478
+ if (ext === '.yaml' || ext === '.yml') {
479
+ config = YAML.parse(content);
480
+ } else if (ext === '.json') {
481
+ config = JSON.parse(content);
482
+ } else {
483
+ logger.error('Unsupported file format. Use .yaml, .yml, or .json');
484
+ process.exitCode = 1;
485
+ return;
486
+ }
487
+
488
+ // Validate schema
489
+ const validationErrors = validateIPRESchema(config as IPREConfig);
490
+
491
+ if (validationErrors.length === 0) {
492
+ console.log(chalk.green('\nIPRE configuration is valid'));
493
+ displayConfigSummary(config as IPREConfig);
494
+ } else {
495
+ console.log(chalk.red('\nIPRE configuration validation failed:\n'));
496
+ for (const error of validationErrors) {
497
+ console.log(chalk.red(` - ${error}`));
498
+ }
499
+ process.exitCode = 1;
500
+ }
501
+ } catch (error) {
502
+ const message = error instanceof Error ? error.message : String(error);
503
+ throw errorHandler.createError(
504
+ 'WUNDR_GOV_VALIDATE_FAILED',
505
+ `Failed to validate IPRE config: ${message}`,
506
+ { file },
507
+ true,
508
+ );
509
+ }
510
+ }
511
+
512
+ // ============================================================================
513
+ // Helper Functions
514
+ // ============================================================================
515
+
516
+ function displayComplianceResult(
517
+ result: ComplianceResult,
518
+ verbose: boolean,
519
+ ): void {
520
+ const statusIcon = result.compliant
521
+ ? chalk.green('[PASS]')
522
+ : chalk.red('[FAIL]');
523
+ console.log(`${statusIcon} Compliance Score: ${colorScore(result.score)}`);
524
+ console.log(` Passed Policies: ${result.passedPolicies.length}`);
525
+ console.log(` Skipped Policies: ${result.skippedPolicies.length}`);
526
+ console.log(` Violations: ${result.violations.length}`);
527
+
528
+ if (verbose && result.violations.length > 0) {
529
+ console.log(chalk.yellow('\n Violations:'));
530
+ for (const violation of result.violations) {
531
+ console.log(
532
+ ` - [${violation.severity.toUpperCase()}] ${violation.policyName}`,
533
+ );
534
+ console.log(` ${violation.description}`);
535
+ if (violation.suggestedFix) {
536
+ console.log(chalk.gray(` Fix: ${violation.suggestedFix}`));
537
+ }
538
+ }
539
+ }
540
+ }
541
+
542
+ function displayAlignmentResult(
543
+ result: EvaluationResult,
544
+ verbose: boolean,
545
+ ): void {
546
+ const statusIcon = result.passed
547
+ ? chalk.green('[PASS]')
548
+ : chalk.red('[FAIL]');
549
+ console.log(`${statusIcon} Alignment Score: ${colorScore(result.score)}`);
550
+ console.log(` Issues: ${result.issues.length}`);
551
+ console.log(` Recommendations: ${result.recommendations.length}`);
552
+
553
+ if (verbose && result.issues.length > 0) {
554
+ console.log(chalk.yellow('\n Issues:'));
555
+ for (const issue of result.issues) {
556
+ console.log(` - ${issue}`);
557
+ }
558
+ }
559
+
560
+ if (verbose && result.recommendations.length > 0) {
561
+ console.log(chalk.blue('\n Recommendations:'));
562
+ for (const rec of result.recommendations) {
563
+ console.log(` - ${rec}`);
564
+ }
565
+ }
566
+ }
567
+
568
+ function displayDriftResult(result: EvaluationResult, verbose: boolean): void {
569
+ // Note: For drift, higher score means less drift (inverted in evaluation)
570
+ const driftScore = 1 - result.score;
571
+ const statusIcon = result.passed
572
+ ? chalk.green('[PASS]')
573
+ : chalk.red('[FAIL]');
574
+ console.log(
575
+ `${statusIcon} Drift Score: ${colorScore(result.score)} (${(driftScore * 100).toFixed(1)}% drift)`,
576
+ );
577
+ console.log(` Drift Alerts: ${result.issues.length}`);
578
+
579
+ if (verbose && result.issues.length > 0) {
580
+ console.log(chalk.yellow('\n Drift Alerts:'));
581
+ for (const issue of result.issues) {
582
+ console.log(` - ${issue}`);
583
+ }
584
+ }
585
+ }
586
+
587
+ function displaySummary(result: {
588
+ passed: boolean;
589
+ overallScore: number;
590
+ results: readonly EvaluationResult[];
591
+ criticalIssues: readonly string[];
592
+ }): void {
593
+ const statusIcon = result.passed
594
+ ? chalk.green('[PASSED]')
595
+ : chalk.red('[FAILED]');
596
+ console.log(
597
+ `\n${statusIcon} Overall Score: ${colorScore(result.overallScore)}`,
598
+ );
599
+
600
+ if (result.criticalIssues.length > 0) {
601
+ console.log(
602
+ chalk.red(`\nCritical Issues (${result.criticalIssues.length}):`),
603
+ );
604
+ for (const issue of result.criticalIssues.slice(0, 5)) {
605
+ console.log(chalk.red(` - ${issue}`));
606
+ }
607
+ if (result.criticalIssues.length > 5) {
608
+ console.log(
609
+ chalk.gray(` ... and ${result.criticalIssues.length - 5} more`),
610
+ );
611
+ }
612
+ }
613
+ }
614
+
615
+ function colorScore(score: number): string {
616
+ const percentage = (score * 100).toFixed(1);
617
+ if (score >= 0.9) {
618
+ return chalk.green(`${percentage}%`);
619
+ }
620
+ if (score >= 0.7) {
621
+ return chalk.yellow(`${percentage}%`);
622
+ }
623
+ return chalk.red(`${percentage}%`);
624
+ }
625
+
626
+ function getSeverityColor(severity: string): (text: string) => string {
627
+ switch (severity) {
628
+ case 'critical':
629
+ return chalk.red;
630
+ case 'high':
631
+ return chalk.yellow;
632
+ case 'medium':
633
+ return chalk.blue;
634
+ default:
635
+ return chalk.gray;
636
+ }
637
+ }
638
+
639
+ function displayProgressBar(score: number): void {
640
+ const width = 30;
641
+ const filled = Math.round(score * width);
642
+ const empty = width - filled;
643
+ const bar =
644
+ chalk.green('[' + '='.repeat(filled)) + chalk.gray('-'.repeat(empty) + ']');
645
+ console.log(` ${bar}`);
646
+ }
647
+
648
+ function calculateAlignmentDebt(
649
+ compliance: ComplianceResult,
650
+ alignment: EvaluationResult,
651
+ drift: EvaluationResult,
652
+ ): number {
653
+ // Calculate debt as weighted sum of issues
654
+ const complianceDebt = (1 - compliance.score) * 0.4;
655
+ const alignmentDebt = (1 - alignment.score) * 0.35;
656
+ const driftDebt = (1 - drift.score) * 0.25;
657
+ return complianceDebt + alignmentDebt + driftDebt;
658
+ }
659
+
660
+ function countCriticalIssues(compliance: ComplianceResult): number {
661
+ return compliance.violations.filter(v => v.severity === 'critical').length;
662
+ }
663
+
664
+ function countHighPriorityItems(alignment: EvaluationResult): number {
665
+ // Count issues that contain high-priority indicators
666
+ return alignment.issues.filter(
667
+ issue =>
668
+ issue.toLowerCase().includes('critical') ||
669
+ issue.toLowerCase().includes('high'),
670
+ ).length;
671
+ }
672
+
673
+ function extractAlignmentGaps(result: EvaluationResult): AlignmentGapDetail[] {
674
+ // Parse alignment gaps from issues
675
+ const gaps: AlignmentGapDetail[] = [];
676
+ for (const issue of result.issues) {
677
+ const match = issue.match(/gap in (\w+): expected ([\d.]+), got ([\d.]+)/i);
678
+ if (match) {
679
+ const expected = parseFloat(match[2] ?? '0');
680
+ const actual = parseFloat(match[3] ?? '0');
681
+ gaps.push({
682
+ dimension: match[1] ?? 'unknown',
683
+ expected,
684
+ actual,
685
+ gap: expected - actual,
686
+ priority:
687
+ expected - actual > 0.2
688
+ ? 'high'
689
+ : expected - actual > 0.1
690
+ ? 'medium'
691
+ : 'low',
692
+ });
693
+ }
694
+ }
695
+ return gaps;
696
+ }
697
+
698
+ function extractDriftAlerts(result: EvaluationResult): DriftAlertDetail[] {
699
+ // Parse drift alerts from issues
700
+ const alerts: DriftAlertDetail[] = [];
701
+ for (const issue of result.issues) {
702
+ const match = issue.match(/Drift.*in (\w+): ([\d.]+)% (\w+)/i);
703
+ if (match) {
704
+ const changePercent = parseFloat(match[2] ?? '0');
705
+ alerts.push({
706
+ pattern: match[1] ?? 'unknown',
707
+ baselineValue: 0.9, // Default baseline
708
+ currentValue: 0.9 * (1 + changePercent / 100),
709
+ changePercent,
710
+ direction: match[3] ?? 'stable',
711
+ severity:
712
+ changePercent >= 30
713
+ ? 'critical'
714
+ : changePercent >= 20
715
+ ? 'high'
716
+ : 'medium',
717
+ });
718
+ }
719
+ }
720
+ return alerts;
721
+ }
722
+
723
+ function generateRecommendations(
724
+ compliance: ComplianceResult,
725
+ alignment: EvaluationResult,
726
+ drift: EvaluationResult,
727
+ ): string[] {
728
+ const recommendations: string[] = [];
729
+
730
+ // Add compliance recommendations
731
+ if (compliance.violations.length > 0) {
732
+ recommendations.push(
733
+ 'Address policy violations immediately, especially critical ones',
734
+ );
735
+ const criticalCount = compliance.violations.filter(
736
+ v => v.severity === 'critical',
737
+ ).length;
738
+ if (criticalCount > 0) {
739
+ recommendations.push(
740
+ `Fix ${criticalCount} critical policy violation(s) before deployment`,
741
+ );
742
+ }
743
+ }
744
+
745
+ // Add alignment recommendations from evaluator
746
+ recommendations.push(...alignment.recommendations);
747
+
748
+ // Add drift recommendations
749
+ if (drift.issues.length > 0) {
750
+ recommendations.push('Investigate drift causes and consider recalibration');
751
+ }
752
+
753
+ // General recommendations
754
+ if (compliance.score < 0.8) {
755
+ recommendations.push('Review and update security policies');
756
+ }
757
+
758
+ if (alignment.score < 0.85) {
759
+ recommendations.push('Schedule alignment review session');
760
+ }
761
+
762
+ return [...new Set(recommendations)]; // Remove duplicates
763
+ }
764
+
765
+ function formatReportAsMarkdown(report: AlignmentDebtReport): string {
766
+ let md = '# Alignment Debt Report\n\n';
767
+ md += `Generated: ${report.generatedAt}\n`;
768
+ if (report.sessionId) {
769
+ md += `Session: ${report.sessionId}\n`;
770
+ }
771
+ md += '\n---\n\n';
772
+
773
+ // Summary
774
+ md += '## Summary\n\n';
775
+ md += '| Metric | Value |\n';
776
+ md += '|--------|-------|\n';
777
+ md += `| Total Alignment Debt | ${report.summary.totalDebt.toFixed(2)} |\n`;
778
+ md += `| Critical Issues | ${report.summary.criticalIssues} |\n`;
779
+ md += `| High Priority Items | ${report.summary.highPriorityItems} |\n`;
780
+ md += `| Alignment Score | ${(report.summary.alignmentScore * 100).toFixed(1)}% |\n`;
781
+ md += `| Compliance Score | ${(report.summary.complianceScore * 100).toFixed(1)}% |\n`;
782
+ md += `| Drift Score | ${(report.summary.driftScore * 100).toFixed(1)}% |\n`;
783
+ md += '\n';
784
+
785
+ // Policy Violations
786
+ if (report.policyViolations.length > 0) {
787
+ md += '## Policy Violations\n\n';
788
+ for (const v of report.policyViolations) {
789
+ md += `### ${v.policyName} (${v.severity.toUpperCase()})\n\n`;
790
+ md += `- **Policy ID:** ${v.policyId}\n`;
791
+ md += `- **Description:** ${v.description}\n`;
792
+ if (v.location) {
793
+ md += `- **Location:** ${v.location}\n`;
794
+ }
795
+ if (v.suggestedFix) {
796
+ md += `- **Suggested Fix:** ${v.suggestedFix}\n`;
797
+ }
798
+ md += '\n';
799
+ }
800
+ }
801
+
802
+ // Alignment Gaps
803
+ if (report.alignmentGaps.length > 0) {
804
+ md += '## Alignment Gaps\n\n';
805
+ md += '| Dimension | Expected | Actual | Gap | Priority |\n';
806
+ md += '|-----------|----------|--------|-----|----------|\n';
807
+ for (const g of report.alignmentGaps) {
808
+ md += `| ${g.dimension} | ${(g.expected * 100).toFixed(1)}% | ${(g.actual * 100).toFixed(1)}% | ${(g.gap * 100).toFixed(1)}% | ${g.priority} |\n`;
809
+ }
810
+ md += '\n';
811
+ }
812
+
813
+ // Drift Alerts
814
+ if (report.driftAlerts.length > 0) {
815
+ md += '## Drift Alerts\n\n';
816
+ md += '| Pattern | Change | Direction | Severity |\n';
817
+ md += '|---------|--------|-----------|----------|\n';
818
+ for (const d of report.driftAlerts) {
819
+ md += `| ${d.pattern} | ${d.changePercent.toFixed(1)}% | ${d.direction} | ${d.severity} |\n`;
820
+ }
821
+ md += '\n';
822
+ }
823
+
824
+ // Recommendations
825
+ if (report.recommendations.length > 0) {
826
+ md += '## Recommendations\n\n';
827
+ for (const rec of report.recommendations) {
828
+ md += `- ${rec}\n`;
829
+ }
830
+ md += '\n';
831
+ }
832
+
833
+ return md;
834
+ }
835
+
836
+ function validateIPRESchema(config: IPREConfig): string[] {
837
+ const errors: string[] = [];
838
+
839
+ // Required fields
840
+ if (!config.version) {
841
+ errors.push('Missing required field: version');
842
+ }
843
+
844
+ if (!config.intent) {
845
+ errors.push('Missing required field: intent');
846
+ } else {
847
+ if (!config.intent.mission) {
848
+ errors.push('Missing required field: intent.mission');
849
+ }
850
+ if (!config.intent.values || !Array.isArray(config.intent.values)) {
851
+ errors.push('Missing or invalid field: intent.values (must be array)');
852
+ }
853
+ }
854
+
855
+ if (!config.policies) {
856
+ errors.push('Missing required field: policies');
857
+ } else {
858
+ if (!Array.isArray(config.policies.security)) {
859
+ errors.push('policies.security must be an array');
860
+ }
861
+ if (!Array.isArray(config.policies.compliance)) {
862
+ errors.push('policies.compliance must be an array');
863
+ }
864
+ if (!Array.isArray(config.policies.operational)) {
865
+ errors.push('policies.operational must be an array');
866
+ }
867
+ }
868
+
869
+ if (!config.rewards) {
870
+ errors.push('Missing required field: rewards');
871
+ } else {
872
+ if (!config.rewards.weights) {
873
+ errors.push('Missing required field: rewards.weights');
874
+ }
875
+ if (typeof config.rewards.threshold !== 'number') {
876
+ errors.push('rewards.threshold must be a number');
877
+ }
878
+ }
879
+
880
+ if (!config.evaluators) {
881
+ errors.push('Missing required field: evaluators');
882
+ } else if (!Array.isArray(config.evaluators)) {
883
+ errors.push('evaluators must be an array');
884
+ }
885
+
886
+ return errors;
887
+ }
888
+
889
+ function displayConfigSummary(config: IPREConfig): void {
890
+ console.log(chalk.blue('\n--- Configuration Summary ---'));
891
+ console.log(`Version: ${config.version}`);
892
+ console.log(`Mission: ${config.intent?.mission || 'Not defined'}`);
893
+ console.log(`Values: ${config.intent?.values?.length || 0} defined`);
894
+ console.log(`Security Policies: ${config.policies?.security?.length || 0}`);
895
+ console.log(
896
+ `Compliance Policies: ${config.policies?.compliance?.length || 0}`,
897
+ );
898
+ console.log(
899
+ `Operational Policies: ${config.policies?.operational?.length || 0}`,
900
+ );
901
+ console.log(`Evaluators: ${config.evaluators?.length || 0}`);
902
+ if (config.rewards?.threshold) {
903
+ console.log(`Reward Threshold: ${config.rewards.threshold}`);
904
+ }
905
+ }
906
+
907
+ // ============================================================================
908
+ // State Management
909
+ // ============================================================================
910
+
911
+ const GOVERNANCE_STATE_PATH = '.wundr/governance-state.json';
912
+
913
+ interface GovernanceState {
914
+ timestamp: string;
915
+ sessionId: string;
916
+ suiteResult?: {
917
+ passed: boolean;
918
+ overallScore: number;
919
+ criticalIssues: string[];
920
+ };
921
+ complianceResult?: unknown;
922
+ alignmentResult?: unknown;
923
+ driftResult?: unknown;
924
+ }
925
+
926
+ async function saveGovernanceState(
927
+ sessionId: string,
928
+ data: {
929
+ complianceResult: ComplianceResult;
930
+ alignmentResult: EvaluationResult;
931
+ driftResult: EvaluationResult;
932
+ suiteResult: {
933
+ passed: boolean;
934
+ overallScore: number;
935
+ results: readonly EvaluationResult[];
936
+ criticalIssues: readonly string[];
937
+ };
938
+ },
939
+ ): Promise<void> {
940
+ const statePath = path.join(process.cwd(), GOVERNANCE_STATE_PATH);
941
+ await fs.ensureDir(path.dirname(statePath));
942
+
943
+ const state: GovernanceState = {
944
+ timestamp: new Date().toISOString(),
945
+ sessionId,
946
+ suiteResult: {
947
+ passed: data.suiteResult.passed,
948
+ overallScore: data.suiteResult.overallScore,
949
+ criticalIssues: [...data.suiteResult.criticalIssues],
950
+ },
951
+ complianceResult: data.complianceResult,
952
+ alignmentResult: data.alignmentResult,
953
+ driftResult: data.driftResult,
954
+ };
955
+
956
+ await fs.writeJson(statePath, state, { spaces: 2 });
957
+ }
958
+
959
+ async function loadGovernanceState(): Promise<GovernanceState | null> {
960
+ const statePath = path.join(process.cwd(), GOVERNANCE_STATE_PATH);
961
+
962
+ if (await fs.pathExists(statePath)) {
963
+ return await fs.readJson(statePath);
964
+ }
965
+
966
+ return null;
967
+ }
968
+
969
+ async function loadRecentInterventions(): Promise<Intervention[]> {
970
+ // Load from state file or return empty array
971
+ // In a real implementation, this would load from a persistent store
972
+ return [];
973
+ }
974
+
975
+ function extractDriftIndicatorsFromState(
976
+ state: GovernanceState | null,
977
+ ): DriftIndicator[] {
978
+ if (!state?.driftResult) {
979
+ return [];
980
+ }
981
+
982
+ const driftResult = state.driftResult as EvaluationResult;
983
+ const indicators: DriftIndicator[] = [];
984
+
985
+ for (const issue of driftResult.issues || []) {
986
+ const match = issue.match(/Drift.*in (\w+): ([\d.]+)%/i);
987
+ if (match) {
988
+ indicators.push({
989
+ pattern: match[1] ?? 'unknown',
990
+ baseline: 0.9,
991
+ current: 0.9 * (1 + parseFloat(match[2] ?? '0') / 100),
992
+ change: parseFloat(match[2] ?? '0') / 100,
993
+ severity: 'medium',
994
+ });
995
+ }
996
+ }
997
+
998
+ return indicators;
999
+ }
1000
+
1001
+ // ============================================================================
1002
+ // Exports
1003
+ // ============================================================================
1004
+
1005
+ export { createGovernanceCommand as governanceCommand };