@soleri/core 9.2.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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.map +1 -1
- package/dist/engine/module-manifest.js +21 -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/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-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-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 +32 -10
- 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 +5 -4
- package/src/engine/module-manifest.ts +21 -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/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-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 +1 -3
- 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.ts +54 -27
- 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-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
|
@@ -11,8 +11,12 @@ import {
|
|
|
11
11
|
import type { PlanTask, TaskEvidence, TaskDeliverable, ReviewEvidence } from './planner-types.js';
|
|
12
12
|
|
|
13
13
|
const makeTask = (overrides: Partial<PlanTask> = {}): PlanTask => ({
|
|
14
|
-
id: 'task-1',
|
|
15
|
-
|
|
14
|
+
id: 'task-1',
|
|
15
|
+
title: 'Test task',
|
|
16
|
+
description: 'Do something',
|
|
17
|
+
status: 'pending',
|
|
18
|
+
updatedAt: 0,
|
|
19
|
+
...overrides,
|
|
16
20
|
});
|
|
17
21
|
|
|
18
22
|
describe('task-verifier', () => {
|
|
@@ -21,7 +25,11 @@ describe('task-verifier', () => {
|
|
|
21
25
|
const existing: TaskEvidence[] = [
|
|
22
26
|
{ criterion: 'cr1', content: 'result', type: 'description', submittedAt: 100 },
|
|
23
27
|
];
|
|
24
|
-
const result = createEvidence(existing, {
|
|
28
|
+
const result = createEvidence(existing, {
|
|
29
|
+
criterion: 'cr2',
|
|
30
|
+
content: 'output',
|
|
31
|
+
type: 'command_output',
|
|
32
|
+
});
|
|
25
33
|
expect(result).toHaveLength(2);
|
|
26
34
|
expect(result[1].criterion).toBe('cr2');
|
|
27
35
|
expect(result[1].submittedAt).toBeGreaterThan(0);
|
|
@@ -66,22 +74,50 @@ describe('task-verifier', () => {
|
|
|
66
74
|
it('returns verified=true when task has approved review', () => {
|
|
67
75
|
const task = makeTask({ status: 'completed' });
|
|
68
76
|
const reviews: ReviewEvidence[] = [
|
|
69
|
-
{
|
|
77
|
+
{
|
|
78
|
+
planId: 'p1',
|
|
79
|
+
taskId: 'task-1',
|
|
80
|
+
reviewer: 'r',
|
|
81
|
+
outcome: 'approved',
|
|
82
|
+
comments: '',
|
|
83
|
+
reviewedAt: 0,
|
|
84
|
+
},
|
|
70
85
|
];
|
|
71
86
|
expect(verifyTaskLogic(task, reviews).verified).toBe(true);
|
|
72
87
|
});
|
|
73
88
|
it('returns verified=false when task has rejected review', () => {
|
|
74
89
|
const task = makeTask({ status: 'completed' });
|
|
75
90
|
const reviews: ReviewEvidence[] = [
|
|
76
|
-
{
|
|
91
|
+
{
|
|
92
|
+
planId: 'p1',
|
|
93
|
+
taskId: 'task-1',
|
|
94
|
+
reviewer: 'r',
|
|
95
|
+
outcome: 'rejected',
|
|
96
|
+
comments: '',
|
|
97
|
+
reviewedAt: 0,
|
|
98
|
+
},
|
|
77
99
|
];
|
|
78
100
|
expect(verifyTaskLogic(task, reviews).verified).toBe(false);
|
|
79
101
|
});
|
|
80
102
|
it('uses latest review outcome', () => {
|
|
81
103
|
const task = makeTask({ status: 'completed' });
|
|
82
104
|
const reviews: ReviewEvidence[] = [
|
|
83
|
-
{
|
|
84
|
-
|
|
105
|
+
{
|
|
106
|
+
planId: 'p1',
|
|
107
|
+
taskId: 'task-1',
|
|
108
|
+
reviewer: 'r',
|
|
109
|
+
outcome: 'rejected',
|
|
110
|
+
comments: '',
|
|
111
|
+
reviewedAt: 0,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
planId: 'p1',
|
|
115
|
+
taskId: 'task-1',
|
|
116
|
+
reviewer: 'r',
|
|
117
|
+
outcome: 'approved',
|
|
118
|
+
comments: '',
|
|
119
|
+
reviewedAt: 1,
|
|
120
|
+
},
|
|
85
121
|
];
|
|
86
122
|
expect(verifyTaskLogic(task, reviews).verified).toBe(true);
|
|
87
123
|
});
|
|
@@ -110,9 +146,13 @@ describe('task-verifier', () => {
|
|
|
110
146
|
expect(result.issues[0].issue).toContain('pending');
|
|
111
147
|
});
|
|
112
148
|
it('flags missing evidence for completed tasks with acceptance criteria', () => {
|
|
113
|
-
const tasks: PlanTask[] = [
|
|
114
|
-
|
|
115
|
-
|
|
149
|
+
const tasks: PlanTask[] = [
|
|
150
|
+
makeTask({
|
|
151
|
+
status: 'completed',
|
|
152
|
+
acceptanceCriteria: ['cr1'],
|
|
153
|
+
evidence: [],
|
|
154
|
+
}),
|
|
155
|
+
];
|
|
116
156
|
const result = verifyPlanLogic('plan-1', tasks);
|
|
117
157
|
expect(result.issues[0].issue).toContain('Missing evidence');
|
|
118
158
|
});
|
|
@@ -138,35 +178,27 @@ describe('task-verifier', () => {
|
|
|
138
178
|
expect(result.staleCount).toBe(0);
|
|
139
179
|
});
|
|
140
180
|
it('marks file deliverables as stale when file does not exist', () => {
|
|
141
|
-
const deliverables: TaskDeliverable[] = [
|
|
142
|
-
{ type: 'file', path: '/nonexistent/path/file.ts' },
|
|
143
|
-
];
|
|
181
|
+
const deliverables: TaskDeliverable[] = [{ type: 'file', path: '/nonexistent/path/file.ts' }];
|
|
144
182
|
const result = verifyDeliverablesLogic(deliverables);
|
|
145
183
|
expect(result.verified).toBe(false);
|
|
146
184
|
expect(result.staleCount).toBe(1);
|
|
147
185
|
expect(result.deliverables[0].stale).toBe(true);
|
|
148
186
|
});
|
|
149
187
|
it('marks vault_entry deliverables as stale when vault returns null', () => {
|
|
150
|
-
const deliverables: TaskDeliverable[] = [
|
|
151
|
-
{ type: 'vault_entry', path: 'entry-123' },
|
|
152
|
-
];
|
|
188
|
+
const deliverables: TaskDeliverable[] = [{ type: 'vault_entry', path: 'entry-123' }];
|
|
153
189
|
const vault = { get: () => null };
|
|
154
190
|
const result = verifyDeliverablesLogic(deliverables, vault);
|
|
155
191
|
expect(result.staleCount).toBe(1);
|
|
156
192
|
});
|
|
157
193
|
it('marks vault_entry deliverables as valid when vault returns non-null', () => {
|
|
158
|
-
const deliverables: TaskDeliverable[] = [
|
|
159
|
-
{ type: 'vault_entry', path: 'entry-123' },
|
|
160
|
-
];
|
|
194
|
+
const deliverables: TaskDeliverable[] = [{ type: 'vault_entry', path: 'entry-123' }];
|
|
161
195
|
const vault = { get: () => ({ id: 'entry-123' }) };
|
|
162
196
|
const result = verifyDeliverablesLogic(deliverables, vault);
|
|
163
197
|
expect(result.verified).toBe(true);
|
|
164
198
|
expect(result.staleCount).toBe(0);
|
|
165
199
|
});
|
|
166
200
|
it('skips url deliverables (no verification)', () => {
|
|
167
|
-
const deliverables: TaskDeliverable[] = [
|
|
168
|
-
{ type: 'url', path: 'https://example.com' },
|
|
169
|
-
];
|
|
201
|
+
const deliverables: TaskDeliverable[] = [{ type: 'url', path: 'https://example.com' }];
|
|
170
202
|
const result = verifyDeliverablesLogic(deliverables);
|
|
171
203
|
expect(result.verified).toBe(true);
|
|
172
204
|
});
|
|
@@ -214,17 +246,17 @@ describe('task-verifier', () => {
|
|
|
214
246
|
expect(prompt).toContain('2. No regressions');
|
|
215
247
|
});
|
|
216
248
|
it('omits criteria section when empty', () => {
|
|
217
|
-
const prompt = buildSpecReviewPrompt(
|
|
218
|
-
{ title: 'T', description: 'd' },
|
|
219
|
-
'Objective',
|
|
220
|
-
);
|
|
249
|
+
const prompt = buildSpecReviewPrompt({ title: 'T', description: 'd' }, 'Objective');
|
|
221
250
|
expect(prompt).not.toContain('Acceptance Criteria');
|
|
222
251
|
});
|
|
223
252
|
});
|
|
224
253
|
|
|
225
254
|
describe('buildQualityReviewPrompt', () => {
|
|
226
255
|
it('includes task info and quality checklist', () => {
|
|
227
|
-
const prompt = buildQualityReviewPrompt({
|
|
256
|
+
const prompt = buildQualityReviewPrompt({
|
|
257
|
+
title: 'Refactor X',
|
|
258
|
+
description: 'Clean up code',
|
|
259
|
+
});
|
|
228
260
|
expect(prompt).toContain('Refactor X');
|
|
229
261
|
expect(prompt).toContain('Clean up code');
|
|
230
262
|
expect(prompt).toContain('Code Quality Review');
|
|
@@ -268,14 +268,18 @@ export function buildSpecReviewPrompt(
|
|
|
268
268
|
? `\n\nAcceptance Criteria:\n${task.acceptanceCriteria.map((c, i) => `${i + 1}. ${c}`).join('\n')}`
|
|
269
269
|
: '';
|
|
270
270
|
return [
|
|
271
|
-
`# Spec Compliance Review`,
|
|
271
|
+
`# Spec Compliance Review`,
|
|
272
|
+
``,
|
|
273
|
+
`## Task: ${task.title}`,
|
|
272
274
|
`**Description:** ${task.description}`,
|
|
273
|
-
`**Plan Objective:** ${planObjective}${criteria}`,
|
|
275
|
+
`**Plan Objective:** ${planObjective}${criteria}`,
|
|
276
|
+
``,
|
|
274
277
|
`## Review Checklist`,
|
|
275
278
|
`1. Does the implementation match the task description?`,
|
|
276
279
|
`2. Are all acceptance criteria satisfied?`,
|
|
277
280
|
`3. Does it align with the plan's overall objective?`,
|
|
278
|
-
`4. Are there any spec deviations?`,
|
|
281
|
+
`4. Are there any spec deviations?`,
|
|
282
|
+
``,
|
|
279
283
|
`Provide: outcome (approved/rejected/needs_changes) and detailed comments.`,
|
|
280
284
|
].join('\n');
|
|
281
285
|
}
|
|
@@ -284,12 +288,13 @@ export function buildSpecReviewPrompt(
|
|
|
284
288
|
* Generate a code quality review prompt for a task.
|
|
285
289
|
* Pure function — no persistence side-effects.
|
|
286
290
|
*/
|
|
287
|
-
export function buildQualityReviewPrompt(
|
|
288
|
-
task: Pick<PlanTask, 'title' | 'description'>,
|
|
289
|
-
): string {
|
|
291
|
+
export function buildQualityReviewPrompt(task: Pick<PlanTask, 'title' | 'description'>): string {
|
|
290
292
|
return [
|
|
291
|
-
`# Code Quality Review`,
|
|
292
|
-
|
|
293
|
+
`# Code Quality Review`,
|
|
294
|
+
``,
|
|
295
|
+
`## Task: ${task.title}`,
|
|
296
|
+
`**Description:** ${task.description}`,
|
|
297
|
+
``,
|
|
293
298
|
`## Quality Checklist`,
|
|
294
299
|
`1. **Correctness** — Does it work as intended?`,
|
|
295
300
|
`2. **Security** — No injection, XSS, or OWASP top 10 vulnerabilities?`,
|
|
@@ -297,7 +302,8 @@ export function buildQualityReviewPrompt(
|
|
|
297
302
|
`4. **Maintainability** — Clear naming, appropriate abstractions, documented intent?`,
|
|
298
303
|
`5. **Testing** — Adequate test coverage for the changes?`,
|
|
299
304
|
`6. **Error Handling** — Graceful degradation, no swallowed errors?`,
|
|
300
|
-
`7. **Conventions** — Follows project coding standards?`,
|
|
305
|
+
`7. **Conventions** — Follows project coding standards?`,
|
|
306
|
+
``,
|
|
301
307
|
`Provide: outcome (approved/rejected/needs_changes) and detailed comments.`,
|
|
302
308
|
].join('\n');
|
|
303
309
|
}
|
|
@@ -19,9 +19,7 @@ function makePlaybook(overrides: Partial<PlaybookDefinition> = {}): PlaybookDefi
|
|
|
19
19
|
tags: [],
|
|
20
20
|
matchIntents: ['BUILD'],
|
|
21
21
|
matchKeywords: [],
|
|
22
|
-
gates: [
|
|
23
|
-
{ phase: 'completion', requirement: 'Tests pass', checkType: 'test-pass' },
|
|
24
|
-
],
|
|
22
|
+
gates: [{ phase: 'completion', requirement: 'Tests pass', checkType: 'test-pass' }],
|
|
25
23
|
taskTemplates: [],
|
|
26
24
|
toolInjections: ['search_intelligent'],
|
|
27
25
|
verificationCriteria: ['All tests pass'],
|
|
@@ -13,7 +13,10 @@ import type { LoadedPlugin, PluginManifest } from './types.js';
|
|
|
13
13
|
let testDirs: string[] = [];
|
|
14
14
|
|
|
15
15
|
function makeTempDir(): string {
|
|
16
|
-
const dir = join(
|
|
16
|
+
const dir = join(
|
|
17
|
+
tmpdir(),
|
|
18
|
+
`soleri-loader-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
19
|
+
);
|
|
17
20
|
mkdirSync(dir, { recursive: true });
|
|
18
21
|
testDirs.push(dir);
|
|
19
22
|
return dir;
|
|
@@ -26,13 +29,15 @@ function writePlugin(parentDir: string, id: string, manifest: Record<string, unk
|
|
|
26
29
|
return dir;
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
function makeLoaded(
|
|
32
|
+
function makeLoaded(
|
|
33
|
+
overrides: Partial<LoadedPlugin & { manifest: Partial<PluginManifest> }> = {},
|
|
34
|
+
): LoadedPlugin {
|
|
30
35
|
return {
|
|
31
36
|
manifest: pluginManifestSchema.parse({
|
|
32
37
|
id: 'test-plugin',
|
|
33
38
|
name: 'Test',
|
|
34
39
|
version: '1.0.0',
|
|
35
|
-
...
|
|
40
|
+
...overrides.manifest,
|
|
36
41
|
}),
|
|
37
42
|
directory: overrides.directory ?? '/tmp/test',
|
|
38
43
|
provenance: overrides.provenance ?? 'global',
|
|
@@ -41,7 +46,11 @@ function makeLoaded(overrides: Partial<LoadedPlugin & { manifest: Partial<Plugin
|
|
|
41
46
|
|
|
42
47
|
afterEach(() => {
|
|
43
48
|
for (const dir of testDirs) {
|
|
44
|
-
try {
|
|
49
|
+
try {
|
|
50
|
+
rmSync(dir, { recursive: true, force: true });
|
|
51
|
+
} catch {
|
|
52
|
+
/* noop */
|
|
53
|
+
}
|
|
45
54
|
}
|
|
46
55
|
testDirs = [];
|
|
47
56
|
});
|
|
@@ -62,11 +71,11 @@ describe('loadPlugins — colocated', () => {
|
|
|
62
71
|
const result = loadPlugins('test-agent', undefined, [dir1, dir2]);
|
|
63
72
|
|
|
64
73
|
expect(result.loaded).toHaveLength(2);
|
|
65
|
-
const ids = result.loaded.map(p => p.manifest.id);
|
|
74
|
+
const ids = result.loaded.map((p) => p.manifest.id);
|
|
66
75
|
expect(ids).toContain('alpha');
|
|
67
76
|
expect(ids).toContain('beta');
|
|
68
77
|
// First occurrence wins
|
|
69
|
-
expect(result.loaded.find(p => p.manifest.id === 'alpha')!.manifest.name).toBe('Alpha');
|
|
78
|
+
expect(result.loaded.find((p) => p.manifest.id === 'alpha')!.manifest.name).toBe('Alpha');
|
|
70
79
|
});
|
|
71
80
|
|
|
72
81
|
it('skips files (non-directories) inside plugin dir', () => {
|
|
@@ -154,18 +163,14 @@ describe('validateDependencies — colocated', () => {
|
|
|
154
163
|
});
|
|
155
164
|
|
|
156
165
|
it('detects multiple missing dependencies', () => {
|
|
157
|
-
const plugins = [
|
|
158
|
-
makeLoaded({ manifest: { id: 'lonely', dependencies: ['dep-a', 'dep-b'] } }),
|
|
159
|
-
];
|
|
166
|
+
const plugins = [makeLoaded({ manifest: { id: 'lonely', dependencies: ['dep-a', 'dep-b'] } })];
|
|
160
167
|
const errors = validateDependencies(plugins);
|
|
161
168
|
expect(errors).toHaveLength(2);
|
|
162
|
-
expect(errors.map(e => e.missingDep)).toEqual(['dep-a', 'dep-b']);
|
|
169
|
+
expect(errors.map((e) => e.missingDep)).toEqual(['dep-a', 'dep-b']);
|
|
163
170
|
});
|
|
164
171
|
|
|
165
172
|
it('handles plugins with no dependencies', () => {
|
|
166
|
-
const plugins = [
|
|
167
|
-
makeLoaded({ manifest: { id: 'standalone' } }),
|
|
168
|
-
];
|
|
173
|
+
const plugins = [makeLoaded({ manifest: { id: 'standalone' } })];
|
|
169
174
|
expect(validateDependencies(plugins)).toEqual([]);
|
|
170
175
|
});
|
|
171
176
|
});
|
|
@@ -181,7 +186,7 @@ describe('sortByDependencies — colocated', () => {
|
|
|
181
186
|
const a = makeLoaded({ manifest: { id: 'a' } });
|
|
182
187
|
|
|
183
188
|
const sorted = sortByDependencies([c, b, a]);
|
|
184
|
-
const ids = sorted.map(p => p.manifest.id);
|
|
189
|
+
const ids = sorted.map((p) => p.manifest.id);
|
|
185
190
|
|
|
186
191
|
expect(ids.indexOf('a')).toBeLessThan(ids.indexOf('b'));
|
|
187
192
|
expect(ids.indexOf('b')).toBeLessThan(ids.indexOf('c'));
|
|
@@ -73,14 +73,16 @@ describe('PluginRegistry — colocated', () => {
|
|
|
73
73
|
it('builds static facades from manifest when no index.js exists', async () => {
|
|
74
74
|
const loaded = makeLoaded({
|
|
75
75
|
manifest: makeManifest({
|
|
76
|
-
facades: [
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
facades: [
|
|
77
|
+
{
|
|
78
|
+
name: 'my_facade',
|
|
79
|
+
description: 'Test facade',
|
|
80
|
+
ops: [
|
|
81
|
+
{ name: 'do_thing', description: 'Does a thing', auth: 'read' },
|
|
82
|
+
{ name: 'admin_thing', description: 'Admin action', auth: 'admin' },
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
],
|
|
84
86
|
}),
|
|
85
87
|
});
|
|
86
88
|
|
|
@@ -98,11 +100,13 @@ describe('PluginRegistry — colocated', () => {
|
|
|
98
100
|
it('static facade ops return error message when called', async () => {
|
|
99
101
|
const loaded = makeLoaded({
|
|
100
102
|
manifest: makeManifest({
|
|
101
|
-
facades: [
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
facades: [
|
|
104
|
+
{
|
|
105
|
+
name: 'f',
|
|
106
|
+
description: '',
|
|
107
|
+
ops: [{ name: 'op1', description: '', auth: 'read' }],
|
|
108
|
+
},
|
|
109
|
+
],
|
|
106
110
|
}),
|
|
107
111
|
});
|
|
108
112
|
|
|
@@ -126,9 +130,9 @@ describe('PluginRegistry — colocated', () => {
|
|
|
126
130
|
});
|
|
127
131
|
|
|
128
132
|
it('throws for unregistered plugin', async () => {
|
|
129
|
-
await expect(
|
|
130
|
-
|
|
131
|
-
)
|
|
133
|
+
await expect(registry.activate('ghost', makeContext(makeLoaded()))).rejects.toThrow(
|
|
134
|
+
'not registered',
|
|
135
|
+
);
|
|
132
136
|
});
|
|
133
137
|
|
|
134
138
|
it('sets error status when index.js fails to load', async () => {
|
|
@@ -152,11 +156,13 @@ describe('PluginRegistry — colocated', () => {
|
|
|
152
156
|
it('deactivates an active plugin and clears facades', async () => {
|
|
153
157
|
const loaded = makeLoaded({
|
|
154
158
|
manifest: makeManifest({
|
|
155
|
-
facades: [
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
facades: [
|
|
160
|
+
{
|
|
161
|
+
name: 'f',
|
|
162
|
+
description: '',
|
|
163
|
+
ops: [{ name: 'op', description: '', auth: 'read' }],
|
|
164
|
+
},
|
|
165
|
+
],
|
|
160
166
|
}),
|
|
161
167
|
});
|
|
162
168
|
|
|
@@ -203,11 +209,13 @@ describe('PluginRegistry — colocated', () => {
|
|
|
203
209
|
const active = makeLoaded({
|
|
204
210
|
manifest: makeManifest({
|
|
205
211
|
id: 'active-one',
|
|
206
|
-
facades: [
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
212
|
+
facades: [
|
|
213
|
+
{
|
|
214
|
+
name: 'af',
|
|
215
|
+
description: '',
|
|
216
|
+
ops: [{ name: 'aop', description: '', auth: 'read' }],
|
|
217
|
+
},
|
|
218
|
+
],
|
|
211
219
|
}),
|
|
212
220
|
});
|
|
213
221
|
const inactive = makeLoaded({ manifest: makeManifest({ id: 'inactive-one' }) });
|
|
@@ -227,10 +235,14 @@ describe('PluginRegistry — colocated', () => {
|
|
|
227
235
|
id: 'multi',
|
|
228
236
|
facades: [
|
|
229
237
|
{ name: 'f1', description: '', ops: [{ name: 'a', description: '', auth: 'read' }] },
|
|
230
|
-
{
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
238
|
+
{
|
|
239
|
+
name: 'f2',
|
|
240
|
+
description: '',
|
|
241
|
+
ops: [
|
|
242
|
+
{ name: 'b', description: '', auth: 'write' },
|
|
243
|
+
{ name: 'c', description: '', auth: 'admin' },
|
|
244
|
+
],
|
|
245
|
+
},
|
|
234
246
|
],
|
|
235
247
|
}),
|
|
236
248
|
});
|
|
@@ -240,7 +252,7 @@ describe('PluginRegistry — colocated', () => {
|
|
|
240
252
|
|
|
241
253
|
const ops = registry.getActiveOps();
|
|
242
254
|
expect(ops).toHaveLength(3);
|
|
243
|
-
expect(ops.map(o => o.name)).toEqual(['a', 'b', 'c']);
|
|
255
|
+
expect(ops.map((o) => o.name)).toEqual(['a', 'b', 'c']);
|
|
244
256
|
});
|
|
245
257
|
|
|
246
258
|
it('returns empty when no active plugins', () => {
|
|
@@ -265,8 +277,8 @@ describe('PluginRegistry — colocated', () => {
|
|
|
265
277
|
|
|
266
278
|
const list = registry.list();
|
|
267
279
|
expect(list).toHaveLength(2);
|
|
268
|
-
expect(list.find(p => p.id === 'a')!.status).toBe('active');
|
|
269
|
-
expect(list.find(p => p.id === 'b')!.status).toBe('registered');
|
|
280
|
+
expect(list.find((p) => p.id === 'a')!.status).toBe('active');
|
|
281
|
+
expect(list.find((p) => p.id === 'b')!.status).toBe('registered');
|
|
270
282
|
});
|
|
271
283
|
});
|
|
272
284
|
});
|
|
@@ -33,9 +33,7 @@ function createMockProvider(): PersistenceProvider {
|
|
|
33
33
|
// Check for duplicate
|
|
34
34
|
const existing = store.project_links.find(
|
|
35
35
|
(r) =>
|
|
36
|
-
r.source_project_id === p[0] &&
|
|
37
|
-
r.target_project_id === p[1] &&
|
|
38
|
-
r.link_type === p[2],
|
|
36
|
+
r.source_project_id === p[0] && r.target_project_id === p[1] && r.link_type === p[2],
|
|
39
37
|
);
|
|
40
38
|
if (existing) return { changes: 0, lastInsertRowid: existing.id as number };
|
|
41
39
|
autoIncrementId++;
|
|
@@ -97,7 +95,11 @@ function createMockProvider(): PersistenceProvider {
|
|
|
97
95
|
return { changes: before - store.project_rules.length, lastInsertRowid: 0 };
|
|
98
96
|
}
|
|
99
97
|
|
|
100
|
-
if (
|
|
98
|
+
if (
|
|
99
|
+
sql.startsWith(
|
|
100
|
+
'DELETE FROM project_links WHERE source_project_id = ? AND target_project_id = ? AND link_type',
|
|
101
|
+
)
|
|
102
|
+
) {
|
|
101
103
|
const before = store.project_links.length;
|
|
102
104
|
store.project_links = store.project_links.filter(
|
|
103
105
|
(r) =>
|
|
@@ -106,16 +108,23 @@ function createMockProvider(): PersistenceProvider {
|
|
|
106
108
|
return { changes: before - store.project_links.length, lastInsertRowid: 0 };
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
if (
|
|
111
|
+
if (
|
|
112
|
+
sql.startsWith(
|
|
113
|
+
'DELETE FROM project_links WHERE source_project_id = ? AND target_project_id = ?',
|
|
114
|
+
)
|
|
115
|
+
) {
|
|
110
116
|
const before = store.project_links.length;
|
|
111
117
|
store.project_links = store.project_links.filter(
|
|
112
|
-
(r) =>
|
|
113
|
-
!(r.source_project_id === p[0] && r.target_project_id === p[1]),
|
|
118
|
+
(r) => !(r.source_project_id === p[0] && r.target_project_id === p[1]),
|
|
114
119
|
);
|
|
115
120
|
return { changes: before - store.project_links.length, lastInsertRowid: 0 };
|
|
116
121
|
}
|
|
117
122
|
|
|
118
|
-
if (
|
|
123
|
+
if (
|
|
124
|
+
sql.startsWith(
|
|
125
|
+
'DELETE FROM project_links WHERE source_project_id = ? OR target_project_id = ?',
|
|
126
|
+
)
|
|
127
|
+
) {
|
|
119
128
|
const before = store.project_links.length;
|
|
120
129
|
store.project_links = store.project_links.filter(
|
|
121
130
|
(r) => r.source_project_id !== p[0] && r.target_project_id !== p[1],
|
|
@@ -141,12 +150,14 @@ function createMockProvider(): PersistenceProvider {
|
|
|
141
150
|
if (sql.includes('FROM registered_projects WHERE path')) {
|
|
142
151
|
return store.registered_projects.find((r) => r.path === p[0]) as T | undefined;
|
|
143
152
|
}
|
|
144
|
-
if (
|
|
153
|
+
if (
|
|
154
|
+
sql.includes(
|
|
155
|
+
'FROM project_links WHERE source_project_id = ? AND target_project_id = ? AND link_type',
|
|
156
|
+
)
|
|
157
|
+
) {
|
|
145
158
|
return store.project_links.find(
|
|
146
159
|
(r) =>
|
|
147
|
-
r.source_project_id === p[0] &&
|
|
148
|
-
r.target_project_id === p[1] &&
|
|
149
|
-
r.link_type === p[2],
|
|
160
|
+
r.source_project_id === p[0] && r.target_project_id === p[1] && r.link_type === p[2],
|
|
150
161
|
) as T | undefined;
|
|
151
162
|
}
|
|
152
163
|
|
|
@@ -8,7 +8,10 @@ describe('TemplateManager', () => {
|
|
|
8
8
|
let tempDir: string;
|
|
9
9
|
|
|
10
10
|
beforeEach(() => {
|
|
11
|
-
tempDir = join(
|
|
11
|
+
tempDir = join(
|
|
12
|
+
tmpdir(),
|
|
13
|
+
`tmpl-mgr-colocated-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
14
|
+
);
|
|
12
15
|
mkdirSync(tempDir, { recursive: true });
|
|
13
16
|
});
|
|
14
17
|
|
|
@@ -57,7 +57,11 @@ function createMockProvider(): PersistenceProvider {
|
|
|
57
57
|
row.completed_at = new Date().toISOString();
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
if (
|
|
60
|
+
if (
|
|
61
|
+
sql.includes('UPDATE') &&
|
|
62
|
+
sql.includes("status = 'pending'") &&
|
|
63
|
+
sql.includes('retry_count')
|
|
64
|
+
) {
|
|
61
65
|
const id = p[0] as string;
|
|
62
66
|
const row = rows.get(id);
|
|
63
67
|
if (row) {
|
|
@@ -144,15 +148,7 @@ describe('JobQueue', () => {
|
|
|
144
148
|
queue.enqueue('groom');
|
|
145
149
|
expect(provider.run).toHaveBeenCalledWith(
|
|
146
150
|
expect.stringContaining('INSERT INTO job_queue'),
|
|
147
|
-
expect.arrayContaining([
|
|
148
|
-
expect.any(String),
|
|
149
|
-
'groom',
|
|
150
|
-
null,
|
|
151
|
-
'{}',
|
|
152
|
-
'[]',
|
|
153
|
-
null,
|
|
154
|
-
3,
|
|
155
|
-
]),
|
|
151
|
+
expect.arrayContaining([expect.any(String), 'groom', null, '{}', '[]', null, 3]),
|
|
156
152
|
);
|
|
157
153
|
});
|
|
158
154
|
|
|
@@ -219,10 +215,10 @@ describe('JobQueue', () => {
|
|
|
219
215
|
const id = queue.enqueue('groom');
|
|
220
216
|
queue.dequeue();
|
|
221
217
|
queue.complete(id);
|
|
222
|
-
expect(provider.run).toHaveBeenCalledWith(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
);
|
|
218
|
+
expect(provider.run).toHaveBeenCalledWith(expect.stringContaining("status = 'completed'"), [
|
|
219
|
+
null,
|
|
220
|
+
id,
|
|
221
|
+
]);
|
|
226
222
|
});
|
|
227
223
|
});
|
|
228
224
|
|
|
@@ -67,9 +67,7 @@ function createMockRuntime(): AgentRuntime {
|
|
|
67
67
|
overall: 'healthy',
|
|
68
68
|
subsystems: { vault: { status: 'healthy' }, brain: { status: 'healthy' } },
|
|
69
69
|
})),
|
|
70
|
-
get: vi.fn((name: string) =>
|
|
71
|
-
name === 'vault' ? { status: 'healthy', failures: 0 } : null,
|
|
72
|
-
),
|
|
70
|
+
get: vi.fn((name: string) => (name === 'vault' ? { status: 'healthy', failures: 0 } : null)),
|
|
73
71
|
},
|
|
74
72
|
flags: {
|
|
75
73
|
getAll: vi.fn(() => ({
|
|
@@ -396,10 +394,7 @@ describe('createAdminExtraOps', () => {
|
|
|
396
394
|
|
|
397
395
|
describe('admin_hot_reload', () => {
|
|
398
396
|
it('reloads brain, vault FTS, and templates', async () => {
|
|
399
|
-
const result = (await findOp(ops, 'admin_hot_reload').handler({})) as Record<
|
|
400
|
-
string,
|
|
401
|
-
unknown
|
|
402
|
-
>;
|
|
397
|
+
const result = (await findOp(ops, 'admin_hot_reload').handler({})) as Record<string, unknown>;
|
|
403
398
|
expect((result.reloaded as string[]).length).toBe(3);
|
|
404
399
|
expect(result.brainTerms).toBe(500);
|
|
405
400
|
expect(result.templateCount).toBe(2);
|
|
@@ -409,10 +404,7 @@ describe('createAdminExtraOps', () => {
|
|
|
409
404
|
vi.mocked(runtime.vault.rebuildFtsIndex).mockImplementation(() => {
|
|
410
405
|
throw new Error('fail');
|
|
411
406
|
});
|
|
412
|
-
const result = (await findOp(ops, 'admin_hot_reload').handler({})) as Record<
|
|
413
|
-
string,
|
|
414
|
-
unknown
|
|
415
|
-
>;
|
|
407
|
+
const result = (await findOp(ops, 'admin_hot_reload').handler({})) as Record<string, unknown>;
|
|
416
408
|
expect(result.reloaded).not.toContain('vault_fts');
|
|
417
409
|
});
|
|
418
410
|
});
|
|
@@ -455,10 +447,7 @@ describe('createAdminExtraOps', () => {
|
|
|
455
447
|
|
|
456
448
|
describe('admin_list_flags', () => {
|
|
457
449
|
it('returns all feature flags', async () => {
|
|
458
|
-
const result = (await findOp(ops, 'admin_list_flags').handler({})) as Record<
|
|
459
|
-
string,
|
|
460
|
-
unknown
|
|
461
|
-
>;
|
|
450
|
+
const result = (await findOp(ops, 'admin_list_flags').handler({})) as Record<string, unknown>;
|
|
462
451
|
expect(result).toHaveProperty('auth-enforcement');
|
|
463
452
|
});
|
|
464
453
|
});
|
|
@@ -516,10 +505,7 @@ describe('createAdminExtraOps', () => {
|
|
|
516
505
|
|
|
517
506
|
describe('admin_setup_run', () => {
|
|
518
507
|
it('runs setup actions', async () => {
|
|
519
|
-
const result = (await findOp(ops, 'admin_setup_run').handler({})) as Record<
|
|
520
|
-
string,
|
|
521
|
-
unknown
|
|
522
|
-
>;
|
|
508
|
+
const result = (await findOp(ops, 'admin_setup_run').handler({})) as Record<string, unknown>;
|
|
523
509
|
expect(result.setup).toBe(true);
|
|
524
510
|
expect((result.actions as string[]).length).toBeGreaterThan(0);
|
|
525
511
|
});
|
|
@@ -135,9 +135,7 @@ describe('createAdminOps', () => {
|
|
|
135
135
|
|
|
136
136
|
it('returns verbose format when verbose=true', async () => {
|
|
137
137
|
const op = findOp(ops, 'admin_tool_list');
|
|
138
|
-
const allOps = [
|
|
139
|
-
{ name: 'admin_health', description: 'Health check', auth: 'read' },
|
|
140
|
-
];
|
|
138
|
+
const allOps = [{ name: 'admin_health', description: 'Health check', auth: 'read' }];
|
|
141
139
|
const result = (await op.handler({
|
|
142
140
|
_allOps: allOps,
|
|
143
141
|
verbose: true,
|
|
@@ -42,9 +42,7 @@ vi.mock('./claude-md-helpers.js', () => ({
|
|
|
42
42
|
}));
|
|
43
43
|
|
|
44
44
|
vi.mock('../skills/sync-skills.js', () => ({
|
|
45
|
-
discoverSkills: vi.fn(() => [
|
|
46
|
-
{ name: 'skill-1', path: '/mock/skills/skill-1' },
|
|
47
|
-
]),
|
|
45
|
+
discoverSkills: vi.fn(() => [{ name: 'skill-1', path: '/mock/skills/skill-1' }]),
|
|
48
46
|
syncSkillsToClaudeCode: vi.fn(() => ({
|
|
49
47
|
installed: ['skill-1'],
|
|
50
48
|
updated: [],
|
|
@@ -158,7 +156,8 @@ describe('createAdminSetupOps', () => {
|
|
|
158
156
|
});
|
|
159
157
|
|
|
160
158
|
it('updates existing agent sections', async () => {
|
|
161
|
-
mockFs['/some/project/CLAUDE.md'] =
|
|
159
|
+
mockFs['/some/project/CLAUDE.md'] =
|
|
160
|
+
'# Project\n<!-- agent:test-agent -->\nOld\n<!-- /agent:test-agent -->';
|
|
162
161
|
const { hasSections } = await import('./claude-md-helpers.js');
|
|
163
162
|
vi.mocked(hasSections).mockReturnValueOnce(true);
|
|
164
163
|
const result = (await findOp(ops, 'admin_inject_claude_md').handler({
|