@cleocode/core 2026.3.69 → 2026.3.71

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 (129) hide show
  1. package/dist/agents/retry.d.ts.map +1 -1
  2. package/dist/agents/retry.js +23 -42
  3. package/dist/agents/retry.js.map +1 -1
  4. package/dist/cleo.d.ts +2 -300
  5. package/dist/cleo.d.ts.map +1 -1
  6. package/dist/cleo.js +2 -2
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +30 -0
  9. package/dist/config.js.map +1 -1
  10. package/dist/hooks/handlers/file-hooks.d.ts +5 -2
  11. package/dist/hooks/handlers/file-hooks.d.ts.map +1 -1
  12. package/dist/hooks/handlers/index.d.ts +2 -0
  13. package/dist/hooks/handlers/index.d.ts.map +1 -1
  14. package/dist/hooks/handlers/mcp-hooks.d.ts +11 -7
  15. package/dist/hooks/handlers/mcp-hooks.d.ts.map +1 -1
  16. package/dist/hooks/handlers/memory-bridge-refresh.d.ts +20 -0
  17. package/dist/hooks/handlers/memory-bridge-refresh.d.ts.map +1 -0
  18. package/dist/hooks/handlers/memory-bridge-refresh.js +42 -0
  19. package/dist/hooks/handlers/memory-bridge-refresh.js.map +1 -0
  20. package/dist/hooks/handlers/session-hooks.d.ts +10 -0
  21. package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
  22. package/dist/hooks/handlers/session-hooks.js +36 -0
  23. package/dist/hooks/handlers/session-hooks.js.map +1 -1
  24. package/dist/hooks/handlers/task-hooks.d.ts +4 -0
  25. package/dist/hooks/handlers/task-hooks.d.ts.map +1 -1
  26. package/dist/hooks/handlers/task-hooks.js +7 -0
  27. package/dist/hooks/handlers/task-hooks.js.map +1 -1
  28. package/dist/hooks/handlers/work-capture-hooks.d.ts +40 -0
  29. package/dist/hooks/handlers/work-capture-hooks.d.ts.map +1 -0
  30. package/dist/index.d.ts +2 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +5069 -4678
  33. package/dist/index.js.map +4 -4
  34. package/dist/internal.d.ts +10 -2
  35. package/dist/internal.d.ts.map +1 -1
  36. package/dist/internal.js +10 -3
  37. package/dist/internal.js.map +1 -1
  38. package/dist/memory/auto-extract.d.ts +13 -0
  39. package/dist/memory/auto-extract.d.ts.map +1 -1
  40. package/dist/memory/auto-extract.js +34 -0
  41. package/dist/memory/auto-extract.js.map +1 -1
  42. package/dist/memory/brain-embedding.d.ts +13 -0
  43. package/dist/memory/brain-embedding.d.ts.map +1 -1
  44. package/dist/memory/brain-embedding.js +17 -0
  45. package/dist/memory/brain-embedding.js.map +1 -1
  46. package/dist/memory/brain-maintenance.d.ts +110 -0
  47. package/dist/memory/brain-maintenance.d.ts.map +1 -0
  48. package/dist/memory/brain-maintenance.js +98 -0
  49. package/dist/memory/brain-maintenance.js.map +1 -0
  50. package/dist/memory/brain-retrieval.d.ts +31 -5
  51. package/dist/memory/brain-retrieval.d.ts.map +1 -1
  52. package/dist/memory/brain-retrieval.js +53 -6
  53. package/dist/memory/brain-retrieval.js.map +1 -1
  54. package/dist/memory/embedding-local.d.ts +55 -0
  55. package/dist/memory/embedding-local.d.ts.map +1 -0
  56. package/dist/memory/embedding-local.js +97 -0
  57. package/dist/memory/embedding-local.js.map +1 -0
  58. package/dist/memory/embedding-queue.d.ts +90 -0
  59. package/dist/memory/embedding-queue.d.ts.map +1 -0
  60. package/dist/memory/embedding-queue.js +271 -0
  61. package/dist/memory/embedding-queue.js.map +1 -0
  62. package/dist/memory/embedding-worker.d.ts +19 -0
  63. package/dist/memory/embedding-worker.d.ts.map +1 -0
  64. package/dist/memory/embedding-worker.js +58 -0
  65. package/dist/memory/embedding-worker.js.map +1 -0
  66. package/dist/memory/memory-bridge.d.ts +21 -1
  67. package/dist/memory/memory-bridge.d.ts.map +1 -1
  68. package/dist/memory/memory-bridge.js +83 -2
  69. package/dist/memory/memory-bridge.js.map +1 -1
  70. package/dist/memory/session-memory.d.ts +26 -0
  71. package/dist/memory/session-memory.d.ts.map +1 -1
  72. package/dist/memory/session-memory.js +105 -0
  73. package/dist/memory/session-memory.js.map +1 -1
  74. package/dist/pagination.js +3 -0
  75. package/dist/pagination.js.map +1 -1
  76. package/dist/sessions/index.d.ts.map +1 -1
  77. package/dist/sessions/index.js +2 -6
  78. package/dist/sessions/index.js.map +1 -1
  79. package/dist/store/brain-sqlite.js +13 -62
  80. package/dist/store/brain-sqlite.js.map +1 -1
  81. package/dist/store/migration-manager.js +151 -0
  82. package/dist/store/migration-manager.js.map +1 -0
  83. package/dist/store/sqlite.d.ts.map +1 -1
  84. package/dist/store/sqlite.js +16 -134
  85. package/dist/store/sqlite.js.map +1 -1
  86. package/dist/tasks/add.js +27 -22
  87. package/dist/tasks/add.js.map +1 -1
  88. package/dist/tasks/complete.d.ts.map +1 -1
  89. package/dist/tasks/complete.js +13 -40
  90. package/dist/tasks/complete.js.map +1 -1
  91. package/dist/tasks/enforcement.js +12 -15
  92. package/dist/tasks/enforcement.js.map +1 -1
  93. package/dist/upgrade.js +246 -3
  94. package/dist/upgrade.js.map +1 -1
  95. package/migrations/drizzle-tasks/20260320013731_wave0-schema-hardening/migration.sql +17 -17
  96. package/package.json +6 -5
  97. package/src/agents/retry.ts +30 -24
  98. package/src/cleo.ts +30 -251
  99. package/src/config.ts +18 -0
  100. package/src/hooks/handlers/file-hooks.ts +29 -3
  101. package/src/hooks/handlers/index.ts +2 -0
  102. package/src/hooks/handlers/mcp-hooks.ts +32 -13
  103. package/src/hooks/handlers/memory-bridge-refresh.ts +47 -0
  104. package/src/hooks/handlers/session-hooks.ts +38 -0
  105. package/src/hooks/handlers/task-hooks.ts +8 -0
  106. package/src/hooks/handlers/work-capture-hooks.ts +184 -0
  107. package/src/index.ts +5 -0
  108. package/src/internal.ts +28 -2
  109. package/src/memory/__tests__/brain-automation.test.ts +941 -0
  110. package/src/memory/auto-extract.ts +40 -0
  111. package/src/memory/brain-embedding.ts +18 -0
  112. package/src/memory/brain-maintenance.ts +183 -0
  113. package/src/memory/brain-retrieval.ts +85 -7
  114. package/src/memory/embedding-local.ts +107 -0
  115. package/src/memory/embedding-queue.ts +304 -0
  116. package/src/memory/embedding-worker.ts +79 -0
  117. package/src/memory/memory-bridge.ts +101 -2
  118. package/src/memory/session-memory.ts +123 -0
  119. package/src/sessions/index.ts +2 -6
  120. package/src/store/__tests__/test-db-helper.js +14 -2
  121. package/src/store/__tests__/test-db-helper.ts +4 -1
  122. package/src/store/sqlite.ts +28 -0
  123. package/src/tasks/__tests__/complete-unblocks.test.ts +4 -1
  124. package/src/tasks/__tests__/complete.test.ts +18 -6
  125. package/src/tasks/__tests__/epic-enforcement.test.ts +4 -1
  126. package/src/tasks/__tests__/update.test.ts +4 -1
  127. package/src/tasks/complete.ts +8 -8
  128. package/templates/config.template.json +19 -0
  129. package/templates/global-config.template.json +19 -0
