@mclawnet/agent 0.5.8 → 0.6.1

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 (78) hide show
  1. package/cli.js +168 -61
  2. package/dist/__tests__/cli.test.d.ts +2 -0
  3. package/dist/__tests__/cli.test.d.ts.map +1 -0
  4. package/dist/__tests__/service-config.test.d.ts +2 -0
  5. package/dist/__tests__/service-config.test.d.ts.map +1 -0
  6. package/dist/__tests__/service-linux.test.d.ts +2 -0
  7. package/dist/__tests__/service-linux.test.d.ts.map +1 -0
  8. package/dist/__tests__/service-macos.test.d.ts +2 -0
  9. package/dist/__tests__/service-macos.test.d.ts.map +1 -0
  10. package/dist/__tests__/service-windows.test.d.ts +2 -0
  11. package/dist/__tests__/service-windows.test.d.ts.map +1 -0
  12. package/dist/backend-adapter.d.ts +2 -0
  13. package/dist/backend-adapter.d.ts.map +1 -1
  14. package/dist/{chunk-KHPEQTWF.js → chunk-KITKMSBE.js} +166 -90
  15. package/dist/chunk-KITKMSBE.js.map +1 -0
  16. package/dist/chunk-W3LSW4XY.js +95 -0
  17. package/dist/chunk-W3LSW4XY.js.map +1 -0
  18. package/dist/hub-connection.d.ts.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/linux-5KQ4SCAA.js +175 -0
  21. package/dist/linux-5KQ4SCAA.js.map +1 -0
  22. package/dist/macos-FGY546NC.js +173 -0
  23. package/dist/macos-FGY546NC.js.map +1 -0
  24. package/dist/service/config.d.ts +19 -0
  25. package/dist/service/config.d.ts.map +1 -0
  26. package/dist/service/index.d.ts +6 -0
  27. package/dist/service/index.d.ts.map +1 -0
  28. package/dist/service/index.js +46 -0
  29. package/dist/service/index.js.map +1 -0
  30. package/dist/service/linux.d.ts +18 -0
  31. package/dist/service/linux.d.ts.map +1 -0
  32. package/dist/service/macos.d.ts +18 -0
  33. package/dist/service/macos.d.ts.map +1 -0
  34. package/dist/service/types.d.ts +19 -0
  35. package/dist/service/types.d.ts.map +1 -0
  36. package/dist/service/windows.d.ts +18 -0
  37. package/dist/service/windows.d.ts.map +1 -0
  38. package/dist/session-manager.d.ts +4 -7
  39. package/dist/session-manager.d.ts.map +1 -1
  40. package/dist/skill-loader.d.ts +8 -0
  41. package/dist/skill-loader.d.ts.map +1 -0
  42. package/dist/start.d.ts.map +1 -1
  43. package/dist/start.js +1 -1
  44. package/dist/windows-PIJ4CMWX.js +164 -0
  45. package/dist/windows-PIJ4CMWX.js.map +1 -0
  46. package/package.json +18 -16
  47. package/skills/academic-search/SKILL.md +147 -0
  48. package/skills/architecture/SKILL.md +294 -0
  49. package/skills/changelog-generator/SKILL.md +112 -0
  50. package/skills/chart-visualization/SKILL.md +183 -0
  51. package/skills/code-review/SKILL.md +304 -0
  52. package/skills/codebase-health/SKILL.md +281 -0
  53. package/skills/consulting-analysis/SKILL.md +584 -0
  54. package/skills/content-research-writer/SKILL.md +546 -0
  55. package/skills/data-analysis/SKILL.md +194 -0
  56. package/skills/deep-research/SKILL.md +198 -0
  57. package/skills/docx/SKILL.md +211 -0
  58. package/skills/github-deep-research/SKILL.md +207 -0
  59. package/skills/image-generation/SKILL.md +209 -0
  60. package/skills/lead-research-assistant/SKILL.md +207 -0
  61. package/skills/mcp-builder/SKILL.md +304 -0
  62. package/skills/meeting-insights-analyzer/SKILL.md +335 -0
  63. package/skills/pair-programming/SKILL.md +196 -0
  64. package/skills/pdf/SKILL.md +309 -0
  65. package/skills/performance-analysis/SKILL.md +261 -0
  66. package/skills/podcast-generation/SKILL.md +224 -0
  67. package/skills/pptx/SKILL.md +497 -0
  68. package/skills/project-learnings/SKILL.md +280 -0
  69. package/skills/security-audit/SKILL.md +211 -0
  70. package/skills/skill-creator/SKILL.md +200 -0
  71. package/skills/technical-writing/SKILL.md +286 -0
  72. package/skills/testing/SKILL.md +363 -0
  73. package/skills/video-generation/SKILL.md +247 -0
  74. package/skills/web-design-guidelines/SKILL.md +203 -0
  75. package/skills/webapp-testing/SKILL.md +162 -0
  76. package/skills/workflow-automation/SKILL.md +299 -0
  77. package/skills/xlsx/SKILL.md +305 -0
  78. package/dist/chunk-KHPEQTWF.js.map +0 -1
