@soleri/core 9.15.0 → 9.16.7
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/deliver.flow.yaml +11 -0
- package/data/flows/design.flow.yaml +4 -14
- package/data/flows/enhance.flow.yaml +10 -0
- package/data/flows/explore.flow.yaml +16 -0
- package/data/flows/fix.flow.yaml +1 -1
- package/data/flows/review.flow.yaml +13 -4
- package/dist/capabilities/chain-mapping.d.ts.map +1 -1
- package/dist/capabilities/chain-mapping.js +5 -4
- package/dist/capabilities/chain-mapping.js.map +1 -1
- package/dist/capabilities/registry.d.ts +6 -0
- package/dist/capabilities/registry.d.ts.map +1 -1
- package/dist/capabilities/registry.js +3 -2
- package/dist/capabilities/registry.js.map +1 -1
- package/dist/context/context-engine.js +1 -1
- package/dist/context/context-engine.js.map +1 -1
- package/dist/engine/core-ops.d.ts.map +1 -1
- package/dist/engine/core-ops.js +38 -1
- package/dist/engine/core-ops.js.map +1 -1
- package/dist/flows/epilogue.d.ts +5 -1
- package/dist/flows/epilogue.d.ts.map +1 -1
- package/dist/flows/epilogue.js +11 -3
- package/dist/flows/epilogue.js.map +1 -1
- package/dist/flows/executor.d.ts.map +1 -1
- package/dist/flows/executor.js +13 -5
- package/dist/flows/executor.js.map +1 -1
- package/dist/flows/index.d.ts +1 -2
- package/dist/flows/index.d.ts.map +1 -1
- package/dist/flows/index.js +1 -0
- package/dist/flows/index.js.map +1 -1
- package/dist/flows/plan-builder.d.ts +17 -1
- package/dist/flows/plan-builder.d.ts.map +1 -1
- package/dist/flows/plan-builder.js +67 -6
- package/dist/flows/plan-builder.js.map +1 -1
- package/dist/flows/probes.d.ts +1 -1
- package/dist/flows/probes.d.ts.map +1 -1
- package/dist/flows/probes.js +15 -3
- package/dist/flows/probes.js.map +1 -1
- package/dist/flows/types.d.ts +31 -4
- package/dist/flows/types.d.ts.map +1 -1
- package/dist/flows/types.js +6 -1
- package/dist/flows/types.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/packs/pack-installer.d.ts.map +1 -1
- package/dist/packs/pack-installer.js +28 -2
- package/dist/packs/pack-installer.js.map +1 -1
- package/dist/planning/planner-types.d.ts +2 -0
- package/dist/planning/planner-types.d.ts.map +1 -1
- package/dist/planning/planner.d.ts +1 -0
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +7 -0
- package/dist/planning/planner.js.map +1 -1
- package/dist/playbooks/playbook-executor.d.ts +10 -1
- package/dist/playbooks/playbook-executor.d.ts.map +1 -1
- package/dist/playbooks/playbook-executor.js +8 -2
- package/dist/playbooks/playbook-executor.js.map +1 -1
- package/dist/playbooks/playbook-types.d.ts +8 -0
- package/dist/playbooks/playbook-types.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +30 -0
- package/dist/runtime/admin-extra-ops.js.map +1 -1
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +60 -21
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/admin-setup-ops.d.ts +11 -0
- package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
- package/dist/runtime/admin-setup-ops.js +87 -17
- package/dist/runtime/admin-setup-ops.js.map +1 -1
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +38 -12
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
- package/dist/runtime/facades/brain-facade.js +16 -4
- package/dist/runtime/facades/brain-facade.js.map +1 -1
- package/dist/runtime/facades/context-facade.d.ts.map +1 -1
- package/dist/runtime/facades/context-facade.js +9 -3
- package/dist/runtime/facades/context-facade.js.map +1 -1
- package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
- package/dist/runtime/facades/memory-facade.js +20 -7
- package/dist/runtime/facades/memory-facade.js.map +1 -1
- package/dist/runtime/facades/orchestrate-facade.d.ts.map +1 -1
- package/dist/runtime/facades/orchestrate-facade.js +12 -0
- package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
- package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
- package/dist/runtime/facades/plan-facade.js +113 -4
- package/dist/runtime/facades/plan-facade.js.map +1 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +24 -3
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts +21 -0
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +132 -38
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/schema-helpers.d.ts.map +1 -1
- package/dist/runtime/schema-helpers.js +4 -0
- package/dist/runtime/schema-helpers.js.map +1 -1
- package/dist/runtime/vault-linking-ops.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.js +16 -3
- package/dist/runtime/vault-linking-ops.js.map +1 -1
- package/dist/scheduler/cron-validator.d.ts +15 -0
- package/dist/scheduler/cron-validator.d.ts.map +1 -0
- package/dist/scheduler/cron-validator.js +93 -0
- package/dist/scheduler/cron-validator.js.map +1 -0
- package/dist/scheduler/platform-linux.d.ts +14 -0
- package/dist/scheduler/platform-linux.d.ts.map +1 -0
- package/dist/scheduler/platform-linux.js +107 -0
- package/dist/scheduler/platform-linux.js.map +1 -0
- package/dist/scheduler/platform-macos.d.ts +15 -0
- package/dist/scheduler/platform-macos.d.ts.map +1 -0
- package/dist/scheduler/platform-macos.js +131 -0
- package/dist/scheduler/platform-macos.js.map +1 -0
- package/dist/scheduler/scheduler-ops.d.ts +14 -0
- package/dist/scheduler/scheduler-ops.d.ts.map +1 -0
- package/dist/scheduler/scheduler-ops.js +77 -0
- package/dist/scheduler/scheduler-ops.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +55 -0
- package/dist/scheduler/scheduler.d.ts.map +1 -0
- package/dist/scheduler/scheduler.js +144 -0
- package/dist/scheduler/scheduler.js.map +1 -0
- package/dist/scheduler/types.d.ts +48 -0
- package/dist/scheduler/types.d.ts.map +1 -0
- package/dist/scheduler/types.js +6 -0
- package/dist/scheduler/types.js.map +1 -0
- package/dist/skills/sync-skills.d.ts +11 -0
- package/dist/skills/sync-skills.d.ts.map +1 -1
- package/dist/skills/sync-skills.js +132 -38
- package/dist/skills/sync-skills.js.map +1 -1
- package/dist/utils/worktree-reaper.d.ts +38 -0
- package/dist/utils/worktree-reaper.d.ts.map +1 -0
- package/dist/utils/worktree-reaper.js +85 -0
- package/dist/utils/worktree-reaper.js.map +1 -0
- package/dist/vault/scope-detector.d.ts.map +1 -1
- package/dist/vault/scope-detector.js +37 -4
- package/dist/vault/scope-detector.js.map +1 -1
- package/dist/vault/vault-entries.d.ts.map +1 -1
- package/dist/vault/vault-entries.js +3 -1
- package/dist/vault/vault-entries.js.map +1 -1
- package/package.json +1 -1
- package/src/agency/agency-manager.test.ts +4 -4
- package/src/agency/default-rules.test.ts +0 -13
- package/src/brain/brain-intelligence.test.ts +0 -5
- package/src/brain/second-brain-features.test.ts +2 -14
- package/src/capabilities/chain-mapping.test.ts +1 -6
- package/src/capabilities/chain-mapping.ts +6 -4
- package/src/capabilities/registry.test.ts +1 -1
- package/src/capabilities/registry.ts +9 -2
- package/src/chat/agent-loop.test.ts +1 -1
- package/src/chat/chat-enhanced.test.ts +0 -8
- package/src/claudemd/compose.test.ts +0 -5
- package/src/context/context-engine.test.ts +0 -1
- package/src/context/context-engine.ts +1 -1
- package/src/control/intent-router.test.ts +2 -2
- package/src/curator/tag-manager.test.ts +0 -4
- package/src/domain-packs/types.test.ts +0 -5
- package/src/dream/dream.test.ts +0 -7
- package/src/enforcement/registry.test.ts +2 -2
- package/src/engine/core-ops.test.ts +4 -22
- package/src/engine/core-ops.ts +36 -1
- package/src/engine/module-manifest.test.ts +1 -31
- package/src/engine/register-engine.test.ts +3 -33
- package/src/errors/retry.test.ts +3 -1
- package/src/flows/chain-runner.test.ts +0 -6
- package/src/flows/context-router.test.ts +3 -3
- package/src/flows/epilogue.test.ts +40 -2
- package/src/flows/epilogue.ts +11 -2
- package/src/flows/executor.test.ts +48 -2
- package/src/flows/executor.ts +15 -5
- package/src/flows/index.ts +1 -3
- package/src/flows/plan-builder.test.ts +201 -0
- package/src/flows/plan-builder.ts +81 -5
- package/src/flows/probes.ts +17 -3
- package/src/flows/types.ts +31 -2
- package/src/health/health-registry.test.ts +3 -1
- package/src/index.ts +17 -0
- package/src/intake/dedup-gate.test.ts +2 -6
- package/src/intake/text-ingester.test.ts +3 -4
- package/src/llm/llm-client.test.ts +1 -1
- package/src/llm/utils.test.ts +1 -1
- package/src/migrations/migration-runner.test.ts +0 -1
- package/src/operator/operator-context-store.test.ts +0 -13
- package/src/operator/operator-profile.test.ts +2 -20
- package/src/packs/pack-installer.ts +28 -2
- package/src/packs/pack-system.test.ts +2 -2
- package/src/persona/defaults.test.ts +19 -19
- package/src/planning/gap-passes.test.ts +0 -46
- package/src/planning/gap-patterns.test.ts +0 -42
- package/src/planning/goal-ancestry.test.ts +3 -1
- package/src/planning/plan-lifecycle.test.ts +15 -7
- package/src/planning/planner-types.ts +2 -0
- package/src/planning/planner.ts +8 -0
- package/src/planning/reconciliation-engine.test.ts +3 -10
- package/src/planning/task-complexity-assessor.test.ts +0 -5
- package/src/planning/task-verifier.test.ts +3 -1
- package/src/playbooks/generic/generic-playbooks.test.ts +0 -28
- package/src/playbooks/index.test.ts +0 -55
- package/src/playbooks/playbook-executor.test.ts +76 -0
- package/src/playbooks/playbook-executor.ts +24 -3
- package/src/playbooks/playbook-types.ts +8 -0
- package/src/plugins/plugin-registry.test.ts +6 -2
- package/src/project/project-registry.test.ts +2 -0
- package/src/queue/async-infrastructure.test.ts +6 -4
- package/src/queue/job-queue.test.ts +13 -7
- package/src/runtime/admin-extra-ops.test.ts +35 -30
- package/src/runtime/admin-extra-ops.ts +30 -0
- package/src/runtime/admin-ops.test.ts +0 -4
- package/src/runtime/admin-ops.ts +63 -21
- package/src/runtime/admin-setup-ops.test.ts +185 -13
- package/src/runtime/admin-setup-ops.ts +86 -16
- package/src/runtime/archive-ops.test.ts +0 -28
- package/src/runtime/branching-ops.test.ts +0 -17
- package/src/runtime/capture-ops.test.ts +41 -16
- package/src/runtime/capture-ops.ts +78 -46
- package/src/runtime/chain-ops.test.ts +0 -21
- package/src/runtime/facades/admin-facade.test.ts +0 -34
- package/src/runtime/facades/agency-facade.test.ts +0 -39
- package/src/runtime/facades/archive-facade.test.ts +0 -43
- package/src/runtime/facades/brain-facade.test.ts +8 -99
- package/src/runtime/facades/brain-facade.ts +29 -12
- package/src/runtime/facades/branching-facade.test.ts +30 -17
- package/src/runtime/facades/chat-facade.test.ts +0 -91
- package/src/runtime/facades/chat-service-ops.test.ts +0 -24
- package/src/runtime/facades/chat-session-ops.test.ts +0 -12
- package/src/runtime/facades/chat-transport-ops.test.ts +0 -23
- package/src/runtime/facades/context-facade.test.ts +0 -17
- package/src/runtime/facades/context-facade.ts +11 -4
- package/src/runtime/facades/control-facade.test.ts +0 -30
- package/src/runtime/facades/curator-facade.test.ts +0 -33
- package/src/runtime/facades/intake-facade.test.ts +0 -33
- package/src/runtime/facades/links-facade.test.ts +0 -37
- package/src/runtime/facades/loop-facade.test.ts +0 -26
- package/src/runtime/facades/memory-facade.test.ts +0 -18
- package/src/runtime/facades/memory-facade.ts +27 -11
- package/src/runtime/facades/operator-facade.test.ts +0 -31
- package/src/runtime/facades/orchestrate-facade.test.ts +0 -21
- package/src/runtime/facades/orchestrate-facade.ts +12 -0
- package/src/runtime/facades/plan-facade.test.ts +7 -32
- package/src/runtime/facades/plan-facade.ts +137 -4
- package/src/runtime/facades/review-facade.test.ts +1 -49
- package/src/runtime/facades/sync-facade.test.ts +24 -41
- package/src/runtime/facades/tier-facade.test.ts +30 -22
- package/src/runtime/facades/vault-facade.test.ts +0 -41
- package/src/runtime/facades/vault-facade.ts +26 -3
- package/src/runtime/grading-ops.test.ts +0 -27
- package/src/runtime/intake-ops.test.ts +0 -19
- package/src/runtime/loop-ops.test.ts +0 -48
- package/src/runtime/memory-cross-project-ops.test.ts +0 -14
- package/src/runtime/memory-extra-ops.test.ts +4 -8
- package/src/runtime/orchestrate-ops.test.ts +238 -19
- package/src/runtime/orchestrate-ops.ts +166 -41
- package/src/runtime/pack-ops.test.ts +0 -26
- package/src/runtime/planning-extra-ops.test.ts +2 -14
- package/src/runtime/playbook-ops-execution.test.ts +9 -20
- package/src/runtime/playbook-ops.test.ts +4 -67
- package/src/runtime/review-ops.test.ts +0 -15
- package/src/runtime/schema-helpers.ts +4 -0
- package/src/runtime/sync-ops.test.ts +0 -18
- package/src/runtime/tier-ops.test.ts +0 -21
- package/src/runtime/vault-extra-ops.test.ts +0 -12
- package/src/runtime/vault-linking-ops.test.ts +0 -4
- package/src/runtime/vault-linking-ops.ts +26 -8
- package/src/runtime/vault-sharing-ops.test.ts +0 -9
- package/src/scheduler/cron-validator.ts +101 -0
- package/src/scheduler/platform-linux.ts +122 -0
- package/src/scheduler/platform-macos.ts +150 -0
- package/src/scheduler/scheduler-ops.ts +77 -0
- package/src/scheduler/scheduler.test.ts +247 -0
- package/src/scheduler/scheduler.ts +174 -0
- package/src/scheduler/types.ts +52 -0
- package/src/skills/__tests__/sync-skills.test.ts +6 -17
- package/src/skills/global-claude-md.test.ts +113 -0
- package/src/skills/sync-skills.ts +143 -35
- package/src/skills/validate-skills.test.ts +12 -11
- package/src/telemetry/telemetry.test.ts +1 -0
- package/src/transport/http-server.test.ts +3 -0
- package/src/transport/session-manager.test.ts +3 -1
- package/src/transport/token-auth.test.ts +6 -9
- package/src/transport/ws-server.test.ts +10 -2
- package/src/utils/worktree-reaper.ts +113 -0
- package/src/vault/__tests__/vault-characterization.test.ts +0 -108
- package/src/vault/linking.test.ts +0 -2
- package/src/vault/playbook.test.ts +4 -1
- package/src/vault/scope-detector.test.ts +3 -1
- package/src/vault/scope-detector.ts +42 -4
- package/src/vault/vault-connect.test.ts +1 -1
- package/src/vault/vault-entries.ts +3 -1
- package/src/vault/vault.test.ts +23 -8
|
@@ -121,30 +121,6 @@ describe('chat-service-ops', () => {
|
|
|
121
121
|
ops = createChatServiceOps(state);
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
-
it('exports 18 service ops', () => {
|
|
125
|
-
const names = ops.map((o) => o.name);
|
|
126
|
-
expect(names).toEqual([
|
|
127
|
-
'chat_cancel_create',
|
|
128
|
-
'chat_cancel_stop',
|
|
129
|
-
'chat_cancel_status',
|
|
130
|
-
'chat_update_init',
|
|
131
|
-
'chat_update_request',
|
|
132
|
-
'chat_update_confirm',
|
|
133
|
-
'chat_file_detect_intent',
|
|
134
|
-
'chat_file_build_content',
|
|
135
|
-
'chat_file_cleanup',
|
|
136
|
-
'chat_notify_init',
|
|
137
|
-
'chat_notify_start',
|
|
138
|
-
'chat_notify_stop',
|
|
139
|
-
'chat_notify_poll',
|
|
140
|
-
'chat_notify_status',
|
|
141
|
-
'chat_browser_init',
|
|
142
|
-
'chat_browser_acquire',
|
|
143
|
-
'chat_browser_release',
|
|
144
|
-
'chat_browser_status',
|
|
145
|
-
]);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
124
|
// ─── Task Cancellation ─────────────────────────────────────────
|
|
149
125
|
|
|
150
126
|
describe('chat_cancel_create', () => {
|
|
@@ -68,18 +68,6 @@ describe('chat-session-ops', () => {
|
|
|
68
68
|
ops = createChatSessionOps(state);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
it('exports 6 session ops', () => {
|
|
72
|
-
const names = ops.map((o) => o.name);
|
|
73
|
-
expect(names).toEqual([
|
|
74
|
-
'chat_session_init',
|
|
75
|
-
'chat_session_get',
|
|
76
|
-
'chat_session_append',
|
|
77
|
-
'chat_session_clear',
|
|
78
|
-
'chat_session_delete',
|
|
79
|
-
'chat_session_list',
|
|
80
|
-
]);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
71
|
describe('chat_session_init', () => {
|
|
84
72
|
it('initializes session manager and returns status', async () => {
|
|
85
73
|
const op = findOp(ops, 'chat_session_init');
|
|
@@ -111,29 +111,6 @@ describe('chat-transport-ops', () => {
|
|
|
111
111
|
ops = createChatTransportOps(state);
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
it('exports 17 transport ops', () => {
|
|
115
|
-
const names = ops.map((o) => o.name);
|
|
116
|
-
expect(names).toEqual([
|
|
117
|
-
'chat_chunk_response',
|
|
118
|
-
'chat_auth_init',
|
|
119
|
-
'chat_auth_check',
|
|
120
|
-
'chat_auth_authenticate',
|
|
121
|
-
'chat_auth_revoke',
|
|
122
|
-
'chat_auth_status',
|
|
123
|
-
'chat_bridge_init',
|
|
124
|
-
'chat_bridge_register',
|
|
125
|
-
'chat_bridge_list',
|
|
126
|
-
'chat_bridge_execute',
|
|
127
|
-
'chat_compress_output',
|
|
128
|
-
'chat_voice_transcribe',
|
|
129
|
-
'chat_voice_synthesize',
|
|
130
|
-
'chat_queue_init',
|
|
131
|
-
'chat_queue_inbox',
|
|
132
|
-
'chat_queue_reply',
|
|
133
|
-
'chat_queue_drain',
|
|
134
|
-
]);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
114
|
// ─── Chunking ──────────────────────────────────────────────────
|
|
138
115
|
|
|
139
116
|
describe('chat_chunk_response', () => {
|
|
@@ -51,23 +51,6 @@ describe('context-facade', () => {
|
|
|
51
51
|
ops = captureOps(createContextFacadeOps(makeRuntime(mockEngine)));
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
it('registers all 3 ops', () => {
|
|
55
|
-
expect(ops.size).toBe(3);
|
|
56
|
-
expect([...ops.keys()]).toEqual(
|
|
57
|
-
expect.arrayContaining([
|
|
58
|
-
'context_extract_entities',
|
|
59
|
-
'context_retrieve_knowledge',
|
|
60
|
-
'context_analyze',
|
|
61
|
-
]),
|
|
62
|
-
);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('has correct auth levels', () => {
|
|
66
|
-
expect(ops.get('context_extract_entities')!.auth).toBe('read');
|
|
67
|
-
expect(ops.get('context_retrieve_knowledge')!.auth).toBe('read');
|
|
68
|
-
expect(ops.get('context_analyze')!.auth).toBe('read');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
54
|
// ─── context_extract_entities ──────────────────────────────────
|
|
72
55
|
|
|
73
56
|
it('context_extract_entities calls engine with prompt', async () => {
|
|
@@ -15,11 +15,18 @@ export function createContextFacadeOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
15
15
|
description:
|
|
16
16
|
'Extract named entities from a prompt — files, functions, domains, actions, technologies, patterns.',
|
|
17
17
|
auth: 'read',
|
|
18
|
-
schema: z
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
schema: z
|
|
19
|
+
.object({
|
|
20
|
+
prompt: z.string().optional().describe('The user prompt to analyze.'),
|
|
21
|
+
text: z.string().optional().describe('Alias for prompt — use either field.'),
|
|
22
|
+
})
|
|
23
|
+
.refine((v) => v.prompt !== undefined || v.text !== undefined, {
|
|
24
|
+
message: 'Provide either "prompt" or "text"',
|
|
25
|
+
}),
|
|
21
26
|
handler: async (params) => {
|
|
22
|
-
|
|
27
|
+
const input =
|
|
28
|
+
(params.prompt as string | undefined) ?? (params.text as string | undefined) ?? '';
|
|
29
|
+
return contextEngine.extractEntities(input);
|
|
23
30
|
},
|
|
24
31
|
},
|
|
25
32
|
{
|
|
@@ -51,36 +51,6 @@ describe('createControlFacadeOps', () => {
|
|
|
51
51
|
ops = createControlFacadeOps(runtime);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
it('returns all expected ops', () => {
|
|
55
|
-
const names = ops.map((o) => o.name);
|
|
56
|
-
expect(names).toContain('get_identity');
|
|
57
|
-
expect(names).toContain('update_identity');
|
|
58
|
-
expect(names).toContain('add_guideline');
|
|
59
|
-
expect(names).toContain('remove_guideline');
|
|
60
|
-
expect(names).toContain('rollback_identity');
|
|
61
|
-
expect(names).toContain('route_intent');
|
|
62
|
-
expect(names).toContain('morph');
|
|
63
|
-
expect(names).toContain('get_behavior_rules');
|
|
64
|
-
expect(names).toContain('governance_policy');
|
|
65
|
-
expect(names).toContain('governance_proposals');
|
|
66
|
-
expect(names).toContain('governance_stats');
|
|
67
|
-
expect(names).toContain('governance_expire');
|
|
68
|
-
expect(names).toContain('governance_dashboard');
|
|
69
|
-
expect(names).toContain('routing_feedback');
|
|
70
|
-
expect(names).toContain('routing_accuracy');
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('assigns correct auth levels', () => {
|
|
74
|
-
expect(findOp(ops, 'get_identity').auth).toBe('read');
|
|
75
|
-
expect(findOp(ops, 'update_identity').auth).toBe('write');
|
|
76
|
-
expect(findOp(ops, 'route_intent').auth).toBe('read');
|
|
77
|
-
expect(findOp(ops, 'morph').auth).toBe('write');
|
|
78
|
-
expect(findOp(ops, 'governance_policy').auth).toBe('write');
|
|
79
|
-
expect(findOp(ops, 'governance_stats').auth).toBe('read');
|
|
80
|
-
expect(findOp(ops, 'routing_feedback').auth).toBe('write');
|
|
81
|
-
expect(findOp(ops, 'routing_accuracy').auth).toBe('read');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
54
|
describe('get_identity', () => {
|
|
85
55
|
it('returns identity when found', async () => {
|
|
86
56
|
const identity = { agentId: 'test', name: 'Test Agent', version: 1 };
|
|
@@ -74,39 +74,6 @@ describe('createCuratorFacadeOps', () => {
|
|
|
74
74
|
ops = createCuratorFacadeOps(runtime);
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
it('returns all expected ops', () => {
|
|
78
|
-
const names = ops.map((o) => o.name);
|
|
79
|
-
expect(names).toContain('curator_status');
|
|
80
|
-
expect(names).toContain('curator_detect_duplicates');
|
|
81
|
-
expect(names).toContain('curator_contradictions');
|
|
82
|
-
expect(names).toContain('curator_resolve_contradiction');
|
|
83
|
-
expect(names).toContain('curator_groom');
|
|
84
|
-
expect(names).toContain('curator_groom_all');
|
|
85
|
-
expect(names).toContain('curator_consolidate');
|
|
86
|
-
expect(names).toContain('curator_health_audit');
|
|
87
|
-
// Extra ops
|
|
88
|
-
expect(names).toContain('curator_entry_history');
|
|
89
|
-
expect(names).toContain('curator_record_snapshot');
|
|
90
|
-
expect(names).toContain('curator_queue_stats');
|
|
91
|
-
expect(names).toContain('curator_enrich');
|
|
92
|
-
expect(names).toContain('curator_hybrid_contradictions');
|
|
93
|
-
expect(names).toContain('curator_pipeline_status');
|
|
94
|
-
expect(names).toContain('curator_enqueue_pipeline');
|
|
95
|
-
expect(names).toContain('curator_schedule_start');
|
|
96
|
-
expect(names).toContain('curator_schedule_stop');
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('assigns correct auth levels', () => {
|
|
100
|
-
expect(findOp(ops, 'curator_status').auth).toBe('read');
|
|
101
|
-
expect(findOp(ops, 'curator_detect_duplicates').auth).toBe('read');
|
|
102
|
-
expect(findOp(ops, 'curator_contradictions').auth).toBe('read');
|
|
103
|
-
expect(findOp(ops, 'curator_resolve_contradiction').auth).toBe('write');
|
|
104
|
-
expect(findOp(ops, 'curator_groom').auth).toBe('write');
|
|
105
|
-
expect(findOp(ops, 'curator_groom_all').auth).toBe('write');
|
|
106
|
-
expect(findOp(ops, 'curator_consolidate').auth).toBe('write');
|
|
107
|
-
expect(findOp(ops, 'curator_health_audit').auth).toBe('read');
|
|
108
|
-
});
|
|
109
|
-
|
|
110
77
|
describe('curator_status', () => {
|
|
111
78
|
it('returns curator status', async () => {
|
|
112
79
|
const result = await findOp(ops, 'curator_status').handler({});
|
|
@@ -50,39 +50,6 @@ describe('intake-facade', () => {
|
|
|
50
50
|
ops = captureOps(createIntakeFacadeOps(runtime));
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
// ─── Registration ─────────────────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
it('returns exactly 7 ops', () => {
|
|
56
|
-
expect(ops.size).toBe(7);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('includes all expected op names', () => {
|
|
60
|
-
const expected = [
|
|
61
|
-
'intake_ingest_book',
|
|
62
|
-
'intake_process',
|
|
63
|
-
'intake_status',
|
|
64
|
-
'intake_preview',
|
|
65
|
-
'ingest_url',
|
|
66
|
-
'ingest_text',
|
|
67
|
-
'ingest_batch',
|
|
68
|
-
];
|
|
69
|
-
for (const name of expected) {
|
|
70
|
-
expect(ops.has(name), `missing op: ${name}`).toBe(true);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// ─── Auth levels ─────────────────────────────────────────────────
|
|
75
|
-
|
|
76
|
-
it('has correct auth levels', () => {
|
|
77
|
-
expect(ops.get('intake_ingest_book')!.auth).toBe('write');
|
|
78
|
-
expect(ops.get('intake_process')!.auth).toBe('write');
|
|
79
|
-
expect(ops.get('intake_status')!.auth).toBe('read');
|
|
80
|
-
expect(ops.get('intake_preview')!.auth).toBe('read');
|
|
81
|
-
expect(ops.get('ingest_url')!.auth).toBe('write');
|
|
82
|
-
expect(ops.get('ingest_text')!.auth).toBe('write');
|
|
83
|
-
expect(ops.get('ingest_batch')!.auth).toBe('write');
|
|
84
|
-
});
|
|
85
|
-
|
|
86
53
|
// ─── Delegation ─────────────────────────────────────────────────
|
|
87
54
|
|
|
88
55
|
describe('intake_ingest_book', () => {
|
|
@@ -50,43 +50,6 @@ describe('links-facade', () => {
|
|
|
50
50
|
ops = captureOps(createLinksFacadeOps(runtime));
|
|
51
51
|
});
|
|
52
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
53
|
// ─── Handler delegation ───────────────────────────────────────────
|
|
91
54
|
|
|
92
55
|
describe('link_entries', () => {
|
|
@@ -87,32 +87,6 @@ describe('loop-facade', () => {
|
|
|
87
87
|
ops = captureOps(createLoopFacadeOps(makeRuntime(mockLoop)));
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
-
it('registers all 9 ops', () => {
|
|
91
|
-
expect(ops.size).toBe(9);
|
|
92
|
-
const names = [...ops.keys()];
|
|
93
|
-
expect(names).toContain('loop_start');
|
|
94
|
-
expect(names).toContain('loop_iterate');
|
|
95
|
-
expect(names).toContain('loop_iterate_gate');
|
|
96
|
-
expect(names).toContain('loop_status');
|
|
97
|
-
expect(names).toContain('loop_cancel');
|
|
98
|
-
expect(names).toContain('loop_history');
|
|
99
|
-
expect(names).toContain('loop_is_active');
|
|
100
|
-
expect(names).toContain('loop_complete');
|
|
101
|
-
expect(names).toContain('loop_anomaly_check');
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('has correct auth levels', () => {
|
|
105
|
-
expect(ops.get('loop_start')!.auth).toBe('write');
|
|
106
|
-
expect(ops.get('loop_iterate')!.auth).toBe('write');
|
|
107
|
-
expect(ops.get('loop_iterate_gate')!.auth).toBe('write');
|
|
108
|
-
expect(ops.get('loop_status')!.auth).toBe('read');
|
|
109
|
-
expect(ops.get('loop_cancel')!.auth).toBe('write');
|
|
110
|
-
expect(ops.get('loop_history')!.auth).toBe('read');
|
|
111
|
-
expect(ops.get('loop_is_active')!.auth).toBe('read');
|
|
112
|
-
expect(ops.get('loop_complete')!.auth).toBe('write');
|
|
113
|
-
expect(ops.get('loop_anomaly_check')!.auth).toBe('read');
|
|
114
|
-
});
|
|
115
|
-
|
|
116
90
|
// ─── loop_start ────────────────────────────────────────────────
|
|
117
91
|
|
|
118
92
|
it('loop_start creates a loop with defaults', async () => {
|
|
@@ -30,24 +30,6 @@ describe('memory-facade', () => {
|
|
|
30
30
|
vault.close();
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
it('registers base + extra + cross-project ops', () => {
|
|
34
|
-
// 4 base + 18 extra + 3 cross-project = 25
|
|
35
|
-
expect(ops.size).toBeGreaterThanOrEqual(25);
|
|
36
|
-
expect([...ops.keys()]).toContain('memory_search');
|
|
37
|
-
expect([...ops.keys()]).toContain('memory_capture');
|
|
38
|
-
expect([...ops.keys()]).toContain('memory_list');
|
|
39
|
-
expect([...ops.keys()]).toContain('session_capture');
|
|
40
|
-
expect([...ops.keys()]).toContain('memory_delete');
|
|
41
|
-
expect([...ops.keys()]).toContain('memory_promote_to_global');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('has correct auth levels for base ops', () => {
|
|
45
|
-
expect(ops.get('memory_search')!.auth).toBe('read');
|
|
46
|
-
expect(ops.get('memory_capture')!.auth).toBe('write');
|
|
47
|
-
expect(ops.get('memory_list')!.auth).toBe('read');
|
|
48
|
-
expect(ops.get('session_capture')!.auth).toBe('write');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
33
|
// ─── memory_capture ────────────────────────────────────────────
|
|
52
34
|
|
|
53
35
|
it('memory_capture stores a memory', async () => {
|
|
@@ -60,21 +60,37 @@ export function createMemoryFacadeOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
60
60
|
name: 'memory_capture',
|
|
61
61
|
description: 'Capture a memory — session summary, lesson learned, or preference.',
|
|
62
62
|
auth: 'write',
|
|
63
|
-
schema: z
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
63
|
+
schema: z
|
|
64
|
+
.object({
|
|
65
|
+
projectPath: z.string().optional().default('.'),
|
|
66
|
+
type: z
|
|
67
|
+
.enum(['session', 'lesson', 'preference'])
|
|
68
|
+
.optional()
|
|
69
|
+
.default('lesson')
|
|
70
|
+
.describe('Memory type: session | lesson | preference (default: "lesson")'),
|
|
71
|
+
context: z.string().optional().describe('What was happening — situation or task context'),
|
|
72
|
+
summary: z.string().optional().describe('What was learned or decided'),
|
|
73
|
+
content: z
|
|
74
|
+
.string()
|
|
75
|
+
.optional()
|
|
76
|
+
.describe('Alias: sets both context and summary when neither is provided'),
|
|
77
|
+
topics: z.array(z.string()).optional().default([]),
|
|
78
|
+
filesModified: z.array(z.string()).optional().default([]),
|
|
79
|
+
toolsUsed: z.array(z.string()).optional().default([]),
|
|
80
|
+
})
|
|
81
|
+
.refine(
|
|
82
|
+
(v) => v.context !== undefined || v.summary !== undefined || v.content !== undefined,
|
|
83
|
+
{
|
|
84
|
+
message: 'Provide at least one of: context, summary, or content',
|
|
85
|
+
},
|
|
86
|
+
),
|
|
72
87
|
handler: async (params) => {
|
|
88
|
+
const rawContent = params.content as string | undefined;
|
|
73
89
|
const memory = vault.captureMemory({
|
|
74
90
|
projectPath: params.projectPath as string,
|
|
75
91
|
type: params.type as 'session' | 'lesson' | 'preference',
|
|
76
|
-
context: params.context as string,
|
|
77
|
-
summary: params.summary as string,
|
|
92
|
+
context: (params.context as string | undefined) ?? rawContent ?? '',
|
|
93
|
+
summary: (params.summary as string | undefined) ?? rawContent ?? '',
|
|
78
94
|
topics: (params.topics as string[]) ?? [],
|
|
79
95
|
filesModified: (params.filesModified as string[]) ?? [],
|
|
80
96
|
toolsUsed: (params.toolsUsed as string[]) ?? [],
|
|
@@ -41,37 +41,6 @@ describe('operator-facade (colocated)', () => {
|
|
|
41
41
|
vault.close();
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
it('registers all 10 ops', () => {
|
|
45
|
-
expect(ops.size).toBe(10);
|
|
46
|
-
expect([...ops.keys()]).toEqual(
|
|
47
|
-
expect.arrayContaining([
|
|
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',
|
|
58
|
-
]),
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('has correct auth levels', () => {
|
|
63
|
-
expect(ops.get('profile_get')!.auth).toBe('read');
|
|
64
|
-
expect(ops.get('profile_update_section')!.auth).toBe('write');
|
|
65
|
-
expect(ops.get('profile_correct')!.auth).toBe('write');
|
|
66
|
-
expect(ops.get('profile_delete')!.auth).toBe('admin');
|
|
67
|
-
expect(ops.get('profile_export')!.auth).toBe('read');
|
|
68
|
-
expect(ops.get('signal_accumulate')!.auth).toBe('write');
|
|
69
|
-
expect(ops.get('signal_list')!.auth).toBe('read');
|
|
70
|
-
expect(ops.get('signal_stats')!.auth).toBe('read');
|
|
71
|
-
expect(ops.get('synthesis_check')!.auth).toBe('read');
|
|
72
|
-
expect(ops.get('profile_snapshot')!.auth).toBe('write');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
44
|
// ─── profile_get ───────────────────────────────────────────────
|
|
76
45
|
|
|
77
46
|
it('profile_get returns null when no profile', async () => {
|
|
@@ -62,27 +62,6 @@ describe('orchestrate-facade', () => {
|
|
|
62
62
|
vault.close();
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
-
it('registers session_start + satellite ops', () => {
|
|
66
|
-
expect(ops.size).toBeGreaterThanOrEqual(20);
|
|
67
|
-
expect([...ops.keys()]).toContain('session_start');
|
|
68
|
-
expect([...ops.keys()]).toContain('orchestrate_plan');
|
|
69
|
-
expect([...ops.keys()]).toContain('orchestrate_execute');
|
|
70
|
-
expect([...ops.keys()]).toContain('orchestrate_complete');
|
|
71
|
-
expect([...ops.keys()]).toContain('orchestrate_status');
|
|
72
|
-
expect([...ops.keys()]).toContain('orchestrate_quick_capture');
|
|
73
|
-
expect([...ops.keys()]).toContain('project_get');
|
|
74
|
-
expect([...ops.keys()]).toContain('project_list');
|
|
75
|
-
expect([...ops.keys()]).toContain('playbook_list');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('has correct auth levels', () => {
|
|
79
|
-
expect(ops.get('session_start')!.auth).toBe('write');
|
|
80
|
-
expect(ops.get('orchestrate_plan')!.auth).toBe('write');
|
|
81
|
-
expect(ops.get('orchestrate_status')!.auth).toBe('read');
|
|
82
|
-
expect(ops.get('project_get')!.auth).toBe('read');
|
|
83
|
-
expect(ops.get('project_list')!.auth).toBe('read');
|
|
84
|
-
});
|
|
85
|
-
|
|
86
65
|
// ─── session_start ─────────────────────────────────────────────
|
|
87
66
|
|
|
88
67
|
it('session_start registers project and returns stats', async () => {
|
|
@@ -120,6 +120,18 @@ export function createOrchestrateFacadeOps(runtime: AgentRuntime): OpDefinition[
|
|
|
120
120
|
/* dream module not available — skip silently */
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
// Auto-reap stale worktrees — best-effort, non-blocking
|
|
124
|
+
try {
|
|
125
|
+
const { worktreeReap } = await import('../../utils/worktree-reaper.js');
|
|
126
|
+
Promise.resolve()
|
|
127
|
+
.then(() => worktreeReap(projectPath))
|
|
128
|
+
.catch(() => {
|
|
129
|
+
/* best-effort */
|
|
130
|
+
});
|
|
131
|
+
} catch {
|
|
132
|
+
/* worktree-reaper not available — skip silently */
|
|
133
|
+
}
|
|
134
|
+
|
|
123
135
|
// ─── Pre-flight manifest ───────────────────────────────
|
|
124
136
|
let skills: string[] = [];
|
|
125
137
|
try {
|
|
@@ -48,26 +48,6 @@ describe('plan-facade', () => {
|
|
|
48
48
|
vault.close();
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
it('registers base + extra + grading + chain ops', () => {
|
|
52
|
-
// 5 base + 22 extra + 5 grading + 5 chain = 37
|
|
53
|
-
expect(ops.size).toBeGreaterThanOrEqual(32);
|
|
54
|
-
expect([...ops.keys()]).toContain('create_plan');
|
|
55
|
-
expect([...ops.keys()]).toContain('get_plan');
|
|
56
|
-
expect([...ops.keys()]).toContain('approve_plan');
|
|
57
|
-
expect([...ops.keys()]).toContain('update_task');
|
|
58
|
-
expect([...ops.keys()]).toContain('complete_plan');
|
|
59
|
-
expect([...ops.keys()]).toContain('plan_grade');
|
|
60
|
-
expect([...ops.keys()]).toContain('chain_execute');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('has correct auth levels for base ops', () => {
|
|
64
|
-
expect(ops.get('create_plan')!.auth).toBe('write');
|
|
65
|
-
expect(ops.get('get_plan')!.auth).toBe('read');
|
|
66
|
-
expect(ops.get('approve_plan')!.auth).toBe('write');
|
|
67
|
-
expect(ops.get('update_task')!.auth).toBe('write');
|
|
68
|
-
expect(ops.get('complete_plan')!.auth).toBe('write');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
51
|
// ─── create_plan ───────────────────────────────────────────────
|
|
72
52
|
|
|
73
53
|
it('create_plan creates a draft plan', async () => {
|
|
@@ -91,7 +71,7 @@ describe('plan-facade', () => {
|
|
|
91
71
|
});
|
|
92
72
|
expect(result.success).toBe(true);
|
|
93
73
|
const plan = (result.data as Record<string, unknown>).plan as Record<string, unknown>;
|
|
94
|
-
expect((plan.tasks as unknown[]).length).
|
|
74
|
+
expect((plan.tasks as unknown[]).length).toBeGreaterThanOrEqual(1);
|
|
95
75
|
});
|
|
96
76
|
|
|
97
77
|
// ─── get_plan ──────────────────────────────────────────────────
|
|
@@ -366,11 +346,11 @@ describe('plan-facade', () => {
|
|
|
366
346
|
vaultEntryIds: string[];
|
|
367
347
|
};
|
|
368
348
|
expect(data.created).toBe(true);
|
|
369
|
-
expect(data.vaultEntryIds
|
|
349
|
+
expect(data.vaultEntryIds).toHaveLength(1); // exactly one seeded entry matches
|
|
370
350
|
// Decisions should contain vault pattern references with entryId markers
|
|
371
351
|
const decisions = data.plan.decisions as string[];
|
|
372
352
|
const vaultDecisions = decisions.filter((d) => d.startsWith('Vault pattern:'));
|
|
373
|
-
expect(vaultDecisions
|
|
353
|
+
expect(vaultDecisions).toHaveLength(1); // one vault entry injected one decision
|
|
374
354
|
// Each vault decision should have an [entryId:...] marker for brain feedback
|
|
375
355
|
for (const vd of vaultDecisions) {
|
|
376
356
|
expect(vd).toMatch(/\[entryId:[^\]]+\]/);
|
|
@@ -413,19 +393,14 @@ describe('plan-facade', () => {
|
|
|
413
393
|
const decisions = data.plan.decisions as string[];
|
|
414
394
|
// User decision preserved
|
|
415
395
|
expect(decisions).toContain('Use vitest as test runner');
|
|
416
|
-
// Vault enrichment added
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
}
|
|
396
|
+
// Vault enrichment added — one seeded entry matches the 'testing' query
|
|
397
|
+
expect(data.vaultEntryIds).toHaveLength(1);
|
|
398
|
+
const vaultDecisions = decisions.filter((d) => d.startsWith('Vault pattern:'));
|
|
399
|
+
expect(vaultDecisions).toHaveLength(1);
|
|
421
400
|
});
|
|
422
401
|
|
|
423
402
|
// ─── plan_close_stale ─────────────────────────────────────────
|
|
424
403
|
|
|
425
|
-
it('plan_close_stale op is registered', () => {
|
|
426
|
-
expect([...ops.keys()]).toContain('plan_close_stale');
|
|
427
|
-
});
|
|
428
|
-
|
|
429
404
|
it('plan_close_stale returns no plans when none are stale', async () => {
|
|
430
405
|
const result = await executeOp(ops, 'plan_close_stale', {});
|
|
431
406
|
expect(result.success).toBe(true);
|