cognitive-modules-cli 1.0.0 → 1.1.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.
package/dist/cli.js CHANGED
@@ -16,7 +16,7 @@
16
16
  import { parseArgs } from 'node:util';
17
17
  import { getProvider, listProviders } from './providers/index.js';
18
18
  import { run, list, pipe, init, add, update, remove, versions } from './commands/index.js';
19
- const VERSION = '1.0.0';
19
+ const VERSION = '1.0.1';
20
20
  async function main() {
21
21
  const args = process.argv.slice(2);
22
22
  const command = args[0];
@@ -169,6 +169,7 @@ function parseLegacyResponse(output, raw) {
169
169
  };
170
170
  }
171
171
  }
172
+ // Return as v2.1 format (data includes confidence)
172
173
  return {
173
174
  ok: true,
174
175
  data: {
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Cognitive Runtime - Core Types
3
- * Version 2.1 - With envelope format, tools policy, failure contract
3
+ * Version 2.2 - With Control/Data plane separation, tier, overflow, extensible enums
4
4
  */
5
5
  export interface Provider {
6
6
  name: string;
@@ -25,6 +25,14 @@ export interface InvokeResult {
25
25
  totalTokens: number;
26
26
  };
27
27
  }
28
+ /** Module classification for schema strictness */
29
+ export type ModuleTier = 'exec' | 'decision' | 'exploration';
30
+ /** Schema validation strictness level */
31
+ export type SchemaStrictness = 'high' | 'medium' | 'low';
32
+ /** Risk level (used in both meta and changes) */
33
+ export type RiskLevel = 'none' | 'low' | 'medium' | 'high';
34
+ /** Enum extension strategy */
35
+ export type EnumStrategy = 'strict' | 'extensible';
28
36
  export interface CognitiveModule {
29
37
  name: string;
30
38
  version: string;
@@ -36,13 +44,21 @@ export interface CognitiveModule {
36
44
  output?: OutputContract;
37
45
  failure?: FailureContract;
38
46
  runtimeRequirements?: RuntimeRequirements;
47
+ tier?: ModuleTier;
48
+ schemaStrictness?: SchemaStrictness;
49
+ overflow?: OverflowConfig;
50
+ enums?: EnumConfig;
51
+ compat?: CompatConfig;
39
52
  context?: 'fork' | 'main';
40
53
  prompt: string;
41
54
  inputSchema?: object;
42
55
  outputSchema?: object;
56
+ dataSchema?: object;
57
+ metaSchema?: object;
43
58
  errorSchema?: object;
44
59
  location: string;
45
- format: 'v1' | 'v2';
60
+ format: 'v0' | 'v1' | 'v2';
61
+ formatVersion?: string;
46
62
  }
47
63
  export interface ModuleConstraints {
48
64
  no_network?: boolean;
@@ -81,27 +97,112 @@ export interface RuntimeRequirements {
81
97
  max_input_tokens?: number;
82
98
  preferred_capabilities?: string[];
83
99
  }
84
- export interface EnvelopeSuccess<T = unknown> {
100
+ /** Overflow configuration for extensions.insights */
101
+ export interface OverflowConfig {
102
+ enabled: boolean;
103
+ recoverable?: boolean;
104
+ max_items?: number;
105
+ require_suggested_mapping?: boolean;
106
+ }
107
+ /** Enum extension configuration */
108
+ export interface EnumConfig {
109
+ strategy: EnumStrategy;
110
+ unknown_tag?: string;
111
+ }
112
+ /** Compatibility configuration for migration */
113
+ export interface CompatConfig {
114
+ accepts_v21_payload?: boolean;
115
+ runtime_auto_wrap?: boolean;
116
+ schema_output_alias?: 'data' | 'output';
117
+ }
118
+ /**
119
+ * Control plane metadata - unified across all modules.
120
+ * Used for routing, logging, UI cards, and middleware decisions.
121
+ */
122
+ export interface EnvelopeMeta {
123
+ /** Confidence score [0, 1] - unified across all modules */
124
+ confidence: number;
125
+ /** Aggregated risk level: max(changes[*].risk) */
126
+ risk: RiskLevel;
127
+ /** Short explanation for middleware/UI (max 280 chars) */
128
+ explain: string;
129
+ /** Distributed tracing ID */
130
+ trace_id?: string;
131
+ /** Provider and model identifier */
132
+ model?: string;
133
+ /** Execution latency in milliseconds */
134
+ latency_ms?: number;
135
+ }
136
+ /** Success response in v2.2 envelope format */
137
+ export interface EnvelopeSuccessV22<T = unknown> {
85
138
  ok: true;
139
+ meta: EnvelopeMeta;
86
140
  data: T;
87
141
  }
88
- export interface EnvelopeError {
142
+ /** Error response in v2.2 envelope format */
143
+ export interface EnvelopeErrorV22 {
89
144
  ok: false;
145
+ meta: EnvelopeMeta;
90
146
  error: {
91
147
  code: string;
92
148
  message: string;
93
149
  };
94
150
  partial_data?: unknown;
95
151
  }
96
- export type EnvelopeResponse<T = unknown> = EnvelopeSuccess<T> | EnvelopeError;
152
+ /** v2.2 envelope response (union type) */
153
+ export type EnvelopeResponseV22<T = unknown> = EnvelopeSuccessV22<T> | EnvelopeErrorV22;
154
+ export interface EnvelopeSuccessV21<T = unknown> {
155
+ ok: true;
156
+ data: T;
157
+ }
158
+ export interface EnvelopeErrorV21 {
159
+ ok: false;
160
+ error: {
161
+ code: string;
162
+ message: string;
163
+ };
164
+ partial_data?: unknown;
165
+ }
166
+ export type EnvelopeResponseV21<T = unknown> = EnvelopeSuccessV21<T> | EnvelopeErrorV21;
167
+ /** Generic envelope response (supports both v2.1 and v2.2) */
168
+ export type EnvelopeResponse<T = unknown> = EnvelopeResponseV22<T> | EnvelopeResponseV21<T>;
169
+ /** An insight that doesn't fit the schema but is valuable */
170
+ export interface Insight {
171
+ /** The observation or insight */
172
+ text: string;
173
+ /** Suggested field/enum to add to schema for future versions */
174
+ suggested_mapping: string;
175
+ /** Supporting evidence for this insight */
176
+ evidence?: string;
177
+ }
178
+ /** Extensions container for overflow data */
179
+ export interface Extensions {
180
+ insights?: Insight[];
181
+ }
182
+ /**
183
+ * Extensible enum type - allows both predefined values and custom extensions.
184
+ *
185
+ * Usage:
186
+ * type ChangeType = ExtensibleEnum<'remove_redundancy' | 'simplify_logic' | 'other'>;
187
+ *
188
+ * Valid values:
189
+ * - "remove_redundancy" (predefined)
190
+ * - { custom: "inline_callback", reason: "Converted callback to arrow function" }
191
+ */
192
+ export type ExtensibleEnum<T extends string> = T | {
193
+ custom: string;
194
+ reason: string;
195
+ };
196
+ /** Base interface for module result data */
97
197
  export interface ModuleResultData {
98
198
  [key: string]: unknown;
99
- confidence: number;
100
199
  rationale: string;
101
- behavior_equivalence?: boolean;
200
+ extensions?: Extensions;
102
201
  }
103
- export interface ModuleResult {
202
+ /** v2.2 module result with meta and data separation */
203
+ export interface ModuleResultV22 {
104
204
  ok: boolean;
205
+ meta: EnvelopeMeta;
105
206
  data?: ModuleResultData;
106
207
  error?: {
107
208
  code: string;
@@ -110,6 +211,21 @@ export interface ModuleResult {
110
211
  partial_data?: unknown;
111
212
  raw?: string;
112
213
  }
214
+ /** Legacy module result (v2.1) */
215
+ export interface ModuleResultV21 {
216
+ ok: boolean;
217
+ data?: ModuleResultData & {
218
+ confidence: number;
219
+ };
220
+ error?: {
221
+ code: string;
222
+ message: string;
223
+ };
224
+ partial_data?: unknown;
225
+ raw?: string;
226
+ }
227
+ /** Generic module result */
228
+ export type ModuleResult = ModuleResultV22 | ModuleResultV21;
113
229
  export interface LegacyModuleResult {
114
230
  output: unknown;
115
231
  confidence: number;
@@ -134,3 +250,15 @@ export interface ModuleInput {
134
250
  options?: Record<string, unknown>;
135
251
  [key: string]: unknown;
136
252
  }
253
+ /** Check if response is v2.2 format */
254
+ export declare function isV22Envelope<T>(response: EnvelopeResponse<T>): response is EnvelopeResponseV22<T>;
255
+ /** Check if response is successful */
256
+ export declare function isEnvelopeSuccess<T>(response: EnvelopeResponse<T>): response is EnvelopeSuccessV22<T> | EnvelopeSuccessV21<T>;
257
+ /** Extract meta from any envelope response */
258
+ export declare function extractMeta<T>(response: EnvelopeResponse<T>): EnvelopeMeta;
259
+ /** Aggregate risk from list of changes */
260
+ export declare function aggregateRisk(changes: Array<{
261
+ risk?: RiskLevel;
262
+ }>): RiskLevel;
263
+ /** Check if result should be escalated to human review */
264
+ export declare function shouldEscalate<T>(response: EnvelopeResponse<T>, confidenceThreshold?: number): boolean;
package/dist/types.js CHANGED
@@ -1,5 +1,68 @@
1
1
  /**
2
2
  * Cognitive Runtime - Core Types
3
- * Version 2.1 - With envelope format, tools policy, failure contract
3
+ * Version 2.2 - With Control/Data plane separation, tier, overflow, extensible enums
4
4
  */
5
- export {};
5
+ // =============================================================================
6
+ // Utility Types
7
+ // =============================================================================
8
+ /** Check if response is v2.2 format */
9
+ export function isV22Envelope(response) {
10
+ return 'meta' in response;
11
+ }
12
+ /** Check if response is successful */
13
+ export function isEnvelopeSuccess(response) {
14
+ return response.ok === true;
15
+ }
16
+ /** Extract meta from any envelope response */
17
+ export function extractMeta(response) {
18
+ if (isV22Envelope(response)) {
19
+ return response.meta;
20
+ }
21
+ // Synthesize meta from v2.1 response
22
+ if (response.ok) {
23
+ const data = response.data;
24
+ return {
25
+ confidence: data?.confidence ?? 0.5,
26
+ risk: 'medium',
27
+ explain: (data?.rationale ?? '').slice(0, 280) || 'No explanation',
28
+ };
29
+ }
30
+ else {
31
+ return {
32
+ confidence: 0,
33
+ risk: 'high',
34
+ explain: response.error?.message?.slice(0, 280) ?? 'Error occurred',
35
+ };
36
+ }
37
+ }
38
+ /** Aggregate risk from list of changes */
39
+ export function aggregateRisk(changes) {
40
+ const riskLevels = { none: 0, low: 1, medium: 2, high: 3 };
41
+ const riskNames = ['none', 'low', 'medium', 'high'];
42
+ if (!changes || changes.length === 0) {
43
+ return 'medium';
44
+ }
45
+ let maxLevel = 0;
46
+ for (const change of changes) {
47
+ const level = riskLevels[change.risk ?? 'medium'];
48
+ maxLevel = Math.max(maxLevel, level);
49
+ }
50
+ return riskNames[maxLevel];
51
+ }
52
+ /** Check if result should be escalated to human review */
53
+ export function shouldEscalate(response, confidenceThreshold = 0.7) {
54
+ const meta = extractMeta(response);
55
+ // Escalate if low confidence
56
+ if (meta.confidence < confidenceThreshold) {
57
+ return true;
58
+ }
59
+ // Escalate if high risk
60
+ if (meta.risk === 'high') {
61
+ return true;
62
+ }
63
+ // Escalate if error
64
+ if (!response.ok) {
65
+ return true;
66
+ }
67
+ return false;
68
+ }
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "cognitive-modules-cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Cognitive Modules - Structured AI Task Execution with version management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
+ "cognitive-modules-cli": "dist/cli.js",
8
9
  "cog": "dist/cli.js"
9
10
  },
10
11
  "scripts": {
package/src/cli.ts CHANGED
@@ -19,7 +19,7 @@ import { getProvider, listProviders } from './providers/index.js';
19
19
  import { run, list, pipe, init, add, update, remove, versions } from './commands/index.js';
20
20
  import type { CommandContext } from './types.js';
21
21
 
22
- const VERSION = '1.0.0';
22
+ const VERSION = '1.0.1';
23
23
 
24
24
  async function main() {
25
25
  const args = process.argv.slice(2);
@@ -7,6 +7,7 @@ import type {
7
7
  Provider,
8
8
  CognitiveModule,
9
9
  ModuleResult,
10
+ ModuleResultV21,
10
11
  Message,
11
12
  ModuleInput,
12
13
  EnvelopeResponse,
@@ -211,6 +212,7 @@ function parseLegacyResponse(output: unknown, raw: string): ModuleResult {
211
212
  }
212
213
  }
213
214
 
215
+ // Return as v2.1 format (data includes confidence)
214
216
  return {
215
217
  ok: true,
216
218
  data: {
@@ -218,9 +220,9 @@ function parseLegacyResponse(output: unknown, raw: string): ModuleResult {
218
220
  confidence,
219
221
  rationale,
220
222
  behavior_equivalence: behaviorEquivalence,
221
- } as ModuleResultData,
223
+ },
222
224
  raw,
223
- };
225
+ } as ModuleResultV21;
224
226
  }
225
227
 
226
228
  /**
package/src/types.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  /**
2
2
  * Cognitive Runtime - Core Types
3
- * Version 2.1 - With envelope format, tools policy, failure contract
3
+ * Version 2.2 - With Control/Data plane separation, tier, overflow, extensible enums
4
4
  */
5
5
 
6
- // Provider interface - all LLM providers implement this
6
+ // =============================================================================
7
+ // Provider Interface
8
+ // =============================================================================
9
+
7
10
  export interface Provider {
8
11
  name: string;
9
12
  invoke(params: InvokeParams): Promise<InvokeResult>;
@@ -31,7 +34,26 @@ export interface InvokeResult {
31
34
  };
32
35
  }
33
36
 
34
- // Module types (v2.1)
37
+ // =============================================================================
38
+ // v2.2 Core Types
39
+ // =============================================================================
40
+
41
+ /** Module classification for schema strictness */
42
+ export type ModuleTier = 'exec' | 'decision' | 'exploration';
43
+
44
+ /** Schema validation strictness level */
45
+ export type SchemaStrictness = 'high' | 'medium' | 'low';
46
+
47
+ /** Risk level (used in both meta and changes) */
48
+ export type RiskLevel = 'none' | 'low' | 'medium' | 'high';
49
+
50
+ /** Enum extension strategy */
51
+ export type EnumStrategy = 'strict' | 'extensible';
52
+
53
+ // =============================================================================
54
+ // Module Configuration (v2.2)
55
+ // =============================================================================
56
+
35
57
  export interface CognitiveModule {
36
58
  // Core identity
37
59
  name: string;
@@ -42,7 +64,7 @@ export interface CognitiveModule {
42
64
  excludes: string[];
43
65
  constraints?: ModuleConstraints;
44
66
 
45
- // Unified policies (v2.1)
67
+ // Unified policies (v2.1+)
46
68
  policies?: ModulePolicies;
47
69
 
48
70
  // Tools policy
@@ -57,6 +79,21 @@ export interface CognitiveModule {
57
79
  // Runtime requirements
58
80
  runtimeRequirements?: RuntimeRequirements;
59
81
 
82
+ // v2.2: Module tier
83
+ tier?: ModuleTier;
84
+
85
+ // v2.2: Schema strictness
86
+ schemaStrictness?: SchemaStrictness;
87
+
88
+ // v2.2: Overflow configuration
89
+ overflow?: OverflowConfig;
90
+
91
+ // v2.2: Enum configuration
92
+ enums?: EnumConfig;
93
+
94
+ // v2.2: Compatibility configuration
95
+ compat?: CompatConfig;
96
+
60
97
  // Execution context
61
98
  context?: 'fork' | 'main';
62
99
 
@@ -65,12 +102,15 @@ export interface CognitiveModule {
65
102
 
66
103
  // Schemas
67
104
  inputSchema?: object;
68
- outputSchema?: object;
105
+ outputSchema?: object; // v2.1 compat
106
+ dataSchema?: object; // v2.2: same as outputSchema
107
+ metaSchema?: object; // v2.2: control plane schema
69
108
  errorSchema?: object;
70
109
 
71
110
  // Metadata
72
111
  location: string;
73
- format: 'v1' | 'v2'; // v1 = MODULE.md, v2 = module.yaml + prompt.md
112
+ format: 'v0' | 'v1' | 'v2';
113
+ formatVersion?: string; // v2.0, v2.1, v2.2
74
114
  }
75
115
 
76
116
  export interface ModuleConstraints {
@@ -96,7 +136,7 @@ export interface ToolsPolicy {
96
136
 
97
137
  export interface OutputContract {
98
138
  format?: 'json_strict' | 'json_lenient' | 'text';
99
- envelope?: boolean; // v2.1: Use {ok, data/error} wrapper
139
+ envelope?: boolean;
100
140
  require?: string[];
101
141
  require_confidence?: boolean;
102
142
  require_rationale?: boolean;
@@ -116,13 +156,90 @@ export interface RuntimeRequirements {
116
156
  preferred_capabilities?: string[];
117
157
  }
118
158
 
119
- // Envelope response format (v2.1)
120
- export interface EnvelopeSuccess<T = unknown> {
159
+ // =============================================================================
160
+ // v2.2 New Configuration Types
161
+ // =============================================================================
162
+
163
+ /** Overflow configuration for extensions.insights */
164
+ export interface OverflowConfig {
165
+ enabled: boolean;
166
+ recoverable?: boolean;
167
+ max_items?: number;
168
+ require_suggested_mapping?: boolean;
169
+ }
170
+
171
+ /** Enum extension configuration */
172
+ export interface EnumConfig {
173
+ strategy: EnumStrategy;
174
+ unknown_tag?: string; // How to represent unknown enums (default: "custom")
175
+ }
176
+
177
+ /** Compatibility configuration for migration */
178
+ export interface CompatConfig {
179
+ accepts_v21_payload?: boolean;
180
+ runtime_auto_wrap?: boolean;
181
+ schema_output_alias?: 'data' | 'output';
182
+ }
183
+
184
+ // =============================================================================
185
+ // Envelope Types (v2.2)
186
+ // =============================================================================
187
+
188
+ /**
189
+ * Control plane metadata - unified across all modules.
190
+ * Used for routing, logging, UI cards, and middleware decisions.
191
+ */
192
+ export interface EnvelopeMeta {
193
+ /** Confidence score [0, 1] - unified across all modules */
194
+ confidence: number;
195
+
196
+ /** Aggregated risk level: max(changes[*].risk) */
197
+ risk: RiskLevel;
198
+
199
+ /** Short explanation for middleware/UI (max 280 chars) */
200
+ explain: string;
201
+
202
+ /** Distributed tracing ID */
203
+ trace_id?: string;
204
+
205
+ /** Provider and model identifier */
206
+ model?: string;
207
+
208
+ /** Execution latency in milliseconds */
209
+ latency_ms?: number;
210
+ }
211
+
212
+ /** Success response in v2.2 envelope format */
213
+ export interface EnvelopeSuccessV22<T = unknown> {
214
+ ok: true;
215
+ meta: EnvelopeMeta;
216
+ data: T;
217
+ }
218
+
219
+ /** Error response in v2.2 envelope format */
220
+ export interface EnvelopeErrorV22 {
221
+ ok: false;
222
+ meta: EnvelopeMeta;
223
+ error: {
224
+ code: string;
225
+ message: string;
226
+ };
227
+ partial_data?: unknown;
228
+ }
229
+
230
+ /** v2.2 envelope response (union type) */
231
+ export type EnvelopeResponseV22<T = unknown> = EnvelopeSuccessV22<T> | EnvelopeErrorV22;
232
+
233
+ // =============================================================================
234
+ // Legacy Envelope Types (v2.1 - for backward compatibility)
235
+ // =============================================================================
236
+
237
+ export interface EnvelopeSuccessV21<T = unknown> {
121
238
  ok: true;
122
239
  data: T;
123
240
  }
124
241
 
125
- export interface EnvelopeError {
242
+ export interface EnvelopeErrorV21 {
126
243
  ok: false;
127
244
  error: {
128
245
  code: string;
@@ -131,18 +248,63 @@ export interface EnvelopeError {
131
248
  partial_data?: unknown;
132
249
  }
133
250
 
134
- export type EnvelopeResponse<T = unknown> = EnvelopeSuccess<T> | EnvelopeError;
251
+ export type EnvelopeResponseV21<T = unknown> = EnvelopeSuccessV21<T> | EnvelopeErrorV21;
252
+
253
+ /** Generic envelope response (supports both v2.1 and v2.2) */
254
+ export type EnvelopeResponse<T = unknown> = EnvelopeResponseV22<T> | EnvelopeResponseV21<T>;
255
+
256
+ // =============================================================================
257
+ // Overflow Types (v2.2)
258
+ // =============================================================================
259
+
260
+ /** An insight that doesn't fit the schema but is valuable */
261
+ export interface Insight {
262
+ /** The observation or insight */
263
+ text: string;
264
+
265
+ /** Suggested field/enum to add to schema for future versions */
266
+ suggested_mapping: string;
267
+
268
+ /** Supporting evidence for this insight */
269
+ evidence?: string;
270
+ }
271
+
272
+ /** Extensions container for overflow data */
273
+ export interface Extensions {
274
+ insights?: Insight[];
275
+ }
276
+
277
+ // =============================================================================
278
+ // Extensible Enum Pattern (v2.2)
279
+ // =============================================================================
280
+
281
+ /**
282
+ * Extensible enum type - allows both predefined values and custom extensions.
283
+ *
284
+ * Usage:
285
+ * type ChangeType = ExtensibleEnum<'remove_redundancy' | 'simplify_logic' | 'other'>;
286
+ *
287
+ * Valid values:
288
+ * - "remove_redundancy" (predefined)
289
+ * - { custom: "inline_callback", reason: "Converted callback to arrow function" }
290
+ */
291
+ export type ExtensibleEnum<T extends string> = T | { custom: string; reason: string };
292
+
293
+ // =============================================================================
294
+ // Module Result Types
295
+ // =============================================================================
135
296
 
136
- // Module result types
297
+ /** Base interface for module result data */
137
298
  export interface ModuleResultData {
138
299
  [key: string]: unknown;
139
- confidence: number;
140
300
  rationale: string;
141
- behavior_equivalence?: boolean;
301
+ extensions?: Extensions;
142
302
  }
143
303
 
144
- export interface ModuleResult {
304
+ /** v2.2 module result with meta and data separation */
305
+ export interface ModuleResultV22 {
145
306
  ok: boolean;
307
+ meta: EnvelopeMeta;
146
308
  data?: ModuleResultData;
147
309
  error?: {
148
310
  code: string;
@@ -152,7 +314,25 @@ export interface ModuleResult {
152
314
  raw?: string;
153
315
  }
154
316
 
155
- // Legacy result format (for backward compatibility)
317
+ /** Legacy module result (v2.1) */
318
+ export interface ModuleResultV21 {
319
+ ok: boolean;
320
+ data?: ModuleResultData & { confidence: number };
321
+ error?: {
322
+ code: string;
323
+ message: string;
324
+ };
325
+ partial_data?: unknown;
326
+ raw?: string;
327
+ }
328
+
329
+ /** Generic module result */
330
+ export type ModuleResult = ModuleResultV22 | ModuleResultV21;
331
+
332
+ // =============================================================================
333
+ // Legacy Types (for backward compatibility)
334
+ // =============================================================================
335
+
156
336
  export interface LegacyModuleResult {
157
337
  output: unknown;
158
338
  confidence: number;
@@ -161,7 +341,10 @@ export interface LegacyModuleResult {
161
341
  raw?: string;
162
342
  }
163
343
 
164
- // Command types
344
+ // =============================================================================
345
+ // Command Types
346
+ // =============================================================================
347
+
165
348
  export interface CommandContext {
166
349
  cwd: string;
167
350
  provider: Provider;
@@ -174,7 +357,10 @@ export interface CommandResult {
174
357
  error?: string;
175
358
  }
176
359
 
177
- // Module input (clean, no CLI pollution)
360
+ // =============================================================================
361
+ // Module Input
362
+ // =============================================================================
363
+
178
364
  export interface ModuleInput {
179
365
  code?: string;
180
366
  query?: string;
@@ -182,3 +368,85 @@ export interface ModuleInput {
182
368
  options?: Record<string, unknown>;
183
369
  [key: string]: unknown;
184
370
  }
371
+
372
+ // =============================================================================
373
+ // Utility Types
374
+ // =============================================================================
375
+
376
+ /** Check if response is v2.2 format */
377
+ export function isV22Envelope<T>(response: EnvelopeResponse<T>): response is EnvelopeResponseV22<T> {
378
+ return 'meta' in response;
379
+ }
380
+
381
+ /** Check if response is successful */
382
+ export function isEnvelopeSuccess<T>(
383
+ response: EnvelopeResponse<T>
384
+ ): response is EnvelopeSuccessV22<T> | EnvelopeSuccessV21<T> {
385
+ return response.ok === true;
386
+ }
387
+
388
+ /** Extract meta from any envelope response */
389
+ export function extractMeta<T>(response: EnvelopeResponse<T>): EnvelopeMeta {
390
+ if (isV22Envelope(response)) {
391
+ return response.meta;
392
+ }
393
+
394
+ // Synthesize meta from v2.1 response
395
+ if (response.ok) {
396
+ const data = response.data as Record<string, unknown>;
397
+ return {
398
+ confidence: (data?.confidence as number) ?? 0.5,
399
+ risk: 'medium',
400
+ explain: ((data?.rationale as string) ?? '').slice(0, 280) || 'No explanation',
401
+ };
402
+ } else {
403
+ return {
404
+ confidence: 0,
405
+ risk: 'high',
406
+ explain: response.error?.message?.slice(0, 280) ?? 'Error occurred',
407
+ };
408
+ }
409
+ }
410
+
411
+ /** Aggregate risk from list of changes */
412
+ export function aggregateRisk(changes: Array<{ risk?: RiskLevel }>): RiskLevel {
413
+ const riskLevels: Record<RiskLevel, number> = { none: 0, low: 1, medium: 2, high: 3 };
414
+ const riskNames: RiskLevel[] = ['none', 'low', 'medium', 'high'];
415
+
416
+ if (!changes || changes.length === 0) {
417
+ return 'medium';
418
+ }
419
+
420
+ let maxLevel = 0;
421
+ for (const change of changes) {
422
+ const level = riskLevels[change.risk ?? 'medium'];
423
+ maxLevel = Math.max(maxLevel, level);
424
+ }
425
+
426
+ return riskNames[maxLevel];
427
+ }
428
+
429
+ /** Check if result should be escalated to human review */
430
+ export function shouldEscalate<T>(
431
+ response: EnvelopeResponse<T>,
432
+ confidenceThreshold: number = 0.7
433
+ ): boolean {
434
+ const meta = extractMeta(response);
435
+
436
+ // Escalate if low confidence
437
+ if (meta.confidence < confidenceThreshold) {
438
+ return true;
439
+ }
440
+
441
+ // Escalate if high risk
442
+ if (meta.risk === 'high') {
443
+ return true;
444
+ }
445
+
446
+ // Escalate if error
447
+ if (!response.ok) {
448
+ return true;
449
+ }
450
+
451
+ return false;
452
+ }