@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.
Files changed (32) hide show
  1. package/README.md +57 -0
  2. package/cli/cli.js +6 -0
  3. package/cli/commands/context.js +791 -0
  4. package/context/context-builder.ts +318 -0
  5. package/context/index.ts +52 -0
  6. package/context/template-loader.ts +161 -0
  7. package/context/templates/base/actions-reference.md +299 -0
  8. package/context/templates/base/cli-reference.md +236 -0
  9. package/context/templates/base/project-overview.md +58 -0
  10. package/context/templates/base/selectors-guide.md +233 -0
  11. package/context/templates/base/yaml-schema.md +210 -0
  12. package/context/templates/skills/balance-timing.md +136 -0
  13. package/context/templates/skills/debug-selector.md +193 -0
  14. package/context/templates/skills/generate-actions.md +94 -0
  15. package/context/templates/skills/optimize-demo.md +218 -0
  16. package/context/templates/skills/review-demo-yaml.md +164 -0
  17. package/context/templates/skills/write-step-script.md +136 -0
  18. package/context/templates/stages/stage1-actions.md +236 -0
  19. package/context/templates/stages/stage2-scripts.md +197 -0
  20. package/context/templates/stages/stage3-balancing.md +229 -0
  21. package/context/templates/stages/stage4-rebalancing.md +228 -0
  22. package/context/tests/context-builder.test.ts +237 -0
  23. package/context/tests/template-loader.test.ts +181 -0
  24. package/context/tests/tool-formatter.test.ts +198 -0
  25. package/context/tool-formatter.ts +189 -0
  26. package/dist/index.cjs +416 -11
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +182 -1
  29. package/dist/index.d.ts +182 -1
  30. package/dist/index.js +391 -11
  31. package/dist/index.js.map +1 -1
  32. package/package.json +2 -1
