cognitive-modules-cli 1.0.1 → 1.2.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/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,16 @@ 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';
36
+ /** Risk aggregation rule */
37
+ export type RiskRule = 'max_changes_risk' | 'max_issues_risk' | 'explicit';
28
38
  export interface CognitiveModule {
29
39
  name: string;
30
40
  version: string;
@@ -36,13 +46,22 @@ export interface CognitiveModule {
36
46
  output?: OutputContract;
37
47
  failure?: FailureContract;
38
48
  runtimeRequirements?: RuntimeRequirements;
49
+ tier?: ModuleTier;
50
+ schemaStrictness?: SchemaStrictness;
51
+ overflow?: OverflowConfig;
52
+ enums?: EnumConfig;
53
+ compat?: CompatConfig;
54
+ metaConfig?: MetaConfig;
39
55
  context?: 'fork' | 'main';
40
56
  prompt: string;
41
57
  inputSchema?: object;
42
58
  outputSchema?: object;
59
+ dataSchema?: object;
60
+ metaSchema?: object;
43
61
  errorSchema?: object;
44
62
  location: string;
45
- format: 'v1' | 'v2';
63
+ format: 'v0' | 'v1' | 'v2';
64
+ formatVersion?: string;
46
65
  }
47
66
  export interface ModuleConstraints {
48
67
  no_network?: boolean;
@@ -81,11 +100,77 @@ export interface RuntimeRequirements {
81
100
  max_input_tokens?: number;
82
101
  preferred_capabilities?: string[];
83
102
  }
84
- export interface EnvelopeSuccess<T = unknown> {
103
+ /** Overflow configuration for extensions.insights */
104
+ export interface OverflowConfig {
105
+ enabled: boolean;
106
+ recoverable?: boolean;
107
+ max_items?: number;
108
+ require_suggested_mapping?: boolean;
109
+ }
110
+ /** Enum extension configuration */
111
+ export interface EnumConfig {
112
+ strategy: EnumStrategy;
113
+ unknown_tag?: string;
114
+ }
115
+ /** Compatibility configuration for migration */
116
+ export interface CompatConfig {
117
+ accepts_v21_payload?: boolean;
118
+ runtime_auto_wrap?: boolean;
119
+ schema_output_alias?: 'data' | 'output';
120
+ }
121
+ /** Meta field configuration (v2.2) */
122
+ export interface MetaConfig {
123
+ required?: string[];
124
+ risk_rule?: RiskRule;
125
+ confidence?: {
126
+ min?: number;
127
+ max?: number;
128
+ };
129
+ explain?: {
130
+ max_chars?: number;
131
+ };
132
+ }
133
+ /**
134
+ * Control plane metadata - unified across all modules.
135
+ * Used for routing, logging, UI cards, and middleware decisions.
136
+ */
137
+ export interface EnvelopeMeta {
138
+ /** Confidence score [0, 1] - unified across all modules */
139
+ confidence: number;
140
+ /** Aggregated risk level: max(changes[*].risk) */
141
+ risk: RiskLevel;
142
+ /** Short explanation for middleware/UI (max 280 chars) */
143
+ explain: string;
144
+ /** Distributed tracing ID */
145
+ trace_id?: string;
146
+ /** Provider and model identifier */
147
+ model?: string;
148
+ /** Execution latency in milliseconds */
149
+ latency_ms?: number;
150
+ }
151
+ /** Success response in v2.2 envelope format */
152
+ export interface EnvelopeSuccessV22<T = unknown> {
153
+ ok: true;
154
+ meta: EnvelopeMeta;
155
+ data: T;
156
+ }
157
+ /** Error response in v2.2 envelope format */
158
+ export interface EnvelopeErrorV22 {
159
+ ok: false;
160
+ meta: EnvelopeMeta;
161
+ error: {
162
+ code: string;
163
+ message: string;
164
+ };
165
+ partial_data?: unknown;
166
+ }
167
+ /** v2.2 envelope response (union type) */
168
+ export type EnvelopeResponseV22<T = unknown> = EnvelopeSuccessV22<T> | EnvelopeErrorV22;
169
+ export interface EnvelopeSuccessV21<T = unknown> {
85
170
  ok: true;
86
171
  data: T;
87
172
  }
88
- export interface EnvelopeError {
173
+ export interface EnvelopeErrorV21 {
89
174
  ok: false;
90
175
  error: {
91
176
  code: string;
@@ -93,15 +178,46 @@ export interface EnvelopeError {
93
178
  };
94
179
  partial_data?: unknown;
95
180
  }
96
- export type EnvelopeResponse<T = unknown> = EnvelopeSuccess<T> | EnvelopeError;
181
+ export type EnvelopeResponseV21<T = unknown> = EnvelopeSuccessV21<T> | EnvelopeErrorV21;
182
+ /** Generic envelope response (supports both v2.1 and v2.2) */
183
+ export type EnvelopeResponse<T = unknown> = EnvelopeResponseV22<T> | EnvelopeResponseV21<T>;
184
+ /** An insight that doesn't fit the schema but is valuable */
185
+ export interface Insight {
186
+ /** The observation or insight */
187
+ text: string;
188
+ /** Suggested field/enum to add to schema for future versions */
189
+ suggested_mapping: string;
190
+ /** Supporting evidence for this insight */
191
+ evidence?: string;
192
+ }
193
+ /** Extensions container for overflow data */
194
+ export interface Extensions {
195
+ insights?: Insight[];
196
+ }
197
+ /**
198
+ * Extensible enum type - allows both predefined values and custom extensions.
199
+ *
200
+ * Usage:
201
+ * type ChangeType = ExtensibleEnum<'remove_redundancy' | 'simplify_logic' | 'other'>;
202
+ *
203
+ * Valid values:
204
+ * - "remove_redundancy" (predefined)
205
+ * - { custom: "inline_callback", reason: "Converted callback to arrow function" }
206
+ */
207
+ export type ExtensibleEnum<T extends string> = T | {
208
+ custom: string;
209
+ reason: string;
210
+ };
211
+ /** Base interface for module result data */
97
212
  export interface ModuleResultData {
98
213
  [key: string]: unknown;
99
- confidence: number;
100
214
  rationale: string;
101
- behavior_equivalence?: boolean;
215
+ extensions?: Extensions;
102
216
  }
103
- export interface ModuleResult {
217
+ /** v2.2 module result with meta and data separation */
218
+ export interface ModuleResultV22 {
104
219
  ok: boolean;
220
+ meta: EnvelopeMeta;
105
221
  data?: ModuleResultData;
106
222
  error?: {
107
223
  code: string;
@@ -110,6 +226,21 @@ export interface ModuleResult {
110
226
  partial_data?: unknown;
111
227
  raw?: string;
112
228
  }
229
+ /** Legacy module result (v2.1) */
230
+ export interface ModuleResultV21 {
231
+ ok: boolean;
232
+ data?: ModuleResultData & {
233
+ confidence: number;
234
+ };
235
+ error?: {
236
+ code: string;
237
+ message: string;
238
+ };
239
+ partial_data?: unknown;
240
+ raw?: string;
241
+ }
242
+ /** Generic module result */
243
+ export type ModuleResult = ModuleResultV22 | ModuleResultV21;
113
244
  export interface LegacyModuleResult {
114
245
  output: unknown;
115
246
  confidence: number;
@@ -134,3 +265,20 @@ export interface ModuleInput {
134
265
  options?: Record<string, unknown>;
135
266
  [key: string]: unknown;
136
267
  }
268
+ /** Check if response is v2.2 format */
269
+ export declare function isV22Envelope<T>(response: EnvelopeResponse<T>): response is EnvelopeResponseV22<T>;
270
+ /** Check if response is successful */
271
+ export declare function isEnvelopeSuccess<T>(response: EnvelopeResponse<T>): response is EnvelopeSuccessV22<T> | EnvelopeSuccessV21<T>;
272
+ /** Extract meta from any envelope response */
273
+ export declare function extractMeta<T>(response: EnvelopeResponse<T>, riskRule?: RiskRule): EnvelopeMeta;
274
+ /**
275
+ * Aggregate risk based on configured rule.
276
+ *
277
+ * Rules:
278
+ * - max_changes_risk: max(data.changes[*].risk) - default
279
+ * - max_issues_risk: max(data.issues[*].risk) - for review modules
280
+ * - explicit: return "medium", module should set risk explicitly
281
+ */
282
+ export declare function aggregateRisk(data: Record<string, unknown>, riskRule?: RiskRule): RiskLevel;
283
+ /** Check if result should be escalated to human review */
284
+ export declare function shouldEscalate<T>(response: EnvelopeResponse<T>, confidenceThreshold?: number): boolean;
package/dist/types.js CHANGED
@@ -1,5 +1,92 @@
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, riskRule = 'max_changes_risk') {
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: aggregateRisk(data, riskRule),
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 items */
39
+ function aggregateRiskFromList(items) {
40
+ const riskLevels = { none: 0, low: 1, medium: 2, high: 3 };
41
+ const riskNames = ['none', 'low', 'medium', 'high'];
42
+ if (!items || items.length === 0) {
43
+ return 'medium';
44
+ }
45
+ let maxLevel = 0;
46
+ for (const item of items) {
47
+ const level = riskLevels[item.risk ?? 'medium'];
48
+ maxLevel = Math.max(maxLevel, level);
49
+ }
50
+ return riskNames[maxLevel];
51
+ }
52
+ /**
53
+ * Aggregate risk based on configured rule.
54
+ *
55
+ * Rules:
56
+ * - max_changes_risk: max(data.changes[*].risk) - default
57
+ * - max_issues_risk: max(data.issues[*].risk) - for review modules
58
+ * - explicit: return "medium", module should set risk explicitly
59
+ */
60
+ export function aggregateRisk(data, riskRule = 'max_changes_risk') {
61
+ if (riskRule === 'max_changes_risk') {
62
+ const changes = data.changes ?? [];
63
+ return aggregateRiskFromList(changes);
64
+ }
65
+ else if (riskRule === 'max_issues_risk') {
66
+ const issues = data.issues ?? [];
67
+ return aggregateRiskFromList(issues);
68
+ }
69
+ else if (riskRule === 'explicit') {
70
+ return 'medium'; // Module should override
71
+ }
72
+ // Fallback to changes
73
+ const changes = data.changes ?? [];
74
+ return aggregateRiskFromList(changes);
75
+ }
76
+ /** Check if result should be escalated to human review */
77
+ export function shouldEscalate(response, confidenceThreshold = 0.7) {
78
+ const meta = extractMeta(response);
79
+ // Escalate if low confidence
80
+ if (meta.confidence < confidenceThreshold) {
81
+ return true;
82
+ }
83
+ // Escalate if high risk
84
+ if (meta.risk === 'high') {
85
+ return true;
86
+ }
87
+ // Escalate if error
88
+ if (!response.ok) {
89
+ return true;
90
+ }
91
+ return false;
92
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognitive-modules-cli",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "Cognitive Modules - Structured AI Task Execution with version management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -6,7 +6,21 @@
6
6
  import * as fs from 'node:fs/promises';
7
7
  import * as path from 'node:path';
8
8
  import yaml from 'js-yaml';
9
- import type { CognitiveModule, ModuleConstraints, ModulePolicies, ToolsPolicy, OutputContract, FailureContract, RuntimeRequirements } from '../types.js';
9
+ import type {
10
+ CognitiveModule,
11
+ ModuleConstraints,
12
+ ModulePolicies,
13
+ ToolsPolicy,
14
+ OutputContract,
15
+ FailureContract,
16
+ RuntimeRequirements,
17
+ OverflowConfig,
18
+ EnumConfig,
19
+ CompatConfig,
20
+ MetaConfig,
21
+ ModuleTier,
22
+ SchemaStrictness
23
+ } from '../types.js';
10
24
 
11
25
  const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?/;
12
26
 
@@ -23,6 +37,19 @@ async function detectFormat(modulePath: string): Promise<'v1' | 'v2'> {
23
37
  }
24
38
  }
25
39
 
40
+ /**
41
+ * Detect v2.x sub-version from manifest
42
+ */
43
+ function detectV2Version(manifest: Record<string, unknown>): string {
44
+ if (manifest.tier || manifest.overflow || manifest.enums) {
45
+ return 'v2.2';
46
+ }
47
+ if (manifest.policies || manifest.failure) {
48
+ return 'v2.1';
49
+ }
50
+ return 'v2.0';
51
+ }
52
+
26
53
  /**
27
54
  * Load v2 format module (module.yaml + prompt.md)
28
55
  */
@@ -35,6 +62,9 @@ async function loadModuleV2(modulePath: string): Promise<CognitiveModule> {
35
62
  const manifestContent = await fs.readFile(manifestFile, 'utf-8');
36
63
  const manifest = yaml.load(manifestContent) as Record<string, unknown>;
37
64
 
65
+ // Detect v2.x version
66
+ const formatVersion = detectV2Version(manifest);
67
+
38
68
  // Read prompt.md
39
69
  let prompt = '';
40
70
  try {
@@ -46,18 +76,68 @@ async function loadModuleV2(modulePath: string): Promise<CognitiveModule> {
46
76
  // Read schema.json
47
77
  let inputSchema: object | undefined;
48
78
  let outputSchema: object | undefined;
79
+ let dataSchema: object | undefined;
80
+ let metaSchema: object | undefined;
49
81
  let errorSchema: object | undefined;
50
82
 
51
83
  try {
52
84
  const schemaContent = await fs.readFile(schemaFile, 'utf-8');
53
85
  const schema = JSON.parse(schemaContent);
54
86
  inputSchema = schema.input;
55
- outputSchema = schema.output;
87
+ // Support both "data" (v2.2) and "output" (v2.1) aliases
88
+ dataSchema = schema.data || schema.output;
89
+ outputSchema = dataSchema; // Backward compat
90
+ metaSchema = schema.meta;
56
91
  errorSchema = schema.error;
57
92
  } catch {
58
93
  // Schema file is optional but recommended
59
94
  }
60
95
 
96
+ // Extract v2.2 fields
97
+ const tier = manifest.tier as ModuleTier | undefined;
98
+ const schemaStrictness = (manifest.schema_strictness as SchemaStrictness) || 'medium';
99
+
100
+ // Determine default max_items based on strictness (SPEC-v2.2)
101
+ const strictnessMaxItems: Record<SchemaStrictness, number> = {
102
+ high: 0,
103
+ medium: 5,
104
+ low: 20
105
+ };
106
+ const defaultMaxItems = strictnessMaxItems[schemaStrictness] ?? 5;
107
+ const defaultEnabled = schemaStrictness !== 'high';
108
+
109
+ // Parse overflow config with strictness-based defaults
110
+ const overflowRaw = (manifest.overflow as Record<string, unknown>) || {};
111
+ const overflow: OverflowConfig = {
112
+ enabled: (overflowRaw.enabled as boolean) ?? defaultEnabled,
113
+ recoverable: (overflowRaw.recoverable as boolean) ?? true,
114
+ max_items: (overflowRaw.max_items as number) ?? defaultMaxItems,
115
+ require_suggested_mapping: (overflowRaw.require_suggested_mapping as boolean) ?? true
116
+ };
117
+
118
+ // Parse enums config
119
+ const enumsRaw = (manifest.enums as Record<string, unknown>) || {};
120
+ const enums: EnumConfig = {
121
+ strategy: (enumsRaw.strategy as 'strict' | 'extensible') ??
122
+ (tier === 'exec' ? 'strict' : 'extensible'),
123
+ unknown_tag: (enumsRaw.unknown_tag as string) ?? 'custom'
124
+ };
125
+
126
+ // Parse compat config
127
+ const compatRaw = (manifest.compat as Record<string, unknown>) || {};
128
+ const compat: CompatConfig = {
129
+ accepts_v21_payload: (compatRaw.accepts_v21_payload as boolean) ?? true,
130
+ runtime_auto_wrap: (compatRaw.runtime_auto_wrap as boolean) ?? true,
131
+ schema_output_alias: (compatRaw.schema_output_alias as 'data' | 'output') ?? 'data'
132
+ };
133
+
134
+ // Parse meta config (including risk_rule)
135
+ const metaRaw = (manifest.meta as Record<string, unknown>) || {};
136
+ const metaConfig: MetaConfig = {
137
+ required: metaRaw.required as string[] | undefined,
138
+ risk_rule: metaRaw.risk_rule as 'max_changes_risk' | 'max_issues_risk' | 'explicit' | undefined,
139
+ };
140
+
61
141
  return {
62
142
  name: manifest.name as string || path.basename(modulePath),
63
143
  version: manifest.version as string || '1.0.0',
@@ -69,13 +149,26 @@ async function loadModuleV2(modulePath: string): Promise<CognitiveModule> {
69
149
  output: manifest.output as OutputContract | undefined,
70
150
  failure: manifest.failure as FailureContract | undefined,
71
151
  runtimeRequirements: manifest.runtime_requirements as RuntimeRequirements | undefined,
152
+ // v2.2 fields
153
+ tier,
154
+ schemaStrictness,
155
+ overflow,
156
+ enums,
157
+ compat,
158
+ metaConfig,
159
+ // Context and prompt
72
160
  context: manifest.context as 'fork' | 'main' | undefined,
73
161
  prompt,
162
+ // Schemas
74
163
  inputSchema,
75
164
  outputSchema,
165
+ dataSchema,
166
+ metaSchema,
76
167
  errorSchema,
168
+ // Metadata
77
169
  location: modulePath,
78
170
  format: 'v2',
171
+ formatVersion,
79
172
  };
80
173
  }
81
174