@zibby/skills 0.1.7 → 0.1.9

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.
@@ -0,0 +1,119 @@
1
+ # Workflow Artifact Layout Evaluation
2
+
3
+ ## Context
4
+
5
+ Current workflow authoring is centered on hidden project files under `.zibby/`:
6
+
7
+ - `.zibby/graph.mjs`
8
+ - `.zibby/nodes/*`
9
+ - `.zibby/chat.mjs`
10
+ - `.zibby/result-handler.mjs`
11
+ - runtime output in `.zibby/output/sessions/*`
12
+
13
+ The product direction is to support live workflow creation via `zibby chat` and local/remote arbitrary workflow execution, while keeping user-authored workflow code commit-friendly.
14
+
15
+ ## Options
16
+
17
+ ### Option A: Keep everything in hidden `.zibby/`
18
+
19
+ Pros:
20
+ - No migration needed.
21
+ - Fully compatible with current Studio/CLI assumptions.
22
+
23
+ Cons:
24
+ - User-authored workflow source remains hidden and less discoverable.
25
+ - Weaker commit ergonomics for user-owned workflow code.
26
+
27
+ ### Option B: Move everything to visible `zibby/`
28
+
29
+ Pros:
30
+ - Clear, commit-friendly source-of-truth for workflow code.
31
+ - Better UX for editing workflow artifacts directly.
32
+
33
+ Cons:
34
+ - High migration cost.
35
+ - Breaks many path assumptions in Studio bridge, Electron, docs, and integrations.
36
+ - Requires dual-path compatibility window to avoid immediate breakage.
37
+
38
+ ### Option C: Hybrid (recommended)
39
+
40
+ Store user-authored workflow source in visible `zibby/`, keep runtime/output in hidden `.zibby/output`.
41
+
42
+ Pros:
43
+ - Commit-friendly source artifacts.
44
+ - Preserves hidden runtime/cache/output behavior.
45
+ - Smaller migration blast radius than full move.
46
+
47
+ Cons:
48
+ - Requires resolver precedence logic and migration tooling.
49
+ - Transitional complexity (legacy `.zibby` source + new `zibby` source).
50
+
51
+ ### Option D: Hybrid + configurable path in `.zibby.config.mjs`
52
+
53
+ Same as Option C, but adds explicit config override for source workflow path.
54
+
55
+ Pros:
56
+ - Flexible for monorepos and custom project conventions.
57
+ - Future-proofs enterprise setups.
58
+
59
+ Cons:
60
+ - Slightly larger surface area and testing burden.
61
+
62
+ ## Impact Map (Current Coupling)
63
+
64
+ Key areas that currently assume hidden-source and/or hidden-output conventions:
65
+
66
+ - `studio/electron/main.js`
67
+ - project-root detection uses `.zibby/graph.mjs`
68
+ - default sessions root uses `.zibby/output/sessions`
69
+ - `studio/vite.config.js`
70
+ - bridge fallbacks for session/output discovery
71
+ - `studio/src/adapters/platform.js`
72
+ - APIs and comments assume `.zibby/output/sessions`
73
+ - `docsite/docs/*`
74
+ - user docs describe hidden `.zibby` workflow/source model
75
+
76
+ Secondary impacts:
77
+
78
+ - integrations under `integrations/*` referencing current command/path patterns
79
+ - helper comments and UI command snippets across Studio/frontend
80
+
81
+ ## Recommended Migration Strategy
82
+
83
+ ### Phase 1 (compatibility, no breakage)
84
+
85
+ - Keep `.zibby/` source loading as primary behavior.
86
+ - Add support for visible `zibby/` source layout in resolvers.
87
+ - Resolver precedence:
88
+ 1. explicit config path (if set)
89
+ 2. `zibby/` source
90
+ 3. legacy `.zibby/` source
91
+ - Keep runtime output in `.zibby/output`.
92
+
93
+ ### Phase 2 (opt-in default shift)
94
+
95
+ - New projects scaffold workflow source under `zibby/`.
96
+ - Existing projects continue to work with `.zibby/`.
97
+ - Add migration helper command to copy/move source artifacts safely.
98
+
99
+ ### Phase 3 (deprecation)
100
+
101
+ - Emit warnings for legacy hidden-source layouts.
102
+ - After a compatibility window, finalize the preferred source layout.
103
+ - Continue hidden runtime/output unless there is strong product need to change it.
104
+
105
+ ## Suggested Source/Runtime Split
106
+
107
+ - User-authored source (commit-friendly):
108
+ - `zibby/graph.mjs`
109
+ - `zibby/nodes/*`
110
+ - `zibby/chat.mjs`
111
+ - `zibby/result-handler.mjs`
112
+ - Runtime/cache/output (hidden):
113
+ - `.zibby/output/*`
114
+ - `.zibby/scratch/*`
115
+ - `.zibby/memory/*`
116
+
117
+ ## Why this recommendation
118
+
119
+ Hybrid with configuration gives the best balance: user-visible source for authoring and version control, while preserving stable hidden runtime/output semantics already used by Studio, CLI, and integrations.
@@ -0,0 +1,558 @@
1
+ ---
2
+ sidebar_position: 4
3
+ title: Workflow Engine
4
+ ---
5
+
6
+ # Workflow Engine
7
+
8
+ Zibby's workflow engine is a **graph-based orchestration system for AI agents**, inspired by [LangGraph](https://github.com/langchain-ai/langgraph) but designed to be **agent-agnostic**. The same workflow definition runs identically on Cursor, Claude, or Codex — you switch agents with a single flag, not by rewriting your pipeline.
9
+
10
+ ## Core Concepts
11
+
12
+ ### Graph = Nodes + Edges + State
13
+
14
+ A workflow is a directed graph where:
15
+
16
+ - **Nodes** — individual steps (AI calls, data transformations, tool usage)
17
+ - **Edges** — connections between nodes (linear or conditional)
18
+ - **State** — a shared key-value store that flows through the graph; every node reads from and writes to it
19
+
20
+ ```
21
+ ┌──────────┐ ┌──────────────┐ ┌─────────────────┐
22
+ │ preflight│────▶│ execute_live │────▶│ generate_script │───▶ END
23
+ └──────────┘ └──────────────┘ └─────────────────┘
24
+
25
+ ▼ (conditional)
26
+ END
27
+ (no actions recorded)
28
+ ```
29
+
30
+ ### Agent-Agnostic Design
31
+
32
+ The workflow framework never calls a specific AI provider directly. Instead, it uses a **Strategy Pattern**:
33
+
34
+ 1. Each agent (Cursor, Claude, Codex) implements the `AgentStrategy` base class
35
+ 2. The `invokeAgent()` function selects the right strategy at runtime based on your config
36
+ 3. Nodes call `invokeAgent()` — they never know which provider executes the prompt
37
+
38
+ This means:
39
+ - Workflows are **portable** across agents
40
+ - Skills (MCP tools) are resolved per-agent automatically
41
+ - You can override the model per-node in config without touching workflow code
42
+
43
+ ```javascript
44
+ // .zibby.config.js — switch agent with one line
45
+ export default {
46
+ agent: {
47
+ cursor: { model: 'auto' },
48
+ // claude: { model: 'sonnet-4.6' },
49
+ // codex: { model: 'gpt-5.2-codex' },
50
+ }
51
+ };
52
+ ```
53
+
54
+ ### Three Supported Agents
55
+
56
+ | Agent | SDK | MCP Integration | Structured Output |
57
+ |---|---|---|---|
58
+ | **Cursor** | cursor-agent CLI / API | MCP servers via `~/.cursor/mcp.json` | JSON extraction from response |
59
+ | **Claude** | `@anthropic-ai/claude-agent-sdk` | Native MCP tool_use with `allowedTools` | Zod schema → SDK structured output |
60
+ | **Codex** | `@openai/codex-sdk` | `mcp_servers` config in SDK | Zod → JSON Schema via `outputSchema` |
61
+
62
+ All three implement the same interface:
63
+
64
+ ```javascript
65
+ class AgentStrategy {
66
+ canHandle(context) // Is this agent available?
67
+ invoke(prompt, options) // Execute prompt with tools + schema
68
+ getName() // 'cursor' | 'claude' | 'codex'
69
+ }
70
+ ```
71
+
72
+ ## Building a Workflow
73
+
74
+ ### The Built-in Default: Browser Test Automation
75
+
76
+ When you run `zibby test test.txt`, the CLI uses the built-in `BrowserTestAutomationAgent` workflow — no init or config needed:
77
+
78
+ ```javascript
79
+ import { WorkflowAgent, WorkflowGraph } from '@zibby/core';
80
+ import { preflightNode, executeLiveNode, generateScriptNode } from './nodes/index.mjs';
81
+
82
+ export class BrowserTestAutomationAgent extends WorkflowAgent {
83
+ buildGraph() {
84
+ const graph = new WorkflowGraph();
85
+
86
+ graph.addNode('preflight', preflightNode);
87
+ graph.addNode('execute_live', executeLiveNode);
88
+ graph.addNode('generate_script', generateScriptNode);
89
+
90
+ graph.setEntryPoint('preflight');
91
+ graph.addEdge('preflight', 'execute_live');
92
+
93
+ graph.addConditionalEdges('execute_live', (state) => {
94
+ const result = state.execute_live;
95
+ const hasExecution = (result?.steps?.length > 0) || (result?.actions?.length > 0);
96
+ return hasExecution ? 'generate_script' : 'END';
97
+ });
98
+
99
+ graph.addEdge('generate_script', 'END');
100
+ return graph;
101
+ }
102
+
103
+ async onComplete(result) {
104
+ // Save artifacts, push to memory, etc.
105
+ }
106
+ }
107
+ ```
108
+
109
+ **What each node does:**
110
+
111
+ | Node | Type | Skills | Purpose |
112
+ |---|---|---|---|
113
+ | `preflight` | Prompt-only (no tools) | — | Reads test spec, extracts title + assertion checklist via LLM |
114
+ | `execute_live` | Tool-using | Browser, Memory | AI drives a real browser, fills forms, clicks, captures selectors |
115
+ | `generate_script` | Prompt-only | — | Converts recorded actions into a reusable Playwright `.spec.js` |
116
+
117
+ ### Custom Workflows via `zibby init`
118
+
119
+ Scaffold a customizable workflow into your project:
120
+
121
+ ```bash
122
+ zibby init --agent cursor
123
+ ```
124
+
125
+ This creates:
126
+
127
+ ```
128
+ .zibby.config.js # Project configuration
129
+ .zibby/
130
+ ├── graph.js # Workflow graph (nodes + edges)
131
+ ├── nodes/
132
+ │ ├── preflight.js # Extract title + assertions
133
+ │ ├── execute-live.js # AI drives browser
134
+ │ └── generate-script.js # Generate Playwright script
135
+ └── result-handler.js # Post-execution artifact saving
136
+ ```
137
+
138
+ You can then modify any node, add new nodes, or change the graph structure.
139
+
140
+ ## WorkflowGraph API
141
+
142
+ ### Creating a Graph
143
+
144
+ ```javascript
145
+ import { WorkflowGraph, Node } from '@zibby/core';
146
+
147
+ const graph = new WorkflowGraph({
148
+ stateSchema: MyZodSchema, // Optional: Zod schema for state validation
149
+ middleware: [myMiddleware], // Optional: middleware functions
150
+ });
151
+ ```
152
+
153
+ ### Adding Nodes
154
+
155
+ ```javascript
156
+ // Simple node with prompt function + output schema
157
+ graph.addNode('my_node', {
158
+ name: 'my_node',
159
+ prompt: (state) => `Analyze: ${state.testSpec}`,
160
+ outputSchema: z.object({
161
+ title: z.string(),
162
+ items: z.array(z.string()),
163
+ }),
164
+ });
165
+
166
+ // Node with skills (MCP tools)
167
+ graph.addNode('browser_step', {
168
+ name: 'browser_step',
169
+ skills: [SKILLS.BROWSER, SKILLS.MEMORY],
170
+ prompt: (state) => `Execute: ${state.testSpec}`,
171
+ outputSchema: ExecutionSchema,
172
+ timeout: 600000,
173
+ });
174
+
175
+ // Node with custom execute (no LLM call)
176
+ graph.addNode('transform', {
177
+ name: 'transform',
178
+ _isCustomCode: true,
179
+ execute: async (context) => {
180
+ const data = context.state.get('raw_data');
181
+ return { cleaned: data.trim(), wordCount: data.split(' ').length };
182
+ },
183
+ outputSchema: TransformSchema,
184
+ });
185
+ ```
186
+
187
+ ### Wiring Edges
188
+
189
+ ```javascript
190
+ // Linear flow
191
+ graph.setEntryPoint('step_a');
192
+ graph.addEdge('step_a', 'step_b');
193
+ graph.addEdge('step_b', 'step_c');
194
+ graph.addEdge('step_c', 'END');
195
+
196
+ // Conditional branching
197
+ graph.addConditionalEdges('step_b', (state) => {
198
+ return state.step_b.success ? 'step_c' : 'error_handler';
199
+ });
200
+ ```
201
+
202
+ ### Running the Graph
203
+
204
+ ```javascript
205
+ const result = await graph.run(agent, {
206
+ testSpec: 'Go to example.com and verify the title',
207
+ cwd: process.cwd(),
208
+ config: { agent: { cursor: { model: 'auto' } } },
209
+ });
210
+
211
+ console.log(result.success); // true
212
+ console.log(result.state.preflight); // { title: '...', assertions: [...] }
213
+ console.log(result.executionLog); // [{ node, success, duration }, ...]
214
+ ```
215
+
216
+ ## Node Anatomy
217
+
218
+ Every node has three key parts:
219
+
220
+ ### 1. Prompt
221
+
222
+ A function or string template that receives the current state and produces the LLM prompt:
223
+
224
+ ```javascript
225
+ prompt: (state) => `
226
+ Test spec: ${state.testSpec}
227
+ Previous results: ${JSON.stringify(state.preflight)}
228
+
229
+ Execute the test and return structured results.
230
+ `
231
+ ```
232
+
233
+ Nodes can also use Handlebars templates when configured with a `prompt` option:
234
+
235
+ ```javascript
236
+ graph.addNode('my_node', nodeImpl, {
237
+ prompt: `Analyze {{testSpec}} and produce {{outputFormat}} results`
238
+ });
239
+ ```
240
+
241
+ ### 2. Output Schema (Zod)
242
+
243
+ Every node declares a Zod schema for its output. The framework validates the AI response against it:
244
+
245
+ ```javascript
246
+ import { z } from '@zibby/core';
247
+
248
+ const MyOutputSchema = z.object({
249
+ title: z.string().describe('Concise test title'),
250
+ assertions: z.array(z.object({
251
+ description: z.string(),
252
+ expected: z.string(),
253
+ })),
254
+ });
255
+
256
+ export const myNode = {
257
+ name: 'my_node',
258
+ outputSchema: MyOutputSchema,
259
+ prompt: (state) => '...',
260
+ };
261
+ ```
262
+
263
+ The schema serves three purposes:
264
+ - **Runtime validation** — the LLM response is parsed and validated against the schema
265
+ - **Structured output** — Claude and Codex agents use the schema for native structured output (no JSON extraction needed)
266
+ - **State contract** — downstream nodes know exactly what shape to expect from upstream output
267
+
268
+ ### 3. Skills
269
+
270
+ Skills declare what MCP tools a node needs. The framework resolves the right MCP server per-agent:
271
+
272
+ ```javascript
273
+ import { SKILLS } from '@zibby/core';
274
+
275
+ export const executeLiveNode = {
276
+ name: 'execute_live',
277
+ skills: [SKILLS.BROWSER, SKILLS.MEMORY],
278
+ // ...
279
+ };
280
+ ```
281
+
282
+ Available built-in skills: `BROWSER`, `JIRA`, `GITHUB`, `SLACK`, `MEMORY`.
283
+
284
+ ## State Management
285
+
286
+ State is a shared key-value store managed by `WorkflowState`. Each node's output is automatically stored under its name:
287
+
288
+ ```javascript
289
+ // After preflight runs:
290
+ state.get('preflight') // → { title: '...', assertions: [...] }
291
+
292
+ // After execute_live runs:
293
+ state.get('execute_live') // → { success: true, steps: [...], actions: [...] }
294
+ ```
295
+
296
+ Built-in state keys:
297
+
298
+ | Key | Type | Description |
299
+ |---|---|---|
300
+ | `messages` | `Array` | Accumulated messages |
301
+ | `errors` | `Array` | Error records `{ node, error }` |
302
+ | `artifacts` | `Object` | Generated artifacts |
303
+ | `config` | `Object` | Resolved `.zibby.config.js` |
304
+ | `agentType` | `string` | Active agent (`cursor`, `claude`, `codex`) |
305
+ | `sessionPath` | `string` | Path to session output directory |
306
+ | `context` | `Object` | Loaded context files (CONTEXT.md, AGENTS.md, env) |
307
+ | `testSpec` | `string` | The test specification text |
308
+ | `<node_name>` | `Object` | Each node's validated output |
309
+
310
+ State supports history and rollback:
311
+
312
+ ```javascript
313
+ state.set('key', 'value');
314
+ state.update({ a: 1, b: 2 });
315
+ state.append('errors', { node: 'x', error: 'failed' });
316
+ state.rollback(); // Undo last mutation
317
+ ```
318
+
319
+ ## Graph Compiler
320
+
321
+ Zibby includes a **graph compiler** that takes a serialized JSON graph (from the dashboard's visual editor) and compiles it into an executable `WorkflowGraph`:
322
+
323
+ ```javascript
324
+ import { compileGraph, validateGraphConfig } from '@zibby/core';
325
+
326
+ // Validate before compiling
327
+ const { valid, errors } = validateGraphConfig(graphJson);
328
+
329
+ // Compile JSON → executable graph
330
+ const graph = compileGraph(graphJson, {
331
+ stateSchema: MySchema,
332
+ middleware: [memoryMiddleware],
333
+ });
334
+
335
+ await graph.run(agent, initialState);
336
+ ```
337
+
338
+ The compiler handles:
339
+ - **Node resolution** — maps node types to registered implementations
340
+ - **Decision nodes** — collapses visual decision diamonds into `addConditionalEdges`
341
+ - **Custom code** — safely compiles inline JavaScript from the visual editor
342
+ - **Tool resolution** — wires MCP tool permissions per node
343
+ - **Entry point detection** — finds the node with no incoming edges
344
+
345
+ ## Middleware
346
+
347
+ Middleware wraps every node execution, enabling cross-cutting concerns:
348
+
349
+ ```javascript
350
+ const graph = new WorkflowGraph({
351
+ middleware: [
352
+ async (nodeName, next, stateValues, state) => {
353
+ console.log(`Starting: ${nodeName}`);
354
+ const result = await next();
355
+ console.log(`Completed: ${nodeName} in ${result.duration}ms`);
356
+ return result;
357
+ }
358
+ ]
359
+ });
360
+ ```
361
+
362
+ Skills can also provide middleware. For example, the Memory skill injects a middleware that loads test history before each node and persists insights after:
363
+
364
+ ```javascript
365
+ // Automatically injected when a node declares skills: [SKILLS.MEMORY]
366
+ const memoryMiddleware = await memorySkill.middleware();
367
+ ```
368
+
369
+ ## Skill Adaptation per Agent
370
+
371
+ Skills are resolved differently depending on which agent is active:
372
+
373
+ | Agent | How Skills (MCP servers) Are Wired |
374
+ |---|---|
375
+ | **Cursor** | Written to `~/.cursor/mcp.json` — Cursor IDE manages the MCP lifecycle |
376
+ | **Claude** | Passed as `mcpServers` config to the Claude Agent SDK — native MCP support |
377
+ | **Codex** | Passed as `mcp_servers` config to the Codex SDK — SDK manages MCP processes |
378
+
379
+ The skill's `resolve()` function returns a platform-neutral server config:
380
+
381
+ ```javascript
382
+ {
383
+ command: 'node',
384
+ args: ['/path/to/mcp-browser.js', '--save-video=1280x720', '--viewport-size=1280x720', '--output-dir=./output'],
385
+ env: { SOME_KEY: '...' }
386
+ }
387
+ ```
388
+
389
+ Each agent strategy translates this into its native MCP format. Node code never changes.
390
+
391
+ ## Context Loading
392
+
393
+ The workflow engine auto-discovers context files that are prepended to prompts:
394
+
395
+ ```javascript
396
+ // .zibby.config.js
397
+ export default {
398
+ context: {
399
+ filenames: ['CONTEXT.md', 'AGENTS.md'],
400
+ discovery: {
401
+ env: `env-${process.env.ENV || 'local'}.js`,
402
+ }
403
+ }
404
+ };
405
+ ```
406
+
407
+ Context files cascade from the project root down to the spec's directory. This lets you provide domain knowledge (login credentials, app structure, known quirks) that the AI uses during execution.
408
+
409
+ ## Per-Node Model Override
410
+
411
+ Override the AI model for specific nodes without changing the workflow:
412
+
413
+ ```javascript
414
+ // .zibby.config.js
415
+ export default {
416
+ agent: {
417
+ cursor: { model: 'auto' },
418
+ },
419
+ models: {
420
+ default: 'auto',
421
+ execute_live: 'claude-opus-4', // Use a more capable model for browser execution
422
+ preflight: 'claude-sonnet-4.6', // Faster model for analysis
423
+ }
424
+ };
425
+ ```
426
+
427
+ Model resolution priority: node override → `models.default` → agent block model → `'auto'`.
428
+
429
+ ## Workflow Templates
430
+
431
+ `@zibby/core` ships two built-in workflow templates:
432
+
433
+ ### Browser Test Automation (`browser-test-automation`)
434
+
435
+ The default workflow for `zibby test`:
436
+
437
+ ```
438
+ preflight → execute_live → generate_script → END
439
+ ```
440
+
441
+ Three nodes: extract spec, drive browser, generate Playwright script.
442
+
443
+ ### Code Analysis (`code-analysis`)
444
+
445
+ Used by the cloud analysis pipeline:
446
+
447
+ ```
448
+ setup → analyze_ticket → generate_code → generate_test_cases → finalize → END
449
+ ```
450
+
451
+ Six nodes: clone repo, analyze Jira ticket, generate code changes, write test cases, compile report.
452
+
453
+ ## Creating Custom Skills
454
+
455
+ ### MCP Skill (wraps an external MCP server)
456
+
457
+ ```javascript
458
+ import { skill } from '@zibby/skills';
459
+
460
+ export const linear = skill('linear', {
461
+ description: 'Linear project management',
462
+ serverName: 'linear',
463
+ allowedTools: ['mcp__linear__*'],
464
+ envKeys: ['LINEAR_API_KEY'],
465
+ resolve() {
466
+ if (!process.env.LINEAR_API_KEY) return null;
467
+ return {
468
+ command: 'npx',
469
+ args: ['-y', '@anthropic/linear-mcp-server'],
470
+ env: { LINEAR_API_KEY: process.env.LINEAR_API_KEY }
471
+ };
472
+ }
473
+ });
474
+ ```
475
+
476
+ ### Function Skill (single tool, no MCP server)
477
+
478
+ ```javascript
479
+ import { skill } from '@zibby/skills';
480
+
481
+ export const add = skill('add', {
482
+ description: 'Add two numbers',
483
+ input: { a: 'number', b: 'number' },
484
+ handler: async ({ a, b }) => ({ result: a + b })
485
+ });
486
+ ```
487
+
488
+ Function skills are automatically bridged to MCP at runtime — the framework spawns a lightweight MCP server that delegates to your handler.
489
+
490
+ ## End-to-End Example: Custom Workflow
491
+
492
+ ```javascript
493
+ import { WorkflowGraph, SKILLS } from '@zibby/core';
494
+ import { z } from '@zibby/core';
495
+
496
+ // 1. Define output schemas
497
+ const AnalysisSchema = z.object({
498
+ summary: z.string(),
499
+ testCases: z.array(z.object({
500
+ name: z.string(),
501
+ steps: z.array(z.string()),
502
+ })),
503
+ });
504
+
505
+ const ExecutionSchema = z.object({
506
+ success: z.boolean(),
507
+ steps: z.array(z.string()),
508
+ actions: z.array(z.object({
509
+ type: z.string(),
510
+ description: z.string(),
511
+ })),
512
+ browserClosed: z.boolean(),
513
+ });
514
+
515
+ // 2. Define nodes
516
+ const analyzeNode = {
517
+ name: 'analyze',
518
+ prompt: (state) => `Analyze this requirement and produce test cases:\n${state.testSpec}`,
519
+ outputSchema: AnalysisSchema,
520
+ };
521
+
522
+ const executeNode = {
523
+ name: 'execute',
524
+ skills: [SKILLS.BROWSER, SKILLS.MEMORY],
525
+ prompt: (state) => `Execute test "${state.analyze.testCases[0].name}":\n${state.analyze.testCases[0].steps.join('\n')}`,
526
+ outputSchema: ExecutionSchema,
527
+ timeout: 600000,
528
+ };
529
+
530
+ // 3. Build graph
531
+ const graph = new WorkflowGraph();
532
+ graph.addNode('analyze', analyzeNode);
533
+ graph.addNode('execute', executeNode);
534
+ graph.setEntryPoint('analyze');
535
+ graph.addEdge('analyze', 'execute');
536
+ graph.addEdge('execute', 'END');
537
+
538
+ // 4. Run
539
+ const result = await graph.run(agent, {
540
+ testSpec: 'Verify the user can log in and see the dashboard',
541
+ cwd: process.cwd(),
542
+ });
543
+ ```
544
+
545
+ ## Workflow CLI Commands
546
+
547
+ ```bash
548
+ # Run a specific workflow (if you have multiple defined)
549
+ zibby test test.txt --workflow QuickSmokeWorkflow
550
+
551
+ # Run a single node (for debugging)
552
+ zibby test test.txt --node execute_live --session last
553
+
554
+ # Upload/download workflow graphs to/from Zibby Cloud
555
+ zibby workflow list
556
+ zibby workflow download --type run_test
557
+ zibby workflow upload --type analysis --file .zibby/workflow-analysis.json
558
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/skills",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Built-in skill definitions for Zibby test automation framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -15,6 +15,7 @@
15
15
  },
16
16
  "scripts": {
17
17
  "build": "node ../scripts/build.mjs",
18
+ "prepack": "node scripts/copy-docs.mjs",
18
19
  "lint": "eslint .",
19
20
  "lint:fix": "eslint --fix ."
20
21
  },
@@ -37,12 +38,16 @@
37
38
  },
38
39
  "files": [
39
40
  "dist/",
41
+ "docs/",
40
42
  "README.md",
41
43
  "LICENSE"
42
44
  ],
43
45
  "engines": {
44
46
  "node": ">=18.0.0"
45
47
  },
48
+ "dependencies": {
49
+ "@zibby/workflow": "^0.1.0"
50
+ },
46
51
  "peerDependencies": {
47
52
  "@zibby/core": ">=0.1.0"
48
53
  },