fraim-framework 2.0.30 → 2.0.34

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 (67) hide show
  1. package/bin/fraim.js +3 -18
  2. package/dist/src/cli/commands/init.js +29 -2
  3. package/dist/src/cli/commands/sync.js +82 -70
  4. package/dist/src/utils/script-sync-utils.js +216 -0
  5. package/dist/tests/debug-tools.js +6 -5
  6. package/dist/tests/test-chalk-regression.js +58 -8
  7. package/dist/tests/test-cli.js +70 -5
  8. package/dist/tests/test-end-to-end-hybrid-validation.js +328 -0
  9. package/dist/tests/test-first-run-journey.js +43 -3
  10. package/dist/tests/test-hybrid-script-execution.js +340 -0
  11. package/dist/tests/test-mcp-connection.js +2 -2
  12. package/dist/tests/test-mcp-issue-integration.js +12 -4
  13. package/dist/tests/test-mcp-lifecycle-methods.js +4 -4
  14. package/dist/tests/test-node-compatibility.js +24 -2
  15. package/dist/tests/test-prep-issue.js +4 -1
  16. package/dist/tests/test-script-location-independence.js +173 -0
  17. package/dist/tests/test-script-sync.js +557 -0
  18. package/dist/tests/test-session-rehydration.js +2 -2
  19. package/dist/tests/test-standalone.js +3 -3
  20. package/dist/tests/test-sync-version-update.js +1 -1
  21. package/dist/tests/test-telemetry.js +2 -2
  22. package/dist/tests/test-user-journey.js +8 -4
  23. package/dist/tests/test-utils.js +13 -0
  24. package/dist/tests/test-wizard.js +2 -2
  25. package/package.json +3 -3
  26. package/registry/rules/agent-testing-guidelines.md +502 -502
  27. package/registry/rules/ephemeral-execution.md +37 -27
  28. package/registry/rules/local-development.md +253 -251
  29. package/registry/rules/successful-debugging-patterns.md +491 -482
  30. package/registry/scripts/prep-issue.sh +468 -468
  31. package/registry/workflows/bootstrap/evaluate-code-quality.md +8 -2
  32. package/registry/workflows/bootstrap/verify-test-coverage.md +8 -2
  33. package/registry/workflows/customer-development/thank-customers.md +203 -193
  34. package/registry/workflows/customer-development/weekly-newsletter.md +366 -362
  35. package/registry/workflows/performance/analyze-performance.md +65 -63
  36. package/registry/workflows/product-building/implement.md +6 -2
  37. package/registry/workflows/product-building/prep-issue.md +11 -24
  38. package/registry/workflows/product-building/resolve.md +5 -1
  39. package/registry/workflows/replicate/replicate-discovery.md +336 -0
  40. package/registry/workflows/replicate/replicate-to-issues.md +319 -0
  41. package/registry/workflows/reviewer/review-implementation-vs-design-spec.md +632 -632
  42. package/.windsurf/rules/windsurf-rules.md +0 -7
  43. package/.windsurf/workflows/resolve-issue.md +0 -6
  44. package/.windsurf/workflows/retrospect.md +0 -6
  45. package/.windsurf/workflows/start-design.md +0 -6
  46. package/.windsurf/workflows/start-impl.md +0 -6
  47. package/.windsurf/workflows/start-spec.md +0 -6
  48. package/.windsurf/workflows/start-tests.md +0 -6
  49. package/registry/scripts/build-scripts-generator.ts +0 -216
  50. package/registry/scripts/cleanup-branch.ts +0 -303
  51. package/registry/scripts/fraim-config.ts +0 -63
  52. package/registry/scripts/generate-engagement-emails.ts +0 -744
  53. package/registry/scripts/generic-issues-api.ts +0 -110
  54. package/registry/scripts/newsletter-helpers.ts +0 -874
  55. package/registry/scripts/openapi-generator.ts +0 -695
  56. package/registry/scripts/performance/profile-server.ts +0 -370
  57. package/registry/scripts/run-thank-you-workflow.ts +0 -122
  58. package/registry/scripts/send-newsletter-simple.ts +0 -104
  59. package/registry/scripts/send-thank-you-emails.ts +0 -57
  60. package/registry/workflows/replicate/re-implementation-strategy.md +0 -226
  61. package/registry/workflows/replicate/use-case-extraction.md +0 -135
  62. package/registry/workflows/replicate/visual-analysis.md +0 -154
  63. package/registry/workflows/replicate/website-discovery-analysis.md +0 -231
  64. package/sample_package.json +0 -18
  65. /package/registry/scripts/{replicate/comprehensive-explorer.py → comprehensive-explorer.py} +0 -0
  66. /package/registry/scripts/{replicate/interactive-explorer.py → interactive-explorer.py} +0 -0
  67. /package/registry/scripts/{replicate/scrape-site.py → scrape-site.py} +0 -0
