@zibby/core 0.1.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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/package.json +94 -0
  4. package/src/agents/base.js +361 -0
  5. package/src/constants.js +47 -0
  6. package/src/enrichment/base.js +49 -0
  7. package/src/enrichment/enrichers/accessibility-enricher.js +197 -0
  8. package/src/enrichment/enrichers/dom-enricher.js +171 -0
  9. package/src/enrichment/enrichers/page-state-enricher.js +129 -0
  10. package/src/enrichment/enrichers/position-enricher.js +67 -0
  11. package/src/enrichment/index.js +96 -0
  12. package/src/enrichment/mcp-integration.js +149 -0
  13. package/src/enrichment/mcp-ref-enricher.js +78 -0
  14. package/src/enrichment/pipeline.js +192 -0
  15. package/src/enrichment/trace-text-enricher.js +115 -0
  16. package/src/framework/AGENTS.md +98 -0
  17. package/src/framework/agents/base.js +72 -0
  18. package/src/framework/agents/claude-strategy.js +278 -0
  19. package/src/framework/agents/cursor-strategy.js +459 -0
  20. package/src/framework/agents/index.js +105 -0
  21. package/src/framework/agents/utils/cursor-output-formatter.js +67 -0
  22. package/src/framework/agents/utils/openai-proxy-formatter.js +249 -0
  23. package/src/framework/code-generator.js +301 -0
  24. package/src/framework/constants.js +33 -0
  25. package/src/framework/context-loader.js +101 -0
  26. package/src/framework/function-bridge.js +78 -0
  27. package/src/framework/function-skill-registry.js +20 -0
  28. package/src/framework/graph-compiler.js +342 -0
  29. package/src/framework/graph.js +610 -0
  30. package/src/framework/index.js +28 -0
  31. package/src/framework/node-registry.js +163 -0
  32. package/src/framework/node.js +259 -0
  33. package/src/framework/output-parser.js +71 -0
  34. package/src/framework/skill-registry.js +55 -0
  35. package/src/framework/state-utils.js +52 -0
  36. package/src/framework/state.js +67 -0
  37. package/src/framework/tool-resolver.js +65 -0
  38. package/src/index.js +342 -0
  39. package/src/runtime/generation/base.js +46 -0
  40. package/src/runtime/generation/index.js +70 -0
  41. package/src/runtime/generation/mcp-ref-strategy.js +197 -0
  42. package/src/runtime/generation/stable-id-strategy.js +170 -0
  43. package/src/runtime/stable-id-runtime.js +248 -0
  44. package/src/runtime/verification/base.js +44 -0
  45. package/src/runtime/verification/index.js +67 -0
  46. package/src/runtime/verification/playwright-json-strategy.js +119 -0
  47. package/src/runtime/zibby-runtime.js +299 -0
  48. package/src/sync/index.js +2 -0
  49. package/src/sync/uploader.js +29 -0
  50. package/src/tools/run-playwright-test.js +158 -0
  51. package/src/utils/adf-converter.js +68 -0
  52. package/src/utils/ast-utils.js +37 -0
  53. package/src/utils/ci-setup.js +124 -0
  54. package/src/utils/cursor-utils.js +71 -0
  55. package/src/utils/logger.js +144 -0
  56. package/src/utils/mcp-config-writer.js +115 -0
  57. package/src/utils/node-schema-parser.js +522 -0
  58. package/src/utils/post-process-events.js +55 -0
  59. package/src/utils/result-handler.js +102 -0
  60. package/src/utils/ripple-effect.js +84 -0
  61. package/src/utils/selector-generator.js +239 -0
  62. package/src/utils/streaming-parser.js +387 -0
  63. package/src/utils/test-post-processor.js +211 -0
  64. package/src/utils/timeline.js +217 -0
  65. package/src/utils/trace-parser.js +325 -0
  66. package/src/utils/video-organizer.js +91 -0
  67. package/templates/browser-test-automation/README.md +114 -0
  68. package/templates/browser-test-automation/graph.js +54 -0
  69. package/templates/browser-test-automation/nodes/execute-live.js +250 -0
  70. package/templates/browser-test-automation/nodes/generate-script.js +77 -0
  71. package/templates/browser-test-automation/nodes/index.js +3 -0
  72. package/templates/browser-test-automation/nodes/preflight.js +59 -0
  73. package/templates/browser-test-automation/nodes/utils.js +154 -0
  74. package/templates/browser-test-automation/result-handler.js +286 -0
  75. package/templates/code-analysis/graph.js +72 -0
  76. package/templates/code-analysis/index.js +18 -0
  77. package/templates/code-analysis/nodes/analyze-ticket-node.js +204 -0
  78. package/templates/code-analysis/nodes/create-pr-node.js +175 -0
  79. package/templates/code-analysis/nodes/finalize-node.js +118 -0
  80. package/templates/code-analysis/nodes/generate-code-node.js +425 -0
  81. package/templates/code-analysis/nodes/generate-test-cases-node.js +376 -0
  82. package/templates/code-analysis/nodes/services/prMetaService.js +86 -0
  83. package/templates/code-analysis/nodes/setup-node.js +142 -0
  84. package/templates/code-analysis/prompts/analyze-ticket.md +181 -0
  85. package/templates/code-analysis/prompts/generate-code.md +33 -0
  86. package/templates/code-analysis/prompts/generate-test-cases.md +110 -0
  87. package/templates/code-analysis/state.js +40 -0
  88. package/templates/code-implementation/graph.js +35 -0
  89. package/templates/code-implementation/index.js +7 -0
  90. package/templates/code-implementation/state.js +14 -0
  91. package/templates/global-setup.js +56 -0
  92. package/templates/index.js +94 -0
  93. package/templates/register-nodes.js +24 -0