@@ -405,6 +405,27 @@ import type { RequiredColumn } from './migration-manager.js';
405
405
 
406
406
  const REQUIRED_TASK_COLUMNS: RequiredColumn[] = [{ name: 'pipeline_stage', ddl: 'text' }];
407
407
 
408
+ /**
409
+ * Required columns that MUST exist on the sessions table before the
410
+ * wave0-schema-hardening migration runs.
411
+ *
412
+ * The wave0 migration rebuilds the sessions table via:
413
+ * INSERT INTO __new_sessions(..., provider_id, stats_json, resume_count, grade_mode)
414
+ * SELECT ..., provider_id, stats_json, resume_count, grade_mode FROM sessions
415
+ *
416
+ * If an existing sessions table (created before these columns were added) is
417
+ * missing any of them, the SELECT fails with "no such column". ensureColumns()
418
+ * adds them as NULL-able columns before the migration runs, making the SELECT safe.
419
+ *
420
+ * @see https://github.com/anthropics/cleo/issues/83
421
+ */
422
+ const REQUIRED_SESSION_COLUMNS: RequiredColumn[] = [
423
+ { name: 'provider_id', ddl: 'text' },
424
+ { name: 'stats_json', ddl: 'text' },
425
+ { name: 'resume_count', ddl: 'integer' },
426
+ { name: 'grade_mode', ddl: 'integer' },
427
+ ];
428
+
408
429
  /**
409
430
  * Run drizzle migrations to create/update tables.
410
431
  *
@@ -426,6 +447,13 @@ function runMigrations(nativeDb: DatabaseSync, db: NodeSQLiteDatabase<typeof sch
426
447
  // Bootstrap baseline + reconcile stale journal entries
427
448
  reconcileJournal(nativeDb, migrationsFolder, 'tasks', 'sqlite');
428
449
 
450
+ // Pre-migration column safety: ensure sessions table has the columns that the
451
+ // wave0-schema-hardening migration SELECTs during its table rebuild. Without
452
+ // this, upgrading from a pre-wave0 DB fails with "no such column: provider_id".
453
+ // Must run BEFORE migrateWithRetry so the migration's INSERT...SELECT succeeds.
454
+ // @see https://github.com/anthropics/cleo/issues/83
455
+ ensureColumns(nativeDb, 'sessions', REQUIRED_SESSION_COLUMNS, 'sqlite');
456
+
429
457
  // Run pending migrations with SQLITE_BUSY retry
430
458
  migrateWithRetry(db, migrationsFolder);
431
459
 
@@ -23,7 +23,10 @@ describe('completeTask unblocked tasks', () => {
23
23
  await writeFile(
24
24
  join(env.cleoDir, 'config.json'),
25
25
  JSON.stringify({
26
- enforcement: { session: { requiredForMutate: false } },
26
+ enforcement: {
27
+ session: { requiredForMutate: false },
28
+ acceptance: { mode: 'off' },
29
+ },
27
30
  lifecycle: { mode: 'off' },
28
31
  verification: { enabled: false },
29
32
  }),
@@ -22,7 +22,10 @@ describe('completeTask', () => {
22
22
  // Pin CLEO_DIR so concurrent workers cannot contaminate path resolution
23
23
  process.env['CLEO_DIR'] = env.cleoDir;
24
24
  await writeConfig({
25
- enforcement: { session: { requiredForMutate: false } },
25
+ enforcement: {
26
+ session: { requiredForMutate: false },
27
+ acceptance: { mode: 'off' },
28
+ },
26
29
  lifecycle: { mode: 'off' },
27
30
  verification: { enabled: false },
28
31
  });
@@ -162,7 +165,10 @@ describe('completeTask', () => {
162
165
  type: 'task',
163
166
  },
164
167
  ]);
165
- await writeConfig({ verification: { enabled: true } });
168
+ await writeConfig({
169
+ enforcement: { acceptance: { mode: 'off' } },
170
+ verification: { enabled: true },
171
+ });
166
172
 
167
173
  await expect(completeTask({ taskId: 'T001' }, env.tempDir, accessor)).rejects.toThrow(
168
174
  'missing verification metadata',
@@ -180,9 +186,11 @@ describe('completeTask', () => {
180
186
  type: 'task',
181
187
  },
182
188
  ]);
183
- // Remove config.json so verification defaults to disabled (opt-in)
184
- const { rm } = await import('node:fs/promises');
185
- await rm(join(env.cleoDir, 'config.json'), { force: true });
189
+ // Write a config that only disables acceptance enforcement but no verification
190
+ // settings verifying that verification defaults to disabled (opt-in behavior).
191
+ await writeConfig({
192
+ enforcement: { acceptance: { mode: 'off' } },
193
+ });
186
194
 
187
195
  const result = await completeTask({ taskId: 'T001' }, env.tempDir, accessor);
188
196
  expect(result.task.status).toBe('done');
@@ -199,7 +207,10 @@ describe('completeTask', () => {
199
207
  type: 'task',
200
208
  },
201
209
  ]);
202
- await writeConfig({ verification: { enabled: false } });
210
+ await writeConfig({
211
+ enforcement: { acceptance: { mode: 'off' } },
212
+ verification: { enabled: false },
213
+ });
203
214
 
204
215
  const result = await completeTask({ taskId: 'T001' }, env.tempDir, accessor);
205
216
  expect(result.task.status).toBe('done');
@@ -228,6 +239,7 @@ describe('completeTask', () => {
228
239
  },
229
240
  ]);
230
241
  await writeConfig({
242
+ enforcement: { acceptance: { mode: 'off' } },
231
243
  verification: {
232
244
  enabled: true,
233
245
  requiredGates: ['implemented', 'testsPassed'],
@@ -12,7 +12,7 @@
12
12
  * @epic T056
13
13
  */
