moflo 4.9.20 → 4.9.22
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/.claude/agents/analysis/analyze-code-quality.md +0 -121
- package/.claude/agents/analysis/code-analyzer.md +5 -26
- package/.claude/agents/architecture/system-design/arch-system-design.md +0 -119
- package/.claude/agents/base-template-generator.md +0 -1
- package/.claude/agents/core/coder.md +0 -22
- package/.claude/agents/core/planner.md +0 -16
- package/.claude/agents/core/researcher.md +0 -16
- package/.claude/agents/core/reviewer.md +0 -17
- package/.claude/agents/core/tester.md +0 -19
- package/.claude/agents/custom/test-long-runner.md +0 -2
- package/.claude/agents/development/dev-backend-api.md +0 -167
- package/.claude/agents/development/dev-database.md +43 -0
- package/.claude/agents/development/dev-frontend.md +42 -0
- package/.claude/agents/devops/ci-cd/ops-cicd-github.md +0 -112
- package/.claude/agents/documentation/api-docs/docs-api-openapi.md +0 -111
- package/.claude/agents/security/security-auditor.md +45 -0
- package/.claude/guidance/shipped/moflo-agent-rules.md +172 -0
- package/.claude/guidance/shipped/moflo-claude-swarm-cohesion.md +73 -265
- package/.claude/guidance/shipped/moflo-cli-reference.md +6 -6
- package/.claude/guidance/shipped/moflo-core-guidance.md +66 -184
- package/.claude/guidance/shipped/moflo-cross-platform.md +1 -1
- package/.claude/guidance/shipped/moflo-error-handling.md +3 -3
- package/.claude/guidance/shipped/moflo-guidance-rules.md +17 -7
- package/.claude/guidance/shipped/moflo-memory-strategy.md +76 -182
- package/.claude/guidance/shipped/moflo-memorydb-maintenance.md +6 -8
- package/.claude/guidance/shipped/moflo-settings-injection.md +7 -9
- package/.claude/guidance/shipped/moflo-source-hygiene.md +5 -5
- package/.claude/guidance/shipped/moflo-spell-connectors.md +3 -4
- package/.claude/guidance/shipped/moflo-spell-custom-steps.md +3 -4
- package/.claude/guidance/shipped/moflo-spell-engine.md +40 -162
- package/.claude/guidance/shipped/moflo-spell-runner.md +134 -0
- package/.claude/guidance/shipped/moflo-spell-sandboxing.md +10 -57
- package/.claude/guidance/shipped/moflo-spell-troubleshooting.md +149 -0
- package/.claude/guidance/shipped/moflo-subagents.md +43 -114
- package/.claude/guidance/shipped/moflo-task-icons.md +4 -4
- package/.claude/guidance/shipped/moflo-user-facing-language.md +3 -3
- package/.claude/guidance/shipped/moflo-verbose-command-filtering.md +3 -3
- package/.claude/guidance/shipped/moflo-yaml-reference.md +4 -5
- package/.claude/helpers/gate.cjs +192 -15
- package/.claude/helpers/prompt-hook.mjs +4 -38
- package/.claude/helpers/simplify-classify.cjs +32 -11
- package/.claude/helpers/subagent-bootstrap.json +1 -1
- package/.claude/helpers/subagent-start.cjs +1 -1
- package/.claude/skills/connector-builder/SKILL.md +42 -429
- package/.claude/skills/connector-builder/templates/connector.md +189 -0
- package/.claude/skills/connector-builder/templates/step-command.md +176 -0
- package/.claude/skills/eldar/SKILL.md +7 -7
- package/.claude/skills/fl/SKILL.md +3 -3
- package/.claude/skills/fl/execution-modes.md +39 -16
- package/.claude/skills/fl/phases.md +3 -3
- package/.claude/skills/{simplify → flo-simplify}/SKILL.md +11 -11
- package/.claude/skills/guidance/SKILL.md +17 -9
- package/.claude/skills/memory-patterns/SKILL.md +1 -1
- package/.claude/skills/publish/SKILL.md +121 -36
- package/.claude/skills/reset-epic/SKILL.md +2 -2
- package/.claude/skills/spell-builder/SKILL.md +39 -226
- package/.claude/skills/spell-builder/architecture.md +1 -1
- package/.claude/skills/spell-builder/permissions.md +107 -0
- package/.claude/skills/spell-builder/preflight.md +101 -0
- package/.claude/skills/spell-schedule/SKILL.md +2 -3
- package/bin/gate.cjs +192 -15
- package/bin/lib/retired-files.mjs +146 -0
- package/bin/prompt-hook.mjs +4 -38
- package/bin/session-start-launcher.mjs +120 -1
- package/bin/setup-project.mjs +63 -69
- package/bin/simplify-classify.cjs +32 -11
- package/dist/src/cli/appliance/rvfa-builder.js +1 -1
- package/dist/src/cli/commands/agent.js +3 -9
- package/dist/src/cli/commands/doctor-checks-deep.js +4 -0
- package/dist/src/cli/commands/hooks.js +1 -3
- package/dist/src/cli/commands/index.js +2 -0
- package/dist/src/cli/commands/retire.js +111 -0
- package/dist/src/cli/hooks/reasoningbank/index.js +7 -7
- package/dist/src/cli/init/claudemd-generator.js +30 -33
- package/dist/src/cli/init/executor.js +53 -69
- package/dist/src/cli/init/helpers-generator.js +165 -52
- package/dist/src/cli/init/moflo-init.js +41 -114
- package/dist/src/cli/init/settings-generator.js +44 -14
- package/dist/src/cli/mcp-tools/agent-tools.js +9 -27
- package/dist/src/cli/mcp-tools/hooks-tools.js +23 -21
- package/dist/src/cli/memory/controllers/semantic-router.js +18 -12
- package/dist/src/cli/memory/sona-optimizer.js +6 -6
- package/dist/src/cli/neural/domain/services/learning-service.js +3 -3
- package/dist/src/cli/services/agent-router.js +2 -5
- package/dist/src/cli/services/hook-block-hash.js +11 -2
- package/dist/src/cli/services/hook-wiring.js +86 -3
- package/dist/src/cli/services/subagent-bootstrap.js +1 -1
- package/dist/src/cli/shared/events/example-usage.js +6 -6
- package/dist/src/cli/shared/hooks/task-hooks.js +8 -8
- package/dist/src/cli/version.js +1 -1
- package/package.json +3 -2
- package/retired-files.json +1989 -0
- package/scripts/post-install-bootstrap.mjs +19 -0
- package/src/cli/data/model-registry.json +2 -2
- package/.claude/agents/consensus/byzantine-coordinator.md +0 -63
- package/.claude/agents/consensus/crdt-synchronizer.md +0 -997
- package/.claude/agents/consensus/gossip-coordinator.md +0 -63
- package/.claude/agents/consensus/performance-benchmarker.md +0 -851
- package/.claude/agents/consensus/quorum-manager.md +0 -823
- package/.claude/agents/consensus/raft-manager.md +0 -63
- package/.claude/agents/consensus/security-manager.md +0 -622
- package/.claude/agents/data/ml/data-ml-model.md +0 -193
- package/.claude/agents/github/code-review-swarm.md +0 -538
- package/.claude/agents/github/github-modes.md +0 -172
- package/.claude/agents/github/issue-tracker.md +0 -311
- package/.claude/agents/github/multi-repo-swarm.md +0 -551
- package/.claude/agents/github/pr-manager.md +0 -183
- package/.claude/agents/github/project-board-sync.md +0 -508
- package/.claude/agents/github/release-manager.md +0 -360
- package/.claude/agents/github/release-swarm.md +0 -580
- package/.claude/agents/github/repo-architect.md +0 -391
- package/.claude/agents/github/swarm-issue.md +0 -566
- package/.claude/agents/github/swarm-pr.md +0 -414
- package/.claude/agents/github/sync-coordinator.md +0 -426
- package/.claude/agents/github/workflow-automation.md +0 -606
- package/.claude/agents/goal/code-goal-planner.md +0 -440
- package/.claude/agents/goal/goal-planner.md +0 -168
- package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +0 -127
- package/.claude/agents/hive-mind/queen-coordinator.md +0 -198
- package/.claude/agents/hive-mind/scout-explorer.md +0 -233
- package/.claude/agents/hive-mind/swarm-memory-manager.md +0 -184
- package/.claude/agents/hive-mind/worker-specialist.md +0 -208
- package/.claude/agents/neural/safla-neural.md +0 -73
- package/.claude/agents/optimization/benchmark-suite.md +0 -665
- package/.claude/agents/optimization/load-balancer.md +0 -431
- package/.claude/agents/optimization/performance-monitor.md +0 -672
- package/.claude/agents/optimization/resource-allocator.md +0 -674
- package/.claude/agents/optimization/topology-optimizer.md +0 -808
- package/.claude/agents/reasoning/goal-planner.md +0 -67
- package/.claude/agents/sona/sona-learning-optimizer.md +0 -74
- package/.claude/agents/sparc/architecture.md +0 -472
- package/.claude/agents/sparc/pseudocode.md +0 -318
- package/.claude/agents/sparc/refinement.md +0 -525
- package/.claude/agents/sparc/specification.md +0 -276
- package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +0 -225
- package/.claude/agents/swarm/adaptive-coordinator.md +0 -391
- package/.claude/agents/swarm/hierarchical-coordinator.md +0 -321
- package/.claude/agents/swarm/mesh-coordinator.md +0 -383
- package/.claude/agents/testing/production-validator.md +0 -395
- package/.claude/agents/testing/tdd-london-swarm.md +0 -244
- package/.claude/agents/v3/adr-architect.md +0 -184
- package/.claude/agents/v3/aidefence-guardian.md +0 -277
- package/.claude/agents/v3/claims-authorizer.md +0 -208
- package/.claude/agents/v3/collective-intelligence-coordinator.md +0 -988
- package/.claude/agents/v3/ddd-domain-expert.md +0 -220
- package/.claude/agents/v3/injection-analyst.md +0 -232
- package/.claude/agents/v3/memory-specialist.md +0 -987
- package/.claude/agents/v3/performance-engineer.md +0 -1225
- package/.claude/agents/v3/pii-detector.md +0 -146
- package/.claude/agents/v3/reasoningbank-learner.md +0 -213
- package/.claude/agents/v3/security-architect-aidefence.md +0 -405
- package/.claude/agents/v3/security-architect.md +0 -865
- package/.claude/agents/v3/security-auditor.md +0 -771
- package/.claude/agents/v3/sparc-orchestrator.md +0 -182
- package/.claude/agents/v3/swarm-memory-manager.md +0 -142
- package/.claude/agents/v3/v3-integration-architect.md +0 -205
- package/.claude/commands/claude-flow-help.md +0 -103
- package/.claude/commands/claude-flow-memory.md +0 -107
- package/.claude/commands/claude-flow-swarm.md +0 -205
- package/.claude/commands/github/README.md +0 -11
- package/.claude/commands/github/code-review-swarm.md +0 -514
- package/.claude/commands/github/code-review.md +0 -25
- package/.claude/commands/github/github-modes.md +0 -146
- package/.claude/commands/github/github-swarm.md +0 -113
- package/.claude/commands/github/issue-tracker.md +0 -284
- package/.claude/commands/github/issue-triage.md +0 -25
- package/.claude/commands/github/multi-repo-swarm.md +0 -519
- package/.claude/commands/github/pr-enhance.md +0 -26
- package/.claude/commands/github/pr-manager.md +0 -164
- package/.claude/commands/github/project-board-sync.md +0 -471
- package/.claude/commands/github/release-manager.md +0 -332
- package/.claude/commands/github/release-swarm.md +0 -544
- package/.claude/commands/github/repo-analyze.md +0 -25
- package/.claude/commands/github/repo-architect.md +0 -361
- package/.claude/commands/github/swarm-issue.md +0 -482
- package/.claude/commands/github/swarm-pr.md +0 -285
- package/.claude/commands/github/sync-coordinator.md +0 -294
- package/.claude/commands/github/workflow-automation.md +0 -442
- package/.claude/commands/hooks/README.md +0 -11
- package/.claude/commands/hooks/overview.md +0 -58
- package/.claude/commands/hooks/post-edit.md +0 -117
- package/.claude/commands/hooks/post-task.md +0 -112
- package/.claude/commands/hooks/pre-edit.md +0 -113
- package/.claude/commands/hooks/pre-task.md +0 -111
- package/.claude/commands/hooks/session-end.md +0 -118
- package/.claude/commands/hooks/setup.md +0 -103
- package/.claude/commands/simplify.md +0 -101
- package/.claude/commands/sparc/analyzer.md +0 -42
- package/.claude/commands/sparc/architect.md +0 -43
- package/.claude/commands/sparc/ask.md +0 -86
- package/.claude/commands/sparc/batch-executor.md +0 -44
- package/.claude/commands/sparc/code.md +0 -78
- package/.claude/commands/sparc/coder.md +0 -44
- package/.claude/commands/sparc/debug.md +0 -72
- package/.claude/commands/sparc/debugger.md +0 -44
- package/.claude/commands/sparc/designer.md +0 -43
- package/.claude/commands/sparc/devops.md +0 -98
- package/.claude/commands/sparc/docs-writer.md +0 -69
- package/.claude/commands/sparc/documenter.md +0 -44
- package/.claude/commands/sparc/innovator.md +0 -44
- package/.claude/commands/sparc/integration.md +0 -72
- package/.claude/commands/sparc/mcp.md +0 -106
- package/.claude/commands/sparc/memory-manager.md +0 -44
- package/.claude/commands/sparc/optimizer.md +0 -44
- package/.claude/commands/sparc/orchestrator.md +0 -116
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +0 -72
- package/.claude/commands/sparc/refinement-optimization-mode.md +0 -72
- package/.claude/commands/sparc/researcher.md +0 -44
- package/.claude/commands/sparc/reviewer.md +0 -44
- package/.claude/commands/sparc/security-review.md +0 -69
- package/.claude/commands/sparc/sparc-modes.md +0 -139
- package/.claude/commands/sparc/sparc.md +0 -99
- package/.claude/commands/sparc/spec-pseudocode.md +0 -69
- package/.claude/commands/sparc/spell-manager.md +0 -44
- package/.claude/commands/sparc/supabase-admin.md +0 -337
- package/.claude/commands/sparc/swarm-coordinator.md +0 -44
- package/.claude/commands/sparc/tdd.md +0 -44
- package/.claude/commands/sparc/tester.md +0 -44
- package/.claude/commands/sparc/tutorial.md +0 -68
- package/.claude/commands/sparc.md +0 -151
- package/.claude/guidance/shipped/moflo-session-start.md +0 -154
- package/.claude/guidance/shipped/moflo-spell-engine-architecture.md +0 -145
- package/.claude/skills/browser/SKILL.md +0 -204
- package/.claude/skills/github-code-review/SKILL.md +0 -1140
- package/.claude/skills/github-multi-repo/SKILL.md +0 -866
- package/.claude/skills/github-project-management/SKILL.md +0 -1272
- package/.claude/skills/github-release-management/SKILL.md +0 -1074
- package/.claude/skills/github-workflow-automation/SKILL.md +0 -1060
- package/.claude/skills/hive-mind-advanced/SKILL.md +0 -712
- package/.claude/skills/hooks-automation/SKILL.md +0 -1193
- package/.claude/skills/pair-programming/SKILL.md +0 -1202
- package/.claude/skills/performance-analysis/SKILL.md +0 -563
- package/.claude/skills/skill-builder/SKILL.md +0 -910
- package/.claude/skills/sparc-methodology/SKILL.md +0 -904
- package/.claude/skills/stream-chain/SKILL.md +0 -563
- package/.claude/skills/swarm-advanced/SKILL.md +0 -811
- package/.claude/skills/swarm-orchestration/SKILL.md +0 -179
- package/.claude/skills/verification-quality/SKILL.md +0 -649
- package/.claude/skills/worker-benchmarks/skill.md +0 -135
- package/.claude/skills/worker-integration/skill.md +0 -154
|
@@ -5,7 +5,17 @@ description: "Scaffold new spell step commands and connectors. Use when building
|
|
|
5
5
|
|
|
6
6
|
# Connector Builder
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Purpose: scaffold production-ready step commands (`StepCommand`) and, when truly needed, generalized I/O connectors (`SpellConnector`) with proper types, tests, and registration.
|
|
9
|
+
|
|
10
|
+
## Read First — Companion Files
|
|
11
|
+
|
|
12
|
+
| File | When to read |
|
|
13
|
+
|------|--------------|
|
|
14
|
+
| [templates/connector.md](templates/connector.md) | When generating a generalized connector — full source + test + registration scaffold |
|
|
15
|
+
| [templates/step-command.md](templates/step-command.md) | When generating a step command — full source + test + registration scaffold |
|
|
16
|
+
| [../spell-builder/architecture.md](../spell-builder/architecture.md) | **Always** — three-layer model and connector-vs-step decision tree |
|
|
17
|
+
| [../spell-builder/permissions.md](../spell-builder/permissions.md) | When defining capabilities — required disclosure format |
|
|
18
|
+
| [../spell-builder/preflight.md](../spell-builder/preflight.md) | When authoring preflight checks — copywriting rules for user-visible `reason` strings |
|
|
9
19
|
|
|
10
20
|
## Prerequisites
|
|
11
21
|
|
|
@@ -30,11 +40,9 @@ Ask the user:
|
|
|
30
40
|
> 1. **Step command** — executes logic within a spell step (transform data, control flow, etc.)
|
|
31
41
|
> 2. **Generalized connector** — wraps a new I/O transport type (e.g., WebSocket, gRPC, MQTT)
|
|
32
42
|
|
|
33
|
-
**Important:** Simple service integrations (Slack webhook, S3 upload, Jira comment) should compose existing connectors (`http`, `github-cli`, `playwright`) in spell YAML — no dedicated connector needed. However, platforms requiring complex multi-step browser interaction (like Outlook.com web UI) DO warrant a dedicated connector. See
|
|
34
|
-
|
|
35
|
-
**Documentation requirement:** When creating any new step command or connector, you MUST also create a README.md following `.claude/guidance/shipped/moflo-guidance-rules.md`. Use existing READMEs in `.claude/skills/spell-builder/steps/` or `connectors/` as templates. Apply automatically — the user should never need to ask.
|
|
43
|
+
**Important:** Simple service integrations (Slack webhook, S3 upload, Jira comment) should compose existing connectors (`http`, `github-cli`, `playwright`) in spell YAML — no dedicated connector needed. However, platforms requiring complex multi-step browser interaction (like Outlook.com web UI) DO warrant a dedicated connector. See [../spell-builder/architecture.md](../spell-builder/architecture.md) for the decision tree.
|
|
36
44
|
|
|
37
|
-
|
|
45
|
+
**Documentation requirement:** When creating any new step command or connector, you MUST also create a README.md following `.claude/guidance/moflo-guidance-rules.md`. Use existing READMEs in `.claude/skills/spell-builder/steps/` or `connectors/` as templates. Apply automatically — the user should never need to ask.
|
|
38
46
|
|
|
39
47
|
---
|
|
40
48
|
|
|
@@ -44,14 +52,12 @@ Then follow the appropriate section below.
|
|
|
44
52
|
|
|
45
53
|
### Step 1: Gather Requirements
|
|
46
54
|
|
|
47
|
-
Ask the user for:
|
|
48
|
-
|
|
49
55
|
| Field | Required | Example |
|
|
50
56
|
|-------|----------|---------|
|
|
51
57
|
| **Name** | Yes | `websocket`, `grpc`, `mqtt` |
|
|
52
58
|
| **Description** | Yes | `WebSocket bidirectional messaging` |
|
|
53
59
|
| **Version** | Yes (default `1.0.0`) | `1.0.0` |
|
|
54
|
-
| **Capabilities** | Yes
|
|
60
|
+
| **Capabilities** | Yes — pick from `read`, `write`, `search`, `subscribe`, `authenticate` | `read`, `write` |
|
|
55
61
|
| **Actions** | Yes (at least 1) | `connect`, `send`, `receive`, `close` |
|
|
56
62
|
|
|
57
63
|
For each action, ask:
|
|
@@ -60,195 +66,33 @@ For each action, ask:
|
|
|
60
66
|
- Input parameters (name, type, required?)
|
|
61
67
|
- Output fields (name, type)
|
|
62
68
|
|
|
63
|
-
**Verify the connector is generalized:**
|
|
64
|
-
|
|
65
|
-
### Step 2: Generate Connector Source
|
|
69
|
+
**Verify the connector is generalized:** the name should describe an I/O transport, not a service. `websocket` is correct; `slack` is not.
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Follow this template, using `github-cli.ts` as the reference implementation:
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
/**
|
|
73
|
-
* <Name> Workflow Connector
|
|
74
|
-
*
|
|
75
|
-
* <Description>
|
|
76
|
-
*
|
|
77
|
-
* Actions: <comma-separated action names>
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
import type {
|
|
81
|
-
SpellConnector,
|
|
82
|
-
ConnectorAction,
|
|
83
|
-
ConnectorOutput,
|
|
84
|
-
ConnectorCapability,
|
|
85
|
-
} from '../types/spell-connector.types.js';
|
|
86
|
-
|
|
87
|
-
export type <Name>Action = '<action-1>' | '<action-2>';
|
|
88
|
-
|
|
89
|
-
export const VALID_ACTIONS: readonly <Name>Action[] = [
|
|
90
|
-
'<action-1>', '<action-2>',
|
|
91
|
-
];
|
|
71
|
+
### Step 2: Disclose Permissions
|
|
92
72
|
|
|
93
|
-
|
|
94
|
-
params: Record<string, unknown>,
|
|
95
|
-
start: number,
|
|
96
|
-
): Promise<ConnectorOutput> {
|
|
97
|
-
// Implementation
|
|
98
|
-
return { success: true, data: { /* result */ }, duration: Date.now() - start };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function validate<Name>Action(
|
|
102
|
-
action: string,
|
|
103
|
-
params: Record<string, unknown>,
|
|
104
|
-
): string[] {
|
|
105
|
-
const errors: string[] = [];
|
|
106
|
-
if (!action || !VALID_ACTIONS.includes(action as <Name>Action)) {
|
|
107
|
-
errors.push(`action must be one of: ${VALID_ACTIONS.join(', ')}`);
|
|
108
|
-
return errors;
|
|
109
|
-
}
|
|
110
|
-
switch (action) {
|
|
111
|
-
case '<action-1>':
|
|
112
|
-
if (!params.<requiredParam>) errors.push('<action-1> requires <requiredParam>');
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
return errors;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const ACTIONS: ConnectorAction[] = [
|
|
119
|
-
{
|
|
120
|
-
name: '<action-1>',
|
|
121
|
-
description: '<action description>',
|
|
122
|
-
inputSchema: {
|
|
123
|
-
type: 'object',
|
|
124
|
-
properties: {
|
|
125
|
-
// Define input params with types and descriptions
|
|
126
|
-
},
|
|
127
|
-
required: ['<required-param>'],
|
|
128
|
-
},
|
|
129
|
-
outputSchema: {
|
|
130
|
-
type: 'object',
|
|
131
|
-
properties: {
|
|
132
|
-
// Define output fields
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
];
|
|
73
|
+
Before generating any source, surface the connector's capability profile to the user. Capabilities like `shell`, `fs:write`, `credentials`, `agent`, `net`, and `browser` carry specific risk classifications and required warning text. **See [../spell-builder/permissions.md](../spell-builder/permissions.md)** for the levels (`readonly`/`standard`/`elevated`/`autonomous`), risk classes (`[SAFE]`/`[SENSITIVE]`/`[DESTRUCTIVE]`), and the warning text to display per capability.
|
|
137
74
|
|
|
138
|
-
|
|
139
|
-
name: '<name>',
|
|
140
|
-
description: '<Description>',
|
|
141
|
-
version: '<version>',
|
|
142
|
-
capabilities: [<capabilities>] as readonly ConnectorCapability[],
|
|
143
|
-
|
|
144
|
-
async initialize(config: Record<string, unknown>): Promise<void> {
|
|
145
|
-
// Validate prerequisites (CLI tools, auth, API keys, etc.)
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
async dispose(): Promise<void> {
|
|
149
|
-
// Clean up connections/resources
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
async execute(action: string, params: Record<string, unknown>): Promise<ConnectorOutput> {
|
|
153
|
-
const start = Date.now();
|
|
154
|
-
const errors = validate<Name>Action(action, params);
|
|
155
|
-
if (errors.length > 0) {
|
|
156
|
-
return { success: false, data: {}, error: errors.join('; '), duration: Date.now() - start };
|
|
157
|
-
}
|
|
158
|
-
switch (action) {
|
|
159
|
-
case '<action-1>':
|
|
160
|
-
return execute<Action1>(params, start);
|
|
161
|
-
default:
|
|
162
|
-
return { success: false, data: {}, error: `Unknown action: ${action}`, duration: Date.now() - start };
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
listActions(): ConnectorAction[] {
|
|
167
|
-
return ACTIONS;
|
|
168
|
-
},
|
|
169
|
-
};
|
|
170
|
-
```
|
|
75
|
+
### Step 3: Generate Connector Source + Test
|
|
171
76
|
|
|
172
|
-
|
|
77
|
+
Use the full scaffold in [templates/connector.md](templates/connector.md). It implements the `SpellConnector` interface with all required pieces:
|
|
173
78
|
|
|
174
|
-
|
|
79
|
+
- `name`, `description`, `version`, `capabilities`
|
|
80
|
+
- Lifecycle methods: `initialize` and `dispose`
|
|
81
|
+
- `execute(action, params)` dispatcher
|
|
82
|
+
- `listActions()` schema reporter
|
|
83
|
+
- Per-action validation function
|
|
84
|
+
- Vitest test file with mocks
|
|
175
85
|
|
|
176
|
-
|
|
177
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
178
|
-
import { <name>Connector, validate<Name>Action } from
|
|
179
|
-
'../../../../src/cli/spells/connectors/<name>.js';
|
|
180
|
-
|
|
181
|
-
describe('<name>Connector', () => {
|
|
182
|
-
describe('metadata', () => {
|
|
183
|
-
it('has required properties', () => {
|
|
184
|
-
expect(<name>Connector.name).toBe('<name>');
|
|
185
|
-
expect(<name>Connector.description).toBeTruthy();
|
|
186
|
-
expect(<name>Connector.version).toMatch(/^\d+\.\d+\.\d+$/);
|
|
187
|
-
expect(<name>Connector.capabilities.length).toBeGreaterThan(0);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it('lists actions with schemas', () => {
|
|
191
|
-
const actions = <name>Connector.listActions();
|
|
192
|
-
expect(actions.length).toBeGreaterThan(0);
|
|
193
|
-
for (const action of actions) {
|
|
194
|
-
expect(action.name).toBeTruthy();
|
|
195
|
-
expect(action.description).toBeTruthy();
|
|
196
|
-
expect(action.inputSchema).toBeDefined();
|
|
197
|
-
expect(action.outputSchema).toBeDefined();
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
describe('validation', () => {
|
|
203
|
-
it('rejects unknown actions', () => {
|
|
204
|
-
const errors = validate<Name>Action('unknown', {});
|
|
205
|
-
expect(errors.length).toBeGreaterThan(0);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('validates required params for <action-1>', () => {
|
|
209
|
-
const errors = validate<Name>Action('<action-1>', {});
|
|
210
|
-
expect(errors.length).toBeGreaterThan(0);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it('accepts valid params for <action-1>', () => {
|
|
214
|
-
const errors = validate<Name>Action('<action-1>', { <requiredParam>: 'value' });
|
|
215
|
-
expect(errors).toEqual([]);
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
describe('execute', () => {
|
|
220
|
-
it('returns error for unknown action', async () => {
|
|
221
|
-
const result = await <name>Connector.execute('unknown', {});
|
|
222
|
-
expect(result.success).toBe(false);
|
|
223
|
-
expect(result.error).toContain('Unknown action');
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
// Add per-action execution tests with mocked externals
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
describe('lifecycle', () => {
|
|
230
|
-
it('initializes without error', async () => {
|
|
231
|
-
// Mock prerequisites as available
|
|
232
|
-
await expect(<name>Connector.initialize({})).resolves.not.toThrow();
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it('disposes without error', async () => {
|
|
236
|
-
await expect(<name>Connector.dispose()).resolves.not.toThrow();
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
```
|
|
86
|
+
The generated test file lives at `src/cli/__tests__/spells/<name>.test.ts`.
|
|
241
87
|
|
|
242
88
|
### Step 4: Register the Connector
|
|
243
89
|
|
|
244
|
-
Add to `src/cli/spells/connectors/index.ts
|
|
90
|
+
Add to `src/cli/spells/connectors/index.ts` so the engine discovers it:
|
|
245
91
|
|
|
246
92
|
```typescript
|
|
247
93
|
import { <name>Connector } from './<name>.js';
|
|
248
|
-
|
|
249
94
|
export { <name>Connector };
|
|
250
95
|
|
|
251
|
-
// Add to the builtinConnectors array:
|
|
252
96
|
export const builtinConnectors: SpellConnector[] = [
|
|
253
97
|
httpConnector,
|
|
254
98
|
githubCliConnector,
|
|
@@ -257,7 +101,7 @@ export const builtinConnectors: SpellConnector[] = [
|
|
|
257
101
|
];
|
|
258
102
|
```
|
|
259
103
|
|
|
260
|
-
### Step 5: Example
|
|
104
|
+
### Step 5: Example Spell YAML
|
|
261
105
|
|
|
262
106
|
```yaml
|
|
263
107
|
name: example-with-<name>
|
|
@@ -287,8 +131,6 @@ steps:
|
|
|
287
131
|
|
|
288
132
|
### Step 1: Gather Requirements
|
|
289
133
|
|
|
290
|
-
Ask the user for:
|
|
291
|
-
|
|
292
134
|
| Field | Required | Example |
|
|
293
135
|
|-------|----------|---------|
|
|
294
136
|
| **Type** | Yes (kebab-case) | `transform`, `notify`, `validate-schema` |
|
|
@@ -299,250 +141,23 @@ Ask the user for:
|
|
|
299
141
|
| **MoFlo level** | No (default `none`) | `none`, `memory`, `hooks`, `full`, `recursive` |
|
|
300
142
|
| **Prerequisites** | No | External CLI tools needed |
|
|
301
143
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
**After gathering capabilities, you MUST display the permission implications to the user.** Classify and show:
|
|
144
|
+
### Step 2: Disclose Permissions
|
|
305
145
|
|
|
306
|
-
|
|
307
|
-
- `readonly` (Read, Glob, Grep) — no `shell`, `fs:write`, `agent`, `net`, `browser` capabilities
|
|
308
|
-
- `standard` (Edit, Write, Read, Glob, Grep) — has `fs:write` or `agent` but not `shell`/`browser`
|
|
309
|
-
- `elevated` (Edit, Write, Bash, Read, Glob, Grep) — has `shell` or `browser`
|
|
310
|
-
- `autonomous` — requires explicit opt-in, never auto-derived
|
|
146
|
+
After gathering capabilities, you MUST display the permission implications to the user — same rules as the connector path. **See [../spell-builder/permissions.md](../spell-builder/permissions.md)** for the format and per-capability warnings. Steps using destructive capabilities will require user acceptance before first run via the spell-wide dry-run report.
|
|
311
147
|
|
|
312
|
-
|
|
313
|
-
- **[SAFE]** — `fs:read`, `memory` only
|
|
314
|
-
- **[SENSITIVE]** — `agent`, `net`, `browser`
|
|
315
|
-
- **[DESTRUCTIVE]** — `shell`, `fs:write`, `browser:evaluate`, `credentials`
|
|
148
|
+
### Step 3: Generate Step Command Source + Test
|
|
316
149
|
|
|
317
|
-
|
|
318
|
-
- `shell`: "Can execute arbitrary shell commands (rm, git push, etc.)"
|
|
319
|
-
- `fs:write`: "Can create, overwrite, or delete files on disk"
|
|
320
|
-
- `credentials`: "Can access stored secrets and API keys"
|
|
321
|
-
- `agent`: "Can spawn autonomous Claude sub-agents"
|
|
322
|
-
- `net`: "Can make network requests to external services"
|
|
150
|
+
Use the full scaffold in [templates/step-command.md](templates/step-command.md). It implements the `StepCommand<TConfig>` interface with all required pieces:
|
|
323
151
|
|
|
324
|
-
|
|
152
|
+
- `type`, `description`, `capabilities`, `defaultMofloLevel`
|
|
153
|
+
- `configSchema` (JSONSchema for runtime validation)
|
|
154
|
+
- `validate(config, context)` and `execute(config, context)` methods
|
|
155
|
+
- `describeOutputs()` for downstream variable references
|
|
156
|
+
- Optional `preflight` block — see [../spell-builder/preflight.md](../spell-builder/preflight.md) for `reason` copywriting rules
|
|
157
|
+
- Optional `rollback(config, context)` for failure cleanup
|
|
158
|
+
- Vitest test file with `mockContext`
|
|
325
159
|
|
|
326
|
-
|
|
327
|
-
Step command "deploy" capabilities:
|
|
328
|
-
[DESTRUCTIVE]
|
|
329
|
-
Permission level: elevated
|
|
330
|
-
Capabilities: shell, fs:write, fs:read
|
|
331
|
-
Warnings:
|
|
332
|
-
!! shell: Can execute arbitrary shell commands (rm, git push, etc.)
|
|
333
|
-
!! fs:write: Can create, overwrite, or delete files on disk
|
|
334
|
-
|
|
335
|
-
Steps using this command will require user acceptance before first run.
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
### Step 2: Generate Step Command Source
|
|
339
|
-
|
|
340
|
-
Create at `src/cli/spells/commands/<type>-command.ts`.
|
|
341
|
-
|
|
342
|
-
Follow this template, using `bash-command.ts` as the reference implementation:
|
|
343
|
-
|
|
344
|
-
```typescript
|
|
345
|
-
/**
|
|
346
|
-
* <Type> Step Command — <description>.
|
|
347
|
-
*/
|
|
348
|
-
|
|
349
|
-
import type {
|
|
350
|
-
StepCommand,
|
|
351
|
-
StepConfig,
|
|
352
|
-
StepOutput,
|
|
353
|
-
CastingContext,
|
|
354
|
-
ValidationResult,
|
|
355
|
-
OutputDescriptor,
|
|
356
|
-
JSONSchema,
|
|
357
|
-
StepCapability,
|
|
358
|
-
} from '../types/step-command.types.js';
|
|
359
|
-
|
|
360
|
-
/** Typed config for the <type> step command. */
|
|
361
|
-
export interface <Type>StepConfig extends StepConfig {
|
|
362
|
-
readonly <field1>: <type1>;
|
|
363
|
-
readonly <field2>?: <type2>;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
export const <type>Command: StepCommand<<Type>StepConfig> = {
|
|
367
|
-
type: '<type>',
|
|
368
|
-
description: '<Description>',
|
|
369
|
-
capabilities: [
|
|
370
|
-
// { type: 'fs:read' },
|
|
371
|
-
] as readonly StepCapability[],
|
|
372
|
-
defaultMofloLevel: 'none',
|
|
373
|
-
configSchema: {
|
|
374
|
-
type: 'object',
|
|
375
|
-
properties: {
|
|
376
|
-
<field1>: { type: '<json-type>', description: '<Field description>' },
|
|
377
|
-
<field2>: { type: '<json-type>', description: '<Field description>' },
|
|
378
|
-
},
|
|
379
|
-
required: ['<field1>'],
|
|
380
|
-
} satisfies JSONSchema,
|
|
381
|
-
|
|
382
|
-
validate(config: <Type>StepConfig): ValidationResult {
|
|
383
|
-
const errors = [];
|
|
384
|
-
if (!config.<field1> || typeof config.<field1> !== '<expected-type>') {
|
|
385
|
-
errors.push({ path: '<field1>', message: '<field1> is required and must be a <expected-type>' });
|
|
386
|
-
}
|
|
387
|
-
return { valid: errors.length === 0, errors };
|
|
388
|
-
},
|
|
389
|
-
|
|
390
|
-
async execute(config: <Type>StepConfig, context: CastingContext): Promise<StepOutput> {
|
|
391
|
-
const start = Date.now();
|
|
392
|
-
try {
|
|
393
|
-
// Implementation here
|
|
394
|
-
const result = {}; // compute result
|
|
395
|
-
|
|
396
|
-
return {
|
|
397
|
-
success: true,
|
|
398
|
-
data: { result },
|
|
399
|
-
duration: Date.now() - start,
|
|
400
|
-
};
|
|
401
|
-
} catch (err) {
|
|
402
|
-
return {
|
|
403
|
-
success: false,
|
|
404
|
-
data: {},
|
|
405
|
-
error: err instanceof Error ? err.message : String(err),
|
|
406
|
-
duration: Date.now() - start,
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
},
|
|
410
|
-
|
|
411
|
-
describeOutputs(): OutputDescriptor[] {
|
|
412
|
-
return [
|
|
413
|
-
{ name: 'result', type: 'object', description: 'The computed result' },
|
|
414
|
-
];
|
|
415
|
-
},
|
|
416
|
-
|
|
417
|
-
// Optional: runtime preflight checks — run BEFORE any step executes.
|
|
418
|
-
// Use for validating runtime state (issue open, service reachable, etc).
|
|
419
|
-
// CRITICAL: the `reason` string IS the message the end user sees.
|
|
420
|
-
// Write it in plain English. State the problem AND the fix. No tool
|
|
421
|
-
// jargon, no exit codes, no internal identifiers.
|
|
422
|
-
//
|
|
423
|
-
// Default severity is 'fatal' (abort on failure). Set severity: 'warning'
|
|
424
|
-
// + resolutions when the user can safely choose how to proceed; in
|
|
425
|
-
// interactive runs they'll be prompted, in non-interactive runs warnings
|
|
426
|
-
// behave like fatals.
|
|
427
|
-
//
|
|
428
|
-
// preflight: [
|
|
429
|
-
// {
|
|
430
|
-
// name: '<service> reachable',
|
|
431
|
-
// severity: 'fatal',
|
|
432
|
-
// check: async (config, ctx) => {
|
|
433
|
-
// const ok = await ping(config.endpoint);
|
|
434
|
-
// if (ok) return { passed: true };
|
|
435
|
-
// return {
|
|
436
|
-
// passed: false,
|
|
437
|
-
// reason: `Can't reach ${config.endpoint}. Check your network connection or the service URL in your spell config.`,
|
|
438
|
-
// };
|
|
439
|
-
// },
|
|
440
|
-
// },
|
|
441
|
-
// {
|
|
442
|
-
// name: 'local cache fresh',
|
|
443
|
-
// severity: 'warning',
|
|
444
|
-
// resolutions: [
|
|
445
|
-
// { label: 'Refresh the cache now', command: '<type>-cli cache refresh' },
|
|
446
|
-
// { label: 'Continue with stale cache' },
|
|
447
|
-
// ],
|
|
448
|
-
// check: async (config) => {
|
|
449
|
-
// const stale = await isCacheStale(config.endpoint);
|
|
450
|
-
// return stale
|
|
451
|
-
// ? { passed: false, reason: 'Your local cache is more than 24 hours old and may produce outdated results.' }
|
|
452
|
-
// : { passed: true };
|
|
453
|
-
// },
|
|
454
|
-
// },
|
|
455
|
-
// ],
|
|
456
|
-
|
|
457
|
-
// Optional: rollback on failure
|
|
458
|
-
// async rollback(config, context) { /* undo side effects */ },
|
|
459
|
-
};
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
Alternatively, use the `createStepCommand()` factory from `src/cli/spells/commands/create-step-command.ts` for compile-time type safety.
|
|
463
|
-
|
|
464
|
-
#### Preflight `reason` strings — write for humans
|
|
465
|
-
|
|
466
|
-
When your step declares `preflight` checks, the `reason` string returned on failure is shown verbatim to end users as the error message. Treat it as user-facing copy:
|
|
467
|
-
|
|
468
|
-
- Plain English, no command names, exit codes, or internal identifiers.
|
|
469
|
-
- State BOTH the problem and the fix.
|
|
470
|
-
- Assume a non-technical reader.
|
|
471
|
-
|
|
472
|
-
Good: `"You're not signed in to GitHub. Run: gh auth login"`
|
|
473
|
-
Bad: `"gh auth status exited with code 1"` — leaks implementation detail
|
|
474
|
-
Bad: `"auth check failed"` — tells the user nothing actionable
|
|
475
|
-
|
|
476
|
-
### Step 3: Generate Step Command Test
|
|
477
|
-
|
|
478
|
-
Create at `tests/packages/spells/commands/<type>-command.test.ts`:
|
|
479
|
-
|
|
480
|
-
```typescript
|
|
481
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
482
|
-
import { <type>Command } from
|
|
483
|
-
'../../../../src/cli/spells/commands/<type>-command.js';
|
|
484
|
-
import type { CastingContext } from
|
|
485
|
-
'../../../../src/cli/spells/types/step-command.types.js';
|
|
486
|
-
|
|
487
|
-
const mockContext: CastingContext = {
|
|
488
|
-
variables: {},
|
|
489
|
-
args: {},
|
|
490
|
-
credentials: { get: vi.fn(), has: vi.fn() },
|
|
491
|
-
memory: { read: vi.fn(), write: vi.fn(), search: vi.fn() },
|
|
492
|
-
taskId: 'test-task',
|
|
493
|
-
spellId: 'test-spell',
|
|
494
|
-
stepIndex: 0,
|
|
495
|
-
};
|
|
496
|
-
|
|
497
|
-
describe('<type>Command', () => {
|
|
498
|
-
describe('metadata', () => {
|
|
499
|
-
it('has required properties', () => {
|
|
500
|
-
expect(<type>Command.type).toBe('<type>');
|
|
501
|
-
expect(<type>Command.description).toBeTruthy();
|
|
502
|
-
expect(<type>Command.configSchema).toBeDefined();
|
|
503
|
-
expect(<type>Command.configSchema.required).toContain('<field1>');
|
|
504
|
-
});
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
describe('validate', () => {
|
|
508
|
-
it('rejects missing required fields', () => {
|
|
509
|
-
const result = <type>Command.validate({} as any, mockContext);
|
|
510
|
-
expect(result.valid).toBe(false);
|
|
511
|
-
expect(result.errors.length).toBeGreaterThan(0);
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
it('accepts valid config', () => {
|
|
515
|
-
const result = <type>Command.validate(
|
|
516
|
-
{ <field1>: '<valid-value>' } as any,
|
|
517
|
-
mockContext,
|
|
518
|
-
);
|
|
519
|
-
expect(result.valid).toBe(true);
|
|
520
|
-
});
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
describe('execute', () => {
|
|
524
|
-
it('succeeds with valid config', async () => {
|
|
525
|
-
const result = await <type>Command.execute(
|
|
526
|
-
{ <field1>: '<valid-value>' } as any,
|
|
527
|
-
mockContext,
|
|
528
|
-
);
|
|
529
|
-
expect(result.success).toBe(true);
|
|
530
|
-
expect(result.duration).toBeGreaterThanOrEqual(0);
|
|
531
|
-
});
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
describe('describeOutputs', () => {
|
|
535
|
-
it('returns output descriptors', () => {
|
|
536
|
-
const outputs = <type>Command.describeOutputs();
|
|
537
|
-
expect(outputs.length).toBeGreaterThan(0);
|
|
538
|
-
for (const output of outputs) {
|
|
539
|
-
expect(output.name).toBeTruthy();
|
|
540
|
-
expect(output.type).toBeTruthy();
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
});
|
|
544
|
-
});
|
|
545
|
-
```
|
|
160
|
+
For compile-time type safety on the config, prefer the `createStepCommand()` factory from `src/cli/spells/commands/create-step-command.ts`.
|
|
546
161
|
|
|
547
162
|
### Step 4: Register the Step Command
|
|
548
163
|
|
|
@@ -550,11 +165,9 @@ Add to `src/cli/spells/commands/index.ts`:
|
|
|
550
165
|
|
|
551
166
|
```typescript
|
|
552
167
|
import { <type>Command } from './<type>-command.js';
|
|
553
|
-
|
|
554
168
|
export { <type>Command };
|
|
555
169
|
export type { <Type>StepConfig } from './<type>-command.js';
|
|
556
170
|
|
|
557
|
-
// Add to the builtinCommands array:
|
|
558
171
|
export const builtinCommands: readonly StepCommand[] = [
|
|
559
172
|
agentCommand,
|
|
560
173
|
bashCommand,
|
|
@@ -563,7 +176,7 @@ export const builtinCommands: readonly StepCommand[] = [
|
|
|
563
176
|
];
|
|
564
177
|
```
|
|
565
178
|
|
|
566
|
-
### Step 5: Example
|
|
179
|
+
### Step 5: Example Spell YAML
|
|
567
180
|
|
|
568
181
|
```yaml
|
|
569
182
|
name: example-with-<type>
|
|
@@ -596,4 +209,4 @@ steps:
|
|
|
596
209
|
|
|
597
210
|
### Related Skills
|
|
598
211
|
|
|
599
|
-
- [/spell-builder](../spell-builder/)
|
|
212
|
+
- [/spell-builder](../spell-builder/) — composes connectors and steps into spell definitions; references this skill when a needed connector doesn't exist
|