@cleocode/core 2026.4.11 → 2026.4.13

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 (184) hide show
  1. package/dist/codebase-map/analyzers/architecture.d.ts.map +1 -1
  2. package/dist/codebase-map/analyzers/architecture.js +0 -1
  3. package/dist/codebase-map/analyzers/architecture.js.map +1 -1
  4. package/dist/conduit/local-transport.d.ts +18 -8
  5. package/dist/conduit/local-transport.d.ts.map +1 -1
  6. package/dist/conduit/local-transport.js +23 -13
  7. package/dist/conduit/local-transport.js.map +1 -1
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +0 -1
  10. package/dist/config.js.map +1 -1
  11. package/dist/errors.d.ts +19 -0
  12. package/dist/errors.d.ts.map +1 -1
  13. package/dist/errors.js +6 -0
  14. package/dist/errors.js.map +1 -1
  15. package/dist/index.js +175 -68950
  16. package/dist/index.js.map +1 -7
  17. package/dist/init.d.ts +1 -2
  18. package/dist/init.d.ts.map +1 -1
  19. package/dist/init.js +1 -2
  20. package/dist/init.js.map +1 -1
  21. package/dist/internal.d.ts +8 -3
  22. package/dist/internal.d.ts.map +1 -1
  23. package/dist/internal.js +13 -6
  24. package/dist/internal.js.map +1 -1
  25. package/dist/memory/learnings.d.ts +2 -2
  26. package/dist/memory/patterns.d.ts +6 -6
  27. package/dist/output.d.ts +32 -11
  28. package/dist/output.d.ts.map +1 -1
  29. package/dist/output.js +67 -67
  30. package/dist/output.js.map +1 -1
  31. package/dist/paths.js +80 -14
  32. package/dist/paths.js.map +1 -1
  33. package/dist/skills/dynamic-skill-generator.d.ts +0 -2
  34. package/dist/skills/dynamic-skill-generator.d.ts.map +1 -1
  35. package/dist/skills/dynamic-skill-generator.js.map +1 -1
  36. package/dist/store/agent-registry-accessor.d.ts +203 -12
  37. package/dist/store/agent-registry-accessor.d.ts.map +1 -1
  38. package/dist/store/agent-registry-accessor.js +618 -100
  39. package/dist/store/agent-registry-accessor.js.map +1 -1
  40. package/dist/store/api-key-kdf.d.ts +73 -0
  41. package/dist/store/api-key-kdf.d.ts.map +1 -0
  42. package/dist/store/api-key-kdf.js +84 -0
  43. package/dist/store/api-key-kdf.js.map +1 -0
  44. package/dist/store/cleanup-legacy.js +171 -0
  45. package/dist/store/cleanup-legacy.js.map +1 -0
  46. package/dist/store/conduit-sqlite.d.ts +184 -0
  47. package/dist/store/conduit-sqlite.d.ts.map +1 -0
  48. package/dist/store/conduit-sqlite.js +570 -0
  49. package/dist/store/conduit-sqlite.js.map +1 -0
  50. package/dist/store/global-salt.d.ts +78 -0
  51. package/dist/store/global-salt.d.ts.map +1 -0
  52. package/dist/store/global-salt.js +147 -0
  53. package/dist/store/global-salt.js.map +1 -0
  54. package/dist/store/migrate-signaldock-to-conduit.d.ts +81 -0
  55. package/dist/store/migrate-signaldock-to-conduit.d.ts.map +1 -0
  56. package/dist/store/migrate-signaldock-to-conduit.js +555 -0
  57. package/dist/store/migrate-signaldock-to-conduit.js.map +1 -0
  58. package/dist/store/nexus-sqlite.js +28 -3
  59. package/dist/store/nexus-sqlite.js.map +1 -1
  60. package/dist/store/signaldock-sqlite.d.ts +122 -19
  61. package/dist/store/signaldock-sqlite.d.ts.map +1 -1
  62. package/dist/store/signaldock-sqlite.js +401 -251
  63. package/dist/store/signaldock-sqlite.js.map +1 -1
  64. package/dist/store/sqlite-backup.js +122 -4
  65. package/dist/store/sqlite-backup.js.map +1 -1
  66. package/dist/system/backup.d.ts +0 -26
  67. package/dist/system/backup.d.ts.map +1 -1
  68. package/dist/system/runtime.d.ts +0 -2
  69. package/dist/system/runtime.d.ts.map +1 -1
  70. package/dist/system/runtime.js +3 -3
  71. package/dist/system/runtime.js.map +1 -1
  72. package/dist/tasks/add.d.ts +1 -1
  73. package/dist/tasks/add.d.ts.map +1 -1
  74. package/dist/tasks/add.js +98 -23
  75. package/dist/tasks/add.js.map +1 -1
  76. package/dist/tasks/complete.d.ts.map +1 -1
  77. package/dist/tasks/complete.js +4 -1
  78. package/dist/tasks/complete.js.map +1 -1
  79. package/dist/tasks/find.d.ts.map +1 -1
  80. package/dist/tasks/find.js +4 -1
  81. package/dist/tasks/find.js.map +1 -1
  82. package/dist/tasks/labels.d.ts.map +1 -1
  83. package/dist/tasks/labels.js +4 -1
  84. package/dist/tasks/labels.js.map +1 -1
  85. package/dist/tasks/relates.d.ts.map +1 -1
  86. package/dist/tasks/relates.js +16 -4
  87. package/dist/tasks/relates.js.map +1 -1
  88. package/dist/tasks/show.d.ts.map +1 -1
  89. package/dist/tasks/show.js +4 -1
  90. package/dist/tasks/show.js.map +1 -1
  91. package/dist/tasks/update.d.ts.map +1 -1
  92. package/dist/tasks/update.js +32 -6
  93. package/dist/tasks/update.js.map +1 -1
  94. package/dist/validation/engine.d.ts.map +1 -1
  95. package/dist/validation/engine.js +16 -4
  96. package/dist/validation/engine.js.map +1 -1
  97. package/dist/validation/param-utils.d.ts +5 -3
  98. package/dist/validation/param-utils.d.ts.map +1 -1
  99. package/dist/validation/param-utils.js +8 -6
  100. package/dist/validation/param-utils.js.map +1 -1
  101. package/dist/validation/protocols/_shared.d.ts.map +1 -1
  102. package/dist/validation/protocols/_shared.js +13 -6
  103. package/dist/validation/protocols/_shared.js.map +1 -1
  104. package/package.json +9 -7
  105. package/src/adapters/__tests__/manager.test.ts +0 -1
  106. package/src/codebase-map/analyzers/architecture.ts +0 -1
  107. package/src/conduit/__tests__/local-credential-flow.test.ts +20 -18
  108. package/src/conduit/__tests__/local-transport.test.ts +14 -12
  109. package/src/conduit/local-transport.ts +23 -13
  110. package/src/config.ts +0 -1
  111. package/src/errors.ts +24 -0
  112. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.ts +2 -5
  113. package/src/init.ts +1 -2
  114. package/src/internal.ts +96 -2
  115. package/src/lifecycle/cant/lifecycle-rcasd.cant +133 -0
  116. package/src/memory/__tests__/engine-compat.test.ts +2 -2
  117. package/src/memory/__tests__/pipeline-manifest-sqlite.test.ts +4 -4
  118. package/src/observability/__tests__/index.test.ts +4 -4
  119. package/src/observability/__tests__/log-filter.test.ts +4 -4
  120. package/src/output.ts +73 -75
  121. package/src/sessions/__tests__/session-grade.integration.test.ts +1 -1
  122. package/src/sessions/__tests__/session-grade.test.ts +2 -2
  123. package/src/skills/__tests__/dynamic-skill-generator.test.ts +0 -2
  124. package/src/skills/dynamic-skill-generator.ts +0 -2
  125. package/src/store/__tests__/agent-registry-accessor.test.ts +807 -0
  126. package/src/store/__tests__/api-key-kdf.test.ts +113 -0
  127. package/src/store/__tests__/backup-crypto.test.ts +101 -0
  128. package/src/store/__tests__/backup-pack.test.ts +491 -0
  129. package/src/store/__tests__/backup-unpack.test.ts +298 -0
  130. package/src/store/__tests__/conduit-sqlite.test.ts +413 -0
  131. package/src/store/__tests__/global-salt.test.ts +195 -0
  132. package/src/store/__tests__/migrate-signaldock-to-conduit.test.ts +715 -0
  133. package/src/store/__tests__/regenerators.test.ts +234 -0
  134. package/src/store/__tests__/restore-conflict-report.test.ts +274 -0
  135. package/src/store/__tests__/restore-json-merge.test.ts +521 -0
  136. package/src/store/__tests__/signaldock-sqlite.test.ts +652 -0
  137. package/src/store/__tests__/sqlite-backup-global.test.ts +307 -3
  138. package/src/store/__tests__/sqlite-backup.test.ts +5 -1
  139. package/src/store/__tests__/t310-integration.test.ts +1150 -0
  140. package/src/store/__tests__/t310-readiness.test.ts +111 -0
  141. package/src/store/__tests__/t311-integration.test.ts +661 -0
  142. package/src/store/agent-registry-accessor.ts +847 -140
  143. package/src/store/api-key-kdf.ts +104 -0
  144. package/src/store/backup-crypto.ts +209 -0
  145. package/src/store/backup-pack.ts +739 -0
  146. package/src/store/backup-unpack.ts +583 -0
  147. package/src/store/conduit-sqlite.ts +655 -0
  148. package/src/store/global-salt.ts +175 -0
  149. package/src/store/migrate-signaldock-to-conduit.ts +669 -0
  150. package/src/store/regenerators.ts +243 -0
  151. package/src/store/restore-conflict-report.ts +317 -0
  152. package/src/store/restore-json-merge.ts +653 -0
  153. package/src/store/signaldock-sqlite.ts +431 -254
  154. package/src/store/sqlite-backup.ts +185 -10
  155. package/src/store/t310-readiness.ts +119 -0
  156. package/src/system/backup.ts +2 -62
  157. package/src/system/runtime.ts +4 -6
  158. package/src/tasks/__tests__/error-hints.test.ts +256 -0
  159. package/src/tasks/add.ts +99 -9
  160. package/src/tasks/complete.ts +4 -1
  161. package/src/tasks/find.ts +4 -1
  162. package/src/tasks/labels.ts +4 -1
  163. package/src/tasks/relates.ts +16 -4
  164. package/src/tasks/show.ts +4 -1
  165. package/src/tasks/update.ts +32 -3
  166. package/src/validation/__tests__/error-hints.test.ts +97 -0
  167. package/src/validation/engine.ts +16 -1
  168. package/src/validation/param-utils.ts +10 -7
  169. package/src/validation/protocols/_shared.ts +14 -6
  170. package/src/validation/protocols/cant/architecture-decision.cant +80 -0
  171. package/src/validation/protocols/cant/artifact-publish.cant +95 -0
  172. package/src/validation/protocols/cant/consensus.cant +74 -0
  173. package/src/validation/protocols/cant/contribution.cant +82 -0
  174. package/src/validation/protocols/cant/decomposition.cant +92 -0
  175. package/src/validation/protocols/cant/implementation.cant +67 -0
  176. package/src/validation/protocols/cant/provenance.cant +88 -0
  177. package/src/validation/protocols/cant/release.cant +96 -0
  178. package/src/validation/protocols/cant/research.cant +66 -0
  179. package/src/validation/protocols/cant/specification.cant +67 -0
  180. package/src/validation/protocols/cant/testing.cant +88 -0
  181. package/src/validation/protocols/cant/validation.cant +65 -0
  182. package/src/validation/protocols/protocols-markdown/decomposition.md +0 -4
  183. package/templates/config.template.json +0 -1
  184. package/templates/global-config.template.json +0 -1
