@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
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colocated contract tests for links-facade.ts.
|
|
3
|
+
* Verifies the facade delegates to createVaultLinkingOps and
|
|
4
|
+
* exposes all 9 linking ops with correct auth levels.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
8
|
+
import { createLinksFacadeOps } from './links-facade.js';
|
|
9
|
+
import { captureOps, executeOp } from '../../engine/test-helpers.js';
|
|
10
|
+
import type { CapturedOp } from '../../engine/test-helpers.js';
|
|
11
|
+
import type { AgentRuntime } from '../types.js';
|
|
12
|
+
|
|
13
|
+
// ─── Mock runtime ────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
function makeRuntime(): AgentRuntime {
|
|
16
|
+
return {
|
|
17
|
+
vault: {
|
|
18
|
+
getProvider: vi.fn().mockReturnValue({
|
|
19
|
+
get: vi.fn().mockReturnValue({ id: 'x' }),
|
|
20
|
+
all: vi.fn().mockReturnValue([]),
|
|
21
|
+
run: vi.fn(),
|
|
22
|
+
}),
|
|
23
|
+
},
|
|
24
|
+
linkManager: {
|
|
25
|
+
addLink: vi.fn(),
|
|
26
|
+
removeLink: vi.fn(),
|
|
27
|
+
getLinks: vi.fn().mockReturnValue([]),
|
|
28
|
+
getBacklinks: vi.fn().mockReturnValue([]),
|
|
29
|
+
getLinkCount: vi.fn().mockReturnValue(1),
|
|
30
|
+
traverse: vi.fn().mockReturnValue([]),
|
|
31
|
+
suggestLinks: vi.fn().mockReturnValue([]),
|
|
32
|
+
getOrphans: vi.fn().mockReturnValue([]),
|
|
33
|
+
backfillLinks: vi.fn().mockReturnValue({ created: 0, preview: [] }),
|
|
34
|
+
},
|
|
35
|
+
llmClient: {
|
|
36
|
+
isAvailable: vi.fn().mockReturnValue({ anthropic: false, openai: false }),
|
|
37
|
+
complete: vi.fn(),
|
|
38
|
+
},
|
|
39
|
+
} as unknown as AgentRuntime;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ─── Tests ───────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
describe('links-facade', () => {
|
|
45
|
+
let runtime: AgentRuntime;
|
|
46
|
+
let ops: Map<string, CapturedOp>;
|
|
47
|
+
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
runtime = makeRuntime();
|
|
50
|
+
ops = captureOps(createLinksFacadeOps(runtime));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// ─── Registration ──────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
it('registers exactly 9 ops', () => {
|
|
56
|
+
expect(ops.size).toBe(9);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('includes all expected op names', () => {
|
|
60
|
+
const expected = [
|
|
61
|
+
'link_entries',
|
|
62
|
+
'unlink_entries',
|
|
63
|
+
'get_links',
|
|
64
|
+
'traverse',
|
|
65
|
+
'suggest_links',
|
|
66
|
+
'get_orphans',
|
|
67
|
+
'relink_vault',
|
|
68
|
+
'backfill_links',
|
|
69
|
+
'link_stats',
|
|
70
|
+
];
|
|
71
|
+
for (const name of expected) {
|
|
72
|
+
expect(ops.has(name), `missing op: ${name}`).toBe(true);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// ─── Auth levels ───────────────────────────────────────────────────
|
|
77
|
+
|
|
78
|
+
it('has correct auth levels', () => {
|
|
79
|
+
expect(ops.get('link_entries')!.auth).toBe('write');
|
|
80
|
+
expect(ops.get('unlink_entries')!.auth).toBe('write');
|
|
81
|
+
expect(ops.get('get_links')!.auth).toBe('read');
|
|
82
|
+
expect(ops.get('traverse')!.auth).toBe('read');
|
|
83
|
+
expect(ops.get('suggest_links')!.auth).toBe('read');
|
|
84
|
+
expect(ops.get('get_orphans')!.auth).toBe('read');
|
|
85
|
+
expect(ops.get('relink_vault')!.auth).toBe('write');
|
|
86
|
+
expect(ops.get('backfill_links')!.auth).toBe('write');
|
|
87
|
+
expect(ops.get('link_stats')!.auth).toBe('read');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// ─── Handler delegation ───────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
describe('link_entries', () => {
|
|
93
|
+
it('creates a link via linkManager', async () => {
|
|
94
|
+
const result = await executeOp(ops, 'link_entries', {
|
|
95
|
+
sourceId: 'a',
|
|
96
|
+
targetId: 'b',
|
|
97
|
+
linkType: 'extends',
|
|
98
|
+
note: 'test',
|
|
99
|
+
});
|
|
100
|
+
expect(result.success).toBe(true);
|
|
101
|
+
const data = result.data as { success: boolean };
|
|
102
|
+
expect(data.success).toBe(true);
|
|
103
|
+
const lm = runtime.linkManager as { addLink: ReturnType<typeof vi.fn> };
|
|
104
|
+
expect(lm.addLink).toHaveBeenCalledWith('a', 'b', 'extends', 'test');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('unlink_entries', () => {
|
|
109
|
+
it('removes a link', async () => {
|
|
110
|
+
const result = await executeOp(ops, 'unlink_entries', {
|
|
111
|
+
sourceId: 'a',
|
|
112
|
+
targetId: 'b',
|
|
113
|
+
});
|
|
114
|
+
expect(result.success).toBe(true);
|
|
115
|
+
const lm = runtime.linkManager as { removeLink: ReturnType<typeof vi.fn> };
|
|
116
|
+
expect(lm.removeLink).toHaveBeenCalledWith('a', 'b');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('get_links', () => {
|
|
121
|
+
it('returns outgoing and incoming links', async () => {
|
|
122
|
+
const result = await executeOp(ops, 'get_links', { entryId: 'a' });
|
|
123
|
+
expect(result.success).toBe(true);
|
|
124
|
+
const data = result.data as { totalLinks: number };
|
|
125
|
+
expect(data.totalLinks).toBe(0);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('traverse', () => {
|
|
130
|
+
it('traverses with default depth', async () => {
|
|
131
|
+
const result = await executeOp(ops, 'traverse', { entryId: 'a' });
|
|
132
|
+
expect(result.success).toBe(true);
|
|
133
|
+
const lm = runtime.linkManager as { traverse: ReturnType<typeof vi.fn> };
|
|
134
|
+
expect(lm.traverse).toHaveBeenCalledWith('a', 2);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe('suggest_links', () => {
|
|
139
|
+
it('returns suggestions', async () => {
|
|
140
|
+
const result = await executeOp(ops, 'suggest_links', { entryId: 'a' });
|
|
141
|
+
expect(result.success).toBe(true);
|
|
142
|
+
const data = result.data as { totalSuggestions: number };
|
|
143
|
+
expect(data.totalSuggestions).toBe(0);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('get_orphans', () => {
|
|
148
|
+
it('returns orphaned entries', async () => {
|
|
149
|
+
const result = await executeOp(ops, 'get_orphans', {});
|
|
150
|
+
expect(result.success).toBe(true);
|
|
151
|
+
const data = result.data as { totalOrphans: number };
|
|
152
|
+
expect(data.totalOrphans).toBe(0);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('backfill_links', () => {
|
|
157
|
+
it('delegates to linkManager', async () => {
|
|
158
|
+
const result = await executeOp(ops, 'backfill_links', {
|
|
159
|
+
threshold: 0.7,
|
|
160
|
+
maxLinks: 3,
|
|
161
|
+
dryRun: false,
|
|
162
|
+
batchSize: 50,
|
|
163
|
+
});
|
|
164
|
+
expect(result.success).toBe(true);
|
|
165
|
+
const data = result.data as { created: number };
|
|
166
|
+
expect(data.created).toBe(0);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('link_stats', () => {
|
|
171
|
+
it('returns graph statistics', async () => {
|
|
172
|
+
const provider = (runtime.vault as { getProvider: ReturnType<typeof vi.fn> }).getProvider();
|
|
173
|
+
vi.mocked(provider.get)
|
|
174
|
+
.mockReturnValueOnce({ c: 10 }) // totalLinks
|
|
175
|
+
.mockReturnValueOnce({ c: 50 }) // totalEntries
|
|
176
|
+
.mockReturnValueOnce({ c: 3 }) // orphans
|
|
177
|
+
.mockReturnValueOnce({ c: 5 }); // withNotes
|
|
178
|
+
vi.mocked(provider.all)
|
|
179
|
+
.mockReturnValueOnce([{ link_type: 'extends', c: 7 }])
|
|
180
|
+
.mockReturnValueOnce([{ title: 'Top', links: 5 }]);
|
|
181
|
+
|
|
182
|
+
const result = await executeOp(ops, 'link_stats', {});
|
|
183
|
+
expect(result.success).toBe(true);
|
|
184
|
+
const data = result.data as { totalLinks: number; totalEntries: number };
|
|
185
|
+
expect(data.totalLinks).toBe(10);
|
|
186
|
+
expect(data.totalEntries).toBe(50);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe('relink_vault', () => {
|
|
191
|
+
it('returns error when no LLM available', async () => {
|
|
192
|
+
const result = await executeOp(ops, 'relink_vault', {
|
|
193
|
+
batchSize: 10,
|
|
194
|
+
limit: 0,
|
|
195
|
+
dryRun: false,
|
|
196
|
+
});
|
|
197
|
+
expect(result.success).toBe(true);
|
|
198
|
+
const data = result.data as { success: boolean; error: string };
|
|
199
|
+
expect(data.success).toBe(false);
|
|
200
|
+
expect(data.error).toContain('No LLM');
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Links facade — Zettelkasten entry linking ops.
|
|
3
|
+
* link_entries, unlink_entries, get_links, traverse, suggest_links,
|
|
4
|
+
* get_orphans, relink_vault, backfill_links, link_stats.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { OpDefinition } from '../../facades/types.js';
|
|
8
|
+
import type { AgentRuntime } from '../types.js';
|
|
9
|
+
import { createVaultLinkingOps } from '../vault-linking-ops.js';
|
|
10
|
+
|
|
11
|
+
export function createLinksFacadeOps(runtime: AgentRuntime): OpDefinition[] {
|
|
12
|
+
return createVaultLinkingOps(runtime);
|
|
13
|
+
}
|
|
@@ -7,7 +7,14 @@ import type { AgentRuntime } from '../types.js';
|
|
|
7
7
|
// ─── Mock LoopManager ──────────────────────────────────────────────
|
|
8
8
|
|
|
9
9
|
function makeMockLoop() {
|
|
10
|
-
const activeLoop: {
|
|
10
|
+
const activeLoop: {
|
|
11
|
+
id: string;
|
|
12
|
+
config: Record<string, unknown>;
|
|
13
|
+
iterations: unknown[];
|
|
14
|
+
status: string;
|
|
15
|
+
startedAt: string;
|
|
16
|
+
completedAt?: string;
|
|
17
|
+
} = {
|
|
11
18
|
id: 'loop-1',
|
|
12
19
|
config: { mode: 'custom', prompt: 'test task', maxIterations: 20 },
|
|
13
20
|
iterations: [],
|
|
@@ -16,7 +23,7 @@ function makeMockLoop() {
|
|
|
16
23
|
};
|
|
17
24
|
|
|
18
25
|
let isActive = false;
|
|
19
|
-
const history: typeof activeLoop[] = [];
|
|
26
|
+
const history: (typeof activeLoop)[] = [];
|
|
20
27
|
|
|
21
28
|
return {
|
|
22
29
|
startLoop: vi.fn().mockImplementation((config: Record<string, unknown>) => {
|
|
@@ -118,7 +125,10 @@ describe('loop-facade', () => {
|
|
|
118
125
|
});
|
|
119
126
|
|
|
120
127
|
it('loop_start uses mode-specific defaults for token-migration', async () => {
|
|
121
|
-
const result = await executeOp(ops, 'loop_start', {
|
|
128
|
+
const result = await executeOp(ops, 'loop_start', {
|
|
129
|
+
mode: 'token-migration',
|
|
130
|
+
prompt: 'migrate tokens',
|
|
131
|
+
});
|
|
122
132
|
expect(result.success).toBe(true);
|
|
123
133
|
const data = result.data as Record<string, unknown>;
|
|
124
134
|
expect(data.maxIterations).toBe(20);
|
|
@@ -126,7 +136,11 @@ describe('loop-facade', () => {
|
|
|
126
136
|
});
|
|
127
137
|
|
|
128
138
|
it('loop_start respects custom maxIterations', async () => {
|
|
129
|
-
const result = await executeOp(ops, 'loop_start', {
|
|
139
|
+
const result = await executeOp(ops, 'loop_start', {
|
|
140
|
+
mode: 'custom',
|
|
141
|
+
prompt: 'test',
|
|
142
|
+
maxIterations: 5,
|
|
143
|
+
});
|
|
130
144
|
expect(result.success).toBe(true);
|
|
131
145
|
expect((result.data as Record<string, unknown>).maxIterations).toBe(5);
|
|
132
146
|
});
|
|
@@ -144,7 +158,10 @@ describe('loop-facade', () => {
|
|
|
144
158
|
|
|
145
159
|
it('loop_iterate records a failing iteration', async () => {
|
|
146
160
|
await executeOp(ops, 'loop_start', { mode: 'custom', prompt: 'test' });
|
|
147
|
-
const result = await executeOp(ops, 'loop_iterate', {
|
|
161
|
+
const result = await executeOp(ops, 'loop_iterate', {
|
|
162
|
+
passed: false,
|
|
163
|
+
validationResult: 'score too low',
|
|
164
|
+
});
|
|
148
165
|
expect(result.success).toBe(true);
|
|
149
166
|
expect((result.data as Record<string, unknown>).passed).toBe(false);
|
|
150
167
|
});
|
|
@@ -127,10 +127,16 @@ describe('memory-facade', () => {
|
|
|
127
127
|
|
|
128
128
|
it('memory_list filters by type', async () => {
|
|
129
129
|
await executeOp(ops, 'memory_capture', {
|
|
130
|
-
projectPath: '/test',
|
|
130
|
+
projectPath: '/test',
|
|
131
|
+
type: 'lesson',
|
|
132
|
+
context: 'c',
|
|
133
|
+
summary: 'lesson',
|
|
131
134
|
});
|
|
132
135
|
await executeOp(ops, 'memory_capture', {
|
|
133
|
-
projectPath: '/test',
|
|
136
|
+
projectPath: '/test',
|
|
137
|
+
type: 'preference',
|
|
138
|
+
context: 'c',
|
|
139
|
+
summary: 'pref',
|
|
134
140
|
});
|
|
135
141
|
const result = await executeOp(ops, 'memory_list', { type: 'lesson' });
|
|
136
142
|
expect(result.success).toBe(true);
|
|
@@ -140,7 +146,10 @@ describe('memory-facade', () => {
|
|
|
140
146
|
|
|
141
147
|
it('memory_list verbose returns full objects', async () => {
|
|
142
148
|
await executeOp(ops, 'memory_capture', {
|
|
143
|
-
projectPath: '/test',
|
|
149
|
+
projectPath: '/test',
|
|
150
|
+
type: 'lesson',
|
|
151
|
+
context: 'c',
|
|
152
|
+
summary: 'verbose list',
|
|
144
153
|
});
|
|
145
154
|
const result = await executeOp(ops, 'memory_list', { verbose: true });
|
|
146
155
|
expect(result.success).toBe(true);
|
|
@@ -192,9 +201,14 @@ describe('memory-facade', () => {
|
|
|
192
201
|
|
|
193
202
|
it('memory_delete removes a memory', async () => {
|
|
194
203
|
const captureResult = await executeOp(ops, 'memory_capture', {
|
|
195
|
-
projectPath: '/test',
|
|
204
|
+
projectPath: '/test',
|
|
205
|
+
type: 'lesson',
|
|
206
|
+
context: 'c',
|
|
207
|
+
summary: 'to delete',
|
|
196
208
|
});
|
|
197
|
-
const memoryId = (
|
|
209
|
+
const memoryId = (
|
|
210
|
+
(captureResult.data as Record<string, unknown>).memory as Record<string, unknown>
|
|
211
|
+
).id as string;
|
|
198
212
|
const result = await executeOp(ops, 'memory_delete', { memoryId });
|
|
199
213
|
expect(result.success).toBe(true);
|
|
200
214
|
expect((result.data as Record<string, unknown>).deleted).toBe(true);
|
|
@@ -45,9 +45,16 @@ describe('operator-facade (colocated)', () => {
|
|
|
45
45
|
expect(ops.size).toBe(10);
|
|
46
46
|
expect([...ops.keys()]).toEqual(
|
|
47
47
|
expect.arrayContaining([
|
|
48
|
-
'profile_get',
|
|
49
|
-
'
|
|
50
|
-
'
|
|
48
|
+
'profile_get',
|
|
49
|
+
'profile_update_section',
|
|
50
|
+
'profile_correct',
|
|
51
|
+
'profile_delete',
|
|
52
|
+
'profile_export',
|
|
53
|
+
'signal_accumulate',
|
|
54
|
+
'signal_list',
|
|
55
|
+
'signal_stats',
|
|
56
|
+
'synthesis_check',
|
|
57
|
+
'profile_snapshot',
|
|
51
58
|
]),
|
|
52
59
|
);
|
|
53
60
|
});
|
|
@@ -85,7 +92,13 @@ describe('operator-facade (colocated)', () => {
|
|
|
85
92
|
it('profile_update_section updates section', async () => {
|
|
86
93
|
const result = await executeOp(ops, 'profile_update_section', {
|
|
87
94
|
section: 'communication',
|
|
88
|
-
data: {
|
|
95
|
+
data: {
|
|
96
|
+
style: 'concise',
|
|
97
|
+
signalWords: ['yo'],
|
|
98
|
+
formality: 0.3,
|
|
99
|
+
patience: 0.9,
|
|
100
|
+
adaptationRules: [],
|
|
101
|
+
},
|
|
89
102
|
});
|
|
90
103
|
expect(result.success).toBe(true);
|
|
91
104
|
expect((result.data as Record<string, unknown>).updated).toBe(true);
|
|
@@ -67,7 +67,8 @@ function profileToMarkdown(profile: Record<string, unknown>): string {
|
|
|
67
67
|
if (evidence.length > 0) {
|
|
68
68
|
lines.push(`**Evidence (${evidence.length}):**`, '');
|
|
69
69
|
for (const e of evidence.slice(0, 10)) {
|
|
70
|
-
const label =
|
|
70
|
+
const label =
|
|
71
|
+
e.source === 'observed' ? '[observed]' : e.source === 'reported' ? '[reported]' : '';
|
|
71
72
|
lines.push(`- ${label} ${e.summary} (confidence: ${e.confidence}, ${e.timestamp})`);
|
|
72
73
|
}
|
|
73
74
|
lines.push('');
|
|
@@ -77,10 +78,17 @@ function profileToMarkdown(profile: Record<string, unknown>): string {
|
|
|
77
78
|
return lines.join('\n');
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
function extractEvidence(
|
|
81
|
+
function extractEvidence(
|
|
82
|
+
obj: Record<string, unknown>,
|
|
83
|
+
): Array<{ summary: string; confidence: number; timestamp: string; source?: string }> {
|
|
81
84
|
const evidence = obj.evidence;
|
|
82
85
|
if (!Array.isArray(evidence)) return [];
|
|
83
|
-
return evidence.filter((e) => e && typeof e === 'object' && 'summary' in e) as Array<{
|
|
86
|
+
return evidence.filter((e) => e && typeof e === 'object' && 'summary' in e) as Array<{
|
|
87
|
+
summary: string;
|
|
88
|
+
confidence: number;
|
|
89
|
+
timestamp: string;
|
|
90
|
+
source?: string;
|
|
91
|
+
}>;
|
|
84
92
|
}
|
|
85
93
|
|
|
86
94
|
// ─── Facade Creator ─────────────────────────────────────────────────
|
|
@@ -25,7 +25,13 @@ function makeRuntime(vault: Vault): AgentRuntime {
|
|
|
25
25
|
const playbookExecutor = new PlaybookExecutor();
|
|
26
26
|
const contextHealth = {
|
|
27
27
|
track: vi.fn(),
|
|
28
|
-
check: vi.fn().mockReturnValue({
|
|
28
|
+
check: vi.fn().mockReturnValue({
|
|
29
|
+
level: 'green',
|
|
30
|
+
estimatedFill: 0.1,
|
|
31
|
+
toolCallCount: 5,
|
|
32
|
+
estimatedTokens: 1000,
|
|
33
|
+
recommendation: '',
|
|
34
|
+
}),
|
|
29
35
|
};
|
|
30
36
|
|
|
31
37
|
return {
|
|
@@ -23,7 +23,13 @@ function makeRuntime(vault: Vault): AgentRuntime {
|
|
|
23
23
|
const linkManager = null;
|
|
24
24
|
const chainRunner = new ChainRunner(vault.getProvider());
|
|
25
25
|
return {
|
|
26
|
-
vault,
|
|
26
|
+
vault,
|
|
27
|
+
planner,
|
|
28
|
+
brain,
|
|
29
|
+
brainIntelligence,
|
|
30
|
+
curator,
|
|
31
|
+
linkManager,
|
|
32
|
+
chainRunner,
|
|
27
33
|
} as unknown as AgentRuntime;
|
|
28
34
|
}
|
|
29
35
|
|
|
@@ -92,9 +98,11 @@ describe('plan-facade', () => {
|
|
|
92
98
|
|
|
93
99
|
it('get_plan returns plan by ID', async () => {
|
|
94
100
|
const createResult = await executeOp(ops, 'create_plan', {
|
|
95
|
-
objective: 'Test',
|
|
101
|
+
objective: 'Test',
|
|
102
|
+
scope: 'test',
|
|
96
103
|
});
|
|
97
|
-
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
104
|
+
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
105
|
+
.id as string;
|
|
98
106
|
const result = await executeOp(ops, 'get_plan', { planId });
|
|
99
107
|
expect(result.success).toBe(true);
|
|
100
108
|
expect((result.data as Record<string, unknown>).objective).toBe('Test');
|
|
@@ -126,7 +134,8 @@ describe('plan-facade', () => {
|
|
|
126
134
|
{ title: 'Task 2', description: 'desc 2' },
|
|
127
135
|
],
|
|
128
136
|
});
|
|
129
|
-
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
137
|
+
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
138
|
+
.id as string;
|
|
130
139
|
|
|
131
140
|
const result = await executeOp(ops, 'approve_plan', { planId });
|
|
132
141
|
expect(result.success).toBe(true);
|
|
@@ -150,7 +159,8 @@ describe('plan-facade', () => {
|
|
|
150
159
|
{ approach: 'Alt B', pros: ['safe'], cons: ['slow'], rejected_reason: 'Too slow' },
|
|
151
160
|
],
|
|
152
161
|
});
|
|
153
|
-
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
162
|
+
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
163
|
+
.id as string;
|
|
154
164
|
|
|
155
165
|
const result = await executeOp(ops, 'approve_plan', { planId, startExecution: true });
|
|
156
166
|
expect(result.success).toBe(true);
|
|
@@ -171,13 +181,15 @@ describe('plan-facade', () => {
|
|
|
171
181
|
});
|
|
172
182
|
const plan = (createResult.data as Record<string, unknown>).plan as Record<string, unknown>;
|
|
173
183
|
const planId = plan.id as string;
|
|
174
|
-
const taskId = (
|
|
184
|
+
const taskId = (plan.tasks as Array<Record<string, unknown>>)[0].id as string;
|
|
175
185
|
|
|
176
186
|
// Approve and start execution first
|
|
177
187
|
await executeOp(ops, 'approve_plan', { planId, startExecution: true });
|
|
178
188
|
|
|
179
189
|
const result = await executeOp(ops, 'update_task', {
|
|
180
|
-
planId,
|
|
190
|
+
planId,
|
|
191
|
+
taskId,
|
|
192
|
+
status: 'completed',
|
|
181
193
|
});
|
|
182
194
|
expect(result.success).toBe(true);
|
|
183
195
|
const data = result.data as { updated: boolean };
|
|
@@ -197,7 +209,8 @@ describe('plan-facade', () => {
|
|
|
197
209
|
{ approach: 'B', pros: ['a'], cons: ['b'], rejected_reason: 'c' },
|
|
198
210
|
],
|
|
199
211
|
});
|
|
200
|
-
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
212
|
+
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
213
|
+
.id as string;
|
|
201
214
|
await executeOp(ops, 'approve_plan', { planId, startExecution: true });
|
|
202
215
|
|
|
203
216
|
const result = await executeOp(ops, 'complete_plan', { planId });
|
|
@@ -211,12 +224,15 @@ describe('plan-facade', () => {
|
|
|
211
224
|
|
|
212
225
|
it('plan_iterate revises a draft plan', async () => {
|
|
213
226
|
const createResult = await executeOp(ops, 'create_plan', {
|
|
214
|
-
objective: 'Initial',
|
|
227
|
+
objective: 'Initial',
|
|
228
|
+
scope: 'test',
|
|
215
229
|
});
|
|
216
|
-
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
230
|
+
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
231
|
+
.id as string;
|
|
217
232
|
|
|
218
233
|
const result = await executeOp(ops, 'plan_iterate', {
|
|
219
|
-
planId,
|
|
234
|
+
planId,
|
|
235
|
+
objective: 'Revised objective',
|
|
220
236
|
});
|
|
221
237
|
expect(result.success).toBe(true);
|
|
222
238
|
const data = result.data as { iterated?: boolean; error?: string };
|
|
@@ -240,7 +256,8 @@ describe('plan-facade', () => {
|
|
|
240
256
|
decisions: ['Use pattern X'],
|
|
241
257
|
tasks: [{ title: 'Task 1', description: 'desc' }],
|
|
242
258
|
});
|
|
243
|
-
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
259
|
+
const planId = ((createResult.data as Record<string, unknown>).plan as Record<string, unknown>)
|
|
260
|
+
.id as string;
|
|
244
261
|
|
|
245
262
|
const result = await executeOp(ops, 'plan_grade', { planId });
|
|
246
263
|
expect(result.success).toBe(true);
|
|
@@ -24,7 +24,10 @@ export function createPlanFacadeOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
24
24
|
schema: z.object({
|
|
25
25
|
objective: z.string().describe('What the plan aims to achieve'),
|
|
26
26
|
scope: z.string().describe('Which parts of the codebase are affected'),
|
|
27
|
-
decisions: z
|
|
27
|
+
decisions: z
|
|
28
|
+
.array(z.union([z.string(), z.object({ decision: z.string(), rationale: z.string() })]))
|
|
29
|
+
.optional()
|
|
30
|
+
.default([]),
|
|
28
31
|
tasks: z
|
|
29
32
|
.array(z.object({ title: z.string(), description: z.string() }))
|
|
30
33
|
.optional()
|
|
@@ -47,7 +50,9 @@ export function createPlanFacadeOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
47
50
|
scope: params.scope as string,
|
|
48
51
|
decisions: (params.decisions as string[]) ?? [],
|
|
49
52
|
tasks: (params.tasks as Array<{ title: string; description: string }>) ?? [],
|
|
50
|
-
alternatives: params.alternatives as
|
|
53
|
+
alternatives: params.alternatives as
|
|
54
|
+
| Array<{ approach: string; pros: string[]; cons: string[]; rejected_reason: string }>
|
|
55
|
+
| undefined,
|
|
51
56
|
});
|
|
52
57
|
return { created: true, plan };
|
|
53
58
|
},
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colocated contract tests for tier-facade.ts.
|
|
3
|
+
* Verifies the facade wrapper delegates to tier-ops.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
7
|
+
import { createTierFacadeOps } from './tier-facade.js';
|
|
8
|
+
import type { AgentRuntime } from '../types.js';
|
|
9
|
+
|
|
10
|
+
function makeRuntime(): AgentRuntime {
|
|
11
|
+
return {
|
|
12
|
+
vaultManager: {
|
|
13
|
+
open: vi.fn(),
|
|
14
|
+
disconnect: vi.fn().mockReturnValue(true),
|
|
15
|
+
listTiers: vi.fn().mockReturnValue([]),
|
|
16
|
+
search: vi.fn().mockReturnValue([]),
|
|
17
|
+
connect: vi.fn(),
|
|
18
|
+
disconnectNamed: vi.fn().mockReturnValue(true),
|
|
19
|
+
listConnected: vi.fn().mockReturnValue([]),
|
|
20
|
+
},
|
|
21
|
+
config: { agentId: 'test-agent' },
|
|
22
|
+
} as unknown as AgentRuntime;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('tier-facade', () => {
|
|
26
|
+
it('returns all 7 tier/source ops', () => {
|
|
27
|
+
const ops = createTierFacadeOps(makeRuntime());
|
|
28
|
+
expect(ops).toHaveLength(7);
|
|
29
|
+
const names = ops.map((o) => o.name);
|
|
30
|
+
expect(names).toContain('vault_connect');
|
|
31
|
+
expect(names).toContain('vault_disconnect');
|
|
32
|
+
expect(names).toContain('vault_tiers');
|
|
33
|
+
expect(names).toContain('vault_search_all');
|
|
34
|
+
expect(names).toContain('vault_connect_source');
|
|
35
|
+
expect(names).toContain('vault_disconnect_source');
|
|
36
|
+
expect(names).toContain('vault_list_sources');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('every op has name, handler, and auth', () => {
|
|
40
|
+
const ops = createTierFacadeOps(makeRuntime());
|
|
41
|
+
for (const op of ops) {
|
|
42
|
+
expect(typeof op.name).toBe('string');
|
|
43
|
+
expect(typeof op.handler).toBe('function');
|
|
44
|
+
expect(typeof op.auth).toBe('string');
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier facade — multi-vault tier and named source operations.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { OpDefinition } from '../../facades/types.js';
|
|
6
|
+
import type { AgentRuntime } from '../types.js';
|
|
7
|
+
import { createTierOps } from '../tier-ops.js';
|
|
8
|
+
|
|
9
|
+
export function createTierFacadeOps(runtime: AgentRuntime): OpDefinition[] {
|
|
10
|
+
return [...createTierOps(runtime)];
|
|
11
|
+
}
|