@zibby/workflow-templates 0.1.0 → 0.2.1

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.
@@ -13,12 +13,17 @@ import {
13
13
  generateScriptNode,
14
14
  } from './nodes/index.mjs';
15
15
  import { BrowserTestResultHandler } from './result-handler.mjs';
16
- import { browserTestAutomationStateSchema } from './state.js';
16
+ import {
17
+ browserTestAutomationInputSchema,
18
+ browserTestAutomationContextSchema,
19
+ } from './state.js';
17
20
 
18
21
  export class BrowserTestAutomationAgent extends WorkflowAgent {
19
22
  buildGraph() {
20
23
  const graph = new WorkflowGraph();
21
- graph.setStateSchema(browserTestAutomationStateSchema);
24
+ graph
25
+ .setInputSchema(browserTestAutomationInputSchema)
26
+ .setContextSchema(browserTestAutomationContextSchema);
22
27
 
23
28
  graph.addNode('preflight', preflightNode);
24
29
  graph.addNode('cache_replay', cacheReplayNode);
@@ -6,7 +6,7 @@
6
6
  "description": "Browser Test Automation \u2014 preflight + live Playwright execution + Playwright-script emission, driven by a Claude/Cursor agent.",
7
7
  "main": "graph.mjs",
8
8
  "dependencies": {
9
- "@zibby/core": "^0.4.0",
9
+ "@zibby/core": "^0.5.1",
10
10
  "zod": "^3.23.0"
11
11
  }
12
12
  }
@@ -1,42 +1,36 @@
1
1
  /**
2
- * Browser Test Automation — Workflow State Schema
2
+ * Browser Test Automation — Workflow State Schemas
3
3
  *
4
- * Declares the input shape that nodes in this template actually read off
5
- * `state`. Wired into the graph via `graph.setStateSchema(...)` in
6
- * graph.mjs so that:
4
+ * Three-schema model (LangGraph / Mastra style):
7
5
  *
8
- * - `zibby workflow run <slug> -p testSpec=...` validates inputs
9
- * against this schema before nodes ever execute.
10
- * - The post-scaffold `Pass inputs:` cheatsheet reads top-level fields
11
- * from this schema so the printed examples match what the template
12
- * actually consumes (testSpec, model) instead of generic placeholders.
6
+ * - browserTestAutomationInputSchema — trigger-time user input
7
+ * - browserTestAutomationContextSchema runner-injected fields
8
+ * - browserTestAutomationStateSchema — derived merge of the two
13
9
  *
14
- * Field provenance:
15
- * - testSpec, model — USER input (passed via -p / --input).
16
- * - cwd, sessionPath, — FRAMEWORK-injected by the workflow runner
17
- * outputPath, context (NOT user input). Declared optional so a
18
- * user-only payload validates cleanly.
19
- * - preflight, execute_live — DOWNSTREAM node outputs (set by earlier
20
- * nodes during graph execution). Same: kept
21
- * optional so initial inputs validate.
10
+ * `graph.mjs` wires the first two via setInputSchema/setContextSchema; the
11
+ * engine derives the merged schema internally for run-time validation.
22
12
  *
23
- * `zod` is imported directly from the `zod` package (not re-exported via
24
- * @zibby/core)same convention as code-analysis/state.js. The
25
- * scaffolded user copy gets `zod` via the template's dep merge in
26
- * templates/index.js.
13
+ * Field provenance:
14
+ * - testSpec, model USER input (passed via -p / --input).
15
+ * - cwd, sessionPath, outputPath, context RUNNER-injected (NOT user input).
16
+ * - preflight, execute_live — node outputs (set during the run;
17
+ * kept optional so initial state validates).
27
18
  */
28
19
 
29
20
  import { z } from 'zod';
30
21
 
31
- export const browserTestAutomationStateSchema = z.object({
32
- // ---- USER INPUT (what `-p` / `--input` populates) ----
22
+ // Trigger-time user input. The trigger modal + CLI render fields from this.
23
+ export const browserTestAutomationInputSchema = z.object({
33
24
  testSpec: z.string().describe(
34
25
  'Plain-English description of the browser test to analyze + execute (REQUIRED).',
35
26
  ),
36
27
  model: z.string().default('auto').describe(
37
28
  'Agent model override (e.g. "auto", "opus-4.6"). Defaults to "auto".',
38
29
  ),
30
+ });
39
31
 
32
+ // Runner-injected at runtime. NOT in the trigger UI.
33
+ export const browserTestAutomationContextSchema = z.object({
40
34
  // ---- FRAMEWORK-INJECTED (set by the workflow runner, not the user) ----
41
35
  cwd: z.string().optional().describe(
42
36
  'Working directory the workflow runs in. Injected by the runner.',
@@ -52,6 +46,9 @@ export const browserTestAutomationStateSchema = z.object({
52
46
  ),
53
47
 
54
48
  // ---- DOWNSTREAM NODE OUTPUTS (populated mid-graph, not by the user) ----
49
+ // Declared on contextSchema (not as a per-node outputSchema) until the
50
+ // graph-engine supports per-node output declarations natively. Optional
51
+ // so initial state validates cleanly before nodes have written them.
55
52
  preflight: z.any().optional().describe(
56
53
  'Output of the preflight node (assertion checklist + title). Set during the run.',
57
54
  ),
@@ -59,3 +56,7 @@ export const browserTestAutomationStateSchema = z.object({
59
56
  'Output of the execute_live node (recorded actions + steps). Set during the run.',
60
57
  ),
61
58
  });
59
+
60
+ // Derived: the full runtime state shape. Exported for tests + tooling.
61
+ export const browserTestAutomationStateSchema =
62
+ browserTestAutomationInputSchema.merge(browserTestAutomationContextSchema);
@@ -18,10 +18,17 @@
18
18
 
19
19
  import { WorkflowAgent, WorkflowGraph } from '@zibby/core';
20
20
  import { buildAnalysisGraph } from './graph.js';
21
+ import {
22
+ analysisInputSchema,
23
+ analysisContextSchema,
24
+ } from './state.js';
21
25
 
22
26
  export class CodeAnalysisAgent extends WorkflowAgent {
23
27
  buildGraph() {
24
28
  const graph = new WorkflowGraph();
29
+ graph
30
+ .setInputSchema(analysisInputSchema)
31
+ .setContextSchema(analysisContextSchema);
25
32
  buildAnalysisGraph(graph);
26
33
  return graph;
27
34
  }
@@ -6,7 +6,7 @@
6
6
  "description": "Code Analysis \u2014 multi-node Jira-to-code workflow: analyze ticket \u2192 generate scoped code changes \u2192 emit covering test cases.",
7
7
  "main": "graph.mjs",
8
8
  "dependencies": {
9
- "@zibby/core": "^0.4.0",
9
+ "@zibby/core": "^0.5.1",
10
10
  "axios": "^1.6.0",
11
11
  "handlebars": "^4.7.8",
12
12
  "zod": "^3.23.0"
@@ -1,48 +1,79 @@
1
1
  /**
2
- * Analysis Workflow State Schema
2
+ * Code Analysis Workflow schemas
3
+ *
4
+ * Three exports following the LangGraph / Mastra three-schema model:
5
+ *
6
+ * - `analysisInputSchema` — trigger-time user input. What the web
7
+ * trigger modal renders, what `zibby workflow trigger -p …` validates,
8
+ * what an external caller (Slack bot, Zapier, CI) sends in `{ input }`
9
+ * to POST /trigger. Strictly the fields a HUMAN provides.
10
+ *
11
+ * - `analysisContextSchema` — system-injected fields. Workspace path,
12
+ * integration tokens, project repos, deploy-time config. The runner
13
+ * populates these from project settings + the resolver registry
14
+ * BEFORE handing the state to nodes. Never user-supplied.
15
+ *
16
+ * - `analysisStateSchema` — derived `inputSchema.merge(contextSchema)`.
17
+ * What the engine validates initial state against. Exported so tests
18
+ * + tooling that need the merged shape don't have to re-merge.
19
+ *
20
+ * Membership IS the declaration: if a field is on `inputSchema` the user
21
+ * supplies it; if on `contextSchema` the runner injects it. No marker
22
+ * convention (no `@inject`, no metadata) — same model as LangGraph's
23
+ * `StateGraph(input_schema=, context_schema=)` split.
3
24
  */
4
25
 
5
26
  import { z } from 'zod';
6
27
 
7
- export const analysisStateSchema = z.object({
8
- workspace: z.string().describe('Local workspace path'),
9
-
10
- repos: z.array(z.object({
11
- name: z.string(),
12
- url: z.string().url(),
13
- path: z.string().optional(),
14
- branch: z.string().default('main'),
15
- isPrimary: z.boolean().default(false),
16
- })).optional().describe('Repository configurations'),
17
-
28
+ // What the user types at trigger time.
29
+ export const analysisInputSchema = z.object({
18
30
  ticketContext: z.object({
19
- key: z.string().regex(/^[A-Z]+-\d+$/, 'Invalid ticket format (expected PROJ-123)').optional(),
20
- ticketKey: z.string().optional(),
31
+ key: z.string().regex(/^[A-Z]+-\d+$/, 'Invalid ticket format (expected PROJ-123)').optional()
32
+ .describe('Ticket key (e.g. PROJ-123)optional if `summary` carries enough context'),
21
33
  summary: z.string().min(1).describe('Ticket summary/title'),
22
- description: z.any().optional().describe('Ticket description (string or ADF object)'),
34
+ description: z.any().optional().describe('Ticket description (string or Atlassian Document Format)'),
23
35
  acceptanceCriteria: z.string().optional(),
24
- type: z.string().optional(),
36
+ type: z.string().optional().describe('Issue type (Bug / Story / Task)'),
25
37
  priority: z.string().optional(),
26
38
  labels: z.array(z.string()).optional(),
27
39
  components: z.array(z.string()).optional(),
28
- }).describe('Jira/ticket context'),
29
-
30
- promptsDir: z.string().optional().describe('Path to prompts directory'),
31
- githubToken: z.string().optional().describe('GitHub personal access token'),
32
- model: z.string().default('auto').describe('AI model to use'),
33
- nodeConfigs: z.record(z.string(), z.any()).optional().describe('Per-node configuration overrides'),
40
+ }).describe('Ticket details — the only required user input'),
41
+
42
+ model: z.string().default('auto')
43
+ .describe('Agent model override (e.g. "auto", "opus-4.6"). Defaults to "auto".'),
44
+ });
45
+
46
+ // System-injected at runtime — the runner populates these from project
47
+ // config + integrations before any node executes. NOT exposed to the
48
+ // trigger UI; users can't override them.
49
+ export const analysisContextSchema = z.object({
50
+ workspace: z.string()
51
+ .describe('Local workspace path — injected by the runner from project root'),
52
+
53
+ repos: z.array(z.object({
54
+ name: z.string(),
55
+ url: z.string().url(),
56
+ path: z.string().optional(),
57
+ branch: z.string().default('main'),
58
+ isPrimary: z.boolean().default(false),
59
+ })).optional()
60
+ .describe('Repository configurations — injected from the project\'s repo settings'),
61
+
62
+ ticketKey: z.string().optional()
63
+ .describe('Convenience alias of ticketContext.key — set by the setup node'),
64
+
65
+ promptsDir: z.string().optional()
66
+ .describe('Path to prompts directory — injected by the runner (defaults to template-bundled prompts/)'),
67
+
68
+ githubToken: z.string().optional()
69
+ .describe('GitHub PAT — injected by the runner from the user\'s GitHub integration'),
70
+
71
+ nodeConfigs: z.record(z.string(), z.any()).optional()
72
+ .describe('Per-node configuration overrides — set at deploy time, not trigger time'),
34
73
  });
35
74
 
36
- // NOTE: legacy `EXECUTION_ID`, `PROGRESS_QUEUE_URL`, `PROGRESS_API_URL`,
37
- // `SQS_AUTH_TOKEN`, `PROJECT_API_TOKEN` fields are no longer declared in
38
- // this schema. They were used only by the legacy `analyze-graph` cli +
39
- // the analysis UI's progress reporter — never by template nodes. Zod's
40
- // safeParse here doesn't strip unknown keys (see graph.js:504), so the
41
- // legacy flow still works at runtime: analyze-graph.js injects them
42
- // into initialState, validation passes, nodes ignore them, the
43
- // progress-reporter middleware reads them off the state argument.
44
- //
45
- // Keeping them out of the schema means scaffolded user copies (via
46
- // `zibby workflow new -t code-analysis`) ship a clean state that
47
- // reflects only what the template actually needs — no false coupling
48
- // to internal infra fields.
75
+ // Derived: what the engine actually validates initialState against at
76
+ // graph.run() time. Re-export so tests and tooling that need the merged
77
+ // shape don't re-merge. NOT canonical the two source-of-truth schemas
78
+ // above are.
79
+ export const analysisStateSchema = analysisInputSchema.merge(analysisContextSchema);
@@ -21,12 +21,17 @@
21
21
  import { WorkflowAgent, WorkflowGraph } from '@zibby/core';
22
22
  import { setupNode } from './nodes/setup-node.js';
23
23
  import { generateTestCasesNode } from './nodes/generate-test-cases-node.js';
24
- import { generateTestCasesStateSchema } from './state.js';
24
+ import {
25
+ generateTestCasesInputSchema,
26
+ generateTestCasesContextSchema,
27
+ } from './state.js';
25
28
 
26
29
  export class GenerateTestCasesAgent extends WorkflowAgent {
27
30
  buildGraph() {
28
31
  const graph = new WorkflowGraph();
29
- graph.setStateSchema(generateTestCasesStateSchema);
32
+ graph
33
+ .setInputSchema(generateTestCasesInputSchema)
34
+ .setContextSchema(generateTestCasesContextSchema);
30
35
 
31
36
  graph.addNode('setup', setupNode);
32
37
  graph.addNode('generate_test_cases', generateTestCasesNode);
@@ -6,7 +6,7 @@
6
6
  "description": "Generate Test Cases \u2014 standalone slice that turns a code diff into prioritized, AI-runnable test specs.",
7
7
  "main": "graph.mjs",
8
8
  "dependencies": {
9
- "@zibby/core": "^0.4.0",
9
+ "@zibby/core": "^0.5.1",
10
10
  "zod": "^3.23.0"
11
11
  }
12
12
  }
@@ -1,28 +1,25 @@
1
1
  /**
2
- * State schema for the generate-test-cases standalone template.
2
+ * generate-test-cases Workflow State Schemas
3
3
  *
4
- * Same shape as code-analysis (workspace + repos + ticketContext) PLUS
5
- * a `codeImplementation` field — the diff this template generates tests
6
- * for. In code-analysis that field is produced by the upstream
7
- * generate_code node; here, the user provides it directly.
4
+ * Same three-schema model as code-analysis + browser-test-automation:
5
+ *
6
+ * - generateTestCasesInputSchema — trigger-time user input
7
+ * - generateTestCasesContextSchema runner-injected fields
8
+ * - generateTestCasesStateSchema — derived merge of the two
9
+ *
10
+ * Differs from code-analysis in one place: `codeImplementation` is part of
11
+ * USER input here (the user already has a PR diff and wants tests for it),
12
+ * whereas in code-analysis it's produced by an upstream `generate_code`
13
+ * node. Otherwise the context fields are the same: workspace + repos +
14
+ * tokens + nodeConfigs come from the runner, not the trigger caller.
8
15
  */
9
16
 
10
17
  import { z } from 'zod';
11
18
 
12
- export const generateTestCasesStateSchema = z.object({
13
- workspace: z.string().describe('Local workspace path'),
14
-
15
- repos: z.array(z.object({
16
- name: z.string(),
17
- url: z.string().url(),
18
- path: z.string().optional(),
19
- branch: z.string().default('main'),
20
- isPrimary: z.boolean().default(false),
21
- })).optional().describe('Repository configurations (cloned by setup node so the LLM can explore routing/components)'),
22
-
19
+ // Trigger-time user input.
20
+ export const generateTestCasesInputSchema = z.object({
23
21
  ticketContext: z.object({
24
22
  key: z.string().regex(/^[A-Z]+-\d+$/, 'Invalid ticket format (expected PROJ-123)').optional(),
25
- ticketKey: z.string().optional(),
26
23
  summary: z.string().min(1).describe('Ticket summary/title'),
27
24
  description: z.any().optional().describe('Ticket description (string or ADF object)'),
28
25
  acceptanceCriteria: z.string().optional(),
@@ -32,23 +29,38 @@ export const generateTestCasesStateSchema = z.object({
32
29
  components: z.array(z.string()).optional(),
33
30
  }).describe('Jira/ticket context — informs test priorities + naming'),
34
31
 
35
- // The new direct-input field that distinguishes this standalone template
36
- // from code-analysis. In code-analysis this comes from generate_code's
37
- // output; here the user supplies it (e.g. from `git diff` of a PR they
38
- // want tests for).
39
32
  codeImplementation: z.object({
40
- diff: z.string().describe('Unified-diff string of the changes'),
33
+ diff: z.string().describe('Unified-diff string of the changes (e.g. from `git diff` of a PR)'),
41
34
  changedFiles: z.array(z.string()).describe('List of file paths touched'),
42
35
  }).describe('Code changes to generate tests for'),
43
36
 
44
- githubToken: z.string().optional().describe('GitHub PAT (needed only if repos[].url requires auth)'),
45
37
  model: z.string().default('auto').describe('AI model to use'),
46
- nodeConfigs: z.record(z.string(), z.any()).optional().describe('Per-node configuration overrides (e.g. extractContext for test credentials)'),
47
38
  });
48
39
 
49
- // Clean isolation: this schema declares ONLY what the template's nodes
50
- // actually need. No EXECUTION_ID / PROGRESS_QUEUE_URL / SQS_AUTH_TOKEN
51
- // / PROJECT_API_TOKEN — those were legacy analysis-UI plumbing fields
52
- // and the new templates run via the standard `workflow run` /
53
- // `workflow trigger` cloud pipeline, which has its own progress
54
- // reporting outside the state object.
40
+ // Runner-injected at runtime. NOT in the trigger UI.
41
+ export const generateTestCasesContextSchema = z.object({
42
+ workspace: z.string()
43
+ .describe('Local workspace path injected by the runner from project root'),
44
+
45
+ repos: z.array(z.object({
46
+ name: z.string(),
47
+ url: z.string().url(),
48
+ path: z.string().optional(),
49
+ branch: z.string().default('main'),
50
+ isPrimary: z.boolean().default(false),
51
+ })).optional()
52
+ .describe('Repository configurations — injected from the project\'s repo settings (cloned by setup node)'),
53
+
54
+ ticketKey: z.string().optional()
55
+ .describe('Convenience alias of ticketContext.key — set by setup node'),
56
+
57
+ githubToken: z.string().optional()
58
+ .describe('GitHub PAT — injected by the runner from the user\'s GitHub integration'),
59
+
60
+ nodeConfigs: z.record(z.string(), z.any()).optional()
61
+ .describe('Per-node configuration overrides — set at deploy time, not trigger time'),
62
+ });
63
+
64
+ // Derived: full runtime state. Exported for tests + tooling.
65
+ export const generateTestCasesStateSchema =
66
+ generateTestCasesInputSchema.merge(generateTestCasesContextSchema);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/workflow-templates",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Built-in workflow templates for Zibby — browser-test-automation, code-analysis, generate-test-cases. Carved out of @zibby/core@0.4.6 so the engine ships without scaffolding payload.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@anthropic-ai/sdk": "^0.88.0",
60
- "@zibby/agent-workflow": "^0.3.0",
60
+ "@zibby/agent-workflow": "^0.4.0",
61
61
  "axios": "^1.15.0",
62
62
  "handlebars": "^4.7.9",
63
63
  "zod": "^3.23.0 || ^4.0.0"