package/src/output.ts CHANGED
@@ -4,22 +4,28 @@
4
4
  * LAFS (LLM-Agent-First Schema) ensures all CLI output is
5
5
  * machine-parseable JSON by default, with optional human-readable modes.
6
6
  *
7
- * All envelopes are now full LAFS-compliant with $schema and _meta.
8
- * The backward-compatible shape (success + data, no _meta) has been removed.
7
+ * All envelopes use the canonical CLI envelope shape:
8
+ * { success, data?, error?, meta, page? }
9
+ *
10
+ * This replaces the three legacy shapes:
11
+ * {ok, r, _m} (minimal MVI — removed)
12
+ * {$schema, _meta, success, result} (full LAFS — now uses meta/data)
13
+ * {success, result} (observe command — now uses data)
9
14
  *
10
15
  * Types are re-exported from the canonical source in src/types/lafs.ts.
11
16
  *
12
17
  * @epic T4663
13
18
  * @task T4672
19
+ * @task T338 (ADR-039 envelope unification)
14
20
  */
15
21
 
16
22
  import { randomUUID } from 'node:crypto';
17
23
  import type { LafsEnvelope, LafsError, LafsSuccess } from '@cleocode/contracts';
18
- import type { LAFSMeta, LAFSPage, Warning } from '@cleocode/lafs';
24
+ import type { CliEnvelope, CliEnvelopeError, CliMeta, LAFSPage, Warning } from '@cleocode/lafs';
19
25
  import { CleoError } from './errors.js';