@@ -0,0 +1,181 @@
1
+ # Analyze Ticket: {{ticketKey}}
2
+
3
+ ## Ticket Information
4
+
5
+ **Type:** {{ticketType}}
6
+ **Priority:** {{ticketPriority}}
7
+ **Summary:** {{{ticketSummary}}}
8
+
9
+ **Description:**
10
+ {{{ticketDescription}}}
11
+
12
+ {{#if ticketLabels}}
13
+ **Labels:** {{ticketLabels}}
14
+ {{/if}}
15
+
16
+ {{#if ticketComponents}}
17
+ **Components:** {{ticketComponents}}
18
+ {{/if}}
19
+
20
+ {{#if additionalContext}}
21
+ ## Additional Context
22
+
23
+ {{{additionalContext}}}
24
+
25
+ {{/if}}
26
+ ---
27
+
28
+ ## Repository Information
29
+
30
+ Your workspace contains ONLY these top-level repository directories:
31
+
32
+ {{#each repositories}}
33
+ - **{{name}}** — {{language}}{{#if framework}}, {{framework}}{{/if}}{{#if packageManager}} ({{packageManager}}){{/if}}
34
+ {{/each}}
35
+
36
+ **IMPORTANT:** These are the ONLY repositories. Sub-directories or internal modules (e.g. Maven modules, packages within a monorepo) are NOT separate repositories. All file paths in your analysis MUST start with one of the repository names listed above (e.g. `{{repositories.[0].name}}/path/to/file`).
37
+
38
+ ---
39
+
40
+ ## Your Task
41
+
42
+ Analyze this ticket **BY EXAMINING THE ACTUAL CODEBASE** and provide:
43
+ 1. **Validation** - Determine if the ticket has enough information to implement
44
+ 2. **Suggested improvements** to the ticket's summary, description, or labels
45
+
46
+ ### Analysis Steps
47
+
48
+ 1. **REPO RELEVANCE CHECK (MANDATORY FIRST STEP)** - Read the repo's `README.md` or `package.json` to understand what this project is. If the ticket's domain/features do not genuinely belong to this codebase, stop immediately — set `canProceed: false`, `status: 'invalid_ticket'`. Do NOT force-fit: files with similar names (e.g. `auth.js`) do not make a ticket relevant.
49
+
50
+ 2. **VALIDATE THE TICKET** - Determine if we can proceed:
51
+ - Does the ticket make sense? Is it clear what needs to be done?
52
+ - Is there enough context to understand the requirements?
53
+ - Are the requirements technically feasible based on the codebase?
54
+ - Is the ticket specific enough, or is it too vague?
55
+ - Are there obvious blockers (missing dependencies, architectural issues)?
56
+
57
+ **If validation fails**, set:
58
+ - `canProceed: false`
59
+ - `status`: One of: 'insufficient_context', 'unclear_requirements', 'invalid_ticket', 'needs_clarification'
60
+ - `reasoning`: Clear explanation of what's missing or unclear
61
+ - `blockers`: List specific issues preventing implementation
62
+
63
+ **If validation passes**, set:
64
+ - `canProceed: true`
65
+ - `status: 'valid'`
66
+ - `reasoning`: Brief confirmation that ticket is ready
67
+ - `blockers`: [] or omit
68
+
69
+ 3. **Review the ticket** - Read the summary, description, and labels carefully
70
+ 4. **Explore the codebase** - Examine the relevant files, functions, and components
71
+ - Use file search, grep, and read tools to understand existing patterns
72
+ - Identify the exact files and code that will be affected
73
+ - Assess the complexity of the changes required
74
+ 5. **Identify improvements** - Look for:
75
+ - Typos, grammar, or incorrect terminology (use real codebase names)
76
+ - Missing acceptance criteria or ambiguous requirements
77
+ - Better ways to phrase the summary based on codebase terminology
78
+ - Missing or incorrect labels based on actual components affected
79
+
80
+ ---
81
+
82
+ ## IMPORTANT: Output Format
83
+
84
+ You MUST return your analysis as valid JSON in the following structure:
85
+
86
+ ```json
87
+ {
88
+ "validation": {
89
+ "canProceed": true,
90
+ "status": "valid",
91
+ "reasoning": "Ticket has clear requirements and matches existing codebase patterns. Implementation is straightforward.",
92
+ "blockers": []
93
+ },
94
+ "suggestedChanges": [
95
+ {
96
+ "field": "summary",
97
+ "original": "<the current ticket summary>",
98
+ "suggested": "Your improved summary here",
99
+ "reasoning": "Why this change improves clarity (reference actual codebase structure)"
100
+ },
101
+ {
102
+ "field": "description",
103
+ "original": "<the current ticket description — full text>",
104
+ "suggested": "<paste the full corrected description here exactly as it should appear — same structure as original, with typos corrected, terminology updated to match the codebase, and any missing details filled in>",
105
+ "reasoning": "Why this change helps developers (based on codebase)"
106
+ },
107
+ {
108
+ "field": "labels",
109
+ "original": "<the current labels or None>",
110
+ "suggested": "frontend, backend, api-change",
111
+ "reasoning": "These labels reflect the actual components affected (based on code)"
112
+ }
113
+ ],
114
+ "technicalAnalysis": {
115
+ "requirements": [
116
+ "Key requirement 1",
117
+ "Key requirement 2"
118
+ ],
119
+ "affectedFiles": [
120
+ "repo-name/src/components/Feature.js",
121
+ "repo-name/src/api/endpoint.js"
122
+ ],
123
+ "complexity": "simple|medium|complex",
124
+ "risks": [
125
+ "Potential risk 1"
126
+ ]
127
+ },
128
+ "overallSummary": "Brief 1-2 sentence summary of findings based on codebase review",
129
+ "implementationPlan": "## Summary\nBrief description of what to build.\n\n## Repositories\nChanges needed in: `repo-a`, `repo-b` (read-only reference: `repo-c`).\nThese MUST be top-level workspace directories listed in Repository Information above.\n\n## TODO\n1. In `repo-a/submodule/src/path/to/NewFile.java` — create new entity following `ExistingEntity` pattern\n2. In `repo-a/submodule/src/path/to/Controller.java` — add POST endpoint `/api/thing`\n3. In `repo-b/config/routes.json` — add route entry\n4. ...\n\nEvery path MUST start with a top-level repo name (repo-a/, repo-b/, etc.), never a sub-directory or internal module name.\n\n## Technical Details\n- Follow pattern in `repo-a/submodule/src/.../ExistingService.java` for the service layer\n- Table name: `snake_case_name` (see existing migration `V1.0.100__example.sql`)\n- Risk: watch out for X"
130
+ }
131
+ ```
132
+
133
+ ### EXAMPLE: Validation Failed (Insufficient Context)
134
+
135
+ ```json
136
+ {
137
+ "validation": {
138
+ "canProceed": false,
139
+ "status": "insufficient_context",
140
+ "reasoning": "The ticket asks to 'fix the login bug' but does not specify what the bug is, how to reproduce it, or what the expected behavior should be. Cannot determine what needs to be fixed.",
141
+ "blockers": [
142
+ "No description of the actual bug or issue",
143
+ "No reproduction steps provided",
144
+ "No expected vs actual behavior specified",
145
+ "Cannot identify which part of login flow is broken"
146
+ ]
147
+ },
148
+ "suggestedChanges": [
149
+ {
150
+ "field": "description",
151
+ "original": "Fix the login bug",
152
+ "suggested": "Fix the login bug\n\n**Bug Description:** [describe the bug]\n\n**Steps to Reproduce:**\n1. Go to /login\n2. Enter valid credentials\n3. Click submit\n\n**Expected:** Should redirect to dashboard\n**Actual:** [describe what happens]\n\n**Environment:** Browser, OS",
153
+ "reasoning": "Description is a single sentence with no reproduction steps or expected behavior — added template for required information."
154
+ }
155
+ ],
156
+ "technicalAnalysis": {
157
+ "requirements": [],
158
+ "affectedFiles": [],
159
+ "complexity": "simple",
160
+ "risks": ["Cannot proceed without more information"]
161
+ },
162
+ "overallSummary": "Ticket is blocked due to insufficient information. Need bug description, reproduction steps, and expected behavior."
163
+ }
164
+ ```
165
+
166
+ ### Rules for Suggested Changes:
167
+
168
+ 1. **`suggested` MUST be the actual replacement text** - The `suggested` value replaces `original` directly. It must be the COMPLETE corrected text, NOT instructions or a summary of changes (e.g. "Fix typos: X → Y" is WRONG). The UI diffs `original` vs `suggested` word-by-word.
169
+ 2. **For summary**: Use correct codebase terminology and fix typos. Output the full corrected summary.
170
+ 3. **For description**: **Enrich, don't rewrite** - You explored the actual codebase, so use that knowledge to improve the ticket: fix typos, correct terminology to match the codebase (e.g. use the real class/component names), add missing acceptance criteria, clarify ambiguous requirements, and add useful technical context you discovered. Keep the original structure and intent — do NOT rewrite from scratch unless the description is fundamentally broken. When adding NEW technical content, use proper Markdown: wrap file paths, function/class/variable names, and inline code references in backticks (e.g. `src/Foo.java`, `toggleLike`), use fenced code blocks for multi-line snippets, but do NOT reformat existing text — only apply formatting to content YOU are adding.
171
+ 4. **For labels**: Use comma-separated values that reflect actual components affected (frontend, backend, api-change, etc.)
172
+ 5. **Skip fields that are already good** - Only include a field in suggestedChanges if it genuinely benefits from changes.
173
+
174
+ ### CRITICAL Guidelines:
175
+
176
+ - **ALWAYS read the codebase first** - Use tools to search and read files
177
+ - **Base ALL suggestions on actual code** - Don't make assumptions
178
+ - **Reference real files** - Include actual file paths in your analysis
179
+ - **Follow existing patterns** - Respect the codebase architecture
180
+
181
+ Return ONLY the JSON object, no additional text before or after.
@@ -0,0 +1,33 @@
1
+ # Implement: {{ticketKey}} — {{{ticketSummary}}}
2
+
3
+ ## Description
4
+ {{{ticketDescription}}}
5
+
6
+ {{#if acceptanceCriteria}}
7
+ ## Acceptance Criteria
8
+ {{{acceptanceCriteria}}}
9
+
10
+ {{/if}}
11
+ {{#if analysisContext}}
12
+ ## Technical Plan
13
+ {{{analysisContext}}}
14
+
15
+ {{/if}}
16
+ {{#if repositories}}
17
+ ## Workspace
18
+ The following repositories are cloned in your workspace:
19
+ {{#each repositories}}
20
+ - `{{name}}` — {{language}}{{#if framework}}, {{framework}}{{/if}}
21
+ {{/each}}
22
+ Make changes in whichever repositories the Technical Plan and ticket require. If the plan references files in multiple repos, modify all of them.
23
+
24
+ {{/if}}
25
+ ## Instructions
26
+ 1. Read the codebase — understand existing patterns and conventions
27
+ 2. Implement the feature — clean code, proper error handling, no unnecessary comments
28
+ 3. Write tests for new functionality
29
+ 4. Verify everything works
30
+
31
+ {{#if isCommitting}}Changes will be committed and pushed to a feature branch.{{else}}Changes will be captured via git diff.{{/if}}
32
+
33
+ Now implement the changes!
@@ -0,0 +1,110 @@
1
+ You are an AI test automation engineer creating human-readable test specifications.
2
+
3
+ WORKSPACE: {{workspace}}
4
+
5
+ TICKET: {{ticketKey}} - {{{ticketSummary}}}
6
+ {{#if ticketDescription}}
7
+ Description: {{{ticketDescription}}}
8
+ {{/if}}
9
+
10
+ MODIFIED FILES:
11
+ {{#each changedFiles}}
12
+ - {{this}}
13
+ {{/each}}
14
+
15
+ FULL CODE DIFF:
16
+ ```diff
17
+ {{{codeDiff}}}
18
+ ```
19
+
20
+ {{#if hasTestContext}}
21
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
22
+ PROVIDED TEST CONTEXT (USE THESE IN TEST CASES)
23
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
24
+
25
+ {{#if testBaseUrl}}Test Base URL: {{testBaseUrl}}{{/if}}
26
+ {{#if adminUsername}}Admin Username: {{adminUsername}}{{/if}}
27
+ {{#if adminPassword}}Admin Password: {{adminPassword}}{{/if}}
28
+ {{#if testAccountUsername}}Test Account Username: {{testAccountUsername}}{{/if}}
29
+ {{#if testAccountPassword}}Test Account Password: {{testAccountPassword}}{{/if}}
30
+
31
+ **IMPORTANT**: Use these exact values in your test cases. Do NOT make up URLs or credentials.
32
+
33
+ {{/if}}
34
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
35
+
36
+ YOUR JOB: Generate 4-8 test specifications in plain-text format that AI agents can interpret.
37
+
38
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
39
+ STEP 1: EXPLORE THE CODEBASE (MANDATORY - DO NOT SKIP)
40
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
41
+
42
+ YOU MUST explore the codebase to understand the application structure BEFORE writing tests.
43
+
44
+ REQUIRED EXPLORATION:
45
+
46
+ 1. **Find and Read Routing Files**
47
+ - Search the workspace for routing files: look for common names like App, routes, router, main, index files in .js/.jsx/.ts/.tsx format
48
+ - Check common locations: src/, app/, client/, web/, components/, pages/ directories
49
+ - Identify ALL routes and their URL patterns
50
+ - Pay special attention to routes with parameters (e.g., /stores/:storeId/products, /users/:userId/orders, /items/:itemId)
51
+
52
+ 2. **Understand Route Parameters**
53
+ - Dynamic segments in routes (marked with :paramName or {paramName}) are PLACEHOLDERS
54
+ - You MUST include navigation steps to select/create that resource first
55
+ - Example: To reach /stores/:storeId/products, you must first navigate to /stores list and select a specific store
56
+ - Example: To reach /orders/:orderId/details, you must first navigate to /orders list and click on a specific order
57
+
58
+ 3. **Map Navigation Flow**
59
+ - Understand the hierarchy: authentication → landing/home → resource lists → individual resources → sub-features
60
+ - Find what links, buttons, tabs exist on each page to navigate to the next level
61
+ - Read page components to understand the UI structure and navigation elements
62
+
63
+ 4. **Find Authentication**
64
+ - Check for login/signin routes, auth components, protected routes, authentication guards
65
+ - Look for HOCs, route wrappers, or middleware that handle authentication
66
+ - Understand if authentication is required and what the login flow looks like
67
+
68
+ 5. **Identify Page Components**
69
+ - Find the actual page/view components referenced in routes
70
+ - Read their code to understand imports, props, state management, and structure
71
+ - Understand what data they load, what APIs they call, and what user actions they support
72
+
73
+ CRITICAL RULES:
74
+ - Routes with dynamic parameters (like :id, :userId, :orderId) REQUIRE parent resource selection
75
+ - You CANNOT jump directly to a URL with an ID - you must navigate through the parent list and SELECT that item
76
+ - Base your test steps on ACTUAL navigation paths you discover in the codebase
77
+ - If you don't explore properly, your tests will have WRONG navigation and be unusable by AI agents
78
+
79
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
80
+ STEP 2: GENERATE TEST SPECIFICATIONS
81
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
82
+
83
+ For each test, provide:
84
+ - **title**: Test name (e.g., "Filter Orders by Status")
85
+ - **application**: Application name (infer from package.json or codebase)
86
+ - **url**: Base application URL (usually http://localhost:3000 or staging URL if found)
87
+ - **testerRole**: Who performs this test (e.g., "Admin user", "End user", "Guest")
88
+ - **feature**: Feature being tested (match the modified files)
89
+ - **ticketId**: Use the ticket key provided above
90
+ - **testCredentials**: Array of credentials needed (if authentication required):
91
+ - field: "Email" / "Password" / "Username" / "API Key", etc.
92
+ - value: Use realistic test data (e.g., "admin@example.com", "TestPass123")
93
+ - **testObjective**: One clear sentence describing what this test verifies
94
+ - **testSteps**: Plain English steps - MUST match actual navigation flow you discovered
95
+ - **expectedResults**: Bullet points of what should happen
96
+ - **priority**: Critical, High, Medium, or Low
97
+ - **category**: Test category (e.g., "Smoke Test", "Regression", "Integration")
98
+
99
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
100
+ FINAL REMINDERS
101
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
102
+
103
+ 1. ALWAYS explore routing files FIRST
104
+ 2. NEVER skip navigation steps - include full path from login to feature
105
+ 3. If routes have :parameters, include parent resource selection
106
+ 4. Use ACTUAL URLs and paths from the codebase
107
+ 5. Write plain English steps - no technical jargon
108
+ 6. Base tests on REAL navigation flow, not assumptions
109
+
110
+ Now generate test specifications for the ticket above.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Analysis Workflow State Schema
3
+ */
4
+
5
+ import { z } from 'zod';
6
+
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
+
18
+ ticketContext: z.object({
19
+ key: z.string().regex(/^[A-Z]+-\d+$/, 'Invalid ticket format (expected PROJ-123)').optional(),
20
+ ticketKey: z.string().optional(),
21
+ summary: z.string().min(1).describe('Ticket summary/title'),
22
+ description: z.any().optional().describe('Ticket description (string or ADF object)'),
23
+ acceptanceCriteria: z.string().optional(),
24
+ type: z.string().optional(),
25
+ priority: z.string().optional(),
26
+ labels: z.array(z.string()).optional(),
27
+ 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.any()).optional().describe('Per-node configuration overrides'),
34
+
35
+ EXECUTION_ID: z.string().nullable().optional(),
36
+ PROGRESS_QUEUE_URL: z.string().url().nullable().optional(),
37
+ PROGRESS_API_URL: z.string().url().nullable().optional(),
38
+ SQS_AUTH_TOKEN: z.string().nullable().optional(),
39
+ PROJECT_API_TOKEN: z.string().nullable().optional(),
40
+ });
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Implementation Graph - Apply code changes AND create PR
3
+ *
4
+ * Flow:
5
+ * 1. setup - Clone repos and init git baseline
6
+ * 2. implement_code - Apply changes, commit, push to branch
7
+ * 3. generate_tests - Generate test cases
8
+ * 4. create_pr - Create GitHub Pull Request
9
+ * 5. finalize - Upload results to API
10
+ */
11
+
12
+ import { setupNode } from '../code-analysis/nodes/setup-node.js';
13
+ import { implementCodeNode } from '../code-analysis/nodes/generate-code-node.js';
14
+ import { generateTestCasesNode } from '../code-analysis/nodes/generate-test-cases-node.js';
15
+ import { createPRNode } from '../code-analysis/nodes/create-pr-node.js';
16
+ import { finalizeNode } from '../code-analysis/nodes/finalize-node.js';
17
+ import { implementationStateSchema } from './state.js';
18
+
19
+ export function buildImplementationGraph(graph) {
20
+ graph.setStateSchema(implementationStateSchema);
21
+
22
+ graph
23
+ .addNode('setup', setupNode) // ← Reused from analysis!
24
+ .addNode('implement_code', implementCodeNode) // ← Real changes + push
25
+ .addNode('generate_test_cases', generateTestCasesNode) // ← Generate human-readable test specs
26
+ .addNode('create_pr', createPRNode) // ← Create GitHub PR
27
+ .addNode('finalize', finalizeNode) // ← Reused from analysis!
28
+ .setEntryPoint('setup')
29
+ .addEdge('setup', 'implement_code')
30
+ .addEdge('implement_code', 'generate_test_cases')
31
+ .addEdge('generate_test_cases', 'create_pr')
32
+ .addEdge('create_pr', 'finalize');
33
+
34
+ return graph;
35
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Code Implementation Module
3
+ * Workflow for applying code changes and creating PRs
4
+ */
5
+
6
+ export { implementationStateSchema } from './state.js';
7
+ export { buildImplementationGraph } from './graph.js';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Implementation Workflow State Schema
3
+ */
4
+
5
+ import { z } from 'zod';
6
+ import { analysisStateSchema } from '../code-analysis/state.js';
7
+
8
+ /**
9
+ * Implementation workflow state schema (extends analysis)
10
+ */
11
+ export const implementationStateSchema = analysisStateSchema.extend({
12
+ branchName: z.string().optional().describe('Git branch name for changes'),
13
+ prTitle: z.string().optional().describe('Pull request title template'),
14
+ });
@@ -0,0 +1,56 @@
1
+ export default async function globalSetup() {
2
+ console.log('🎭 Zibby global setup - enabling visual feedback...');
3
+ }
4
+
5
+ export async function setupRippleEffect(page) {
6
+ await page.addInitScript(`
7
+ const style = document.createElement('style');
8
+ style.textContent = \`
9
+ @keyframes zibby-ripple {
10
+ 0% {
11
+ transform: scale(0);
12
+ opacity: 0.7;
13
+ }
14
+ 100% {
15
+ transform: scale(4);
16
+ opacity: 0;
17
+ }
18
+ }
19
+ .zibby-ripple {
20
+ position: absolute;
21
+ border-radius: 50%;
22
+ background: rgba(59, 130, 246, 0.7);
23
+ pointer-events: none;
24
+ animation: zibby-ripple 0.6s ease-out;
25
+ z-index: 999999;
26
+ }
27
+ \`;
28
+
29
+ document.addEventListener('DOMContentLoaded', () => {
30
+ if (document.head && !document.getElementById('zibby-ripple-style')) {
31
+ style.id = 'zibby-ripple-style';
32
+ document.head.appendChild(style);
33
+ }
34
+ });
35
+
36
+ if (document.head && !document.getElementById('zibby-ripple-style')) {
37
+ style.id = 'zibby-ripple-style';
38
+ document.head.appendChild(style);
39
+ }
40
+
41
+ window.__zibbyShowRipple = function(x, y) {
42
+ const ripple = document.createElement('div');
43
+ ripple.className = 'zibby-ripple';
44
+ ripple.style.left = (x - 10) + 'px';
45
+ ripple.style.top = (y - 10) + 'px';
46
+ ripple.style.width = '20px';
47
+ ripple.style.height = '20px';
48
+
49
+ if (document.body) {
50
+ document.body.appendChild(ripple);
51
+ setTimeout(() => ripple.remove(), 600);
52
+ }
53
+ };
54
+ `);
55
+ }
56
+
@@ -0,0 +1,94 @@
1
+ import { join, dirname } from 'path';
2
+ import { fileURLToPath } from 'url';
3
+ import { existsSync } from 'fs';
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+
8
+ export const TEMPLATES = {
9
+ 'browser-test-automation': {
10
+ name: 'browser-test-automation',
11
+ displayName: 'Browser Test Automation (Full Workflow)',
12
+ description: 'Complete browser test automation workflow with title generation, live execution, and script generation',
13
+ path: join(__dirname, 'browser-test-automation'),
14
+ default: true,
15
+ features: [
16
+ 'Preflight analysis: extract title + assertion checklist from spec',
17
+ 'Execute test live with AI + browser (Claude or Cursor)',
18
+ 'Generate Playwright script with stable IDs',
19
+ 'Real-time streaming output',
20
+ 'Video recording of browser sessions'
21
+ ]
22
+ }
23
+ };
24
+
25
+ export class TemplateFactory {
26
+ static listTemplates() {
27
+ return Object.values(TEMPLATES);
28
+ }
29
+
30
+ static getDefault() {
31
+ return Object.values(TEMPLATES).find(t => t.default) || TEMPLATES['browser-test-automation'];
32
+ }
33
+
34
+ static getTemplate(name) {
35
+ const template = TEMPLATES[name];
36
+ if (!template) {
37
+ const available = Object.keys(TEMPLATES).join(', ');
38
+ throw new Error(`Template "${name}" not found. Available: ${available}`);
39
+ }
40
+ return template;
41
+ }
42
+
43
+ static validateTemplate(templatePath) {
44
+ const requiredFiles = ['graph.js', 'nodes', 'README.md'];
45
+
46
+ for (const file of requiredFiles) {
47
+ const filePath = join(templatePath, file);
48
+ if (!existsSync(filePath)) {
49
+ throw new Error(`Template missing required file: ${file}`);
50
+ }
51
+ }
52
+
53
+ return true;
54
+ }
55
+
56
+ static getTemplateFiles(templateName) {
57
+ const template = this.getTemplate(templateName);
58
+ this.validateTemplate(template.path);
59
+
60
+ const resultHandlerPath = join(template.path, 'result-handler.js');
61
+ return {
62
+ graphPath: join(template.path, 'graph.js'),
63
+ nodesPath: join(template.path, 'nodes'),
64
+ readmePath: join(template.path, 'README.md'),
65
+ resultHandlerPath: existsSync(resultHandlerPath) ? resultHandlerPath : null,
66
+ template
67
+ };
68
+ }
69
+
70
+ static registerCustomTemplate(name, config) {
71
+ if (TEMPLATES[name]) {
72
+ throw new Error(`Template "${name}" already exists`);
73
+ }
74
+
75
+ if (!config.path || !config.displayName) {
76
+ throw new Error('Custom template must have "path" and "displayName"');
77
+ }
78
+
79
+ this.validateTemplate(config.path);
80
+
81
+ TEMPLATES[name] = {
82
+ name,
83
+ displayName: config.displayName,
84
+ description: config.description || '',
85
+ path: config.path,
86
+ features: config.features || [],
87
+ custom: true
88
+ };
89
+
90
+ return TEMPLATES[name];
91
+ }
92
+ }
93
+
94
+ export default TemplateFactory;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Template node registrations
3
+ *
4
+ * Import this module as a side-effect to register all built-in
5
+ * template nodes with the framework's node registry.
6
+ *
7
+ * Usage: import '@zibby/core/templates/register-nodes.js';
8
+ */
9
+
10
+ import { registerNode } from '../src/framework/node-registry.js';
11
+ import { setupNode } from './code-analysis/nodes/setup-node.js';
12
+ import { analyzeTicketNode } from './code-analysis/nodes/analyze-ticket-node.js';
13
+ import { generateCodeNode, implementCodeNode } from './code-analysis/nodes/generate-code-node.js';
14
+ import { generateTestCasesNode } from './code-analysis/nodes/generate-test-cases-node.js';
15
+ import { finalizeNode } from './code-analysis/nodes/finalize-node.js';
16
+ import { createPRNode } from './code-analysis/nodes/create-pr-node.js';
17
+
18
+ registerNode('setup', setupNode);
19
+ registerNode('analyze_ticket', analyzeTicketNode);
20
+ registerNode('generate_code', generateCodeNode);
21
+ registerNode('generate_test_cases', generateTestCasesNode);
22
+ registerNode('finalize', finalizeNode);
23
+ registerNode('implement_code', implementCodeNode);
24
+ registerNode('create_pr', createPRNode);