@@ -0,0 +1,261 @@
1
+ ---
2
+ name: performance-analysis
3
+ description: Analyze application performance, identify bottlenecks, and provide optimization recommendations. Use when profiling slow code, diagnosing latency issues, optimizing database queries, reducing memory usage, or improving throughput.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # Performance Analysis
8
+
9
+ Systematic performance analysis for identifying bottlenecks, profiling application behavior, and providing actionable optimization recommendations.
10
+
11
+ ## Overview
12
+
13
+ Performance problems are always specific — "the app is slow" is a symptom, not a diagnosis. This skill provides a structured process to move from symptoms to root causes to fixes, covering CPU, memory, I/O, network, and database performance dimensions.
14
+
15
+ ## When to Use
16
+
17
+ - Application or page load is slower than expected
18
+ - Database queries are timing out or causing latency
19
+ - Memory usage is growing unexpectedly
20
+ - API endpoints are slow under load
21
+ - Need to establish performance baselines before optimization
22
+ - Preparing for increased traffic or scaling
23
+
24
+ ## When NOT to Use
25
+
26
+ - **Code correctness bugs** — use the debugging skill; fix correctness before performance
27
+ - **Architecture redesign** — use the `architecture` skill for structural changes
28
+ - **Load testing setup** — this skill analyzes results, not runs load tests
29
+ - **Premature optimization** — if there's no measured problem, don't optimize
30
+
31
+ ## Analysis Process
32
+
33
+ ### Step 1: Establish Baseline
34
+
35
+ Before optimizing anything, measure the current state.
36
+
37
+ **What to measure:**
38
+ - Response time (p50, p95, p99)
39
+ - Throughput (requests/second)
40
+ - Error rate
41
+ - Resource utilization (CPU, memory, disk I/O, network)
42
+
43
+ **How to measure:**
44
+ - **Browser**: Chrome DevTools → Performance tab, Lighthouse
45
+ - **Backend**: APM tools (DataDog, New Relic), custom timing middleware
46
+ - **Database**: Query execution plans, slow query logs
47
+ - **System**: `top`/`htop`, `vmstat`, `iostat`, `netstat`
48
+
49
+ **Record the baseline** — you can't prove an optimization works without a before/after comparison.
50
+
51
+ ### Step 2: Identify the Bottleneck Category
52
+
53
+ Performance problems fall into five categories. Identify which one before diving into code:
54
+
55
+ | Category | Symptoms | Diagnostic Tools |
56
+ |---|---|---|
57
+ | **CPU-bound** | High CPU usage, slow computation, blocking main thread | Profiler (flame graph), CPU sampling |
58
+ | **Memory-bound** | Growing memory, GC pauses, OOM errors | Heap snapshots, memory profiler |
59
+ | **I/O-bound** | Slow file reads/writes, disk wait | `iostat`, strace, I/O profiler |
60
+ | **Network-bound** | High latency, slow API calls, timeout errors | Network tab, traceroute, ping |
61
+ | **Database-bound** | Slow queries, connection pool exhaustion, lock contention | EXPLAIN plans, slow query log, connection metrics |
62
+
63
+ ### Step 3: Profile the Hot Path
64
+
65
+ Once you know the category, profile the specific code path:
66
+
67
+ **CPU profiling:**
68
+ ```javascript
69
+ // Node.js
70
+ const { performance } = require('perf_hooks');
71
+ const start = performance.now();
72
+ expensiveOperation();
73
+ console.log(`Took ${performance.now() - start}ms`);
74
+ ```
75
+
76
+ ```python
77
+ # Python
78
+ import cProfile
79
+ cProfile.run('expensive_operation()', sort='cumulative')
80
+ ```
81
+
82
+ **Memory profiling:**
83
+ ```javascript
84
+ // Node.js - heap snapshot
85
+ const v8 = require('v8');
86
+ const snapshot = v8.writeHeapSnapshot();
87
+ console.log(`Heap snapshot written to ${snapshot}`);
88
+ ```
89
+
90
+ **Database profiling:**
91
+ ```sql
92
+ -- PostgreSQL
93
+ EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
94
+
95
+ -- MySQL
96
+ EXPLAIN FORMAT=JSON SELECT * FROM users WHERE email = 'test@example.com';
97
+ ```
98
+
99
+ ### Step 4: Analyze and Diagnose
100
+
101
+ **CPU bottlenecks:**
102
+ - Look for O(n²) or worse algorithms on growing datasets
103
+ - Check for synchronous operations blocking the event loop
104
+ - Identify hot functions in flame graphs (widest bars = most time)
105
+ - Check for unnecessary serialization/deserialization
106
+
107
+ **Memory bottlenecks:**
108
+ - Look for unbounded caches, growing arrays, event listener leaks
109
+ - Check for large object allocations in loops
110
+ - Identify retained references preventing garbage collection
111
+ - Watch for string concatenation in loops (use builders/arrays instead)
112
+
113
+ **I/O bottlenecks:**
114
+ - Check for sequential reads that could be parallel
115
+ - Look for unbuffered I/O operations
116
+ - Verify streaming is used for large files (not loading entire file into memory)
117
+ - Check for unnecessary file operations (redundant reads, temp files not cleaned)
118
+
119
+ **Network bottlenecks:**
120
+ - Identify N+1 API call patterns (loop of individual requests instead of batch)
121
+ - Check for missing compression (gzip/brotli)
122
+ - Look for oversized payloads (sending more data than the client needs)
123
+ - Verify connection reuse (keep-alive, connection pooling)
124
+
125
+ **Database bottlenecks:**
126
+ - Check for missing indexes (full table scans in EXPLAIN output)
127
+ - Identify N+1 query patterns (ORM lazy loading in loops)
128
+ - Look for unbounded queries (missing LIMIT/pagination)
129
+ - Check for lock contention (long-running transactions holding locks)
130
+
131
+ ### Step 5: Recommend Fixes
132
+
133
+ Prioritize fixes by impact and effort:
134
+
135
+ | Priority | Criteria | Example |
136
+ |---|---|---|
137
+ | **Quick Win** | High impact, low effort | Add a missing database index |
138
+ | **Planned** | High impact, medium effort | Implement caching layer |
139
+ | **Backlog** | Low impact, low effort | Optimize string formatting |
140
+ | **Evaluate** | High impact, high effort | Redesign data model |
141
+
142
+ For each recommendation:
143
+ 1. **What**: Specific change to make
144
+ 2. **Why**: Root cause it addresses
145
+ 3. **Expected impact**: Quantified improvement estimate
146
+ 4. **Risk**: What could go wrong
147
+ 5. **Verification**: How to confirm the fix worked
148
+
149
+ ## Common Optimization Patterns
150
+
151
+ ### Caching
152
+
153
+ ```
154
+ Cache hit rate < 80% → Cache is too small or keys are wrong
155
+ Cache hit rate > 99% → Check if data is stale
156
+ ```
157
+
158
+ **When to cache:**
159
+ - Expensive computations called with same inputs
160
+ - Database queries that rarely change
161
+ - API responses with known freshness windows
162
+
163
+ **Cache invalidation strategies:**
164
+ - TTL (time-based) — simplest, works when staleness is acceptable
165
+ - Event-based — invalidate on write, ensures freshness
166
+ - Versioned — cache key includes version, new version = new cache
167
+
168
+ ### Database Query Optimization
169
+
170
+ **Index strategy:**
171
+ ```sql
172
+ -- Columns used in WHERE clauses
173
+ CREATE INDEX idx_users_email ON users(email);
174
+
175
+ -- Composite index for multi-column queries
176
+ CREATE INDEX idx_orders_user_date ON orders(user_id, created_at DESC);
177
+
178
+ -- Covering index (includes all selected columns)
179
+ CREATE INDEX idx_orders_cover ON orders(user_id, status) INCLUDE (total);
180
+ ```
181
+
182
+ **N+1 elimination:**
183
+ ```python
184
+ # BAD: N+1 queries
185
+ for user in users:
186
+ orders = db.query("SELECT * FROM orders WHERE user_id = ?", user.id)
187
+
188
+ # GOOD: Single query with JOIN or IN
189
+ orders = db.query("SELECT * FROM orders WHERE user_id IN (?)", user_ids)
190
+ ```
191
+
192
+ ### Async / Parallel Processing
193
+
194
+ ```javascript
195
+ // BAD: Sequential
196
+ const a = await fetchA();
197
+ const b = await fetchB();
198
+ const c = await fetchC();
199
+
200
+ // GOOD: Parallel (when independent)
201
+ const [a, b, c] = await Promise.all([fetchA(), fetchB(), fetchC()]);
202
+ ```
203
+
204
+ ### Pagination
205
+
206
+ ```sql
207
+ -- Offset pagination (simple, slow for deep pages)
208
+ SELECT * FROM items ORDER BY id LIMIT 20 OFFSET 1000;
209
+
210
+ -- Cursor pagination (consistent, fast at any depth)
211
+ SELECT * FROM items WHERE id > :last_seen_id ORDER BY id LIMIT 20;
212
+ ```
213
+
214
+ ## Performance Report Template
215
+
216
+ ```markdown
217
+ ## Performance Analysis Report
218
+
219
+ ### Summary
220
+ - **Component**: [what was analyzed]
221
+ - **Bottleneck**: [CPU / Memory / I/O / Network / Database]
222
+ - **Impact**: [quantified: "p95 latency is 2.3s, target is 500ms"]
223
+ - **Root cause**: [one sentence]
224
+
225
+ ### Baseline Measurements
226
+ | Metric | Current | Target |
227
+ |--------|---------|--------|
228
+ | p50 latency | 450ms | 200ms |
229
+ | p95 latency | 2.3s | 500ms |
230
+ | Throughput | 50 rps | 200 rps |
231
+ | Error rate | 0.5% | <0.1% |
232
+
233
+ ### Root Cause Analysis
234
+ [Detailed explanation with evidence from profiling]
235
+
236
+ ### Recommendations
237
+ 1. **[Quick Win]** Add index on users.email → est. 60% query time reduction
238
+ 2. **[Planned]** Implement Redis cache for user profiles → est. 80% reduction in DB load
239
+ 3. **[Backlog]** Migrate to cursor pagination → eliminates deep page slowness
240
+
241
+ ### Verification Plan
242
+ [How to measure improvement after each fix]
243
+ ```
244
+
245
+ ## Anti-Patterns
246
+
247
+ ### Optimizing Without Measuring
248
+ **Problem**: "I think this loop is slow" → rewrites it → no measured improvement.
249
+ **Fix**: Always measure before and after. Profile first, optimize second.
250
+
251
+ ### Micro-Optimization of Cold Paths
252
+ **Problem**: Optimizing code that runs once during startup.
253
+ **Fix**: Focus on hot paths — code that runs per-request or per-user-action.
254
+
255
+ ### Caching Everything
256
+ **Problem**: Cache layer added everywhere, stale data bugs appear.
257
+ **Fix**: Cache only what's measured as slow. Implement proper invalidation.
258
+
259
+ ### Ignoring Tail Latency
260
+ **Problem**: p50 is fine, but p99 is 10x worse.
261
+ **Fix**: Always measure percentiles. p99 affects 1 in 100 users — that's a lot of users at scale.
@@ -0,0 +1,224 @@
1
+ ---
2
+ name: podcast-generation
3
+ description: Create structured podcast scripts with dialogue, timing, and production notes. Use when generating podcast content, interview scripts, audio storytelling outlines, or multi-speaker dialogue for audio production.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # Podcast Generation
8
+
9
+ Create professional podcast scripts with structured dialogue, timing estimates, segment planning, and production notes for audio content creation.
10
+
11
+ ## Overview
12
+
13
+ This skill helps create complete podcast scripts from topic research through final production-ready scripts. It covers single-host, interview, panel discussion, and narrative storytelling formats with proper pacing, transitions, and audience engagement techniques.
14
+
15
+ ## When to Use
16
+
17
+ - Creating podcast episode scripts from a topic or outline
18
+ - Planning interview questions and conversation flow
19
+ - Writing multi-speaker dialogue for audio content
20
+ - Structuring educational or storytelling audio content
21
+ - Generating show notes, summaries, and timestamps
22
+
23
+ ## When NOT to Use
24
+
25
+ - **Blog posts or articles** — use the `content-research-writer` skill
26
+ - **Video scripts** — use the `video-generation` skill (different pacing and visual cues)
27
+ - **Actual audio synthesis** — this produces scripts, not audio files
28
+ - **Music composition** — outside scope
29
+
30
+ ## Podcast Formats
31
+
32
+ ### Solo / Monologue
33
+ One host presenting information or telling a story.
34
+ - Duration: 10-30 minutes typical
35
+ - Pacing: Varied — mix explanation, examples, and personal stories
36
+ - Structure: Hook → Intro → 3-4 segments → Recap → CTA
37
+
38
+ ### Interview
39
+ Host asking questions, guest answering.
40
+ - Duration: 20-60 minutes typical
41
+ - Pacing: Follow the guest's energy, go deeper on interesting threads
42
+ - Structure: Intro → Guest intro → 5-8 questions → Rapid fire → Outro
43
+
44
+ ### Panel Discussion
45
+ Multiple speakers discussing a topic.
46
+ - Duration: 30-60 minutes typical
47
+ - Pacing: Moderator keeps flow, each panelist gets equal time
48
+ - Structure: Intro → Topic overview → Discussion rounds → Audience Q&A → Wrap
49
+
50
+ ### Narrative / Storytelling
51
+ Produced content with narration, sound design cues, and story arc.
52
+ - Duration: 15-45 minutes typical
53
+ - Pacing: Slow build, emotional peaks and valleys
54
+ - Structure: Cold open → Act 1 (setup) → Act 2 (conflict) → Act 3 (resolution) → Outro
55
+
56
+ ## Script Creation Process
57
+
58
+ ### Step 1: Research and Outline
59
+
60
+ Before writing dialogue, define:
61
+
62
+ 1. **Topic**: What is this episode about? (one sentence)
63
+ 2. **Audience**: Who is listening? What do they already know?
64
+ 3. **Key takeaway**: What should the listener remember? (one sentence)
65
+ 4. **Format**: Solo / Interview / Panel / Narrative
66
+ 5. **Target duration**: How long?
67
+ 6. **Segments**: 3-5 main segments with topics
68
+
69
+ ### Step 2: Write the Script
70
+
71
+ **Script format:**
72
+
73
+ ```
74
+ [SEGMENT: Introduction — 2 min]
75
+
76
+ HOST: Welcome to [Show Name]. I'm [Name], and today we're
77
+ diving into [topic]. By the end of this episode, you'll
78
+ understand [key takeaway].
79
+
80
+ [TRANSITION: Music sting — 3 sec]
81
+
82
+ [SEGMENT: Background — 5 min]
83
+
84
+ HOST: Let's start with some context. [Topic] first emerged
85
+ when... [background information]
86
+
87
+ Here's what's interesting about this: [hook that creates
88
+ curiosity]
89
+
90
+ [SEGMENT: Deep Dive — 10 min]
91
+
92
+ HOST: Now let's get into the details...
93
+ ```
94
+
95
+ ### Step 3: Pacing and Timing
96
+
97
+ **Timing estimates:**
98
+ - Average speaking pace: 150 words per minute
99
+ - 10-minute segment ≈ 1,500 words of dialogue
100
+ - Allow 10-15% extra time for pauses, transitions, music
101
+
102
+ **Pacing rules:**
103
+ - Vary segment length — don't make every segment the same duration
104
+ - Place the most engaging content in the first third (prevent drop-off)
105
+ - Add "micro-breaks" — brief pauses, music stings, or recaps every 5-7 minutes
106
+ - End each segment with a tease for what's coming next
107
+
108
+ ### Step 4: Production Notes
109
+
110
+ Add cues for audio production:
111
+
112
+ ```
113
+ [SFX: Door opening]
114
+ [MUSIC: Upbeat intro theme — 15 sec, fade under]
115
+ [PAUSE: 2 sec for emphasis]
116
+ [CLIP: Interview excerpt from Episode 12 — 30 sec]
117
+ [MUSIC: Transition sting — 3 sec]
118
+ [SFX: Typing sounds, subtle]
119
+ ```
120
+
121
+ ## Script Template
122
+
123
+ ```markdown
124
+ # [Show Name] — Episode [N]: [Title]
125
+
126
+ ## Metadata
127
+ - **Topic**: [one sentence]
128
+ - **Format**: [Solo / Interview / Panel / Narrative]
129
+ - **Target Duration**: [X minutes]
130
+ - **Host(s)**: [names]
131
+ - **Guest(s)**: [names, if applicable]
132
+
133
+ ## Pre-Production Notes
134
+ - [Research sources]
135
+ - [Key statistics to mention]
136
+ - [Stories or anecdotes to include]
137
+
138
+ ---
139
+
140
+ ## Script
141
+
142
+ ### Cold Open [0:00 — 0:30]
143
+
144
+ HOST: [Attention-grabbing opening line or question]
145
+
146
+ [MUSIC: Intro theme — 15 sec]
147
+
148
+ ### Introduction [0:30 — 2:00]
149
+
150
+ HOST: Welcome to [Show Name]...
151
+
152
+ ### Segment 1: [Title] [2:00 — 8:00]
153
+
154
+ HOST: ...
155
+
156
+ ### Segment 2: [Title] [8:00 — 15:00]
157
+
158
+ HOST: ...
159
+
160
+ ### Segment 3: [Title] [15:00 — 22:00]
161
+
162
+ HOST: ...
163
+
164
+ ### Recap & CTA [22:00 — 25:00]
165
+
166
+ HOST: Let's recap what we covered today...
167
+
168
+ If you enjoyed this episode, [call to action].
169
+
170
+ [MUSIC: Outro theme — 15 sec]
171
+
172
+ ---
173
+
174
+ ## Show Notes
175
+
176
+ ### Summary
177
+ [2-3 sentence episode summary]
178
+
179
+ ### Timestamps
180
+ - 0:00 — Introduction
181
+ - 2:00 — [Segment 1 title]
182
+ - 8:00 — [Segment 2 title]
183
+ - 15:00 — [Segment 3 title]
184
+ - 22:00 — Recap
185
+
186
+ ### Resources Mentioned
187
+ - [Link 1]
188
+ - [Link 2]
189
+
190
+ ### Credits
191
+ - Host: [Name]
192
+ - Music: [Source]
193
+ - Production: [Name]
194
+ ```
195
+
196
+ ## Interview Question Design
197
+
198
+ **Question types:**
199
+ - **Opener**: Easy, warm-up question ("Tell us about your background")
200
+ - **Core**: Deep questions about the topic ("Walk us through how you...")
201
+ - **Challenge**: Push for deeper insight ("What would you say to critics who...")
202
+ - **Story**: Elicit narratives ("Can you describe a time when...")
203
+ - **Rapid fire**: Quick, fun questions to change pace
204
+
205
+ **Good questions:**
206
+ - Open-ended (not yes/no)
207
+ - Specific enough to get concrete answers
208
+ - Build on each other (create a narrative arc)
209
+ - Include follow-up prompts ("And then what happened?")
210
+
211
+ **Bad questions:**
212
+ - Multiple questions in one ("What do you think about X and also Y?")
213
+ - Leading questions ("Don't you think that X is the best approach?")
214
+ - Questions the audience won't care about
215
+ - Questions easily answered by reading the guest's bio
216
+
217
+ ## Audio Content Best Practices
218
+
219
+ - **Start strong**: The first 30 seconds determine if someone keeps listening
220
+ - **Use concrete examples**: "One user saved $50K" > "Users save money"
221
+ - **Vary energy levels**: Mix high-energy segments with reflective moments
222
+ - **Signpost transitions**: "Now let's shift to..." helps listeners follow
223
+ - **Repeat key points**: Audio listeners can't re-read — repeat important ideas
224
+ - **End with action**: Tell the listener what to do with what they learned