@holoscript/framework 6.0.3 → 6.0.4
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/CHANGELOG.md +1 -2
- package/ROADMAP.md +68 -66
- package/dist/{InvisibleWallet-BB6tFvRA.d.cts → InvisibleWallet-EFiuaLn3.d.cts} +1 -1
- package/dist/{OrchestratorAgent-BvWgf9uw.d.cts → OrchestratorAgent-CrLDGNL6.d.cts} +1 -1
- package/dist/agents/index.cjs +11 -10
- package/dist/agents/index.d.cts +4 -16
- package/dist/ai/index.cjs +2 -2
- package/dist/behavior.cjs +10 -0
- package/dist/economy/index.cjs +4 -4
- package/dist/economy/index.d.cts +2 -2
- package/dist/index.cjs +33 -11
- package/dist/index.d.cts +3 -3
- package/dist/swarm/index.cjs +3 -0
- package/package.json +14 -9
- package/src/__tests__/bounty-marketplace.test.ts +53 -21
- package/src/__tests__/delegation.test.ts +1 -4
- package/src/__tests__/done-log-audit.test.ts +38 -46
- package/src/__tests__/framework.test.ts +172 -53
- package/src/__tests__/goal-synthesizer.test.ts +9 -6
- package/src/__tests__/presence.test.ts +1 -1
- package/src/__tests__/protocol-agent.test.ts +12 -11
- package/src/__tests__/revenue-splitter.test.ts +22 -15
- package/src/__tests__/scenario-driven-todo.test.ts +55 -35
- package/src/__tests__/self-improve.test.ts +28 -9
- package/src/__tests__/service-lifecycle.test.ts +9 -3
- package/src/__tests__/skill-router.test.ts +3 -3
- package/src/agents/CulturalMemory.ts +6 -6
- package/src/agents/DelegationTraceHooks.ts +560 -0
- package/src/agents/FederatedRegistryAdapter.ts +1 -1
- package/src/agents/NormEngine.ts +3 -8
- package/src/agents/OrchestratorAgent.ts +1 -1
- package/src/agents/TaskDelegationService.ts +5 -9
- package/src/agents/__tests__/AgentWalletRegistry.test.ts +5 -4
- package/src/agents/__tests__/CrossRealityHandoff.test.ts +9 -3
- package/src/agents/__tests__/DelegationTraceHooks.test.ts +390 -0
- package/src/agents/__tests__/TaskDelegationService.test.ts +4 -2
- package/src/agents/spatial-comms/Layer1RealTime.ts +36 -19
- package/src/agents/spatial-comms/Layer2A2A.ts +1 -3
- package/src/agents/spatial-comms/Layer3MCP.ts +13 -4
- package/src/agents/spatial-comms/ProtocolTypes.ts +5 -2
- package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +2 -2
- package/src/ai/HoloScriptGenerator.ts +2 -2
- package/src/ai/__tests__/PerceptionSystem.prod.test.ts +1 -1
- package/src/ai/__tests__/PerceptionSystem.test.ts +14 -14
- package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +1 -1
- package/src/ai/index.ts +5 -1
- package/src/board/audit.ts +17 -6
- package/src/board/board-ops.ts +45 -15
- package/src/board/board-types.ts +94 -20
- package/src/delegation.ts +5 -3
- package/src/distributed-claimer.ts +13 -2
- package/src/economy/BountyManager.ts +40 -18
- package/src/economy/KnowledgeMarketplace.ts +27 -8
- package/src/economy/PaymentWebhookService.ts +0 -1
- package/src/economy/RevenueSplitter.ts +2 -4
- package/src/economy/UnifiedBudgetOptimizer.ts +8 -9
- package/src/economy/_core-stubs.ts +1 -1
- package/src/economy/x402-facilitator.ts +17 -8
- package/src/index.ts +16 -12
- package/src/knowledge/__tests__/knowledge-consolidator.test.ts +138 -89
- package/src/knowledge/__tests__/knowledge-store-vector.test.ts +59 -16
- package/src/knowledge/brain.ts +7 -7
- package/src/knowledge/consolidation.ts +16 -16
- package/src/knowledge/knowledge-consolidator.ts +60 -30
- package/src/knowledge/knowledge-store.ts +83 -45
- package/src/learning/ProceduralCompiler.ts +6 -1
- package/src/learning/learning/MemoryConsolidator.ts +102 -0
- package/src/learning/learning/MemoryScorer.ts +69 -0
- package/src/learning/learning/ProceduralCompiler.ts +45 -0
- package/src/learning/learning/SemanticClusterer.ts +66 -0
- package/src/llm/llm-adapter.ts +24 -10
- package/src/mesh/index.ts +37 -17
- package/src/protocol/goal-synthesizer.ts +24 -34
- package/src/protocol/implementations.ts +91 -22
- package/src/protocol/micro-phase-decomposer.ts +25 -17
- package/src/protocol/micro-step-decomposer.test.ts +104 -39
- package/src/protocol-agent.test.ts +17 -7
- package/src/protocol-agent.ts +45 -42
- package/src/self-improve/absorb-scanner.ts +9 -6
- package/src/self-improve/evolution-engine.ts +36 -18
- package/src/self-improve/framework-absorber.ts +21 -16
- package/src/self-improve/index.ts +2 -10
- package/src/self-improve/prompt-optimizer.ts +31 -19
- package/src/self-improve/test-generator.ts +16 -12
- package/src/skill-router.ts +7 -6
- package/src/swarm/messaging/GossipProtocol.ts +1 -1
- package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +31 -9
- package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +21 -7
- package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +24 -8
- package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +6 -2
- package/src/team.ts +277 -122
- package/src/training/scripts/generate-spatial-dataset.ts +1 -1
- package/src/training/training/LRScheduler.ts +377 -0
- package/src/training/training/QualityScoringPipeline.ts +139 -0
- package/src/training/training/SoftDedup.ts +461 -0
- package/src/training/training/SparsityMonitor.ts +685 -0
- package/src/training/training/SparsityMonitorTypes.ts +209 -0
- package/src/training/training/SpatialTrainingDataGenerator.ts +1526 -0
- package/src/training/training/SpatialTrainingDataTypes.ts +216 -0
- package/src/training/training/TrainingPipelineConfig.ts +215 -0
- package/src/training/training/__tests__/CorpusValidation.test.ts +87 -0
- package/src/training/training/__tests__/LRScheduler.test.ts +592 -0
- package/src/training/training/__tests__/SoftDedup.test.ts +415 -0
- package/src/training/training/__tests__/SparsityMonitor.test.ts +1623 -0
- package/src/training/training/__tests__/SpatialCorpusValidation.test.ts +72 -0
- package/src/training/training/__tests__/SpatialTrainingDataGenerator.test.ts +1244 -0
- package/src/training/training/__tests__/TrainingMonkeyIntegration.test.ts +897 -0
- package/src/training/training/__tests__/TrainingPipelineConfig.test.ts +202 -0
- package/src/training/training/__tests__/schema.test.ts +72 -0
- package/src/training/training/__tests__/training-constants.test.ts +106 -0
- package/src/training/training/__tests__/trait-mappings.test.ts +81 -0
- package/src/training/training/constants.ts +94 -0
- package/src/training/training/index.ts +17 -0
- package/src/training/training/schema.ts +147 -0
- package/src/training/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
- package/src/training/training/scripts/generate-spatial-dataset.ts +521 -0
- package/src/training/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
- package/src/training/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
- package/src/training/training/trainingmonkey/index.ts +26 -0
- package/src/training/training/trait-mappings.ts +157 -0
- package/src/types.ts +2 -7
- package/ALL-test-results.json +0 -1
- package/LICENSE +0 -21
- package/dist/AgentManifest-CB4xM-Ma.d.ts +0 -704
- package/dist/BehaviorTree-BrBFECv5.d.ts +0 -103
- package/dist/InvisibleWallet-rtRrBOA8.d.ts +0 -1732
- package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +0 -798
- package/dist/agents/index.d.ts +0 -1788
- package/dist/agents/index.js +0 -4695
- package/dist/ai/index.d.ts +0 -1753
- package/dist/ai/index.js +0 -5244
- package/dist/behavior.d.ts +0 -130
- package/dist/behavior.js +0 -407
- package/dist/economy/index.d.ts +0 -747
- package/dist/economy/index.js +0 -3617
- package/dist/implementations-D9T3un9D.d.ts +0 -236
- package/dist/index.d.ts +0 -1729
- package/dist/index.js +0 -24277
- package/dist/learning/index.d.ts +0 -104
- package/dist/learning/index.js +0 -189
- package/dist/negotiation/index.d.ts +0 -610
- package/dist/negotiation/index.js +0 -931
- package/dist/skills/index.d.ts +0 -289
- package/dist/skills/index.js +0 -1079
- package/dist/swarm/index.d.ts +0 -2433
- package/dist/swarm/index.js +0 -5221
- package/dist/training/index.d.ts +0 -1734
- package/dist/training/index.js +0 -2687
- package/extract-failures.js +0 -10
- package/src/training/training/data/novel-use-cases.jsonl +0 -153
- package/src/training/training/data/spatial-reasoning-10k.jsonl +0 -9354
- package/src/types/core-stubs.d.ts +0 -113
- package/test-output.txt +0 -0
- package/test-result.json +0 -1
- package/tsc-errors.txt +0 -4
- package/tsc_output.txt +0 -0
- package/typescript-errors-2.txt +0 -0
- package/typescript-errors.txt +0 -22
- package/vitest-log-utf8.txt +0 -268
- package/vitest-log.txt +0 -0
|
@@ -12,8 +12,19 @@ function mockLLM(response: string): LLMAdapter {
|
|
|
12
12
|
return { call: vi.fn().mockResolvedValue(response) };
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
function phase(
|
|
16
|
-
|
|
15
|
+
function phase(
|
|
16
|
+
id: string,
|
|
17
|
+
deps: string[] = [],
|
|
18
|
+
duration = 5000,
|
|
19
|
+
caps: string[] = ['coding']
|
|
20
|
+
): MicroPhase {
|
|
21
|
+
return {
|
|
22
|
+
id,
|
|
23
|
+
description: `Phase ${id}`,
|
|
24
|
+
dependencies: deps,
|
|
25
|
+
estimatedDuration: duration,
|
|
26
|
+
requiredCapabilities: caps,
|
|
27
|
+
};
|
|
17
28
|
}
|
|
18
29
|
|
|
19
30
|
const simpleTask: TaskDescription = {
|
|
@@ -30,11 +41,7 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
30
41
|
const llm = mockLLM('');
|
|
31
42
|
const decomposer = new SmartMicroPhaseDecomposer(llm);
|
|
32
43
|
|
|
33
|
-
const phases: MicroPhase[] = [
|
|
34
|
-
phase('a'),
|
|
35
|
-
phase('b'),
|
|
36
|
-
phase('c'),
|
|
37
|
-
];
|
|
44
|
+
const phases: MicroPhase[] = [phase('a'), phase('b'), phase('c')];
|
|
38
45
|
|
|
39
46
|
const plan = decomposer.buildExecutionPlan(phases);
|
|
40
47
|
|
|
@@ -49,18 +56,14 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
49
56
|
const llm = mockLLM('');
|
|
50
57
|
const decomposer = new SmartMicroPhaseDecomposer(llm);
|
|
51
58
|
|
|
52
|
-
const phases: MicroPhase[] = [
|
|
53
|
-
phase('a'),
|
|
54
|
-
phase('b', ['a']),
|
|
55
|
-
phase('c', ['b']),
|
|
56
|
-
];
|
|
59
|
+
const phases: MicroPhase[] = [phase('a'), phase('b', ['a']), phase('c', ['b'])];
|
|
57
60
|
|
|
58
61
|
const plan = decomposer.buildExecutionPlan(phases);
|
|
59
62
|
|
|
60
63
|
expect(plan.waves).toHaveLength(3);
|
|
61
|
-
expect(plan.waves[0].map(p => p.id)).toEqual(['a']);
|
|
62
|
-
expect(plan.waves[1].map(p => p.id)).toEqual(['b']);
|
|
63
|
-
expect(plan.waves[2].map(p => p.id)).toEqual(['c']);
|
|
64
|
+
expect(plan.waves[0].map((p) => p.id)).toEqual(['a']);
|
|
65
|
+
expect(plan.waves[1].map((p) => p.id)).toEqual(['b']);
|
|
66
|
+
expect(plan.waves[2].map((p) => p.id)).toEqual(['c']);
|
|
64
67
|
expect(plan.totalEstimatedDuration).toBe(15000);
|
|
65
68
|
expect(plan.parallelizationRatio).toBe(0);
|
|
66
69
|
});
|
|
@@ -84,9 +87,9 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
84
87
|
const plan = decomposer.buildExecutionPlan(phases);
|
|
85
88
|
|
|
86
89
|
expect(plan.waves).toHaveLength(3);
|
|
87
|
-
expect(plan.waves[0].map(p => p.id)).toEqual(['a']);
|
|
88
|
-
expect(plan.waves[1].map(p => p.id).sort()).toEqual(['b', 'c']);
|
|
89
|
-
expect(plan.waves[2].map(p => p.id)).toEqual(['d']);
|
|
90
|
+
expect(plan.waves[0].map((p) => p.id)).toEqual(['a']);
|
|
91
|
+
expect(plan.waves[1].map((p) => p.id).sort()).toEqual(['b', 'c']);
|
|
92
|
+
expect(plan.waves[2].map((p) => p.id)).toEqual(['d']);
|
|
90
93
|
});
|
|
91
94
|
|
|
92
95
|
it('returns empty plan for no phases', () => {
|
|
@@ -112,10 +115,7 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
112
115
|
const llm = mockLLM('');
|
|
113
116
|
const decomposer = new SmartMicroPhaseDecomposer(llm);
|
|
114
117
|
|
|
115
|
-
const phases: MicroPhase[] = [
|
|
116
|
-
phase('a', ['b']),
|
|
117
|
-
phase('b', ['a']),
|
|
118
|
-
];
|
|
118
|
+
const phases: MicroPhase[] = [phase('a', ['b']), phase('b', ['a'])];
|
|
119
119
|
|
|
120
120
|
expect(() => decomposer.buildExecutionPlan(phases)).toThrow('Circular dependency');
|
|
121
121
|
});
|
|
@@ -150,10 +150,34 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
150
150
|
it('parses well-formed LLM JSON response', async () => {
|
|
151
151
|
const llmResponse = JSON.stringify({
|
|
152
152
|
phases: [
|
|
153
|
-
{
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
153
|
+
{
|
|
154
|
+
id: 'phase_1',
|
|
155
|
+
description: 'Setup project',
|
|
156
|
+
dependencies: [],
|
|
157
|
+
estimatedDuration: 3000,
|
|
158
|
+
requiredCapabilities: ['coding'],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: 'phase_2',
|
|
162
|
+
description: 'Write components',
|
|
163
|
+
dependencies: ['phase_1'],
|
|
164
|
+
estimatedDuration: 8000,
|
|
165
|
+
requiredCapabilities: ['coding'],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
id: 'phase_3',
|
|
169
|
+
description: 'Write tests',
|
|
170
|
+
dependencies: ['phase_1'],
|
|
171
|
+
estimatedDuration: 5000,
|
|
172
|
+
requiredCapabilities: ['testing'],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: 'phase_4',
|
|
176
|
+
description: 'Integration test',
|
|
177
|
+
dependencies: ['phase_2', 'phase_3'],
|
|
178
|
+
estimatedDuration: 4000,
|
|
179
|
+
requiredCapabilities: ['testing'],
|
|
180
|
+
},
|
|
157
181
|
],
|
|
158
182
|
});
|
|
159
183
|
|
|
@@ -169,7 +193,8 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
169
193
|
});
|
|
170
194
|
|
|
171
195
|
it('extracts JSON from markdown code blocks', async () => {
|
|
172
|
-
const llmResponse =
|
|
196
|
+
const llmResponse =
|
|
197
|
+
'```json\n{"phases": [{"id": "p1", "description": "Do it", "dependencies": [], "estimatedDuration": 5000, "requiredCapabilities": ["coding"]}]}\n```';
|
|
173
198
|
|
|
174
199
|
const llm = mockLLM(llmResponse);
|
|
175
200
|
const decomposer = new SmartMicroPhaseDecomposer(llm);
|
|
@@ -200,7 +225,15 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
200
225
|
|
|
201
226
|
it('does not mark as decomposed when below complexity threshold', async () => {
|
|
202
227
|
const llmResponse = JSON.stringify({
|
|
203
|
-
phases: [
|
|
228
|
+
phases: [
|
|
229
|
+
{
|
|
230
|
+
id: 'only',
|
|
231
|
+
description: 'Just do it',
|
|
232
|
+
dependencies: [],
|
|
233
|
+
estimatedDuration: 3000,
|
|
234
|
+
requiredCapabilities: ['coding'],
|
|
235
|
+
},
|
|
236
|
+
],
|
|
204
237
|
});
|
|
205
238
|
|
|
206
239
|
const llm = mockLLM(llmResponse);
|
|
@@ -214,8 +247,20 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
214
247
|
it('respects custom complexity threshold', async () => {
|
|
215
248
|
const llmResponse = JSON.stringify({
|
|
216
249
|
phases: [
|
|
217
|
-
{
|
|
218
|
-
|
|
250
|
+
{
|
|
251
|
+
id: 'a',
|
|
252
|
+
description: 'Step A',
|
|
253
|
+
dependencies: [],
|
|
254
|
+
estimatedDuration: 3000,
|
|
255
|
+
requiredCapabilities: ['coding'],
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
id: 'b',
|
|
259
|
+
description: 'Step B',
|
|
260
|
+
dependencies: [],
|
|
261
|
+
estimatedDuration: 3000,
|
|
262
|
+
requiredCapabilities: ['coding'],
|
|
263
|
+
},
|
|
219
264
|
],
|
|
220
265
|
});
|
|
221
266
|
|
|
@@ -229,10 +274,34 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
229
274
|
it('enforces maxParallelism by adding synthetic dependencies', async () => {
|
|
230
275
|
const llmResponse = JSON.stringify({
|
|
231
276
|
phases: [
|
|
232
|
-
{
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
277
|
+
{
|
|
278
|
+
id: 'a',
|
|
279
|
+
description: 'A',
|
|
280
|
+
dependencies: [],
|
|
281
|
+
estimatedDuration: 3000,
|
|
282
|
+
requiredCapabilities: ['coding'],
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
id: 'b',
|
|
286
|
+
description: 'B',
|
|
287
|
+
dependencies: [],
|
|
288
|
+
estimatedDuration: 3000,
|
|
289
|
+
requiredCapabilities: ['coding'],
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
id: 'c',
|
|
293
|
+
description: 'C',
|
|
294
|
+
dependencies: [],
|
|
295
|
+
estimatedDuration: 3000,
|
|
296
|
+
requiredCapabilities: ['coding'],
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
id: 'd',
|
|
300
|
+
description: 'D',
|
|
301
|
+
dependencies: [],
|
|
302
|
+
estimatedDuration: 3000,
|
|
303
|
+
requiredCapabilities: ['coding'],
|
|
304
|
+
},
|
|
236
305
|
],
|
|
237
306
|
});
|
|
238
307
|
|
|
@@ -272,11 +341,7 @@ describe('SmartMicroPhaseDecomposer', () => {
|
|
|
272
341
|
const decomposer = new SmartMicroPhaseDecomposer(llm);
|
|
273
342
|
|
|
274
343
|
// a(5s) and b(5s) in parallel, c(5s) depends on both
|
|
275
|
-
const phases = [
|
|
276
|
-
phase('a', [], 5000),
|
|
277
|
-
phase('b', [], 5000),
|
|
278
|
-
phase('c', ['a', 'b'], 5000),
|
|
279
|
-
];
|
|
344
|
+
const phases = [phase('a', [], 5000), phase('b', [], 5000), phase('c', ['a', 'b'], 5000)];
|
|
280
345
|
const plan = decomposer.buildExecutionPlan(phases);
|
|
281
346
|
|
|
282
347
|
// Sequential: 15000ms, Parallel: 5000 + 5000 = 10000ms
|
|
@@ -36,17 +36,21 @@ describe('defineProtocolAgent', () => {
|
|
|
36
36
|
// ── Validation ──
|
|
37
37
|
|
|
38
38
|
it('throws on empty name', () => {
|
|
39
|
-
expect(() => defineProtocolAgent({ ...BASE_CONFIG, name: '' })).toThrow(
|
|
39
|
+
expect(() => defineProtocolAgent({ ...BASE_CONFIG, name: '' })).toThrow(
|
|
40
|
+
'Agent name is required'
|
|
41
|
+
);
|
|
40
42
|
});
|
|
41
43
|
|
|
42
44
|
it('throws on invalid role', () => {
|
|
43
|
-
expect(() => defineProtocolAgent({ ...BASE_CONFIG, role: 'wizard' as never })).toThrow(
|
|
45
|
+
expect(() => defineProtocolAgent({ ...BASE_CONFIG, role: 'wizard' as never })).toThrow(
|
|
46
|
+
'Invalid role'
|
|
47
|
+
);
|
|
44
48
|
});
|
|
45
49
|
|
|
46
50
|
it('throws on missing model provider', () => {
|
|
47
|
-
expect(() =>
|
|
48
|
-
|
|
49
|
-
);
|
|
51
|
+
expect(() =>
|
|
52
|
+
defineProtocolAgent({ ...BASE_CONFIG, model: { provider: '' as never, model: 'x' } })
|
|
53
|
+
).toThrow('Agent model must specify provider and model');
|
|
50
54
|
});
|
|
51
55
|
|
|
52
56
|
it('throws on empty capabilities', () => {
|
|
@@ -138,7 +142,7 @@ describe('defineProtocolAgent', () => {
|
|
|
138
142
|
expect(handle.status).toBe('cancelled');
|
|
139
143
|
|
|
140
144
|
// At least INTAKE and REFLECT ran, then EXECUTE should be skipped
|
|
141
|
-
const skipped = result.phases.filter(p => p.status === 'skipped');
|
|
145
|
+
const skipped = result.phases.filter((p) => p.status === 'skipped');
|
|
142
146
|
expect(skipped.length).toBeGreaterThan(0);
|
|
143
147
|
});
|
|
144
148
|
|
|
@@ -256,7 +260,13 @@ describe('protocolToFrameworkCycleResult', () => {
|
|
|
256
260
|
status: 'success',
|
|
257
261
|
data: {
|
|
258
262
|
validated: [
|
|
259
|
-
{
|
|
263
|
+
{
|
|
264
|
+
type: 'wisdom',
|
|
265
|
+
content: 'insight',
|
|
266
|
+
domain: 'testing',
|
|
267
|
+
confidence: 0.8,
|
|
268
|
+
source: 'test',
|
|
269
|
+
},
|
|
260
270
|
],
|
|
261
271
|
},
|
|
262
272
|
durationMs: 50,
|
package/src/protocol-agent.ts
CHANGED
|
@@ -29,8 +29,7 @@ const PHASE_PROMPTS: Record<number, string> = {
|
|
|
29
29
|
'You are gathering context for a task. Summarize the task, relevant knowledge, and constraints. Be concise.',
|
|
30
30
|
[ProtocolPhase.REFLECT]:
|
|
31
31
|
'You are analyzing an approach. Given the context, identify the best strategy, risks, and key considerations. Be brief.',
|
|
32
|
-
[ProtocolPhase.EXECUTE]:
|
|
33
|
-
'', // Uses the agent's own system prompt
|
|
32
|
+
[ProtocolPhase.EXECUTE]: '', // Uses the agent's own system prompt
|
|
34
33
|
[ProtocolPhase.COMPRESS]:
|
|
35
34
|
'You are extracting knowledge from completed work. Identify Wisdom (insights), Patterns (reusable solutions), and Gotchas (pitfalls). Format each as: [wisdom|pattern|gotcha] content',
|
|
36
35
|
[ProtocolPhase.REINTAKE]:
|
|
@@ -302,11 +301,7 @@ export class ProtocolAgent extends BaseAgent {
|
|
|
302
301
|
// ── Helpers ──
|
|
303
302
|
|
|
304
303
|
/** Parse LLM output into KnowledgeInsight[]. */
|
|
305
|
-
function parseKnowledgeItems(
|
|
306
|
-
content: string,
|
|
307
|
-
domain: string,
|
|
308
|
-
source: string
|
|
309
|
-
): KnowledgeInsight[] {
|
|
304
|
+
function parseKnowledgeItems(content: string, domain: string, source: string): KnowledgeInsight[] {
|
|
310
305
|
const insights: KnowledgeInsight[] = [];
|
|
311
306
|
|
|
312
307
|
for (const line of content.split('\n')) {
|
|
@@ -344,20 +339,13 @@ export async function runProtocolCycle(
|
|
|
344
339
|
});
|
|
345
340
|
|
|
346
341
|
// Extract summary from EXECUTE phase
|
|
347
|
-
const executePhase = cycleResult.phases.find(
|
|
348
|
-
(p) => p.phase === ProtocolPhase.EXECUTE
|
|
349
|
-
);
|
|
342
|
+
const executePhase = cycleResult.phases.find((p) => p.phase === ProtocolPhase.EXECUTE);
|
|
350
343
|
const summary =
|
|
351
|
-
(executePhase?.data as { output?: string })?.output?.slice(0, 500) ??
|
|
352
|
-
'Task completed';
|
|
344
|
+
(executePhase?.data as { output?: string })?.output?.slice(0, 500) ?? 'Task completed';
|
|
353
345
|
|
|
354
346
|
// Extract insights from REINTAKE phase (validated) or COMPRESS phase (raw)
|
|
355
|
-
const reintakePhase = cycleResult.phases.find(
|
|
356
|
-
|
|
357
|
-
);
|
|
358
|
-
const compressPhase = cycleResult.phases.find(
|
|
359
|
-
(p) => p.phase === ProtocolPhase.COMPRESS
|
|
360
|
-
);
|
|
347
|
+
const reintakePhase = cycleResult.phases.find((p) => p.phase === ProtocolPhase.REINTAKE);
|
|
348
|
+
const compressPhase = cycleResult.phases.find((p) => p.phase === ProtocolPhase.COMPRESS);
|
|
361
349
|
const insights: KnowledgeInsight[] =
|
|
362
350
|
(reintakePhase?.data as { validated?: KnowledgeInsight[] })?.validated ??
|
|
363
351
|
(compressPhase?.data as { insights?: KnowledgeInsight[] })?.insights ??
|
|
@@ -383,29 +371,32 @@ export function protocolToFrameworkCycleResult(
|
|
|
383
371
|
cycle: number
|
|
384
372
|
): FrameworkCycleResult {
|
|
385
373
|
// Extract insights from compress/reintake phases
|
|
386
|
-
const reintake = protocol.phases.find(p => p.phase === ProtocolPhase.REINTAKE);
|
|
387
|
-
const compress = protocol.phases.find(p => p.phase === ProtocolPhase.COMPRESS);
|
|
374
|
+
const reintake = protocol.phases.find((p) => p.phase === ProtocolPhase.REINTAKE);
|
|
375
|
+
const compress = protocol.phases.find((p) => p.phase === ProtocolPhase.COMPRESS);
|
|
388
376
|
const insights: KnowledgeInsight[] =
|
|
389
377
|
(reintake?.data as { validated?: KnowledgeInsight[] })?.validated ??
|
|
390
378
|
(compress?.data as { insights?: KnowledgeInsight[] })?.insights ??
|
|
391
379
|
[];
|
|
392
380
|
|
|
393
|
-
const executePhase = protocol.phases.find(p => p.phase === ProtocolPhase.EXECUTE);
|
|
394
|
-
const summary =
|
|
381
|
+
const executePhase = protocol.phases.find((p) => p.phase === ProtocolPhase.EXECUTE);
|
|
382
|
+
const summary =
|
|
383
|
+
(executePhase?.data as { output?: string })?.output?.slice(0, 500) ?? 'Task completed';
|
|
395
384
|
|
|
396
385
|
const hasFailed = protocol.status === 'failed';
|
|
397
386
|
|
|
398
387
|
return {
|
|
399
388
|
teamName,
|
|
400
389
|
cycle,
|
|
401
|
-
agentResults: [
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
390
|
+
agentResults: [
|
|
391
|
+
{
|
|
392
|
+
agentName: protocol.domain, // best available identifier
|
|
393
|
+
taskId: protocol.cycleId,
|
|
394
|
+
taskTitle: protocol.task,
|
|
395
|
+
action: hasFailed ? 'error' : 'completed',
|
|
396
|
+
summary,
|
|
397
|
+
knowledge: insights,
|
|
398
|
+
},
|
|
399
|
+
],
|
|
409
400
|
knowledgeProduced: insights,
|
|
410
401
|
compoundedInsights: insights.length,
|
|
411
402
|
durationMs: protocol.totalDurationMs,
|
|
@@ -421,7 +412,7 @@ export function frameworkToProtocolCycleResult(
|
|
|
421
412
|
domain: string
|
|
422
413
|
): ProtocolCycleResult {
|
|
423
414
|
const now = Date.now();
|
|
424
|
-
const hasError = fw.agentResults.some(r => r.action === 'error');
|
|
415
|
+
const hasError = fw.agentResults.some((r) => r.action === 'error');
|
|
425
416
|
|
|
426
417
|
return {
|
|
427
418
|
cycleId: `cycle_${fw.cycle}_${now.toString(36)}`,
|
|
@@ -460,7 +451,7 @@ export function defineProtocolAgent(config: ProtocolAgentConfig): ProtocolAgentH
|
|
|
460
451
|
throw new Error('Agent name is required');
|
|
461
452
|
}
|
|
462
453
|
const VALID_ROLES = ['architect', 'coder', 'researcher', 'reviewer'] as const;
|
|
463
|
-
if (!VALID_ROLES.includes(config.role as typeof VALID_ROLES[number])) {
|
|
454
|
+
if (!VALID_ROLES.includes(config.role as (typeof VALID_ROLES)[number])) {
|
|
464
455
|
throw new Error(`Invalid role "${config.role}". Valid: ${VALID_ROLES.join(', ')}`);
|
|
465
456
|
}
|
|
466
457
|
if (!config.model?.provider || !config.model?.model) {
|
|
@@ -472,7 +463,9 @@ export function defineProtocolAgent(config: ProtocolAgentConfig): ProtocolAgentH
|
|
|
472
463
|
|
|
473
464
|
const protocolStyle = config.protocolStyle ?? 'uaa2';
|
|
474
465
|
if (protocolStyle !== 'uaa2') {
|
|
475
|
-
throw new Error(
|
|
466
|
+
throw new Error(
|
|
467
|
+
`Protocol style "${protocolStyle}" is not yet implemented. Only 'uaa2' is supported.`
|
|
468
|
+
);
|
|
476
469
|
}
|
|
477
470
|
|
|
478
471
|
// Internal mutable state
|
|
@@ -509,7 +502,7 @@ export function defineProtocolAgent(config: ProtocolAgentConfig): ProtocolAgentH
|
|
|
509
502
|
// Check pause — wait until resumed
|
|
510
503
|
if (pauseRequested) {
|
|
511
504
|
status = 'paused';
|
|
512
|
-
await new Promise<void>(resolve => {
|
|
505
|
+
await new Promise<void>((resolve) => {
|
|
513
506
|
pauseResolver = resolve;
|
|
514
507
|
});
|
|
515
508
|
status = 'running';
|
|
@@ -555,14 +548,24 @@ export function defineProtocolAgent(config: ProtocolAgentConfig): ProtocolAgentH
|
|
|
555
548
|
}
|
|
556
549
|
|
|
557
550
|
const handle: ProtocolAgentHandle = {
|
|
558
|
-
get name() {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
get
|
|
551
|
+
get name() {
|
|
552
|
+
return config.name;
|
|
553
|
+
},
|
|
554
|
+
get role() {
|
|
555
|
+
return config.role;
|
|
556
|
+
},
|
|
557
|
+
get status() {
|
|
558
|
+
return status;
|
|
559
|
+
},
|
|
560
|
+
get history() {
|
|
561
|
+
return [...phaseHistory];
|
|
562
|
+
},
|
|
562
563
|
|
|
563
564
|
async execute(task: { title: string; description: string }): Promise<ProtocolCycleResult> {
|
|
564
565
|
if (status === 'running') {
|
|
565
|
-
throw new Error(
|
|
566
|
+
throw new Error(
|
|
567
|
+
'Agent is already executing. Await the current execution or cancel() first.'
|
|
568
|
+
);
|
|
566
569
|
}
|
|
567
570
|
|
|
568
571
|
status = 'running';
|
|
@@ -605,17 +608,17 @@ export function defineProtocolAgent(config: ProtocolAgentConfig): ProtocolAgentH
|
|
|
605
608
|
previousData = result.data;
|
|
606
609
|
}
|
|
607
610
|
|
|
608
|
-
const hasFailed = phaseResults.some(p => p.status === 'failure');
|
|
611
|
+
const hasFailed = phaseResults.some((p) => p.status === 'failure');
|
|
609
612
|
const wasCancelled = cancelRequested;
|
|
610
613
|
|
|
611
|
-
status = wasCancelled ? 'cancelled' :
|
|
614
|
+
status = wasCancelled ? 'cancelled' : hasFailed ? 'error' : 'idle';
|
|
612
615
|
|
|
613
616
|
return {
|
|
614
617
|
cycleId,
|
|
615
618
|
task: task.title,
|
|
616
619
|
domain: agent.identity.domain,
|
|
617
620
|
phases: phaseResults,
|
|
618
|
-
status: wasCancelled ? 'partial' :
|
|
621
|
+
status: wasCancelled ? 'partial' : hasFailed ? 'partial' : 'complete',
|
|
619
622
|
totalDurationMs: Date.now() - startedAt,
|
|
620
623
|
startedAt,
|
|
621
624
|
completedAt: Date.now(),
|
|
@@ -71,10 +71,11 @@ interface KnowledgeEntry {
|
|
|
71
71
|
*/
|
|
72
72
|
export async function scanFramework(config: AbsorbScanConfig = {}): Promise<ScanResult> {
|
|
73
73
|
const orchestratorUrl = config.orchestratorUrl || DEFAULT_ORCHESTRATOR_URL;
|
|
74
|
-
const apiKey = config.mcpApiKey || process.env.
|
|
74
|
+
const apiKey = config.mcpApiKey || process.env.HOLOSCRIPT_API_KEY || '';
|
|
75
75
|
const workspaceId = config.workspaceId || DEFAULT_WORKSPACE_ID;
|
|
76
76
|
const maxTasks = config.maxTasks || 20;
|
|
77
|
-
const searchQuery =
|
|
77
|
+
const searchQuery =
|
|
78
|
+
config.searchQuery ||
|
|
78
79
|
'framework improvement opportunities type-safety test-coverage refactoring agents';
|
|
79
80
|
|
|
80
81
|
if (!apiKey) {
|
|
@@ -84,7 +85,7 @@ export async function scanFramework(config: AbsorbScanConfig = {}): Promise<Scan
|
|
|
84
85
|
issuesFound: 0,
|
|
85
86
|
improvements: [],
|
|
86
87
|
knowledge: [],
|
|
87
|
-
error: '
|
|
88
|
+
error: 'HOLOSCRIPT_API_KEY required for knowledge store query',
|
|
88
89
|
};
|
|
89
90
|
}
|
|
90
91
|
|
|
@@ -108,7 +109,7 @@ export async function scanFramework(config: AbsorbScanConfig = {}): Promise<Scan
|
|
|
108
109
|
let filesAnalyzed = 0;
|
|
109
110
|
|
|
110
111
|
if (queryRes.ok) {
|
|
111
|
-
const data = await queryRes.json() as {
|
|
112
|
+
const data = (await queryRes.json()) as {
|
|
112
113
|
results?: KnowledgeEntry[];
|
|
113
114
|
entries?: KnowledgeEntry[];
|
|
114
115
|
};
|
|
@@ -245,8 +246,10 @@ export async function scanTodos(codebasePath: string): Promise<ScanResult> {
|
|
|
245
246
|
function categorizeContent(content: string): ImprovementTask['category'] {
|
|
246
247
|
const lower = content.toLowerCase();
|
|
247
248
|
if (lower.includes('test') || lower.includes('coverage') || lower.includes('spec')) return 'test';
|
|
248
|
-
if (lower.includes('perf') || lower.includes('slow') || lower.includes('optim'))
|
|
249
|
+
if (lower.includes('perf') || lower.includes('slow') || lower.includes('optim'))
|
|
250
|
+
return 'performance';
|
|
249
251
|
if (lower.includes('doc') || lower.includes('readme') || lower.includes('comment')) return 'docs';
|
|
250
|
-
if (lower.includes('type') || lower.includes('any') || lower.includes('cast'))
|
|
252
|
+
if (lower.includes('type') || lower.includes('any') || lower.includes('cast'))
|
|
253
|
+
return 'type-safety';
|
|
251
254
|
return 'refactor';
|
|
252
255
|
}
|
|
@@ -91,7 +91,9 @@ export async function evolve(team: Team, config: EvolutionConfig = {}): Promise<
|
|
|
91
91
|
await team.suggest(imp.title, {
|
|
92
92
|
description: imp.description,
|
|
93
93
|
category: mapCategory(imp.category),
|
|
94
|
-
evidence: imp.file
|
|
94
|
+
evidence: imp.file
|
|
95
|
+
? `Detected in ${imp.file}${imp.line ? `:${imp.line}` : ''}`
|
|
96
|
+
: undefined,
|
|
95
97
|
});
|
|
96
98
|
suggestionsCreated++;
|
|
97
99
|
} catch {
|
|
@@ -102,9 +104,9 @@ export async function evolve(team: Team, config: EvolutionConfig = {}): Promise<
|
|
|
102
104
|
|
|
103
105
|
// Step 3: Auto-board critical items
|
|
104
106
|
if (autoBoard) {
|
|
105
|
-
const critical = scan.improvements.filter(imp => imp.priority <= autoBoardMinPriority);
|
|
107
|
+
const critical = scan.improvements.filter((imp) => imp.priority <= autoBoardMinPriority);
|
|
106
108
|
if (critical.length > 0) {
|
|
107
|
-
const tasks = critical.map(imp => ({
|
|
109
|
+
const tasks = critical.map((imp) => ({
|
|
108
110
|
title: imp.title,
|
|
109
111
|
description: `[Self-improvement] ${imp.description}`,
|
|
110
112
|
priority: imp.priority,
|
|
@@ -119,31 +121,47 @@ export async function evolve(team: Team, config: EvolutionConfig = {}): Promise<
|
|
|
119
121
|
// Step 4: Publish extracted knowledge
|
|
120
122
|
for (const k of scan.knowledge) {
|
|
121
123
|
team.knowledge.publish(
|
|
122
|
-
{
|
|
124
|
+
{
|
|
125
|
+
type: k.type,
|
|
126
|
+
content: k.content,
|
|
127
|
+
domain: k.domain,
|
|
128
|
+
confidence: k.confidence,
|
|
129
|
+
source: 'evolution:self-scan',
|
|
130
|
+
},
|
|
123
131
|
'evolution-engine'
|
|
124
132
|
);
|
|
125
133
|
knowledgePublished++;
|
|
126
134
|
}
|
|
127
135
|
|
|
128
136
|
// Step 5: Compound
|
|
129
|
-
team.knowledge.compound(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
team.knowledge.compound(
|
|
138
|
+
scan.knowledge.map((k) => ({
|
|
139
|
+
type: k.type,
|
|
140
|
+
content: k.content,
|
|
141
|
+
domain: k.domain,
|
|
142
|
+
confidence: k.confidence,
|
|
143
|
+
source: 'evolution:self-scan',
|
|
144
|
+
}))
|
|
145
|
+
);
|
|
136
146
|
|
|
137
147
|
return { scan, todoScan, suggestionsCreated, tasksCreated, knowledgePublished };
|
|
138
148
|
}
|
|
139
149
|
|
|
140
|
-
function mapCategory(
|
|
150
|
+
function mapCategory(
|
|
151
|
+
cat: ImprovementTask['category']
|
|
152
|
+
): 'process' | 'tooling' | 'architecture' | 'testing' | 'docs' | 'performance' | 'other' {
|
|
141
153
|
switch (cat) {
|
|
142
|
-
case 'refactor':
|
|
143
|
-
|
|
144
|
-
case '
|
|
145
|
-
|
|
146
|
-
case '
|
|
147
|
-
|
|
154
|
+
case 'refactor':
|
|
155
|
+
return 'architecture';
|
|
156
|
+
case 'test':
|
|
157
|
+
return 'testing';
|
|
158
|
+
case 'docs':
|
|
159
|
+
return 'docs';
|
|
160
|
+
case 'performance':
|
|
161
|
+
return 'performance';
|
|
162
|
+
case 'type-safety':
|
|
163
|
+
return 'tooling';
|
|
164
|
+
default:
|
|
165
|
+
return 'other';
|
|
148
166
|
}
|
|
149
167
|
}
|
|
@@ -10,7 +10,12 @@
|
|
|
10
10
|
* service is unreachable.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
AbsorbScanConfig,
|
|
15
|
+
ScanResult,
|
|
16
|
+
ImprovementTask,
|
|
17
|
+
ExtractedKnowledge,
|
|
18
|
+
} from './absorb-scanner';
|
|
14
19
|
import { scanFramework, scanTodos } from './absorb-scanner';
|
|
15
20
|
|
|
16
21
|
export interface CodebaseGraph {
|
|
@@ -117,7 +122,7 @@ export class FrameworkAbsorber {
|
|
|
117
122
|
if (rpcResult.result?.content) {
|
|
118
123
|
// Parse the absorb graph from the MCP response
|
|
119
124
|
const raw = rpcResult.result.content;
|
|
120
|
-
const textContent = raw.find(c => c.text)?.text;
|
|
125
|
+
const textContent = raw.find((c) => c.text)?.text;
|
|
121
126
|
let parsed: Record<string, unknown> = {};
|
|
122
127
|
if (textContent) {
|
|
123
128
|
try {
|
|
@@ -129,19 +134,19 @@ export class FrameworkAbsorber {
|
|
|
129
134
|
}
|
|
130
135
|
|
|
131
136
|
return {
|
|
132
|
-
fileCount:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
? parsed.
|
|
141
|
-
:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
137
|
+
fileCount:
|
|
138
|
+
typeof parsed.file_count === 'number'
|
|
139
|
+
? parsed.file_count
|
|
140
|
+
: typeof parsed.files === 'number'
|
|
141
|
+
? parsed.files
|
|
142
|
+
: 0,
|
|
143
|
+
edgeCount:
|
|
144
|
+
typeof parsed.edge_count === 'number'
|
|
145
|
+
? parsed.edge_count
|
|
146
|
+
: typeof parsed.edges === 'number'
|
|
147
|
+
? parsed.edges
|
|
148
|
+
: 0,
|
|
149
|
+
modules: Array.isArray(parsed.modules) ? (parsed.modules as string[]) : [],
|
|
145
150
|
raw: parsed,
|
|
146
151
|
};
|
|
147
152
|
}
|
|
@@ -167,7 +172,7 @@ export class FrameworkAbsorber {
|
|
|
167
172
|
* Returns ranked improvement list with confidence scores.
|
|
168
173
|
*/
|
|
169
174
|
async findImprovements(): Promise<Improvement[]> {
|
|
170
|
-
const scan = this.lastScan || await this.runFullScan();
|
|
175
|
+
const scan = this.lastScan || (await this.runFullScan());
|
|
171
176
|
return scan.improvements.map((imp, i) => ({
|
|
172
177
|
id: `fw-imp-${i}-${Date.now()}`,
|
|
173
178
|
title: imp.title,
|