@cleocode/core 2026.3.57 → 2026.3.59

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 (136) hide show
  1. package/dist/agents/agent-registry.d.ts +206 -0
  2. package/dist/agents/agent-registry.d.ts.map +1 -0
  3. package/dist/agents/agent-schema.d.ts.map +1 -1
  4. package/dist/agents/execution-learning.d.ts +223 -0
  5. package/dist/agents/execution-learning.d.ts.map +1 -0
  6. package/dist/agents/health-monitor.d.ts +161 -0
  7. package/dist/agents/health-monitor.d.ts.map +1 -0
  8. package/dist/agents/index.d.ts +4 -1
  9. package/dist/agents/index.d.ts.map +1 -1
  10. package/dist/agents/retry.d.ts +57 -4
  11. package/dist/agents/retry.d.ts.map +1 -1
  12. package/dist/backfill/index.d.ts +83 -0
  13. package/dist/backfill/index.d.ts.map +1 -0
  14. package/dist/bootstrap.d.ts +1 -1
  15. package/dist/config.d.ts +47 -0
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/index.d.ts +2 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +6985 -5068
  20. package/dist/index.js.map +4 -4
  21. package/dist/intelligence/adaptive-validation.d.ts +151 -0
  22. package/dist/intelligence/adaptive-validation.d.ts.map +1 -0
  23. package/dist/intelligence/impact.d.ts +34 -1
  24. package/dist/intelligence/impact.d.ts.map +1 -1
  25. package/dist/intelligence/index.d.ts +7 -2
  26. package/dist/intelligence/index.d.ts.map +1 -1
  27. package/dist/intelligence/types.d.ts +60 -0
  28. package/dist/intelligence/types.d.ts.map +1 -1
  29. package/dist/internal.d.ts +8 -4
  30. package/dist/internal.d.ts.map +1 -1
  31. package/dist/lib/index.d.ts +10 -0
  32. package/dist/lib/index.d.ts.map +1 -0
  33. package/dist/lib/retry.d.ts +128 -0
  34. package/dist/lib/retry.d.ts.map +1 -0
  35. package/dist/nexus/sharing/index.d.ts +48 -2
  36. package/dist/nexus/sharing/index.d.ts.map +1 -1
  37. package/dist/sessions/session-enforcement.d.ts.map +1 -1
  38. package/dist/stats/index.d.ts +1 -0
  39. package/dist/stats/index.d.ts.map +1 -1
  40. package/dist/stats/workflow-telemetry.d.ts +89 -0
  41. package/dist/stats/workflow-telemetry.d.ts.map +1 -0
  42. package/dist/store/brain-schema.d.ts.map +1 -1
  43. package/dist/store/converters.d.ts.map +1 -1
  44. package/dist/store/cross-db-cleanup.d.ts +93 -0
  45. package/dist/store/cross-db-cleanup.d.ts.map +1 -0
  46. package/dist/store/db-helpers.d.ts.map +1 -1
  47. package/dist/store/migration-sqlite.d.ts.map +1 -1
  48. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  49. package/dist/store/sqlite.d.ts.map +1 -1
  50. package/dist/store/task-store.d.ts.map +1 -1
  51. package/dist/store/tasks-schema.d.ts +18 -3
  52. package/dist/store/tasks-schema.d.ts.map +1 -1
  53. package/dist/store/validation-schemas.d.ts +32 -0
  54. package/dist/store/validation-schemas.d.ts.map +1 -1
  55. package/dist/tasks/add.d.ts +10 -1
  56. package/dist/tasks/add.d.ts.map +1 -1
  57. package/dist/tasks/complete.d.ts.map +1 -1
  58. package/dist/tasks/enforcement.d.ts +22 -0
  59. package/dist/tasks/enforcement.d.ts.map +1 -0
  60. package/dist/tasks/epic-enforcement.d.ts +199 -0
  61. package/dist/tasks/epic-enforcement.d.ts.map +1 -0
  62. package/dist/tasks/index.d.ts +1 -1
  63. package/dist/tasks/index.d.ts.map +1 -1
  64. package/dist/tasks/pipeline-stage.d.ts +181 -0
  65. package/dist/tasks/pipeline-stage.d.ts.map +1 -0
  66. package/dist/tasks/update.d.ts +2 -0
  67. package/dist/tasks/update.d.ts.map +1 -1
  68. package/migrations/drizzle-brain/20260321000001_t033-brain-indexes/migration.sql +12 -0
  69. package/migrations/drizzle-brain/20260321000001_t033-brain-indexes/snapshot.json +1232 -0
  70. package/migrations/drizzle-tasks/20260321000000_t033-connection-health/migration.sql +518 -0
  71. package/migrations/drizzle-tasks/20260321000000_t033-connection-health/snapshot.json +4312 -0
  72. package/migrations/drizzle-tasks/20260321000002_t060-pipeline-stage-binding/migration.sql +82 -0
  73. package/migrations/drizzle-tasks/20260321000002_t060-pipeline-stage-binding/snapshot.json +9 -0
  74. package/package.json +5 -5
  75. package/schemas/config.schema.json +37 -1547
  76. package/src/__tests__/sharing.test.ts +24 -0
  77. package/src/agents/__tests__/agent-registry.test.ts +351 -0
  78. package/src/agents/__tests__/execution-learning.test.ts +684 -0
  79. package/src/agents/__tests__/health-monitor.test.ts +332 -0
  80. package/src/agents/__tests__/registry.test.ts +30 -2
  81. package/src/agents/agent-registry.ts +394 -0
  82. package/src/agents/agent-schema.ts +5 -0
  83. package/src/agents/execution-learning.ts +675 -0
  84. package/src/agents/health-monitor.ts +279 -0
  85. package/src/agents/index.ts +37 -1
  86. package/src/agents/retry.ts +57 -4
  87. package/src/backfill/index.ts +309 -0
  88. package/src/bootstrap.ts +1 -1
  89. package/src/config.ts +126 -0
  90. package/src/index.ts +8 -1
  91. package/src/intelligence/__tests__/adaptive-validation.test.ts +694 -0
  92. package/src/intelligence/__tests__/impact.test.ts +165 -1
  93. package/src/intelligence/adaptive-validation.ts +764 -0
  94. package/src/intelligence/impact.ts +203 -0
  95. package/src/intelligence/index.ts +19 -0
  96. package/src/intelligence/types.ts +76 -0
  97. package/src/internal.ts +39 -0
  98. package/src/lib/__tests__/retry.test.ts +321 -0
  99. package/src/lib/index.ts +16 -0
  100. package/src/lib/retry.ts +224 -0
  101. package/src/lifecycle/__tests__/chain-store.test.ts +7 -0
  102. package/src/lifecycle/__tests__/tessera-engine.test.ts +52 -0
  103. package/src/nexus/sharing/index.ts +142 -2
  104. package/src/sessions/__tests__/session-edge-cases.test.ts +24 -1
  105. package/src/sessions/session-enforcement.ts +13 -2
  106. package/src/stats/index.ts +7 -0
  107. package/src/stats/workflow-telemetry.ts +502 -0
  108. package/src/store/__tests__/migration-safety.test.ts +3 -0
  109. package/src/store/__tests__/session-store.test.ts +132 -1
  110. package/src/store/__tests__/task-store.test.ts +22 -1
  111. package/src/store/__tests__/test-db-helper.ts +29 -2
  112. package/src/store/brain-schema.ts +4 -1
  113. package/src/store/converters.ts +2 -0
  114. package/src/store/cross-db-cleanup.ts +192 -0
  115. package/src/store/db-helpers.ts +2 -0
  116. package/src/store/migration-sqlite.ts +6 -0
  117. package/src/store/sqlite-data-accessor.ts +20 -28
  118. package/src/store/sqlite.ts +14 -2
  119. package/src/store/task-store.ts +6 -0
  120. package/src/store/tasks-schema.ts +59 -20
  121. package/src/tasks/__tests__/add.test.ts +16 -0
  122. package/src/tasks/__tests__/complete-unblocks.test.ts +10 -1
  123. package/src/tasks/__tests__/complete.test.ts +11 -2
  124. package/src/tasks/__tests__/epic-enforcement.test.ts +909 -0
  125. package/src/tasks/__tests__/minimal-test.test.ts +28 -0
  126. package/src/tasks/__tests__/pipeline-stage.test.ts +403 -0
  127. package/src/tasks/__tests__/update.test.ts +40 -6
  128. package/src/tasks/add.ts +128 -2
  129. package/src/tasks/complete.ts +29 -17
  130. package/src/tasks/enforcement.ts +127 -0
  131. package/src/tasks/epic-enforcement.ts +364 -0
  132. package/src/tasks/index.ts +1 -0
  133. package/src/tasks/pipeline-stage.ts +293 -0
  134. package/src/tasks/update.ts +62 -0
  135. package/templates/config.template.json +34 -111
  136. package/templates/global-config.template.json +24 -40
