@soleri/core 2.1.0 → 2.4.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/dist/brain/brain.d.ts +3 -1
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +60 -4
- package/dist/brain/brain.js.map +1 -1
- package/dist/brain/intelligence.d.ts +36 -1
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +119 -14
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/brain/types.d.ts +32 -0
- package/dist/brain/types.d.ts.map +1 -1
- package/dist/control/identity-manager.d.ts +22 -0
- package/dist/control/identity-manager.d.ts.map +1 -0
- package/dist/control/identity-manager.js +233 -0
- package/dist/control/identity-manager.js.map +1 -0
- package/dist/control/intent-router.d.ts +32 -0
- package/dist/control/intent-router.d.ts.map +1 -0
- package/dist/control/intent-router.js +242 -0
- package/dist/control/intent-router.js.map +1 -0
- package/dist/control/types.d.ts +68 -0
- package/dist/control/types.d.ts.map +1 -0
- package/dist/control/types.js +9 -0
- package/dist/control/types.js.map +1 -0
- package/dist/curator/curator.d.ts +29 -0
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +135 -0
- package/dist/curator/curator.js.map +1 -1
- package/dist/facades/types.d.ts +1 -1
- package/dist/governance/governance.d.ts +42 -0
- package/dist/governance/governance.d.ts.map +1 -0
- package/dist/governance/governance.js +488 -0
- package/dist/governance/governance.js.map +1 -0
- package/dist/governance/index.d.ts +3 -0
- package/dist/governance/index.d.ts.map +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/index.js.map +1 -0
- package/dist/governance/types.d.ts +102 -0
- package/dist/governance/types.d.ts.map +1 -0
- package/dist/governance/types.js +3 -0
- package/dist/governance/types.js.map +1 -0
- package/dist/index.d.ts +32 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/logging/logger.d.ts +37 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +145 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/logging/types.d.ts +19 -0
- package/dist/logging/types.d.ts.map +1 -0
- package/dist/logging/types.js +2 -0
- package/dist/logging/types.js.map +1 -0
- package/dist/loop/loop-manager.d.ts +49 -0
- package/dist/loop/loop-manager.d.ts.map +1 -0
- package/dist/loop/loop-manager.js +105 -0
- package/dist/loop/loop-manager.js.map +1 -0
- package/dist/loop/types.d.ts +35 -0
- package/dist/loop/types.d.ts.map +1 -0
- package/dist/loop/types.js +8 -0
- package/dist/loop/types.js.map +1 -0
- package/dist/planning/gap-analysis.d.ts +29 -0
- package/dist/planning/gap-analysis.d.ts.map +1 -0
- package/dist/planning/gap-analysis.js +265 -0
- package/dist/planning/gap-analysis.js.map +1 -0
- package/dist/planning/gap-types.d.ts +29 -0
- package/dist/planning/gap-types.d.ts.map +1 -0
- package/dist/planning/gap-types.js +28 -0
- package/dist/planning/gap-types.js.map +1 -0
- package/dist/planning/planner.d.ts +150 -1
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +365 -2
- package/dist/planning/planner.js.map +1 -1
- package/dist/project/project-registry.d.ts +79 -0
- package/dist/project/project-registry.d.ts.map +1 -0
- package/dist/project/project-registry.js +276 -0
- package/dist/project/project-registry.js.map +1 -0
- package/dist/project/types.d.ts +28 -0
- package/dist/project/types.d.ts.map +1 -0
- package/dist/project/types.js +5 -0
- package/dist/project/types.js.map +1 -0
- package/dist/runtime/admin-extra-ops.d.ts +13 -0
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -0
- package/dist/runtime/admin-extra-ops.js +284 -0
- package/dist/runtime/admin-extra-ops.js.map +1 -0
- package/dist/runtime/admin-ops.d.ts +15 -0
- package/dist/runtime/admin-ops.d.ts.map +1 -0
- package/dist/runtime/admin-ops.js +322 -0
- package/dist/runtime/admin-ops.js.map +1 -0
- package/dist/runtime/capture-ops.d.ts +15 -0
- package/dist/runtime/capture-ops.d.ts.map +1 -0
- package/dist/runtime/capture-ops.js +345 -0
- package/dist/runtime/capture-ops.js.map +1 -0
- package/dist/runtime/core-ops.d.ts +7 -3
- package/dist/runtime/core-ops.d.ts.map +1 -1
- package/dist/runtime/core-ops.js +474 -8
- package/dist/runtime/core-ops.js.map +1 -1
- package/dist/runtime/curator-extra-ops.d.ts +9 -0
- package/dist/runtime/curator-extra-ops.d.ts.map +1 -0
- package/dist/runtime/curator-extra-ops.js +59 -0
- package/dist/runtime/curator-extra-ops.js.map +1 -0
- package/dist/runtime/domain-ops.d.ts.map +1 -1
- package/dist/runtime/domain-ops.js +59 -13
- package/dist/runtime/domain-ops.js.map +1 -1
- package/dist/runtime/grading-ops.d.ts +14 -0
- package/dist/runtime/grading-ops.d.ts.map +1 -0
- package/dist/runtime/grading-ops.js +105 -0
- package/dist/runtime/grading-ops.js.map +1 -0
- package/dist/runtime/loop-ops.d.ts +13 -0
- package/dist/runtime/loop-ops.d.ts.map +1 -0
- package/dist/runtime/loop-ops.js +179 -0
- package/dist/runtime/loop-ops.js.map +1 -0
- package/dist/runtime/memory-cross-project-ops.d.ts +12 -0
- package/dist/runtime/memory-cross-project-ops.d.ts.map +1 -0
- package/dist/runtime/memory-cross-project-ops.js +165 -0
- package/dist/runtime/memory-cross-project-ops.js.map +1 -0
- package/dist/runtime/memory-extra-ops.d.ts +13 -0
- package/dist/runtime/memory-extra-ops.d.ts.map +1 -0
- package/dist/runtime/memory-extra-ops.js +173 -0
- package/dist/runtime/memory-extra-ops.js.map +1 -0
- package/dist/runtime/orchestrate-ops.d.ts +17 -0
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -0
- package/dist/runtime/orchestrate-ops.js +240 -0
- package/dist/runtime/orchestrate-ops.js.map +1 -0
- package/dist/runtime/planning-extra-ops.d.ts +17 -0
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -0
- package/dist/runtime/planning-extra-ops.js +300 -0
- package/dist/runtime/planning-extra-ops.js.map +1 -0
- package/dist/runtime/project-ops.d.ts +15 -0
- package/dist/runtime/project-ops.d.ts.map +1 -0
- package/dist/runtime/project-ops.js +181 -0
- package/dist/runtime/project-ops.js.map +1 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +44 -1
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +21 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.d.ts +9 -0
- package/dist/runtime/vault-extra-ops.d.ts.map +1 -0
- package/dist/runtime/vault-extra-ops.js +195 -0
- package/dist/runtime/vault-extra-ops.js.map +1 -0
- package/dist/telemetry/telemetry.d.ts +48 -0
- package/dist/telemetry/telemetry.d.ts.map +1 -0
- package/dist/telemetry/telemetry.js +87 -0
- package/dist/telemetry/telemetry.js.map +1 -0
- package/dist/vault/vault.d.ts +94 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +340 -1
- package/dist/vault/vault.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/admin-extra-ops.test.ts +420 -0
- package/src/__tests__/admin-ops.test.ts +271 -0
- package/src/__tests__/brain-intelligence.test.ts +205 -0
- package/src/__tests__/brain.test.ts +131 -0
- package/src/__tests__/capture-ops.test.ts +509 -0
- package/src/__tests__/core-ops.test.ts +266 -2
- package/src/__tests__/curator-extra-ops.test.ts +359 -0
- package/src/__tests__/domain-ops.test.ts +66 -0
- package/src/__tests__/governance.test.ts +522 -0
- package/src/__tests__/grading-ops.test.ts +340 -0
- package/src/__tests__/identity-manager.test.ts +243 -0
- package/src/__tests__/intent-router.test.ts +222 -0
- package/src/__tests__/logger.test.ts +200 -0
- package/src/__tests__/loop-ops.test.ts +398 -0
- package/src/__tests__/memory-cross-project-ops.test.ts +246 -0
- package/src/__tests__/memory-extra-ops.test.ts +352 -0
- package/src/__tests__/orchestrate-ops.test.ts +284 -0
- package/src/__tests__/planner.test.ts +331 -0
- package/src/__tests__/planning-extra-ops.test.ts +548 -0
- package/src/__tests__/project-ops.test.ts +367 -0
- package/src/__tests__/vault-extra-ops.test.ts +407 -0
- package/src/brain/brain.ts +114 -7
- package/src/brain/intelligence.ts +179 -10
- package/src/brain/types.ts +38 -0
- package/src/control/identity-manager.ts +354 -0
- package/src/control/intent-router.ts +326 -0
- package/src/control/types.ts +102 -0
- package/src/curator/curator.ts +213 -0
- package/src/governance/governance.ts +698 -0
- package/src/governance/index.ts +18 -0
- package/src/governance/types.ts +111 -0
- package/src/index.ts +102 -2
- package/src/logging/logger.ts +154 -0
- package/src/logging/types.ts +21 -0
- package/src/loop/loop-manager.ts +130 -0
- package/src/loop/types.ts +44 -0
- package/src/planning/gap-analysis.ts +506 -0
- package/src/planning/gap-types.ts +58 -0
- package/src/planning/planner.ts +478 -2
- package/src/project/project-registry.ts +358 -0
- package/src/project/types.ts +31 -0
- package/src/runtime/admin-extra-ops.ts +307 -0
- package/src/runtime/admin-ops.ts +329 -0
- package/src/runtime/capture-ops.ts +385 -0
- package/src/runtime/core-ops.ts +535 -7
- package/src/runtime/curator-extra-ops.ts +71 -0
- package/src/runtime/domain-ops.ts +65 -13
- package/src/runtime/grading-ops.ts +121 -0
- package/src/runtime/loop-ops.ts +194 -0
- package/src/runtime/memory-cross-project-ops.ts +192 -0
- package/src/runtime/memory-extra-ops.ts +186 -0
- package/src/runtime/orchestrate-ops.ts +272 -0
- package/src/runtime/planning-extra-ops.ts +327 -0
- package/src/runtime/project-ops.ts +196 -0
- package/src/runtime/runtime.ts +49 -1
- package/src/runtime/types.ts +21 -0
- package/src/runtime/vault-extra-ops.ts +225 -0
- package/src/telemetry/telemetry.ts +118 -0
- package/src/vault/vault.ts +412 -1
|
@@ -34,8 +34,8 @@ describe('createCoreOps', () => {
|
|
|
34
34
|
return op;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
it('should return
|
|
38
|
-
expect(ops.length).toBe(
|
|
37
|
+
it('should return 147 ops', () => {
|
|
38
|
+
expect(ops.length).toBe(147);
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
it('should have all expected op names', () => {
|
|
@@ -60,6 +60,8 @@ describe('createCoreOps', () => {
|
|
|
60
60
|
expect(names).toContain('complete_plan');
|
|
61
61
|
// Brain
|
|
62
62
|
expect(names).toContain('record_feedback');
|
|
63
|
+
expect(names).toContain('brain_feedback');
|
|
64
|
+
expect(names).toContain('brain_feedback_stats');
|
|
63
65
|
expect(names).toContain('rebuild_vocabulary');
|
|
64
66
|
expect(names).toContain('brain_stats');
|
|
65
67
|
expect(names).toContain('llm_status');
|
|
@@ -75,6 +77,7 @@ describe('createCoreOps', () => {
|
|
|
75
77
|
expect(names).toContain('brain_archive_sessions');
|
|
76
78
|
expect(names).toContain('brain_promote_proposals');
|
|
77
79
|
expect(names).toContain('brain_lifecycle');
|
|
80
|
+
expect(names).toContain('brain_reset_extracted');
|
|
78
81
|
// Curator
|
|
79
82
|
expect(names).toContain('curator_status');
|
|
80
83
|
expect(names).toContain('curator_detect_duplicates');
|
|
@@ -84,6 +87,134 @@ describe('createCoreOps', () => {
|
|
|
84
87
|
expect(names).toContain('curator_groom_all');
|
|
85
88
|
expect(names).toContain('curator_consolidate');
|
|
86
89
|
expect(names).toContain('curator_health_audit');
|
|
90
|
+
// Control
|
|
91
|
+
expect(names).toContain('get_identity');
|
|
92
|
+
expect(names).toContain('update_identity');
|
|
93
|
+
expect(names).toContain('add_guideline');
|
|
94
|
+
expect(names).toContain('remove_guideline');
|
|
95
|
+
expect(names).toContain('rollback_identity');
|
|
96
|
+
expect(names).toContain('route_intent');
|
|
97
|
+
expect(names).toContain('morph');
|
|
98
|
+
expect(names).toContain('get_behavior_rules');
|
|
99
|
+
// Cognee
|
|
100
|
+
expect(names).toContain('cognee_status');
|
|
101
|
+
expect(names).toContain('cognee_search');
|
|
102
|
+
expect(names).toContain('cognee_add');
|
|
103
|
+
expect(names).toContain('cognee_cognify');
|
|
104
|
+
expect(names).toContain('cognee_config');
|
|
105
|
+
// LLM
|
|
106
|
+
expect(names).toContain('llm_rotate');
|
|
107
|
+
expect(names).toContain('llm_call');
|
|
108
|
+
// Governance
|
|
109
|
+
expect(names).toContain('governance_policy');
|
|
110
|
+
expect(names).toContain('governance_proposals');
|
|
111
|
+
expect(names).toContain('governance_stats');
|
|
112
|
+
expect(names).toContain('governance_expire');
|
|
113
|
+
expect(names).toContain('governance_dashboard');
|
|
114
|
+
// Planning Extra (9)
|
|
115
|
+
expect(names).toContain('plan_iterate');
|
|
116
|
+
expect(names).toContain('plan_split');
|
|
117
|
+
expect(names).toContain('plan_reconcile');
|
|
118
|
+
expect(names).toContain('plan_complete_lifecycle');
|
|
119
|
+
expect(names).toContain('plan_dispatch');
|
|
120
|
+
expect(names).toContain('plan_review');
|
|
121
|
+
expect(names).toContain('plan_archive');
|
|
122
|
+
expect(names).toContain('plan_list_tasks');
|
|
123
|
+
expect(names).toContain('plan_stats');
|
|
124
|
+
// Memory Extra (8)
|
|
125
|
+
expect(names).toContain('memory_delete');
|
|
126
|
+
expect(names).toContain('memory_stats');
|
|
127
|
+
expect(names).toContain('memory_export');
|
|
128
|
+
expect(names).toContain('memory_import');
|
|
129
|
+
expect(names).toContain('memory_prune');
|
|
130
|
+
expect(names).toContain('memory_deduplicate');
|
|
131
|
+
expect(names).toContain('memory_topics');
|
|
132
|
+
expect(names).toContain('memory_by_project');
|
|
133
|
+
// Vault Extra (12)
|
|
134
|
+
expect(names).toContain('vault_get');
|
|
135
|
+
expect(names).toContain('vault_update');
|
|
136
|
+
expect(names).toContain('vault_remove');
|
|
137
|
+
expect(names).toContain('vault_bulk_add');
|
|
138
|
+
expect(names).toContain('vault_bulk_remove');
|
|
139
|
+
expect(names).toContain('vault_tags');
|
|
140
|
+
expect(names).toContain('vault_domains');
|
|
141
|
+
expect(names).toContain('vault_recent');
|
|
142
|
+
expect(names).toContain('vault_import');
|
|
143
|
+
expect(names).toContain('vault_seed');
|
|
144
|
+
expect(names).toContain('vault_backup');
|
|
145
|
+
expect(names).toContain('vault_age_report');
|
|
146
|
+
// Admin (8)
|
|
147
|
+
expect(names).toContain('admin_health');
|
|
148
|
+
expect(names).toContain('admin_tool_list');
|
|
149
|
+
expect(names).toContain('admin_config');
|
|
150
|
+
expect(names).toContain('admin_vault_size');
|
|
151
|
+
expect(names).toContain('admin_uptime');
|
|
152
|
+
expect(names).toContain('admin_version');
|
|
153
|
+
expect(names).toContain('admin_reset_cache');
|
|
154
|
+
expect(names).toContain('admin_diagnostic');
|
|
155
|
+
// Admin Extra (10)
|
|
156
|
+
expect(names).toContain('admin_telemetry');
|
|
157
|
+
expect(names).toContain('admin_telemetry_recent');
|
|
158
|
+
expect(names).toContain('admin_telemetry_reset');
|
|
159
|
+
expect(names).toContain('admin_permissions');
|
|
160
|
+
expect(names).toContain('admin_vault_analytics');
|
|
161
|
+
expect(names).toContain('admin_search_insights');
|
|
162
|
+
expect(names).toContain('admin_module_status');
|
|
163
|
+
expect(names).toContain('admin_env');
|
|
164
|
+
expect(names).toContain('admin_gc');
|
|
165
|
+
expect(names).toContain('admin_export_config');
|
|
166
|
+
// Loop (7)
|
|
167
|
+
expect(names).toContain('loop_start');
|
|
168
|
+
expect(names).toContain('loop_iterate');
|
|
169
|
+
expect(names).toContain('loop_status');
|
|
170
|
+
expect(names).toContain('loop_cancel');
|
|
171
|
+
expect(names).toContain('loop_history');
|
|
172
|
+
expect(names).toContain('loop_is_active');
|
|
173
|
+
expect(names).toContain('loop_complete');
|
|
174
|
+
// Orchestrate (5)
|
|
175
|
+
expect(names).toContain('orchestrate_plan');
|
|
176
|
+
expect(names).toContain('orchestrate_execute');
|
|
177
|
+
expect(names).toContain('orchestrate_complete');
|
|
178
|
+
expect(names).toContain('orchestrate_status');
|
|
179
|
+
expect(names).toContain('orchestrate_quick_capture');
|
|
180
|
+
// Grading (5)
|
|
181
|
+
expect(names).toContain('plan_grade');
|
|
182
|
+
expect(names).toContain('plan_check_history');
|
|
183
|
+
expect(names).toContain('plan_latest_check');
|
|
184
|
+
expect(names).toContain('plan_meets_grade');
|
|
185
|
+
expect(names).toContain('plan_auto_improve');
|
|
186
|
+
// Capture (4)
|
|
187
|
+
expect(names).toContain('capture_knowledge');
|
|
188
|
+
expect(names).toContain('capture_quick');
|
|
189
|
+
expect(names).toContain('search_intelligent');
|
|
190
|
+
expect(names).toContain('search_feedback');
|
|
191
|
+
// Curator Extra (4)
|
|
192
|
+
expect(names).toContain('curator_entry_history');
|
|
193
|
+
expect(names).toContain('curator_record_snapshot');
|
|
194
|
+
expect(names).toContain('curator_queue_stats');
|
|
195
|
+
expect(names).toContain('curator_enrich');
|
|
196
|
+
// Project (12)
|
|
197
|
+
expect(names).toContain('project_get');
|
|
198
|
+
expect(names).toContain('project_list');
|
|
199
|
+
expect(names).toContain('project_unregister');
|
|
200
|
+
expect(names).toContain('project_get_rules');
|
|
201
|
+
expect(names).toContain('project_list_rules');
|
|
202
|
+
expect(names).toContain('project_add_rule');
|
|
203
|
+
expect(names).toContain('project_remove_rule');
|
|
204
|
+
expect(names).toContain('project_link');
|
|
205
|
+
expect(names).toContain('project_unlink');
|
|
206
|
+
expect(names).toContain('project_get_links');
|
|
207
|
+
expect(names).toContain('project_linked_projects');
|
|
208
|
+
expect(names).toContain('project_touch');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('register should include governance summary', async () => {
|
|
212
|
+
const result = (await findOp('register').handler({ projectPath: '/tmp/test-gov-reg' })) as {
|
|
213
|
+
governance: { pendingProposals: number; quotaPercent: number; isQuotaWarning: boolean };
|
|
214
|
+
};
|
|
215
|
+
expect(typeof result.governance.pendingProposals).toBe('number');
|
|
216
|
+
expect(typeof result.governance.quotaPercent).toBe('number');
|
|
217
|
+
expect(typeof result.governance.isQuotaWarning).toBe('boolean');
|
|
87
218
|
});
|
|
88
219
|
|
|
89
220
|
it('search should query vault via brain', async () => {
|
|
@@ -196,6 +327,47 @@ describe('createCoreOps', () => {
|
|
|
196
327
|
expect(results.length).toBeGreaterThan(0);
|
|
197
328
|
});
|
|
198
329
|
|
|
330
|
+
it('brain_feedback should record enhanced feedback', async () => {
|
|
331
|
+
runtime.vault.seed([
|
|
332
|
+
{
|
|
333
|
+
id: 'bf-1',
|
|
334
|
+
type: 'pattern',
|
|
335
|
+
domain: 'testing',
|
|
336
|
+
title: 'Brain feedback test',
|
|
337
|
+
severity: 'warning',
|
|
338
|
+
description: 'Test.',
|
|
339
|
+
tags: ['test'],
|
|
340
|
+
},
|
|
341
|
+
]);
|
|
342
|
+
ops = createCoreOps(runtime);
|
|
343
|
+
const result = (await findOp('brain_feedback').handler({
|
|
344
|
+
query: 'test',
|
|
345
|
+
entryId: 'bf-1',
|
|
346
|
+
action: 'modified',
|
|
347
|
+
source: 'recommendation',
|
|
348
|
+
confidence: 0.8,
|
|
349
|
+
})) as { id: number; action: string; source: string };
|
|
350
|
+
expect(result.id).toBeGreaterThan(0);
|
|
351
|
+
expect(result.action).toBe('modified');
|
|
352
|
+
expect(result.source).toBe('recommendation');
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('brain_feedback_stats should return stats', async () => {
|
|
356
|
+
const stats = (await findOp('brain_feedback_stats').handler({})) as {
|
|
357
|
+
total: number;
|
|
358
|
+
acceptanceRate: number;
|
|
359
|
+
};
|
|
360
|
+
expect(typeof stats.total).toBe('number');
|
|
361
|
+
expect(typeof stats.acceptanceRate).toBe('number');
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('brain_reset_extracted should return reset count', async () => {
|
|
365
|
+
const result = (await findOp('brain_reset_extracted').handler({ all: true })) as {
|
|
366
|
+
reset: number;
|
|
367
|
+
};
|
|
368
|
+
expect(typeof result.reset).toBe('number');
|
|
369
|
+
});
|
|
370
|
+
|
|
199
371
|
it('export should return bundles', async () => {
|
|
200
372
|
runtime.vault.seed([
|
|
201
373
|
{
|
|
@@ -215,4 +387,96 @@ describe('createCoreOps', () => {
|
|
|
215
387
|
expect(result.exported).toBe(true);
|
|
216
388
|
expect(result.totalEntries).toBe(1);
|
|
217
389
|
});
|
|
390
|
+
|
|
391
|
+
it('cognee_status should return health check result', async () => {
|
|
392
|
+
// Cognee is not running in tests — should degrade gracefully
|
|
393
|
+
const result = (await findOp('cognee_status').handler({})) as {
|
|
394
|
+
available: boolean;
|
|
395
|
+
url: string;
|
|
396
|
+
};
|
|
397
|
+
expect(typeof result.available).toBe('boolean');
|
|
398
|
+
expect(typeof result.url).toBe('string');
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it('cognee_search should return empty when unavailable', async () => {
|
|
402
|
+
const results = (await findOp('cognee_search').handler({
|
|
403
|
+
query: 'test pattern',
|
|
404
|
+
})) as unknown[];
|
|
405
|
+
expect(results).toEqual([]);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('cognee_add should return 0 when unavailable', async () => {
|
|
409
|
+
runtime.vault.seed([
|
|
410
|
+
{
|
|
411
|
+
id: 'cog-1',
|
|
412
|
+
type: 'pattern',
|
|
413
|
+
domain: 'testing',
|
|
414
|
+
title: 'Cognee test',
|
|
415
|
+
severity: 'warning',
|
|
416
|
+
description: 'Test.',
|
|
417
|
+
tags: ['test'],
|
|
418
|
+
},
|
|
419
|
+
]);
|
|
420
|
+
const result = (await findOp('cognee_add').handler({
|
|
421
|
+
entryIds: ['cog-1'],
|
|
422
|
+
})) as { added: number };
|
|
423
|
+
expect(result.added).toBe(0);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('cognee_cognify should return unavailable when Cognee is down', async () => {
|
|
427
|
+
const result = (await findOp('cognee_cognify').handler({})) as { status: string };
|
|
428
|
+
expect(result.status).toBe('unavailable');
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('cognee_config should return config and null status', async () => {
|
|
432
|
+
const result = (await findOp('cognee_config').handler({})) as {
|
|
433
|
+
config: { baseUrl: string; dataset: string };
|
|
434
|
+
cachedStatus: null;
|
|
435
|
+
};
|
|
436
|
+
expect(result.config.baseUrl).toBe('http://localhost:8000');
|
|
437
|
+
expect(result.config.dataset).toBe('test-core-ops');
|
|
438
|
+
expect(result.cachedStatus).toBeNull();
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('llm_rotate should return rotation status', async () => {
|
|
442
|
+
const result = (await findOp('llm_rotate').handler({ provider: 'openai' })) as {
|
|
443
|
+
rotated?: boolean;
|
|
444
|
+
poolSize?: number;
|
|
445
|
+
error?: string;
|
|
446
|
+
};
|
|
447
|
+
// Either reports no keys or successfully rotates
|
|
448
|
+
expect(typeof result.rotated === 'boolean' || typeof result.error === 'string').toBe(true);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('governance_policy get should return defaults', async () => {
|
|
452
|
+
const result = (await findOp('governance_policy').handler({
|
|
453
|
+
action: 'get',
|
|
454
|
+
projectPath: '/test',
|
|
455
|
+
})) as { quotas: { maxEntriesTotal: number } };
|
|
456
|
+
expect(result.quotas.maxEntriesTotal).toBe(500);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
it('governance_stats should return quota and proposal stats', async () => {
|
|
460
|
+
const result = (await findOp('governance_stats').handler({
|
|
461
|
+
projectPath: '/test',
|
|
462
|
+
})) as {
|
|
463
|
+
quotaStatus: { total: number };
|
|
464
|
+
proposalStats: { total: number };
|
|
465
|
+
};
|
|
466
|
+
expect(typeof result.quotaStatus.total).toBe('number');
|
|
467
|
+
expect(typeof result.proposalStats.total).toBe('number');
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('governance_dashboard should return combined view', async () => {
|
|
471
|
+
const result = (await findOp('governance_dashboard').handler({
|
|
472
|
+
projectPath: '/test',
|
|
473
|
+
})) as {
|
|
474
|
+
vaultSize: number;
|
|
475
|
+
quotaPercent: number;
|
|
476
|
+
pendingProposals: number;
|
|
477
|
+
};
|
|
478
|
+
expect(typeof result.vaultSize).toBe('number');
|
|
479
|
+
expect(typeof result.quotaPercent).toBe('number');
|
|
480
|
+
expect(result.pendingProposals).toBe(0);
|
|
481
|
+
});
|
|
218
482
|
});
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { createAgentRuntime } from '../runtime/runtime.js';
|
|
3
|
+
import { createCuratorExtraOps } from '../runtime/curator-extra-ops.js';
|
|
4
|
+
import type { AgentRuntime } from '../runtime/types.js';
|
|
5
|
+
import type { OpDefinition } from '../facades/types.js';
|
|
6
|
+
|
|
7
|
+
describe('createCuratorExtraOps', () => {
|
|
8
|
+
let runtime: AgentRuntime;
|
|
9
|
+
let ops: OpDefinition[];
|
|
10
|
+
|
|
11
|
+
function findOp(name: string): OpDefinition {
|
|
12
|
+
const op = ops.find((o) => o.name === name);
|
|
13
|
+
if (!op) throw new Error(`Op "${name}" not found`);
|
|
14
|
+
return op;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
runtime?.close();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
function setup() {
|
|
22
|
+
runtime = createAgentRuntime({
|
|
23
|
+
agentId: 'test-curator-extra',
|
|
24
|
+
vaultPath: ':memory:',
|
|
25
|
+
});
|
|
26
|
+
ops = createCuratorExtraOps(runtime);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
it('should return 4 ops', () => {
|
|
30
|
+
setup();
|
|
31
|
+
expect(ops).toHaveLength(4);
|
|
32
|
+
const names = ops.map((o) => o.name);
|
|
33
|
+
expect(names).toEqual([
|
|
34
|
+
'curator_entry_history',
|
|
35
|
+
'curator_record_snapshot',
|
|
36
|
+
'curator_queue_stats',
|
|
37
|
+
'curator_enrich',
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// ─── curator_record_snapshot ───────────────────────────────────
|
|
42
|
+
|
|
43
|
+
describe('curator_record_snapshot', () => {
|
|
44
|
+
it('should record a snapshot and return historyId', async () => {
|
|
45
|
+
setup();
|
|
46
|
+
runtime.vault.seed([
|
|
47
|
+
{
|
|
48
|
+
id: 'snap-1',
|
|
49
|
+
type: 'pattern',
|
|
50
|
+
domain: 'testing',
|
|
51
|
+
title: 'Snapshot Test',
|
|
52
|
+
severity: 'warning',
|
|
53
|
+
description: 'A test entry for snapshots.',
|
|
54
|
+
tags: ['test'],
|
|
55
|
+
},
|
|
56
|
+
]);
|
|
57
|
+
const result = (await findOp('curator_record_snapshot').handler({
|
|
58
|
+
entryId: 'snap-1',
|
|
59
|
+
changedBy: 'user',
|
|
60
|
+
changeReason: 'manual snapshot',
|
|
61
|
+
})) as { recorded: boolean; historyId: number };
|
|
62
|
+
|
|
63
|
+
expect(result.recorded).toBe(true);
|
|
64
|
+
expect(result.historyId).toBeGreaterThan(0);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should return recorded false for missing entry', async () => {
|
|
68
|
+
setup();
|
|
69
|
+
const result = (await findOp('curator_record_snapshot').handler({
|
|
70
|
+
entryId: 'nonexistent',
|
|
71
|
+
})) as { recorded: boolean; historyId: number };
|
|
72
|
+
|
|
73
|
+
expect(result.recorded).toBe(false);
|
|
74
|
+
expect(result.historyId).toBe(-1);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// ─── curator_entry_history ─────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
describe('curator_entry_history', () => {
|
|
81
|
+
it('should return version history with 2 snapshots in order', async () => {
|
|
82
|
+
setup();
|
|
83
|
+
runtime.vault.seed([
|
|
84
|
+
{
|
|
85
|
+
id: 'hist-1',
|
|
86
|
+
type: 'pattern',
|
|
87
|
+
domain: 'testing',
|
|
88
|
+
title: 'History Test',
|
|
89
|
+
severity: 'warning',
|
|
90
|
+
description: 'Entry for history test.',
|
|
91
|
+
tags: ['test'],
|
|
92
|
+
},
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
// Record two snapshots
|
|
96
|
+
runtime.curator.recordSnapshot('hist-1', 'user', 'first snapshot');
|
|
97
|
+
runtime.curator.recordSnapshot('hist-1', 'system', 'second snapshot');
|
|
98
|
+
|
|
99
|
+
const result = (await findOp('curator_entry_history').handler({
|
|
100
|
+
entryId: 'hist-1',
|
|
101
|
+
})) as {
|
|
102
|
+
entryId: string;
|
|
103
|
+
history: Array<{
|
|
104
|
+
historyId: number;
|
|
105
|
+
entryId: string;
|
|
106
|
+
snapshot: { title: string };
|
|
107
|
+
changedBy: string;
|
|
108
|
+
changeReason: string | null;
|
|
109
|
+
createdAt: number;
|
|
110
|
+
}>;
|
|
111
|
+
count: number;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
expect(result.entryId).toBe('hist-1');
|
|
115
|
+
expect(result.count).toBe(2);
|
|
116
|
+
expect(result.history).toHaveLength(2);
|
|
117
|
+
// First snapshot first (ASC order)
|
|
118
|
+
expect(result.history[0].changedBy).toBe('user');
|
|
119
|
+
expect(result.history[0].changeReason).toBe('first snapshot');
|
|
120
|
+
expect(result.history[0].snapshot.title).toBe('History Test');
|
|
121
|
+
expect(result.history[1].changedBy).toBe('system');
|
|
122
|
+
expect(result.history[1].changeReason).toBe('second snapshot');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should return empty history for entry with no snapshots', async () => {
|
|
126
|
+
setup();
|
|
127
|
+
runtime.vault.seed([
|
|
128
|
+
{
|
|
129
|
+
id: 'hist-2',
|
|
130
|
+
type: 'pattern',
|
|
131
|
+
domain: 'testing',
|
|
132
|
+
title: 'No History',
|
|
133
|
+
severity: 'warning',
|
|
134
|
+
description: 'Entry with no history.',
|
|
135
|
+
tags: ['test'],
|
|
136
|
+
},
|
|
137
|
+
]);
|
|
138
|
+
|
|
139
|
+
const result = (await findOp('curator_entry_history').handler({
|
|
140
|
+
entryId: 'hist-2',
|
|
141
|
+
})) as { count: number };
|
|
142
|
+
|
|
143
|
+
expect(result.count).toBe(0);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ─── curator_queue_stats ───────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
describe('curator_queue_stats', () => {
|
|
150
|
+
it('should return correct grooming stats', async () => {
|
|
151
|
+
setup();
|
|
152
|
+
// Seed 3 entries
|
|
153
|
+
runtime.vault.seed([
|
|
154
|
+
{
|
|
155
|
+
id: 'qs-1',
|
|
156
|
+
type: 'pattern',
|
|
157
|
+
domain: 'testing',
|
|
158
|
+
title: 'Queue A',
|
|
159
|
+
severity: 'warning',
|
|
160
|
+
description: 'Test.',
|
|
161
|
+
tags: ['test'],
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: 'qs-2',
|
|
165
|
+
type: 'pattern',
|
|
166
|
+
domain: 'testing',
|
|
167
|
+
title: 'Queue B',
|
|
168
|
+
severity: 'warning',
|
|
169
|
+
description: 'Test.',
|
|
170
|
+
tags: ['test'],
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
id: 'qs-3',
|
|
174
|
+
type: 'pattern',
|
|
175
|
+
domain: 'testing',
|
|
176
|
+
title: 'Queue C',
|
|
177
|
+
severity: 'warning',
|
|
178
|
+
description: 'Test.',
|
|
179
|
+
tags: ['test'],
|
|
180
|
+
},
|
|
181
|
+
]);
|
|
182
|
+
|
|
183
|
+
// Groom only 2 of the 3
|
|
184
|
+
runtime.curator.groomEntry('qs-1');
|
|
185
|
+
runtime.curator.groomEntry('qs-2');
|
|
186
|
+
|
|
187
|
+
const result = (await findOp('curator_queue_stats').handler({})) as {
|
|
188
|
+
totalEntries: number;
|
|
189
|
+
groomedEntries: number;
|
|
190
|
+
ungroomedEntries: number;
|
|
191
|
+
staleEntries: number;
|
|
192
|
+
freshEntries: number;
|
|
193
|
+
avgDaysSinceGroom: number;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
expect(result.totalEntries).toBe(3);
|
|
197
|
+
expect(result.groomedEntries).toBe(2);
|
|
198
|
+
expect(result.ungroomedEntries).toBe(1);
|
|
199
|
+
// Just groomed, so they should be fresh
|
|
200
|
+
expect(result.freshEntries).toBe(2);
|
|
201
|
+
expect(result.staleEntries).toBe(0);
|
|
202
|
+
expect(result.avgDaysSinceGroom).toBeGreaterThanOrEqual(0);
|
|
203
|
+
expect(result.avgDaysSinceGroom).toBeLessThan(1);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should return zeroes for empty vault', async () => {
|
|
207
|
+
setup();
|
|
208
|
+
const result = (await findOp('curator_queue_stats').handler({})) as {
|
|
209
|
+
totalEntries: number;
|
|
210
|
+
groomedEntries: number;
|
|
211
|
+
ungroomedEntries: number;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
expect(result.totalEntries).toBe(0);
|
|
215
|
+
expect(result.groomedEntries).toBe(0);
|
|
216
|
+
expect(result.ungroomedEntries).toBe(0);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// ─── curator_enrich ────────────────────────────────────────────
|
|
221
|
+
|
|
222
|
+
describe('curator_enrich', () => {
|
|
223
|
+
it('should enrich entry with messy metadata', async () => {
|
|
224
|
+
setup();
|
|
225
|
+
runtime.vault.seed([
|
|
226
|
+
{
|
|
227
|
+
id: 'enrich-1',
|
|
228
|
+
type: 'pattern',
|
|
229
|
+
domain: 'testing',
|
|
230
|
+
title: 'avoid using any types',
|
|
231
|
+
severity: 'suggestion',
|
|
232
|
+
description: ' You should avoid using any types in TypeScript. ',
|
|
233
|
+
tags: ['TypeScript', ' testing ', 'typescript'],
|
|
234
|
+
},
|
|
235
|
+
]);
|
|
236
|
+
|
|
237
|
+
const result = (await findOp('curator_enrich').handler({
|
|
238
|
+
entryId: 'enrich-1',
|
|
239
|
+
})) as {
|
|
240
|
+
enriched: boolean;
|
|
241
|
+
changes: Array<{ field: string; before: string; after: string }>;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
expect(result.enriched).toBe(true);
|
|
245
|
+
expect(result.changes.length).toBeGreaterThan(0);
|
|
246
|
+
|
|
247
|
+
// Check specific changes
|
|
248
|
+
const fieldNames = result.changes.map((c) => c.field);
|
|
249
|
+
|
|
250
|
+
// Title should be capitalized
|
|
251
|
+
expect(fieldNames).toContain('title');
|
|
252
|
+
const titleChange = result.changes.find((c) => c.field === 'title')!;
|
|
253
|
+
expect(titleChange.after).toBe('Avoid using any types');
|
|
254
|
+
|
|
255
|
+
// Tags should be normalized (lowercase, trimmed, deduped)
|
|
256
|
+
expect(fieldNames).toContain('tags');
|
|
257
|
+
const tagChange = result.changes.find((c) => c.field === 'tags')!;
|
|
258
|
+
const normalizedTags = JSON.parse(tagChange.after);
|
|
259
|
+
expect(normalizedTags).toEqual(['typescript', 'testing']);
|
|
260
|
+
|
|
261
|
+
// Type should be inferred as anti-pattern (starts with "avoid")
|
|
262
|
+
expect(fieldNames).toContain('type');
|
|
263
|
+
const typeChange = result.changes.find((c) => c.field === 'type')!;
|
|
264
|
+
expect(typeChange.after).toBe('anti-pattern');
|
|
265
|
+
|
|
266
|
+
// Description should be trimmed
|
|
267
|
+
expect(fieldNames).toContain('description');
|
|
268
|
+
const descChange = result.changes.find((c) => c.field === 'description')!;
|
|
269
|
+
expect(descChange.after).toBe('You should avoid using any types in TypeScript.');
|
|
270
|
+
|
|
271
|
+
// Verify the entry was actually updated in the vault
|
|
272
|
+
const updated = runtime.vault.get('enrich-1');
|
|
273
|
+
expect(updated).not.toBeNull();
|
|
274
|
+
expect(updated!.type).toBe('anti-pattern');
|
|
275
|
+
expect(updated!.title).toBe('Avoid using any types');
|
|
276
|
+
|
|
277
|
+
// Verify a snapshot was recorded
|
|
278
|
+
const history = runtime.curator.getVersionHistory('enrich-1');
|
|
279
|
+
expect(history.length).toBeGreaterThan(0);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('should return enriched false for clean entry', async () => {
|
|
283
|
+
setup();
|
|
284
|
+
runtime.vault.seed([
|
|
285
|
+
{
|
|
286
|
+
id: 'enrich-2',
|
|
287
|
+
type: 'pattern',
|
|
288
|
+
domain: 'testing',
|
|
289
|
+
title: 'Clean entry with proper metadata',
|
|
290
|
+
severity: 'warning',
|
|
291
|
+
description: 'This entry is already clean.',
|
|
292
|
+
tags: ['clean', 'testing'],
|
|
293
|
+
},
|
|
294
|
+
]);
|
|
295
|
+
|
|
296
|
+
const result = (await findOp('curator_enrich').handler({
|
|
297
|
+
entryId: 'enrich-2',
|
|
298
|
+
})) as {
|
|
299
|
+
enriched: boolean;
|
|
300
|
+
changes: Array<{ field: string; before: string; after: string }>;
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
expect(result.enriched).toBe(false);
|
|
304
|
+
expect(result.changes).toEqual([]);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should return enriched false for missing entry', async () => {
|
|
308
|
+
setup();
|
|
309
|
+
const result = (await findOp('curator_enrich').handler({
|
|
310
|
+
entryId: 'nonexistent',
|
|
311
|
+
})) as { enriched: boolean };
|
|
312
|
+
|
|
313
|
+
expect(result.enriched).toBe(false);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('should infer severity from critical keywords', async () => {
|
|
317
|
+
setup();
|
|
318
|
+
runtime.vault.seed([
|
|
319
|
+
{
|
|
320
|
+
id: 'enrich-3',
|
|
321
|
+
type: 'rule',
|
|
322
|
+
domain: 'security',
|
|
323
|
+
title: 'Never expose API keys',
|
|
324
|
+
severity: 'suggestion',
|
|
325
|
+
description: 'API keys must not be committed to version control.',
|
|
326
|
+
tags: ['security'],
|
|
327
|
+
},
|
|
328
|
+
]);
|
|
329
|
+
|
|
330
|
+
const result = (await findOp('curator_enrich').handler({
|
|
331
|
+
entryId: 'enrich-3',
|
|
332
|
+
})) as {
|
|
333
|
+
enriched: boolean;
|
|
334
|
+
changes: Array<{ field: string; before: string; after: string }>;
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
expect(result.enriched).toBe(true);
|
|
338
|
+
const severityChange = result.changes.find((c) => c.field === 'severity');
|
|
339
|
+
expect(severityChange).toBeDefined();
|
|
340
|
+
expect(severityChange!.after).toBe('critical');
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// ─── Auth levels ───────────────────────────────────────────────
|
|
345
|
+
|
|
346
|
+
describe('auth levels', () => {
|
|
347
|
+
it('should use read auth for query ops', () => {
|
|
348
|
+
setup();
|
|
349
|
+
expect(findOp('curator_entry_history').auth).toBe('read');
|
|
350
|
+
expect(findOp('curator_queue_stats').auth).toBe('read');
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('should use write auth for mutation ops', () => {
|
|
354
|
+
setup();
|
|
355
|
+
expect(findOp('curator_record_snapshot').auth).toBe('write');
|
|
356
|
+
expect(findOp('curator_enrich').auth).toBe('write');
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
});
|