@mytechtoday/augment-extensions 2.3.7 → 2.5.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 (48) hide show
  1. package/augment-extensions/writing-standards/screenplay/commercials/CHARACTER-COUNT-TRACKING.md +226 -0
  2. package/augment-extensions/writing-standards/screenplay/commercials/CONFIGURATION.md +327 -0
  3. package/augment-extensions/writing-standards/screenplay/commercials/README.md +223 -0
  4. package/augment-extensions/writing-standards/screenplay/commercials/REFACTORING-SUMMARY.md +193 -0
  5. package/augment-extensions/writing-standards/screenplay/commercials/REFERENCES.md +157 -0
  6. package/augment-extensions/writing-standards/screenplay/commercials/VALIDATION-REPORT.md +109 -0
  7. package/augment-extensions/writing-standards/screenplay/commercials/examples/.gitkeep +0 -0
  8. package/augment-extensions/writing-standards/screenplay/commercials/module.json +111 -0
  9. package/augment-extensions/writing-standards/screenplay/commercials/rules/.gitkeep +0 -0
  10. package/augment-extensions/writing-standards/screenplay/commercials/rules/commercial-audience.md +343 -0
  11. package/augment-extensions/writing-standards/screenplay/commercials/rules/commercial-formats.md +396 -0
  12. package/augment-extensions/writing-standards/screenplay/commercials/rules/commercial-persuasion.md +387 -0
  13. package/augment-extensions/writing-standards/screenplay/commercials/rules/commercial-scripts.md +531 -0
  14. package/augment-extensions/writing-standards/screenplay/commercials/rules/commercial-techniques.md +912 -0
  15. package/augment-extensions/writing-standards/screenplay/commercials/rules/commercial-types.md +700 -0
  16. package/augment-extensions/writing-standards/screenplay/commercials/rules/commercials.md +285 -0
  17. package/augment-extensions/writing-standards/screenplay/commercials/scripts/validate-character-count.ts +284 -0
  18. package/cli/dist/commands/generate-shot-list/generator/ai-blocking-extractor.d.ts +58 -0
  19. package/cli/dist/commands/generate-shot-list/generator/ai-blocking-extractor.d.ts.map +1 -0
  20. package/cli/dist/commands/generate-shot-list/generator/ai-blocking-extractor.js +275 -0
  21. package/cli/dist/commands/generate-shot-list/generator/ai-blocking-extractor.js.map +1 -0
  22. package/cli/dist/commands/generate-shot-list/generator/ai-entity-extractor.d.ts +41 -0
  23. package/cli/dist/commands/generate-shot-list/generator/ai-entity-extractor.d.ts.map +1 -0
  24. package/cli/dist/commands/generate-shot-list/generator/ai-entity-extractor.js +155 -0
  25. package/cli/dist/commands/generate-shot-list/generator/ai-entity-extractor.js.map +1 -0
  26. package/cli/dist/commands/generate-shot-list/generator/context-builder.d.ts +65 -2
  27. package/cli/dist/commands/generate-shot-list/generator/context-builder.d.ts.map +1 -1
  28. package/cli/dist/commands/generate-shot-list/generator/context-builder.js +394 -98
  29. package/cli/dist/commands/generate-shot-list/generator/context-builder.js.map +1 -1
  30. package/cli/dist/commands/generate-shot-list/generator/index.d.ts +59 -1
  31. package/cli/dist/commands/generate-shot-list/generator/index.d.ts.map +1 -1
  32. package/cli/dist/commands/generate-shot-list/generator/index.js +364 -34
  33. package/cli/dist/commands/generate-shot-list/generator/index.js.map +1 -1
  34. package/cli/dist/commands/generate-shot-list/generator/types.d.ts +3 -2
  35. package/cli/dist/commands/generate-shot-list/generator/types.d.ts.map +1 -1
  36. package/cli/dist/commands/generate-shot-list/generator/validator.d.ts +33 -0
  37. package/cli/dist/commands/generate-shot-list/generator/validator.d.ts.map +1 -1
  38. package/cli/dist/commands/generate-shot-list/generator/validator.js +167 -0
  39. package/cli/dist/commands/generate-shot-list/generator/validator.js.map +1 -1
  40. package/cli/dist/commands/generate-shot-list/help-text.d.ts +1 -1
  41. package/cli/dist/commands/generate-shot-list/help-text.d.ts.map +1 -1
  42. package/cli/dist/commands/generate-shot-list/help-text.js +11 -0
  43. package/cli/dist/commands/generate-shot-list/help-text.js.map +1 -1
  44. package/cli/dist/commands/generate-shot-list.d.ts +1 -0
  45. package/cli/dist/commands/generate-shot-list.d.ts.map +1 -1
  46. package/cli/dist/commands/generate-shot-list.js +7 -4
  47. package/cli/dist/commands/generate-shot-list.js.map +1 -1
  48. package/package.json +5 -1