20
26
  import { getCurrentSessionId } from './sessions/context-alert.js';
21
27
 
22
- export type { LafsEnvelope, LafsError, LafsSuccess };
28
+ export type { CliEnvelope, CliEnvelopeError, CliMeta, LafsEnvelope, LafsError, LafsSuccess };
23
29
 
24
30
  /**
25
31
  * Accumulated warnings for the current request.
@@ -70,47 +76,57 @@ export interface FormatOptions {
70
76
  }
71
77
 
72
78
  /**
73
- * Create a LAFS-conformant _meta object for CLI envelopes.
79
+ * Create a canonical `CliMeta` object for CLI envelopes.
80
+ *
74
81
  * Includes sessionId (T4702) and warnings (T4669) when present.
82
+ * Drains the pending warnings queue so they are included in the current envelope.
83
+ *
84
+ * @param operation - Dot-delimited operation identifier (e.g. `"tasks.show"`).
85
+ * @param duration_ms - Wall-clock duration in milliseconds. Defaults to 0.
86
+ * @returns A fully populated {@link CliMeta} object.
75
87
  *
76
88
  * @task T4700
77
89
  * @task T4702
90
+ * @task T338
78
91
  * @epic T4663
79
92
  */
80
- function createCliMeta(
81
- operation: string,
82
- mvi: import('@cleocode/lafs').MVILevel = 'minimal',
83
- ): LAFSMeta {
93
+ function createCliMeta(operation: string, duration_ms = 0): CliMeta {
84
94
  const warnings = drainWarnings();
85
- const meta: LAFSMeta = {
86
- specVersion: '1.2.3',
87
- schemaVersion: '2026.2.1',
88
- timestamp: new Date().toISOString(),
95
+ const meta: CliMeta = {
89
96
  operation,
90
97
  requestId: randomUUID(),
91
- transport: 'cli',
92
- strict: true,
93
- mvi,
94
- contextVersion: 1,
95
- ...(warnings && { warnings }),
98
+ duration_ms,
99
+ timestamp: new Date().toISOString(),
96
100
  };
97
101
  const sessionId = getCurrentSessionId();
98
102
  if (sessionId) {
99
- meta.sessionId = sessionId;
103
+ meta['sessionId'] = sessionId;
104
+ }
105
+ if (warnings && warnings.length > 0) {
106
+ meta['warnings'] = warnings;
100
107
  }
101
108
  return meta;
102
109
  }
103
110
 
104
111
  /**
105
- * Format a successful result as a full LAFS-conformant envelope.
112
+ * Format a successful result as a canonical CLI envelope.
113
+ *
114
+ * Produces the unified `CliEnvelope<T>` shape: `{success, data, meta, page?}`.
115
+ * This replaces all three legacy shapes (minimal `{ok,r,_m}`, full `{$schema,_meta,result}`,
116
+ * and observe `{success,result}`) with a single canonical format (ADR-039).
117
+ *
118
+ * The `mvi` option in `FormatOptions` is accepted for backward compatibility but
119
+ * no longer affects the envelope shape — the canonical shape is always emitted.
106
120
  *
107
- * Always produces the full LAFSEnvelope with $schema and _meta.
108
- * When operation is omitted, defaults to 'cli.output'.
109
- * Supports optional page (T4668) and _extensions (T4670).
121
+ * @param data - The operation result payload.
122
+ * @param message - Optional success message (attached to `meta.message`).
123
+ * @param operationOrOpts - Operation name string or `FormatOptions` object.
124
+ * @returns JSON-serialized `CliEnvelope<T>`.
110
125
  *
111
126
  * @task T4672
112
127
  * @task T4668
113
128
  * @task T4670
129
+ * @task T338
114
130
  * @epic T4663
115
131
  */
116
132
  export function formatSuccess<T>(
@@ -121,71 +137,53 @@ export function formatSuccess<T>(
121
137
  const opts: FormatOptions =
122
138
  typeof operationOrOpts === 'string' ? { operation: operationOrOpts } : (operationOrOpts ?? {});
123
139
 
124
- // Determine MVI level: default is 'minimal' (agent-optimized).
125
- // Only --human flag or explicit mvi='full'/'standard' overrides.
126
- const mviLevel = opts.mvi ?? 'minimal';
140
+ const meta = createCliMeta(opts.operation ?? 'cli.output');
127
141
 
128
- const meta = createCliMeta(opts.operation ?? 'cli.output', mviLevel);
129
- const fullEnvelope: Record<string, unknown> = {
130
- $schema: 'https://lafs.dev/schemas/v1/envelope.schema.json',
131
- _meta: meta,
132
- success: true as const,
133
- result: data as Record<string, unknown> | Record<string, unknown>[] | null,
134
- ...(message && { message }),
142
+ const envelope: CliEnvelope<T> = {
143
+ success: true,
144
+ data,
145
+ meta: message ? { ...meta, message } : meta,
135
146
  ...(opts.page && { page: opts.page }),
136
- ...(opts.extensions &&
137
- Object.keys(opts.extensions).length > 0 && { _extensions: opts.extensions }),
138
147
  };
139
148
 
140
- // For 'full' level, skip projection — return the complete envelope as-is.
141
- // This is the backward-compatible path used by --human and conformance tests.
142
- if (mviLevel === 'full') {
143
- return JSON.stringify(fullEnvelope);
144
- }
145
-
146
- // Apply MVI projection — strips envelope to the declared level.
147
- // 'minimal': { success, result, _meta: { requestId, contextVersion } }
148
- // 'standard': + $schema, timestamp, operation, mvi
149
- if (mviLevel === 'minimal') {
150
- // Inline minimal projection — avoids dynamic import overhead.
151
- // Matches projectMetaMinimal() from @cleocode/lafs/mviProjection.ts
152
- const minimalMeta: Record<string, unknown> = {
153
- op: meta.operation,
154
- rid: meta.requestId,
155
- };
156
- if (meta.sessionId) minimalMeta.sid = meta.sessionId;
157
- if (meta.warnings?.length) minimalMeta.w = meta.warnings;
158
-
159
- const minimal: Record<string, unknown> = {
160
- ok: true,
161
- r: data,
162
- _m: minimalMeta,
163
- };
164
- if (message) minimal.msg = message;
165
- if (opts.page) minimal.p = opts.page;
166
- return JSON.stringify(minimal);
167
- }
168
-
169
- // 'standard' level — use the full envelope structure (current behavior)
170
- return JSON.stringify(fullEnvelope);
149
+ return JSON.stringify(envelope);
171
150
  }
172
151
 
173
152
  /**
174
- * Format an error as a full LAFS-conformant envelope.
153
+ * Format an error as a canonical CLI error envelope.
154
+ *
155
+ * Produces `{success: false, error: CliEnvelopeError, meta: CliMeta}`.
156
+ * Every error envelope now always includes `meta` (ADR-039).
157
+ * When operation is omitted, defaults to `'cli.output'`.
175
158
  *
176
- * Always produces the full LAFSEnvelope with $schema and _meta.
177
- * When operation is omitted, defaults to 'cli.output'.
159
+ * @param error - The `CleoError` to format.
160
+ * @param operation - Optional dot-delimited operation identifier.
161
+ * @returns JSON-serialized error `CliEnvelope`.
178
162
  *
179
163
  * @task T4672
164
+ * @task T338
180
165
  * @epic T4663
181
166
  */
182
167
  export function formatError(error: CleoError, operation?: string): string {
183
- const envelope = {
184
- $schema: 'https://lafs.dev/schemas/v1/envelope.schema.json',
185
- _meta: createCliMeta(operation ?? 'cli.output'),
186
- success: false as const,
187
- result: null,
188
- error: error.toLAFSError(),
168
+ const lafsError = error.toLAFSError();
169
+ const errorObj: CliEnvelopeError = {
170
+ code: lafsError.code,
171
+ message: lafsError.message,
172
+ details: lafsError.details,
173
+ };
174
+ if ('category' in lafsError && lafsError.category) {
175
+ (errorObj as Record<string, unknown>)['category'] = lafsError.category;
176
+ }
177
+ if ('retryable' in lafsError) {
178
+ (errorObj as Record<string, unknown>)['retryable'] = lafsError.retryable;
179
+ }
180
+ if ('agentAction' in lafsError && lafsError.agentAction) {
181
+ (errorObj as Record<string, unknown>)['agentAction'] = lafsError.agentAction;
182
+ }
183
+ const envelope: CliEnvelope<null> = {
184
+ success: false,
185
+ error: errorObj,
186
+ meta: createCliMeta(operation ?? 'cli.output'),
189
187
  };
190
188
  return JSON.stringify(envelope);
191
189
  }
@@ -160,7 +160,7 @@ function sloppySession(): AuditEntry[] {
160
160
  params: { title: 'Do something', description: 'Duplicate' },
161
161
  result: { success: true, exitCode: 0, duration: 20 },
162
162
  }),
163
- // No session.end, no help calls, no MCP gateway
163
+ // No session.end, no help calls, no query gateway usage
164
164
  ];
165
165
  }
166
166
 
@@ -657,7 +657,7 @@ describe('gradeSession', () => {
657
657
  }),
658
658
  ]);