@@ -10,8 +10,14 @@ To perform a deep analysis of the codebase's quality, evaluating it against FRAI
10
10
  - Verify that `.fraim` directory (or equivalent config) is present.
11
11
 
12
12
  2. **Run Quality Analysis**
13
- - Find the `evaluate-code-quality.ts` script in the FRAIM registry.
14
- - Execute it using `scripts/evaluate-code-quality.ts` (fetch via `get_fraim_file` first).
13
+ - Execute the self-contained quality analysis script:
14
+ ```bash
15
+ # Execute evaluate-code-quality script directly from synced location
16
+ npx tsx ~/.fraim/scripts/evaluate-code-quality.ts
17
+
18
+ # On Windows:
19
+ # npx tsx %USERPROFILE%\.fraim\scripts\evaluate-code-quality.ts
20
+ ```
15
21
 
16
22
  3. **Author Report**
17
23
  - Read the terminal output from Step 2.
@@ -14,8 +14,14 @@ To verify the depth and effectiveness of the test suite by comparing actual test
14
14
  - Extract "Validation Plan" tables from these documents.
15
15
 
16
16
  3. **Analyze Coverage Gaps**
17
- - Find the `verify-test-coverage.ts` script in the FRAIM registry.
18
- - Execute it using `scripts/verify-test-coverage.ts` (fetch via `get_fraim_file` first).
17
+ - Execute the self-contained test coverage verification script:
18
+ ```bash
19
+ # Execute verify-test-coverage script directly from synced location
20
+ npx tsx ~/.fraim/scripts/verify-test-coverage.ts
21
+
22
+ # On Windows:
23
+ # npx tsx %USERPROFILE%\.fraim\scripts\verify-test-coverage.ts
24
+ ```
19
25
 
20
26
  4. **Author Report**
21
27
  - Read the terminal output from Step 3.
