@soleri/core 2.1.0 → 2.5.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 +10 -1
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +116 -13
- 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 +34 -2
- package/dist/brain/types.d.ts.map +1 -1
- package/dist/cognee/client.d.ts +3 -0
- package/dist/cognee/client.d.ts.map +1 -1
- package/dist/cognee/client.js +17 -0
- package/dist/cognee/client.js.map +1 -1
- package/dist/cognee/sync-manager.d.ts +94 -0
- package/dist/cognee/sync-manager.d.ts.map +1 -0
- package/dist/cognee/sync-manager.js +293 -0
- package/dist/cognee/sync-manager.js.map +1 -0
- 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 +37 -1
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +199 -1
- package/dist/curator/curator.js.map +1 -1
- package/dist/errors/classify.d.ts +13 -0
- package/dist/errors/classify.d.ts.map +1 -0
- package/dist/errors/classify.js +97 -0
- package/dist/errors/classify.js.map +1 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +4 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/retry.d.ts +40 -0
- package/dist/errors/retry.d.ts.map +1 -0
- package/dist/errors/retry.js +97 -0
- package/dist/errors/retry.js.map +1 -0
- package/dist/errors/types.d.ts +48 -0
- package/dist/errors/types.d.ts.map +1 -0
- package/dist/errors/types.js +59 -0
- package/dist/errors/types.js.map +1 -0
- 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 +52 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -1
- package/dist/index.js.map +1 -1
- package/dist/intake/content-classifier.d.ts +14 -0
- package/dist/intake/content-classifier.d.ts.map +1 -0
- package/dist/intake/content-classifier.js +125 -0
- package/dist/intake/content-classifier.js.map +1 -0
- package/dist/intake/dedup-gate.d.ts +17 -0
- package/dist/intake/dedup-gate.d.ts.map +1 -0
- package/dist/intake/dedup-gate.js +66 -0
- package/dist/intake/dedup-gate.js.map +1 -0
- package/dist/intake/intake-pipeline.d.ts +63 -0
- package/dist/intake/intake-pipeline.d.ts.map +1 -0
- package/dist/intake/intake-pipeline.js +373 -0
- package/dist/intake/intake-pipeline.js.map +1 -0
- package/dist/intake/types.d.ts +65 -0
- package/dist/intake/types.d.ts.map +1 -0
- package/dist/intake/types.js +3 -0
- package/dist/intake/types.js.map +1 -0
- package/dist/intelligence/loader.js +1 -1
- package/dist/intelligence/loader.js.map +1 -1
- package/dist/intelligence/types.d.ts +3 -1
- package/dist/intelligence/types.d.ts.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 +100 -0
- package/dist/loop/loop-manager.d.ts.map +1 -0
- package/dist/loop/loop-manager.js +379 -0
- package/dist/loop/loop-manager.js.map +1 -0
- package/dist/loop/types.d.ts +103 -0
- package/dist/loop/types.d.ts.map +1 -0
- package/dist/loop/types.js +11 -0
- package/dist/loop/types.js.map +1 -0
- package/dist/persistence/index.d.ts +3 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +2 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/sqlite-provider.d.ts +25 -0
- package/dist/persistence/sqlite-provider.d.ts.map +1 -0
- package/dist/persistence/sqlite-provider.js +59 -0
- package/dist/persistence/sqlite-provider.js.map +1 -0
- package/dist/persistence/types.d.ts +36 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +8 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/planning/gap-analysis.d.ts +72 -0
- package/dist/planning/gap-analysis.d.ts.map +1 -0
- package/dist/planning/gap-analysis.js +442 -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 +421 -4
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +949 -21
- package/dist/planning/planner.js.map +1 -1
- package/dist/playbooks/generic/brainstorming.d.ts +9 -0
- package/dist/playbooks/generic/brainstorming.d.ts.map +1 -0
- package/dist/playbooks/generic/brainstorming.js +105 -0
- package/dist/playbooks/generic/brainstorming.js.map +1 -0
- package/dist/playbooks/generic/code-review.d.ts +11 -0
- package/dist/playbooks/generic/code-review.d.ts.map +1 -0
- package/dist/playbooks/generic/code-review.js +176 -0
- package/dist/playbooks/generic/code-review.js.map +1 -0
- package/dist/playbooks/generic/subagent-execution.d.ts +9 -0
- package/dist/playbooks/generic/subagent-execution.d.ts.map +1 -0
- package/dist/playbooks/generic/subagent-execution.js +68 -0
- package/dist/playbooks/generic/subagent-execution.js.map +1 -0
- package/dist/playbooks/generic/systematic-debugging.d.ts +9 -0
- package/dist/playbooks/generic/systematic-debugging.d.ts.map +1 -0
- package/dist/playbooks/generic/systematic-debugging.js +87 -0
- package/dist/playbooks/generic/systematic-debugging.js.map +1 -0
- package/dist/playbooks/generic/tdd.d.ts +9 -0
- package/dist/playbooks/generic/tdd.d.ts.map +1 -0
- package/dist/playbooks/generic/tdd.js +70 -0
- package/dist/playbooks/generic/tdd.js.map +1 -0
- package/dist/playbooks/generic/verification.d.ts +9 -0
- package/dist/playbooks/generic/verification.d.ts.map +1 -0
- package/dist/playbooks/generic/verification.js +74 -0
- package/dist/playbooks/generic/verification.js.map +1 -0
- package/dist/playbooks/index.d.ts +4 -0
- package/dist/playbooks/index.d.ts.map +1 -0
- package/dist/playbooks/index.js +5 -0
- package/dist/playbooks/index.js.map +1 -0
- package/dist/playbooks/playbook-registry.d.ts +42 -0
- package/dist/playbooks/playbook-registry.d.ts.map +1 -0
- package/dist/playbooks/playbook-registry.js +227 -0
- package/dist/playbooks/playbook-registry.js.map +1 -0
- package/dist/playbooks/playbook-seeder.d.ts +47 -0
- package/dist/playbooks/playbook-seeder.d.ts.map +1 -0
- package/dist/playbooks/playbook-seeder.js +104 -0
- package/dist/playbooks/playbook-seeder.js.map +1 -0
- package/dist/playbooks/playbook-types.d.ts +132 -0
- package/dist/playbooks/playbook-types.d.ts.map +1 -0
- package/dist/playbooks/playbook-types.js +12 -0
- package/dist/playbooks/playbook-types.js.map +1 -0
- 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 +274 -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/prompts/index.d.ts +4 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +3 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/parser.d.ts +17 -0
- package/dist/prompts/parser.d.ts.map +1 -0
- package/dist/prompts/parser.js +47 -0
- package/dist/prompts/parser.js.map +1 -0
- package/dist/prompts/template-manager.d.ts +25 -0
- package/dist/prompts/template-manager.d.ts.map +1 -0
- package/dist/prompts/template-manager.js +71 -0
- package/dist/prompts/template-manager.js.map +1 -0
- package/dist/prompts/types.d.ts +26 -0
- package/dist/prompts/types.d.ts.map +1 -0
- package/dist/prompts/types.js +5 -0
- package/dist/prompts/types.js.map +1 -0
- package/dist/runtime/admin-extra-ops.d.ts +15 -0
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -0
- package/dist/runtime/admin-extra-ops.js +595 -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 +329 -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 +363 -0
- package/dist/runtime/capture-ops.js.map +1 -0
- package/dist/runtime/cognee-sync-ops.d.ts +12 -0
- package/dist/runtime/cognee-sync-ops.d.ts.map +1 -0
- package/dist/runtime/cognee-sync-ops.js +55 -0
- package/dist/runtime/cognee-sync-ops.js.map +1 -0
- package/dist/runtime/core-ops.d.ts +9 -3
- package/dist/runtime/core-ops.d.ts.map +1 -1
- package/dist/runtime/core-ops.js +693 -10
- 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 +71 -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 +61 -15
- 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/intake-ops.d.ts +14 -0
- package/dist/runtime/intake-ops.d.ts.map +1 -0
- package/dist/runtime/intake-ops.js +110 -0
- package/dist/runtime/intake-ops.js.map +1 -0
- package/dist/runtime/loop-ops.d.ts +14 -0
- package/dist/runtime/loop-ops.d.ts.map +1 -0
- package/dist/runtime/loop-ops.js +251 -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 +246 -0
- package/dist/runtime/orchestrate-ops.js.map +1 -0
- package/dist/runtime/planning-extra-ops.d.ts +25 -0
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -0
- package/dist/runtime/planning-extra-ops.js +663 -0
- package/dist/runtime/planning-extra-ops.js.map +1 -0
- package/dist/runtime/playbook-ops.d.ts +14 -0
- package/dist/runtime/playbook-ops.d.ts.map +1 -0
- package/dist/runtime/playbook-ops.js +141 -0
- package/dist/runtime/playbook-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 +186 -0
- package/dist/runtime/project-ops.js.map +1 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +65 -3
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +29 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.d.ts +10 -0
- package/dist/runtime/vault-extra-ops.d.ts.map +1 -0
- package/dist/runtime/vault-extra-ops.js +536 -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/playbook.d.ts +34 -0
- package/dist/vault/playbook.d.ts.map +1 -0
- package/dist/vault/playbook.js +60 -0
- package/dist/vault/playbook.js.map +1 -0
- package/dist/vault/vault.d.ts +97 -4
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +424 -65
- package/dist/vault/vault.js.map +1 -1
- package/package.json +7 -3
- package/src/__tests__/admin-extra-ops.test.ts +467 -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 +134 -3
- package/src/__tests__/capture-ops.test.ts +509 -0
- package/src/__tests__/cognee-integration.test.ts +80 -0
- package/src/__tests__/cognee-sync-manager.test.ts +103 -0
- package/src/__tests__/core-ops.test.ts +292 -2
- package/src/__tests__/curator-extra-ops.test.ts +381 -0
- package/src/__tests__/domain-ops.test.ts +66 -0
- package/src/__tests__/errors.test.ts +388 -0
- package/src/__tests__/governance.test.ts +522 -0
- package/src/__tests__/grading-ops.test.ts +361 -0
- package/src/__tests__/identity-manager.test.ts +243 -0
- package/src/__tests__/intake-pipeline.test.ts +162 -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 +469 -0
- package/src/__tests__/memory-cross-project-ops.test.ts +248 -0
- package/src/__tests__/memory-extra-ops.test.ts +352 -0
- package/src/__tests__/orchestrate-ops.test.ts +289 -0
- package/src/__tests__/persistence.test.ts +225 -0
- package/src/__tests__/planner.test.ts +416 -7
- package/src/__tests__/planning-extra-ops.test.ts +706 -0
- package/src/__tests__/playbook-registry.test.ts +326 -0
- package/src/__tests__/playbook-seeder.test.ts +163 -0
- package/src/__tests__/playbook.test.ts +389 -0
- package/src/__tests__/project-ops.test.ts +381 -0
- package/src/__tests__/template-manager.test.ts +222 -0
- package/src/__tests__/vault-extra-ops.test.ts +482 -0
- package/src/brain/brain.ts +185 -16
- package/src/brain/intelligence.ts +179 -10
- package/src/brain/types.ts +40 -2
- package/src/cognee/client.ts +18 -0
- package/src/cognee/sync-manager.ts +389 -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 +295 -1
- package/src/errors/classify.ts +102 -0
- package/src/errors/index.ts +5 -0
- package/src/errors/retry.ts +132 -0
- package/src/errors/types.ts +81 -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 +213 -2
- package/src/intake/content-classifier.ts +146 -0
- package/src/intake/dedup-gate.ts +92 -0
- package/src/intake/intake-pipeline.ts +503 -0
- package/src/intake/types.ts +69 -0
- package/src/intelligence/loader.ts +1 -1
- package/src/intelligence/types.ts +3 -1
- package/src/logging/logger.ts +154 -0
- package/src/logging/types.ts +21 -0
- package/src/loop/loop-manager.ts +448 -0
- package/src/loop/types.ts +115 -0
- package/src/persistence/index.ts +7 -0
- package/src/persistence/sqlite-provider.ts +62 -0
- package/src/persistence/types.ts +44 -0
- package/src/planning/gap-analysis.ts +775 -0
- package/src/planning/gap-types.ts +61 -0
- package/src/planning/planner.ts +1273 -24
- package/src/playbooks/generic/brainstorming.ts +110 -0
- package/src/playbooks/generic/code-review.ts +181 -0
- package/src/playbooks/generic/subagent-execution.ts +74 -0
- package/src/playbooks/generic/systematic-debugging.ts +92 -0
- package/src/playbooks/generic/tdd.ts +75 -0
- package/src/playbooks/generic/verification.ts +79 -0
- package/src/playbooks/index.ts +27 -0
- package/src/playbooks/playbook-registry.ts +284 -0
- package/src/playbooks/playbook-seeder.ts +119 -0
- package/src/playbooks/playbook-types.ts +162 -0
- package/src/project/project-registry.ts +370 -0
- package/src/project/types.ts +31 -0
- package/src/prompts/index.ts +3 -0
- package/src/prompts/parser.ts +59 -0
- package/src/prompts/template-manager.ts +77 -0
- package/src/prompts/types.ts +28 -0
- package/src/runtime/admin-extra-ops.ts +652 -0
- package/src/runtime/admin-ops.ts +340 -0
- package/src/runtime/capture-ops.ts +404 -0
- package/src/runtime/cognee-sync-ops.ts +63 -0
- package/src/runtime/core-ops.ts +787 -9
- package/src/runtime/curator-extra-ops.ts +85 -0
- package/src/runtime/domain-ops.ts +67 -15
- package/src/runtime/grading-ops.ts +130 -0
- package/src/runtime/intake-ops.ts +126 -0
- package/src/runtime/loop-ops.ts +277 -0
- package/src/runtime/memory-cross-project-ops.ts +191 -0
- package/src/runtime/memory-extra-ops.ts +186 -0
- package/src/runtime/orchestrate-ops.ts +278 -0
- package/src/runtime/planning-extra-ops.ts +718 -0
- package/src/runtime/playbook-ops.ts +169 -0
- package/src/runtime/project-ops.ts +202 -0
- package/src/runtime/runtime.ts +77 -3
- package/src/runtime/types.ts +29 -0
- package/src/runtime/vault-extra-ops.ts +606 -0
- package/src/telemetry/telemetry.ts +118 -0
- package/src/vault/playbook.ts +87 -0
- package/src/vault/vault.ts +575 -98
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { createAgentRuntime } from '../runtime/runtime.js';
|
|
3
|
+
import { createAdminOps } from '../runtime/admin-ops.js';
|
|
4
|
+
import type { AgentRuntime } from '../runtime/types.js';
|
|
5
|
+
import type { OpDefinition } from '../facades/types.js';
|
|
6
|
+
|
|
7
|
+
describe('createAdminOps', () => {
|
|
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-admin',
|
|
24
|
+
vaultPath: ':memory:',
|
|
25
|
+
});
|
|
26
|
+
ops = createAdminOps(runtime);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
it('should return 8 ops', () => {
|
|
30
|
+
setup();
|
|
31
|
+
expect(ops).toHaveLength(8);
|
|
32
|
+
const names = ops.map((o) => o.name);
|
|
33
|
+
expect(names).toEqual([
|
|
34
|
+
'admin_health',
|
|
35
|
+
'admin_tool_list',
|
|
36
|
+
'admin_config',
|
|
37
|
+
'admin_vault_size',
|
|
38
|
+
'admin_uptime',
|
|
39
|
+
'admin_version',
|
|
40
|
+
'admin_reset_cache',
|
|
41
|
+
'admin_diagnostic',
|
|
42
|
+
]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// ─── admin_health ──────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
describe('admin_health', () => {
|
|
48
|
+
it('should return comprehensive health status', async () => {
|
|
49
|
+
setup();
|
|
50
|
+
const result = (await findOp('admin_health').handler({})) as Record<string, unknown>;
|
|
51
|
+
|
|
52
|
+
expect(result.status).toBe('ok');
|
|
53
|
+
expect(result.vault).toEqual({ entries: 0, domains: [] });
|
|
54
|
+
expect(result.cognee).toEqual({ available: false });
|
|
55
|
+
expect(result.llm).toHaveProperty('openai');
|
|
56
|
+
expect(result.llm).toHaveProperty('anthropic');
|
|
57
|
+
expect(result.brain).toHaveProperty('vocabularySize');
|
|
58
|
+
expect(result.brain).toHaveProperty('feedbackCount');
|
|
59
|
+
expect(result.curator).toEqual({ initialized: true });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should reflect vault entries after seed', async () => {
|
|
63
|
+
setup();
|
|
64
|
+
runtime.vault.seed([
|
|
65
|
+
{
|
|
66
|
+
id: 'ah-1',
|
|
67
|
+
type: 'pattern',
|
|
68
|
+
domain: 'testing',
|
|
69
|
+
title: 'Health Test',
|
|
70
|
+
severity: 'warning',
|
|
71
|
+
description: 'Test entry.',
|
|
72
|
+
tags: ['test'],
|
|
73
|
+
},
|
|
74
|
+
]);
|
|
75
|
+
const result = (await findOp('admin_health').handler({})) as Record<string, unknown>;
|
|
76
|
+
const vault = result.vault as { entries: number; domains: string[] };
|
|
77
|
+
expect(vault.entries).toBe(1);
|
|
78
|
+
expect(vault.domains).toContain('testing');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// ─── admin_tool_list ───────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
describe('admin_tool_list', () => {
|
|
85
|
+
it('should return fallback list without _allOps', async () => {
|
|
86
|
+
setup();
|
|
87
|
+
const result = (await findOp('admin_tool_list').handler({})) as {
|
|
88
|
+
count: number;
|
|
89
|
+
ops: Array<{ name: string }>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
expect(result.count).toBe(8);
|
|
93
|
+
expect(result.ops.map((o) => o.name)).toContain('admin_health');
|
|
94
|
+
expect(result.ops.map((o) => o.name)).toContain('admin_diagnostic');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should return injected ops when _allOps is provided', async () => {
|
|
98
|
+
setup();
|
|
99
|
+
const allOps = [
|
|
100
|
+
{ name: 'search', description: 'Search vault', auth: 'read' },
|
|
101
|
+
{ name: 'admin_health', description: 'Health check', auth: 'read' },
|
|
102
|
+
];
|
|
103
|
+
const result = (await findOp('admin_tool_list').handler({ _allOps: allOps })) as {
|
|
104
|
+
count: number;
|
|
105
|
+
ops: Array<{ name: string; description: string; auth: string }>;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
expect(result.count).toBe(2);
|
|
109
|
+
expect(result.ops[0].name).toBe('search');
|
|
110
|
+
expect(result.ops[1].name).toBe('admin_health');
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ─── admin_config ──────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
describe('admin_config', () => {
|
|
117
|
+
it('should return runtime config', async () => {
|
|
118
|
+
setup();
|
|
119
|
+
const result = (await findOp('admin_config').handler({})) as Record<string, unknown>;
|
|
120
|
+
|
|
121
|
+
expect(result.agentId).toBe('test-admin');
|
|
122
|
+
expect(result.vaultPath).toBe(':memory:');
|
|
123
|
+
expect(result.logLevel).toBe('info');
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// ─── admin_vault_size ──────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
describe('admin_vault_size', () => {
|
|
130
|
+
it('should return null size for in-memory vault', async () => {
|
|
131
|
+
setup();
|
|
132
|
+
const result = (await findOp('admin_vault_size').handler({})) as Record<string, unknown>;
|
|
133
|
+
|
|
134
|
+
expect(result.path).toBe(':memory:');
|
|
135
|
+
expect(result.sizeBytes).toBeNull();
|
|
136
|
+
expect(result.sizeHuman).toBe('in-memory');
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// ─── admin_uptime ──────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
describe('admin_uptime', () => {
|
|
143
|
+
it('should return uptime since creation', async () => {
|
|
144
|
+
setup();
|
|
145
|
+
const result = (await findOp('admin_uptime').handler({})) as Record<string, unknown>;
|
|
146
|
+
|
|
147
|
+
expect(result.createdAt).toBeDefined();
|
|
148
|
+
expect(typeof result.uptimeMs).toBe('number');
|
|
149
|
+
expect(typeof result.uptimeSec).toBe('number');
|
|
150
|
+
expect(typeof result.uptimeHuman).toBe('string');
|
|
151
|
+
expect(result.uptimeMs as number).toBeGreaterThanOrEqual(0);
|
|
152
|
+
expect(result.uptimeMs as number).toBeLessThan(5000); // should be nearly instant
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should have valid ISO date in createdAt', async () => {
|
|
156
|
+
setup();
|
|
157
|
+
const result = (await findOp('admin_uptime').handler({})) as { createdAt: string };
|
|
158
|
+
const parsed = new Date(result.createdAt);
|
|
159
|
+
expect(parsed.getTime()).toBeGreaterThan(0);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// ─── admin_version ─────────────────────────────────────────────
|
|
164
|
+
|
|
165
|
+
describe('admin_version', () => {
|
|
166
|
+
it('should return version information', async () => {
|
|
167
|
+
setup();
|
|
168
|
+
const result = (await findOp('admin_version').handler({})) as Record<string, unknown>;
|
|
169
|
+
|
|
170
|
+
expect(typeof result.core).toBe('string');
|
|
171
|
+
expect(result.node).toMatch(/^v\d+/);
|
|
172
|
+
expect(typeof result.platform).toBe('string');
|
|
173
|
+
expect(typeof result.arch).toBe('string');
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// ─── admin_reset_cache ─────────────────────────────────────────
|
|
178
|
+
|
|
179
|
+
describe('admin_reset_cache', () => {
|
|
180
|
+
it('should clear caches and return status', async () => {
|
|
181
|
+
setup();
|
|
182
|
+
const result = (await findOp('admin_reset_cache').handler({})) as Record<string, unknown>;
|
|
183
|
+
|
|
184
|
+
expect(result.cleared).toEqual(['brain_vocabulary', 'cognee_health_cache']);
|
|
185
|
+
expect(typeof (result as { brainVocabularySize: number }).brainVocabularySize).toBe('number');
|
|
186
|
+
expect(typeof (result as { cogneeAvailable: boolean }).cogneeAvailable).toBe('boolean');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('should have write auth', () => {
|
|
190
|
+
setup();
|
|
191
|
+
const op = findOp('admin_reset_cache');
|
|
192
|
+
expect(op.auth).toBe('write');
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// ─── admin_diagnostic ──────────────────────────────────────────
|
|
197
|
+
|
|
198
|
+
describe('admin_diagnostic', () => {
|
|
199
|
+
it('should return diagnostic report with all checks', async () => {
|
|
200
|
+
setup();
|
|
201
|
+
const result = (await findOp('admin_diagnostic').handler({})) as {
|
|
202
|
+
overall: string;
|
|
203
|
+
checks: Array<{ name: string; status: string; detail: string }>;
|
|
204
|
+
summary: string;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
expect(['healthy', 'degraded', 'unhealthy']).toContain(result.overall);
|
|
208
|
+
expect(result.checks.length).toBeGreaterThanOrEqual(7);
|
|
209
|
+
|
|
210
|
+
const checkNames = result.checks.map((c) => c.name);
|
|
211
|
+
expect(checkNames).toContain('vault');
|
|
212
|
+
expect(checkNames).toContain('brain_vocabulary');
|
|
213
|
+
expect(checkNames).toContain('brain_intelligence');
|
|
214
|
+
expect(checkNames).toContain('cognee');
|
|
215
|
+
expect(checkNames).toContain('llm_openai');
|
|
216
|
+
expect(checkNames).toContain('llm_anthropic');
|
|
217
|
+
expect(checkNames).toContain('curator');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should report vault as ok for empty vault', async () => {
|
|
221
|
+
setup();
|
|
222
|
+
const result = (await findOp('admin_diagnostic').handler({})) as {
|
|
223
|
+
checks: Array<{ name: string; status: string }>;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const vaultCheck = result.checks.find((c) => c.name === 'vault');
|
|
227
|
+
expect(vaultCheck?.status).toBe('ok');
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should report curator as ok', async () => {
|
|
231
|
+
setup();
|
|
232
|
+
const result = (await findOp('admin_diagnostic').handler({})) as {
|
|
233
|
+
checks: Array<{ name: string; status: string }>;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const curatorCheck = result.checks.find((c) => c.name === 'curator');
|
|
237
|
+
expect(curatorCheck?.status).toBe('ok');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('should include summary string', async () => {
|
|
241
|
+
setup();
|
|
242
|
+
const result = (await findOp('admin_diagnostic').handler({})) as { summary: string };
|
|
243
|
+
expect(result.summary).toMatch(/\d+ checks:/);
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// ─── Auth levels ───────────────────────────────────────────────
|
|
248
|
+
|
|
249
|
+
describe('auth levels', () => {
|
|
250
|
+
it('should use read auth for status ops', () => {
|
|
251
|
+
setup();
|
|
252
|
+
const readOps = [
|
|
253
|
+
'admin_health',
|
|
254
|
+
'admin_tool_list',
|
|
255
|
+
'admin_config',
|
|
256
|
+
'admin_vault_size',
|
|
257
|
+
'admin_uptime',
|
|
258
|
+
'admin_version',
|
|
259
|
+
'admin_diagnostic',
|
|
260
|
+
];
|
|
261
|
+
for (const name of readOps) {
|
|
262
|
+
expect(findOp(name).auth).toBe('read');
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('should use write auth for mutation ops', () => {
|
|
267
|
+
setup();
|
|
268
|
+
expect(findOp('admin_reset_cache').auth).toBe('write');
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
});
|
|
@@ -431,6 +431,41 @@ describe('BrainIntelligence', () => {
|
|
|
431
431
|
expect(result.failed).toContain('non-existent');
|
|
432
432
|
});
|
|
433
433
|
|
|
434
|
+
it('should gate promote through governance when strict preset', () => {
|
|
435
|
+
// Create a brain session and extract proposals
|
|
436
|
+
runtime.brainIntelligence.lifecycle({
|
|
437
|
+
action: 'start',
|
|
438
|
+
sessionId: 'gov-promo-1',
|
|
439
|
+
toolsUsed: ['w', 'w', 'w'],
|
|
440
|
+
});
|
|
441
|
+
runtime.brainIntelligence.lifecycle({ action: 'end', sessionId: 'gov-promo-1' });
|
|
442
|
+
runtime.brainIntelligence.extractKnowledge('gov-promo-1');
|
|
443
|
+
|
|
444
|
+
const proposals = runtime.brainIntelligence.getProposals({ sessionId: 'gov-promo-1' });
|
|
445
|
+
expect(proposals.length).toBeGreaterThan(0);
|
|
446
|
+
|
|
447
|
+
// Apply strict preset — requireReview: true
|
|
448
|
+
runtime.governance.applyPreset('.', 'strict', 'test');
|
|
449
|
+
|
|
450
|
+
const result = runtime.brainIntelligence.promoteProposals(
|
|
451
|
+
[proposals[0].id],
|
|
452
|
+
runtime.governance,
|
|
453
|
+
'.',
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
// Should be gated, not promoted
|
|
457
|
+
expect(result.promoted).toBe(0);
|
|
458
|
+
expect(result.gated.length).toBe(1);
|
|
459
|
+
expect(result.gated[0].action).toBe('propose');
|
|
460
|
+
|
|
461
|
+
// Entry should NOT be in vault
|
|
462
|
+
expect(runtime.vault.get(`proposal-${proposals[0].id}`)).toBeNull();
|
|
463
|
+
|
|
464
|
+
// But should be in governance proposals
|
|
465
|
+
const pending = runtime.governance.listPendingProposals('.');
|
|
466
|
+
expect(pending.some((p) => p.source === 'brain-promote')).toBe(true);
|
|
467
|
+
});
|
|
468
|
+
|
|
434
469
|
// ─── Build Intelligence ────────────────────────────────────────
|
|
435
470
|
|
|
436
471
|
it('should build intelligence pipeline', () => {
|
|
@@ -557,6 +592,7 @@ describe('BrainIntelligence', () => {
|
|
|
557
592
|
filesModified: [],
|
|
558
593
|
planId: null,
|
|
559
594
|
planOutcome: null,
|
|
595
|
+
extractedAt: null,
|
|
560
596
|
},
|
|
561
597
|
],
|
|
562
598
|
proposals: [],
|
|
@@ -609,6 +645,7 @@ describe('BrainIntelligence', () => {
|
|
|
609
645
|
filesModified: [],
|
|
610
646
|
planId: null,
|
|
611
647
|
planOutcome: null,
|
|
648
|
+
extractedAt: null,
|
|
612
649
|
},
|
|
613
650
|
],
|
|
614
651
|
proposals: [],
|
|
@@ -620,4 +657,172 @@ describe('BrainIntelligence', () => {
|
|
|
620
657
|
const result = runtime.brainIntelligence.importData(data);
|
|
621
658
|
expect(result.imported.sessions).toBe(0); // Duplicate ignored
|
|
622
659
|
});
|
|
660
|
+
|
|
661
|
+
// ─── Auto-extraction on session end ─────────────────────────
|
|
662
|
+
|
|
663
|
+
it('should auto-extract when session ends with tools used', () => {
|
|
664
|
+
runtime.brainIntelligence.lifecycle({
|
|
665
|
+
action: 'start',
|
|
666
|
+
sessionId: 'auto-1',
|
|
667
|
+
domain: 'testing',
|
|
668
|
+
toolsUsed: ['search', 'search', 'search'],
|
|
669
|
+
});
|
|
670
|
+
const session = runtime.brainIntelligence.lifecycle({
|
|
671
|
+
action: 'end',
|
|
672
|
+
sessionId: 'auto-1',
|
|
673
|
+
});
|
|
674
|
+
// extractedAt should be set automatically
|
|
675
|
+
expect(session.extractedAt).not.toBeNull();
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
it('should not auto-extract when session has no signal', () => {
|
|
679
|
+
runtime.brainIntelligence.lifecycle({
|
|
680
|
+
action: 'start',
|
|
681
|
+
sessionId: 'auto-2',
|
|
682
|
+
});
|
|
683
|
+
const session = runtime.brainIntelligence.lifecycle({
|
|
684
|
+
action: 'end',
|
|
685
|
+
sessionId: 'auto-2',
|
|
686
|
+
});
|
|
687
|
+
// No tools, no files, no plan — should not extract
|
|
688
|
+
expect(session.extractedAt).toBeNull();
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
it('should auto-extract when session has a plan', () => {
|
|
692
|
+
runtime.brainIntelligence.lifecycle({
|
|
693
|
+
action: 'start',
|
|
694
|
+
sessionId: 'auto-3',
|
|
695
|
+
planId: 'plan-123',
|
|
696
|
+
});
|
|
697
|
+
const session = runtime.brainIntelligence.lifecycle({
|
|
698
|
+
action: 'end',
|
|
699
|
+
sessionId: 'auto-3',
|
|
700
|
+
planOutcome: 'completed',
|
|
701
|
+
});
|
|
702
|
+
expect(session.extractedAt).not.toBeNull();
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
// ─── extractedAt Tracking ──────────────────────────────────
|
|
706
|
+
|
|
707
|
+
it('should set extractedAt when extractKnowledge is called manually', () => {
|
|
708
|
+
// Use a session with no tools/files/plan so auto-extraction doesn't fire
|
|
709
|
+
runtime.brainIntelligence.lifecycle({
|
|
710
|
+
action: 'start',
|
|
711
|
+
sessionId: 'ext-1',
|
|
712
|
+
domain: 'testing',
|
|
713
|
+
});
|
|
714
|
+
runtime.brainIntelligence.lifecycle({
|
|
715
|
+
action: 'end',
|
|
716
|
+
sessionId: 'ext-1',
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// Before manual extraction, extractedAt should be null (no auto-extract — no signal)
|
|
720
|
+
const ctx = runtime.brainIntelligence.getSessionContext(10);
|
|
721
|
+
const before = ctx.recentSessions.find((s) => s.id === 'ext-1');
|
|
722
|
+
expect(before?.extractedAt).toBeNull();
|
|
723
|
+
|
|
724
|
+
// Manual extract
|
|
725
|
+
runtime.brainIntelligence.extractKnowledge('ext-1');
|
|
726
|
+
|
|
727
|
+
// After extraction, extractedAt should be set
|
|
728
|
+
const ctx2 = runtime.brainIntelligence.getSessionContext(10);
|
|
729
|
+
const after = ctx2.recentSessions.find((s) => s.id === 'ext-1');
|
|
730
|
+
expect(after?.extractedAt).not.toBeNull();
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
// ─── resetExtracted ────────────────────────────────────────
|
|
734
|
+
|
|
735
|
+
it('should reset extractedAt for a specific session', () => {
|
|
736
|
+
runtime.brainIntelligence.lifecycle({
|
|
737
|
+
action: 'start',
|
|
738
|
+
sessionId: 'reset-1',
|
|
739
|
+
toolsUsed: ['a', 'a', 'a'],
|
|
740
|
+
});
|
|
741
|
+
runtime.brainIntelligence.lifecycle({ action: 'end', sessionId: 'reset-1' });
|
|
742
|
+
runtime.brainIntelligence.extractKnowledge('reset-1');
|
|
743
|
+
|
|
744
|
+
const result = runtime.brainIntelligence.resetExtracted({ sessionId: 'reset-1' });
|
|
745
|
+
expect(result.reset).toBe(1);
|
|
746
|
+
|
|
747
|
+
const ctx = runtime.brainIntelligence.getSessionContext(10);
|
|
748
|
+
const session = ctx.recentSessions.find((s) => s.id === 'reset-1');
|
|
749
|
+
expect(session?.extractedAt).toBeNull();
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
it('should reset all extracted sessions', () => {
|
|
753
|
+
runtime.brainIntelligence.lifecycle({
|
|
754
|
+
action: 'start',
|
|
755
|
+
sessionId: 'reset-a',
|
|
756
|
+
toolsUsed: ['a', 'a', 'a'],
|
|
757
|
+
});
|
|
758
|
+
runtime.brainIntelligence.lifecycle({ action: 'end', sessionId: 'reset-a' });
|
|
759
|
+
runtime.brainIntelligence.extractKnowledge('reset-a');
|
|
760
|
+
|
|
761
|
+
runtime.brainIntelligence.lifecycle({
|
|
762
|
+
action: 'start',
|
|
763
|
+
sessionId: 'reset-b',
|
|
764
|
+
toolsUsed: ['b', 'b', 'b'],
|
|
765
|
+
});
|
|
766
|
+
runtime.brainIntelligence.lifecycle({ action: 'end', sessionId: 'reset-b' });
|
|
767
|
+
runtime.brainIntelligence.extractKnowledge('reset-b');
|
|
768
|
+
|
|
769
|
+
const result = runtime.brainIntelligence.resetExtracted({ all: true });
|
|
770
|
+
expect(result.reset).toBe(2);
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
it('should return 0 when nothing to reset', () => {
|
|
774
|
+
const result = runtime.brainIntelligence.resetExtracted({ all: true });
|
|
775
|
+
expect(result.reset).toBe(0);
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
it('should return 0 when no filter is provided', () => {
|
|
779
|
+
const result = runtime.brainIntelligence.resetExtracted();
|
|
780
|
+
expect(result.reset).toBe(0);
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
it('should allow re-extraction after reset', () => {
|
|
784
|
+
runtime.brainIntelligence.lifecycle({
|
|
785
|
+
action: 'start',
|
|
786
|
+
sessionId: 'reext-1',
|
|
787
|
+
toolsUsed: ['search', 'search', 'search'],
|
|
788
|
+
});
|
|
789
|
+
runtime.brainIntelligence.lifecycle({ action: 'end', sessionId: 'reext-1' });
|
|
790
|
+
|
|
791
|
+
const first = runtime.brainIntelligence.extractKnowledge('reext-1');
|
|
792
|
+
expect(first.proposals.length).toBeGreaterThan(0);
|
|
793
|
+
|
|
794
|
+
runtime.brainIntelligence.resetExtracted({ sessionId: 'reext-1' });
|
|
795
|
+
|
|
796
|
+
const second = runtime.brainIntelligence.extractKnowledge('reext-1');
|
|
797
|
+
expect(second.proposals.length).toBeGreaterThan(0);
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
// ─── computeStrengths with modified feedback ───────────────
|
|
801
|
+
|
|
802
|
+
it('should weight modified feedback at 0.5 in computeStrengths', () => {
|
|
803
|
+
// Seed an entry for feedback to reference
|
|
804
|
+
runtime.vault.seed([
|
|
805
|
+
{
|
|
806
|
+
id: 'str-1',
|
|
807
|
+
type: 'pattern',
|
|
808
|
+
domain: 'testing',
|
|
809
|
+
title: 'Strength test pattern',
|
|
810
|
+
severity: 'warning',
|
|
811
|
+
description: 'Testing strength computation with modified feedback.',
|
|
812
|
+
tags: ['test'],
|
|
813
|
+
},
|
|
814
|
+
]);
|
|
815
|
+
|
|
816
|
+
// Record feedback: 1 accepted, 1 modified, 1 failed
|
|
817
|
+
runtime.brain.recordFeedback({ query: 'q1', entryId: 'str-1', action: 'accepted' });
|
|
818
|
+
runtime.brain.recordFeedback({ query: 'q2', entryId: 'str-1', action: 'modified' });
|
|
819
|
+
runtime.brain.recordFeedback({ query: 'q3', entryId: 'str-1', action: 'failed' });
|
|
820
|
+
|
|
821
|
+
const strengths = runtime.brainIntelligence.computeStrengths();
|
|
822
|
+
const s = strengths.find((p) => p.pattern === 'Strength test pattern');
|
|
823
|
+
expect(s).toBeDefined();
|
|
824
|
+
|
|
825
|
+
// successRate = (1 + 0.5) / (3 - 1) = 1.5/2 = 0.75
|
|
826
|
+
expect(s!.successRate).toBeCloseTo(0.75, 2);
|
|
827
|
+
});
|
|
623
828
|
});
|
|
@@ -140,7 +140,7 @@ describe('Brain', () => {
|
|
|
140
140
|
expect(breakdown).toHaveProperty('semantic');
|
|
141
141
|
expect(breakdown).toHaveProperty('vector');
|
|
142
142
|
expect(breakdown).toHaveProperty('severity');
|
|
143
|
-
expect(breakdown).toHaveProperty('
|
|
143
|
+
expect(breakdown).toHaveProperty('temporalDecay');
|
|
144
144
|
expect(breakdown).toHaveProperty('tagOverlap');
|
|
145
145
|
expect(breakdown).toHaveProperty('domainMatch');
|
|
146
146
|
expect(breakdown).toHaveProperty('total');
|
|
@@ -584,7 +584,7 @@ describe('Brain', () => {
|
|
|
584
584
|
stats.weights.semantic +
|
|
585
585
|
stats.weights.vector +
|
|
586
586
|
stats.weights.severity +
|
|
587
|
-
stats.weights.
|
|
587
|
+
stats.weights.temporalDecay +
|
|
588
588
|
stats.weights.tagOverlap +
|
|
589
589
|
stats.weights.domainMatch;
|
|
590
590
|
expect(sum).toBeCloseTo(1.0, 5);
|
|
@@ -741,6 +741,137 @@ describe('Brain', () => {
|
|
|
741
741
|
});
|
|
742
742
|
});
|
|
743
743
|
|
|
744
|
+
// ─── Enhanced Feedback ─────────────────────────────────────
|
|
745
|
+
|
|
746
|
+
describe('enhanced feedback', () => {
|
|
747
|
+
beforeEach(() => {
|
|
748
|
+
vault.seed([makeEntry({ id: 'fb-1', title: 'Feedback test pattern', tags: ['feedback'] })]);
|
|
749
|
+
brain = new Brain(vault);
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
it('should accept legacy 3-arg form (backward compat)', () => {
|
|
753
|
+
brain.recordFeedback('test query', 'fb-1', 'accepted');
|
|
754
|
+
const stats = brain.getFeedbackStats();
|
|
755
|
+
expect(stats.total).toBe(1);
|
|
756
|
+
expect(stats.byAction['accepted']).toBe(1);
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
it('should accept FeedbackInput and return FeedbackEntry', () => {
|
|
760
|
+
const entry = brain.recordFeedback({
|
|
761
|
+
query: 'test query',
|
|
762
|
+
entryId: 'fb-1',
|
|
763
|
+
action: 'modified',
|
|
764
|
+
source: 'recommendation',
|
|
765
|
+
confidence: 0.85,
|
|
766
|
+
duration: 1200,
|
|
767
|
+
reason: 'adjusted wording',
|
|
768
|
+
});
|
|
769
|
+
expect(entry).toBeDefined();
|
|
770
|
+
expect(entry.action).toBe('modified');
|
|
771
|
+
expect(entry.source).toBe('recommendation');
|
|
772
|
+
expect(entry.confidence).toBe(0.85);
|
|
773
|
+
expect(entry.duration).toBe(1200);
|
|
774
|
+
expect(entry.reason).toBe('adjusted wording');
|
|
775
|
+
expect(entry.id).toBeGreaterThan(0);
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
it('should accept modified and failed action types', () => {
|
|
779
|
+
brain.recordFeedback({ query: 'q1', entryId: 'fb-1', action: 'modified' });
|
|
780
|
+
brain.recordFeedback({ query: 'q2', entryId: 'fb-1', action: 'failed' });
|
|
781
|
+
const stats = brain.getFeedbackStats();
|
|
782
|
+
expect(stats.total).toBe(2);
|
|
783
|
+
expect(stats.byAction['modified']).toBe(1);
|
|
784
|
+
expect(stats.byAction['failed']).toBe(1);
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
it('should use default source and confidence when not provided', () => {
|
|
788
|
+
const entry = brain.recordFeedback({ query: 'q1', entryId: 'fb-1', action: 'accepted' });
|
|
789
|
+
expect(entry.source).toBe('search');
|
|
790
|
+
expect(entry.confidence).toBe(0.6);
|
|
791
|
+
});
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
// ─── Feedback Stats ───────────────────────────────────────
|
|
795
|
+
|
|
796
|
+
describe('getFeedbackStats', () => {
|
|
797
|
+
beforeEach(() => {
|
|
798
|
+
vault.seed([makeEntry({ id: 'fs-1', tags: ['stats'] })]);
|
|
799
|
+
brain = new Brain(vault);
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
it('should return zero stats on empty feedback', () => {
|
|
803
|
+
const stats = brain.getFeedbackStats();
|
|
804
|
+
expect(stats.total).toBe(0);
|
|
805
|
+
expect(stats.acceptanceRate).toBe(0);
|
|
806
|
+
expect(stats.averageConfidence).toBe(0);
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
it('should compute acceptance rate correctly', () => {
|
|
810
|
+
brain.recordFeedback('q1', 'fs-1', 'accepted');
|
|
811
|
+
brain.recordFeedback('q2', 'fs-1', 'dismissed');
|
|
812
|
+
brain.recordFeedback('q3', 'fs-1', 'accepted');
|
|
813
|
+
const stats = brain.getFeedbackStats();
|
|
814
|
+
expect(stats.total).toBe(3);
|
|
815
|
+
expect(stats.acceptanceRate).toBeCloseTo(2 / 3, 2);
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
it('should group by action and source', () => {
|
|
819
|
+
brain.recordFeedback({ query: 'q1', entryId: 'fs-1', action: 'accepted', source: 'search' });
|
|
820
|
+
brain.recordFeedback({
|
|
821
|
+
query: 'q2',
|
|
822
|
+
entryId: 'fs-1',
|
|
823
|
+
action: 'modified',
|
|
824
|
+
source: 'recommendation',
|
|
825
|
+
});
|
|
826
|
+
brain.recordFeedback({
|
|
827
|
+
query: 'q3',
|
|
828
|
+
entryId: 'fs-1',
|
|
829
|
+
action: 'failed',
|
|
830
|
+
source: 'tool-execution',
|
|
831
|
+
});
|
|
832
|
+
const stats = brain.getFeedbackStats();
|
|
833
|
+
expect(stats.byAction['accepted']).toBe(1);
|
|
834
|
+
expect(stats.byAction['modified']).toBe(1);
|
|
835
|
+
expect(stats.byAction['failed']).toBe(1);
|
|
836
|
+
expect(stats.bySource['search']).toBe(1);
|
|
837
|
+
expect(stats.bySource['recommendation']).toBe(1);
|
|
838
|
+
expect(stats.bySource['tool-execution']).toBe(1);
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
it('should compute average confidence', () => {
|
|
842
|
+
brain.recordFeedback({ query: 'q1', entryId: 'fs-1', action: 'accepted', confidence: 0.9 });
|
|
843
|
+
brain.recordFeedback({ query: 'q2', entryId: 'fs-1', action: 'dismissed', confidence: 0.3 });
|
|
844
|
+
const stats = brain.getFeedbackStats();
|
|
845
|
+
expect(stats.averageConfidence).toBeCloseTo(0.6, 2);
|
|
846
|
+
});
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
// ─── Recompute Weights with Modified/Failed ──────────────
|
|
850
|
+
|
|
851
|
+
describe('recomputeWeights with modified/failed', () => {
|
|
852
|
+
beforeEach(() => {
|
|
853
|
+
vault.seed([makeEntry({ id: 'rw-1', tags: ['weights'] })]);
|
|
854
|
+
brain = new Brain(vault);
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
it('should exclude failed from weight computation', () => {
|
|
858
|
+
// Add enough feedback to exceed threshold (30)
|
|
859
|
+
for (let i = 0; i < 20; i++) {
|
|
860
|
+
brain.recordFeedback('q', 'rw-1', 'accepted');
|
|
861
|
+
}
|
|
862
|
+
for (let i = 0; i < 10; i++) {
|
|
863
|
+
brain.recordFeedback({ query: 'q', entryId: 'rw-1', action: 'failed' });
|
|
864
|
+
}
|
|
865
|
+
// Failed entries should not count toward total for weight adaptation
|
|
866
|
+
// 20 accepted out of 20 relevant = 100% accept rate
|
|
867
|
+
const stats = brain.getStats();
|
|
868
|
+
// Weights should have adapted since we have 30+ total but only 20 non-failed
|
|
869
|
+
// (threshold is 30, total is 30, but only 20 are non-failed so threshold not met)
|
|
870
|
+
// The recomputeWeights() counts non-failed, which is 20 < 30, so weights stay default
|
|
871
|
+
expect(stats.weights.semantic).toBeCloseTo(0.4, 2);
|
|
872
|
+
});
|
|
873
|
+
});
|
|
874
|
+
|
|
744
875
|
// ─── Graceful Degradation ───────────────────────────────────
|
|
745
876
|
|
|
746
877
|
describe('graceful degradation', () => {
|
|
@@ -750,7 +881,7 @@ describe('Brain', () => {
|
|
|
750
881
|
expect(results).toEqual([]);
|
|
751
882
|
});
|
|
752
883
|
|
|
753
|
-
it('should fall back to severity +
|
|
884
|
+
it('should fall back to severity + temporalDecay scoring when vocabulary is empty', async () => {
|
|
754
885
|
vault.seed([
|
|
755
886
|
makeEntry({
|
|
756
887
|
id: 'gd-1',
|