@@ -8,13 +8,19 @@
8
8
  * - Blast radius calculation
9
9
  * - Critical path detection
10
10
  * - Edge cases (orphan tasks, circular refs, no deps)
11
+ * - predictImpact: free-text change description matching (T043)
11
12
  *
12
13
  * @module intelligence
13
14
  */
14
15
 
15
16
  import type { DataAccessor, Task } from '@cleocode/contracts';
16
17
  import { describe, expect, it } from 'vitest';
17
- import { analyzeChangeImpact, analyzeTaskImpact, calculateBlastRadius } from '../impact.js';
18
+ import {
19
+ analyzeChangeImpact,
20
+ analyzeTaskImpact,
21
+ calculateBlastRadius,
22
+ predictImpact,
23
+ } from '../impact.js';
18
24
 
19
25
  // ============================================================================
20
26
  // Test Helpers
@@ -451,3 +457,161 @@ describe('calculateBlastRadius', () => {
451
457
  expect(result.transitiveCount).toBe(2);
452
458
  });
453
459
  });
460
+
461
+ // ============================================================================
462
+ // predictImpact (T043)
463
+ // ============================================================================
464
+
465
+ describe('predictImpact', () => {
466
+ it('returns empty report when no tasks match the change description', async () => {
467
+ const tasks = [
468
+ makeTask({ id: 'T001', title: 'Set up CI pipeline', description: 'Configure CI runner' }),
469
+ makeTask({ id: 'T002', title: 'Write unit tests', description: 'Add test coverage' }),
470
+ ];
471
+ const acc = mockAccessor(tasks);
472
+
473
+ const result = await predictImpact('authentication login oauth', undefined, acc);
474
+
475
+ expect(result.change).toBe('authentication login oauth');
476
+ expect(result.matchedTasks).toHaveLength(0);
477
+ expect(result.affectedTasks).toHaveLength(0);
478
+ expect(result.totalAffected).toBe(0);
479
+ expect(result.summary).toContain('No tasks matched');
480
+ });
481
+
482
+ it('returns direct match when task title contains change keywords', async () => {
483
+ const tasks = [
484
+ makeTask({
485
+ id: 'T001',
486
+ title: 'Implement authentication module',
487
+ description: 'Add JWT auth',
488
+ }),
489
+ makeTask({ id: 'T002', title: 'Set up database schema', description: 'Create tables' }),
490
+ ];
491
+ const acc = mockAccessor(tasks);
492
+
493
+ const result = await predictImpact('authentication module', undefined, acc);
494
+
495
+ expect(result.matchedTasks).toHaveLength(1);
496
+ expect(result.matchedTasks[0]?.id).toBe('T001');
497
+ expect(result.matchedTasks[0]?.exposure).toBe('direct');
498
+ expect(result.totalAffected).toBe(1);
499
+ });
500
+
501
+ it('traces downstream dependents from matched seed tasks', async () => {
502
+ const tasks = [
503
+ makeTask({ id: 'T001', title: 'authentication service implementation', description: '' }),
504
+ makeTask({
505
+ id: 'T002',
506
+ title: 'User login form',
507
+ description: 'Depends on auth service',
508
+ depends: ['T001'],
509
+ }),
510
+ makeTask({
511
+ id: 'T003',
512
+ title: 'Dashboard access control',
513
+ description: 'Requires user login',
514
+ depends: ['T002'],
515
+ }),
516
+ makeTask({
517
+ id: 'T004',
518
+ title: 'Unrelated database migration',
519
+ description: 'Schema changes',
520
+ }),
521
+ ];
522
+ const acc = mockAccessor(tasks);
523
+
524
+ const result = await predictImpact('authentication service', undefined, acc);
525
+
526
+ // T001 is the direct match (seed)
527
+ expect(result.matchedTasks.map((t) => t.id)).toContain('T001');
528
+
529
+ // T002 and T003 should be in affectedTasks as dependents/transitive
530
+ const ids = result.affectedTasks.map((t) => t.id);
531
+ expect(ids).toContain('T001');
532
+ expect(ids).toContain('T002');
533
+ expect(ids).toContain('T003');
534
+ // T004 is unrelated and should not appear
535
+ expect(ids).not.toContain('T004');
536
+ });
537
+
538
+ it('classifies exposure correctly: direct, dependent, transitive', async () => {
539
+ const tasks = [
540
+ makeTask({ id: 'T001', title: 'auth login service', description: '' }),
541
+ makeTask({ id: 'T002', title: 'Session management', description: '', depends: ['T001'] }),
542
+ makeTask({ id: 'T003', title: 'Profile page', description: '', depends: ['T002'] }),
543
+ ];
544
+ const acc = mockAccessor(tasks);
545
+
546
+ const result = await predictImpact('auth login', undefined, acc);
547
+
548
+ const t1 = result.affectedTasks.find((t) => t.id === 'T001');
549
+ const t2 = result.affectedTasks.find((t) => t.id === 'T002');
550
+ const t3 = result.affectedTasks.find((t) => t.id === 'T003');
551
+
552
+ expect(t1?.exposure).toBe('direct');
553
+ expect(t2?.exposure).toBe('dependent');
554
+ expect(t3?.exposure).toBe('transitive');
555
+ });
556
+
557
+ it('sorts affectedTasks: direct first, then dependent, then transitive', async () => {
558
+ const tasks = [
559
+ makeTask({ id: 'T001', title: 'auth service core', description: '' }),
560
+ makeTask({ id: 'T002', title: 'Login controller', description: '', depends: ['T001'] }),
561
+ makeTask({ id: 'T003', title: 'Session store', description: '', depends: ['T002'] }),
562
+ ];
563
+ const acc = mockAccessor(tasks);
564
+
565
+ const result = await predictImpact('auth service', undefined, acc);
566
+
567
+ const exposures = result.affectedTasks.map((t) => t.exposure);
568
+ // direct must come before dependent which must come before transitive
569
+ const directIdx = exposures.indexOf('direct');
570
+ const dependentIdx = exposures.indexOf('dependent');
571
+ const transitiveIdx = exposures.indexOf('transitive');
572
+
573
+ if (directIdx !== -1 && dependentIdx !== -1) {
574
+ expect(directIdx).toBeLessThan(dependentIdx);
575
+ }
576
+ if (dependentIdx !== -1 && transitiveIdx !== -1) {
577
+ expect(dependentIdx).toBeLessThan(transitiveIdx);
578
+ }
579
+ });
580
+
581
+ it('respects matchLimit parameter', async () => {
582
+ const tasks = [
583
+ makeTask({ id: 'T001', title: 'auth module setup', description: '' }),
584
+ makeTask({ id: 'T002', title: 'auth token generation', description: '' }),
585
+ makeTask({ id: 'T003', title: 'auth session management', description: '' }),
586
+ ];
587
+ const acc = mockAccessor(tasks);
588
+
589
+ // Limit to 1 seed
590
+ const result = await predictImpact('auth', undefined, acc, 1);
591
+
592
+ // Only 1 direct match seeded
593
+ expect(result.matchedTasks).toHaveLength(1);
594
+ });
595
+
596
+ it('produces a meaningful summary string', async () => {
597
+ const tasks = [
598
+ makeTask({ id: 'T001', title: 'auth service', description: '' }),
599
+ makeTask({ id: 'T002', title: 'Login page', description: '', depends: ['T001'] }),
600
+ ];
601
+ const acc = mockAccessor(tasks);
602
+
603
+ const result = await predictImpact('auth service', undefined, acc);
604
+
605
+ expect(result.summary).toContain('auth service');
606
+ expect(result.summary).toMatch(/\d+ task/);
607
+ });
608
+
609
+ it('downstreamCount is 0 for leaf tasks with no dependents', async () => {
610
+ const tasks = [makeTask({ id: 'T001', title: 'auth service core', description: '' })];
611
+ const acc = mockAccessor(tasks);
612
+
613
+ const result = await predictImpact('auth service', undefined, acc);
614
+
615
+ expect(result.affectedTasks[0]?.downstreamCount).toBe(0);
616
+ });
617
+ });