@soleri/core 2.4.0 → 2.5.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/dist/brain/brain.d.ts +7 -0
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +56 -9
- package/dist/brain/brain.js.map +1 -1
- package/dist/brain/types.d.ts +2 -2
- package/dist/brain/types.d.ts.map +1 -1
- package/dist/cognee/client.d.ts +3 -0
- package/dist/cognee/client.d.ts.map +1 -1
- package/dist/cognee/client.js +17 -0
- package/dist/cognee/client.js.map +1 -1
- package/dist/cognee/sync-manager.d.ts +94 -0
- package/dist/cognee/sync-manager.d.ts.map +1 -0
- package/dist/cognee/sync-manager.js +293 -0
- package/dist/cognee/sync-manager.js.map +1 -0
- package/dist/curator/curator.d.ts +8 -1
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +64 -1
- package/dist/curator/curator.js.map +1 -1
- package/dist/errors/classify.d.ts +13 -0
- package/dist/errors/classify.d.ts.map +1 -0
- package/dist/errors/classify.js +97 -0
- package/dist/errors/classify.js.map +1 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +4 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/retry.d.ts +40 -0
- package/dist/errors/retry.d.ts.map +1 -0
- package/dist/errors/retry.js +97 -0
- package/dist/errors/retry.js.map +1 -0
- package/dist/errors/types.d.ts +48 -0
- package/dist/errors/types.d.ts.map +1 -0
- package/dist/errors/types.js +59 -0
- package/dist/errors/types.js.map +1 -0
- package/dist/index.d.ts +25 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/intake/content-classifier.d.ts +14 -0
- package/dist/intake/content-classifier.d.ts.map +1 -0
- package/dist/intake/content-classifier.js +125 -0
- package/dist/intake/content-classifier.js.map +1 -0
- package/dist/intake/dedup-gate.d.ts +17 -0
- package/dist/intake/dedup-gate.d.ts.map +1 -0
- package/dist/intake/dedup-gate.js +66 -0
- package/dist/intake/dedup-gate.js.map +1 -0
- package/dist/intake/intake-pipeline.d.ts +63 -0
- package/dist/intake/intake-pipeline.d.ts.map +1 -0
- package/dist/intake/intake-pipeline.js +373 -0
- package/dist/intake/intake-pipeline.js.map +1 -0
- package/dist/intake/types.d.ts +65 -0
- package/dist/intake/types.d.ts.map +1 -0
- package/dist/intake/types.js +3 -0
- package/dist/intake/types.js.map +1 -0
- package/dist/intelligence/loader.js +1 -1
- package/dist/intelligence/loader.js.map +1 -1
- package/dist/intelligence/types.d.ts +3 -1
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/loop/loop-manager.d.ts +58 -7
- package/dist/loop/loop-manager.d.ts.map +1 -1
- package/dist/loop/loop-manager.js +280 -6
- package/dist/loop/loop-manager.js.map +1 -1
- package/dist/loop/types.d.ts +69 -1
- package/dist/loop/types.d.ts.map +1 -1
- package/dist/loop/types.js +4 -1
- package/dist/loop/types.js.map +1 -1
- package/dist/persistence/index.d.ts +3 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +2 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/sqlite-provider.d.ts +25 -0
- package/dist/persistence/sqlite-provider.d.ts.map +1 -0
- package/dist/persistence/sqlite-provider.js +59 -0
- package/dist/persistence/sqlite-provider.js.map +1 -0
- package/dist/persistence/types.d.ts +36 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +8 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/planning/gap-analysis.d.ts +47 -4
- package/dist/planning/gap-analysis.d.ts.map +1 -1
- package/dist/planning/gap-analysis.js +190 -13
- package/dist/planning/gap-analysis.js.map +1 -1
- package/dist/planning/gap-types.d.ts +1 -1
- package/dist/planning/gap-types.d.ts.map +1 -1
- package/dist/planning/gap-types.js.map +1 -1
- package/dist/planning/planner.d.ts +277 -9
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +611 -46
- package/dist/planning/planner.js.map +1 -1
- package/dist/playbooks/generic/brainstorming.d.ts +9 -0
- package/dist/playbooks/generic/brainstorming.d.ts.map +1 -0
- package/dist/playbooks/generic/brainstorming.js +105 -0
- package/dist/playbooks/generic/brainstorming.js.map +1 -0
- package/dist/playbooks/generic/code-review.d.ts +11 -0
- package/dist/playbooks/generic/code-review.d.ts.map +1 -0
- package/dist/playbooks/generic/code-review.js +176 -0
- package/dist/playbooks/generic/code-review.js.map +1 -0
- package/dist/playbooks/generic/subagent-execution.d.ts +9 -0
- package/dist/playbooks/generic/subagent-execution.d.ts.map +1 -0
- package/dist/playbooks/generic/subagent-execution.js +68 -0
- package/dist/playbooks/generic/subagent-execution.js.map +1 -0
- package/dist/playbooks/generic/systematic-debugging.d.ts +9 -0
- package/dist/playbooks/generic/systematic-debugging.d.ts.map +1 -0
- package/dist/playbooks/generic/systematic-debugging.js +87 -0
- package/dist/playbooks/generic/systematic-debugging.js.map +1 -0
- package/dist/playbooks/generic/tdd.d.ts +9 -0
- package/dist/playbooks/generic/tdd.d.ts.map +1 -0
- package/dist/playbooks/generic/tdd.js +70 -0
- package/dist/playbooks/generic/tdd.js.map +1 -0
- package/dist/playbooks/generic/verification.d.ts +9 -0
- package/dist/playbooks/generic/verification.d.ts.map +1 -0
- package/dist/playbooks/generic/verification.js +74 -0
- package/dist/playbooks/generic/verification.js.map +1 -0
- package/dist/playbooks/index.d.ts +4 -0
- package/dist/playbooks/index.d.ts.map +1 -0
- package/dist/playbooks/index.js +5 -0
- package/dist/playbooks/index.js.map +1 -0
- package/dist/playbooks/playbook-registry.d.ts +42 -0
- package/dist/playbooks/playbook-registry.d.ts.map +1 -0
- package/dist/playbooks/playbook-registry.js +227 -0
- package/dist/playbooks/playbook-registry.js.map +1 -0
- package/dist/playbooks/playbook-seeder.d.ts +47 -0
- package/dist/playbooks/playbook-seeder.d.ts.map +1 -0
- package/dist/playbooks/playbook-seeder.js +104 -0
- package/dist/playbooks/playbook-seeder.js.map +1 -0
- package/dist/playbooks/playbook-types.d.ts +132 -0
- package/dist/playbooks/playbook-types.d.ts.map +1 -0
- package/dist/playbooks/playbook-types.js +12 -0
- package/dist/playbooks/playbook-types.js.map +1 -0
- package/dist/project/project-registry.d.ts.map +1 -1
- package/dist/project/project-registry.js +9 -11
- package/dist/project/project-registry.js.map +1 -1
- package/dist/prompts/index.d.ts +4 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +3 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/parser.d.ts +17 -0
- package/dist/prompts/parser.d.ts.map +1 -0
- package/dist/prompts/parser.js +47 -0
- package/dist/prompts/parser.js.map +1 -0
- package/dist/prompts/template-manager.d.ts +25 -0
- package/dist/prompts/template-manager.d.ts.map +1 -0
- package/dist/prompts/template-manager.js +71 -0
- package/dist/prompts/template-manager.js.map +1 -0
- package/dist/prompts/types.d.ts +26 -0
- package/dist/prompts/types.d.ts.map +1 -0
- package/dist/prompts/types.js +5 -0
- package/dist/prompts/types.js.map +1 -0
- package/dist/runtime/admin-extra-ops.d.ts +5 -3
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +322 -11
- 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 +10 -3
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +20 -2
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/cognee-sync-ops.d.ts +12 -0
- package/dist/runtime/cognee-sync-ops.d.ts.map +1 -0
- package/dist/runtime/cognee-sync-ops.js +55 -0
- package/dist/runtime/cognee-sync-ops.js.map +1 -0
- package/dist/runtime/core-ops.d.ts +8 -6
- package/dist/runtime/core-ops.d.ts.map +1 -1
- package/dist/runtime/core-ops.js +226 -9
- package/dist/runtime/core-ops.js.map +1 -1
- package/dist/runtime/curator-extra-ops.d.ts +2 -2
- package/dist/runtime/curator-extra-ops.d.ts.map +1 -1
- package/dist/runtime/curator-extra-ops.js +15 -3
- package/dist/runtime/curator-extra-ops.js.map +1 -1
- package/dist/runtime/domain-ops.js +2 -2
- package/dist/runtime/domain-ops.js.map +1 -1
- package/dist/runtime/grading-ops.d.ts.map +1 -1
- package/dist/runtime/grading-ops.js.map +1 -1
- package/dist/runtime/intake-ops.d.ts +14 -0
- package/dist/runtime/intake-ops.d.ts.map +1 -0
- package/dist/runtime/intake-ops.js +110 -0
- package/dist/runtime/intake-ops.js.map +1 -0
- package/dist/runtime/loop-ops.d.ts +5 -4
- package/dist/runtime/loop-ops.d.ts.map +1 -1
- package/dist/runtime/loop-ops.js +84 -12
- package/dist/runtime/loop-ops.js.map +1 -1
- package/dist/runtime/memory-cross-project-ops.d.ts.map +1 -1
- package/dist/runtime/memory-cross-project-ops.js.map +1 -1
- package/dist/runtime/memory-extra-ops.js +5 -5
- package/dist/runtime/memory-extra-ops.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +8 -2
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts +13 -5
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js +381 -18
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/playbook-ops.d.ts +14 -0
- package/dist/runtime/playbook-ops.d.ts.map +1 -0
- package/dist/runtime/playbook-ops.js +141 -0
- package/dist/runtime/playbook-ops.js.map +1 -0
- package/dist/runtime/project-ops.d.ts.map +1 -1
- package/dist/runtime/project-ops.js +7 -2
- package/dist/runtime/project-ops.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +27 -8
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +8 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.d.ts +3 -2
- package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.js +345 -4
- package/dist/runtime/vault-extra-ops.js.map +1 -1
- package/dist/vault/playbook.d.ts +34 -0
- package/dist/vault/playbook.d.ts.map +1 -0
- package/dist/vault/playbook.js +60 -0
- package/dist/vault/playbook.js.map +1 -0
- package/dist/vault/vault.d.ts +31 -32
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +201 -181
- package/dist/vault/vault.js.map +1 -1
- package/package.json +7 -3
- package/src/__tests__/admin-extra-ops.test.ts +62 -15
- package/src/__tests__/admin-ops.test.ts +2 -2
- package/src/__tests__/brain.test.ts +3 -3
- package/src/__tests__/cognee-integration.test.ts +80 -0
- package/src/__tests__/cognee-sync-manager.test.ts +103 -0
- package/src/__tests__/core-ops.test.ts +30 -4
- package/src/__tests__/curator-extra-ops.test.ts +24 -2
- package/src/__tests__/errors.test.ts +388 -0
- package/src/__tests__/grading-ops.test.ts +28 -7
- package/src/__tests__/intake-pipeline.test.ts +162 -0
- package/src/__tests__/loop-ops.test.ts +74 -3
- package/src/__tests__/memory-cross-project-ops.test.ts +3 -1
- package/src/__tests__/orchestrate-ops.test.ts +8 -3
- package/src/__tests__/persistence.test.ts +225 -0
- package/src/__tests__/planner.test.ts +99 -21
- package/src/__tests__/planning-extra-ops.test.ts +168 -10
- package/src/__tests__/playbook-registry.test.ts +326 -0
- package/src/__tests__/playbook-seeder.test.ts +163 -0
- package/src/__tests__/playbook.test.ts +389 -0
- package/src/__tests__/project-ops.test.ts +18 -4
- package/src/__tests__/template-manager.test.ts +222 -0
- package/src/__tests__/vault-extra-ops.test.ts +82 -7
- package/src/brain/brain.ts +71 -9
- package/src/brain/types.ts +2 -2
- package/src/cognee/client.ts +18 -0
- package/src/cognee/sync-manager.ts +389 -0
- package/src/curator/curator.ts +88 -7
- package/src/errors/classify.ts +102 -0
- package/src/errors/index.ts +5 -0
- package/src/errors/retry.ts +132 -0
- package/src/errors/types.ts +81 -0
- package/src/index.ts +114 -3
- package/src/intake/content-classifier.ts +146 -0
- package/src/intake/dedup-gate.ts +92 -0
- package/src/intake/intake-pipeline.ts +503 -0
- package/src/intake/types.ts +69 -0
- package/src/intelligence/loader.ts +1 -1
- package/src/intelligence/types.ts +3 -1
- package/src/loop/loop-manager.ts +325 -7
- package/src/loop/types.ts +72 -1
- package/src/persistence/index.ts +7 -0
- package/src/persistence/sqlite-provider.ts +62 -0
- package/src/persistence/types.ts +44 -0
- package/src/planning/gap-analysis.ts +286 -17
- package/src/planning/gap-types.ts +4 -1
- package/src/planning/planner.ts +828 -55
- package/src/playbooks/generic/brainstorming.ts +110 -0
- package/src/playbooks/generic/code-review.ts +181 -0
- package/src/playbooks/generic/subagent-execution.ts +74 -0
- package/src/playbooks/generic/systematic-debugging.ts +92 -0
- package/src/playbooks/generic/tdd.ts +75 -0
- package/src/playbooks/generic/verification.ts +79 -0
- package/src/playbooks/index.ts +27 -0
- package/src/playbooks/playbook-registry.ts +284 -0
- package/src/playbooks/playbook-seeder.ts +119 -0
- package/src/playbooks/playbook-types.ts +162 -0
- package/src/project/project-registry.ts +29 -17
- package/src/prompts/index.ts +3 -0
- package/src/prompts/parser.ts +59 -0
- package/src/prompts/template-manager.ts +77 -0
- package/src/prompts/types.ts +28 -0
- package/src/runtime/admin-extra-ops.ts +358 -13
- package/src/runtime/admin-ops.ts +17 -6
- package/src/runtime/capture-ops.ts +25 -6
- package/src/runtime/cognee-sync-ops.ts +63 -0
- package/src/runtime/core-ops.ts +258 -8
- package/src/runtime/curator-extra-ops.ts +17 -3
- package/src/runtime/domain-ops.ts +2 -2
- package/src/runtime/grading-ops.ts +11 -2
- package/src/runtime/intake-ops.ts +126 -0
- package/src/runtime/loop-ops.ts +96 -13
- package/src/runtime/memory-cross-project-ops.ts +1 -2
- package/src/runtime/memory-extra-ops.ts +5 -5
- package/src/runtime/orchestrate-ops.ts +8 -2
- package/src/runtime/planning-extra-ops.ts +414 -23
- package/src/runtime/playbook-ops.ts +169 -0
- package/src/runtime/project-ops.ts +9 -3
- package/src/runtime/runtime.ts +35 -9
- package/src/runtime/types.ts +8 -0
- package/src/runtime/vault-extra-ops.ts +385 -4
- package/src/vault/playbook.ts +87 -0
- package/src/vault/vault.ts +301 -235
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Extended planning operations —
|
|
2
|
+
* Extended planning operations — 22 ops for advanced plan lifecycle management.
|
|
3
3
|
*
|
|
4
4
|
* These complement the 5 basic planning ops in core-ops.ts with:
|
|
5
5
|
* iteration, splitting, reconciliation, lifecycle completion,
|
|
6
|
-
* dispatch, review, archival, task listing,
|
|
6
|
+
* dispatch, review, archival, task listing, statistics,
|
|
7
|
+
* evidence submission, verification, validation, auto-reconciliation,
|
|
8
|
+
* review prompt generation, brainstorming, execution metrics,
|
|
9
|
+
* deliverable submission, and deliverable verification.
|
|
7
10
|
*/
|
|
8
11
|
|
|
9
12
|
import { z } from 'zod';
|
|
10
13
|
import type { OpDefinition } from '../facades/types.js';
|
|
11
14
|
import type { AgentRuntime } from './types.js';
|
|
12
|
-
import type { DriftItem } from '../planning/planner.js';
|
|
15
|
+
import type { DriftItem, TaskEvidence } from '../planning/planner.js';
|
|
16
|
+
import { matchPlaybooks, type PlaybookMatchResult } from '../playbooks/index.js';
|
|
17
|
+
import { entryToPlaybookDefinition } from '../playbooks/index.js';
|
|
13
18
|
|
|
14
19
|
/**
|
|
15
|
-
* Create
|
|
20
|
+
* Create 22 extended planning operations for an agent runtime.
|
|
16
21
|
*
|
|
17
|
-
* Groups:
|
|
18
|
-
*
|
|
22
|
+
* Groups:
|
|
23
|
+
* mutation: plan_iterate, plan_split, plan_reconcile, plan_complete_lifecycle,
|
|
24
|
+
* plan_review, plan_archive, plan_submit_evidence, plan_auto_reconcile,
|
|
25
|
+
* plan_review_outcome, plan_record_task_metrics, plan_submit_deliverable
|
|
26
|
+
* query: plan_dispatch, plan_list_tasks, plan_stats, plan_verify_task,
|
|
27
|
+
* plan_verify_plan, plan_validate, plan_review_spec, plan_review_quality,
|
|
28
|
+
* plan_brainstorm, plan_execution_metrics, plan_verify_deliverables
|
|
19
29
|
*/
|
|
20
30
|
export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
21
31
|
const { planner, vault } = runtime;
|
|
@@ -31,15 +41,15 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
31
41
|
planId: z.string().describe('ID of the draft plan to iterate on'),
|
|
32
42
|
objective: z.string().optional().describe('New objective (replaces existing)'),
|
|
33
43
|
scope: z.string().optional().describe('New scope (replaces existing)'),
|
|
34
|
-
decisions: z
|
|
44
|
+
decisions: z
|
|
45
|
+
.array(z.string())
|
|
46
|
+
.optional()
|
|
47
|
+
.describe('New decisions list (replaces existing)'),
|
|
35
48
|
addTasks: z
|
|
36
49
|
.array(z.object({ title: z.string(), description: z.string() }))
|
|
37
50
|
.optional()
|
|
38
51
|
.describe('Tasks to append'),
|
|
39
|
-
removeTasks: z
|
|
40
|
-
.array(z.string())
|
|
41
|
-
.optional()
|
|
42
|
-
.describe('Task IDs to remove'),
|
|
52
|
+
removeTasks: z.array(z.string()).optional().describe('Task IDs to remove'),
|
|
43
53
|
}),
|
|
44
54
|
handler: async (params) => {
|
|
45
55
|
try {
|
|
@@ -135,10 +145,7 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
135
145
|
auth: 'write',
|
|
136
146
|
schema: z.object({
|
|
137
147
|
planId: z.string().describe('Plan ID (must be completed with reconciliation data)'),
|
|
138
|
-
patterns: z
|
|
139
|
-
.array(z.string())
|
|
140
|
-
.optional()
|
|
141
|
-
.describe('Patterns discovered during execution'),
|
|
148
|
+
patterns: z.array(z.string()).optional().describe('Patterns discovered during execution'),
|
|
142
149
|
antiPatterns: z
|
|
143
150
|
.array(z.string())
|
|
144
151
|
.optional()
|
|
@@ -208,10 +215,7 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
208
215
|
}),
|
|
209
216
|
handler: async (params) => {
|
|
210
217
|
try {
|
|
211
|
-
const dispatch = planner.getDispatch(
|
|
212
|
-
params.planId as string,
|
|
213
|
-
params.taskId as string,
|
|
214
|
-
);
|
|
218
|
+
const dispatch = planner.getDispatch(params.planId as string, params.taskId as string);
|
|
215
219
|
return dispatch;
|
|
216
220
|
} catch (err) {
|
|
217
221
|
return { error: (err as Error).message };
|
|
@@ -229,9 +233,7 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
229
233
|
planId: z.string().describe('Plan ID to review'),
|
|
230
234
|
taskId: z.string().optional().describe('Specific task ID (omit to review the whole plan)'),
|
|
231
235
|
reviewer: z.string().describe('Name or ID of reviewer'),
|
|
232
|
-
outcome: z
|
|
233
|
-
.enum(['approved', 'rejected', 'needs_changes'])
|
|
234
|
-
.describe('Review outcome'),
|
|
236
|
+
outcome: z.enum(['approved', 'rejected', 'needs_changes']).describe('Review outcome'),
|
|
235
237
|
comments: z.string().describe('Review comments'),
|
|
236
238
|
}),
|
|
237
239
|
handler: async (params) => {
|
|
@@ -266,7 +268,10 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
266
268
|
try {
|
|
267
269
|
const olderThanDays = (params.olderThanDays as number) ?? 30;
|
|
268
270
|
const archived = planner.archive(olderThanDays);
|
|
269
|
-
return {
|
|
271
|
+
return {
|
|
272
|
+
archived: archived.length,
|
|
273
|
+
plans: archived.map((p) => ({ id: p.id, objective: p.objective })),
|
|
274
|
+
};
|
|
270
275
|
} catch (err) {
|
|
271
276
|
return { error: (err as Error).message };
|
|
272
277
|
}
|
|
@@ -323,5 +328,391 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
323
328
|
}
|
|
324
329
|
},
|
|
325
330
|
},
|
|
331
|
+
|
|
332
|
+
// ─── Evidence Submission (#148) ──────────────────────────────
|
|
333
|
+
{
|
|
334
|
+
name: 'plan_submit_evidence',
|
|
335
|
+
description:
|
|
336
|
+
'Submit command output evidence for a task acceptance criterion. Makes playbook verification gates enforceable.',
|
|
337
|
+
auth: 'write',
|
|
338
|
+
schema: z.object({
|
|
339
|
+
planId: z.string().describe('Plan ID'),
|
|
340
|
+
taskId: z.string().describe('Task ID to submit evidence for'),
|
|
341
|
+
criterion: z.string().describe('Which acceptance criterion this evidence satisfies'),
|
|
342
|
+
content: z
|
|
343
|
+
.string()
|
|
344
|
+
.describe('Evidence content — command output, URL, file path, or description'),
|
|
345
|
+
type: z.enum(['command_output', 'url', 'file', 'description']).describe('Evidence type'),
|
|
346
|
+
}),
|
|
347
|
+
handler: async (params) => {
|
|
348
|
+
try {
|
|
349
|
+
const task = planner.submitEvidence(params.planId as string, params.taskId as string, {
|
|
350
|
+
criterion: params.criterion as string,
|
|
351
|
+
content: params.content as string,
|
|
352
|
+
type: params.type as TaskEvidence['type'],
|
|
353
|
+
});
|
|
354
|
+
return {
|
|
355
|
+
submitted: true,
|
|
356
|
+
taskId: task.id,
|
|
357
|
+
evidenceCount: task.evidence?.length ?? 0,
|
|
358
|
+
};
|
|
359
|
+
} catch (err) {
|
|
360
|
+
return { error: (err as Error).message };
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
// ─── Verify Task (#148) ─────────────────────────────────────
|
|
366
|
+
{
|
|
367
|
+
name: 'plan_verify_task',
|
|
368
|
+
description:
|
|
369
|
+
'Check task evidence submitted + reviews passed → mark verified. Returns verification status with details.',
|
|
370
|
+
auth: 'read',
|
|
371
|
+
schema: z.object({
|
|
372
|
+
planId: z.string().describe('Plan ID'),
|
|
373
|
+
taskId: z.string().describe('Task ID to verify'),
|
|
374
|
+
}),
|
|
375
|
+
handler: async (params) => {
|
|
376
|
+
try {
|
|
377
|
+
return planner.verifyTask(params.planId as string, params.taskId as string);
|
|
378
|
+
} catch (err) {
|
|
379
|
+
return { error: (err as Error).message };
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
// ─── Verify Plan (#148) ─────────────────────────────────────
|
|
385
|
+
{
|
|
386
|
+
name: 'plan_verify_plan',
|
|
387
|
+
description:
|
|
388
|
+
'Check all tasks verified → plan is ready for reconciliation. Returns validation status with per-task issues.',
|
|
389
|
+
auth: 'read',
|
|
390
|
+
schema: z.object({
|
|
391
|
+
planId: z.string().describe('Plan ID to verify'),
|
|
392
|
+
}),
|
|
393
|
+
handler: async (params) => {
|
|
394
|
+
try {
|
|
395
|
+
return planner.verifyPlan(params.planId as string);
|
|
396
|
+
} catch (err) {
|
|
397
|
+
return { error: (err as Error).message };
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
|
|
402
|
+
// ─── Review Spec (#149) ─────────────────────────────────────
|
|
403
|
+
{
|
|
404
|
+
name: 'plan_review_spec',
|
|
405
|
+
description:
|
|
406
|
+
'Generate a spec compliance review prompt for a task. Stage 1 of the two-stage subagent review model.',
|
|
407
|
+
auth: 'read',
|
|
408
|
+
schema: z.object({
|
|
409
|
+
planId: z.string().describe('Plan ID'),
|
|
410
|
+
taskId: z.string().describe('Task ID to generate review prompt for'),
|
|
411
|
+
}),
|
|
412
|
+
handler: async (params) => {
|
|
413
|
+
try {
|
|
414
|
+
return planner.generateReviewSpec(params.planId as string, params.taskId as string);
|
|
415
|
+
} catch (err) {
|
|
416
|
+
return { error: (err as Error).message };
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
|
|
421
|
+
// ─── Review Quality (#149) ──────────────────────────────────
|
|
422
|
+
{
|
|
423
|
+
name: 'plan_review_quality',
|
|
424
|
+
description:
|
|
425
|
+
'Generate a code quality review prompt for a task. Stage 2 of the two-stage subagent review model.',
|
|
426
|
+
auth: 'read',
|
|
427
|
+
schema: z.object({
|
|
428
|
+
planId: z.string().describe('Plan ID'),
|
|
429
|
+
taskId: z.string().describe('Task ID to generate review prompt for'),
|
|
430
|
+
}),
|
|
431
|
+
handler: async (params) => {
|
|
432
|
+
try {
|
|
433
|
+
return planner.generateReviewQuality(params.planId as string, params.taskId as string);
|
|
434
|
+
} catch (err) {
|
|
435
|
+
return { error: (err as Error).message };
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
|
|
440
|
+
// ─── Review Outcome (#149) ──────────────────────────────────
|
|
441
|
+
{
|
|
442
|
+
name: 'plan_review_outcome',
|
|
443
|
+
description:
|
|
444
|
+
'Record a subagent review pass/fail result with feedback. Works alongside plan_review for structured review tracking.',
|
|
445
|
+
auth: 'write',
|
|
446
|
+
schema: z.object({
|
|
447
|
+
planId: z.string().describe('Plan ID'),
|
|
448
|
+
taskId: z.string().describe('Task ID being reviewed'),
|
|
449
|
+
reviewType: z
|
|
450
|
+
.enum(['spec', 'quality'])
|
|
451
|
+
.describe('Type of review — spec compliance or code quality'),
|
|
452
|
+
reviewer: z.string().describe('Reviewer identifier (subagent name)'),
|
|
453
|
+
outcome: z.enum(['approved', 'rejected', 'needs_changes']).describe('Review outcome'),
|
|
454
|
+
comments: z.string().describe('Review comments and feedback'),
|
|
455
|
+
}),
|
|
456
|
+
handler: async (params) => {
|
|
457
|
+
try {
|
|
458
|
+
const plan = planner.addReview(params.planId as string, {
|
|
459
|
+
taskId: params.taskId as string,
|
|
460
|
+
reviewer: `${params.reviewType}-review:${params.reviewer}`,
|
|
461
|
+
outcome: params.outcome as 'approved' | 'rejected' | 'needs_changes',
|
|
462
|
+
comments: params.comments as string,
|
|
463
|
+
});
|
|
464
|
+
return {
|
|
465
|
+
recorded: true,
|
|
466
|
+
totalReviews: plan.reviews?.length ?? 0,
|
|
467
|
+
taskId: params.taskId,
|
|
468
|
+
reviewType: params.reviewType,
|
|
469
|
+
outcome: params.outcome,
|
|
470
|
+
};
|
|
471
|
+
} catch (err) {
|
|
472
|
+
return { error: (err as Error).message };
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
|
|
477
|
+
// ─── Brainstorm (#150) ──────────────────────────────────────
|
|
478
|
+
{
|
|
479
|
+
name: 'plan_brainstorm',
|
|
480
|
+
description:
|
|
481
|
+
'Match a playbook for the given intent/text and return its brainstorm sections. ' +
|
|
482
|
+
'Enforces the brainstorming gate — design must be explored before plan creation.',
|
|
483
|
+
auth: 'read',
|
|
484
|
+
schema: z.object({
|
|
485
|
+
intent: z
|
|
486
|
+
.enum(['BUILD', 'FIX', 'REVIEW', 'PLAN', 'IMPROVE', 'DELIVER'])
|
|
487
|
+
.optional()
|
|
488
|
+
.describe('Detected intent (optional, improves matching)'),
|
|
489
|
+
text: z.string().describe('Task description text to match against playbooks'),
|
|
490
|
+
}),
|
|
491
|
+
handler: async (params) => {
|
|
492
|
+
try {
|
|
493
|
+
// Load vault playbooks for matching
|
|
494
|
+
const vaultEntries = vault.list({ type: 'playbook' });
|
|
495
|
+
const vaultPlaybooks = vaultEntries
|
|
496
|
+
.map((e) => entryToPlaybookDefinition(e))
|
|
497
|
+
.filter((p): p is NonNullable<typeof p> => p !== null);
|
|
498
|
+
|
|
499
|
+
const intent = params.intent as
|
|
500
|
+
| 'BUILD'
|
|
501
|
+
| 'FIX'
|
|
502
|
+
| 'REVIEW'
|
|
503
|
+
| 'PLAN'
|
|
504
|
+
| 'IMPROVE'
|
|
505
|
+
| 'DELIVER'
|
|
506
|
+
| undefined;
|
|
507
|
+
const result: PlaybookMatchResult = matchPlaybooks(
|
|
508
|
+
intent,
|
|
509
|
+
params.text as string,
|
|
510
|
+
vaultPlaybooks,
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
if (!result.playbook) {
|
|
514
|
+
return { matched: false, sections: [], playbook: null };
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Gather brainstorm sections from matched playbooks
|
|
518
|
+
const sections = [
|
|
519
|
+
...(result.playbook.generic?.brainstormSections ?? []),
|
|
520
|
+
...(result.playbook.domain?.brainstormSections ?? []),
|
|
521
|
+
];
|
|
522
|
+
|
|
523
|
+
return {
|
|
524
|
+
matched: true,
|
|
525
|
+
label: result.playbook.label,
|
|
526
|
+
genericMatch: result.genericMatch ?? null,
|
|
527
|
+
domainMatch: result.domainMatch ?? null,
|
|
528
|
+
sections,
|
|
529
|
+
gates: result.playbook.mergedGates,
|
|
530
|
+
toolInjections: result.playbook.mergedTools,
|
|
531
|
+
};
|
|
532
|
+
} catch (err) {
|
|
533
|
+
return { error: (err as Error).message };
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
|
|
538
|
+
// ─── Auto-Reconcile (#151) ──────────────────────────────────
|
|
539
|
+
{
|
|
540
|
+
name: 'plan_auto_reconcile',
|
|
541
|
+
description:
|
|
542
|
+
'Automated fast-path reconciliation. Checks task completion status, generates drift report automatically. ' +
|
|
543
|
+
'Returns null if drift is too significant (>2 non-completed tasks).',
|
|
544
|
+
auth: 'write',
|
|
545
|
+
schema: z.object({
|
|
546
|
+
planId: z.string().describe('Plan ID to auto-reconcile'),
|
|
547
|
+
}),
|
|
548
|
+
handler: async (params) => {
|
|
549
|
+
try {
|
|
550
|
+
const result = planner.autoReconcile(params.planId as string);
|
|
551
|
+
if (!result) {
|
|
552
|
+
return {
|
|
553
|
+
autoReconciled: false,
|
|
554
|
+
reason: 'Drift too significant for auto-reconciliation — use manual plan_reconcile',
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
return {
|
|
558
|
+
autoReconciled: true,
|
|
559
|
+
accuracy: result.reconciliation!.accuracy,
|
|
560
|
+
driftCount: result.reconciliation!.driftItems.length,
|
|
561
|
+
plan: result,
|
|
562
|
+
};
|
|
563
|
+
} catch (err) {
|
|
564
|
+
return { error: (err as Error).message };
|
|
565
|
+
}
|
|
566
|
+
},
|
|
567
|
+
},
|
|
568
|
+
|
|
569
|
+
// ─── Validate Plan (#152) ───────────────────────────────────
|
|
570
|
+
{
|
|
571
|
+
name: 'plan_validate',
|
|
572
|
+
description:
|
|
573
|
+
'Post-execution validation — checks all tasks final, evidence exists for verification tasks, ' +
|
|
574
|
+
'no tasks stuck in_progress. Run before reconciliation.',
|
|
575
|
+
auth: 'read',
|
|
576
|
+
schema: z.object({
|
|
577
|
+
planId: z.string().describe('Plan ID to validate'),
|
|
578
|
+
}),
|
|
579
|
+
handler: async (params) => {
|
|
580
|
+
try {
|
|
581
|
+
return planner.verifyPlan(params.planId as string);
|
|
582
|
+
} catch (err) {
|
|
583
|
+
return { error: (err as Error).message };
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
},
|
|
587
|
+
|
|
588
|
+
// ─── Execution Metrics (#80) ─────────────────────────────────
|
|
589
|
+
{
|
|
590
|
+
name: 'plan_execution_metrics',
|
|
591
|
+
description:
|
|
592
|
+
'Per-task timing and aggregate execution summary for a plan. Shows duration, status counts, and average task time.',
|
|
593
|
+
auth: 'read',
|
|
594
|
+
schema: z.object({
|
|
595
|
+
planId: z.string().describe('Plan ID to get metrics for'),
|
|
596
|
+
}),
|
|
597
|
+
handler: async (params) => {
|
|
598
|
+
try {
|
|
599
|
+
const plan = planner.get(params.planId as string);
|
|
600
|
+
if (!plan) return { error: `Plan not found: ${params.planId}` };
|
|
601
|
+
|
|
602
|
+
const taskMetrics = plan.tasks.map((t) => ({
|
|
603
|
+
id: t.id,
|
|
604
|
+
title: t.title,
|
|
605
|
+
status: t.status,
|
|
606
|
+
startedAt: t.startedAt ?? null,
|
|
607
|
+
completedAt: t.completedAt ?? null,
|
|
608
|
+
metrics: t.metrics ?? null,
|
|
609
|
+
}));
|
|
610
|
+
|
|
611
|
+
return {
|
|
612
|
+
planId: plan.id,
|
|
613
|
+
status: plan.status,
|
|
614
|
+
executionSummary: plan.executionSummary ?? null,
|
|
615
|
+
taskMetrics,
|
|
616
|
+
};
|
|
617
|
+
} catch (err) {
|
|
618
|
+
return { error: (err as Error).message };
|
|
619
|
+
}
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
|
|
623
|
+
// ─── Record Task Metrics (#80) ──────────────────────────────
|
|
624
|
+
{
|
|
625
|
+
name: 'plan_record_task_metrics',
|
|
626
|
+
description:
|
|
627
|
+
'Record execution metrics for a task — tool calls, model tier, estimated cost. Merges with existing metrics.',
|
|
628
|
+
auth: 'write',
|
|
629
|
+
schema: z.object({
|
|
630
|
+
planId: z.string().describe('Plan ID'),
|
|
631
|
+
taskId: z.string().describe('Task ID to record metrics for'),
|
|
632
|
+
toolCalls: z.number().optional().describe('Number of tool calls made'),
|
|
633
|
+
modelTier: z.string().optional().describe('Model tier used (e.g., "opus", "sonnet")'),
|
|
634
|
+
estimatedCostUsd: z.number().optional().describe('Estimated cost in USD'),
|
|
635
|
+
iterations: z.number().optional().describe('Number of iterations taken'),
|
|
636
|
+
}),
|
|
637
|
+
handler: async (params) => {
|
|
638
|
+
try {
|
|
639
|
+
const plan = planner.get(params.planId as string);
|
|
640
|
+
if (!plan) return { error: `Plan not found: ${params.planId}` };
|
|
641
|
+
const task = plan.tasks.find((t) => t.id === params.taskId);
|
|
642
|
+
if (!task) return { error: `Task not found: ${params.taskId}` };
|
|
643
|
+
|
|
644
|
+
if (!task.metrics) task.metrics = {};
|
|
645
|
+
if (params.toolCalls !== undefined) task.metrics.toolCalls = params.toolCalls as number;
|
|
646
|
+
if (params.modelTier !== undefined) task.metrics.modelTier = params.modelTier as string;
|
|
647
|
+
if (params.estimatedCostUsd !== undefined)
|
|
648
|
+
task.metrics.estimatedCostUsd = params.estimatedCostUsd as number;
|
|
649
|
+
if (params.iterations !== undefined)
|
|
650
|
+
task.metrics.iterations = params.iterations as number;
|
|
651
|
+
|
|
652
|
+
task.updatedAt = Date.now();
|
|
653
|
+
plan.updatedAt = Date.now();
|
|
654
|
+
|
|
655
|
+
return {
|
|
656
|
+
recorded: true,
|
|
657
|
+
taskId: task.id,
|
|
658
|
+
metrics: task.metrics,
|
|
659
|
+
};
|
|
660
|
+
} catch (err) {
|
|
661
|
+
return { error: (err as Error).message };
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
},
|
|
665
|
+
|
|
666
|
+
// ─── Submit Deliverable (#83) ───────────────────────────────
|
|
667
|
+
{
|
|
668
|
+
name: 'plan_submit_deliverable',
|
|
669
|
+
description:
|
|
670
|
+
'Record a deliverable on a task. Auto-computes SHA-256 hash for file deliverables.',
|
|
671
|
+
auth: 'write',
|
|
672
|
+
schema: z.object({
|
|
673
|
+
planId: z.string().describe('Plan ID'),
|
|
674
|
+
taskId: z.string().describe('Task ID to attach deliverable to'),
|
|
675
|
+
type: z.enum(['file', 'vault_entry', 'url']).describe('Deliverable type'),
|
|
676
|
+
path: z.string().describe('File path, vault entry ID, or URL'),
|
|
677
|
+
}),
|
|
678
|
+
handler: async (params) => {
|
|
679
|
+
try {
|
|
680
|
+
const task = planner.submitDeliverable(params.planId as string, params.taskId as string, {
|
|
681
|
+
type: params.type as 'file' | 'vault_entry' | 'url',
|
|
682
|
+
path: params.path as string,
|
|
683
|
+
});
|
|
684
|
+
return {
|
|
685
|
+
submitted: true,
|
|
686
|
+
taskId: task.id,
|
|
687
|
+
deliverableCount: task.deliverables?.length ?? 0,
|
|
688
|
+
};
|
|
689
|
+
} catch (err) {
|
|
690
|
+
return { error: (err as Error).message };
|
|
691
|
+
}
|
|
692
|
+
},
|
|
693
|
+
},
|
|
694
|
+
|
|
695
|
+
// ─── Verify Deliverables (#83) ──────────────────────────────
|
|
696
|
+
{
|
|
697
|
+
name: 'plan_verify_deliverables',
|
|
698
|
+
description:
|
|
699
|
+
'Verify all deliverables for a task — checks file existence + SHA-256 hash match, vault entry existence. Returns stale count.',
|
|
700
|
+
auth: 'read',
|
|
701
|
+
schema: z.object({
|
|
702
|
+
planId: z.string().describe('Plan ID'),
|
|
703
|
+
taskId: z.string().describe('Task ID to verify deliverables for'),
|
|
704
|
+
}),
|
|
705
|
+
handler: async (params) => {
|
|
706
|
+
try {
|
|
707
|
+
return planner.verifyDeliverables(
|
|
708
|
+
params.planId as string,
|
|
709
|
+
params.taskId as string,
|
|
710
|
+
vault,
|
|
711
|
+
);
|
|
712
|
+
} catch (err) {
|
|
713
|
+
return { error: (err as Error).message };
|
|
714
|
+
}
|
|
715
|
+
},
|
|
716
|
+
},
|
|
326
717
|
];
|
|
327
718
|
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playbook Operations — 5 ops for playbook management.
|
|
3
|
+
*
|
|
4
|
+
* Existing ops (moved from core-ops.ts):
|
|
5
|
+
* playbook_list, playbook_get, playbook_create
|
|
6
|
+
*
|
|
7
|
+
* New ops:
|
|
8
|
+
* playbook_match — match playbooks by intent + text
|
|
9
|
+
* playbook_seed — seed built-in playbooks into vault
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import type { OpDefinition } from '../facades/types.js';
|
|
14
|
+
import type { AgentRuntime } from './types.js';
|
|
15
|
+
import { parsePlaybookFromEntry, validatePlaybook } from '../vault/playbook.js';
|
|
16
|
+
import {
|
|
17
|
+
matchPlaybooks,
|
|
18
|
+
seedDefaultPlaybooks,
|
|
19
|
+
entryToPlaybookDefinition,
|
|
20
|
+
} from '../playbooks/index.js';
|
|
21
|
+
import type { PlaybookIntent } from '../playbooks/index.js';
|
|
22
|
+
|
|
23
|
+
export function createPlaybookOps(runtime: AgentRuntime): OpDefinition[] {
|
|
24
|
+
const { vault } = runtime;
|
|
25
|
+
|
|
26
|
+
return [
|
|
27
|
+
// ─── playbook_list ──────────────────────────────────────────────
|
|
28
|
+
{
|
|
29
|
+
name: 'playbook_list',
|
|
30
|
+
description: 'List playbooks stored in the vault, optionally filtered by domain.',
|
|
31
|
+
auth: 'read',
|
|
32
|
+
schema: z.object({
|
|
33
|
+
domain: z.string().optional(),
|
|
34
|
+
limit: z.number().optional(),
|
|
35
|
+
}),
|
|
36
|
+
handler: async (params) => {
|
|
37
|
+
const entries = vault.list({
|
|
38
|
+
type: 'playbook',
|
|
39
|
+
domain: params.domain as string | undefined,
|
|
40
|
+
limit: (params.limit as number) ?? 50,
|
|
41
|
+
});
|
|
42
|
+
const playbooks = entries.map((e) => parsePlaybookFromEntry(e)).filter((p) => p !== null);
|
|
43
|
+
return { playbooks, count: playbooks.length };
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
// ─── playbook_get ───────────────────────────────────────────────
|
|
48
|
+
{
|
|
49
|
+
name: 'playbook_get',
|
|
50
|
+
description: 'Get a single playbook by ID, parsed into structured steps.',
|
|
51
|
+
auth: 'read',
|
|
52
|
+
schema: z.object({ id: z.string() }),
|
|
53
|
+
handler: async (params) => {
|
|
54
|
+
const entry = vault.get(params.id as string);
|
|
55
|
+
if (!entry) return { error: 'Playbook not found: ' + params.id };
|
|
56
|
+
if (entry.type !== 'playbook') return { error: 'Entry is not a playbook: ' + params.id };
|
|
57
|
+
const playbook = parsePlaybookFromEntry(entry);
|
|
58
|
+
if (!playbook) return { error: 'Failed to parse playbook context: ' + params.id };
|
|
59
|
+
return playbook;
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
// ─── playbook_create ────────────────────────────────────────────
|
|
64
|
+
{
|
|
65
|
+
name: 'playbook_create',
|
|
66
|
+
description:
|
|
67
|
+
'Create a playbook with structured steps. Validates step ordering and builds vault entry automatically.',
|
|
68
|
+
auth: 'write',
|
|
69
|
+
schema: z.object({
|
|
70
|
+
id: z.string().optional(),
|
|
71
|
+
title: z.string(),
|
|
72
|
+
domain: z.string(),
|
|
73
|
+
description: z.string(),
|
|
74
|
+
steps: z.array(
|
|
75
|
+
z.object({
|
|
76
|
+
title: z.string(),
|
|
77
|
+
description: z.string(),
|
|
78
|
+
validation: z.string().optional(),
|
|
79
|
+
}),
|
|
80
|
+
),
|
|
81
|
+
tags: z.array(z.string()).optional().default([]),
|
|
82
|
+
severity: z.enum(['critical', 'warning', 'suggestion']).optional().default('suggestion'),
|
|
83
|
+
}),
|
|
84
|
+
handler: async (params) => {
|
|
85
|
+
const title = params.title as string;
|
|
86
|
+
const domain = params.domain as string;
|
|
87
|
+
const rawSteps = params.steps as Array<{
|
|
88
|
+
title: string;
|
|
89
|
+
description: string;
|
|
90
|
+
validation?: string;
|
|
91
|
+
}>;
|
|
92
|
+
|
|
93
|
+
const steps = rawSteps.map((s, i) => ({ ...s, order: i + 1 }));
|
|
94
|
+
const id =
|
|
95
|
+
(params.id as string | undefined) ??
|
|
96
|
+
`playbook-${domain}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
97
|
+
|
|
98
|
+
const playbook = {
|
|
99
|
+
id,
|
|
100
|
+
title,
|
|
101
|
+
domain,
|
|
102
|
+
description: params.description as string,
|
|
103
|
+
steps,
|
|
104
|
+
tags: params.tags as string[],
|
|
105
|
+
createdAt: Date.now(),
|
|
106
|
+
updatedAt: Date.now(),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const validation = validatePlaybook(playbook);
|
|
110
|
+
if (!validation.valid) {
|
|
111
|
+
return { created: false, id, errors: validation.errors };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
vault.add({
|
|
115
|
+
id,
|
|
116
|
+
type: 'playbook',
|
|
117
|
+
domain,
|
|
118
|
+
title,
|
|
119
|
+
severity:
|
|
120
|
+
(params.severity as 'critical' | 'warning' | 'suggestion' | undefined) ?? 'suggestion',
|
|
121
|
+
description: params.description as string,
|
|
122
|
+
context: JSON.stringify({ steps }),
|
|
123
|
+
tags: params.tags as string[],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return { created: true, id, steps: steps.length };
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
// ─── playbook_match (NEW) ───────────────────────────────────────
|
|
131
|
+
{
|
|
132
|
+
name: 'playbook_match',
|
|
133
|
+
description:
|
|
134
|
+
'Match playbooks by intent and text. Combines vault-stored and built-in playbooks, returns best match with merged gates/tasks/tools.',
|
|
135
|
+
auth: 'read',
|
|
136
|
+
schema: z.object({
|
|
137
|
+
intent: z
|
|
138
|
+
.enum(['BUILD', 'FIX', 'REVIEW', 'PLAN', 'IMPROVE', 'DELIVER'])
|
|
139
|
+
.optional()
|
|
140
|
+
.describe('Plan intent for matching'),
|
|
141
|
+
text: z.string().describe('Plan objective + scope text to match against'),
|
|
142
|
+
}),
|
|
143
|
+
handler: async (params) => {
|
|
144
|
+
const intent = params.intent as PlaybookIntent | undefined;
|
|
145
|
+
const text = params.text as string;
|
|
146
|
+
|
|
147
|
+
// Load vault playbooks and convert to PlaybookDefinition
|
|
148
|
+
const vaultEntries = vault.list({ type: 'playbook', limit: 200 });
|
|
149
|
+
const vaultPlaybooks = vaultEntries
|
|
150
|
+
.map((e) => entryToPlaybookDefinition(e))
|
|
151
|
+
.filter((p): p is NonNullable<typeof p> => p !== null);
|
|
152
|
+
|
|
153
|
+
const result = matchPlaybooks(intent, text, vaultPlaybooks);
|
|
154
|
+
return result;
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
// ─── playbook_seed (NEW) ────────────────────────────────────────
|
|
159
|
+
{
|
|
160
|
+
name: 'playbook_seed',
|
|
161
|
+
description:
|
|
162
|
+
'Seed built-in playbooks into the vault. Idempotent — skips existing playbooks. Seeds 6 generic playbooks (TDD, brainstorming, code-review, subagent-execution, debugging, verification).',
|
|
163
|
+
auth: 'write',
|
|
164
|
+
handler: async () => {
|
|
165
|
+
return seedDefaultPlaybooks(vault);
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
];
|
|
169
|
+
}
|