@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
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
9
|
-
import { createVaultFacadeOps } from './vault-facade.js';
|
|
9
|
+
import { createVaultFacadeOps, deprecateOps } from './vault-facade.js';
|
|
10
10
|
import { captureOps, executeOp } from '../../engine/test-helpers.js';
|
|
11
11
|
import type { CapturedOp } from '../../engine/test-helpers.js';
|
|
12
12
|
import type { AgentRuntime } from '../types.js';
|
|
13
|
+
import { resetDeprecationWarnings } from '../deprecation.js';
|
|
13
14
|
|
|
14
15
|
// ─── Mock factories ──────────────────────────────────────────────────
|
|
15
16
|
|
|
@@ -34,7 +35,9 @@ function makeMockVault() {
|
|
|
34
35
|
getRecent: vi.fn().mockReturnValue([]),
|
|
35
36
|
exportAll: vi.fn().mockReturnValue({ entries: [] }),
|
|
36
37
|
getAgeReport: vi.fn().mockReturnValue({ buckets: [], oldestTimestamp: null }),
|
|
37
|
-
getDb: vi
|
|
38
|
+
getDb: vi
|
|
39
|
+
.fn()
|
|
40
|
+
.mockReturnValue({ prepare: vi.fn().mockReturnValue({ all: vi.fn().mockReturnValue([]) }) }),
|
|
38
41
|
searchMemories: vi.fn().mockReturnValue([]),
|
|
39
42
|
isAutoLinkEnabled: vi.fn().mockReturnValue(false),
|
|
40
43
|
setTemporal: vi.fn().mockReturnValue(true),
|
|
@@ -52,17 +55,14 @@ function makeMockVault() {
|
|
|
52
55
|
|
|
53
56
|
function makeMockBrain() {
|
|
54
57
|
return {
|
|
55
|
-
intelligentSearch: vi.fn().mockResolvedValue([
|
|
56
|
-
|
|
57
|
-
]),
|
|
58
|
-
scanSearch: vi.fn().mockResolvedValue([
|
|
59
|
-
{ id: 'e1', title: 'Result 1', score: 0.8 },
|
|
60
|
-
]),
|
|
61
|
-
loadEntries: vi.fn().mockReturnValue([
|
|
62
|
-
{ id: 'e1', title: 'Full entry', type: 'pattern' },
|
|
63
|
-
]),
|
|
58
|
+
intelligentSearch: vi.fn().mockResolvedValue([{ id: 'e1', title: 'Result 1', score: 0.9 }]),
|
|
59
|
+
scanSearch: vi.fn().mockResolvedValue([{ id: 'e1', title: 'Result 1', score: 0.8 }]),
|
|
60
|
+
loadEntries: vi.fn().mockReturnValue([{ id: 'e1', title: 'Full entry', type: 'pattern' }]),
|
|
64
61
|
enrichAndCapture: vi.fn().mockReturnValue({
|
|
65
|
-
captured: true,
|
|
62
|
+
captured: true,
|
|
63
|
+
id: 'cap-1',
|
|
64
|
+
autoTags: ['auto'],
|
|
65
|
+
duplicate: null,
|
|
66
66
|
}),
|
|
67
67
|
recordFeedback: vi.fn(),
|
|
68
68
|
};
|
|
@@ -72,17 +72,11 @@ function makeMockVaultManager() {
|
|
|
72
72
|
return {
|
|
73
73
|
open: vi.fn(),
|
|
74
74
|
disconnect: vi.fn().mockReturnValue(true),
|
|
75
|
-
listTiers: vi.fn().mockReturnValue([
|
|
76
|
-
|
|
77
|
-
]),
|
|
78
|
-
search: vi.fn().mockReturnValue([
|
|
79
|
-
{ id: 'e1', tier: 'agent', score: 0.9 },
|
|
80
|
-
]),
|
|
75
|
+
listTiers: vi.fn().mockReturnValue([{ tier: 'agent', connected: true, entries: 25 }]),
|
|
76
|
+
search: vi.fn().mockReturnValue([{ id: 'e1', tier: 'agent', score: 0.9 }]),
|
|
81
77
|
connect: vi.fn(),
|
|
82
78
|
disconnectNamed: vi.fn().mockReturnValue(true),
|
|
83
|
-
listConnected: vi.fn().mockReturnValue([
|
|
84
|
-
{ name: 'team-shared', priority: 0.5 },
|
|
85
|
-
]),
|
|
79
|
+
listConnected: vi.fn().mockReturnValue([{ name: 'team-shared', priority: 0.5 }]),
|
|
86
80
|
};
|
|
87
81
|
}
|
|
88
82
|
|
|
@@ -175,16 +169,17 @@ describe('vault-facade', () => {
|
|
|
175
169
|
it('registers ops from all groups', () => {
|
|
176
170
|
// The facade includes inline ops + satellite ops from 5 modules.
|
|
177
171
|
// We check the inline ops explicitly, satellite ops just need to exist.
|
|
178
|
-
expect(ops.size).toBeGreaterThan(
|
|
172
|
+
expect(ops.size).toBeGreaterThan(20);
|
|
179
173
|
});
|
|
180
174
|
|
|
181
175
|
it('includes core inline op names', () => {
|
|
182
176
|
const coreOps = [
|
|
183
|
-
'search',
|
|
184
|
-
'
|
|
185
|
-
'
|
|
186
|
-
'
|
|
187
|
-
'
|
|
177
|
+
'search',
|
|
178
|
+
'load_entries',
|
|
179
|
+
'vault_stats',
|
|
180
|
+
'list_all',
|
|
181
|
+
'export',
|
|
182
|
+
'capture_enriched',
|
|
188
183
|
];
|
|
189
184
|
for (const name of coreOps) {
|
|
190
185
|
expect(ops.has(name), `missing op: ${name}`).toBe(true);
|
|
@@ -193,10 +188,10 @@ describe('vault-facade', () => {
|
|
|
193
188
|
|
|
194
189
|
it('includes satellite ops', () => {
|
|
195
190
|
// Spot-check a few ops from each satellite module
|
|
196
|
-
expect(ops.has('vault_get')).toBe(true);
|
|
191
|
+
expect(ops.has('vault_get')).toBe(true); // vault-extra-ops
|
|
197
192
|
expect(ops.has('capture_knowledge')).toBe(true); // capture-ops
|
|
198
193
|
expect(ops.has('search_intelligent')).toBe(true); // capture-ops
|
|
199
|
-
|
|
194
|
+
// link_entries moved to vault-linking-facade
|
|
200
195
|
});
|
|
201
196
|
|
|
202
197
|
// ─── Auth levels ─────────────────────────────────────────────────
|
|
@@ -208,18 +203,6 @@ describe('vault-facade', () => {
|
|
|
208
203
|
expect(ops.get('list_all')!.auth).toBe('read');
|
|
209
204
|
expect(ops.get('export')!.auth).toBe('read');
|
|
210
205
|
expect(ops.get('capture_enriched')!.auth).toBe('write');
|
|
211
|
-
expect(ops.get('vault_connect')!.auth).toBe('admin');
|
|
212
|
-
expect(ops.get('vault_disconnect')!.auth).toBe('admin');
|
|
213
|
-
expect(ops.get('vault_tiers')!.auth).toBe('read');
|
|
214
|
-
expect(ops.get('vault_search_all')!.auth).toBe('read');
|
|
215
|
-
expect(ops.get('vault_connect_source')!.auth).toBe('admin');
|
|
216
|
-
expect(ops.get('vault_disconnect_source')!.auth).toBe('admin');
|
|
217
|
-
expect(ops.get('vault_list_sources')!.auth).toBe('read');
|
|
218
|
-
expect(ops.get('vault_branch')!.auth).toBe('write');
|
|
219
|
-
expect(ops.get('vault_branch_add')!.auth).toBe('write');
|
|
220
|
-
expect(ops.get('vault_branch_list')!.auth).toBe('read');
|
|
221
|
-
expect(ops.get('vault_merge_branch')!.auth).toBe('admin');
|
|
222
|
-
expect(ops.get('vault_delete_branch')!.auth).toBe('admin');
|
|
223
206
|
});
|
|
224
207
|
|
|
225
208
|
// ─── search ────────────────────────────────────────────────────────
|
|
@@ -230,32 +213,47 @@ describe('vault-facade', () => {
|
|
|
230
213
|
expect(result.success).toBe(true);
|
|
231
214
|
const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
|
|
232
215
|
expect(brain.intelligentSearch).toHaveBeenCalledWith('tokens', {
|
|
233
|
-
domain: undefined,
|
|
234
|
-
|
|
216
|
+
domain: undefined,
|
|
217
|
+
type: undefined,
|
|
218
|
+
severity: undefined,
|
|
219
|
+
tags: undefined,
|
|
220
|
+
limit: 10,
|
|
235
221
|
});
|
|
236
222
|
});
|
|
237
223
|
|
|
238
224
|
it('uses scan mode when specified', async () => {
|
|
239
225
|
const result = await executeOp(ops, 'search', {
|
|
240
|
-
query: 'tokens',
|
|
226
|
+
query: 'tokens',
|
|
227
|
+
mode: 'scan',
|
|
241
228
|
});
|
|
242
229
|
expect(result.success).toBe(true);
|
|
243
230
|
const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
|
|
244
|
-
expect(brain.scanSearch).toHaveBeenCalledWith(
|
|
245
|
-
|
|
246
|
-
|
|
231
|
+
expect(brain.scanSearch).toHaveBeenCalledWith(
|
|
232
|
+
'tokens',
|
|
233
|
+
expect.objectContaining({
|
|
234
|
+
limit: 10,
|
|
235
|
+
}),
|
|
236
|
+
);
|
|
247
237
|
expect(brain.intelligentSearch).not.toHaveBeenCalled();
|
|
248
238
|
});
|
|
249
239
|
|
|
250
240
|
it('passes all filter params', async () => {
|
|
251
241
|
await executeOp(ops, 'search', {
|
|
252
|
-
query: 'test',
|
|
253
|
-
|
|
242
|
+
query: 'test',
|
|
243
|
+
domain: 'design',
|
|
244
|
+
type: 'pattern',
|
|
245
|
+
severity: 'critical',
|
|
246
|
+
tags: ['a11y'],
|
|
247
|
+
limit: 5,
|
|
248
|
+
mode: 'full',
|
|
254
249
|
});
|
|
255
250
|
const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
|
|
256
251
|
expect(brain.intelligentSearch).toHaveBeenCalledWith('test', {
|
|
257
|
-
domain: 'design',
|
|
258
|
-
|
|
252
|
+
domain: 'design',
|
|
253
|
+
type: 'pattern',
|
|
254
|
+
severity: 'critical',
|
|
255
|
+
tags: ['a11y'],
|
|
256
|
+
limit: 5,
|
|
259
257
|
});
|
|
260
258
|
});
|
|
261
259
|
});
|
|
@@ -315,20 +313,26 @@ describe('vault-facade', () => {
|
|
|
315
313
|
it('uses default pagination', async () => {
|
|
316
314
|
await executeOp(ops, 'list_all', {});
|
|
317
315
|
const vault = runtime.vault as ReturnType<typeof makeMockVault>;
|
|
318
|
-
expect(vault.list).toHaveBeenCalledWith(
|
|
319
|
-
expect.objectContaining({ limit: 20, offset: 0 }),
|
|
320
|
-
);
|
|
316
|
+
expect(vault.list).toHaveBeenCalledWith(expect.objectContaining({ limit: 20, offset: 0 }));
|
|
321
317
|
});
|
|
322
318
|
|
|
323
319
|
it('passes all filter params', async () => {
|
|
324
320
|
await executeOp(ops, 'list_all', {
|
|
325
|
-
domain: 'design',
|
|
326
|
-
|
|
321
|
+
domain: 'design',
|
|
322
|
+
type: 'pattern',
|
|
323
|
+
severity: 'warning',
|
|
324
|
+
tags: ['a11y'],
|
|
325
|
+
limit: 5,
|
|
326
|
+
offset: 10,
|
|
327
327
|
});
|
|
328
328
|
const vault = runtime.vault as ReturnType<typeof makeMockVault>;
|
|
329
329
|
expect(vault.list).toHaveBeenCalledWith({
|
|
330
|
-
domain: 'design',
|
|
331
|
-
|
|
330
|
+
domain: 'design',
|
|
331
|
+
type: 'pattern',
|
|
332
|
+
severity: 'warning',
|
|
333
|
+
tags: ['a11y'],
|
|
334
|
+
limit: 5,
|
|
335
|
+
offset: 10,
|
|
332
336
|
});
|
|
333
337
|
});
|
|
334
338
|
});
|
|
@@ -359,8 +363,11 @@ describe('vault-facade', () => {
|
|
|
359
363
|
describe('capture_enriched', () => {
|
|
360
364
|
it('captures with LLM enrichment when successful', async () => {
|
|
361
365
|
const result = await executeOp(ops, 'capture_enriched', {
|
|
362
|
-
title: 'Semantic tokens',
|
|
363
|
-
|
|
366
|
+
title: 'Semantic tokens',
|
|
367
|
+
description: 'Always use semantic tokens',
|
|
368
|
+
type: 'pattern',
|
|
369
|
+
domain: 'design',
|
|
370
|
+
tags: ['tokens'],
|
|
364
371
|
});
|
|
365
372
|
expect(result.success).toBe(true);
|
|
366
373
|
const data = result.data as { captured: boolean; enriched: boolean; entryId: string };
|
|
@@ -370,10 +377,13 @@ describe('vault-facade', () => {
|
|
|
370
377
|
|
|
371
378
|
it('falls back to basic capture when enrichment fails', async () => {
|
|
372
379
|
const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
|
|
373
|
-
brain.enrichAndCapture.mockImplementation(() => {
|
|
380
|
+
brain.enrichAndCapture.mockImplementation(() => {
|
|
381
|
+
throw new Error('LLM unavailable');
|
|
382
|
+
});
|
|
374
383
|
|
|
375
384
|
const result = await executeOp(ops, 'capture_enriched', {
|
|
376
|
-
title: 'Test entry',
|
|
385
|
+
title: 'Test entry',
|
|
386
|
+
description: 'A test pattern to avoid problems',
|
|
377
387
|
});
|
|
378
388
|
expect(result.success).toBe(true);
|
|
379
389
|
const data = result.data as { captured: boolean; enriched: boolean };
|
|
@@ -383,34 +393,37 @@ describe('vault-facade', () => {
|
|
|
383
393
|
|
|
384
394
|
it('infers anti-pattern type from description keywords', async () => {
|
|
385
395
|
const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
|
|
386
|
-
brain.enrichAndCapture.mockImplementation(() => {
|
|
396
|
+
brain.enrichAndCapture.mockImplementation(() => {
|
|
397
|
+
throw new Error('LLM down');
|
|
398
|
+
});
|
|
387
399
|
const vault = runtime.vault as ReturnType<typeof makeMockVault>;
|
|
388
400
|
|
|
389
401
|
await executeOp(ops, 'capture_enriched', {
|
|
390
402
|
title: 'Avoid inline styles',
|
|
391
403
|
description: "Don't use inline styles in components",
|
|
392
404
|
});
|
|
393
|
-
expect(vault.add).toHaveBeenCalledWith(
|
|
394
|
-
expect.objectContaining({ type: 'anti-pattern' }),
|
|
395
|
-
);
|
|
405
|
+
expect(vault.add).toHaveBeenCalledWith(expect.objectContaining({ type: 'anti-pattern' }));
|
|
396
406
|
});
|
|
397
407
|
|
|
398
408
|
it('infers critical severity from keywords', async () => {
|
|
399
409
|
const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
|
|
400
|
-
brain.enrichAndCapture.mockImplementation(() => {
|
|
410
|
+
brain.enrichAndCapture.mockImplementation(() => {
|
|
411
|
+
throw new Error('fail');
|
|
412
|
+
});
|
|
401
413
|
const vault = runtime.vault as ReturnType<typeof makeMockVault>;
|
|
402
414
|
|
|
403
415
|
await executeOp(ops, 'capture_enriched', {
|
|
404
|
-
title: 'Security check',
|
|
416
|
+
title: 'Security check',
|
|
417
|
+
description: 'This is a critical security requirement',
|
|
405
418
|
});
|
|
406
|
-
expect(vault.add).toHaveBeenCalledWith(
|
|
407
|
-
expect.objectContaining({ severity: 'critical' }),
|
|
408
|
-
);
|
|
419
|
+
expect(vault.add).toHaveBeenCalledWith(expect.objectContaining({ severity: 'critical' }));
|
|
409
420
|
});
|
|
410
421
|
|
|
411
422
|
it('auto-generates tags from title when none provided', async () => {
|
|
412
423
|
const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
|
|
413
|
-
brain.enrichAndCapture.mockImplementation(() => {
|
|
424
|
+
brain.enrichAndCapture.mockImplementation(() => {
|
|
425
|
+
throw new Error('fail');
|
|
426
|
+
});
|
|
414
427
|
const vault = runtime.vault as ReturnType<typeof makeMockVault>;
|
|
415
428
|
|
|
416
429
|
await executeOp(ops, 'capture_enriched', {
|
|
@@ -426,12 +439,17 @@ describe('vault-facade', () => {
|
|
|
426
439
|
|
|
427
440
|
it('returns error on total failure', async () => {
|
|
428
441
|
const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
|
|
429
|
-
brain.enrichAndCapture.mockImplementation(() => {
|
|
442
|
+
brain.enrichAndCapture.mockImplementation(() => {
|
|
443
|
+
throw new Error('fail');
|
|
444
|
+
});
|
|
430
445
|
const vault = runtime.vault as ReturnType<typeof makeMockVault>;
|
|
431
|
-
vault.add.mockImplementation(() => {
|
|
446
|
+
vault.add.mockImplementation(() => {
|
|
447
|
+
throw new Error('DB error');
|
|
448
|
+
});
|
|
432
449
|
|
|
433
450
|
const result = await executeOp(ops, 'capture_enriched', {
|
|
434
|
-
title: 'Test',
|
|
451
|
+
title: 'Test',
|
|
452
|
+
description: 'Test',
|
|
435
453
|
});
|
|
436
454
|
expect(result.success).toBe(true);
|
|
437
455
|
const data = result.data as { error: string };
|
|
@@ -439,193 +457,107 @@ describe('vault-facade', () => {
|
|
|
439
457
|
});
|
|
440
458
|
});
|
|
441
459
|
|
|
442
|
-
// ───
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
it('connects a vault tier', async () => {
|
|
446
|
-
const result = await executeOp(ops, 'vault_connect', {
|
|
447
|
-
tier: 'project', path: '/tmp/project.db',
|
|
448
|
-
});
|
|
449
|
-
expect(result.success).toBe(true);
|
|
450
|
-
const data = result.data as { connected: boolean; tier: string; path: string };
|
|
451
|
-
expect(data.connected).toBe(true);
|
|
452
|
-
expect(data.tier).toBe('project');
|
|
453
|
-
expect(data.path).toBe('/tmp/project.db');
|
|
454
|
-
});
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
describe('vault_disconnect', () => {
|
|
458
|
-
it('disconnects a vault tier', async () => {
|
|
459
|
-
const result = await executeOp(ops, 'vault_disconnect', { tier: 'team' });
|
|
460
|
-
expect(result.success).toBe(true);
|
|
461
|
-
const data = result.data as { disconnected: boolean; tier: string };
|
|
462
|
-
expect(data.disconnected).toBe(true);
|
|
463
|
-
expect(data.tier).toBe('team');
|
|
464
|
-
});
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
describe('vault_tiers', () => {
|
|
468
|
-
it('lists vault tiers', async () => {
|
|
469
|
-
const result = await executeOp(ops, 'vault_tiers', {});
|
|
470
|
-
expect(result.success).toBe(true);
|
|
471
|
-
const data = result.data as { tiers: Array<{ tier: string }> };
|
|
472
|
-
expect(data.tiers).toHaveLength(1);
|
|
473
|
-
expect(data.tiers[0].tier).toBe('agent');
|
|
474
|
-
});
|
|
475
|
-
});
|
|
460
|
+
// ─── Obsidian ops ──────────────────────────────────────────────────
|
|
461
|
+
// ObsidianSync is instantiated inside the handler, so we test param passing
|
|
462
|
+
// and that the handler doesn't throw. Full ObsidianSync tests are elsewhere.
|
|
476
463
|
|
|
477
|
-
|
|
478
|
-
it('searches across all tiers', async () => {
|
|
479
|
-
const result = await executeOp(ops, 'vault_search_all', { query: 'tokens' });
|
|
480
|
-
expect(result.success).toBe(true);
|
|
481
|
-
const data = result.data as { results: unknown[]; count: number };
|
|
482
|
-
expect(data.count).toBe(1);
|
|
483
|
-
const vm = runtime.vaultManager as ReturnType<typeof makeMockVaultManager>;
|
|
484
|
-
expect(vm.search).toHaveBeenCalledWith('tokens', 20);
|
|
485
|
-
});
|
|
464
|
+
// ─── Backward-compat stubs ──────────────────────────────────────────
|
|
486
465
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
expect(vm.search).toHaveBeenCalledWith('test', 5);
|
|
466
|
+
describe('backward-compat deprecated stubs', () => {
|
|
467
|
+
beforeEach(() => {
|
|
468
|
+
resetDeprecationWarnings();
|
|
491
469
|
});
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
// ─── Named vault connections ───────────────────────────────────────
|
|
495
470
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
471
|
+
it('includes moved ops from all new facades', () => {
|
|
472
|
+
// Spot-check one op from each moved facade
|
|
473
|
+
const movedOps = [
|
|
474
|
+
'vault_archive', // archive
|
|
475
|
+
'vault_git_push', // sync
|
|
476
|
+
'vault_submit_review', // review
|
|
477
|
+
'link_entries', // links
|
|
478
|
+
'vault_branch', // branching
|
|
479
|
+
'vault_connect', // tier
|
|
480
|
+
];
|
|
481
|
+
for (const name of movedOps) {
|
|
482
|
+
expect(ops.has(name), `missing compat stub: ${name}`).toBe(true);
|
|
483
|
+
}
|
|
505
484
|
});
|
|
506
485
|
|
|
507
|
-
it('
|
|
508
|
-
const
|
|
509
|
-
name: 'primary', path: '/tmp/p.db', priority: 1.5,
|
|
510
|
-
});
|
|
511
|
-
expect(result.success).toBe(true);
|
|
512
|
-
const vm = runtime.vaultManager as ReturnType<typeof makeMockVaultManager>;
|
|
513
|
-
expect(vm.connect).toHaveBeenCalledWith('primary', '/tmp/p.db', 1.5);
|
|
514
|
-
});
|
|
515
|
-
});
|
|
486
|
+
it('logs deprecation warning and forwards to real handler', async () => {
|
|
487
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
516
488
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
name: 'team-kb',
|
|
489
|
+
// vault_archive is from archive-facade — call it via vault facade compat
|
|
490
|
+
const result = await executeOp(ops, 'vault_archive', {
|
|
491
|
+
olderThanDays: 90,
|
|
521
492
|
});
|
|
522
493
|
expect(result.success).toBe(true);
|
|
523
|
-
const data = result.data as { disconnected: boolean; name: string };
|
|
524
|
-
expect(data.disconnected).toBe(true);
|
|
525
|
-
expect(data.name).toBe('team-kb');
|
|
526
|
-
});
|
|
527
|
-
});
|
|
528
494
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
expect(
|
|
533
|
-
const data = result.data as { sources: Array<{ name: string }> };
|
|
534
|
-
expect(data.sources).toHaveLength(1);
|
|
535
|
-
expect(data.sources[0].name).toBe('team-shared');
|
|
536
|
-
});
|
|
537
|
-
});
|
|
495
|
+
// Verify deprecation warning was logged
|
|
496
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('[DEPRECATED]'));
|
|
497
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('vault_archive'));
|
|
498
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('archive'));
|
|
538
499
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
it('creates a branch', async () => {
|
|
543
|
-
const result = await executeOp(ops, 'vault_branch', { name: 'experiment' });
|
|
544
|
-
expect(result.success).toBe(true);
|
|
545
|
-
const data = result.data as { created: boolean; name: string };
|
|
546
|
-
expect(data.created).toBe(true);
|
|
547
|
-
expect(data.name).toBe('experiment');
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
it('returns error on duplicate branch', async () => {
|
|
551
|
-
const vb = runtime.vaultBranching as ReturnType<typeof makeMockVaultBranching>;
|
|
552
|
-
vb.branch.mockImplementation(() => { throw new Error('Branch already exists'); });
|
|
553
|
-
const result = await executeOp(ops, 'vault_branch', { name: 'dup' });
|
|
554
|
-
expect(result.success).toBe(true);
|
|
555
|
-
const data = result.data as { error: string };
|
|
556
|
-
expect(data.error).toBe('Branch already exists');
|
|
557
|
-
});
|
|
558
|
-
});
|
|
500
|
+
// Verify the real handler was invoked
|
|
501
|
+
const vault = runtime.vault as ReturnType<typeof makeMockVault>;
|
|
502
|
+
expect(vault.archive).toHaveBeenCalled();
|
|
559
503
|
|
|
560
|
-
|
|
561
|
-
it('adds an operation to a branch', async () => {
|
|
562
|
-
const result = await executeOp(ops, 'vault_branch_add', {
|
|
563
|
-
branchName: 'exp', entryId: 'e1', action: 'add',
|
|
564
|
-
entryData: { id: 'e1', title: 'New', type: 'pattern', domain: 'test' },
|
|
565
|
-
});
|
|
566
|
-
expect(result.success).toBe(true);
|
|
567
|
-
const data = result.data as { added: boolean; action: string };
|
|
568
|
-
expect(data.added).toBe(true);
|
|
569
|
-
expect(data.action).toBe('add');
|
|
504
|
+
warnSpy.mockRestore();
|
|
570
505
|
});
|
|
571
506
|
|
|
572
|
-
it('
|
|
573
|
-
const
|
|
574
|
-
vb.addOperation.mockImplementation(() => { throw new Error('Branch not found'); });
|
|
575
|
-
const result = await executeOp(ops, 'vault_branch_add', {
|
|
576
|
-
branchName: 'missing', entryId: 'e1', action: 'remove',
|
|
577
|
-
});
|
|
578
|
-
expect(result.success).toBe(true);
|
|
579
|
-
expect((result.data as { error: string }).error).toBe('Branch not found');
|
|
580
|
-
});
|
|
581
|
-
});
|
|
507
|
+
it('only logs deprecation warning once per op', async () => {
|
|
508
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
582
509
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
const result = await executeOp(ops, 'vault_branch_list', {});
|
|
586
|
-
expect(result.success).toBe(true);
|
|
587
|
-
const data = result.data as { branches: Array<{ name: string }> };
|
|
588
|
-
expect(data.branches).toHaveLength(1);
|
|
589
|
-
expect(data.branches[0].name).toBe('experiment');
|
|
590
|
-
});
|
|
591
|
-
});
|
|
510
|
+
await executeOp(ops, 'vault_archive', { olderThanDays: 30 });
|
|
511
|
+
await executeOp(ops, 'vault_archive', { olderThanDays: 60 });
|
|
592
512
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
expect(result.success).toBe(true);
|
|
599
|
-
const data = result.data as { merged: boolean; applied: number };
|
|
600
|
-
expect(data.merged).toBe(true);
|
|
601
|
-
expect(data.applied).toBe(3);
|
|
602
|
-
});
|
|
513
|
+
// deprecationWarning deduplicates by op name
|
|
514
|
+
const archiveWarnings = warnSpy.mock.calls.filter(
|
|
515
|
+
(call) => typeof call[0] === 'string' && call[0].includes('vault_archive'),
|
|
516
|
+
);
|
|
517
|
+
expect(archiveWarnings).toHaveLength(1);
|
|
603
518
|
|
|
604
|
-
|
|
605
|
-
const vb = runtime.vaultBranching as ReturnType<typeof makeMockVaultBranching>;
|
|
606
|
-
vb.merge.mockImplementation(() => { throw new Error('Conflict detected'); });
|
|
607
|
-
const result = await executeOp(ops, 'vault_merge_branch', {
|
|
608
|
-
branchName: 'conflict',
|
|
609
|
-
});
|
|
610
|
-
expect(result.success).toBe(true);
|
|
611
|
-
expect((result.data as { error: string }).error).toBe('Conflict detected');
|
|
519
|
+
warnSpy.mockRestore();
|
|
612
520
|
});
|
|
613
521
|
});
|
|
614
522
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
523
|
+
// ─── deprecateOps utility ───────────────────────────────────────────
|
|
524
|
+
|
|
525
|
+
describe('deprecateOps', () => {
|
|
526
|
+
beforeEach(() => {
|
|
527
|
+
resetDeprecationWarnings();
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
it('preserves op metadata (name, description, auth, schema)', () => {
|
|
531
|
+
const original = [
|
|
532
|
+
{
|
|
533
|
+
name: 'test_op',
|
|
534
|
+
description: 'A test op',
|
|
535
|
+
auth: 'write' as const,
|
|
536
|
+
handler: async () => ({ ok: true }),
|
|
537
|
+
},
|
|
538
|
+
];
|
|
539
|
+
const wrapped = deprecateOps(original, 'new-facade');
|
|
540
|
+
expect(wrapped).toHaveLength(1);
|
|
541
|
+
expect(wrapped[0].name).toBe('test_op');
|
|
542
|
+
expect(wrapped[0].description).toBe('A test op');
|
|
543
|
+
expect(wrapped[0].auth).toBe('write');
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it('wraps handler to log warning and return original result', async () => {
|
|
547
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
548
|
+
const original = [
|
|
549
|
+
{
|
|
550
|
+
name: 'moved_op',
|
|
551
|
+
description: 'Moved',
|
|
552
|
+
auth: 'read' as const,
|
|
553
|
+
handler: async () => ({ value: 42 }),
|
|
554
|
+
},
|
|
555
|
+
];
|
|
556
|
+
const wrapped = deprecateOps(original, 'target-facade');
|
|
557
|
+
const result = await wrapped[0].handler({});
|
|
558
|
+
expect(result).toEqual({ value: 42 });
|
|
559
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('target-facade'));
|
|
560
|
+
warnSpy.mockRestore();
|
|
624
561
|
});
|
|
625
562
|
});
|
|
626
|
-
|
|
627
|
-
// ─── Obsidian ops ──────────────────────────────────────────────────
|
|
628
|
-
// ObsidianSync is instantiated inside the handler, so we test param passing
|
|
629
|
-
// and that the handler doesn't throw. Full ObsidianSync tests are elsewhere.
|
|
630
|
-
|
|
631
563
|
});
|