@@ -0,0 +1,285 @@
1
+ # Commercial Writing: Core Principles
2
+
3
+ ## Overview
4
+
5
+ Commercial writing is the art of persuasive storytelling within strict time constraints. Whether creating a 15-second spot or a 60-second narrative, the goal is to capture attention, communicate value, and inspire action—all while maintaining brand integrity and legal compliance.
6
+
7
+ ## The Five Pillars of Effective Commercial Writing
8
+
9
+ ### 1. Clear Messaging
10
+
11
+ **Principle:** One commercial, one message. Trying to communicate multiple ideas dilutes impact and confuses viewers.
12
+
13
+ **Best Practices:**
14
+ - Identify the single most important message before writing
15
+ - Every element (visual, audio, dialogue) should support this message
16
+ - Test your message: Can a viewer recall it 24 hours later?
17
+ - Avoid jargon, complex terminology, or industry-speak
18
+ - Use simple, direct language that resonates with your target audience
19
+
20
+ **Example - Clear vs. Unclear:**
21
+
22
+ ```
23
+ ❌ UNCLEAR (30-second car commercial):
24
+ "The new Apex sedan features advanced safety technology,
25
+ best-in-class fuel efficiency, premium leather interior,
26
+ cutting-edge infotainment system, and award-winning design."
27
+
28
+ ✅ CLEAR (30-second car commercial):
29
+ "The new Apex sedan. The safest car we've ever built."
30
+ (All visuals and copy support this single safety message)
31
+ ```
32
+
33
+ ### 2. Strong Call-to-Action (CTA)
34
+
35
+ **Principle:** Every commercial must tell viewers exactly what to do next. A weak or missing CTA wastes the entire investment.
36
+
37
+ **Best Practices:**
38
+ - Place CTA in final 5-10 seconds (depending on length)
39
+ - Use action verbs: "Visit," "Call," "Download," "Try," "Shop"
40
+ - Make it specific: "Visit dealership.com/test-drive" not just "Visit our website"
41
+ - Include urgency when appropriate: "Limited time offer," "While supplies last"
42
+ - Ensure CTA is visually and audibly clear (on-screen text + voiceover)
43
+
44
+ **CTA Strength Hierarchy:**
45
+ 1. **Strongest:** Specific action + deadline ("Order by midnight for 50% off")
46
+ 2. **Strong:** Specific action + incentive ("Visit today for free consultation")
47
+ 3. **Moderate:** Specific action ("Download the app now")
48
+ 4. **Weak:** Generic action ("Learn more online")
49
+ 5. **Weakest:** No action ("Brand X. We're here.")
50
+
51
+ **Example - Strong CTA:**
52
+
53
+ ```
54
+ VOICEOVER
55
+ Visit TryApex.com slash safety to schedule
56
+ your test drive. That's TryApex.com slash safety.
57
+
58
+ ON-SCREEN TEXT
59
+ TryApex.com/safety
60
+ ```
61
+
62
+ ### 3. Memorable Hook
63
+
64
+ **Principle:** You have 2-3 seconds to capture attention before viewers tune out. The hook is everything.
65
+
66
+ **Hook Types:**
67
+ - **Visual Hook:** Unexpected imagery, striking visuals, pattern interruption
68
+ - **Audio Hook:** Distinctive sound, music sting, silence, unexpected noise
69
+ - **Narrative Hook:** Question, conflict, relatable problem, surprising statement
70
+ - **Emotional Hook:** Humor, nostalgia, fear, joy, surprise
71
+
72
+ **Best Practices:**
73
+ - Open with the hook—don't build up to it
74
+ - Make it relevant to your message (not just attention-grabbing)
75
+ - Test hooks with target audience before production
76
+ - Avoid clichés: babies, puppies, explosions (unless truly original)
77
+
78
+ **Example - Effective Hooks:**
79
+
80
+ ```
81
+ VISUAL HOOK:
82
+ [OPEN ON: A car driving normally, suddenly flips upside-down]
83
+ [REVEAL: It's a toy car in a child's hand]
84
+ VOICEOVER: "When you're a parent, everything feels like a crash test."
85
+
86
+ AUDIO HOOK:
87
+ [OPEN ON: Complete silence. No music, no sound]
88
+ [5 seconds of silence]
89
+ VOICEOVER (whisper): "Noise-canceling headphones that actually work."
90
+
91
+ NARRATIVE HOOK:
92
+ [OPEN ON: Woman at laptop, frustrated]
93
+ WOMAN: "I've been on hold for 47 minutes."
94
+ VOICEOVER: "There's a better way."
95
+ ```
96
+
97
+ ### 4. Emotional Connection
98
+
99
+ **Principle:** People buy with emotion and justify with logic. Create an emotional response first, then support with rational benefits.
100
+
101
+ **Emotional Triggers:**
102
+ - **Joy/Happiness:** Celebrations, achievements, family moments
103
+ - **Fear/Anxiety:** Loss prevention, security, safety
104
+ - **Nostalgia:** "Remember when," throwback aesthetics, familiar music
105
+ - **Aspiration:** "Be like this," lifestyle upgrade, status
106
+ - **Belonging:** Community, shared values, "people like you"
107
+ - **Relief:** Problem solved, stress removed, simplification
108
+
109
+ **Best Practices:**
110
+ - Choose ONE primary emotion per commercial
111
+ - Show emotion through characters, not just tell through copy
112
+ - Use music to amplify emotional tone
113
+ - Authentic emotion beats manufactured sentiment
114
+ - Test emotional resonance with focus groups
115
+
116
+ **Example - Emotional Connection:**
117
+
118
+ ```
119
+ [OPEN ON: Elderly man sitting alone at kitchen table]
120
+ [He opens a video call on tablet]
121
+ [Grandchildren appear on screen, waving]
122
+ GRANDKIDS (V.O.): "Hi Grandpa!"
123
+ [Man's face lights up with genuine joy]
124
+ VOICEOVER: "Stay connected to what matters."
125
+ [SUPER: FamilyConnect Video Calling]
126
+ ```
127
+
128
+ ### 5. Audience Targeting
129
+
130
+ **Principle:** A commercial for everyone is a commercial for no one. Know exactly who you're talking to and speak their language.
131
+
132
+ **Targeting Dimensions:**
133
+ - **Demographics:** Age, gender, income, education, location
134
+ - **Psychographics:** Values, interests, lifestyle, attitudes
135
+ - **Behavioral:** Purchase history, brand loyalty, media consumption
136
+ - **Situational:** Life stage, current needs, pain points
137
+
138
+ **Best Practices:**
139
+ - Create detailed audience personas before writing
140
+ - Use language, references, and cultural touchpoints that resonate
141
+ - Cast talent that reflects your target audience
142
+ - Choose media placement that reaches your audience
143
+ - Avoid alienating non-target audiences (unless intentional)
144
+
145
+ **Example - Targeted Messaging:**
146
+
147
+ ```
148
+ MILLENNIAL AUDIENCE (Streaming service):
149
+ [OPEN ON: Young professional on couch, scrolling phone]
150
+ VOICEOVER: "Another Friday night, another 45 minutes
151
+ deciding what to watch."
152
+ [App interface appears]
153
+ VOICEOVER: "StreamPick AI knows what you'll love.
154
+ No more scrolling. Just watching."
155
+
156
+ BOOMER AUDIENCE (Same service):
157
+ [OPEN ON: Couple in living room, confused by remote]
158
+ VOICEOVER: "Remember when TV was simple?"
159
+ [Simple interface appears]
160
+ VOICEOVER: "StreamPick. All your favorites.
161
+ One button. No confusion."
162
+ ```
163
+
164
+ ## The Commercial Writing Formula
165
+
166
+ ### 3-Act Structure (Adapted for Commercials)
167
+
168
+ **Act 1: Problem/Hook (First 20-30%)**
169
+ - Establish relatable problem or capture attention
170
+ - Introduce conflict or need
171
+ - Create curiosity or concern
172
+
173
+ **Act 2: Solution (Middle 40-50%)**
174
+ - Introduce product/service as solution
175
+ - Demonstrate key benefit
176
+ - Show transformation or resolution
177
+
178
+ **Act 3: Call-to-Action (Final 20-30%)**
179
+ - Reinforce benefit
180
+ - Clear, specific CTA
181
+ - Brand reinforcement
182
+
183
+ **Example - 30-Second Structure:**
184
+
185
+ ```
186
+ ACT 1 (0:00-0:08) - PROBLEM
187
+ [Woman at desk, surrounded by paperwork, stressed]
188
+ WOMAN: "I spend more time doing paperwork than
189
+ seeing patients."
190
+
191
+ ACT 2 (0:09-0:22) - SOLUTION
192
+ [She opens laptop, uses software]
193
+ VOICEOVER: "MediFlow automates your admin.
194
+ Charts, billing, scheduling—done."
195
+ [She closes laptop, smiles]
196
+
197
+ ACT 3 (0:23-0:30) - CTA
198
+ VOICEOVER: "Try MediFlow free for 30 days.
199
+ Visit MediFlow.com."
200
+ [SUPER: MediFlow.com - 30 Day Free Trial]
201
+ ```
202
+
203
+ ## Common Pitfalls to Avoid
204
+
205
+ ### 1. Feature Dumping
206
+ **Problem:** Listing every product feature instead of focusing on benefits
207
+ **Solution:** Choose 1-2 key benefits that matter most to your audience
208
+
209
+ ### 2. Weak Opening
210
+ **Problem:** Slow build-up, logo first, generic establishing shots
211
+ **Solution:** Hook in first 2-3 seconds, logo at end
212
+
213
+ ### 3. Unclear Brand
214
+ **Problem:** Viewer can't remember who the commercial was for
215
+ **Solution:** Brand integration throughout, not just end card
216
+
217
+ ### 4. No Differentiation
218
+ **Problem:** Could be any competitor's commercial
219
+ **Solution:** Unique selling proposition, distinctive creative approach
220
+
221
+ ### 5. Overproduction
222
+ **Problem:** Style over substance, effects overshadow message
223
+ **Solution:** Serve the message, not the ego
224
+
225
+ ## Writing for Different Commercial Lengths
226
+
227
+ ### 15-Second Spots
228
+ - **One idea only**
229
+ - Hook + benefit + CTA
230
+ - No time for storytelling
231
+ - Every word counts
232
+ - Often used for brand awareness or simple promotions
233
+
234
+ ### 30-Second Spots
235
+ - **Industry standard**
236
+ - Room for simple narrative
237
+ - Problem-solution structure works well
238
+ - 2-3 key points maximum
239
+ - Most versatile length
240
+
241
+ ### 60-Second Spots
242
+ - **Premium storytelling**
243
+ - Full narrative arc possible
244
+ - Emotional depth achievable
245
+ - Multiple benefits can be shown
246
+ - Higher production value expected
247
+
248
+ ## Integration with Brand Guidelines
249
+
250
+ Every commercial must align with:
251
+ - **Brand Voice:** Tone, personality, language style
252
+ - **Brand Values:** What the company stands for
253
+ - **Visual Identity:** Colors, fonts, logo usage
254
+ - **Messaging Hierarchy:** Primary and secondary messages
255
+ - **Legal Requirements:** Disclaimers, disclosures, compliance
256
+
257
+ ## Measurement and Optimization
258
+
259
+ **Key Performance Indicators (KPIs):**
260
+ - **Awareness:** Brand recall, message retention
261
+ - **Engagement:** View-through rate, social shares
262
+ - **Action:** Click-through rate, conversions, sales lift
263
+ - **Efficiency:** Cost per acquisition, return on ad spend
264
+
265
+ **A/B Testing Opportunities:**
266
+ - Different hooks (first 3 seconds)
267
+ - CTA variations (wording, placement, urgency)
268
+ - Emotional tone (humor vs. serious)
269
+ - Talent/casting choices
270
+ - Music/audio approaches
271
+
272
+ ## Conclusion
273
+
274
+ Effective commercial writing combines art and science: the art of storytelling and emotional connection, the science of persuasion and measurement. Master these five pillars—clear messaging, strong CTAs, memorable hooks, emotional connection, and precise targeting—and you'll create commercials that not only capture attention but drive real business results.
275
+
276
+ Remember: In commercial writing, every second counts, every word matters, and every element must earn its place. Be ruthless in editing, relentless in testing, and always put your audience first.
277
+
278
+ ---
279
+
280
+ **Next Steps:**
281
+ - Review [Commercial Formats](./commercial-formats.md) for duration-specific guidelines
282
+ - Explore [Commercial Types](./commercial-types.md) for category-specific best practices
283
+ - Study [Persuasion Techniques](./commercial-persuasion.md) for advanced strategies
284
+ - Consult [Legal Compliance](./commercial-laws.md) before production
285
+
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Validate Character Count for Commercials Module
4
+ * Version: 3.0.0
5
+ * Last Updated: 2026-03-03
6
+ *
7
+ * Validates that each individual content file is between 3,000 and 45,000 characters
8
+ *
9
+ * Usage:
10
+ * npx tsx validate-character-count.ts [--verbose] [--json]
11
+ * npm run validate:commercials [-- --verbose] [-- --json]
12
+ */
13
+
14
+ import * as fs from 'fs';
15
+ import * as path from 'path';
16
+ import * as process from 'process';
17
+
18
+ // Configuration
19
+ const FILE_MIN = 3000;
20
+ const FILE_MAX = 45000;
21
+
22
+ const EXCLUDED_FILES = [
23
+ 'module.json',
24
+ 'README.md',
25
+ 'CONFIGURATION.md',
26
+ 'REFERENCES.md',
27
+ 'CHARACTER-COUNT-TRACKING.md',
28
+ 'VALIDATION-REPORT.md'
29
+ ];
30
+
31
+ // Color codes for terminal output
32
+ const colors = {
33
+ reset: '\x1b[0m',
34
+ cyan: '\x1b[36m',
35
+ green: '\x1b[32m',
36
+ red: '\x1b[31m',
37
+ gray: '\x1b[90m',
38
+ white: '\x1b[37m',
39
+ yellow: '\x1b[33m'
40
+ };
41
+
42
+ interface FileInfo {
43
+ file: string;
44
+ path: string;
45
+ characters: number;
46
+ status: string;
47
+ statusColor: keyof typeof colors;
48
+ isExcluded: boolean;
49
+ directory: string;
50
+ }
51
+
52
+ interface ValidationResult {
53
+ totalCharacters: number;
54
+ fileMin: number;
55
+ fileMax: number;
56
+ status: 'PASS' | 'FAIL';
57
+ message: string;
58
+ passedFiles: number;
59
+ failedFiles: number;
60
+ files: FileInfo[];
61
+ }
62
+
63
+ // Parse command line arguments
64
+ const args = process.argv.slice(2);
65
+ const verbose = args.includes('--verbose') || args.includes('-v');
66
+ const jsonOutput = args.includes('--json') || args.includes('-j');
67
+
68
+ // Get module root (parent of scripts directory)
69
+ const moduleRoot = path.resolve(__dirname, '..');
70
+
71
+ /**
72
+ * Find all markdown files recursively
73
+ */
74
+ function findMarkdownFiles(dir: string): string[] {
75
+ const files: string[] = [];
76
+
77
+ function traverse(currentDir: string) {
78
+ const entries = fs.readdirSync(currentDir, { withFileTypes: true });
79
+
80
+ for (const entry of entries) {
81
+ const fullPath = path.join(currentDir, entry.name);
82
+
83
+ if (entry.isDirectory()) {
84
+ traverse(fullPath);
85
+ } else if (entry.isFile() && entry.name.endsWith('.md')) {
86
+ files.push(fullPath);
87
+ }
88
+ }
89
+ }
90
+
91
+ traverse(dir);
92
+ return files;
93
+ }
94
+
95
+ /**
96
+ * Validate character counts
97
+ */
98
+ function validateCharacterCounts(): ValidationResult {
99
+ const markdownFiles = findMarkdownFiles(moduleRoot);
100
+ const fileBreakdown: FileInfo[] = [];
101
+ let totalChars = 0;
102
+ let passedCount = 0;
103
+ let failedCount = 0;
104
+
105
+ for (const filePath of markdownFiles) {
106
+ const fileName = path.basename(filePath);
107
+ const relativePath = path.relative(moduleRoot, filePath);
108
+ const directory = path.basename(path.dirname(filePath));
109
+ const isExcluded = EXCLUDED_FILES.includes(fileName);
110
+
111
+ const content = fs.readFileSync(filePath, 'utf-8');
112
+ const charCount = content.length;
113
+ totalChars += charCount;
114
+
115
+ let status: string;
116
+ let statusColor: keyof typeof colors;
117
+
118
+ if (isExcluded) {
119
+ status = 'EXCLUDED';
120
+ statusColor = 'gray';
121
+ } else if (charCount >= FILE_MIN && charCount <= FILE_MAX) {
122
+ status = 'PASS';
123
+ statusColor = 'green';
124
+ passedCount++;
125
+ } else if (charCount < FILE_MIN) {
126
+ const deficit = FILE_MIN - charCount;
127
+ status = `FAIL (too short by ${deficit} chars)`;
128
+ statusColor = 'red';
129
+ failedCount++;
130
+ } else {
131
+ const excess = charCount - FILE_MAX;
132
+ status = `FAIL (too long by ${excess} chars)`;
133
+ statusColor = 'red';
134
+ failedCount++;
135
+ }
136
+
137
+ fileBreakdown.push({
138
+ file: fileName,
139
+ path: relativePath,
140
+ characters: charCount,
141
+ status,
142
+ statusColor,
143
+ isExcluded,
144
+ directory
145
+ });
146
+ }
147
+
148
+ const overallStatus: 'PASS' | 'FAIL' = failedCount === 0 ? 'PASS' : 'FAIL';
149
+ const message = failedCount === 0
150
+ ? 'All content files within 3,000 - 45,000 character range'
151
+ : `${failedCount} file(s) outside target range`;
152
+
153
+ return {
154
+ totalCharacters: totalChars,
155
+ fileMin: FILE_MIN,
156
+ fileMax: FILE_MAX,
157
+ status: overallStatus,
158
+ message,
159
+ passedFiles: passedCount,
160
+ failedFiles: failedCount,
161
+ files: fileBreakdown
162
+ };
163
+ }
164
+
165
+ /**
166
+ * Print colored text to console
167
+ */
168
+ function printColor(text: string, color: keyof typeof colors) {
169
+ console.log(`${colors[color]}${text}${colors.reset}`);
170
+ }
171
+
172
+ /**
173
+ * Print validation results to console
174
+ */
175
+ function printResults(result: ValidationResult) {
176
+ console.log('');
177
+ printColor('=== Commercial Writing Standards - Per-File Character Count Validation ===', 'cyan');
178
+ printColor(`Per-File Target Range: ${FILE_MIN} - ${FILE_MAX} characters`, 'gray');
179
+ printColor(`Total Module Characters: ${result.totalCharacters}`, 'white');
180
+ console.log('');
181
+
182
+ const symbol = result.status === 'PASS' ? '✓' : '✗';
183
+ printColor(`${symbol} ${result.status} : ${result.message}`, result.status === 'PASS' ? 'green' : 'red');
184
+
185
+ // Show failed files prominently
186
+ const failedFiles = result.files.filter(f => f.status.startsWith('FAIL'));
187
+ if (failedFiles.length > 0) {
188
+ console.log('');
189
+ printColor('=== Failed Files ===', 'red');
190
+ for (const file of failedFiles) {
191
+ printColor(` ✗ ${file.file}: ${file.characters} chars - ${file.status}`, 'red');
192
+ }
193
+ }
194
+
195
+ // Verbose output
196
+ if (verbose) {
197
+ console.log('');
198
+ printColor('=== All Files ===', 'cyan');
199
+
200
+ const sortedFiles = [...result.files].sort((a, b) => {
201
+ if (a.isExcluded !== b.isExcluded) return a.isExcluded ? 1 : -1;
202
+ return b.characters - a.characters;
203
+ });
204
+
205
+ for (const file of sortedFiles) {
206
+ const symbol = file.status === 'PASS' ? '✓' : file.status === 'EXCLUDED' ? '○' : '✗';
207
+ printColor(` ${symbol} ${file.file}: ${file.characters} chars - ${file.status}`, file.statusColor);
208
+ }
209
+
210
+ // Category totals
211
+ console.log('');
212
+ printColor('=== Category Totals ===', 'cyan');
213
+
214
+ const categories = {
215
+ 'Foundational Rules': result.files.filter(f => /^commercial(s|-(formats|types))\.md$/.test(f.file)),
216
+ 'Technique Rules': result.files.filter(f => /^commercial-(techniques|persuasion|audience|scripts|tips)\.md$/.test(f.file)),
217
+ 'Legal/Ethical Rules': result.files.filter(f => /^commercial-(laws|ethics)\.md$/.test(f.file)),
218
+ 'Supporting Rules': result.files.filter(f => /^commercial-(counter-principles-examples|templates|mistakes|history|glossary)\.md$/.test(f.file)),
219
+ 'Example Files': result.files.filter(f => /^(effective|ineffective)-commercials\.md$/.test(f.file)),
220
+ 'Infrastructure': result.files.filter(f => f.isExcluded)
221
+ };
222
+
223
+ for (const [category, files] of Object.entries(categories)) {
224
+ if (files.length > 0) {
225
+ const total = files.reduce((sum, f) => sum + f.characters, 0);
226
+ const passCount = files.filter(f => f.status === 'PASS' || f.status === 'EXCLUDED').length;
227
+ printColor(`${category} : ${total} chars - ${files.length} files (${passCount} passing)`, 'white');
228
+ } else {
229
+ printColor(`${category} : 0 chars - 0 files`, 'gray');
230
+ }
231
+ }
232
+
233
+ // Summary
234
+ console.log('');
235
+ printColor('=== Summary ===', 'cyan');
236
+ printColor(`Content Files: ${result.files.length - EXCLUDED_FILES.length}`, 'white');
237
+ printColor(`Passed: ${result.passedFiles}`, 'green');
238
+ printColor(`Failed: ${result.failedFiles}`, result.failedFiles === 0 ? 'green' : 'red');
239
+ printColor(`Excluded: ${EXCLUDED_FILES.length}`, 'gray');
240
+ }
241
+
242
+ console.log('');
243
+ }
244
+
245
+ /**
246
+ * Main execution
247
+ */
248
+ function main() {
249
+ const result = validateCharacterCounts();
250
+
251
+ if (jsonOutput) {
252
+ // JSON output
253
+ const output = {
254
+ totalCharacters: result.totalCharacters,
255
+ fileMin: result.fileMin,
256
+ fileMax: result.fileMax,
257
+ status: result.status,
258
+ message: result.message,
259
+ passedFiles: result.passedFiles,
260
+ failedFiles: result.failedFiles,
261
+ files: result.files.map(f => ({
262
+ file: f.file,
263
+ path: f.path,
264
+ characters: f.characters,
265
+ status: f.status,
266
+ isExcluded: f.isExcluded
267
+ }))
268
+ };
269
+
270
+ console.log(JSON.stringify(output, null, 2));
271
+ } else {
272
+ // Console output
273
+ printResults(result);
274
+ }
275
+
276
+ // Exit with appropriate code
277
+ process.exit(result.status === 'PASS' ? 0 : 1);
278
+ }
279
+
280
+ // Run if executed directly
281
+ if (require.main === module) {
282
+ main();
283
+ }
284
+
@@ -0,0 +1,58 @@
1
+ /**
2
+ * AI-Powered Blocking Extractor
3
+ *
4
+ * Uses Claude Sonnet 4.6 to extract detailed character blocking and spatial positions
5
+ * from screenplay action lines. Infers stage positions, relative positions, and
6
+ * maintains spatial consistency across shots.
7
+ */
8
+ export interface CharacterBlockingPosition {
9
+ character: string;
10
+ position: string;
11
+ stagePosition?: string;
12
+ relativePosition?: string;
13
+ action?: string;
14
+ }
15
+ export interface CharacterDescription {
16
+ character: string;
17
+ physicalAppearance: string;
18
+ wardrobe: string;
19
+ emotion?: string;
20
+ }
21
+ export interface BlockingExtractionResult {
22
+ characterPositions: CharacterBlockingPosition[];
23
+ characterDescriptions: CharacterDescription[];
24
+ setDescription: string;
25
+ characterActions: string[];
26
+ soundEffects: string[];
27
+ }
28
+ export declare class AIBlockingExtractor {
29
+ private client;
30
+ private characterDescriptionCache;
31
+ private styleGuidelines;
32
+ constructor(apiKey?: string, styleGuidelines?: any);
33
+ /**
34
+ * Clear the character description cache (call at start of new screenplay)
35
+ */
36
+ clearCache(): void;
37
+ /**
38
+ * Get cached character description
39
+ */
40
+ getCachedDescription(characterName: string): CharacterDescription | undefined;
41
+ /**
42
+ * Extract blocking, set description, and actions from action lines using AI
43
+ */
44
+ extractBlocking(actionLines: string[], characterNames: string[], previousPositions?: Map<string, CharacterBlockingPosition>): Promise<BlockingExtractionResult>;
45
+ /**
46
+ * Build prompt for AI blocking extraction
47
+ */
48
+ private buildBlockingPrompt;
49
+ /**
50
+ * Parse AI response into structured blocking data
51
+ */
52
+ private parseBlockingResponse;
53
+ /**
54
+ * Fallback extraction when AI fails
55
+ */
56
+ private fallbackExtraction;
57
+ }
58
+ //# sourceMappingURL=ai-blocking-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-blocking-extractor.d.ts","sourceRoot":"","sources":["../../../../src/commands/generate-shot-list/generator/ai-blocking-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,kBAAkB,EAAE,yBAAyB,EAAE,CAAC;IAChD,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,yBAAyB,CAAgD;IACjF,OAAO,CAAC,eAAe,CAAoB;gBAE/B,MAAM,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,GAAG;IAOlD;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAI7E;;OAEG;IACG,eAAe,CACnB,WAAW,EAAE,MAAM,EAAE,EACrB,cAAc,EAAE,MAAM,EAAE,EACxB,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,yBAAyB,CAAC,GACzD,OAAO,CAAC,wBAAwB,CAAC;IAwDpC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgK3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA4B7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAe3B"}