@t3lnet/sceneforge 1.0.8 → 1.0.10
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/README.md +57 -0
- package/cli/cli.js +6 -0
- package/cli/commands/context.js +791 -0
- package/context/context-builder.ts +318 -0
- package/context/index.ts +52 -0
- package/context/template-loader.ts +161 -0
- package/context/templates/base/actions-reference.md +299 -0
- package/context/templates/base/cli-reference.md +236 -0
- package/context/templates/base/project-overview.md +58 -0
- package/context/templates/base/selectors-guide.md +233 -0
- package/context/templates/base/yaml-schema.md +210 -0
- package/context/templates/skills/balance-timing.md +136 -0
- package/context/templates/skills/debug-selector.md +193 -0
- package/context/templates/skills/generate-actions.md +94 -0
- package/context/templates/skills/optimize-demo.md +218 -0
- package/context/templates/skills/review-demo-yaml.md +164 -0
- package/context/templates/skills/write-step-script.md +136 -0
- package/context/templates/stages/stage1-actions.md +236 -0
- package/context/templates/stages/stage2-scripts.md +197 -0
- package/context/templates/stages/stage3-balancing.md +229 -0
- package/context/templates/stages/stage4-rebalancing.md +228 -0
- package/context/tests/context-builder.test.ts +237 -0
- package/context/tests/template-loader.test.ts +181 -0
- package/context/tests/tool-formatter.test.ts +198 -0
- package/context/tool-formatter.ts +189 -0
- package/dist/index.cjs +416 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +182 -1
- package/dist/index.d.ts +182 -1
- package/dist/index.js +391 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Skill: Write Step Script
|
|
2
|
+
|
|
3
|
+
Write voiceover script text for a SceneForge demo step.
|
|
4
|
+
|
|
5
|
+
## Task
|
|
6
|
+
|
|
7
|
+
Create engaging, clear voiceover script that explains the actions in a demo step.
|
|
8
|
+
|
|
9
|
+
## Input Required
|
|
10
|
+
|
|
11
|
+
Provide the following:
|
|
12
|
+
- **Step ID**: The identifier of the step
|
|
13
|
+
- **Actions**: The actions that will be performed
|
|
14
|
+
- **Context**: What has happened before this step
|
|
15
|
+
- **Target duration**: Approximate time (optional)
|
|
16
|
+
|
|
17
|
+
## Output Format
|
|
18
|
+
|
|
19
|
+
A single `script` field value suitable for voice synthesis:
|
|
20
|
+
- Natural, conversational tone
|
|
21
|
+
- Explains what's happening and why
|
|
22
|
+
- Matches approximate action timing
|
|
23
|
+
- Clean punctuation for speech synthesis
|
|
24
|
+
|
|
25
|
+
## Writing Guidelines
|
|
26
|
+
|
|
27
|
+
### Speaking Rate
|
|
28
|
+
- Target: ~150 words per minute
|
|
29
|
+
- 5 words ≈ 2 seconds
|
|
30
|
+
- 15 words ≈ 6 seconds
|
|
31
|
+
|
|
32
|
+
### Tone
|
|
33
|
+
- Conversational, not robotic
|
|
34
|
+
- Second person ("you") or first person plural ("we")
|
|
35
|
+
- Action-oriented ("Click", "Enter", "Notice")
|
|
36
|
+
|
|
37
|
+
### Structure
|
|
38
|
+
- Start with action verb when possible
|
|
39
|
+
- Explain purpose, not just mechanics
|
|
40
|
+
- Add context for unfamiliar features
|
|
41
|
+
|
|
42
|
+
## Examples
|
|
43
|
+
|
|
44
|
+
### Simple Click Action
|
|
45
|
+
|
|
46
|
+
**Actions:**
|
|
47
|
+
```yaml
|
|
48
|
+
- action: click
|
|
49
|
+
target:
|
|
50
|
+
type: button
|
|
51
|
+
text: "Save"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Script:**
|
|
55
|
+
```
|
|
56
|
+
"Click Save to store your changes."
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Form Entry
|
|
60
|
+
|
|
61
|
+
**Actions:**
|
|
62
|
+
```yaml
|
|
63
|
+
- action: type
|
|
64
|
+
target: { type: input, name: "email" }
|
|
65
|
+
text: "user@example.com"
|
|
66
|
+
- action: type
|
|
67
|
+
target: { type: input, name: "password" }
|
|
68
|
+
text: "********"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Script:**
|
|
72
|
+
```
|
|
73
|
+
"Enter your email address and password to sign in to your account."
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Feature Introduction
|
|
77
|
+
|
|
78
|
+
**Actions:**
|
|
79
|
+
```yaml
|
|
80
|
+
- action: hover
|
|
81
|
+
target:
|
|
82
|
+
type: selector
|
|
83
|
+
selector: ".analytics-panel"
|
|
84
|
+
- action: wait
|
|
85
|
+
duration: 2000
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Script:**
|
|
89
|
+
```
|
|
90
|
+
"The analytics panel provides real-time insights into your project's performance. You can see visitor counts, engagement metrics, and conversion rates at a glance."
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Navigation
|
|
94
|
+
|
|
95
|
+
**Actions:**
|
|
96
|
+
```yaml
|
|
97
|
+
- action: click
|
|
98
|
+
target:
|
|
99
|
+
type: link
|
|
100
|
+
text: "Settings"
|
|
101
|
+
- action: wait
|
|
102
|
+
waitFor:
|
|
103
|
+
type: idle
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Script:**
|
|
107
|
+
```
|
|
108
|
+
"Navigate to Settings to customize your preferences and configure your account options."
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Anti-Patterns to Avoid
|
|
112
|
+
|
|
113
|
+
**Too mechanical:**
|
|
114
|
+
```
|
|
115
|
+
"Click the button that says Save."
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Too verbose:**
|
|
119
|
+
```
|
|
120
|
+
"Now what we're going to do is we're going to click on this Save button here to save all of the changes that we've made."
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Stating the obvious:**
|
|
124
|
+
```
|
|
125
|
+
"You can see there is a button. The button is blue. Click on it."
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Checklist
|
|
129
|
+
|
|
130
|
+
Before finalizing:
|
|
131
|
+
- [ ] Natural, conversational language
|
|
132
|
+
- [ ] Appropriate length for action duration
|
|
133
|
+
- [ ] Explains purpose, not just action
|
|
134
|
+
- [ ] No filler words
|
|
135
|
+
- [ ] Proper punctuation for speech
|
|
136
|
+
- [ ] Consistent tone with other steps
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Stage 1: Action Generation
|
|
2
|
+
|
|
3
|
+
This stage focuses on creating the action sequences that will be executed by Playwright to record the demo video.
|
|
4
|
+
|
|
5
|
+
## Objectives
|
|
6
|
+
|
|
7
|
+
1. Define clear, reliable action sequences
|
|
8
|
+
2. Choose stable, maintainable selectors
|
|
9
|
+
3. Add appropriate wait conditions
|
|
10
|
+
4. Structure steps logically
|
|
11
|
+
|
|
12
|
+
## Action Generation Guidelines
|
|
13
|
+
|
|
14
|
+
### Step Structure
|
|
15
|
+
|
|
16
|
+
Each step should represent a logical unit of the demo:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
- id: create-new-item
|
|
20
|
+
script: "" # Leave empty for now, fill in Stage 2
|
|
21
|
+
actions:
|
|
22
|
+
- action: click
|
|
23
|
+
target:
|
|
24
|
+
type: button
|
|
25
|
+
text: "New Item"
|
|
26
|
+
- action: wait
|
|
27
|
+
waitFor:
|
|
28
|
+
type: selector
|
|
29
|
+
value: ".modal-content"
|
|
30
|
+
- action: type
|
|
31
|
+
target:
|
|
32
|
+
type: input
|
|
33
|
+
name: "item-name"
|
|
34
|
+
text: "My New Item"
|
|
35
|
+
- action: click
|
|
36
|
+
target:
|
|
37
|
+
type: button
|
|
38
|
+
text: "Create"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Selector Selection Strategy
|
|
42
|
+
|
|
43
|
+
**Priority Order:**
|
|
44
|
+
1. `[data-testid="..."]` - Best stability
|
|
45
|
+
2. `[aria-label="..."]` - Good for accessible UIs
|
|
46
|
+
3. `role=button[name="..."]` - Semantic, readable
|
|
47
|
+
4. `button:has-text("...")` - Text-based fallback
|
|
48
|
+
5. CSS selectors - Last resort
|
|
49
|
+
|
|
50
|
+
**Examples:**
|
|
51
|
+
```yaml
|
|
52
|
+
# Best: data-testid
|
|
53
|
+
target:
|
|
54
|
+
type: selector
|
|
55
|
+
selector: "[data-testid='submit-btn']"
|
|
56
|
+
|
|
57
|
+
# Good: aria-label
|
|
58
|
+
target:
|
|
59
|
+
type: selector
|
|
60
|
+
selector: "[aria-label='Close dialog']"
|
|
61
|
+
|
|
62
|
+
# Acceptable: role with text
|
|
63
|
+
target:
|
|
64
|
+
type: button
|
|
65
|
+
text: "Submit"
|
|
66
|
+
|
|
67
|
+
# Avoid: complex CSS paths
|
|
68
|
+
target:
|
|
69
|
+
type: selector
|
|
70
|
+
selector: "div.container > form > div:nth-child(3) > button"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Wait Conditions
|
|
74
|
+
|
|
75
|
+
Always add wait conditions after actions that trigger:
|
|
76
|
+
- Network requests
|
|
77
|
+
- Animations/transitions
|
|
78
|
+
- Modal dialogs
|
|
79
|
+
- Dynamic content loading
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
# After navigation
|
|
83
|
+
- action: navigate
|
|
84
|
+
path: /dashboard
|
|
85
|
+
waitFor:
|
|
86
|
+
type: idle
|
|
87
|
+
|
|
88
|
+
# After click that loads content
|
|
89
|
+
- action: click
|
|
90
|
+
target:
|
|
91
|
+
type: button
|
|
92
|
+
text: "Load Data"
|
|
93
|
+
waitFor:
|
|
94
|
+
type: selector
|
|
95
|
+
value: ".data-table"
|
|
96
|
+
|
|
97
|
+
# After click that opens modal
|
|
98
|
+
- action: click
|
|
99
|
+
target:
|
|
100
|
+
type: button
|
|
101
|
+
text: "Settings"
|
|
102
|
+
waitFor:
|
|
103
|
+
type: selector
|
|
104
|
+
value: ".settings-modal"
|
|
105
|
+
|
|
106
|
+
# Wait for spinner to disappear
|
|
107
|
+
- action: wait
|
|
108
|
+
waitFor:
|
|
109
|
+
type: selectorHidden
|
|
110
|
+
value: ".loading-spinner"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Common Patterns
|
|
114
|
+
|
|
115
|
+
### Form Filling
|
|
116
|
+
```yaml
|
|
117
|
+
- id: fill-contact-form
|
|
118
|
+
script: ""
|
|
119
|
+
actions:
|
|
120
|
+
- action: type
|
|
121
|
+
target:
|
|
122
|
+
type: input
|
|
123
|
+
name: "name"
|
|
124
|
+
text: "John Smith"
|
|
125
|
+
- action: type
|
|
126
|
+
target:
|
|
127
|
+
type: input
|
|
128
|
+
name: "email"
|
|
129
|
+
text: "john@example.com"
|
|
130
|
+
- action: type
|
|
131
|
+
target:
|
|
132
|
+
type: selector
|
|
133
|
+
selector: "textarea[name='message']"
|
|
134
|
+
text: "Hello, I would like to inquire about..."
|
|
135
|
+
- action: click
|
|
136
|
+
target:
|
|
137
|
+
type: button
|
|
138
|
+
text: "Send Message"
|
|
139
|
+
waitFor:
|
|
140
|
+
type: text
|
|
141
|
+
value: "Message sent!"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Dropdown Selection
|
|
145
|
+
```yaml
|
|
146
|
+
- id: select-country
|
|
147
|
+
script: ""
|
|
148
|
+
actions:
|
|
149
|
+
- action: click
|
|
150
|
+
target:
|
|
151
|
+
type: selector
|
|
152
|
+
selector: "[data-testid='country-dropdown']"
|
|
153
|
+
- action: wait
|
|
154
|
+
waitFor:
|
|
155
|
+
type: selector
|
|
156
|
+
value: ".dropdown-menu"
|
|
157
|
+
- action: click
|
|
158
|
+
target:
|
|
159
|
+
type: text
|
|
160
|
+
text: "United States"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Modal Workflow
|
|
164
|
+
```yaml
|
|
165
|
+
- id: confirm-deletion
|
|
166
|
+
script: ""
|
|
167
|
+
actions:
|
|
168
|
+
- action: click
|
|
169
|
+
target:
|
|
170
|
+
type: button
|
|
171
|
+
text: "Delete"
|
|
172
|
+
- action: wait
|
|
173
|
+
waitFor:
|
|
174
|
+
type: selector
|
|
175
|
+
value: ".confirmation-modal"
|
|
176
|
+
- action: click
|
|
177
|
+
target:
|
|
178
|
+
type: selector
|
|
179
|
+
selector: ".confirmation-modal >> button:has-text('Confirm')"
|
|
180
|
+
- action: wait
|
|
181
|
+
waitFor:
|
|
182
|
+
type: selectorHidden
|
|
183
|
+
value: ".confirmation-modal"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Async Content
|
|
187
|
+
```yaml
|
|
188
|
+
- id: load-report
|
|
189
|
+
script: ""
|
|
190
|
+
actions:
|
|
191
|
+
- action: click
|
|
192
|
+
target:
|
|
193
|
+
type: button
|
|
194
|
+
text: "Generate Report"
|
|
195
|
+
- action: wait
|
|
196
|
+
waitFor:
|
|
197
|
+
type: selectorHidden
|
|
198
|
+
value: ".generating-spinner"
|
|
199
|
+
timeout: 30000
|
|
200
|
+
- action: wait
|
|
201
|
+
waitFor:
|
|
202
|
+
type: selector
|
|
203
|
+
value: ".report-content"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Testing Actions
|
|
207
|
+
|
|
208
|
+
Run in headed mode to verify actions work correctly:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
sceneforge record --definition demo.yaml --base-url http://localhost:3000 --headed
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Debugging tips:**
|
|
215
|
+
- Add `--slowmo 500` to slow down execution
|
|
216
|
+
- Watch for selector failures in the console
|
|
217
|
+
- Check if wait conditions are adequate
|
|
218
|
+
- Verify timing between actions
|
|
219
|
+
|
|
220
|
+
## Step ID Conventions
|
|
221
|
+
|
|
222
|
+
Use descriptive, kebab-case IDs:
|
|
223
|
+
- `login-to-dashboard`
|
|
224
|
+
- `create-new-project`
|
|
225
|
+
- `upload-document`
|
|
226
|
+
- `configure-settings`
|
|
227
|
+
- `submit-and-confirm`
|
|
228
|
+
|
|
229
|
+
## Checklist Before Stage 2
|
|
230
|
+
|
|
231
|
+
- [ ] All actions execute without errors
|
|
232
|
+
- [ ] Selectors are stable (use data-testid where possible)
|
|
233
|
+
- [ ] Wait conditions prevent race conditions
|
|
234
|
+
- [ ] Steps are logically grouped
|
|
235
|
+
- [ ] Step IDs are descriptive
|
|
236
|
+
- [ ] Demo completes successfully in headed mode
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Stage 2: Script Writing
|
|
2
|
+
|
|
3
|
+
This stage focuses on writing voiceover scripts that will be synthesized to speech and synchronized with the recorded actions.
|
|
4
|
+
|
|
5
|
+
## Objectives
|
|
6
|
+
|
|
7
|
+
1. Write clear, engaging voiceover scripts
|
|
8
|
+
2. Match script duration to action timing
|
|
9
|
+
3. Optimize for voice synthesis
|
|
10
|
+
4. Create natural pacing
|
|
11
|
+
|
|
12
|
+
## Script Writing Guidelines
|
|
13
|
+
|
|
14
|
+
### Target Speaking Rate
|
|
15
|
+
|
|
16
|
+
**~150 words per minute** is the ideal speaking rate for clarity.
|
|
17
|
+
|
|
18
|
+
Quick estimation:
|
|
19
|
+
- 5 words ≈ 2 seconds
|
|
20
|
+
- 15 words ≈ 6 seconds
|
|
21
|
+
- 30 words ≈ 12 seconds
|
|
22
|
+
|
|
23
|
+
### Script Format
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
steps:
|
|
27
|
+
- id: navigate-to-dashboard
|
|
28
|
+
script: "Let's start by navigating to the dashboard where we can see an overview of all our projects."
|
|
29
|
+
actions:
|
|
30
|
+
- action: navigate
|
|
31
|
+
path: /dashboard
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Writing Style
|
|
35
|
+
|
|
36
|
+
**Do:**
|
|
37
|
+
- Use conversational, natural language
|
|
38
|
+
- Start sentences with action words ("Click", "Notice", "Let's")
|
|
39
|
+
- Explain the purpose of actions
|
|
40
|
+
- Add context for viewers unfamiliar with the app
|
|
41
|
+
|
|
42
|
+
**Don't:**
|
|
43
|
+
- Use overly technical jargon without explanation
|
|
44
|
+
- Write long, complex sentences
|
|
45
|
+
- Include filler words ("um", "uh", "basically")
|
|
46
|
+
- Repeat obvious visual information
|
|
47
|
+
|
|
48
|
+
### Script Examples
|
|
49
|
+
|
|
50
|
+
**Good:**
|
|
51
|
+
```yaml
|
|
52
|
+
script: "Click the Create button to open the new project form. Here we'll enter the basic details for our project."
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Avoid:**
|
|
56
|
+
```yaml
|
|
57
|
+
script: "So basically what we're going to do now is we're going to click on this button here that says Create and that's going to open up a form."
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Timing Alignment
|
|
61
|
+
|
|
62
|
+
Match script length to action complexity:
|
|
63
|
+
|
|
64
|
+
**Short actions (click, hover):**
|
|
65
|
+
```yaml
|
|
66
|
+
- id: click-save
|
|
67
|
+
script: "Click Save to store your changes."
|
|
68
|
+
actions:
|
|
69
|
+
- action: click
|
|
70
|
+
target:
|
|
71
|
+
type: button
|
|
72
|
+
text: "Save"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Longer actions (form filling):**
|
|
76
|
+
```yaml
|
|
77
|
+
- id: fill-user-details
|
|
78
|
+
script: "Enter the user's information in the form. We'll add their name, email address, and select their role from the dropdown menu."
|
|
79
|
+
actions:
|
|
80
|
+
- action: type
|
|
81
|
+
target: { type: input, name: "name" }
|
|
82
|
+
text: "Jane Smith"
|
|
83
|
+
- action: type
|
|
84
|
+
target: { type: input, name: "email" }
|
|
85
|
+
text: "jane@company.com"
|
|
86
|
+
- action: click
|
|
87
|
+
target: { type: selector, selector: "[data-testid='role-select']" }
|
|
88
|
+
- action: click
|
|
89
|
+
target: { type: text, text: "Administrator" }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Voice Synthesis Considerations
|
|
93
|
+
|
|
94
|
+
ElevenLabs handles most natural speech patterns, but consider:
|
|
95
|
+
|
|
96
|
+
**Punctuation affects pacing:**
|
|
97
|
+
- Periods (.) create full pauses
|
|
98
|
+
- Commas (,) create brief pauses
|
|
99
|
+
- Ellipsis (...) creates hesitation
|
|
100
|
+
|
|
101
|
+
**Emphasis:**
|
|
102
|
+
- Use sentence structure for emphasis
|
|
103
|
+
- Place important words at sentence start/end
|
|
104
|
+
|
|
105
|
+
**Numbers and abbreviations:**
|
|
106
|
+
- Write out numbers for clarity: "three" not "3"
|
|
107
|
+
- Spell out abbreviations: "API" → "A P I" or "application programming interface"
|
|
108
|
+
|
|
109
|
+
## Common Patterns
|
|
110
|
+
|
|
111
|
+
### Introduction Step
|
|
112
|
+
```yaml
|
|
113
|
+
- id: intro
|
|
114
|
+
script: "Welcome to this demo of the Project Management dashboard. I'll show you how to create a new project and assign team members."
|
|
115
|
+
actions:
|
|
116
|
+
- action: wait
|
|
117
|
+
duration: 2000
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Navigation Narration
|
|
121
|
+
```yaml
|
|
122
|
+
- id: go-to-settings
|
|
123
|
+
script: "Let's head over to the Settings page where we can configure our preferences."
|
|
124
|
+
actions:
|
|
125
|
+
- action: click
|
|
126
|
+
target:
|
|
127
|
+
type: link
|
|
128
|
+
text: "Settings"
|
|
129
|
+
- action: wait
|
|
130
|
+
waitFor:
|
|
131
|
+
type: idle
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Feature Highlight
|
|
135
|
+
```yaml
|
|
136
|
+
- id: show-filter
|
|
137
|
+
script: "Notice the filter panel on the left. This allows you to narrow down results by date, status, or category."
|
|
138
|
+
actions:
|
|
139
|
+
- action: hover
|
|
140
|
+
target:
|
|
141
|
+
type: selector
|
|
142
|
+
selector: ".filter-panel"
|
|
143
|
+
highlight: true
|
|
144
|
+
- action: wait
|
|
145
|
+
duration: 1500
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Form Walkthrough
|
|
149
|
+
```yaml
|
|
150
|
+
- id: complete-form
|
|
151
|
+
script: "Fill in the required fields. Start with the project name, then add a description. Finally, select a category from the dropdown."
|
|
152
|
+
actions:
|
|
153
|
+
- action: type
|
|
154
|
+
target: { type: input, name: "name" }
|
|
155
|
+
text: "Q1 Marketing Campaign"
|
|
156
|
+
- action: type
|
|
157
|
+
target: { type: selector, selector: "textarea[name='description']" }
|
|
158
|
+
text: "Campaign planning and execution for Q1 product launch."
|
|
159
|
+
- action: click
|
|
160
|
+
target: { type: selector, selector: "[data-testid='category-select']" }
|
|
161
|
+
- action: click
|
|
162
|
+
target: { type: text, text: "Marketing" }
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Conclusion Step
|
|
166
|
+
```yaml
|
|
167
|
+
- id: outro
|
|
168
|
+
script: "That completes our walkthrough. You've learned how to create projects, assign team members, and configure basic settings. For more tutorials, visit our documentation."
|
|
169
|
+
actions:
|
|
170
|
+
- action: wait
|
|
171
|
+
duration: 2000
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Duration Estimation
|
|
175
|
+
|
|
176
|
+
Calculate approximate script duration:
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
word_count / 2.5 = seconds
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Example: 25 words / 2.5 = 10 seconds
|
|
183
|
+
|
|
184
|
+
Compare with expected action duration and adjust:
|
|
185
|
+
- Add detail if actions take longer
|
|
186
|
+
- Trim script if too long
|
|
187
|
+
- Add `wait` actions for padding
|
|
188
|
+
|
|
189
|
+
## Checklist Before Stage 3
|
|
190
|
+
|
|
191
|
+
- [ ] All steps have scripts (none empty)
|
|
192
|
+
- [ ] Scripts explain what's happening
|
|
193
|
+
- [ ] Language is clear and conversational
|
|
194
|
+
- [ ] Technical terms are explained
|
|
195
|
+
- [ ] Script length roughly matches action duration
|
|
196
|
+
- [ ] No spelling or grammar errors
|
|
197
|
+
- [ ] Intro and outro provide context
|