@@ -1,193 +1,203 @@
1
- # Thank Customers Workflow
2
-
3
- ## INTENT
4
- To automatically generate and send personalized thank you emails to customers whose feedback has been implemented, strengthening customer relationships and encouraging continued engagement.
5
-
6
- ## PRINCIPLES
7
- - **Personal Touch**: Ashley's voice, grateful tone, "Thank you for making me better..."
8
- - **Voice & Pronouns**: Emails are written in first person from Ashley ("I", "me", "my"). When referring to Ashley in third person (outside the email body), use they/them pronouns. Avoid gendered pronouns for Ashley.
9
- - **Customer-Focused**: No technical jargon or issue numbers in customer emails
10
- - **Short and Sweet**: To the point, instructive, humble
11
- - **Encourage more feedback**: ChatGPT (https://ashley-chat.wellnessatwork.me) is the best way
12
-
13
- ## WORKFLOW TRIGGER
14
- **User triggers this workflow manually**:
15
- - When customer issues are resolved and deployed
16
- - User says: "Generate thank you emails for customers" or similar
17
-
18
- ## AI AGENT PROCESS
19
-
20
- ### Step 1: Issue Retrieval
21
- **AI Agent calls function**:
22
- ```typescript
23
- // Note: Retrieve script via get_fraim_file({ path: "scripts/generate-thank-you-emails.ts" }) and save to tmp/generate-thank-you-emails.ts
24
- import { getResolvedIssues, findExecutiveByEmail, getAshleyEmailForExecutive } from './tmp/generate-thank-you-emails.ts';
25
-
26
- // Get issues resolved since last thank-you date (automatic) or user-specified date
27
- const resolvedIssues = await getResolvedIssues(); // Automatically uses latest thank-you date
28
- // OR with explicit date:
29
- const resolvedIssues = await getResolvedIssues('2025-10-29'); // Optional: user-specified date
30
- ```
31
-
32
- **Note**: The `getResolvedIssues()` function automatically:
33
- - Finds the most recent date from existing `thank-you-candidates-YYYY-MM-DD.json` files where emails were sent (status: "sent")
34
- - Uses that date as the starting point to only fetch issues resolved AFTER that date
35
- - If no thank-you files exist, falls back to last 14 days
36
- - This ensures we never send duplicate thank-you emails for the same resolved issues
37
-
38
- ### Step 2: Customer Information Extraction
39
- **AI Agent does intelligent extraction**:
40
- 1. **Go through each resolved issue**
41
- 2. **Extract customer email** from:
42
- - Issue title format: `email@domain.com: summary`
43
- - Issue body: look for email patterns
44
- - If no email found, extract customer name and use database lookup
45
- 3. **Extract customer name** from:
46
- - Issue title or body
47
- - Previous thank-you notes
48
- - Onboarding insights documents
49
-
50
- ### Step 3: Database Lookup
51
- **AI Agent calls function for each customer**:
52
- ```typescript
53
- // Look up executive by customer email
54
- const executive = await findExecutiveByEmail(customerEmail);
55
-
56
- // Get Ashley email address for this executive
57
- const ashleyEmail = await getAshleyEmailForExecutive(executive.id);
58
- ```
59
-
60
- ### Step 4: Collate Issues by Customer
61
- **AI Agent organizes data**:
62
- - Group all resolved issues by customer email
63
- - **Consolidate customers with multiple email addresses** by matching customer names (case-insensitive)
64
- - When a customer has multiple emails, use the primary email from the database lookup
65
- - Output customer list to console for verification
66
-
67
- ### Step 5: Generate Single Thank-You File
68
- **AI Agent creates ONE file**:
69
- - File: `docs/customer-development/thank-you-notes/thank-you-candidates-YYYY-MM-DD.json`
70
- - Format: Structured JSON (not markdown) for easy parsing by mail sending script
71
- - Contains ALL customers and their personalized emails
72
- - **AI Agent writes the email content** - be creative, personal, and contextual!
73
- - Follow principles: personal touch, customer-focused, short and sweet, encourage feedback
74
- - **NO TECHNICAL JARGON**: Do not mention issue numbers, BAML, internal systems, or technical details
75
- - **CUSTOMER EXPERIENCE FOCUS**: Describe what was broken from the user's perspective, what was fixed, and how they can verify it works
76
- - **First-person Email Body**: Use "I" for actions Ashley took (e.g., "I fixed", "I now", "I will"), not "Ashley" or "she". Sign off as Ashley.
77
- - Include `From:` field showing Ashley email from PPE (via `getAshleyEmailForExecutive()`)
78
-
79
- **File format** (JSON):
80
- ```json
81
- {
82
- "metadata": {
83
- "generatedOn": "2025-10-29T02:29:02.497Z",
84
- "issuesResolvedSince": "2025-10-28",
85
- "totalCustomers": 2,
86
- "totalIssues": 3
87
- },
88
- "candidates": [
89
- {
90
- "customer": {
91
- "name": "Olga Ivanova",
92
- "email": "olga.ivanova@gmail.com"
93
- },
94
- "executive": {
95
- "name": "Olga Ivanova",
96
- "id": "exec-..."
97
- },
98
- "status": "pending",
99
- "from": {
100
- "displayName": "Ashley - Olga Ivanova's AI Executive Assistant",
101
- "email": "ashley+olga@ashleycalendar.ai"
102
- },
103
- "to": "olga.ivanova@gmail.com",
104
- "subject": "Thank you for your feedback - your issues have been addressed!",
105
- "greeting": "Hi Olga,",
106
- "opening": "Thank you for making me better! I wanted to personally reach out because your feedback helped us catch and fix an important bug.",
107
- "improvements": [
108
- {
109
- "title": "Issue filing feature",
110
- "description": "The issue filing feature is now working properly - when you ask me to file a bug or feature request through voice, I'll handle it correctly.",
111
- "verification": "Try asking me to file a bug or feature request and it should work smoothly now."
112
- }
113
- ],
114
- "closing": "Your quick feedback saved you (and others) frustration down the line. That kind of real-time input makes all the difference as I'm learning."
115
- }
116
- ]
117
- }
118
- ```
119
-
120
- **Note**: The structured format allows the HTML template to format each section beautifully:
121
- - `greeting`: Personal greeting (e.g., "Hi Olga,")
122
- - `opening`: Opening paragraph - thanks and context
123
- - `improvements[]`: Array of improvements (title, description, optional verification step)
124
- - `closing`: Closing paragraph - encouraging more feedback
125
-
126
- The HTML template formats each section with appropriate styling.
127
-
128
- ### Step 6: User Review
129
- **AI Agent**:
130
- 1. **Points user to the generated file**: `docs/customer-development/thank-you-notes/thank-you-candidates-YYYY-MM-DD.json`
131
- 2. **Requests review** and any edits needed (user can edit JSON directly)
132
- 3. **Waits for user approval** before proceeding
133
-
134
- **Note**: Each email section includes a `From:` field showing the display name and email address that will be used when sending. The signature includes a humble note about ramping up, without displaying a generic email address.
135
-
136
- ### Step 7: Send Emails (Separate Command)
137
- **When user says "Send the emails" or similar**:
138
-
139
- **AI Agent calls function**:
140
- ```typescript
141
- // Note: Retrieve script via get_fraim_file({ path: "scripts/generate-thank-you-emails.ts" }) and save to tmp/generate-thank-you-emails.ts
142
- import { sendCustomerMail } from './tmp/generate-thank-you-emails.ts';
143
-
144
- // Send emails from the candidates JSON file (all pending candidates)
145
- await sendCustomerMail('docs/customer-development/thank-you-notes/thank-you-candidates-YYYY-MM-DD.json');
146
-
147
- // OR send to a specific executive only (optional)
148
- await sendCustomerMail('docs/customer-development/thank-you-notes/thank-you-candidates-YYYY-MM-DD.json', 'exec-1761011032377-q36j91sdl');
149
- ```
150
-
151
- **Note**: The `sendCustomerMail` function parses JSON (not markdown) for easy, deterministic parsing.
152
-
153
- **Function parameters**:
154
- - `candidatesFilePath` (required): Path to the JSON candidates file
155
- - `executiveId` (optional): If provided, only sends emails for candidates matching this executive ID. If omitted, sends to all pending candidates.
156
-
157
- **This function will**:
158
- - Parse the JSON candidates file
159
- - If `executiveId` is provided, filter to only that executive's candidates
160
- - For each candidate with `status: "pending"`, send email
161
- - Use the `from` field (displayName and email) specified in JSON
162
- - Use the `to`, `subject`, and `body` fields from JSON
163
- - Update the JSON file after each send with status: `"sent"` or `"failed"`
164
- - Skip candidates that already have status `"sent"` or `"failed"`
165
-
166
- ## REQUIRED FUNCTIONS IN SCRIPT
167
-
168
- The script must provide these deterministic functions for AI agents to call:
169
-
170
- ```typescript
171
- // Get resolved issues since a date
172
- export async function getResolvedIssues(date: string): Promise<ResolvedIssue[]>
173
-
174
- // Find executive by email in PPE database
175
- export async function findExecutiveByEmail(email: string): Promise<Executive | null>
176
-
177
- // Get Ashley email for executive from PPE database
178
- export async function getAshleyEmailForExecutive(executiveId: string): Promise<string>
179
-
180
- // Send emails from candidates file
181
- // executiveId is optional - if provided, only sends to that executive; if omitted, sends to all pending
182
- export async function sendCustomerMail(candidatesFilePath: string, executiveId?: string): Promise<void>
183
- ```
184
-
185
- **Note**: The script provides ONLY data retrieval and sending. The AI agent does ALL intelligent work:
186
- - Extracts customer info from issues (intelligent parsing)
187
- - Writes personalized, creative email content (better than hardcoded templates!)
188
- - Organizes and formats the candidates file
189
-
190
- ## WORKFLOW COMPLETION
191
-
192
- **Generate workflow completes with**: Single candidates file ready for review
193
- **Send workflow completes with**: All emails sent and file updated with status
1
+ # Thank Customers Workflow
2
+
3
+ ## INTENT
4
+ To automatically generate and send personalized thank you emails to customers whose feedback has been implemented, strengthening customer relationships and encouraging continued engagement.
5
+
6
+ ## PRINCIPLES
7
+ - **Personal Touch**: Ashley's voice, grateful tone, "Thank you for making me better..."
8
+ - **Voice & Pronouns**: Emails are written in first person from Ashley ("I", "me", "my"). When referring to Ashley in third person (outside the email body), use they/them pronouns. Avoid gendered pronouns for Ashley.
9
+ - **Customer-Focused**: No technical jargon or issue numbers in customer emails
10
+ - **Short and Sweet**: To the point, instructive, humble
11
+ - **Encourage more feedback**: ChatGPT (https://ashley-chat.wellnessatwork.me) is the best way
12
+
13
+ ## WORKFLOW TRIGGER
14
+ **User triggers this workflow manually**:
15
+ - When customer issues are resolved and deployed
16
+ - User says: "Generate thank you emails for customers" or similar
17
+
18
+ ## AI AGENT PROCESS
19
+
20
+ ### Step 1: Issue Retrieval
21
+ **AI Agent calls function**:
22
+ ```typescript
23
+ // Import helper functions directly from synced location
24
+ const os = require('os');
25
+ const path = require('path');
26
+ const scriptsDir = path.join(os.homedir(), '.fraim', 'scripts');
27
+ const scriptPath = path.join(scriptsDir, 'generate-engagement-emails.ts');
28
+
29
+ import { getResolvedIssues, findExecutiveByEmail, getAshleyEmailForExecutive } from scriptPath;
30
+
31
+ // Get issues resolved since last thank-you date (automatic) or user-specified date
32
+ const resolvedIssues = await getResolvedIssues(); // Automatically uses latest thank-you date
33
+ // OR with explicit date:
34
+ const resolvedIssues = await getResolvedIssues('2025-10-29'); // Optional: user-specified date
35
+ ```
36
+
37
+ **Note**: The `getResolvedIssues()` function automatically:
38
+ - Finds the most recent date from existing `thank-you-candidates-YYYY-MM-DD.json` files where emails were sent (status: "sent")
39
+ - Uses that date as the starting point to only fetch issues resolved AFTER that date
40
+ - If no thank-you files exist, falls back to last 14 days
41
+ - This ensures we never send duplicate thank-you emails for the same resolved issues
42
+
43
+ ### Step 2: Customer Information Extraction
44
+ **AI Agent does intelligent extraction**:
45
+ 1. **Go through each resolved issue**
46
+ 2. **Extract customer email** from:
47
+ - Issue title format: `email@domain.com: summary`
48
+ - Issue body: look for email patterns
49
+ - If no email found, extract customer name and use database lookup
50
+ 3. **Extract customer name** from:
51
+ - Issue title or body
52
+ - Previous thank-you notes
53
+ - Onboarding insights documents
54
+
55
+ ### Step 3: Database Lookup
56
+ **AI Agent calls function for each customer**:
57
+ ```typescript
58
+ // Look up executive by customer email
59
+ const executive = await findExecutiveByEmail(customerEmail);
60
+
61
+ // Get Ashley email address for this executive
62
+ const ashleyEmail = await getAshleyEmailForExecutive(executive.id);
63
+ ```
64
+
65
+ ### Step 4: Collate Issues by Customer
66
+ **AI Agent organizes data**:
67
+ - Group all resolved issues by customer email
68
+ - **Consolidate customers with multiple email addresses** by matching customer names (case-insensitive)
69
+ - When a customer has multiple emails, use the primary email from the database lookup
70
+ - Output customer list to console for verification
71
+
72
+ ### Step 5: Generate Single Thank-You File
73
+ **AI Agent creates ONE file**:
74
+ - File: `docs/customer-development/thank-you-notes/thank-you-candidates-YYYY-MM-DD.json`
75
+ - Format: Structured JSON (not markdown) for easy parsing by mail sending script
76
+ - Contains ALL customers and their personalized emails
77
+ - **AI Agent writes the email content** - be creative, personal, and contextual!
78
+ - Follow principles: personal touch, customer-focused, short and sweet, encourage feedback
79
+ - **NO TECHNICAL JARGON**: Do not mention issue numbers, BAML, internal systems, or technical details
80
+ - **CUSTOMER EXPERIENCE FOCUS**: Describe what was broken from the user's perspective, what was fixed, and how they can verify it works
81
+ - **First-person Email Body**: Use "I" for actions Ashley took (e.g., "I fixed", "I now", "I will"), not "Ashley" or "she". Sign off as Ashley.
82
+ - Include `From:` field showing Ashley email from PPE (via `getAshleyEmailForExecutive()`)
83
+
84
+ **File format** (JSON):
85
+ ```json
86
+ {
87
+ "metadata": {
88
+ "generatedOn": "2025-10-29T02:29:02.497Z",
89
+ "issuesResolvedSince": "2025-10-28",
90
+ "totalCustomers": 2,
91
+ "totalIssues": 3
92
+ },
93
+ "candidates": [
94
+ {
95
+ "customer": {
96
+ "name": "Olga Ivanova",
97
+ "email": "olga.ivanova@gmail.com"
98
+ },
99
+ "executive": {
100
+ "name": "Olga Ivanova",
101
+ "id": "exec-..."
102
+ },
103
+ "status": "pending",
104
+ "from": {
105
+ "displayName": "Ashley - Olga Ivanova's AI Executive Assistant",
106
+ "email": "ashley+olga@ashleycalendar.ai"
107
+ },
108
+ "to": "olga.ivanova@gmail.com",
109
+ "subject": "Thank you for your feedback - your issues have been addressed!",
110
+ "greeting": "Hi Olga,",
111
+ "opening": "Thank you for making me better! I wanted to personally reach out because your feedback helped us catch and fix an important bug.",
112
+ "improvements": [
113
+ {
114
+ "title": "Issue filing feature",
115
+ "description": "The issue filing feature is now working properly - when you ask me to file a bug or feature request through voice, I'll handle it correctly.",
116
+ "verification": "Try asking me to file a bug or feature request and it should work smoothly now."
117
+ }
118
+ ],
119
+ "closing": "Your quick feedback saved you (and others) frustration down the line. That kind of real-time input makes all the difference as I'm learning."
120
+ }
121
+ ]
122
+ }
123
+ ```
124
+
125
+ **Note**: The structured format allows the HTML template to format each section beautifully:
126
+ - `greeting`: Personal greeting (e.g., "Hi Olga,")
127
+ - `opening`: Opening paragraph - thanks and context
128
+ - `improvements[]`: Array of improvements (title, description, optional verification step)
129
+ - `closing`: Closing paragraph - encouraging more feedback
130
+
131
+ The HTML template formats each section with appropriate styling.
132
+
133
+ ### Step 6: User Review
134
+ **AI Agent**:
135
+ 1. **Points user to the generated file**: `docs/customer-development/thank-you-notes/thank-you-candidates-YYYY-MM-DD.json`
136
+ 2. **Requests review** and any edits needed (user can edit JSON directly)
137
+ 3. **Waits for user approval** before proceeding
138
+
139
+ **Note**: Each email section includes a `From:` field showing the display name and email address that will be used when sending. The signature includes a humble note about ramping up, without displaying a generic email address.
140
+
141
+ ### Step 7: Send Emails (Separate Command)
142
+ **When user says "Send the emails" or similar**:
143
+
144
+ **AI Agent calls function**:
145
+ ```typescript
146
+ // Import helper functions directly from synced location
147
+ const os = require('os');
148
+ const path = require('path');
149
+ const scriptsDir = path.join(os.homedir(), '.fraim', 'scripts');
150
+ const scriptPath = path.join(scriptsDir, 'generate-engagement-emails.ts');
151
+
152
+ import { sendCustomerMail } from scriptPath;
153
+
154
+ // Send emails from the candidates JSON file (all pending candidates)
155
+ await sendCustomerMail('docs/customer-development/thank-you-notes/thank-you-candidates-YYYY-MM-DD.json');
156
+
157
+ // OR send to a specific executive only (optional)
158
+ await sendCustomerMail('docs/customer-development/thank-you-notes/thank-you-candidates-YYYY-MM-DD.json', 'exec-1761011032377-q36j91sdl');
159
+ ```
160
+
161
+ **Note**: The `sendCustomerMail` function parses JSON (not markdown) for easy, deterministic parsing.
162
+
163
+ **Function parameters**:
164
+ - `candidatesFilePath` (required): Path to the JSON candidates file
165
+ - `executiveId` (optional): If provided, only sends emails for candidates matching this executive ID. If omitted, sends to all pending candidates.
166
+
167
+ **This function will**:
168
+ - Parse the JSON candidates file
169
+ - If `executiveId` is provided, filter to only that executive's candidates
170
+ - For each candidate with `status: "pending"`, send email
171
+ - Use the `from` field (displayName and email) specified in JSON
172
+ - Use the `to`, `subject`, and `body` fields from JSON
173
+ - Update the JSON file after each send with status: `"sent"` or `"failed"`
174
+ - Skip candidates that already have status `"sent"` or `"failed"`
175
+
176
+ ## REQUIRED FUNCTIONS IN SCRIPT
177
+
178
+ The script must provide these deterministic functions for AI agents to call:
179
+
180
+ ```typescript
181
+ // Get resolved issues since a date
182
+ export async function getResolvedIssues(date: string): Promise<ResolvedIssue[]>
183
+
184
+ // Find executive by email in PPE database
185
+ export async function findExecutiveByEmail(email: string): Promise<Executive | null>
186
+
187
+ // Get Ashley email for executive from PPE database
188
+ export async function getAshleyEmailForExecutive(executiveId: string): Promise<string>
189
+
190
+ // Send emails from candidates file
191
+ // executiveId is optional - if provided, only sends to that executive; if omitted, sends to all pending
192
+ export async function sendCustomerMail(candidatesFilePath: string, executiveId?: string): Promise<void>
193
+ ```
194
+
195
+ **Note**: The script provides ONLY data retrieval and sending. The AI agent does ALL intelligent work:
196
+ - Extracts customer info from issues (intelligent parsing)
197
+ - Writes personalized, creative email content (better than hardcoded templates!)
198
+ - Organizes and formats the candidates file
199
+
200
+ ## WORKFLOW COMPLETION
201
+
202
+ **Generate workflow completes with**: Single candidates file ready for review
203
+ **Send workflow completes with**: All emails sent and file updated with status