@@ -0,0 +1,233 @@
1
+ # SceneForge Selectors Guide
2
+
3
+ ## Selector Priority
4
+
5
+ When targeting elements, use this priority order for reliability:
6
+
7
+ 1. **data-testid** - Most reliable, designed for testing
8
+ 2. **aria-label** - Good for accessibility-labeled elements
9
+ 3. **role + text** - Semantic matching for buttons, links
10
+ 4. **name attribute** - Form inputs
11
+ 5. **placeholder** - Input placeholders
12
+ 6. **text content** - Visible text (least stable)
13
+ 7. **CSS selector** - Last resort, most brittle
14
+
15
+ ## Target Types in SceneForge
16
+
17
+ ### Using `type: selector`
18
+
19
+ Direct CSS selector - most flexible but requires maintenance.
20
+
21
+ ```yaml
22
+ target:
23
+ type: selector
24
+ selector: "[data-testid='submit-button']"
25
+ ```
26
+
27
+ **Good selectors:**
28
+ ```yaml
29
+ # data-testid (best)
30
+ selector: "[data-testid='save-btn']"
31
+
32
+ # aria-label
33
+ selector: "[aria-label='Close dialog']"
34
+
35
+ # role with name
36
+ selector: "button[name='submit']"
37
+
38
+ # Unique ID
39
+ selector: "#main-header"
40
+
41
+ # Playwright-specific role selector
42
+ selector: "button:has-text('Save')"
43
+ selector: "role=button[name='Submit']"
44
+ ```
45
+
46
+ **Avoid:**
47
+ ```yaml
48
+ # Fragile class-based selectors
49
+ selector: ".btn.btn-primary.mt-4"
50
+
51
+ # Position-based
52
+ selector: "div > div > button:first-child"
53
+
54
+ # Generated class names
55
+ selector: ".css-1a2b3c"
56
+ ```
57
+
58
+ ### Using `type: button`
59
+
60
+ Match button elements by text, name, or selector.
61
+
62
+ ```yaml
63
+ # By visible text
64
+ target:
65
+ type: button
66
+ text: "Save Changes"
67
+
68
+ # By name attribute
69
+ target:
70
+ type: button
71
+ name: "submit"
72
+
73
+ # By selector (fallback)
74
+ target:
75
+ type: button
76
+ selector: "[data-testid='save']"
77
+ ```
78
+
79
+ ### Using `type: link`
80
+
81
+ Match anchor elements.
82
+
83
+ ```yaml
84
+ target:
85
+ type: link
86
+ text: "Learn More"
87
+ ```
88
+
89
+ ### Using `type: input`
90
+
91
+ Match form input elements.
92
+
93
+ ```yaml
94
+ # By name (most common)
95
+ target:
96
+ type: input
97
+ name: "email"
98
+
99
+ # By placeholder text
100
+ target:
101
+ type: input
102
+ text: "Enter your email"
103
+
104
+ # By selector
105
+ target:
106
+ type: input
107
+ selector: "[data-testid='email-input']"
108
+ ```
109
+
110
+ ### Using `type: text`
111
+
112
+ Match any element containing specific text.
113
+
114
+ ```yaml
115
+ target:
116
+ type: text
117
+ text: "Welcome back!"
118
+ ```
119
+
120
+ **Use for:**
121
+ - Headings and labels
122
+ - Menu items
123
+ - Any element identified by its text content
124
+
125
+ ## Playwright Selector Syntax
126
+
127
+ SceneForge uses Playwright under the hood. You can use Playwright's selector syntax:
128
+
129
+ ### Role Selectors
130
+ ```yaml
131
+ selector: "role=button[name='Submit']"
132
+ selector: "role=link[name='Dashboard']"
133
+ selector: "role=textbox[name='Email']"
134
+ ```
135
+
136
+ ### Text Selectors
137
+ ```yaml
138
+ selector: "text=Click here"
139
+ selector: "text=/welcome/i" # Regex, case-insensitive
140
+ ```
141
+
142
+ ### Has-text Selectors
143
+ ```yaml
144
+ selector: "button:has-text('Save')"
145
+ selector: "div:has-text('Loading')"
146
+ ```
147
+
148
+ ### Combining Selectors
149
+ ```yaml
150
+ selector: ".modal >> button:has-text('Confirm')"
151
+ selector: "[data-testid='form'] >> input[name='email']"
152
+ ```
153
+
154
+ ## Common Patterns
155
+
156
+ ### Dropdown/Select
157
+ ```yaml
158
+ # Click to open dropdown
159
+ - action: click
160
+ target:
161
+ type: selector
162
+ selector: "[data-testid='country-select']"
163
+
164
+ # Click option
165
+ - action: click
166
+ target:
167
+ type: text
168
+ text: "United States"
169
+ ```
170
+
171
+ ### Modal Dialog
172
+ ```yaml
173
+ # Wait for modal
174
+ - action: wait
175
+ waitFor:
176
+ type: selector
177
+ value: ".modal-content"
178
+
179
+ # Click modal button
180
+ - action: click
181
+ target:
182
+ type: selector
183
+ selector: ".modal-content >> button:has-text('Confirm')"
184
+ ```
185
+
186
+ ### Dynamic Content
187
+ ```yaml
188
+ # Wait for async content
189
+ - action: wait
190
+ waitFor:
191
+ type: selectorHidden
192
+ value: ".skeleton-loader"
193
+
194
+ # Now interact with loaded content
195
+ - action: click
196
+ target:
197
+ type: selector
198
+ selector: "[data-testid='data-row-1']"
199
+ ```
200
+
201
+ ### Form Inputs
202
+ ```yaml
203
+ # Input with label
204
+ target:
205
+ type: selector
206
+ selector: "label:has-text('Email') >> input"
207
+
208
+ # Input by placeholder
209
+ target:
210
+ type: selector
211
+ selector: "[placeholder='Enter email address']"
212
+ ```
213
+
214
+ ## Debugging Selectors
215
+
216
+ Run the demo in headed mode to verify selectors:
217
+
218
+ ```bash
219
+ sceneforge record --definition demo.yaml --headed
220
+ ```
221
+
222
+ Use browser DevTools to:
223
+ 1. Inspect element attributes
224
+ 2. Test selectors in console: `document.querySelector('[data-testid="x"]')`
225
+ 3. Check for unique identifiers
226
+
227
+ ## Selector Stability Tips
228
+
229
+ 1. **Request data-testid**: Ask developers to add test IDs
230
+ 2. **Use aria-labels**: Good for accessibility anyway
231
+ 3. **Avoid CSS classes**: Often change with styling updates
232
+ 4. **Avoid deep nesting**: Use direct selectors when possible
233
+ 5. **Test after UI changes**: Re-verify selectors periodically
@@ -0,0 +1,210 @@
1
+ # SceneForge YAML Schema Reference
2
+
3
+ ## Demo Definition Structure
4
+
5
+ ```yaml
6
+ version: 1
7
+ name: demo-name # Identifier (used for output folders)
8
+ title: "Demo Title" # Display title
9
+ description: "Optional description"
10
+ steps:
11
+ - id: step-1
12
+ script: "Voiceover text for this step"
13
+ actions:
14
+ - action: navigate
15
+ path: /page-path
16
+ - action: click
17
+ target:
18
+ type: button
19
+ text: "Click Me"
20
+ ```
21
+
22
+ ## Root Properties
23
+
24
+ | Property | Type | Required | Description |
25
+ |----------|------|----------|-------------|
26
+ | `version` | number | No | Schema version (default: 1) |
27
+ | `name` | string | Yes | Demo identifier for output folders |
28
+ | `title` | string | Yes | Display title for the demo |
29
+ | `description` | string | No | Optional description |
30
+ | `steps` | DemoStep[] | Yes | Array of demo steps |
31
+ | `media` | MediaConfig | No | Intro/outro and music config |
32
+
33
+ ## DemoStep
34
+
35
+ | Property | Type | Required | Description |
36
+ |----------|------|----------|-------------|
37
+ | `id` | string | Yes | Unique step identifier |
38
+ | `script` | string | Yes | Voiceover text (can be empty string) |
39
+ | `actions` | DemoAction[] | Yes | Array of actions to execute |
40
+
41
+ ## DemoAction Types
42
+
43
+ ### navigate
44
+ Navigate to a URL path.
45
+ ```yaml
46
+ - action: navigate
47
+ path: /dashboard
48
+ waitFor: # Optional
49
+ type: idle
50
+ ```
51
+
52
+ ### click
53
+ Click on an element.
54
+ ```yaml
55
+ - action: click
56
+ target:
57
+ type: button
58
+ text: "Submit"
59
+ highlight: true # Optional: visual highlight
60
+ waitFor: # Optional
61
+ type: selector
62
+ value: ".success-message"
63
+ ```
64
+
65
+ ### type
66
+ Type text into an input.
67
+ ```yaml
68
+ - action: type
69
+ target:
70
+ type: input
71
+ name: email
72
+ text: "user@example.com"
73
+ ```
74
+
75
+ ### hover
76
+ Hover over an element.
77
+ ```yaml
78
+ - action: hover
79
+ target:
80
+ type: selector
81
+ selector: "[data-testid='menu']"
82
+ ```
83
+
84
+ ### scroll
85
+ Scroll the page by duration.
86
+ ```yaml
87
+ - action: scroll
88
+ duration: 1000 # Scroll for 1 second
89
+ ```
90
+
91
+ ### scrollTo
92
+ Scroll to bring an element into view.
93
+ ```yaml
94
+ - action: scrollTo
95
+ target:
96
+ type: text
97
+ text: "Section Title"
98
+ ```
99
+
100
+ ### wait
101
+ Wait for duration or condition.
102
+ ```yaml
103
+ # Wait for fixed duration
104
+ - action: wait
105
+ duration: 2000 # 2 seconds
106
+
107
+ # Wait for condition
108
+ - action: wait
109
+ waitFor:
110
+ type: selector
111
+ value: ".loaded"
112
+ timeout: 10000 # Optional timeout
113
+ ```
114
+
115
+ ### upload
116
+ Upload a file.
117
+ ```yaml
118
+ - action: upload
119
+ file: ./assets/document.pdf
120
+ target: # Optional: specific file input
121
+ type: selector
122
+ selector: "input[type='file']"
123
+ ```
124
+
125
+ ### drag
126
+ Drag an element.
127
+ ```yaml
128
+ - action: drag
129
+ target:
130
+ type: selector
131
+ selector: ".draggable"
132
+ drag:
133
+ deltaX: 100
134
+ deltaY: 50
135
+ steps: 10 # Optional: smoothness
136
+ ```
137
+
138
+ ## StepTarget Types
139
+
140
+ | Type | Required Fields | Description |
141
+ |------|-----------------|-------------|
142
+ | `button` | `text`, `name`, or `selector` | Match a button element |
143
+ | `link` | `text`, `name`, or `selector` | Match a link element |
144
+ | `input` | `text`, `name`, or `selector` | Match an input element |
145
+ | `text` | `text` | Match element containing text |
146
+ | `selector` | `selector` | Match by CSS selector |
147
+
148
+ ### Target Examples
149
+ ```yaml
150
+ # By visible text
151
+ target:
152
+ type: button
153
+ text: "Save Changes"
154
+
155
+ # By name attribute
156
+ target:
157
+ type: input
158
+ name: "username"
159
+
160
+ # By CSS selector
161
+ target:
162
+ type: selector
163
+ selector: "[data-testid='submit-btn']"
164
+ ```
165
+
166
+ ## WaitCondition Types
167
+
168
+ | Type | Requires Value | Description |
169
+ |------|----------------|-------------|
170
+ | `text` | Yes | Wait for text to appear |
171
+ | `selector` | Yes | Wait for selector to match |
172
+ | `textHidden` | Yes | Wait for text to disappear |
173
+ | `selectorHidden` | Yes | Wait for selector to disappear |
174
+ | `navigation` | No | Wait for page navigation |
175
+ | `idle` | No | Wait for network idle |
176
+
177
+ ### WaitCondition Examples
178
+ ```yaml
179
+ waitFor:
180
+ type: text
181
+ value: "Success!"
182
+ timeout: 5000
183
+
184
+ waitFor:
185
+ type: selectorHidden
186
+ value: ".loading-spinner"
187
+ ```
188
+
189
+ ## Media Configuration
190
+
191
+ ```yaml
192
+ media:
193
+ intro:
194
+ file: ./assets/intro.mp4
195
+ duration: 5 # Optional: trim to seconds
196
+ fade: true
197
+ fadeDuration: 0.5
198
+ outro:
199
+ file: ./assets/outro.mp4
200
+ backgroundMusic:
201
+ file: ./assets/music.mp3
202
+ volume: 0.15
203
+ loop: true
204
+ fadeIn: 2
205
+ fadeOut: 2
206
+ startAt:
207
+ type: afterIntro
208
+ endAt:
209
+ type: beforeOutro
210
+ ```
@@ -0,0 +1,136 @@
1
+ # Skill: Balance Timing
2
+
3
+ Analyze and balance the timing between script duration and action duration in a SceneForge demo.
4
+
5
+ ## Task
6
+
7
+ Review timing data from the scripts JSON and suggest adjustments to achieve better synchronization.
8
+
9
+ ## Input Required
10
+
11
+ Provide the following:
12
+ - **Scripts JSON data**: Content from `output/<demo>/scripts/<demo>-scripts.json`
13
+ - **Problem steps**: Steps with timing issues (optional)
14
+ - **Constraints**: Any timing requirements (optional)
15
+
16
+ ## Analysis Process
17
+
18
+ ### Step 1: Calculate Timing Difference
19
+
20
+ For each step:
21
+ ```
22
+ difference = stepTimingMs - estimatedDurationMs
23
+ ```
24
+
25
+ - **Positive**: Actions take longer than voiceover
26
+ - **Negative**: Voiceover takes longer than actions
27
+
28
+ ### Step 2: Categorize Issues
29
+
30
+ | Difference | Severity | Action Needed |
31
+ |------------|----------|---------------|
32
+ | ±500ms | Minor | Usually acceptable |
33
+ | 500-1500ms | Moderate | Consider adjustment |
34
+ | >1500ms | Significant | Must adjust |
35
+
36
+ ### Step 3: Recommend Solutions
37
+
38
+ ## Output Format
39
+
40
+ Provide a timing analysis report with:
41
+ 1. Summary of all steps with issues
42
+ 2. Recommended adjustments per step
43
+ 3. Updated YAML snippets
44
+
45
+ ## Example Analysis
46
+
47
+ ### Input Data
48
+ ```json
49
+ {
50
+ "steps": [
51
+ {
52
+ "stepId": "intro",
53
+ "estimatedDurationMs": 4800,
54
+ "stepTimingMs": 2000,
55
+ "wordCount": 12
56
+ },
57
+ {
58
+ "stepId": "fill-form",
59
+ "estimatedDurationMs": 3600,
60
+ "stepTimingMs": 6000,
61
+ "wordCount": 9
62
+ }
63
+ ]
64
+ }
65
+ ```
66
+
67
+ ### Analysis Output
68
+
69
+ ```
70
+ ## Timing Analysis Report
71
+
72
+ ### Step: intro
73
+ - Script duration: 4800ms (12 words)
74
+ - Video duration: 2000ms
75
+ - Difference: -2800ms (voiceover too long)
76
+
77
+ **Recommendation:** Add wait action to extend step duration
78
+
79
+ ```yaml
80
+ - id: intro
81
+ script: "Welcome to this demo..."
82
+ actions:
83
+ - action: wait
84
+ duration: 5000 # Extended from 2000ms
85
+ ```
86
+
87
+ ### Step: fill-form
88
+ - Script duration: 3600ms (9 words)
89
+ - Video duration: 6000ms
90
+ - Difference: +2400ms (video has dead air)
91
+
92
+ **Recommendation:** Expand script to fill time
93
+
94
+ **Current script (9 words):**
95
+ "Enter your details in the form below."
96
+
97
+ **Suggested script (15 words):**
98
+ "Enter your details in the form below. We'll add your name, email, and message."
99
+ ```
100
+
101
+ ## Adjustment Strategies
102
+
103
+ ### When Video > Script (Dead Air)
104
+
105
+ **Option 1: Expand script**
106
+ - Add more context or explanation
107
+ - Describe what user should notice
108
+ - Preview next step
109
+
110
+ **Option 2: Split into multiple steps**
111
+ - If step has distinct phases
112
+ - Each gets focused narration
113
+
114
+ ### When Script > Video (Overlap Risk)
115
+
116
+ **Option 1: Add wait action**
117
+ ```yaml
118
+ actions:
119
+ - action: click
120
+ target: ...
121
+ - action: wait
122
+ duration: 2000 # Added padding
123
+ ```
124
+
125
+ **Option 2: Shorten script**
126
+ - Remove redundant words
127
+ - Focus on essential information
128
+ - Split long sentences
129
+
130
+ ## Checklist
131
+
132
+ - [ ] All steps analyzed for timing variance
133
+ - [ ] Significant issues identified
134
+ - [ ] Solutions provided for each issue
135
+ - [ ] Updated YAML snippets included
136
+ - [ ] Total runtime remains reasonable