cognitive-core 0.0.1 → 0.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/README.md +363 -2
- package/SKILL.md +193 -0
- package/dist/agents/index.d.ts +3 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +5 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/mock-provider.d.ts +23 -0
- package/dist/agents/mock-provider.d.ts.map +1 -0
- package/dist/agents/mock-provider.js +71 -0
- package/dist/agents/mock-provider.js.map +1 -0
- package/dist/agents/types.d.ts +98 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +44 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/atlas.d.ts +196 -0
- package/dist/atlas.d.ts.map +1 -0
- package/dist/atlas.js +373 -0
- package/dist/atlas.js.map +1 -0
- package/dist/bin/cognitive-core.d.ts +18 -0
- package/dist/bin/cognitive-core.d.ts.map +1 -0
- package/dist/bin/cognitive-core.js +419 -0
- package/dist/bin/cognitive-core.js.map +1 -0
- package/dist/embeddings/bm25.d.ts +104 -0
- package/dist/embeddings/bm25.d.ts.map +1 -0
- package/dist/embeddings/bm25.js +264 -0
- package/dist/embeddings/bm25.js.map +1 -0
- package/dist/embeddings/index.d.ts +12 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +16 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/manager.d.ts +112 -0
- package/dist/embeddings/manager.d.ts.map +1 -0
- package/dist/embeddings/manager.js +215 -0
- package/dist/embeddings/manager.js.map +1 -0
- package/dist/embeddings/provider.d.ts +101 -0
- package/dist/embeddings/provider.d.ts.map +1 -0
- package/dist/embeddings/provider.js +232 -0
- package/dist/embeddings/provider.js.map +1 -0
- package/dist/embeddings/vector-store.d.ts +101 -0
- package/dist/embeddings/vector-store.d.ts.map +1 -0
- package/dist/embeddings/vector-store.js +256 -0
- package/dist/embeddings/vector-store.js.map +1 -0
- package/dist/factory.d.ts +193 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +109 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/learning/analyzer.d.ts +110 -0
- package/dist/learning/analyzer.d.ts.map +1 -0
- package/dist/learning/analyzer.js +213 -0
- package/dist/learning/analyzer.js.map +1 -0
- package/dist/learning/effectiveness.d.ts +158 -0
- package/dist/learning/effectiveness.d.ts.map +1 -0
- package/dist/learning/effectiveness.js +251 -0
- package/dist/learning/effectiveness.js.map +1 -0
- package/dist/learning/index.d.ts +8 -0
- package/dist/learning/index.d.ts.map +1 -0
- package/dist/learning/index.js +11 -0
- package/dist/learning/index.js.map +1 -0
- package/dist/learning/llm-extractor.d.ts +88 -0
- package/dist/learning/llm-extractor.d.ts.map +1 -0
- package/dist/learning/llm-extractor.js +372 -0
- package/dist/learning/llm-extractor.js.map +1 -0
- package/dist/learning/meta-learner.d.ts +80 -0
- package/dist/learning/meta-learner.d.ts.map +1 -0
- package/dist/learning/meta-learner.js +355 -0
- package/dist/learning/meta-learner.js.map +1 -0
- package/dist/learning/pipeline.d.ts +65 -0
- package/dist/learning/pipeline.d.ts.map +1 -0
- package/dist/learning/pipeline.js +170 -0
- package/dist/learning/pipeline.js.map +1 -0
- package/dist/learning/playbook-extractor.d.ts +113 -0
- package/dist/learning/playbook-extractor.d.ts.map +1 -0
- package/dist/learning/playbook-extractor.js +523 -0
- package/dist/learning/playbook-extractor.js.map +1 -0
- package/dist/learning/usage-inference.d.ts +82 -0
- package/dist/learning/usage-inference.d.ts.map +1 -0
- package/dist/learning/usage-inference.js +261 -0
- package/dist/learning/usage-inference.js.map +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +6 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/playbook-server.d.ts +120 -0
- package/dist/mcp/playbook-server.d.ts.map +1 -0
- package/dist/mcp/playbook-server.js +427 -0
- package/dist/mcp/playbook-server.js.map +1 -0
- package/dist/memory/curated-loader.d.ts +62 -0
- package/dist/memory/curated-loader.d.ts.map +1 -0
- package/dist/memory/curated-loader.js +106 -0
- package/dist/memory/curated-loader.js.map +1 -0
- package/dist/memory/experience.d.ts +122 -0
- package/dist/memory/experience.d.ts.map +1 -0
- package/dist/memory/experience.js +392 -0
- package/dist/memory/experience.js.map +1 -0
- package/dist/memory/index.d.ts +6 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/meta.d.ts +90 -0
- package/dist/memory/meta.d.ts.map +1 -0
- package/dist/memory/meta.js +362 -0
- package/dist/memory/meta.js.map +1 -0
- package/dist/memory/playbook.d.ts +133 -0
- package/dist/memory/playbook.d.ts.map +1 -0
- package/dist/memory/playbook.js +357 -0
- package/dist/memory/playbook.js.map +1 -0
- package/dist/memory/system.d.ts +167 -0
- package/dist/memory/system.d.ts.map +1 -0
- package/dist/memory/system.js +383 -0
- package/dist/memory/system.js.map +1 -0
- package/dist/runtime/backends/acp.d.ts +67 -0
- package/dist/runtime/backends/acp.d.ts.map +1 -0
- package/dist/runtime/backends/acp.js +290 -0
- package/dist/runtime/backends/acp.js.map +1 -0
- package/dist/runtime/backends/index.d.ts +5 -0
- package/dist/runtime/backends/index.d.ts.map +1 -0
- package/dist/runtime/backends/index.js +6 -0
- package/dist/runtime/backends/index.js.map +1 -0
- package/dist/runtime/backends/mock.d.ts +67 -0
- package/dist/runtime/backends/mock.d.ts.map +1 -0
- package/dist/runtime/backends/mock.js +153 -0
- package/dist/runtime/backends/mock.js.map +1 -0
- package/dist/runtime/backends/subprocess.d.ts +56 -0
- package/dist/runtime/backends/subprocess.d.ts.map +1 -0
- package/dist/runtime/backends/subprocess.js +260 -0
- package/dist/runtime/backends/subprocess.js.map +1 -0
- package/dist/runtime/flows/learning.d.ts +73 -0
- package/dist/runtime/flows/learning.d.ts.map +1 -0
- package/dist/runtime/flows/learning.js +116 -0
- package/dist/runtime/flows/learning.js.map +1 -0
- package/dist/runtime/flows/validation.d.ts +122 -0
- package/dist/runtime/flows/validation.d.ts.map +1 -0
- package/dist/runtime/flows/validation.js +223 -0
- package/dist/runtime/flows/validation.js.map +1 -0
- package/dist/runtime/index.d.ts +6 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/manager.d.ts +116 -0
- package/dist/runtime/manager.d.ts.map +1 -0
- package/dist/runtime/manager.js +416 -0
- package/dist/runtime/manager.js.map +1 -0
- package/dist/runtime/types.d.ts +138 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/search/evaluator.d.ts +102 -0
- package/dist/search/evaluator.d.ts.map +1 -0
- package/dist/search/evaluator.js +352 -0
- package/dist/search/evaluator.js.map +1 -0
- package/dist/search/index.d.ts +7 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +11 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/refinement-loop.d.ts +73 -0
- package/dist/search/refinement-loop.d.ts.map +1 -0
- package/dist/search/refinement-loop.js +245 -0
- package/dist/search/refinement-loop.js.map +1 -0
- package/dist/search/refinement-types.d.ts +154 -0
- package/dist/search/refinement-types.d.ts.map +1 -0
- package/dist/search/refinement-types.js +99 -0
- package/dist/search/refinement-types.js.map +1 -0
- package/dist/search/router.d.ts +61 -0
- package/dist/search/router.d.ts.map +1 -0
- package/dist/search/router.js +197 -0
- package/dist/search/router.js.map +1 -0
- package/dist/search/solver.d.ts +75 -0
- package/dist/search/solver.d.ts.map +1 -0
- package/dist/search/solver.js +216 -0
- package/dist/search/solver.js.map +1 -0
- package/dist/search/verification-runner.d.ts +125 -0
- package/dist/search/verification-runner.d.ts.map +1 -0
- package/dist/search/verification-runner.js +440 -0
- package/dist/search/verification-runner.js.map +1 -0
- package/dist/surfacing/index.d.ts +2 -0
- package/dist/surfacing/index.d.ts.map +1 -0
- package/dist/surfacing/index.js +2 -0
- package/dist/surfacing/index.js.map +1 -0
- package/dist/surfacing/skill-library.d.ts +158 -0
- package/dist/surfacing/skill-library.d.ts.map +1 -0
- package/dist/surfacing/skill-library.js +429 -0
- package/dist/surfacing/skill-library.js.map +1 -0
- package/dist/types/config.d.ts +1113 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +274 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +14 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/memory.d.ts +339 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/memory.js +207 -0
- package/dist/types/memory.js.map +1 -0
- package/dist/types/meta.d.ts +146 -0
- package/dist/types/meta.d.ts.map +1 -0
- package/dist/types/meta.js +51 -0
- package/dist/types/meta.js.map +1 -0
- package/dist/types/outcome.d.ts +42 -0
- package/dist/types/outcome.d.ts.map +1 -0
- package/dist/types/outcome.js +50 -0
- package/dist/types/outcome.js.map +1 -0
- package/dist/types/playbook.d.ts +119 -0
- package/dist/types/playbook.d.ts.map +1 -0
- package/dist/types/playbook.js +71 -0
- package/dist/types/playbook.js.map +1 -0
- package/dist/types/step.d.ts +44 -0
- package/dist/types/step.d.ts.map +1 -0
- package/dist/types/step.js +32 -0
- package/dist/types/step.js.map +1 -0
- package/dist/types/task.d.ts +91 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +39 -0
- package/dist/types/task.js.map +1 -0
- package/dist/types/trajectory.d.ts +221 -0
- package/dist/types/trajectory.d.ts.map +1 -0
- package/dist/types/trajectory.js +60 -0
- package/dist/types/trajectory.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/similarity.d.ts +31 -0
- package/dist/utils/similarity.d.ts.map +1 -0
- package/dist/utils/similarity.js +107 -0
- package/dist/utils/similarity.js.map +1 -0
- package/dist/utils/storage.d.ts +106 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/storage.js +203 -0
- package/dist/utils/storage.js.map +1 -0
- package/dist/utils/validation.d.ts +129 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +171 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +61 -9
- package/scripts/migrate-to-playbooks.ts +307 -0
- package/src/agents/index.ts +14 -0
- package/src/agents/mock-provider.ts +93 -0
- package/src/agents/types.ts +137 -0
- package/src/atlas.ts +560 -0
- package/src/bin/cognitive-core.ts +470 -0
- package/src/embeddings/bm25.ts +337 -0
- package/src/embeddings/index.ts +39 -0
- package/src/embeddings/manager.ts +288 -0
- package/src/embeddings/provider.ts +311 -0
- package/src/embeddings/vector-store.ts +353 -0
- package/src/factory.ts +263 -0
- package/src/index.ts +246 -0
- package/src/learning/analyzer.ts +335 -0
- package/src/learning/effectiveness.ts +428 -0
- package/src/learning/index.ts +58 -0
- package/src/learning/llm-extractor.ts +542 -0
- package/src/learning/meta-learner.ts +516 -0
- package/src/learning/pipeline.ts +244 -0
- package/src/learning/playbook-extractor.ts +702 -0
- package/src/learning/usage-inference.ts +372 -0
- package/src/mcp/index.ts +12 -0
- package/src/mcp/playbook-server.ts +565 -0
- package/src/memory/curated-loader.ts +160 -0
- package/src/memory/experience.ts +515 -0
- package/src/memory/index.ts +27 -0
- package/src/memory/meta.ts +506 -0
- package/src/memory/playbook.ts +493 -0
- package/src/memory/system.ts +551 -0
- package/src/runtime/backends/acp.ts +378 -0
- package/src/runtime/backends/index.ts +24 -0
- package/src/runtime/backends/mock.ts +218 -0
- package/src/runtime/backends/subprocess.ts +356 -0
- package/src/runtime/flows/learning.ts +183 -0
- package/src/runtime/flows/validation.ts +381 -0
- package/src/runtime/index.ts +53 -0
- package/src/runtime/manager.ts +541 -0
- package/src/runtime/types.ts +157 -0
- package/src/search/evaluator.ts +474 -0
- package/src/search/index.ts +59 -0
- package/src/search/refinement-loop.ts +363 -0
- package/src/search/refinement-types.ts +159 -0
- package/src/search/router.ts +261 -0
- package/src/search/solver.ts +303 -0
- package/src/search/verification-runner.ts +570 -0
- package/src/surfacing/index.ts +6 -0
- package/src/surfacing/skill-library.ts +594 -0
- package/src/types/config.ts +333 -0
- package/src/types/index.ts +130 -0
- package/src/types/memory.ts +270 -0
- package/src/types/meta.ts +218 -0
- package/src/types/outcome.ts +66 -0
- package/src/types/playbook.ts +196 -0
- package/src/types/step.ts +40 -0
- package/src/types/task.ts +52 -0
- package/src/types/trajectory.ts +80 -0
- package/src/utils/index.ts +38 -0
- package/src/utils/similarity.ts +139 -0
- package/src/utils/storage.ts +249 -0
- package/src/utils/validation.ts +286 -0
- package/tests/embeddings/bm25.test.ts +130 -0
- package/tests/embeddings/manager.test.ts +205 -0
- package/tests/integration/atlas.test.ts +266 -0
- package/tests/integration/e2e.test.ts +929 -0
- package/tests/learning/analyzer.test.ts +426 -0
- package/tests/learning/effectiveness.test.ts +542 -0
- package/tests/learning/pipeline.test.ts +176 -0
- package/tests/learning/playbook-extractor-provenance.test.ts +114 -0
- package/tests/learning/usage-inference.test.ts +254 -0
- package/tests/mcp/playbook-server.test.ts +252 -0
- package/tests/memory/experience.test.ts +198 -0
- package/tests/memory/playbook.test.ts +338 -0
- package/tests/memory/provenance.test.ts +639 -0
- package/tests/memory/system.test.ts +325 -0
- package/tests/runtime/agent-manager.test.ts +512 -0
- package/tests/runtime/mock-backend.test.ts +248 -0
- package/tests/search/refinement-loop.test.ts +468 -0
- package/tests/search/refinement.test.ts +267 -0
- package/tests/search/router.test.ts +427 -0
- package/tests/surfacing/skill-library.test.ts +292 -0
- package/tests/types/outcome.test.ts +147 -0
- package/tests/types/step.test.ts +133 -0
- package/tests/types/task.test.ts +158 -0
- package/tests/types/trajectory.test.ts +253 -0
- package/tests/utils/similarity.test.ts +188 -0
- package/tests/utils/validation.test.ts +252 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +22 -0
- package/index.d.ts +0 -4
- package/index.js +0 -4
|
@@ -0,0 +1,929 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
Atlas,
|
|
4
|
+
createAtlas,
|
|
5
|
+
createAtlasWithAgents,
|
|
6
|
+
} from '../../src/atlas.js';
|
|
7
|
+
import { createTask } from '../../src/types/task.js';
|
|
8
|
+
import { createTrajectory } from '../../src/types/trajectory.js';
|
|
9
|
+
import { createStep } from '../../src/types/step.js';
|
|
10
|
+
import { successOutcome, failureOutcome } from '../../src/types/outcome.js';
|
|
11
|
+
import { MockBackend, createMockBackend } from '../../src/runtime/backends/mock.js';
|
|
12
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { tmpdir } from 'node:os';
|
|
15
|
+
|
|
16
|
+
describe('Integration: End-to-End Solve Flow', () => {
|
|
17
|
+
let tempDir: string;
|
|
18
|
+
let atlas: Atlas;
|
|
19
|
+
let mockBackend: MockBackend;
|
|
20
|
+
|
|
21
|
+
beforeEach(async () => {
|
|
22
|
+
tempDir = await mkdtemp(join(tmpdir(), 'atlas-e2e-test-'));
|
|
23
|
+
mockBackend = createMockBackend({
|
|
24
|
+
success: true,
|
|
25
|
+
result: 'Task completed successfully',
|
|
26
|
+
durationMs: 50,
|
|
27
|
+
toolCalls: [
|
|
28
|
+
{ name: 'read_file', input: { path: 'src/main.ts' }, output: 'code content' },
|
|
29
|
+
{ name: 'write_file', input: { path: 'src/main.ts', content: 'updated' }, output: 'written' },
|
|
30
|
+
],
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
atlas = createAtlasWithAgents([mockBackend], {
|
|
34
|
+
storage: { baseDir: tempDir },
|
|
35
|
+
learning: {
|
|
36
|
+
minTrajectories: 2,
|
|
37
|
+
deduplicationThreshold: 0.8,
|
|
38
|
+
},
|
|
39
|
+
execution: {
|
|
40
|
+
defaultAgentType: 'mock',
|
|
41
|
+
maxExecutionTime: 60,
|
|
42
|
+
captureToolCalls: true,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
await atlas.init();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
afterEach(async () => {
|
|
50
|
+
await atlas.close();
|
|
51
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('solve() with AgentManager', () => {
|
|
55
|
+
it('should solve a task and return trajectory', async () => {
|
|
56
|
+
const task = createTask({
|
|
57
|
+
domain: 'code',
|
|
58
|
+
description: 'Fix the bug in authentication module',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const result = await atlas.solve(task);
|
|
62
|
+
|
|
63
|
+
expect(result.trajectory).toBeDefined();
|
|
64
|
+
expect(result.trajectory.outcome.success).toBe(true);
|
|
65
|
+
expect(result.usedAgentManager).toBe(true);
|
|
66
|
+
expect(result.routing).toBeDefined();
|
|
67
|
+
expect(result.routing?.strategy).toBeDefined();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should inject playbooks when available', async () => {
|
|
71
|
+
// Add a playbook that should be injected
|
|
72
|
+
const memory = atlas.getMemory();
|
|
73
|
+
await memory.playbooks.add({
|
|
74
|
+
id: 'auth-playbook',
|
|
75
|
+
name: 'Authentication Bug Fix',
|
|
76
|
+
applicability: {
|
|
77
|
+
situations: ['Fix authentication bug', 'Auth module issue'],
|
|
78
|
+
triggers: ['authentication', 'auth', 'login'],
|
|
79
|
+
antiPatterns: [],
|
|
80
|
+
domains: ['code', 'auth'],
|
|
81
|
+
},
|
|
82
|
+
guidance: {
|
|
83
|
+
strategy: 'Check token validation and session management',
|
|
84
|
+
tactics: ['Verify token expiry', 'Check session storage'],
|
|
85
|
+
steps: ['Read auth code', 'Find issue', 'Apply fix', 'Test'],
|
|
86
|
+
},
|
|
87
|
+
verification: {
|
|
88
|
+
successIndicators: ['Tests pass', 'No auth errors'],
|
|
89
|
+
failureIndicators: ['Auth still fails'],
|
|
90
|
+
},
|
|
91
|
+
evolution: {
|
|
92
|
+
version: '1.0.0',
|
|
93
|
+
createdFrom: [],
|
|
94
|
+
failures: [],
|
|
95
|
+
refinements: [],
|
|
96
|
+
successCount: 5,
|
|
97
|
+
failureCount: 0,
|
|
98
|
+
},
|
|
99
|
+
confidence: 0.85,
|
|
100
|
+
complexity: 'moderate',
|
|
101
|
+
estimatedEffort: 2,
|
|
102
|
+
createdAt: new Date(),
|
|
103
|
+
updatedAt: new Date(),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Refresh skill library tiers
|
|
107
|
+
const skillLibrary = atlas.getSkillLibrary();
|
|
108
|
+
await skillLibrary?.refreshTiers();
|
|
109
|
+
|
|
110
|
+
const task = createTask({
|
|
111
|
+
domain: 'code',
|
|
112
|
+
description: 'Fix the authentication bug in login flow',
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const result = await atlas.solve(task);
|
|
116
|
+
|
|
117
|
+
expect(result.trajectory).toBeDefined();
|
|
118
|
+
// Playbooks should be tracked (may or may not be injected depending on scoring)
|
|
119
|
+
expect(result.injectedPlaybooks).toBeDefined();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should track memory context from router', async () => {
|
|
123
|
+
const task = createTask({
|
|
124
|
+
domain: 'code',
|
|
125
|
+
description: 'Implement new feature',
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const result = await atlas.solve(task);
|
|
129
|
+
|
|
130
|
+
expect(result.routing).toBeDefined();
|
|
131
|
+
expect(result.routing?.memoryContext).toBeDefined();
|
|
132
|
+
expect(result.routing?.confidence).toBeDefined();
|
|
133
|
+
expect(result.routing?.estimatedBudget).toBeDefined();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('should process trajectory for learning after solve', async () => {
|
|
137
|
+
const task = createTask({
|
|
138
|
+
domain: 'code',
|
|
139
|
+
description: 'Test learning integration',
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
await atlas.solve(task);
|
|
143
|
+
|
|
144
|
+
const stats = await atlas.getStats();
|
|
145
|
+
expect(stats.learning.trajectoriesProcessed).toBe(1);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should handle failed agent execution', async () => {
|
|
149
|
+
mockBackend.setDefaultBehavior({
|
|
150
|
+
success: false,
|
|
151
|
+
error: 'Agent execution failed',
|
|
152
|
+
result: 'Partial result before failure', // Provide result for experience creation
|
|
153
|
+
durationMs: 50,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const task = createTask({
|
|
157
|
+
domain: 'code',
|
|
158
|
+
description: 'Failing task',
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const result = await atlas.solve(task);
|
|
162
|
+
|
|
163
|
+
expect(result.trajectory.outcome.success).toBe(false);
|
|
164
|
+
expect(result.usedAgentManager).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe('solve() with multiple tasks', () => {
|
|
169
|
+
it('should solve batch of tasks', async () => {
|
|
170
|
+
const tasks = [
|
|
171
|
+
createTask({ domain: 'code', description: 'Task 1' }),
|
|
172
|
+
createTask({ domain: 'code', description: 'Task 2' }),
|
|
173
|
+
createTask({ domain: 'code', description: 'Task 3' }),
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
const results = await atlas.solveBatch(tasks);
|
|
177
|
+
|
|
178
|
+
expect(results.length).toBe(3);
|
|
179
|
+
results.forEach(result => {
|
|
180
|
+
expect(result.trajectory).toBeDefined();
|
|
181
|
+
expect(result.usedAgentManager).toBe(true);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const stats = await atlas.getStats();
|
|
185
|
+
expect(stats.learning.trajectoriesProcessed).toBe(3);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should accumulate learning across tasks', async () => {
|
|
189
|
+
// Solve multiple similar tasks
|
|
190
|
+
for (let i = 0; i < 3; i++) {
|
|
191
|
+
await atlas.solve(createTask({
|
|
192
|
+
domain: 'code',
|
|
193
|
+
description: `Fix TypeScript error ${i}`,
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const stats = await atlas.getStats();
|
|
198
|
+
expect(stats.learning.trajectoriesProcessed).toBe(3);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('Integration: Learning Pipeline Batch Extraction', () => {
|
|
204
|
+
let tempDir: string;
|
|
205
|
+
let atlas: Atlas;
|
|
206
|
+
let mockBackend: MockBackend;
|
|
207
|
+
|
|
208
|
+
beforeEach(async () => {
|
|
209
|
+
tempDir = await mkdtemp(join(tmpdir(), 'atlas-learning-test-'));
|
|
210
|
+
mockBackend = createMockBackend({
|
|
211
|
+
success: true,
|
|
212
|
+
result: 'Completed',
|
|
213
|
+
durationMs: 30,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
atlas = createAtlasWithAgents([mockBackend], {
|
|
217
|
+
storage: { baseDir: tempDir },
|
|
218
|
+
learning: {
|
|
219
|
+
minTrajectories: 3, // Low threshold for testing
|
|
220
|
+
deduplicationThreshold: 0.7,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
await atlas.init();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
afterEach(async () => {
|
|
228
|
+
await atlas.close();
|
|
229
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should accumulate trajectories until batch threshold', async () => {
|
|
233
|
+
// Process trajectories below threshold
|
|
234
|
+
for (let i = 0; i < 2; i++) {
|
|
235
|
+
const trajectory = createTrajectory({
|
|
236
|
+
id: `traj-${i}`,
|
|
237
|
+
task: createTask({ domain: 'code', description: `Task ${i}` }),
|
|
238
|
+
steps: [
|
|
239
|
+
createStep({ action: 'read', observation: 'content' }),
|
|
240
|
+
createStep({ action: 'write', observation: 'done' }),
|
|
241
|
+
],
|
|
242
|
+
outcome: successOutcome('Done'),
|
|
243
|
+
agentId: 'test-agent',
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
await atlas.processTrajectory(trajectory);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const stats = await atlas.getStats();
|
|
250
|
+
expect(stats.learning.trajectoriesProcessed).toBe(2);
|
|
251
|
+
expect(stats.learning.pendingTrajectories).toBe(2);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should trigger batch learning when threshold reached', async () => {
|
|
255
|
+
// Process trajectories to trigger batch
|
|
256
|
+
for (let i = 0; i < 4; i++) {
|
|
257
|
+
const trajectory = createTrajectory({
|
|
258
|
+
id: `batch-traj-${i}`,
|
|
259
|
+
task: createTask({
|
|
260
|
+
domain: 'code',
|
|
261
|
+
description: `Fix TypeScript error in module ${i}`,
|
|
262
|
+
}),
|
|
263
|
+
steps: [
|
|
264
|
+
createStep({
|
|
265
|
+
thought: 'Need to fix the type error',
|
|
266
|
+
action: 'Read the file with error',
|
|
267
|
+
observation: 'Found type mismatch',
|
|
268
|
+
}),
|
|
269
|
+
createStep({
|
|
270
|
+
thought: 'Applying the fix',
|
|
271
|
+
action: 'Update type annotation',
|
|
272
|
+
observation: 'Type error resolved',
|
|
273
|
+
}),
|
|
274
|
+
],
|
|
275
|
+
outcome: successOutcome('Fixed type error'),
|
|
276
|
+
agentId: 'test-agent',
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await atlas.processTrajectory(trajectory);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// After threshold, batch learning should have been triggered
|
|
283
|
+
const stats = await atlas.getStats();
|
|
284
|
+
expect(stats.learning.trajectoriesProcessed).toBe(4);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('should extract playbooks from similar trajectories', async () => {
|
|
288
|
+
// Create similar successful trajectories
|
|
289
|
+
const similarTasks = [
|
|
290
|
+
'Fix authentication token validation',
|
|
291
|
+
'Fix authentication session expiry',
|
|
292
|
+
'Fix authentication login flow',
|
|
293
|
+
];
|
|
294
|
+
|
|
295
|
+
for (let i = 0; i < similarTasks.length; i++) {
|
|
296
|
+
const trajectory = createTrajectory({
|
|
297
|
+
id: `auth-traj-${i}`,
|
|
298
|
+
task: createTask({
|
|
299
|
+
domain: 'auth',
|
|
300
|
+
description: similarTasks[i],
|
|
301
|
+
}),
|
|
302
|
+
steps: [
|
|
303
|
+
createStep({
|
|
304
|
+
thought: 'Check authentication code',
|
|
305
|
+
action: 'Read auth module',
|
|
306
|
+
observation: 'Found the issue',
|
|
307
|
+
}),
|
|
308
|
+
createStep({
|
|
309
|
+
thought: 'Apply fix',
|
|
310
|
+
action: 'Update auth logic',
|
|
311
|
+
observation: 'Fixed',
|
|
312
|
+
}),
|
|
313
|
+
createStep({
|
|
314
|
+
thought: 'Verify fix',
|
|
315
|
+
action: 'Run auth tests',
|
|
316
|
+
observation: 'All tests pass',
|
|
317
|
+
}),
|
|
318
|
+
],
|
|
319
|
+
outcome: successOutcome('Auth issue fixed'),
|
|
320
|
+
agentId: 'test-agent',
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
await atlas.processTrajectory(trajectory);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Force batch learning
|
|
327
|
+
const batchResult = await atlas.runBatchLearning();
|
|
328
|
+
expect(batchResult.trajectoriesProcessed).toBe(3);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('should run batch learning explicitly', async () => {
|
|
332
|
+
// Add a trajectory
|
|
333
|
+
const trajectory = createTrajectory({
|
|
334
|
+
task: createTask({ domain: 'test', description: 'Explicit batch test' }),
|
|
335
|
+
steps: [createStep({ action: 'test', observation: 'result' })],
|
|
336
|
+
outcome: successOutcome('Done'),
|
|
337
|
+
agentId: 'test',
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
await atlas.processTrajectory(trajectory);
|
|
341
|
+
|
|
342
|
+
// Explicitly run batch learning
|
|
343
|
+
const result = await atlas.runBatchLearning();
|
|
344
|
+
|
|
345
|
+
expect(result).toBeDefined();
|
|
346
|
+
expect(result.trajectoriesProcessed).toBeGreaterThanOrEqual(0);
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
describe('Integration: Skill Tier Promotion/Demotion', () => {
|
|
351
|
+
let tempDir: string;
|
|
352
|
+
let atlas: Atlas;
|
|
353
|
+
let mockBackend: MockBackend;
|
|
354
|
+
|
|
355
|
+
beforeEach(async () => {
|
|
356
|
+
tempDir = await mkdtemp(join(tmpdir(), 'atlas-tier-test-'));
|
|
357
|
+
mockBackend = createMockBackend({ success: true, durationMs: 30 });
|
|
358
|
+
|
|
359
|
+
atlas = createAtlasWithAgents([mockBackend], {
|
|
360
|
+
storage: { baseDir: tempDir },
|
|
361
|
+
skillLibrary: {
|
|
362
|
+
promotion: {
|
|
363
|
+
minConfidence: 0.8,
|
|
364
|
+
minSuccessCount: 3,
|
|
365
|
+
minSuccessRate: 0.7,
|
|
366
|
+
},
|
|
367
|
+
demotion: {
|
|
368
|
+
failureThreshold: 2,
|
|
369
|
+
minConfidenceToRetain: 0.5,
|
|
370
|
+
},
|
|
371
|
+
limits: {
|
|
372
|
+
maxCoreSkills: 5,
|
|
373
|
+
maxDomainSkills: 3,
|
|
374
|
+
maxContextualPlaybooks: 2,
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
await atlas.init();
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
afterEach(async () => {
|
|
383
|
+
await atlas.close();
|
|
384
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('should promote high-performing playbooks to core skills', async () => {
|
|
388
|
+
const memory = atlas.getMemory();
|
|
389
|
+
const skillLibrary = atlas.getSkillLibrary();
|
|
390
|
+
|
|
391
|
+
// Add a high-confidence, high-success playbook
|
|
392
|
+
await memory.playbooks.add({
|
|
393
|
+
id: 'promote-playbook',
|
|
394
|
+
name: 'High Performance Playbook',
|
|
395
|
+
applicability: {
|
|
396
|
+
situations: ['Common coding task'],
|
|
397
|
+
triggers: ['code', 'fix'],
|
|
398
|
+
antiPatterns: [],
|
|
399
|
+
domains: ['code'],
|
|
400
|
+
},
|
|
401
|
+
guidance: {
|
|
402
|
+
strategy: 'Proven approach',
|
|
403
|
+
tactics: ['Step 1', 'Step 2'],
|
|
404
|
+
},
|
|
405
|
+
verification: {
|
|
406
|
+
successIndicators: ['Works'],
|
|
407
|
+
failureIndicators: ['Fails'],
|
|
408
|
+
},
|
|
409
|
+
evolution: {
|
|
410
|
+
version: '1.0.0',
|
|
411
|
+
createdFrom: [],
|
|
412
|
+
failures: [],
|
|
413
|
+
refinements: [],
|
|
414
|
+
successCount: 10,
|
|
415
|
+
failureCount: 1,
|
|
416
|
+
},
|
|
417
|
+
confidence: 0.9,
|
|
418
|
+
complexity: 'simple',
|
|
419
|
+
estimatedEffort: 1,
|
|
420
|
+
createdAt: new Date(),
|
|
421
|
+
updatedAt: new Date(),
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// Refresh tiers
|
|
425
|
+
const tierResult = await skillLibrary?.refreshTiers();
|
|
426
|
+
|
|
427
|
+
expect(tierResult?.promoted).toBeDefined();
|
|
428
|
+
expect(tierResult?.coreCount).toBeGreaterThanOrEqual(0);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('should demote failing playbooks', async () => {
|
|
432
|
+
const memory = atlas.getMemory();
|
|
433
|
+
const skillLibrary = atlas.getSkillLibrary();
|
|
434
|
+
|
|
435
|
+
// Add a playbook that will be demoted
|
|
436
|
+
await memory.playbooks.add({
|
|
437
|
+
id: 'demote-playbook',
|
|
438
|
+
name: 'Failing Playbook',
|
|
439
|
+
applicability: {
|
|
440
|
+
situations: ['Edge case'],
|
|
441
|
+
triggers: ['rare'],
|
|
442
|
+
antiPatterns: [],
|
|
443
|
+
domains: ['test'],
|
|
444
|
+
},
|
|
445
|
+
guidance: {
|
|
446
|
+
strategy: 'Risky approach',
|
|
447
|
+
tactics: [],
|
|
448
|
+
},
|
|
449
|
+
verification: {
|
|
450
|
+
successIndicators: [],
|
|
451
|
+
failureIndicators: [],
|
|
452
|
+
},
|
|
453
|
+
evolution: {
|
|
454
|
+
version: '1.0.0',
|
|
455
|
+
createdFrom: [],
|
|
456
|
+
failures: [],
|
|
457
|
+
refinements: [],
|
|
458
|
+
successCount: 1,
|
|
459
|
+
failureCount: 5,
|
|
460
|
+
},
|
|
461
|
+
confidence: 0.3,
|
|
462
|
+
complexity: 'complex',
|
|
463
|
+
estimatedEffort: 5,
|
|
464
|
+
createdAt: new Date(),
|
|
465
|
+
updatedAt: new Date(),
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
await skillLibrary?.refreshTiers();
|
|
469
|
+
|
|
470
|
+
// Playbook with low success should not be in core
|
|
471
|
+
const coreSkills = skillLibrary?.getCoreSkills();
|
|
472
|
+
const isInCore = coreSkills?.some(s => s.id === 'demote-playbook');
|
|
473
|
+
expect(isInCore).toBe(false);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('should track consecutive failures for demotion', async () => {
|
|
477
|
+
const memory = atlas.getMemory();
|
|
478
|
+
const skillLibrary = atlas.getSkillLibrary();
|
|
479
|
+
|
|
480
|
+
// Add playbook and record failures
|
|
481
|
+
await memory.playbooks.add({
|
|
482
|
+
id: 'failure-track-playbook',
|
|
483
|
+
name: 'Track Failures',
|
|
484
|
+
applicability: {
|
|
485
|
+
situations: ['Test'],
|
|
486
|
+
triggers: ['test'],
|
|
487
|
+
antiPatterns: [],
|
|
488
|
+
domains: ['test'],
|
|
489
|
+
},
|
|
490
|
+
guidance: {
|
|
491
|
+
strategy: 'Test strategy',
|
|
492
|
+
tactics: [],
|
|
493
|
+
},
|
|
494
|
+
verification: {
|
|
495
|
+
successIndicators: [],
|
|
496
|
+
failureIndicators: [],
|
|
497
|
+
},
|
|
498
|
+
evolution: {
|
|
499
|
+
version: '1.0.0',
|
|
500
|
+
createdFrom: [],
|
|
501
|
+
failures: [],
|
|
502
|
+
refinements: [],
|
|
503
|
+
successCount: 5,
|
|
504
|
+
failureCount: 0,
|
|
505
|
+
},
|
|
506
|
+
confidence: 0.85,
|
|
507
|
+
complexity: 'simple',
|
|
508
|
+
estimatedEffort: 1,
|
|
509
|
+
createdAt: new Date(),
|
|
510
|
+
updatedAt: new Date(),
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
await skillLibrary?.refreshTiers();
|
|
514
|
+
|
|
515
|
+
// Record consecutive failures
|
|
516
|
+
await skillLibrary?.recordOutcome('failure-track-playbook', 'traj-1', false, 'First failure');
|
|
517
|
+
await skillLibrary?.recordOutcome('failure-track-playbook', 'traj-2', false, 'Second failure');
|
|
518
|
+
|
|
519
|
+
const failures = skillLibrary?.getConsecutiveFailures('failure-track-playbook');
|
|
520
|
+
expect(failures).toBe(2);
|
|
521
|
+
|
|
522
|
+
// Check at-risk playbooks
|
|
523
|
+
const atRisk = skillLibrary?.getAtRiskPlaybooks();
|
|
524
|
+
expect(atRisk).toBeDefined();
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
it('should reset failure count on success', async () => {
|
|
528
|
+
const memory = atlas.getMemory();
|
|
529
|
+
const skillLibrary = atlas.getSkillLibrary();
|
|
530
|
+
|
|
531
|
+
await memory.playbooks.add({
|
|
532
|
+
id: 'reset-playbook',
|
|
533
|
+
name: 'Reset Test',
|
|
534
|
+
applicability: {
|
|
535
|
+
situations: ['Test'],
|
|
536
|
+
triggers: ['test'],
|
|
537
|
+
antiPatterns: [],
|
|
538
|
+
domains: ['test'],
|
|
539
|
+
},
|
|
540
|
+
guidance: {
|
|
541
|
+
strategy: 'Test',
|
|
542
|
+
tactics: [],
|
|
543
|
+
},
|
|
544
|
+
verification: {
|
|
545
|
+
successIndicators: [],
|
|
546
|
+
failureIndicators: [],
|
|
547
|
+
},
|
|
548
|
+
evolution: {
|
|
549
|
+
version: '1.0.0',
|
|
550
|
+
createdFrom: [],
|
|
551
|
+
failures: [],
|
|
552
|
+
refinements: [],
|
|
553
|
+
successCount: 5,
|
|
554
|
+
failureCount: 0,
|
|
555
|
+
},
|
|
556
|
+
confidence: 0.85,
|
|
557
|
+
complexity: 'simple',
|
|
558
|
+
estimatedEffort: 1,
|
|
559
|
+
createdAt: new Date(),
|
|
560
|
+
updatedAt: new Date(),
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
await skillLibrary?.refreshTiers();
|
|
564
|
+
|
|
565
|
+
// Record failures then success
|
|
566
|
+
await skillLibrary?.recordOutcome('reset-playbook', 'traj-1', false);
|
|
567
|
+
await skillLibrary?.recordOutcome('reset-playbook', 'traj-2', false);
|
|
568
|
+
|
|
569
|
+
let failures = skillLibrary?.getConsecutiveFailures('reset-playbook');
|
|
570
|
+
expect(failures).toBe(2);
|
|
571
|
+
|
|
572
|
+
// Success should reset
|
|
573
|
+
await skillLibrary?.recordOutcome('reset-playbook', 'traj-3', true);
|
|
574
|
+
|
|
575
|
+
failures = skillLibrary?.getConsecutiveFailures('reset-playbook');
|
|
576
|
+
expect(failures).toBe(0);
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
it('should organize skills by domain', async () => {
|
|
580
|
+
const memory = atlas.getMemory();
|
|
581
|
+
const skillLibrary = atlas.getSkillLibrary();
|
|
582
|
+
|
|
583
|
+
// Add playbooks in different domains
|
|
584
|
+
const domains = ['frontend', 'backend', 'database'];
|
|
585
|
+
for (const domain of domains) {
|
|
586
|
+
await memory.playbooks.add({
|
|
587
|
+
id: `${domain}-playbook`,
|
|
588
|
+
name: `${domain} Playbook`,
|
|
589
|
+
applicability: {
|
|
590
|
+
situations: [`${domain} task`],
|
|
591
|
+
triggers: [domain],
|
|
592
|
+
antiPatterns: [],
|
|
593
|
+
domains: [domain],
|
|
594
|
+
},
|
|
595
|
+
guidance: {
|
|
596
|
+
strategy: `${domain} strategy`,
|
|
597
|
+
tactics: [],
|
|
598
|
+
},
|
|
599
|
+
verification: {
|
|
600
|
+
successIndicators: [],
|
|
601
|
+
failureIndicators: [],
|
|
602
|
+
},
|
|
603
|
+
evolution: {
|
|
604
|
+
version: '1.0.0',
|
|
605
|
+
createdFrom: [],
|
|
606
|
+
failures: [],
|
|
607
|
+
refinements: [],
|
|
608
|
+
successCount: 3,
|
|
609
|
+
failureCount: 1,
|
|
610
|
+
},
|
|
611
|
+
confidence: 0.7,
|
|
612
|
+
complexity: 'moderate',
|
|
613
|
+
estimatedEffort: 2,
|
|
614
|
+
createdAt: new Date(),
|
|
615
|
+
updatedAt: new Date(),
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
await skillLibrary?.refreshTiers();
|
|
620
|
+
|
|
621
|
+
const allDomains = skillLibrary?.getDomains();
|
|
622
|
+
expect(allDomains?.length).toBeGreaterThanOrEqual(0);
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
describe('Integration: Memory Persistence', () => {
|
|
627
|
+
let tempDir: string;
|
|
628
|
+
|
|
629
|
+
beforeEach(async () => {
|
|
630
|
+
tempDir = await mkdtemp(join(tmpdir(), 'atlas-persist-test-'));
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
afterEach(async () => {
|
|
634
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
it('should persist and restore memory across sessions', async () => {
|
|
638
|
+
// First session - add data
|
|
639
|
+
const atlas1 = createAtlasWithAgents([createMockBackend()], {
|
|
640
|
+
storage: { baseDir: tempDir },
|
|
641
|
+
});
|
|
642
|
+
await atlas1.init();
|
|
643
|
+
|
|
644
|
+
const memory1 = atlas1.getMemory();
|
|
645
|
+
await memory1.experiences.add({
|
|
646
|
+
id: 'persist-exp-1',
|
|
647
|
+
taskInput: 'Persistent experience',
|
|
648
|
+
solutionOutput: 'Solution persisted',
|
|
649
|
+
feedback: 'Good',
|
|
650
|
+
success: true,
|
|
651
|
+
domain: 'test',
|
|
652
|
+
trajectoryId: 'persist-traj-1',
|
|
653
|
+
usageCount: 0,
|
|
654
|
+
createdAt: new Date(),
|
|
655
|
+
metadata: {},
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
await memory1.playbooks.add({
|
|
659
|
+
id: 'persist-playbook-1',
|
|
660
|
+
name: 'Persistent Playbook',
|
|
661
|
+
applicability: {
|
|
662
|
+
situations: ['Test persistence'],
|
|
663
|
+
triggers: ['persist'],
|
|
664
|
+
antiPatterns: [],
|
|
665
|
+
domains: ['test'],
|
|
666
|
+
},
|
|
667
|
+
guidance: {
|
|
668
|
+
strategy: 'Persist this',
|
|
669
|
+
tactics: [],
|
|
670
|
+
},
|
|
671
|
+
verification: {
|
|
672
|
+
successIndicators: [],
|
|
673
|
+
failureIndicators: [],
|
|
674
|
+
},
|
|
675
|
+
evolution: {
|
|
676
|
+
version: '1.0.0',
|
|
677
|
+
createdFrom: [],
|
|
678
|
+
failures: [],
|
|
679
|
+
refinements: [],
|
|
680
|
+
successCount: 0,
|
|
681
|
+
failureCount: 0,
|
|
682
|
+
},
|
|
683
|
+
confidence: 0.7,
|
|
684
|
+
complexity: 'simple',
|
|
685
|
+
estimatedEffort: 1,
|
|
686
|
+
createdAt: new Date(),
|
|
687
|
+
updatedAt: new Date(),
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
await atlas1.close();
|
|
691
|
+
|
|
692
|
+
// Second session - verify data persisted
|
|
693
|
+
const atlas2 = createAtlasWithAgents([createMockBackend()], {
|
|
694
|
+
storage: { baseDir: tempDir },
|
|
695
|
+
});
|
|
696
|
+
await atlas2.init();
|
|
697
|
+
|
|
698
|
+
const stats = await atlas2.getStats();
|
|
699
|
+
expect(stats.memory.experienceCount).toBe(1);
|
|
700
|
+
expect(stats.memory.playbookCount).toBe(1);
|
|
701
|
+
|
|
702
|
+
const memory2 = atlas2.getMemory();
|
|
703
|
+
const exp = await memory2.experiences.get('persist-exp-1');
|
|
704
|
+
expect(exp?.taskInput).toBe('Persistent experience');
|
|
705
|
+
|
|
706
|
+
const playbook = await memory2.playbooks.get('persist-playbook-1');
|
|
707
|
+
expect(playbook?.name).toBe('Persistent Playbook');
|
|
708
|
+
|
|
709
|
+
await atlas2.close();
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
it('should persist skill library state', async () => {
|
|
713
|
+
// First session
|
|
714
|
+
const atlas1 = createAtlasWithAgents([createMockBackend()], {
|
|
715
|
+
storage: { baseDir: tempDir },
|
|
716
|
+
});
|
|
717
|
+
await atlas1.init();
|
|
718
|
+
|
|
719
|
+
const memory1 = atlas1.getMemory();
|
|
720
|
+
const skillLibrary1 = atlas1.getSkillLibrary();
|
|
721
|
+
|
|
722
|
+
// Add playbook and record outcomes
|
|
723
|
+
await memory1.playbooks.add({
|
|
724
|
+
id: 'skill-persist',
|
|
725
|
+
name: 'Skill Persist Test',
|
|
726
|
+
applicability: {
|
|
727
|
+
situations: ['Test'],
|
|
728
|
+
triggers: ['test'],
|
|
729
|
+
antiPatterns: [],
|
|
730
|
+
domains: ['test'],
|
|
731
|
+
},
|
|
732
|
+
guidance: {
|
|
733
|
+
strategy: 'Test',
|
|
734
|
+
tactics: [],
|
|
735
|
+
},
|
|
736
|
+
verification: {
|
|
737
|
+
successIndicators: [],
|
|
738
|
+
failureIndicators: [],
|
|
739
|
+
},
|
|
740
|
+
evolution: {
|
|
741
|
+
version: '1.0.0',
|
|
742
|
+
createdFrom: [],
|
|
743
|
+
failures: [],
|
|
744
|
+
refinements: [],
|
|
745
|
+
successCount: 5,
|
|
746
|
+
failureCount: 0,
|
|
747
|
+
},
|
|
748
|
+
confidence: 0.85,
|
|
749
|
+
complexity: 'simple',
|
|
750
|
+
estimatedEffort: 1,
|
|
751
|
+
createdAt: new Date(),
|
|
752
|
+
updatedAt: new Date(),
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
await skillLibrary1?.refreshTiers();
|
|
756
|
+
|
|
757
|
+
// Record failures
|
|
758
|
+
await skillLibrary1?.recordOutcome('skill-persist', 'traj-1', false);
|
|
759
|
+
await skillLibrary1?.recordOutcome('skill-persist', 'traj-2', false);
|
|
760
|
+
|
|
761
|
+
// Export failure state for verification
|
|
762
|
+
const failureState = skillLibrary1?.exportFailureState();
|
|
763
|
+
expect(failureState?.['skill-persist']).toBe(2);
|
|
764
|
+
|
|
765
|
+
await atlas1.close();
|
|
766
|
+
|
|
767
|
+
// Note: Failure state is in-memory only, but playbook state persists
|
|
768
|
+
const atlas2 = createAtlasWithAgents([createMockBackend()], {
|
|
769
|
+
storage: { baseDir: tempDir },
|
|
770
|
+
});
|
|
771
|
+
await atlas2.init();
|
|
772
|
+
|
|
773
|
+
const memory2 = atlas2.getMemory();
|
|
774
|
+
const playbook = await memory2.playbooks.get('skill-persist');
|
|
775
|
+
expect(playbook).toBeDefined();
|
|
776
|
+
|
|
777
|
+
await atlas2.close();
|
|
778
|
+
});
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
describe('Integration: Playbook Usage Inference', () => {
|
|
782
|
+
let tempDir: string;
|
|
783
|
+
let atlas: Atlas;
|
|
784
|
+
let mockBackend: MockBackend;
|
|
785
|
+
|
|
786
|
+
beforeEach(async () => {
|
|
787
|
+
tempDir = await mkdtemp(join(tmpdir(), 'atlas-usage-test-'));
|
|
788
|
+
mockBackend = createMockBackend({
|
|
789
|
+
success: true,
|
|
790
|
+
result: 'Done',
|
|
791
|
+
durationMs: 30,
|
|
792
|
+
messages: [
|
|
793
|
+
{ role: 'assistant', content: 'Following the authentication fix playbook...' },
|
|
794
|
+
{ role: 'assistant', content: 'Checking token validation as suggested...' },
|
|
795
|
+
],
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
atlas = createAtlasWithAgents([mockBackend], {
|
|
799
|
+
storage: { baseDir: tempDir },
|
|
800
|
+
execution: {
|
|
801
|
+
defaultAgentType: 'mock',
|
|
802
|
+
},
|
|
803
|
+
});
|
|
804
|
+
await atlas.init();
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
afterEach(async () => {
|
|
808
|
+
await atlas.close();
|
|
809
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
it('should infer playbook usage from trajectory', async () => {
|
|
813
|
+
const memory = atlas.getMemory();
|
|
814
|
+
|
|
815
|
+
// Add playbook
|
|
816
|
+
await memory.playbooks.add({
|
|
817
|
+
id: 'auth-fix-playbook',
|
|
818
|
+
name: 'Authentication Fix',
|
|
819
|
+
applicability: {
|
|
820
|
+
situations: ['Fix auth issue'],
|
|
821
|
+
triggers: ['authentication', 'token', 'auth'],
|
|
822
|
+
antiPatterns: [],
|
|
823
|
+
domains: ['auth'],
|
|
824
|
+
},
|
|
825
|
+
guidance: {
|
|
826
|
+
strategy: 'Check token validation and fix',
|
|
827
|
+
tactics: ['Validate tokens', 'Check expiry'],
|
|
828
|
+
},
|
|
829
|
+
verification: {
|
|
830
|
+
successIndicators: ['Auth works'],
|
|
831
|
+
failureIndicators: ['Auth fails'],
|
|
832
|
+
},
|
|
833
|
+
evolution: {
|
|
834
|
+
version: '1.0.0',
|
|
835
|
+
createdFrom: [],
|
|
836
|
+
failures: [],
|
|
837
|
+
refinements: [],
|
|
838
|
+
successCount: 5,
|
|
839
|
+
failureCount: 0,
|
|
840
|
+
},
|
|
841
|
+
confidence: 0.8,
|
|
842
|
+
complexity: 'moderate',
|
|
843
|
+
estimatedEffort: 2,
|
|
844
|
+
createdAt: new Date(),
|
|
845
|
+
updatedAt: new Date(),
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
await atlas.getSkillLibrary()?.refreshTiers();
|
|
849
|
+
|
|
850
|
+
const task = createTask({
|
|
851
|
+
domain: 'auth',
|
|
852
|
+
description: 'Fix authentication token validation issue',
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
const result = await atlas.solve(task);
|
|
856
|
+
|
|
857
|
+
// Usage inference should have run
|
|
858
|
+
expect(result.injectedPlaybooks).toBeDefined();
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
it('should track all injected playbooks', async () => {
|
|
862
|
+
const memory = atlas.getMemory();
|
|
863
|
+
|
|
864
|
+
// Add multiple playbooks
|
|
865
|
+
await memory.playbooks.add({
|
|
866
|
+
id: 'playbook-a',
|
|
867
|
+
name: 'Playbook A',
|
|
868
|
+
applicability: {
|
|
869
|
+
situations: ['Test situation A'],
|
|
870
|
+
triggers: ['test-a'],
|
|
871
|
+
antiPatterns: [],
|
|
872
|
+
domains: ['test'],
|
|
873
|
+
},
|
|
874
|
+
guidance: { strategy: 'Strategy A', tactics: [] },
|
|
875
|
+
verification: { successIndicators: [], failureIndicators: [] },
|
|
876
|
+
evolution: {
|
|
877
|
+
version: '1.0.0',
|
|
878
|
+
createdFrom: [],
|
|
879
|
+
failures: [],
|
|
880
|
+
refinements: [],
|
|
881
|
+
successCount: 3,
|
|
882
|
+
failureCount: 0,
|
|
883
|
+
},
|
|
884
|
+
confidence: 0.75,
|
|
885
|
+
complexity: 'simple',
|
|
886
|
+
estimatedEffort: 1,
|
|
887
|
+
createdAt: new Date(),
|
|
888
|
+
updatedAt: new Date(),
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
await memory.playbooks.add({
|
|
892
|
+
id: 'playbook-b',
|
|
893
|
+
name: 'Playbook B',
|
|
894
|
+
applicability: {
|
|
895
|
+
situations: ['Test situation B'],
|
|
896
|
+
triggers: ['test-b'],
|
|
897
|
+
antiPatterns: [],
|
|
898
|
+
domains: ['test'],
|
|
899
|
+
},
|
|
900
|
+
guidance: { strategy: 'Strategy B', tactics: [] },
|
|
901
|
+
verification: { successIndicators: [], failureIndicators: [] },
|
|
902
|
+
evolution: {
|
|
903
|
+
version: '1.0.0',
|
|
904
|
+
createdFrom: [],
|
|
905
|
+
failures: [],
|
|
906
|
+
refinements: [],
|
|
907
|
+
successCount: 3,
|
|
908
|
+
failureCount: 0,
|
|
909
|
+
},
|
|
910
|
+
confidence: 0.75,
|
|
911
|
+
complexity: 'simple',
|
|
912
|
+
estimatedEffort: 1,
|
|
913
|
+
createdAt: new Date(),
|
|
914
|
+
updatedAt: new Date(),
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
await atlas.getSkillLibrary()?.refreshTiers();
|
|
918
|
+
|
|
919
|
+
const task = createTask({
|
|
920
|
+
domain: 'test',
|
|
921
|
+
description: 'Test task for tracking',
|
|
922
|
+
});
|
|
923
|
+
|
|
924
|
+
const result = await atlas.solve(task);
|
|
925
|
+
|
|
926
|
+
// Should have tracked injected playbooks (may include playbooks from router context)
|
|
927
|
+
expect(result.injectedPlaybooks).toBeDefined();
|
|
928
|
+
});
|
|
929
|
+
});
|