@soleri/core 9.2.0 → 9.3.1
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/data/flows/build.flow.yaml +8 -9
- package/data/flows/deliver.flow.yaml +9 -10
- package/data/flows/design.flow.yaml +3 -4
- package/data/flows/enhance.flow.yaml +5 -6
- package/data/flows/explore.flow.yaml +3 -4
- package/data/flows/fix.flow.yaml +5 -6
- package/data/flows/plan.flow.yaml +4 -5
- package/data/flows/review.flow.yaml +3 -4
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +98 -22
- package/dist/curator/curator.js.map +1 -1
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/module-manifest.d.ts +2 -0
- package/dist/engine/module-manifest.d.ts.map +1 -1
- package/dist/engine/module-manifest.js +136 -1
- package/dist/engine/module-manifest.js.map +1 -1
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +25 -1
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/flows/gate-evaluator.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/operator/operator-profile.d.ts.map +1 -1
- package/dist/operator/operator-profile.js +11 -5
- package/dist/operator/operator-profile.js.map +1 -1
- package/dist/operator/operator-signals.d.ts.map +1 -1
- package/dist/operator/operator-signals.js.map +1 -1
- package/dist/planning/evidence-collector.js.map +1 -1
- package/dist/planning/gap-passes.d.ts.map +1 -1
- package/dist/planning/gap-passes.js +23 -6
- package/dist/planning/gap-passes.js.map +1 -1
- package/dist/planning/gap-patterns.d.ts.map +1 -1
- package/dist/planning/gap-patterns.js +57 -11
- package/dist/planning/gap-patterns.js.map +1 -1
- package/dist/planning/github-projection.d.ts.map +1 -1
- package/dist/planning/github-projection.js +39 -20
- package/dist/planning/github-projection.js.map +1 -1
- package/dist/planning/impact-analyzer.d.ts.map +1 -1
- package/dist/planning/impact-analyzer.js +20 -18
- package/dist/planning/impact-analyzer.js.map +1 -1
- package/dist/planning/plan-lifecycle.d.ts.map +1 -1
- package/dist/planning/plan-lifecycle.js +22 -9
- package/dist/planning/plan-lifecycle.js.map +1 -1
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +60 -17
- package/dist/planning/planner.js.map +1 -1
- package/dist/planning/rationalization-detector.d.ts.map +1 -1
- package/dist/planning/rationalization-detector.js.map +1 -1
- package/dist/planning/reconciliation-engine.d.ts.map +1 -1
- package/dist/planning/reconciliation-engine.js.map +1 -1
- package/dist/planning/task-complexity-assessor.d.ts +42 -0
- package/dist/planning/task-complexity-assessor.d.ts.map +1 -0
- package/dist/planning/task-complexity-assessor.js +132 -0
- package/dist/planning/task-complexity-assessor.js.map +1 -0
- package/dist/planning/task-verifier.d.ts.map +1 -1
- package/dist/planning/task-verifier.js +14 -6
- package/dist/planning/task-verifier.js.map +1 -1
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +18 -0
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
- package/dist/runtime/admin-setup-ops.js +2 -1
- package/dist/runtime/admin-setup-ops.js.map +1 -1
- package/dist/runtime/branching-ops.d.ts +12 -0
- package/dist/runtime/branching-ops.d.ts.map +1 -0
- package/dist/runtime/branching-ops.js +100 -0
- package/dist/runtime/branching-ops.js.map +1 -0
- package/dist/runtime/context-health.d.ts.map +1 -1
- package/dist/runtime/context-health.js.map +1 -1
- package/dist/runtime/facades/branching-facade.d.ts +7 -0
- package/dist/runtime/facades/branching-facade.d.ts.map +1 -0
- package/dist/runtime/facades/branching-facade.js +8 -0
- package/dist/runtime/facades/branching-facade.js.map +1 -0
- package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -1
- package/dist/runtime/facades/chat-service-ops.js +3 -1
- package/dist/runtime/facades/chat-service-ops.js.map +1 -1
- package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -1
- package/dist/runtime/facades/chat-transport-ops.js.map +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +42 -0
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/intake-facade.d.ts +9 -0
- package/dist/runtime/facades/intake-facade.d.ts.map +1 -0
- package/dist/runtime/facades/intake-facade.js +11 -0
- package/dist/runtime/facades/intake-facade.js.map +1 -0
- package/dist/runtime/facades/links-facade.d.ts +9 -0
- package/dist/runtime/facades/links-facade.d.ts.map +1 -0
- package/dist/runtime/facades/links-facade.js +10 -0
- package/dist/runtime/facades/links-facade.js.map +1 -0
- package/dist/runtime/facades/operator-facade.d.ts.map +1 -1
- package/dist/runtime/facades/operator-facade.js.map +1 -1
- package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
- package/dist/runtime/facades/plan-facade.js +4 -1
- package/dist/runtime/facades/plan-facade.js.map +1 -1
- package/dist/runtime/facades/tier-facade.d.ts +7 -0
- package/dist/runtime/facades/tier-facade.d.ts.map +1 -0
- package/dist/runtime/facades/tier-facade.js +8 -0
- package/dist/runtime/facades/tier-facade.js.map +1 -0
- package/dist/runtime/facades/vault-facade.d.ts +9 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +44 -187
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/github-integration.d.ts.map +1 -1
- package/dist/runtime/github-integration.js +11 -4
- package/dist/runtime/github-integration.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +75 -42
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +3 -1
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/session-briefing.d.ts.map +1 -1
- package/dist/runtime/session-briefing.js +5 -1
- package/dist/runtime/session-briefing.js.map +1 -1
- package/dist/runtime/tier-ops.d.ts +13 -0
- package/dist/runtime/tier-ops.d.ts.map +1 -0
- package/dist/runtime/tier-ops.js +110 -0
- package/dist/runtime/tier-ops.js.map +1 -0
- package/dist/skills/sync-skills.d.ts.map +1 -1
- package/dist/skills/sync-skills.js +1 -1
- package/dist/skills/sync-skills.js.map +1 -1
- package/dist/vault/linking.d.ts.map +1 -1
- package/dist/vault/linking.js +41 -5
- package/dist/vault/linking.js.map +1 -1
- package/dist/vault/vault-entries.d.ts.map +1 -1
- package/dist/vault/vault-entries.js +68 -26
- package/dist/vault/vault-entries.js.map +1 -1
- package/dist/vault/vault-maintenance.d.ts.map +1 -1
- package/dist/vault/vault-maintenance.js +6 -2
- package/dist/vault/vault-maintenance.js.map +1 -1
- package/dist/vault/vault-markdown-sync.d.ts.map +1 -1
- package/dist/vault/vault-markdown-sync.js.map +1 -1
- package/dist/vault/vault-memories.d.ts.map +1 -1
- package/dist/vault/vault-memories.js +3 -1
- package/dist/vault/vault-memories.js.map +1 -1
- package/dist/vault/vault-schema.js +36 -10
- package/dist/vault/vault-schema.js.map +1 -1
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +5 -1
- package/dist/vault/vault.js.map +1 -1
- package/package.json +7 -7
- package/src/agency/agency-manager.test.ts +60 -40
- package/src/agency/default-rules.test.ts +17 -9
- package/src/capabilities/registry.test.ts +2 -12
- package/src/chat/agent-loop.test.ts +33 -43
- package/src/chat/mcp-bridge.test.ts +7 -2
- package/src/claudemd/inject.test.ts +2 -12
- package/src/context/context-engine.test.ts +96 -51
- package/src/control/intent-router.test.ts +3 -3
- package/src/curator/classifier.test.ts +14 -8
- package/src/curator/contradiction-detector.test.ts +30 -5
- package/src/curator/curator.ts +278 -56
- package/src/curator/duplicate-detector.test.ts +77 -15
- package/src/curator/quality-gate.test.ts +71 -31
- package/src/curator/tag-manager.test.ts +12 -4
- package/src/domain-packs/knowledge-installer.test.ts +2 -10
- package/src/domain-packs/token-resolver.test.ts +1 -3
- package/src/domain-packs/types.test.ts +16 -2
- package/src/enforcement/registry.test.ts +2 -8
- package/src/engine/bin/soleri-engine.ts +3 -1
- package/src/engine/module-manifest.test.ts +48 -4
- package/src/engine/module-manifest.ts +138 -1
- package/src/engine/register-engine.test.ts +6 -1
- package/src/engine/register-engine.ts +26 -3
- package/src/errors/classify.test.ts +6 -2
- package/src/errors/retry.test.ts +1 -4
- package/src/facades/facade-factory.test.ts +110 -64
- package/src/flows/epilogue.test.ts +16 -10
- package/src/flows/gate-evaluator.test.ts +12 -6
- package/src/flows/gate-evaluator.ts +1 -3
- package/src/governance/governance.test.ts +137 -21
- package/src/health/health-registry.test.ts +8 -1
- package/src/index.ts +8 -0
- package/src/intake/content-classifier.test.ts +121 -51
- package/src/intake/dedup-gate.test.ts +38 -22
- package/src/intake/intake-pipeline.test.ts +5 -3
- package/src/intake/text-ingester.test.ts +26 -20
- package/src/llm/key-pool.test.ts +1 -3
- package/src/llm/llm-client.test.ts +1 -4
- package/src/llm/oauth-discovery.test.ts +16 -16
- package/src/llm/utils.test.ts +62 -18
- package/src/logging/logger.test.ts +4 -1
- package/src/loop/loop-manager.test.ts +2 -6
- package/src/migrations/migration-runner.edge-cases.test.ts +2 -7
- package/src/operator/operator-profile-extended.test.ts +15 -5
- package/src/operator/operator-profile.test.ts +26 -8
- package/src/operator/operator-profile.ts +38 -22
- package/src/operator/operator-signals-extended.test.ts +35 -23
- package/src/operator/operator-signals.test.ts +6 -10
- package/src/operator/operator-signals.ts +2 -1
- package/src/operator/prompts/hook-precompact-operator-dispatch.md +10 -6
- package/src/operator/prompts/subagent-soft-signal-extractor.md +5 -0
- package/src/operator/prompts/subagent-synthesis-cognition.md +19 -10
- package/src/operator/prompts/subagent-synthesis-communication.md +13 -7
- package/src/operator/prompts/subagent-synthesis-technical.md +19 -9
- package/src/operator/prompts/subagent-synthesis-trust.md +27 -21
- package/src/persona/defaults.test.ts +1 -5
- package/src/planning/evidence-collector.test.ts +147 -38
- package/src/planning/evidence-collector.ts +1 -4
- package/src/planning/gap-analysis-alternatives.test.ts +41 -11
- package/src/planning/gap-passes.test.ts +215 -33
- package/src/planning/gap-passes.ts +115 -46
- package/src/planning/gap-patterns.test.ts +87 -13
- package/src/planning/gap-patterns.ts +114 -31
- package/src/planning/github-projection.test.ts +6 -1
- package/src/planning/github-projection.ts +41 -20
- package/src/planning/impact-analyzer.test.ts +10 -23
- package/src/planning/impact-analyzer.ts +33 -46
- package/src/planning/plan-lifecycle.test.ts +103 -36
- package/src/planning/plan-lifecycle.ts +49 -18
- package/src/planning/planner.test.ts +12 -2
- package/src/planning/planner.ts +198 -58
- package/src/planning/rationalization-detector.test.ts +5 -20
- package/src/planning/rationalization-detector.ts +14 -16
- package/src/planning/reconciliation-engine.test.ts +20 -3
- package/src/planning/reconciliation-engine.ts +1 -2
- package/src/planning/task-complexity-assessor.test.ts +298 -0
- package/src/planning/task-complexity-assessor.ts +183 -0
- package/src/planning/task-verifier.test.ts +59 -27
- package/src/planning/task-verifier.ts +15 -9
- package/src/playbooks/playbook-executor.test.ts +1 -3
- package/src/plugins/plugin-loader.test.ts +19 -14
- package/src/plugins/plugin-registry.test.ts +45 -33
- package/src/project/project-registry.test.ts +23 -12
- package/src/prompts/template-manager.test.ts +4 -1
- package/src/queue/job-queue.test.ts +10 -14
- package/src/runtime/admin-extra-ops.test.ts +5 -19
- package/src/runtime/admin-ops.test.ts +22 -1
- package/src/runtime/admin-ops.ts +19 -0
- package/src/runtime/admin-setup-ops.test.ts +3 -4
- package/src/runtime/admin-setup-ops.ts +9 -2
- package/src/runtime/archive-ops.test.ts +4 -1
- package/src/runtime/branching-ops.test.ts +144 -0
- package/src/runtime/branching-ops.ts +107 -0
- package/src/runtime/capture-ops.test.ts +7 -21
- package/src/runtime/chain-ops.test.ts +16 -6
- package/src/runtime/claude-md-helpers.test.ts +1 -3
- package/src/runtime/context-health.test.ts +1 -3
- package/src/runtime/context-health.ts +1 -3
- package/src/runtime/curator-extra-ops.test.ts +3 -1
- package/src/runtime/domain-ops.test.ts +46 -36
- package/src/runtime/facades/admin-facade.test.ts +1 -4
- package/src/runtime/facades/archive-facade.test.ts +21 -7
- package/src/runtime/facades/brain-facade.test.ts +176 -72
- package/src/runtime/facades/branching-facade.test.ts +43 -0
- package/src/runtime/facades/branching-facade.ts +11 -0
- package/src/runtime/facades/chat-facade.test.ts +81 -28
- package/src/runtime/facades/chat-service-ops.test.ts +178 -73
- package/src/runtime/facades/chat-service-ops.ts +3 -1
- package/src/runtime/facades/chat-session-ops.test.ts +25 -10
- package/src/runtime/facades/chat-transport-ops.test.ts +101 -34
- package/src/runtime/facades/chat-transport-ops.ts +0 -1
- package/src/runtime/facades/context-facade.test.ts +19 -4
- package/src/runtime/facades/control-facade.test.ts +3 -3
- package/src/runtime/facades/index.ts +42 -0
- package/src/runtime/facades/intake-facade.test.ts +215 -0
- package/src/runtime/facades/intake-facade.ts +14 -0
- package/src/runtime/facades/links-facade.test.ts +203 -0
- package/src/runtime/facades/links-facade.ts +13 -0
- package/src/runtime/facades/loop-facade.test.ts +22 -5
- package/src/runtime/facades/memory-facade.test.ts +19 -5
- package/src/runtime/facades/operator-facade.test.ts +17 -4
- package/src/runtime/facades/operator-facade.ts +11 -3
- package/src/runtime/facades/orchestrate-facade.test.ts +7 -1
- package/src/runtime/facades/plan-facade.test.ts +29 -12
- package/src/runtime/facades/plan-facade.ts +7 -2
- package/src/runtime/facades/tier-facade.test.ts +47 -0
- package/src/runtime/facades/tier-facade.ts +11 -0
- package/src/runtime/facades/vault-facade.test.ts +174 -242
- package/src/runtime/facades/vault-facade.ts +55 -199
- package/src/runtime/github-integration.ts +11 -8
- package/src/runtime/grading-ops.test.ts +39 -8
- package/src/runtime/intake-ops.test.ts +69 -16
- package/src/runtime/loop-ops.test.ts +16 -6
- package/src/runtime/memory-cross-project-ops.test.ts +25 -14
- package/src/runtime/orchestrate-ops.test.ts +204 -0
- package/src/runtime/orchestrate-ops.ts +103 -65
- package/src/runtime/pack-ops.test.ts +23 -6
- package/src/runtime/planning-extra-ops.test.ts +17 -7
- package/src/runtime/planning-extra-ops.ts +3 -1
- package/src/runtime/playbook-ops.test.ts +26 -3
- package/src/runtime/plugin-ops.test.ts +83 -25
- package/src/runtime/project-ops.test.ts +26 -6
- package/src/runtime/runtime.ts +3 -1
- package/src/runtime/session-briefing.test.ts +183 -54
- package/src/runtime/session-briefing.ts +8 -2
- package/src/runtime/sync-ops.test.ts +3 -12
- package/src/runtime/telemetry-ops.test.ts +31 -6
- package/src/runtime/tier-ops.test.ts +159 -0
- package/src/runtime/tier-ops.ts +119 -0
- package/src/runtime/vault-extra-ops.test.ts +32 -8
- package/src/runtime/vault-sharing-ops.test.ts +1 -4
- package/src/skills/sync-skills.ts +2 -12
- package/src/transport/ws-server.test.ts +7 -4
- package/src/vault/__tests__/vault-characterization.test.ts +492 -81
- package/src/vault/linking.test.ts +50 -17
- package/src/vault/linking.ts +48 -7
- package/src/vault/obsidian-sync.test.ts +6 -3
- package/src/vault/scope-detector.test.ts +1 -3
- package/src/vault/vault-branching.test.ts +9 -7
- package/src/vault/vault-entries.ts +209 -65
- package/src/vault/vault-maintenance.ts +7 -12
- package/src/vault/vault-manager.test.ts +10 -10
- package/src/vault/vault-markdown-sync.ts +4 -1
- package/src/vault/vault-memories.ts +7 -7
- package/src/vault/vault-scaling.test.ts +5 -5
- package/src/vault/vault-schema.ts +72 -15
- package/src/vault/vault.ts +55 -9
- package/src/brain/strength-scorer.ts +0 -404
- package/src/engine/index.ts +0 -21
- package/src/persona/index.ts +0 -9
- package/src/vault/vault-interfaces.ts +0 -56
|
@@ -15,14 +15,33 @@ export interface AutoLinkConfig {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/** Updatable fields on an entry. */
|
|
18
|
-
export type EntryUpdateFields = Partial<
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
export type EntryUpdateFields = Partial<
|
|
19
|
+
Pick<
|
|
20
|
+
IntelligenceEntry,
|
|
21
|
+
| 'title'
|
|
22
|
+
| 'description'
|
|
23
|
+
| 'context'
|
|
24
|
+
| 'example'
|
|
25
|
+
| 'counterExample'
|
|
26
|
+
| 'why'
|
|
27
|
+
| 'tags'
|
|
28
|
+
| 'appliesTo'
|
|
29
|
+
| 'severity'
|
|
30
|
+
| 'type'
|
|
31
|
+
| 'domain'
|
|
32
|
+
| 'validFrom'
|
|
33
|
+
| 'validUntil'
|
|
34
|
+
>
|
|
35
|
+
>;
|
|
21
36
|
|
|
22
37
|
/** Search/list filter options. */
|
|
23
38
|
export interface EntryFilterOptions {
|
|
24
|
-
domain?: string;
|
|
25
|
-
|
|
39
|
+
domain?: string;
|
|
40
|
+
type?: string;
|
|
41
|
+
severity?: string;
|
|
42
|
+
origin?: 'agent' | 'pack' | 'user';
|
|
43
|
+
limit?: number;
|
|
44
|
+
includeExpired?: boolean;
|
|
26
45
|
}
|
|
27
46
|
|
|
28
47
|
export function autoLink(entryId: string, config: AutoLinkConfig): void {
|
|
@@ -32,10 +51,16 @@ export function autoLink(entryId: string, config: AutoLinkConfig): void {
|
|
|
32
51
|
for (const s of suggestions) {
|
|
33
52
|
config.linkManager.addLink(entryId, s.entryId, s.suggestedType, `auto: ${s.reason}`);
|
|
34
53
|
}
|
|
35
|
-
} catch {
|
|
54
|
+
} catch {
|
|
55
|
+
/* best-effort */
|
|
56
|
+
}
|
|
36
57
|
}
|
|
37
58
|
|
|
38
|
-
export function seed(
|
|
59
|
+
export function seed(
|
|
60
|
+
provider: PersistenceProvider,
|
|
61
|
+
entries: IntelligenceEntry[],
|
|
62
|
+
alc: AutoLinkConfig,
|
|
63
|
+
): number {
|
|
39
64
|
const sql = `
|
|
40
65
|
INSERT INTO entries (id,type,domain,title,severity,description,context,example,counter_example,why,tags,applies_to,valid_from,valid_until,content_hash,tier,origin)
|
|
41
66
|
VALUES (@id,@type,@domain,@title,@severity,@description,@context,@example,@counterExample,@why,@tags,@appliesTo,@validFrom,@validUntil,@contentHash,@tier,@origin)
|
|
@@ -48,13 +73,23 @@ export function seed(provider: PersistenceProvider, entries: IntelligenceEntry[]
|
|
|
48
73
|
let count = 0;
|
|
49
74
|
for (const entry of entries) {
|
|
50
75
|
provider.run(sql, {
|
|
51
|
-
id: entry.id,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
76
|
+
id: entry.id,
|
|
77
|
+
type: entry.type,
|
|
78
|
+
domain: entry.domain,
|
|
79
|
+
title: entry.title,
|
|
80
|
+
severity: entry.severity,
|
|
81
|
+
description: entry.description,
|
|
82
|
+
context: entry.context ?? null,
|
|
83
|
+
example: entry.example ?? null,
|
|
84
|
+
counterExample: entry.counterExample ?? null,
|
|
85
|
+
why: entry.why ?? null,
|
|
86
|
+
tags: JSON.stringify(entry.tags),
|
|
87
|
+
appliesTo: JSON.stringify(entry.appliesTo ?? []),
|
|
88
|
+
validFrom: entry.validFrom ?? null,
|
|
89
|
+
validUntil: entry.validUntil ?? null,
|
|
90
|
+
contentHash: computeContentHash(entry),
|
|
91
|
+
tier: entry.tier ?? 'agent',
|
|
92
|
+
origin: entry.origin ?? 'agent',
|
|
58
93
|
});
|
|
59
94
|
count++;
|
|
60
95
|
}
|
|
@@ -67,10 +102,13 @@ export function seed(provider: PersistenceProvider, entries: IntelligenceEntry[]
|
|
|
67
102
|
}
|
|
68
103
|
|
|
69
104
|
export function seedDedup(
|
|
70
|
-
provider: PersistenceProvider,
|
|
105
|
+
provider: PersistenceProvider,
|
|
106
|
+
entries: IntelligenceEntry[],
|
|
107
|
+
alc: AutoLinkConfig,
|
|
71
108
|
): Array<{ id: string; action: 'inserted' | 'duplicate'; existingId?: string }> {
|
|
72
109
|
return provider.transaction(() => {
|
|
73
|
-
const results: Array<{ id: string; action: 'inserted' | 'duplicate'; existingId?: string }> =
|
|
110
|
+
const results: Array<{ id: string; action: 'inserted' | 'duplicate'; existingId?: string }> =
|
|
111
|
+
[];
|
|
74
112
|
for (const entry of entries) {
|
|
75
113
|
const hash = computeContentHash(entry);
|
|
76
114
|
const existing = findByContentHash(provider, hash);
|
|
@@ -86,24 +124,44 @@ export function seedDedup(
|
|
|
86
124
|
}
|
|
87
125
|
|
|
88
126
|
export function installPack(
|
|
89
|
-
provider: PersistenceProvider,
|
|
127
|
+
provider: PersistenceProvider,
|
|
128
|
+
entries: IntelligenceEntry[],
|
|
129
|
+
alc: AutoLinkConfig,
|
|
90
130
|
): { installed: number; skipped: number } {
|
|
91
|
-
let installed = 0,
|
|
131
|
+
let installed = 0,
|
|
132
|
+
skipped = 0;
|
|
92
133
|
const tagged = entries.map((e) => ({ ...e, origin: 'pack' as const }));
|
|
93
134
|
for (const r of seedDedup(provider, tagged, alc)) {
|
|
94
|
-
if (r.action === 'inserted') installed++;
|
|
135
|
+
if (r.action === 'inserted') installed++;
|
|
136
|
+
else skipped++;
|
|
95
137
|
}
|
|
96
138
|
return { installed, skipped };
|
|
97
139
|
}
|
|
98
140
|
|
|
99
|
-
export function search(
|
|
141
|
+
export function search(
|
|
142
|
+
provider: PersistenceProvider,
|
|
143
|
+
query: string,
|
|
144
|
+
options?: EntryFilterOptions,
|
|
145
|
+
): SearchResult[] {
|
|
100
146
|
const limit = options?.limit ?? 10;
|
|
101
147
|
const filters: string[] = [];
|
|
102
148
|
const fp: Record<string, unknown> = {};
|
|
103
|
-
if (options?.domain) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
149
|
+
if (options?.domain) {
|
|
150
|
+
filters.push('e.domain = @domain');
|
|
151
|
+
fp.domain = options.domain;
|
|
152
|
+
}
|
|
153
|
+
if (options?.type) {
|
|
154
|
+
filters.push('e.type = @type');
|
|
155
|
+
fp.type = options.type;
|
|
156
|
+
}
|
|
157
|
+
if (options?.severity) {
|
|
158
|
+
filters.push('e.severity = @severity');
|
|
159
|
+
fp.severity = options.severity;
|
|
160
|
+
}
|
|
161
|
+
if (options?.origin) {
|
|
162
|
+
filters.push('e.origin = @origin');
|
|
163
|
+
fp.origin = options.origin;
|
|
164
|
+
}
|
|
107
165
|
if (!options?.includeExpired) {
|
|
108
166
|
const now = Math.floor(Date.now() / 1000);
|
|
109
167
|
filters.push('(e.valid_until IS NULL OR e.valid_until > @now)');
|
|
@@ -125,7 +183,9 @@ export function search(provider: PersistenceProvider, query: string, options?: E
|
|
|
125
183
|
{ query, limit, ...fp },
|
|
126
184
|
);
|
|
127
185
|
return rows.map(rowToSearchResult);
|
|
128
|
-
} catch {
|
|
186
|
+
} catch {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
129
189
|
}
|
|
130
190
|
}
|
|
131
191
|
|
|
@@ -140,12 +200,27 @@ export function list(
|
|
|
140
200
|
): IntelligenceEntry[] {
|
|
141
201
|
const filters: string[] = [];
|
|
142
202
|
const params: Record<string, unknown> = {};
|
|
143
|
-
if (options?.domain) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
203
|
+
if (options?.domain) {
|
|
204
|
+
filters.push('domain = @domain');
|
|
205
|
+
params.domain = options.domain;
|
|
206
|
+
}
|
|
207
|
+
if (options?.type) {
|
|
208
|
+
filters.push('type = @type');
|
|
209
|
+
params.type = options.type;
|
|
210
|
+
}
|
|
211
|
+
if (options?.severity) {
|
|
212
|
+
filters.push('severity = @severity');
|
|
213
|
+
params.severity = options.severity;
|
|
214
|
+
}
|
|
215
|
+
if (options?.origin) {
|
|
216
|
+
filters.push('origin = @origin');
|
|
217
|
+
params.origin = options.origin;
|
|
218
|
+
}
|
|
147
219
|
if (options?.tags?.length) {
|
|
148
|
-
const c = options.tags.map((t, i) => {
|
|
220
|
+
const c = options.tags.map((t, i) => {
|
|
221
|
+
params[`tag${i}`] = `%"${t}"%`;
|
|
222
|
+
return `tags LIKE @tag${i}`;
|
|
223
|
+
});
|
|
149
224
|
filters.push(`(${c.join(' OR ')})`);
|
|
150
225
|
}
|
|
151
226
|
if (!options?.includeExpired) {
|
|
@@ -164,10 +239,19 @@ export function list(
|
|
|
164
239
|
|
|
165
240
|
export function stats(provider: PersistenceProvider): VaultStats {
|
|
166
241
|
const total = provider.get<{ count: number }>('SELECT COUNT(*) as count FROM entries')!.count;
|
|
167
|
-
return {
|
|
242
|
+
return {
|
|
243
|
+
totalEntries: total,
|
|
244
|
+
byType: gc(provider, 'type'),
|
|
245
|
+
byDomain: gc(provider, 'domain'),
|
|
246
|
+
bySeverity: gc(provider, 'severity'),
|
|
247
|
+
};
|
|
168
248
|
}
|
|
169
249
|
|
|
170
|
-
export function add(
|
|
250
|
+
export function add(
|
|
251
|
+
provider: PersistenceProvider,
|
|
252
|
+
entry: IntelligenceEntry,
|
|
253
|
+
alc: AutoLinkConfig,
|
|
254
|
+
): void {
|
|
171
255
|
seed(provider, [entry], alc);
|
|
172
256
|
}
|
|
173
257
|
|
|
@@ -175,38 +259,64 @@ export function remove(provider: PersistenceProvider, id: string): boolean {
|
|
|
175
259
|
return provider.run('DELETE FROM entries WHERE id = ?', [id]).changes > 0;
|
|
176
260
|
}
|
|
177
261
|
|
|
178
|
-
export function update(
|
|
262
|
+
export function update(
|
|
263
|
+
provider: PersistenceProvider,
|
|
264
|
+
id: string,
|
|
265
|
+
fields: EntryUpdateFields,
|
|
266
|
+
alc: AutoLinkConfig,
|
|
267
|
+
): IntelligenceEntry | null {
|
|
179
268
|
const existing = get(provider, id);
|
|
180
269
|
if (!existing) return null;
|
|
181
270
|
seed(provider, [{ ...existing, ...fields }], alc);
|
|
182
271
|
return get(provider, id);
|
|
183
272
|
}
|
|
184
273
|
|
|
185
|
-
export function setTemporal(
|
|
274
|
+
export function setTemporal(
|
|
275
|
+
provider: PersistenceProvider,
|
|
276
|
+
id: string,
|
|
277
|
+
validFrom?: number,
|
|
278
|
+
validUntil?: number,
|
|
279
|
+
): boolean {
|
|
186
280
|
const sets: string[] = [];
|
|
187
281
|
const params: Record<string, unknown> = { id };
|
|
188
|
-
if (validFrom !== undefined) {
|
|
189
|
-
|
|
282
|
+
if (validFrom !== undefined) {
|
|
283
|
+
sets.push('valid_from = @validFrom');
|
|
284
|
+
params.validFrom = validFrom;
|
|
285
|
+
}
|
|
286
|
+
if (validUntil !== undefined) {
|
|
287
|
+
sets.push('valid_until = @validUntil');
|
|
288
|
+
params.validUntil = validUntil;
|
|
289
|
+
}
|
|
190
290
|
if (sets.length === 0) return false;
|
|
191
291
|
sets.push('updated_at = unixepoch()');
|
|
192
292
|
return provider.run(`UPDATE entries SET ${sets.join(', ')} WHERE id = @id`, params).changes > 0;
|
|
193
293
|
}
|
|
194
294
|
|
|
195
|
-
export function findExpiring(
|
|
295
|
+
export function findExpiring(
|
|
296
|
+
provider: PersistenceProvider,
|
|
297
|
+
withinDays: number,
|
|
298
|
+
): IntelligenceEntry[] {
|
|
196
299
|
const now = Math.floor(Date.now() / 1000);
|
|
197
300
|
const cutoff = now + withinDays * 86400;
|
|
198
|
-
return provider
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
301
|
+
return provider
|
|
302
|
+
.all<Record<string, unknown>>(
|
|
303
|
+
'SELECT * FROM entries WHERE valid_until IS NOT NULL AND valid_until > @now AND valid_until <= @cutoff ORDER BY valid_until ASC',
|
|
304
|
+
{ now, cutoff },
|
|
305
|
+
)
|
|
306
|
+
.map(rowToEntry);
|
|
202
307
|
}
|
|
203
308
|
|
|
204
|
-
export function findExpired(
|
|
309
|
+
export function findExpired(
|
|
310
|
+
provider: PersistenceProvider,
|
|
311
|
+
limit: number = 50,
|
|
312
|
+
): IntelligenceEntry[] {
|
|
205
313
|
const now = Math.floor(Date.now() / 1000);
|
|
206
|
-
return provider
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
314
|
+
return provider
|
|
315
|
+
.all<Record<string, unknown>>(
|
|
316
|
+
'SELECT * FROM entries WHERE valid_until IS NOT NULL AND valid_until <= @now ORDER BY valid_until DESC LIMIT @limit',
|
|
317
|
+
{ now, limit },
|
|
318
|
+
)
|
|
319
|
+
.map(rowToEntry);
|
|
210
320
|
}
|
|
211
321
|
|
|
212
322
|
export function bulkRemove(provider: PersistenceProvider, ids: string[]): number {
|
|
@@ -225,45 +335,75 @@ export function getTags(provider: PersistenceProvider): Array<{ tag: string; cou
|
|
|
225
335
|
counts.set(tag, (counts.get(tag) ?? 0) + 1);
|
|
226
336
|
}
|
|
227
337
|
}
|
|
228
|
-
return Array.from(counts.entries())
|
|
338
|
+
return Array.from(counts.entries())
|
|
339
|
+
.map(([tag, count]) => ({ tag, count }))
|
|
340
|
+
.sort((a, b) => b.count - a.count);
|
|
229
341
|
}
|
|
230
342
|
|
|
231
|
-
export function getDomains(
|
|
232
|
-
|
|
343
|
+
export function getDomains(
|
|
344
|
+
provider: PersistenceProvider,
|
|
345
|
+
): Array<{ domain: string; count: number }> {
|
|
346
|
+
return provider.all(
|
|
347
|
+
'SELECT domain, COUNT(*) as count FROM entries GROUP BY domain ORDER BY count DESC',
|
|
348
|
+
);
|
|
233
349
|
}
|
|
234
350
|
|
|
235
351
|
export function getRecent(provider: PersistenceProvider, limit: number = 20): IntelligenceEntry[] {
|
|
236
|
-
return provider
|
|
352
|
+
return provider
|
|
353
|
+
.all<Record<string, unknown>>('SELECT * FROM entries ORDER BY updated_at DESC LIMIT ?', [limit])
|
|
354
|
+
.map(rowToEntry);
|
|
237
355
|
}
|
|
238
356
|
|
|
239
357
|
export function findByContentHash(provider: PersistenceProvider, hash: string): string | null {
|
|
240
|
-
return
|
|
358
|
+
return (
|
|
359
|
+
provider.get<{ id: string }>('SELECT id FROM entries WHERE content_hash = @hash', { hash })
|
|
360
|
+
?.id ?? null
|
|
361
|
+
);
|
|
241
362
|
}
|
|
242
363
|
|
|
243
|
-
export function contentHashStats(provider: PersistenceProvider): {
|
|
364
|
+
export function contentHashStats(provider: PersistenceProvider): {
|
|
365
|
+
total: number;
|
|
366
|
+
hashed: number;
|
|
367
|
+
uniqueHashes: number;
|
|
368
|
+
} {
|
|
244
369
|
const total = provider.get<{ c: number }>('SELECT COUNT(*) as c FROM entries')?.c ?? 0;
|
|
245
|
-
const hashed =
|
|
246
|
-
|
|
370
|
+
const hashed =
|
|
371
|
+
provider.get<{ c: number }>('SELECT COUNT(*) as c FROM entries WHERE content_hash IS NOT NULL')
|
|
372
|
+
?.c ?? 0;
|
|
373
|
+
const uniqueHashes =
|
|
374
|
+
provider.get<{ c: number }>(
|
|
375
|
+
'SELECT COUNT(DISTINCT content_hash) as c FROM entries WHERE content_hash IS NOT NULL',
|
|
376
|
+
)?.c ?? 0;
|
|
247
377
|
return { total, hashed, uniqueHashes };
|
|
248
378
|
}
|
|
249
379
|
|
|
250
380
|
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
251
381
|
|
|
252
382
|
function gc(provider: PersistenceProvider, col: string): Record<string, number> {
|
|
253
|
-
const rows = provider.all<{ key: string; count: number }>(
|
|
383
|
+
const rows = provider.all<{ key: string; count: number }>(
|
|
384
|
+
`SELECT ${col} as key, COUNT(*) as count FROM entries GROUP BY ${col}`,
|
|
385
|
+
);
|
|
254
386
|
return Object.fromEntries(rows.map((r) => [r.key, r.count]));
|
|
255
387
|
}
|
|
256
388
|
|
|
257
389
|
export function rowToEntry(row: Record<string, unknown>): IntelligenceEntry {
|
|
258
390
|
return {
|
|
259
|
-
id: row.id as string,
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
391
|
+
id: row.id as string,
|
|
392
|
+
type: row.type as IntelligenceEntry['type'],
|
|
393
|
+
domain: row.domain as IntelligenceEntry['domain'],
|
|
394
|
+
title: row.title as string,
|
|
395
|
+
severity: row.severity as IntelligenceEntry['severity'],
|
|
396
|
+
description: row.description as string,
|
|
397
|
+
context: (row.context as string) ?? undefined,
|
|
398
|
+
example: (row.example as string) ?? undefined,
|
|
399
|
+
counterExample: (row.counter_example as string) ?? undefined,
|
|
400
|
+
why: (row.why as string) ?? undefined,
|
|
401
|
+
tags: JSON.parse((row.tags as string) || '[]'),
|
|
402
|
+
appliesTo: JSON.parse((row.applies_to as string) || '[]'),
|
|
403
|
+
tier: (row.tier as IntelligenceEntry['tier']) ?? undefined,
|
|
404
|
+
origin: (row.origin as IntelligenceEntry['origin']) ?? undefined,
|
|
405
|
+
validFrom: (row.valid_from as number) ?? undefined,
|
|
406
|
+
validUntil: (row.valid_until as number) ?? undefined,
|
|
267
407
|
};
|
|
268
408
|
}
|
|
269
409
|
|
|
@@ -274,8 +414,12 @@ export function rowToSearchResult(row: Record<string, unknown>): SearchResult {
|
|
|
274
414
|
|
|
275
415
|
/** Build FTS5 query from natural language: terms joined with OR for broad matching. */
|
|
276
416
|
export function buildFtsQuery(query: string): string {
|
|
277
|
-
const terms = query
|
|
278
|
-
.
|
|
417
|
+
const terms = query
|
|
418
|
+
.toLowerCase()
|
|
419
|
+
.split(/\s+/)
|
|
420
|
+
.filter((t) => t.length >= 2)
|
|
421
|
+
.map((t) => t.replace(/[^a-z0-9]/g, ''))
|
|
422
|
+
.filter(Boolean);
|
|
279
423
|
if (terms.length === 0) return query;
|
|
280
424
|
if (terms.length === 1) return terms[0];
|
|
281
425
|
return terms.join(' OR ');
|
|
@@ -111,10 +111,9 @@ export function archive(
|
|
|
111
111
|
const reason = options.reason ?? `Archived: older than ${options.olderThanDays} days`;
|
|
112
112
|
|
|
113
113
|
return provider.transaction(() => {
|
|
114
|
-
const candidates = provider.all<{ id: string }>(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
);
|
|
114
|
+
const candidates = provider.all<{ id: string }>('SELECT id FROM entries WHERE updated_at < ?', [
|
|
115
|
+
cutoff,
|
|
116
|
+
]);
|
|
118
117
|
|
|
119
118
|
if (candidates.length === 0) return { archived: 0 };
|
|
120
119
|
|
|
@@ -173,14 +172,10 @@ export function registerProject(
|
|
|
173
172
|
return getProject(provider, path)!;
|
|
174
173
|
}
|
|
175
174
|
|
|
176
|
-
export function getProject(
|
|
177
|
-
provider
|
|
178
|
-
|
|
179
|
-
)
|
|
180
|
-
const row = provider.get<Record<string, unknown>>(
|
|
181
|
-
'SELECT * FROM projects WHERE path = ?',
|
|
182
|
-
[path],
|
|
183
|
-
);
|
|
175
|
+
export function getProject(provider: PersistenceProvider, path: string): ProjectInfo | null {
|
|
176
|
+
const row = provider.get<Record<string, unknown>>('SELECT * FROM projects WHERE path = ?', [
|
|
177
|
+
path,
|
|
178
|
+
]);
|
|
184
179
|
if (!row) return null;
|
|
185
180
|
return {
|
|
186
181
|
path: row.path as string,
|
|
@@ -7,13 +7,17 @@ vi.mock('./vault.js', () => {
|
|
|
7
7
|
const MockVault = function (this: Record<string, unknown>, path: string) {
|
|
8
8
|
this._path = path;
|
|
9
9
|
this.search = vi.fn().mockReturnValue([]);
|
|
10
|
-
this.stats = vi
|
|
10
|
+
this.stats = vi
|
|
11
|
+
.fn()
|
|
12
|
+
.mockReturnValue({ totalEntries: 0, byType: {}, byDomain: {}, bySeverity: {} });
|
|
11
13
|
this.close = vi.fn();
|
|
12
|
-
} as unknown as typeof import('./vault.js')['Vault'];
|
|
14
|
+
} as unknown as (typeof import('./vault.js'))['Vault'];
|
|
13
15
|
return { Vault: MockVault };
|
|
14
16
|
});
|
|
15
17
|
|
|
16
|
-
function makeManager(
|
|
18
|
+
function makeManager(
|
|
19
|
+
weights?: Partial<Record<'agent' | 'project' | 'team', number>>,
|
|
20
|
+
): VaultManager {
|
|
17
21
|
return new VaultManager({ agentId: 'test-agent', weights });
|
|
18
22
|
}
|
|
19
23
|
|
|
@@ -74,7 +78,7 @@ describe('VaultManager', () => {
|
|
|
74
78
|
|
|
75
79
|
it('throws when connecting duplicate named vault', () => {
|
|
76
80
|
mgr.connect('shared', '/tmp/shared.db');
|
|
77
|
-
expect(() => mgr.connect('shared', '/tmp/other.db')).toThrow(
|
|
81
|
+
expect(() => mgr.connect('shared', '/tmp/other.db')).toThrow('already connected');
|
|
78
82
|
});
|
|
79
83
|
|
|
80
84
|
it('disconnects a named vault', () => {
|
|
@@ -122,14 +126,10 @@ describe('VaultManager', () => {
|
|
|
122
126
|
it('deduplicates entries keeping highest weighted score', () => {
|
|
123
127
|
const entry = { id: 'e1', title: 'Shared' };
|
|
124
128
|
const agentVault = mgr.open('agent', '/tmp/a.db');
|
|
125
|
-
(agentVault.search as ReturnType<typeof vi.fn>).mockReturnValue([
|
|
126
|
-
{ entry, score: 0.5 },
|
|
127
|
-
]);
|
|
129
|
+
(agentVault.search as ReturnType<typeof vi.fn>).mockReturnValue([{ entry, score: 0.5 }]);
|
|
128
130
|
|
|
129
131
|
const teamVault = mgr.open('team', '/tmp/t.db');
|
|
130
|
-
(teamVault.search as ReturnType<typeof vi.fn>).mockReturnValue([
|
|
131
|
-
{ entry, score: 0.8 },
|
|
132
|
-
]);
|
|
132
|
+
(teamVault.search as ReturnType<typeof vi.fn>).mockReturnValue([{ entry, score: 0.8 }]);
|
|
133
133
|
|
|
134
134
|
const results = mgr.search('test');
|
|
135
135
|
// Agent: 0.5 * 1.0 = 0.5, Team: 0.8 * 0.6 = 0.48 → agent wins
|
|
@@ -105,7 +105,10 @@ export async function syncAllToMarkdown(
|
|
|
105
105
|
for (const entry of entries) {
|
|
106
106
|
const domain = entry.domain || '_general';
|
|
107
107
|
const slug = titleToSlug(entry.title);
|
|
108
|
-
if (!slug) {
|
|
108
|
+
if (!slug) {
|
|
109
|
+
skipped++;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
109
112
|
|
|
110
113
|
const filePath = join(knowledgeDir, 'vault', domain, `${slug}.md`);
|
|
111
114
|
if (existsSync(filePath)) {
|
|
@@ -228,16 +228,16 @@ export function pruneMemories(
|
|
|
228
228
|
olderThanDays: number,
|
|
229
229
|
): { pruned: number } {
|
|
230
230
|
const cutoff = Math.floor(Date.now() / 1000) - olderThanDays * 86400;
|
|
231
|
-
const result = provider.run(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
);
|
|
231
|
+
const result = provider.run('DELETE FROM memories WHERE created_at < ? AND archived_at IS NULL', [
|
|
232
|
+
cutoff,
|
|
233
|
+
]);
|
|
235
234
|
return { pruned: result.changes };
|
|
236
235
|
}
|
|
237
236
|
|
|
238
|
-
export function deduplicateMemories(
|
|
239
|
-
|
|
240
|
-
|
|
237
|
+
export function deduplicateMemories(provider: PersistenceProvider): {
|
|
238
|
+
removed: number;
|
|
239
|
+
groups: Array<{ kept: string; removed: string[] }>;
|
|
240
|
+
} {
|
|
241
241
|
const dupeRows = provider.all<{ id1: string; id2: string }>(`
|
|
242
242
|
SELECT m1.id as id1, m2.id as id2
|
|
243
243
|
FROM memories m1
|
|
@@ -92,7 +92,7 @@ describe('Vault Scaling — 10K entries', () => {
|
|
|
92
92
|
expect(elapsed).toBeLessThan(50);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
test('list with filters under
|
|
95
|
+
test('list with filters under 200ms at 10K', () => {
|
|
96
96
|
vault = new Vault(':memory:');
|
|
97
97
|
vault.seed(generateEntries(10_000));
|
|
98
98
|
|
|
@@ -101,7 +101,7 @@ describe('Vault Scaling — 10K entries', () => {
|
|
|
101
101
|
const elapsed = performance.now() - start;
|
|
102
102
|
|
|
103
103
|
expect(entries.length).toBeGreaterThan(0);
|
|
104
|
-
expect(elapsed).toBeLessThan(
|
|
104
|
+
expect(elapsed).toBeLessThan(200);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
// ─── Stats performance ───────────────────────────────
|
|
@@ -223,7 +223,7 @@ describe('Vault Scaling — 10K entries', () => {
|
|
|
223
223
|
|
|
224
224
|
// ─── Tags and domains at scale ────────────────────────
|
|
225
225
|
|
|
226
|
-
test('getTags under
|
|
226
|
+
test('getTags under 500ms at 10K', () => {
|
|
227
227
|
vault = new Vault(':memory:');
|
|
228
228
|
vault.seed(generateEntries(10_000));
|
|
229
229
|
|
|
@@ -232,7 +232,7 @@ describe('Vault Scaling — 10K entries', () => {
|
|
|
232
232
|
const elapsed = performance.now() - start;
|
|
233
233
|
|
|
234
234
|
expect(tags.length).toBeGreaterThan(0);
|
|
235
|
-
expect(elapsed).toBeLessThan(
|
|
235
|
+
expect(elapsed).toBeLessThan(500);
|
|
236
236
|
});
|
|
237
237
|
|
|
238
238
|
test('getDomains under 10ms at 10K', () => {
|
|
@@ -244,7 +244,7 @@ describe('Vault Scaling — 10K entries', () => {
|
|
|
244
244
|
const elapsed = performance.now() - start;
|
|
245
245
|
|
|
246
246
|
expect(domains.length).toBe(DOMAINS.length);
|
|
247
|
-
expect(elapsed).toBeLessThan(
|
|
247
|
+
expect(elapsed).toBeLessThan(200);
|
|
248
248
|
});
|
|
249
249
|
|
|
250
250
|
// ─── FTS rebuild at scale ─────────────────────────────
|