@forwardimpact/basecamp 1.0.0 → 2.2.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.
- package/README.md +1 -1
- package/config/scheduler.json +18 -17
- package/package.json +3 -3
- package/src/basecamp.js +532 -259
- package/template/.claude/agents/chief-of-staff.md +103 -0
- package/template/.claude/agents/concierge.md +75 -0
- package/template/.claude/agents/librarian.md +59 -0
- package/template/.claude/agents/postman.md +73 -0
- package/template/.claude/agents/recruiter.md +222 -0
- package/template/.claude/settings.json +0 -4
- package/template/.claude/skills/analyze-cv/SKILL.md +267 -0
- package/template/.claude/skills/create-presentations/SKILL.md +2 -2
- package/template/.claude/skills/create-presentations/references/slide.css +1 -1
- package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.mjs +47 -0
- package/template/.claude/skills/draft-emails/SKILL.md +85 -123
- package/template/.claude/skills/draft-emails/scripts/scan-emails.mjs +66 -0
- package/template/.claude/skills/draft-emails/scripts/send-email.mjs +118 -0
- package/template/.claude/skills/extract-entities/SKILL.md +2 -2
- package/template/.claude/skills/extract-entities/scripts/state.mjs +130 -0
- package/template/.claude/skills/manage-tasks/SKILL.md +242 -0
- package/template/.claude/skills/organize-files/SKILL.md +3 -3
- package/template/.claude/skills/organize-files/scripts/organize-by-type.mjs +105 -0
- package/template/.claude/skills/organize-files/scripts/summarize.mjs +84 -0
- package/template/.claude/skills/process-hyprnote/SKILL.md +2 -2
- package/template/.claude/skills/send-chat/SKILL.md +170 -0
- package/template/.claude/skills/sync-apple-calendar/SKILL.md +5 -5
- package/template/.claude/skills/sync-apple-calendar/scripts/sync.mjs +325 -0
- package/template/.claude/skills/sync-apple-mail/SKILL.md +6 -6
- package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.mjs +374 -0
- package/template/.claude/skills/sync-apple-mail/scripts/sync.mjs +629 -0
- package/template/.claude/skills/track-candidates/SKILL.md +375 -0
- package/template/.claude/skills/weekly-update/SKILL.md +250 -0
- package/template/CLAUDE.md +73 -29
- package/template/knowledge/Briefings/.gitkeep +0 -0
- package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.js +0 -32
- package/template/.claude/skills/draft-emails/scripts/scan-emails.sh +0 -34
- package/template/.claude/skills/extract-entities/scripts/state.py +0 -100
- package/template/.claude/skills/organize-files/scripts/organize-by-type.sh +0 -42
- package/template/.claude/skills/organize-files/scripts/summarize.sh +0 -21
- package/template/.claude/skills/sync-apple-calendar/scripts/sync.py +0 -242
- package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.py +0 -104
- package/template/.claude/skills/sync-apple-mail/scripts/sync.py +0 -455
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: analyze-cv
|
|
3
|
+
description: >
|
|
4
|
+
Analyze candidate CVs against the engineering career framework using
|
|
5
|
+
fit-pathway as the reference point. Assess skill alignment, identify track
|
|
6
|
+
fit (forward_deployed vs platform), estimate career level, and produce
|
|
7
|
+
structured assessments. Use when the user asks to evaluate a CV, compare a
|
|
8
|
+
candidate to a role, or assess engineering fit.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Analyze CV
|
|
12
|
+
|
|
13
|
+
Analyze a candidate's CV against the engineering career framework defined in
|
|
14
|
+
`fit-pathway`. Produces a structured assessment: estimated career level, track
|
|
15
|
+
fit, skill alignment, gaps, and a hiring recommendation. Every assessment is
|
|
16
|
+
grounded in the framework — no subjective impressions.
|
|
17
|
+
|
|
18
|
+
## Trigger
|
|
19
|
+
|
|
20
|
+
Run this skill:
|
|
21
|
+
|
|
22
|
+
- When the user asks to analyze, evaluate, or assess a CV
|
|
23
|
+
- When a new CV is added to `knowledge/Candidates/{Name}/`
|
|
24
|
+
- When the user asks "is this person a fit for {role}?"
|
|
25
|
+
- When comparing a candidate's background against a specific job level and track
|
|
26
|
+
|
|
27
|
+
## Prerequisites
|
|
28
|
+
|
|
29
|
+
- `fit-pathway` CLI installed (`npx fit-pathway` must work)
|
|
30
|
+
- A CV file (PDF or DOCX) accessible on the filesystem
|
|
31
|
+
- Optionally, a target role specified by the user (discipline + level + track)
|
|
32
|
+
|
|
33
|
+
## Inputs
|
|
34
|
+
|
|
35
|
+
- CV file path (e.g. `knowledge/Candidates/{Name}/CV.pdf` or a path the user
|
|
36
|
+
provides)
|
|
37
|
+
- Target role (optional): `{discipline} {level} --track={track}`
|
|
38
|
+
- Existing candidate brief (if available):
|
|
39
|
+
`knowledge/Candidates/{Name}/brief.md`
|
|
40
|
+
|
|
41
|
+
## Outputs
|
|
42
|
+
|
|
43
|
+
- `knowledge/Candidates/{Name}/assessment.md` — structured CV assessment
|
|
44
|
+
- Updated `knowledge/Candidates/{Name}/brief.md` — skills and summary enriched
|
|
45
|
+
from CV analysis
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 1: Read the CV
|
|
50
|
+
|
|
51
|
+
Read the candidate's CV file. Extract:
|
|
52
|
+
|
|
53
|
+
| Field | What to look for |
|
|
54
|
+
| ---------------------- | ------------------------------------------------------ |
|
|
55
|
+
| **Current role** | Most recent job title |
|
|
56
|
+
| **Years of experience**| Total and per-role tenure |
|
|
57
|
+
| **Technical skills** | Languages, frameworks, platforms, tools mentioned |
|
|
58
|
+
| **Domain experience** | Industries, business domains, customer-facing work |
|
|
59
|
+
| **Education** | Degrees, certifications, relevant courses |
|
|
60
|
+
| **Leadership signals** | Team size, mentoring, cross-team work, architecture |
|
|
61
|
+
| **Scope signals** | Scale of systems, user base, revenue impact |
|
|
62
|
+
| **Communication** | Publications, talks, open source, documentation |
|
|
63
|
+
| **Gender** | Pronouns, gendered titles, first name if unambiguous |
|
|
64
|
+
|
|
65
|
+
## Step 2: Look Up the Framework Reference
|
|
66
|
+
|
|
67
|
+
Use `fit-pathway` to load the reference data for assessment.
|
|
68
|
+
|
|
69
|
+
### If a target role is specified
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Get the full job definition
|
|
73
|
+
npx fit-pathway job {discipline} {level} --track={track}
|
|
74
|
+
|
|
75
|
+
# Get the skill matrix for comparison
|
|
76
|
+
npx fit-pathway job {discipline} {level} --track={track} --skills
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### If no target role is specified
|
|
80
|
+
|
|
81
|
+
Estimate the most likely discipline and level from the CV, then look it up:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# See available disciplines and their tracks
|
|
85
|
+
npx fit-pathway discipline
|
|
86
|
+
|
|
87
|
+
# See available levels
|
|
88
|
+
npx fit-pathway level
|
|
89
|
+
|
|
90
|
+
# Look up the estimated role
|
|
91
|
+
npx fit-pathway job {discipline} {level} --track={track}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Estimation heuristics:**
|
|
95
|
+
|
|
96
|
+
| CV Signal | Likely Level |
|
|
97
|
+
| -------------------------------------------- | ---------------- |
|
|
98
|
+
| 0-2 years, junior titles, learning signals | J040 (Level I) |
|
|
99
|
+
| 2-5 years, mid-level titles, independent | J060 (Level II) |
|
|
100
|
+
| 5-8 years, senior titles, mentoring signals | J070 (Level III) |
|
|
101
|
+
| 8-12 years, staff/lead titles, area scope | J090 (Staff) |
|
|
102
|
+
| 12+ years, principal titles, org-wide impact | J100 (Principal) |
|
|
103
|
+
|
|
104
|
+
### Track fit estimation
|
|
105
|
+
|
|
106
|
+
Use `fit-pathway` to compare tracks:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx fit-pathway track forward_deployed
|
|
110
|
+
npx fit-pathway track platform
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Map CV evidence to track indicators:
|
|
114
|
+
|
|
115
|
+
| Forward Deployed signals | Platform signals |
|
|
116
|
+
| -------------------------------------------- | ------------------------------------------- |
|
|
117
|
+
| Customer-facing projects | Internal tooling / shared services |
|
|
118
|
+
| Business domain immersion | Infrastructure / platform-as-product |
|
|
119
|
+
| Rapid prototyping, MVPs | Architecture, system design |
|
|
120
|
+
| Data integration, analytics | CI/CD, DevOps, reliability |
|
|
121
|
+
| Stakeholder management | Code quality, technical debt management |
|
|
122
|
+
| Cross-functional work | Scalability, performance engineering |
|
|
123
|
+
| Multiple industries or domain breadth | Deep platform ownership |
|
|
124
|
+
|
|
125
|
+
## Step 3: Map CV to Framework Skills
|
|
126
|
+
|
|
127
|
+
For each skill in the target job's skill matrix, assess the candidate's likely
|
|
128
|
+
proficiency based on CV evidence:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Get skill detail for nuanced assessment
|
|
132
|
+
npx fit-pathway skill {skill_id}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Use the proficiency definitions from the framework:
|
|
136
|
+
|
|
137
|
+
| Proficiency | CV Evidence |
|
|
138
|
+
| -------------- | -------------------------------------------------------- |
|
|
139
|
+
| `awareness` | Mentioned but no project evidence |
|
|
140
|
+
| `foundational` | Used in projects, basic application |
|
|
141
|
+
| `working` | Primary tool/skill in multiple roles, independent usage |
|
|
142
|
+
| `practitioner` | Led teams using this skill, mentored others, deep work |
|
|
143
|
+
| `expert` | Published, shaped org practice, industry recognition |
|
|
144
|
+
|
|
145
|
+
**Be conservative.** CVs inflate; default one level below what's claimed unless
|
|
146
|
+
there's concrete evidence (metrics, project details, scope indicators).
|
|
147
|
+
|
|
148
|
+
## Step 4: Assess Behaviour Indicators
|
|
149
|
+
|
|
150
|
+
Check the CV for behaviour signals aligned with the framework:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npx fit-pathway behaviour --list
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Map CV evidence to behaviours:
|
|
157
|
+
|
|
158
|
+
| Behaviour | CV Evidence |
|
|
159
|
+
| ---------------------------- | -------------------------------------------------- |
|
|
160
|
+
| Own the Outcome | End-to-end ownership, P&L impact, delivery metrics |
|
|
161
|
+
| Think in Systems | Architecture decisions, system-wide reasoning |
|
|
162
|
+
| Communicate with Precision | Technical writing, documentation, talks |
|
|
163
|
+
| Be Polymath Oriented | Cross-domain work, diverse tech stack |
|
|
164
|
+
| Don't Lose Your Curiosity | Side projects, continuous learning, certifications |
|
|
165
|
+
|
|
166
|
+
## Step 5: Identify Gaps and Strengths
|
|
167
|
+
|
|
168
|
+
Compare the candidate's estimated skill profile against the target job:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# If comparing progression potential
|
|
172
|
+
npx fit-pathway progress {discipline} {level} --track={track}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Classify each skill as:
|
|
176
|
+
|
|
177
|
+
- **Strong match** — candidate meets or exceeds the expected proficiency
|
|
178
|
+
- **Adequate** — candidate is within one level of expected proficiency
|
|
179
|
+
- **Gap** — candidate is two or more levels below expected proficiency
|
|
180
|
+
- **Not evidenced** — CV doesn't mention this skill area
|
|
181
|
+
|
|
182
|
+
## Step 6: Write Assessment
|
|
183
|
+
|
|
184
|
+
Create `knowledge/Candidates/{Name}/assessment.md`:
|
|
185
|
+
|
|
186
|
+
```markdown
|
|
187
|
+
# CV Assessment — {Full Name}
|
|
188
|
+
|
|
189
|
+
**Assessed against:** {Discipline} {Level} — {Track}
|
|
190
|
+
**Date:** {YYYY-MM-DD}
|
|
191
|
+
**CV source:** [{filename}](./{filename})
|
|
192
|
+
|
|
193
|
+
## Summary
|
|
194
|
+
|
|
195
|
+
{2-3 sentence summary: overall fit, key strengths, primary concerns}
|
|
196
|
+
|
|
197
|
+
## Estimated Profile
|
|
198
|
+
|
|
199
|
+
| Dimension | Assessment |
|
|
200
|
+
| ---------------- | ----------------------------------------- |
|
|
201
|
+
| **Level** | {estimated level and confidence} |
|
|
202
|
+
| **Track fit** | {forward_deployed / platform / either} |
|
|
203
|
+
| **Discipline** | {best discipline match} |
|
|
204
|
+
| **Gender** | {Woman / Man / —} |
|
|
205
|
+
|
|
206
|
+
## Skill Alignment
|
|
207
|
+
|
|
208
|
+
| Skill | Expected | Estimated | Status |
|
|
209
|
+
| --- | --- | --- | --- |
|
|
210
|
+
| {skill} | {framework level} | {CV-based estimate} | {Strong/Adequate/Gap/Not evidenced} |
|
|
211
|
+
|
|
212
|
+
### Key Strengths
|
|
213
|
+
- {Strength 1 — with CV evidence}
|
|
214
|
+
- {Strength 2 — with CV evidence}
|
|
215
|
+
|
|
216
|
+
### Key Gaps
|
|
217
|
+
- {Gap 1 — what's missing and why it matters for the role}
|
|
218
|
+
- {Gap 2 — what's missing and why it matters for the role}
|
|
219
|
+
|
|
220
|
+
## Behaviour Indicators
|
|
221
|
+
|
|
222
|
+
| Behaviour | Expected Maturity | CV Evidence | Signal |
|
|
223
|
+
| --- | --- | --- | --- |
|
|
224
|
+
| {behaviour} | {maturity} | {evidence or "—"} | {Strong/Weak/None} |
|
|
225
|
+
|
|
226
|
+
## Track Fit Analysis
|
|
227
|
+
|
|
228
|
+
{Paragraph explaining why this candidate fits forward_deployed, platform,
|
|
229
|
+
or could work on either. Reference specific CV evidence.}
|
|
230
|
+
|
|
231
|
+
## Hiring Recommendation
|
|
232
|
+
|
|
233
|
+
**Recommendation:** {Proceed / Proceed with reservations / Do not proceed}
|
|
234
|
+
|
|
235
|
+
**Rationale:** {3-5 sentences grounding the recommendation in framework data.
|
|
236
|
+
Reference specific skill gaps or strengths and their impact on the role.}
|
|
237
|
+
|
|
238
|
+
**Interview focus areas:**
|
|
239
|
+
- {Area 1 — what to probe in interviews to validate}
|
|
240
|
+
- {Area 2 — what to probe in interviews to validate}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Step 7: Enrich Candidate Brief
|
|
244
|
+
|
|
245
|
+
If `knowledge/Candidates/{Name}/brief.md` exists, update it with findings:
|
|
246
|
+
|
|
247
|
+
- Add or update the **Skills** section with framework skill IDs
|
|
248
|
+
- Update **Summary** if the CV provides better context
|
|
249
|
+
- Set the **Gender** field if identifiable from the CV and not already set
|
|
250
|
+
- Add a link to the assessment: `- [CV Assessment](./assessment.md)`
|
|
251
|
+
|
|
252
|
+
**Use precise edits — don't rewrite the entire file.**
|
|
253
|
+
|
|
254
|
+
If no brief exists, note that the `track-candidates` skill should be run first
|
|
255
|
+
to create the candidate profile from email threads.
|
|
256
|
+
|
|
257
|
+
## Quality Checklist
|
|
258
|
+
|
|
259
|
+
- [ ] Assessment is grounded in `fit-pathway` framework data, not subjective
|
|
260
|
+
opinion
|
|
261
|
+
- [ ] Every skill rating cites specific CV evidence or marks "Not evidenced"
|
|
262
|
+
- [ ] Estimated level is conservative (one below CV claims unless proven)
|
|
263
|
+
- [ ] Track fit analysis references specific skill modifiers from the framework
|
|
264
|
+
- [ ] Gaps are actionable — they suggest interview focus areas
|
|
265
|
+
- [ ] Assessment file uses correct path format and links to CV
|
|
266
|
+
- [ ] Candidate brief updated with skill tags and assessment link
|
|
267
|
+
- [ ] Gender field set in both assessment and brief where identifiable
|
|
@@ -41,7 +41,7 @@ Run when the user asks to create a presentation, slide deck, or pitch deck.
|
|
|
41
41
|
4. Include the required CSS from [references/slide.css](references/slide.css)
|
|
42
42
|
5. Run the conversion script:
|
|
43
43
|
|
|
44
|
-
node scripts/convert-to-pdf.
|
|
44
|
+
node scripts/convert-to-pdf.mjs
|
|
45
45
|
|
|
46
46
|
6. Tell the user: "Your presentation is ready at ~/Desktop/presentation.pdf"
|
|
47
47
|
|
|
@@ -49,7 +49,7 @@ Run when the user asks to create a presentation, slide deck, or pitch deck.
|
|
|
49
49
|
|
|
50
50
|
The conversion script accepts optional arguments:
|
|
51
51
|
|
|
52
|
-
node scripts/convert-to-pdf.
|
|
52
|
+
node scripts/convert-to-pdf.mjs [input.html] [output.pdf]
|
|
53
53
|
|
|
54
54
|
Defaults: input = `/tmp/basecamp-presentation.html`, output =
|
|
55
55
|
`~/Desktop/presentation.pdf`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* Required CSS for HTML slide decks rendered to PDF via Playwright.
|
|
2
2
|
*
|
|
3
3
|
* Include this in the <style> block of /tmp/basecamp-presentation.html.
|
|
4
|
-
* See scripts/convert-to-pdf.
|
|
4
|
+
* See scripts/convert-to-pdf.mjs for the rendering script.
|
|
5
5
|
*
|
|
6
6
|
* PDF rendering rules:
|
|
7
7
|
* - No layered elements — style content directly, no separate backgrounds
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Convert HTML slides to PDF using Playwright.
|
|
4
|
+
*
|
|
5
|
+
* Renders an HTML file containing slide markup (1280x720px per slide) into a
|
|
6
|
+
* PDF document. Each slide is sized to exactly 1280x720 pixels with background
|
|
7
|
+
* colours and images preserved. Defaults to reading from /tmp and writing to
|
|
8
|
+
* ~/Desktop when no arguments are given.
|
|
9
|
+
*
|
|
10
|
+
* Requires: npm install playwright && npx playwright install chromium
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { resolve } from "node:path";
|
|
15
|
+
import { homedir } from "node:os";
|
|
16
|
+
|
|
17
|
+
const HELP = `convert-to-pdf — render HTML slides to PDF via Playwright
|
|
18
|
+
|
|
19
|
+
Usage: node scripts/convert-to-pdf.mjs [input.html] [output.pdf] [-h|--help]
|
|
20
|
+
|
|
21
|
+
Arguments:
|
|
22
|
+
input.html HTML slides file (default: /tmp/basecamp-presentation.html)
|
|
23
|
+
output.pdf Output PDF path (default: ~/Desktop/presentation.pdf)
|
|
24
|
+
|
|
25
|
+
Requires: npm install playwright && npx playwright install chromium`;
|
|
26
|
+
|
|
27
|
+
if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
28
|
+
console.log(HELP);
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const positional = process.argv.slice(2).filter((a) => !a.startsWith("-"));
|
|
33
|
+
const input = positional[0] || "/tmp/basecamp-presentation.html";
|
|
34
|
+
const output = positional[1] || join(homedir(), "Desktop", "presentation.pdf");
|
|
35
|
+
|
|
36
|
+
const { chromium } = await import("playwright");
|
|
37
|
+
const browser = await chromium.launch();
|
|
38
|
+
const page = await browser.newPage();
|
|
39
|
+
await page.goto(`file://${resolve(input)}`, { waitUntil: "networkidle" });
|
|
40
|
+
await page.pdf({
|
|
41
|
+
path: output,
|
|
42
|
+
width: "1280px",
|
|
43
|
+
height: "720px",
|
|
44
|
+
printBackground: true,
|
|
45
|
+
});
|
|
46
|
+
await browser.close();
|
|
47
|
+
console.log(`Done: ${output}`);
|
|
@@ -1,57 +1,46 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: draft-emails
|
|
3
|
-
description: Draft email responses using the knowledge base and calendar for
|
|
3
|
+
description: Draft and send email responses using the knowledge base and calendar for context. Use when the user asks to draft, reply to, respond to, or send an email.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Draft Emails
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
Draft and send email responses. Uses the knowledge base and calendar for full
|
|
9
|
+
context on every person and conversation. All drafts require explicit user
|
|
10
|
+
approval before sending.
|
|
11
11
|
|
|
12
12
|
## Trigger
|
|
13
13
|
|
|
14
|
-
Run when the user asks to draft, reply to,
|
|
14
|
+
Run when the user asks to draft, reply to, respond to, or send an email.
|
|
15
15
|
|
|
16
16
|
## Prerequisites
|
|
17
17
|
|
|
18
18
|
- Knowledge base populated (from `extract-entities` skill)
|
|
19
|
-
- Synced email data in `~/.cache/fit/basecamp/apple_mail/`
|
|
20
|
-
`~/.cache/fit/basecamp/gmail/`
|
|
19
|
+
- Synced email data in `~/.cache/fit/basecamp/apple_mail/`
|
|
21
20
|
|
|
22
|
-
##
|
|
21
|
+
## Data Locations
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
## Outputs
|
|
35
|
-
|
|
36
|
-
- `drafts/{email_id}_draft.md` — draft email files
|
|
37
|
-
- `drafts/last_processed` — updated timestamp
|
|
38
|
-
- `drafts/drafted` — updated with newly drafted IDs
|
|
39
|
-
- `drafts/ignored` — updated with newly ignored IDs
|
|
23
|
+
| Data | Location |
|
|
24
|
+
| --------------- | --------------------------------------------- |
|
|
25
|
+
| People | `knowledge/People/*.md` |
|
|
26
|
+
| Organizations | `knowledge/Organizations/*.md` |
|
|
27
|
+
| Email threads | `~/.cache/fit/basecamp/apple_mail/*.md` |
|
|
28
|
+
| Calendar events | `~/.cache/fit/basecamp/apple_calendar/*.json` |
|
|
29
|
+
| Drafted IDs | `drafts/drafted` (one ID per line) |
|
|
30
|
+
| Ignored IDs | `drafts/ignored` (one ID per line) |
|
|
31
|
+
| Draft files | `drafts/{email_id}_draft.md` |
|
|
40
32
|
|
|
41
33
|
---
|
|
42
34
|
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
**BEFORE drafting any email, you MUST look up the person/organization in the
|
|
46
|
-
knowledge base.**
|
|
35
|
+
## Always Look Up Context First
|
|
47
36
|
|
|
48
|
-
|
|
37
|
+
**BEFORE drafting any email, look up the person/organization in the knowledge
|
|
38
|
+
base.**
|
|
49
39
|
|
|
50
|
-
1. **
|
|
51
|
-
2. **
|
|
52
|
-
3. **
|
|
53
|
-
4. **
|
|
54
|
-
5. **THEN DRAFT** — Only now draft the email, using this context
|
|
40
|
+
1. **Search** — `rg -l "Name" knowledge/`
|
|
41
|
+
2. **Read** — `cat "knowledge/People/Name.md"`
|
|
42
|
+
3. **Understand** — Extract role, organization, relationship history, open items
|
|
43
|
+
4. **Draft** — Only now draft the email, using this context
|
|
55
44
|
|
|
56
45
|
## Key Principles
|
|
57
46
|
|
|
@@ -59,55 +48,46 @@ When the user says "draft an email to Monica" or mentions ANY person:
|
|
|
59
48
|
|
|
60
49
|
- If intent is unclear, ASK what the email should be about
|
|
61
50
|
- If a person has multiple contexts, ASK which one
|
|
62
|
-
- **WRONG:** "Here are three variants — pick one"
|
|
63
|
-
- **RIGHT:** "I see Akhilesh is involved in Rowboat and banking. Which topic?"
|
|
64
51
|
|
|
65
|
-
**Be decisive
|
|
52
|
+
**Be decisive:**
|
|
66
53
|
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
|
|
71
|
-
## Processing Flow
|
|
72
|
-
|
|
73
|
-
### Step 1: Scan for New Emails
|
|
54
|
+
- Draft ONE email — no multiple versions
|
|
55
|
+
- Personalize from knowledge base context
|
|
56
|
+
- Match the tone of the incoming email
|
|
74
57
|
|
|
75
|
-
|
|
58
|
+
**User approves before sending:**
|
|
76
59
|
|
|
77
|
-
|
|
60
|
+
- Always present the draft for review before sending
|
|
61
|
+
- Never send without explicit approval
|
|
78
62
|
|
|
79
|
-
|
|
80
|
-
`drafts/drafted` or `drafts/ignored`.
|
|
63
|
+
## Workflow
|
|
81
64
|
|
|
82
|
-
###
|
|
65
|
+
### 1. Scan for New Emails
|
|
83
66
|
|
|
84
|
-
|
|
67
|
+
```bash
|
|
68
|
+
node scripts/scan-emails.mjs
|
|
69
|
+
```
|
|
85
70
|
|
|
86
|
-
-
|
|
87
|
-
- `**Thread ID:** <id>`
|
|
88
|
-
- `**Message Count:** <count>`
|
|
89
|
-
- `### From: Name <email@example.com>`
|
|
90
|
-
- `**Date:** <date>`
|
|
71
|
+
Outputs tab-separated `email_id<TAB>subject` for unprocessed emails.
|
|
91
72
|
|
|
92
|
-
###
|
|
73
|
+
### 2. Classify
|
|
93
74
|
|
|
94
|
-
**
|
|
75
|
+
**Ignore** (append ID to `drafts/ignored`):
|
|
95
76
|
|
|
96
77
|
- Newsletters, marketing, automated notifications
|
|
97
78
|
- Spam or irrelevant cold outreach
|
|
98
79
|
- Outbound emails from user with no reply
|
|
99
80
|
|
|
100
|
-
**
|
|
81
|
+
**Draft response for:**
|
|
101
82
|
|
|
102
83
|
- Meeting requests or scheduling
|
|
103
84
|
- Personal emails from known contacts
|
|
104
|
-
- Business inquiries
|
|
105
|
-
- Follow-ups on existing conversations
|
|
85
|
+
- Business inquiries or follow-ups
|
|
106
86
|
- Emails requesting information or action
|
|
107
87
|
|
|
108
|
-
###
|
|
88
|
+
### 3. Gather Context
|
|
109
89
|
|
|
110
|
-
**Knowledge
|
|
90
|
+
**Knowledge base** (required for every draft):
|
|
111
91
|
|
|
112
92
|
```bash
|
|
113
93
|
rg -l "sender_name" knowledge/
|
|
@@ -115,106 +95,88 @@ cat "knowledge/People/Sender Name.md"
|
|
|
115
95
|
cat "knowledge/Organizations/Company Name.md"
|
|
116
96
|
```
|
|
117
97
|
|
|
118
|
-
**Calendar (for scheduling emails)
|
|
98
|
+
**Calendar** (for scheduling emails):
|
|
119
99
|
|
|
120
100
|
```bash
|
|
121
|
-
ls ~/.cache/fit/basecamp/apple_calendar/
|
|
101
|
+
ls ~/.cache/fit/basecamp/apple_calendar/ 2>/dev/null
|
|
122
102
|
cat "$HOME/.cache/fit/basecamp/apple_calendar/event123.json"
|
|
123
103
|
```
|
|
124
104
|
|
|
125
|
-
###
|
|
105
|
+
### 4. Write Draft
|
|
126
106
|
|
|
127
|
-
|
|
107
|
+
Save to `drafts/{email_id}_draft.md`:
|
|
128
108
|
|
|
129
109
|
```markdown
|
|
130
110
|
# Draft Response
|
|
131
111
|
|
|
132
|
-
**
|
|
133
|
-
**
|
|
134
|
-
**
|
|
135
|
-
**Date Processed:** {date}
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## Context Used
|
|
140
|
-
- Calendar: {relevant info or N/A}
|
|
141
|
-
- Knowledge: {relevant notes or N/A}
|
|
112
|
+
**To:** recipient@example.com
|
|
113
|
+
**CC:** other@example.com
|
|
114
|
+
**Subject:** Re: {subject}
|
|
142
115
|
|
|
143
116
|
---
|
|
144
117
|
|
|
145
|
-
## Draft Response
|
|
146
|
-
|
|
147
|
-
Subject: Re: {subject}
|
|
148
|
-
|
|
149
118
|
{personalized draft body}
|
|
150
119
|
|
|
151
120
|
---
|
|
152
121
|
|
|
153
122
|
## Notes
|
|
154
|
-
|
|
123
|
+
- **Original Email ID:** {id}
|
|
124
|
+
- **From:** {sender}
|
|
125
|
+
- **Context:** {knowledge base notes used}
|
|
155
126
|
```
|
|
156
127
|
|
|
157
|
-
|
|
128
|
+
Guidelines:
|
|
158
129
|
|
|
159
|
-
- Draft ONE email —
|
|
160
|
-
-
|
|
161
|
-
-
|
|
162
|
-
|
|
163
|
-
|
|
130
|
+
- Draft ONE email — reference past interactions naturally
|
|
131
|
+
- For scheduling: propose specific times from calendar availability
|
|
132
|
+
- If unsure about intent, ask a clarifying question instead of drafting
|
|
133
|
+
|
|
134
|
+
### 5. Present for Review
|
|
135
|
+
|
|
136
|
+
Show the draft to the user. Wait for explicit approval before sending. The user
|
|
137
|
+
may request edits — apply them and present again.
|
|
164
138
|
|
|
165
|
-
###
|
|
139
|
+
### 6. Send
|
|
166
140
|
|
|
167
|
-
After
|
|
141
|
+
After the user approves, send via Apple Mail:
|
|
168
142
|
|
|
169
143
|
```bash
|
|
170
|
-
|
|
171
|
-
|
|
144
|
+
node scripts/send-email.mjs \
|
|
145
|
+
--to "recipient@example.com" \
|
|
146
|
+
--cc "other@example.com" \
|
|
147
|
+
--subject "Re: Subject" \
|
|
148
|
+
--body "Plain text body"
|
|
172
149
|
```
|
|
173
150
|
|
|
174
|
-
|
|
151
|
+
Options: `--to` (required), `--cc` (optional), `--bcc` (optional), `--subject`
|
|
152
|
+
(required), `--body` (required, plain text only).
|
|
175
153
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
**Emails Scanned:** X
|
|
179
|
-
**Drafts Created:** Y
|
|
180
|
-
**Ignored:** Z
|
|
154
|
+
Do NOT include an email signature — Apple Mail appends the configured signature
|
|
155
|
+
automatically.
|
|
181
156
|
|
|
182
|
-
###
|
|
183
|
-
- {id}: {subject} — {reason}
|
|
157
|
+
### 7. Update State
|
|
184
158
|
|
|
185
|
-
|
|
186
|
-
|
|
159
|
+
```bash
|
|
160
|
+
echo "$EMAIL_ID" >> drafts/drafted # or drafts/ignored
|
|
187
161
|
```
|
|
188
162
|
|
|
189
163
|
## Recruitment & Staffing Emails
|
|
190
164
|
|
|
191
|
-
**
|
|
192
|
-
|
|
193
|
-
When an email involves recruitment, staffing, or hiring:
|
|
165
|
+
**Candidates must NEVER be copied on internal emails about them.**
|
|
194
166
|
|
|
195
|
-
1. **Identify the candidate**
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
internal stakeholders (hiring managers, recruiters, interview panel, etc.).
|
|
199
|
-
The candidate’s email address must NOT appear in To, CC, or BCC
|
|
200
|
-
3. **Only recruiters email candidates directly** — If the email is a direct
|
|
201
|
-
reply TO a candidate (e.g., scheduling an interview, extending an offer),
|
|
202
|
-
flag it clearly so only the recruiter sends it. Add a note:
|
|
167
|
+
1. **Identify the candidate** from the thread and knowledge base
|
|
168
|
+
2. **Strip the candidate from recipients** — draft to internal stakeholders only
|
|
169
|
+
3. **Direct-to-candidate emails** — flag with:
|
|
203
170
|
`⚠️ RECRUITER ONLY — This email goes directly to the candidate.`
|
|
204
171
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
- Interview feedback or debrief
|
|
208
|
-
- Candidate evaluation or comparison
|
|
209
|
-
- Hiring decision discussions
|
|
210
|
-
- Compensation/offer discussions
|
|
211
|
-
- Reference check follow-ups between colleagues
|
|
172
|
+
Internal recruitment emails (candidate excluded): interview feedback, candidate
|
|
173
|
+
evaluation, hiring decisions, compensation discussions, reference checks.
|
|
212
174
|
|
|
213
|
-
**When in doubt:** If an email thread mentions a candidate
|
|
214
|
-
|
|
175
|
+
**When in doubt:** If an email thread mentions a candidate and involves multiple
|
|
176
|
+
internal recipients, treat it as internal and exclude the candidate.
|
|
215
177
|
|
|
216
178
|
## Constraints
|
|
217
179
|
|
|
218
|
-
- Never
|
|
180
|
+
- Never send without explicit user approval
|
|
219
181
|
- Be conservative with ignore — when in doubt, create a draft
|
|
220
|
-
- For ambiguous emails,
|
|
182
|
+
- For ambiguous emails, draft with a note explaining the ambiguity
|