659
659
 
660
- const result = await gradeSession('s5-mcp', tempDir);
660
+ const result = await gradeSession('s5-query', tempDir);
661
661
 
662
662
  expect(result.dimensions.disclosureUse.score).toBe(10);
663
663
  expect(result.dimensions.disclosureUse.evidence).toEqual(
@@ -698,7 +698,7 @@ describe('gradeSession', () => {
698
698
  entry({ domain: 'tasks', operation: 'find', timestamp: ts(0) }),
699
699
  ]);
700
700
 
701
- const result = await gradeSession('s5-nomcp', tempDir);
701
+ const result = await gradeSession('s5-noqueries', tempDir);
702
702
 
703
703
  expect(result.flags).toContain(
704
704
  'No query gateway calls (use query operations for programmatic access)',
@@ -9,7 +9,6 @@ import {
9
9
  const cliProvider: ProviderContext = {
10
10
  providerId: 'claude-code',
11
11
  providerName: 'Claude Code',
12
- supportsMcp: false,
13
12
  supportsHooks: true,
14
13
  supportsSpawn: true,
15
14
  instructionFilePattern: 'CLAUDE.md',
@@ -18,7 +17,6 @@ const cliProvider: ProviderContext = {
18
17
  const limitedProvider: ProviderContext = {
19
18
  providerId: 'cursor',
20
19
  providerName: 'Cursor',
21
- supportsMcp: false,
22
20
  supportsHooks: false,
23
21
  supportsSpawn: false,
24
22
  instructionFilePattern: '.cursor/rules/*.mdc',
@@ -16,8 +16,6 @@ import { getPreferredChannel } from './routing-table.js';
16
16
  export interface ProviderContext {
17
17
  providerId: string;
18
18
  providerName: string;
19
- /** Always false. CLI dispatch only. */
20
- supportsMcp: boolean;
21
19
  supportsHooks: boolean;
22
20
  supportsSpawn: boolean;
23
21
  instructionFilePattern?: string;