14
14
 
15
- import { writeFile } from 'node:fs/promises';
15
+ import { unlink, writeFile } from 'node:fs/promises';
16
16
  import { join } from 'node:path';
17
17
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
18
18
  import { createTestDb, type TestDbEnv } from '../../store/__tests__/test-db-helper.js';
@@ -80,6 +80,9 @@ describe('getLifecycleMode', () => {
80
80
  });
81
81
 
82
82
  it('returns strict by default when no config', async () => {
83
+ // Remove the config.json written by createTestDb() so getLifecycleMode
84
+ // sees no project config and falls back to the 'strict' default.
85
+ await unlink(join(env.cleoDir, 'config.json'));
83
86
  const mode = await getLifecycleMode(env.tempDir);
84
87
  expect(mode).toBe('strict');
85
88
  });
@@ -24,7 +24,10 @@ describe('updateTask', () => {
24
24
  await writeFile(
25
25
  join(env.cleoDir, 'config.json'),
26
26
  JSON.stringify({
27
- enforcement: { session: { requiredForMutate: false } },
27
+ enforcement: {
28
+ session: { requiredForMutate: false },
29
+ acceptance: { mode: 'off' },
30
+ },
28
31
  lifecycle: { mode: 'off' },
29
32
  verification: { enabled: false },
30
33
  }),
@@ -7,7 +7,7 @@
7
7
  import type { Task, TaskRef, VerificationGate } from '@cleocode/contracts';
8
8
  // safeAppendLog replaced by tx.appendLog inside transaction (T023)
9
9
  import { ExitCode } from '@cleocode/contracts';
10
- import { loadConfig } from '../config.js';
10
+ import { getRawConfigValue, loadConfig } from '../config.js';
11
11
  import { CleoError } from '../errors.js';
12
12
  import { requireActiveSession } from '../sessions/session-enforcement.js';
13
13
  import type { DataAccessor } from '../store/data-accessor.js';
@@ -69,7 +69,11 @@ async function loadCompletionEnforcement(cwd?: string): Promise<CompletionEnforc
69
69
  const acceptanceMode = acceptance?.mode ?? (isTest ? 'off' : 'block');
70
70
  const acceptanceRequiredForPriorities =
71
71
  acceptance?.requiredForPriorities ?? (isTest ? [] : ['critical', 'high', 'medium', 'low']);
72
- const verificationEnabled = verificationCfg?.enabled ?? !isTest;
72
+ // Use getRawConfigValue to read only the project-level config (no DEFAULTS cascade).
73
+ // This ensures the isTest fallback activates when verification.enabled is not explicitly set.
74
+ const rawVerificationEnabled = await getRawConfigValue('verification.enabled', cwd);
75
+ const verificationEnabled =
76
+ rawVerificationEnabled !== undefined ? (rawVerificationEnabled as boolean) : !isTest;
73
77
  const verificationRequiredGates =
74
78
  (verificationCfg?.requiredGates ?? []).filter(isVerificationGate).length > 0
75
79
  ? (verificationCfg?.requiredGates ?? []).filter(isVerificationGate)
@@ -278,12 +282,8 @@ export async function completeTask(
278
282
  }
279
283
  }
280
284
 
281
- // Regenerate .cleo/memory-bridge.md (best-effort, T5240)
282
- import('../memory/memory-bridge.js')
283
- .then(({ refreshMemoryBridge }) => refreshMemoryBridge(cwd ?? process.cwd()))
284
- .catch(() => {
285
- /* Memory bridge refresh is best-effort */
286
- });
285
+ // NOTE: Memory bridge refresh is now handled by the onToolComplete hook
286
+ // via memory-bridge-refresh.ts (T138). No direct call needed here.
287
287
 
288
288
  // Auto-extract memory from task completion (best-effort, T-audit)
289
289
  import('../memory/auto-extract.js')
@@ -106,5 +106,24 @@
106
106
 
107
107
  "retention": {
108
108
  "autoEndActiveAfterDays": 7
109
+ },
110
+
111
+ "brain": {
112
+ "autoCapture": true,
113
+ "captureFiles": false,
114
+ "captureMcp": false,
115
+ "captureWork": false,
116
+ "embedding": {
117
+ "enabled": true,
118
+ "provider": "local"
119
+ },
120
+ "memoryBridge": {
121
+ "autoRefresh": true,
122
+ "contextAware": true,
123
+ "maxTokens": 2000
124
+ },
125
+ "summarization": {
126
+ "enabled": true
127
+ }
109
128
  }
110
129
  }
@@ -36,5 +36,24 @@
36
36
  },
37
37
  "defaults": {
38
38
  "priority": "medium"
39
+ },
40
+
41
+ "brain": {
42
+ "autoCapture": true,
43
+ "captureFiles": false,
44
+ "captureMcp": false,
45
+ "captureWork": false,
46
+ "embedding": {
47
+ "enabled": true,
48
+ "provider": "local"
49
+ },
50
+ "memoryBridge": {
51
+ "autoRefresh": true,
52
+ "contextAware": true,
53
+ "maxTokens": 2000
54
+ },
55
+ "summarization": {
56
+ "enabled": true
57
+ }
39
58
  }
40
59
  }