@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.
- package/LICENSE +21 -0
- package/README.md +147 -0
- package/package.json +94 -0
- package/src/agents/base.js +361 -0
- package/src/constants.js +47 -0
- package/src/enrichment/base.js +49 -0
- package/src/enrichment/enrichers/accessibility-enricher.js +197 -0
- package/src/enrichment/enrichers/dom-enricher.js +171 -0
- package/src/enrichment/enrichers/page-state-enricher.js +129 -0
- package/src/enrichment/enrichers/position-enricher.js +67 -0
- package/src/enrichment/index.js +96 -0
- package/src/enrichment/mcp-integration.js +149 -0
- package/src/enrichment/mcp-ref-enricher.js +78 -0
- package/src/enrichment/pipeline.js +192 -0
- package/src/enrichment/trace-text-enricher.js +115 -0
- package/src/framework/AGENTS.md +98 -0
- package/src/framework/agents/base.js +72 -0
- package/src/framework/agents/claude-strategy.js +278 -0
- package/src/framework/agents/cursor-strategy.js +459 -0
- package/src/framework/agents/index.js +105 -0
- package/src/framework/agents/utils/cursor-output-formatter.js +67 -0
- package/src/framework/agents/utils/openai-proxy-formatter.js +249 -0
- package/src/framework/code-generator.js +301 -0
- package/src/framework/constants.js +33 -0
- package/src/framework/context-loader.js +101 -0
- package/src/framework/function-bridge.js +78 -0
- package/src/framework/function-skill-registry.js +20 -0
- package/src/framework/graph-compiler.js +342 -0
- package/src/framework/graph.js +610 -0
- package/src/framework/index.js +28 -0
- package/src/framework/node-registry.js +163 -0
- package/src/framework/node.js +259 -0
- package/src/framework/output-parser.js +71 -0
- package/src/framework/skill-registry.js +55 -0
- package/src/framework/state-utils.js +52 -0
- package/src/framework/state.js +67 -0
- package/src/framework/tool-resolver.js +65 -0
- package/src/index.js +342 -0
- package/src/runtime/generation/base.js +46 -0
- package/src/runtime/generation/index.js +70 -0
- package/src/runtime/generation/mcp-ref-strategy.js +197 -0
- package/src/runtime/generation/stable-id-strategy.js +170 -0
- package/src/runtime/stable-id-runtime.js +248 -0
- package/src/runtime/verification/base.js +44 -0
- package/src/runtime/verification/index.js +67 -0
- package/src/runtime/verification/playwright-json-strategy.js +119 -0
- package/src/runtime/zibby-runtime.js +299 -0
- package/src/sync/index.js +2 -0
- package/src/sync/uploader.js +29 -0
- package/src/tools/run-playwright-test.js +158 -0
- package/src/utils/adf-converter.js +68 -0
- package/src/utils/ast-utils.js +37 -0
- package/src/utils/ci-setup.js +124 -0
- package/src/utils/cursor-utils.js +71 -0
- package/src/utils/logger.js +144 -0
- package/src/utils/mcp-config-writer.js +115 -0
- package/src/utils/node-schema-parser.js +522 -0
- package/src/utils/post-process-events.js +55 -0
- package/src/utils/result-handler.js +102 -0
- package/src/utils/ripple-effect.js +84 -0
- package/src/utils/selector-generator.js +239 -0
- package/src/utils/streaming-parser.js +387 -0
- package/src/utils/test-post-processor.js +211 -0
- package/src/utils/timeline.js +217 -0
- package/src/utils/trace-parser.js +325 -0
- package/src/utils/video-organizer.js +91 -0
- package/templates/browser-test-automation/README.md +114 -0
- package/templates/browser-test-automation/graph.js +54 -0
- package/templates/browser-test-automation/nodes/execute-live.js +250 -0
- package/templates/browser-test-automation/nodes/generate-script.js +77 -0
- package/templates/browser-test-automation/nodes/index.js +3 -0
- package/templates/browser-test-automation/nodes/preflight.js +59 -0
- package/templates/browser-test-automation/nodes/utils.js +154 -0
- package/templates/browser-test-automation/result-handler.js +286 -0
- package/templates/code-analysis/graph.js +72 -0
- package/templates/code-analysis/index.js +18 -0
- package/templates/code-analysis/nodes/analyze-ticket-node.js +204 -0
- package/templates/code-analysis/nodes/create-pr-node.js +175 -0
- package/templates/code-analysis/nodes/finalize-node.js +118 -0
- package/templates/code-analysis/nodes/generate-code-node.js +425 -0
- package/templates/code-analysis/nodes/generate-test-cases-node.js +376 -0
- package/templates/code-analysis/nodes/services/prMetaService.js +86 -0
- package/templates/code-analysis/nodes/setup-node.js +142 -0
- package/templates/code-analysis/prompts/analyze-ticket.md +181 -0
- package/templates/code-analysis/prompts/generate-code.md +33 -0
- package/templates/code-analysis/prompts/generate-test-cases.md +110 -0
- package/templates/code-analysis/state.js +40 -0
- package/templates/code-implementation/graph.js +35 -0
- package/templates/code-implementation/index.js +7 -0
- package/templates/code-implementation/state.js +14 -0
- package/templates/global-setup.js +56 -0
- package/templates/index.js +94 -0
- 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,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);
|