@forwardimpact/basecamp 2.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.
Files changed (39) hide show
  1. package/config/scheduler.json +5 -0
  2. package/package.json +1 -1
  3. package/src/basecamp.js +288 -57
  4. package/template/.claude/agents/chief-of-staff.md +6 -2
  5. package/template/.claude/agents/concierge.md +2 -3
  6. package/template/.claude/agents/librarian.md +4 -6
  7. package/template/.claude/agents/recruiter.md +222 -0
  8. package/template/.claude/settings.json +0 -4
  9. package/template/.claude/skills/analyze-cv/SKILL.md +267 -0
  10. package/template/.claude/skills/create-presentations/SKILL.md +2 -2
  11. package/template/.claude/skills/create-presentations/references/slide.css +1 -1
  12. package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.mjs +47 -0
  13. package/template/.claude/skills/draft-emails/SKILL.md +85 -123
  14. package/template/.claude/skills/draft-emails/scripts/scan-emails.mjs +66 -0
  15. package/template/.claude/skills/draft-emails/scripts/send-email.mjs +118 -0
  16. package/template/.claude/skills/extract-entities/SKILL.md +2 -2
  17. package/template/.claude/skills/extract-entities/scripts/state.mjs +130 -0
  18. package/template/.claude/skills/manage-tasks/SKILL.md +242 -0
  19. package/template/.claude/skills/organize-files/SKILL.md +3 -3
  20. package/template/.claude/skills/organize-files/scripts/organize-by-type.mjs +105 -0
  21. package/template/.claude/skills/organize-files/scripts/summarize.mjs +84 -0
  22. package/template/.claude/skills/process-hyprnote/SKILL.md +2 -2
  23. package/template/.claude/skills/send-chat/SKILL.md +170 -0
  24. package/template/.claude/skills/sync-apple-calendar/SKILL.md +5 -5
  25. package/template/.claude/skills/sync-apple-calendar/scripts/sync.mjs +325 -0
  26. package/template/.claude/skills/sync-apple-mail/SKILL.md +6 -6
  27. package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.mjs +374 -0
  28. package/template/.claude/skills/sync-apple-mail/scripts/sync.mjs +629 -0
  29. package/template/.claude/skills/track-candidates/SKILL.md +375 -0
  30. package/template/.claude/skills/weekly-update/SKILL.md +250 -0
  31. package/template/CLAUDE.md +63 -40
  32. package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.js +0 -32
  33. package/template/.claude/skills/draft-emails/scripts/scan-emails.sh +0 -34
  34. package/template/.claude/skills/extract-entities/scripts/state.py +0 -100
  35. package/template/.claude/skills/organize-files/scripts/organize-by-type.sh +0 -42
  36. package/template/.claude/skills/organize-files/scripts/summarize.sh +0 -21
  37. package/template/.claude/skills/sync-apple-calendar/scripts/sync.py +0 -242
  38. package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.py +0 -104
  39. package/template/.claude/skills/sync-apple-mail/scripts/sync.py +0 -455
@@ -0,0 +1,375 @@
1
+ ---
2
+ name: track-candidates
3
+ description: Scan synced email threads for recruitment candidates, extract structured profiles, and create/update notes in knowledge/Candidates/. Use when the user asks to track candidates, process recruitment emails, or update the hiring pipeline.
4
+ ---
5
+
6
+ # Track Candidates
7
+
8
+ Scan synced email threads from `~/.cache/fit/basecamp/apple_mail/` for
9
+ recruitment candidates. Extract structured candidate profiles and create/update
10
+ notes in `knowledge/Candidates/`. This builds a local, searchable recruitment
11
+ pipeline from scattered email threads.
12
+
13
+ ## Trigger
14
+
15
+ Run this skill:
16
+
17
+ - When the user asks to track, process, or update candidates
18
+ - When the user asks about recruitment pipeline status
19
+ - After `sync-apple-mail` has pulled new threads
20
+
21
+ ## Prerequisites
22
+
23
+ - Synced email data in `~/.cache/fit/basecamp/apple_mail/` (from
24
+ `sync-apple-mail`)
25
+ - User identity configured in `USER.md`
26
+
27
+ ## Inputs
28
+
29
+ - `~/.cache/fit/basecamp/apple_mail/*.md` — synced email threads
30
+ - `~/.cache/fit/basecamp/apple_mail/attachments/` — CV/resume attachments
31
+ - `~/.cache/fit/basecamp/state/graph_processed` — tracks processed files (shared
32
+ with `extract-entities`)
33
+ - `USER.md` — user identity for self-exclusion
34
+
35
+ ## Outputs
36
+
37
+ - `knowledge/Candidates/{Full Name}/brief.md` — candidate profile note
38
+ - `knowledge/Candidates/{Full Name}/CV.pdf` — local copy of CV (or `CV.docx`)
39
+ - `~/.cache/fit/basecamp/state/graph_processed` — updated with processed threads
40
+
41
+ ---
42
+
43
+ ## Before Starting
44
+
45
+ 1. Read `USER.md` to get the user's name, email, and domain.
46
+ 2. Find new/changed email files to process:
47
+
48
+ ```bash
49
+ node .claude/skills/extract-entities/scripts/state.mjs check
50
+ ```
51
+
52
+ This outputs one file path per line for all source files that are new or
53
+ changed. Filter this list to only `apple_mail/*.md` files — calendar events are
54
+ not relevant for candidate tracking.
55
+
56
+ **Process in batches of 10 files per run.**
57
+
58
+ ## Step 0: Build Candidate Index
59
+
60
+ Scan existing candidate notes to avoid duplicates:
61
+
62
+ ```bash
63
+ ls -d knowledge/Candidates/*/
64
+ ```
65
+
66
+ Each candidate has their own directory at `knowledge/Candidates/{Name}/`
67
+ containing standardized files:
68
+
69
+ - `brief.md` — the candidate profile note
70
+ - `CV.pdf` (or `CV.docx`) — local copy of CV (if available)
71
+
72
+ For each existing note, read the header fields (Name, Role, Source, Status) to
73
+ build a mental index of known candidates.
74
+
75
+ Also scan `knowledge/People/`, `knowledge/Organizations/`, and
76
+ `knowledge/Projects/` to resolve recruiter names, agency orgs, and project
77
+ links.
78
+
79
+ ## Step 1: Identify Recruitment Emails
80
+
81
+ For each new/changed email thread, determine if it contains candidate
82
+ information. Look for these signals:
83
+
84
+ ### CV/Resume Attachments
85
+
86
+ Check `~/.cache/fit/basecamp/apple_mail/attachments/{thread_id}/` for PDF or
87
+ DOCX files with candidate names in filenames.
88
+
89
+ ### Recruiter Sender Domains
90
+
91
+ Emails from known recruitment agency domains. Map sender domains to
92
+ organizations using `knowledge/Organizations/` — look for notes tagged as
93
+ recruitment agencies.
94
+
95
+ If no known agencies exist yet, use sender patterns as hints:
96
+
97
+ - Multiple candidates presented by the same sender
98
+ - Structured profile formatting (rate, availability, skills)
99
+ - Forwarding candidate CVs on behalf of others
100
+
101
+ ### Profile Presentation Patterns
102
+
103
+ Look for structured candidate descriptions containing:
104
+
105
+ - "Rate:" or rate/cost information
106
+ - "Availability:" or notice period
107
+ - "English:" or language level
108
+ - "Location:" or country/city
109
+ - Candidate name + role formatting (e.g. "Staff Software Engineer")
110
+ - "years of experience" or "YoE"
111
+ - Skills/tech stack listings
112
+
113
+ ### Interview Scheduling
114
+
115
+ - "schedule a call", "schedule an interview"
116
+ - "first interview", "second interview", "technical interview"
117
+ - "interview slot", "available for a call"
118
+
119
+ ### Follow-up on Existing Candidates
120
+
121
+ Threads that mention a candidate already in `knowledge/Candidates/` by name —
122
+ these update pipeline status.
123
+
124
+ **Skip threads that don't match any signal.** Not all email threads are
125
+ recruitment-related.
126
+
127
+ ## Step 2: Extract Candidate Data
128
+
129
+ For each candidate found in a recruitment email, extract:
130
+
131
+ | Field | Source | Required |
132
+ | ----------------- | ------------------------------------------------- | ------------------- |
133
+ | **Name** | Filename, email body, CV | Yes |
134
+ | **Role** | Email body, CV | Yes |
135
+ | **Rate** | Email body (e.g. "$120/hr", "€80/h") | If available |
136
+ | **Availability** | Email body (e.g. "1 month notice", "immediately") | If available |
137
+ | **English** | Email body (e.g. "B2", "Upper-intermediate") | If available |
138
+ | **Location** | Email body, CV | If available |
139
+ | **Source agency** | Sender domain → Organization | Yes |
140
+ | **Recruiter** | Email sender or CC'd recruiter | Yes |
141
+ | **CV path** | Attachment directory | If available |
142
+ | **Skills** | Email body, CV | If available |
143
+ | **Gender** | Name, pronouns, recruiter context | If identifiable |
144
+ | **Summary** | Email body, CV | Yes — 2-3 sentences |
145
+
146
+ ### Determining Gender
147
+
148
+ Record the candidate's gender when identifiable from the email or CV:
149
+
150
+ - Pronouns used by the recruiter ("she is available", "her CV attached")
151
+ - Gendered titles ("Ms.", "Mrs.", "Mr.")
152
+ - First name when culturally unambiguous
153
+
154
+ Record as `Woman`, `Man`, or `—` (unknown). When uncertain, use `—` — never
155
+ guess. This field supports pool diversity tracking; it has **no bearing** on
156
+ hiring decisions or assessment criteria.
157
+
158
+ ### Determining Source and Recruiter
159
+
160
+ - Map sender email domain to an organization in `knowledge/Organizations/`.
161
+ - The person who sent or forwarded the candidate profile is the recruiter. Look
162
+ them up in `knowledge/People/` and link with `[[People/Name]]`.
163
+ - If the organization or recruiter doesn't exist yet, create notes for them.
164
+
165
+ ### CV Attachment Path
166
+
167
+ Check for attachments:
168
+
169
+ ```bash
170
+ ls ~/.cache/fit/basecamp/apple_mail/attachments/{thread_id}/
171
+ ```
172
+
173
+ Match CV files to candidates by name similarity in the filename. Copy the CV
174
+ into the candidate's directory with a standardized name:
175
+
176
+ ```bash
177
+ mkdir -p "knowledge/Candidates/{Full Name}"
178
+ cp "~/.cache/fit/basecamp/apple_mail/attachments/{thread_id}/{filename}" \
179
+ "knowledge/Candidates/{Full Name}/CV.pdf"
180
+ ```
181
+
182
+ Use `CV.pdf` for PDF files and `CV.docx` for Word documents. The `## CV` link in
183
+ the brief uses a relative path: `./CV.pdf`.
184
+
185
+ ## Step 3: Determine Pipeline Status
186
+
187
+ Assign a status based on the email context:
188
+
189
+ | Status | Signal |
190
+ | ------------------ | ----------------------------------------------------- |
191
+ | `new` | CV/profile received, no response yet |
192
+ | `screening` | Under review, questions asked about the candidate |
193
+ | `first-interview` | First interview scheduled or completed |
194
+ | `second-interview` | Second interview scheduled or completed |
195
+ | `offer` | Offer extended |
196
+ | `hired` | Accepted and onboarding |
197
+ | `rejected` | Explicitly passed on ("not a fit", "pass", "decline") |
198
+ | `on-hold` | Paused, waiting on notice period, or deferred |
199
+
200
+ **Default to `new`** if no response signals are found. Read the full thread
201
+ chronologically to determine the most recent status.
202
+
203
+ ### Status Advancement Signals
204
+
205
+ Look for these patterns in the hiring manager's replies:
206
+
207
+ - "let's schedule" / "set up an interview" → `first-interview`
208
+ - "second round" / "follow-up interview" → `second-interview`
209
+ - "not what we're looking for" / "pass" → `rejected`
210
+ - "extend an offer" / "make an offer" → `offer`
211
+ - "they've accepted" / "start date" → `hired`
212
+ - "put on hold" / "come back to later" → `on-hold`
213
+ - No response to profile → remains `new`
214
+
215
+ ## Step 4: Build Pipeline Timeline
216
+
217
+ Extract a chronological timeline from the thread:
218
+
219
+ ```markdown
220
+ ## Pipeline
221
+ - **2026-01-29**: Profile shared by {Recruiter} ({Agency})
222
+ - **2026-02-03**: {Recruiter} followed up asking about scheduling
223
+ - **2026-02-10**: {Hiring Manager} requested first interview
224
+ ```
225
+
226
+ Each entry: `**{date}**: {what happened}` — one line per meaningful event.
227
+ Include who did what. Skip noise (signature blocks, disclaimers, forwarded
228
+ headers).
229
+
230
+ ## Step 5: Write Candidate Note
231
+
232
+ ### For NEW candidates
233
+
234
+ Create the candidate directory and note:
235
+
236
+ ```bash
237
+ mkdir -p "knowledge/Candidates/{Full Name}"
238
+ ```
239
+
240
+ Then create `knowledge/Candidates/{Full Name}/brief.md`:
241
+
242
+ ```markdown
243
+ # {Full Name}
244
+
245
+ ## Info
246
+ **Role:** {role title}
247
+ **Rate:** {rate or "—"}
248
+ **Availability:** {availability or "—"}
249
+ **English:** {level or "—"}
250
+ **Location:** {location or "—"}
251
+ **Gender:** {Woman / Man / —}
252
+ **Source:** [[Organizations/{Agency}]] via [[People/{Recruiter Name}]]
253
+ **Status:** {pipeline status}
254
+ **First seen:** {date profile was shared, YYYY-MM-DD}
255
+ **Last activity:** {date of most recent thread activity, YYYY-MM-DD}
256
+
257
+ ## Summary
258
+ {2-3 sentences: role, experience level, key strengths}
259
+
260
+ ## CV
261
+ - [CV.pdf](./CV.pdf)
262
+
263
+ ## Connected to
264
+ - [[Organizations/{Agency}]] — sourced by
265
+ - [[People/{Recruiter}]] — recruiter
266
+
267
+ ## Pipeline
268
+ - **{date}**: {event}
269
+
270
+ ## Skills
271
+ {comma-separated skill tags}
272
+
273
+ ## Notes
274
+ ```
275
+
276
+ If a CV attachment exists, **copy it into the candidate directory** before
277
+ writing the note.
278
+
279
+ If no CV attachment exists, omit the `## CV` section entirely.
280
+
281
+ ### For EXISTING candidates
282
+
283
+ Read `knowledge/Candidates/{Full Name}/brief.md`, then apply targeted edits:
284
+
285
+ - Update **Status** if it has advanced
286
+ - Update **Last activity** date
287
+ - Add new **Pipeline** entries at the bottom (chronological order)
288
+ - Update **Rate**, **Availability**, or other fields if new information is
289
+ available
290
+ - Add new **Skills** if mentioned
291
+
292
+ **Use precise edits — don't rewrite the entire file.**
293
+
294
+ ## Step 5b: Capture Key Insights
295
+
296
+ After writing or updating candidate notes, check whether any **high-signal
297
+ observations** belong in `knowledge/Candidates/Insights.md`. This is a shared
298
+ file for cross-candidate strategic thinking.
299
+
300
+ **Add an insight only when:**
301
+
302
+ - A candidate may be better suited for a **different role** than the one they
303
+ applied for
304
+ - A candidate stands out as a **strong match** for a specific team or leader
305
+ - There's a meaningful **comparison between candidates** (e.g. complementary
306
+ strengths, overlapping profiles)
307
+ - A hiring decision or trade-off needs to be **remembered across sessions**
308
+
309
+ **Do NOT add:**
310
+
311
+ - Per-candidate status updates (that's what `brief.md` is for)
312
+ - Generic strengths/weaknesses already captured in interview notes
313
+ - Anything that only matters within a single candidate's context
314
+
315
+ Format: one bullet per insight under `## Placement Notes`, with
316
+ `[[Candidates/Name/brief|Name]]` links and relevant people/org backlinks.
317
+
318
+ ## Step 6: Ensure Bidirectional Links
319
+
320
+ After writing candidate notes, verify links go both ways:
321
+
322
+ | If you add... | Then also add... |
323
+ | ------------------------ | ------------------------------------------- |
324
+ | Candidate → Organization | Organization → Candidate |
325
+ | Candidate → Recruiter | Recruiter → Candidate (in Activity section) |
326
+ | Candidate → Project | Project → Candidate (in People section) |
327
+
328
+ Use absolute paths: `[[Candidates/Name/brief|Name]]`,
329
+ `[[Organizations/Agency]]`, `[[People/Recruiter]]`.
330
+
331
+ **Important:** Only add backlinks to Organization/People/Project notes if they
332
+ don't already reference the candidate. Check before editing.
333
+
334
+ ## Step 7: Update Graph State
335
+
336
+ After processing each email thread, mark it as processed:
337
+
338
+ ```bash
339
+ node .claude/skills/extract-entities/scripts/state.mjs update "{file_path}"
340
+ ```
341
+
342
+ This uses the same state file as `extract-entities`, so threads processed here
343
+ won't be re-scanned by either skill (unless the file changes).
344
+
345
+ ## Step 8: Tag Skills with Framework IDs
346
+
347
+ When a candidate's email or CV mentions technical skills, map them to the
348
+ engineering framework using `fit-pathway`:
349
+
350
+ ```bash
351
+ npx fit-pathway skill --list
352
+ ```
353
+
354
+ Use framework skill IDs (e.g. `data_integration`, `full_stack_development`,
355
+ `architecture_and_design`) in the **Skills** section of the candidate brief
356
+ instead of free-form tags. This enables consistent cross-candidate comparison.
357
+
358
+ If a candidate has a CV attachment, flag them for the `analyze-cv` skill which
359
+ produces a full framework-aligned assessment.
360
+
361
+ ## Quality Checklist
362
+
363
+ - [ ] Scanned all new/changed email threads for recruitment signals
364
+ - [ ] Extracted all candidates found (check attachment directories too)
365
+ - [ ] Each candidate has a complete note with all available fields
366
+ - [ ] CV paths are correct and point to actual files
367
+ - [ ] Pipeline status reflects the latest thread activity
368
+ - [ ] Timeline entries are in chronological order
369
+ - [ ] Used `[[absolute/path]]` links throughout
370
+ - [ ] Bidirectional links are consistent
371
+ - [ ] Graph state updated for all processed threads
372
+ - [ ] No duplicate candidate notes created
373
+ - [ ] Key strategic insights added to `Insights.md` where warranted
374
+ - [ ] Skills tagged using framework skill IDs where possible
375
+ - [ ] Gender field populated where identifiable (Woman / Man / —)
@@ -0,0 +1,250 @@
1
+ ---
2
+ name: weekly-update
3
+ description: Generate or refresh a weekly priorities document. Pulls from task boards, recent activity, and calendar to create a point-in-time snapshot. Use when the user asks to update their weekly, prep for the week, or on a Monday morning schedule.
4
+ ---
5
+
6
+ # Weekly Update
7
+
8
+ Generate or refresh a weekly priorities document in
9
+ `knowledge/Weeklies/{Person Name}/`. Each weekly is a point-in-time snapshot —
10
+ created at the start of the week, updated as priorities shift, and closed out
11
+ with a retrospective at end-of-week.
12
+
13
+ ## Trigger
14
+
15
+ Run this skill:
16
+
17
+ - When the user asks to update their weekly or prep for the week
18
+ - Monday mornings (scheduled)
19
+ - When the user asks to review someone's weekly
20
+ - End-of-week to fill in accomplishments and retrospective
21
+
22
+ ## Prerequisites
23
+
24
+ - `knowledge/Weeklies/` directory exists
25
+ - `knowledge/Tasks/{Person Name}.md` exists (task board — see `manage-tasks`
26
+ skill)
27
+ - Calendar data in `~/.cache/fit/basecamp/apple_calendar/`
28
+ - User identity configured in `USER.md`
29
+
30
+ ## Inputs
31
+
32
+ - `knowledge/Tasks/{Person Name}.md` — current task board
33
+ - `knowledge/People/{Person Name}.md` — recent activity, context
34
+ - `~/.cache/fit/basecamp/apple_calendar/*.json` — calendar events for the week
35
+ - Previous weekly document (if exists) — for continuity and carry-forward
36
+
37
+ ## Outputs
38
+
39
+ - `knowledge/Weeklies/{Person Name}/{YYYY}-W{WW}.md` — the weekly document
40
+
41
+ ---
42
+
43
+ ## Weekly Document Format
44
+
45
+ ```markdown
46
+ # {YYYY}-W{WW} — {Person Name}
47
+
48
+ > {Focus statement: one sentence summarizing the week's theme}
49
+
50
+ ## Priorities
51
+
52
+ - [ ] Priority one — [[Projects/Name]]
53
+ - [ ] Priority two
54
+ - [x] Completed priority
55
+
56
+ ## Key Meetings
57
+
58
+ - **Monday**: Meeting title with [[People/Name]] — purpose
59
+ - **Wednesday**: Meeting title — purpose
60
+
61
+ ## Blockers
62
+
63
+ - Waiting on X from [[People/Name]]
64
+
65
+ ## Accomplishments
66
+
67
+ - Completed X
68
+ - Shipped Y
69
+
70
+ ## Retrospective
71
+
72
+ - **Went well:** ...
73
+ - **Didn't go as planned:** ...
74
+ - **Carry forward:** ...
75
+ ```
76
+
77
+ **Key conventions:**
78
+
79
+ - **Week numbers:** ISO 8601 (e.g., `2026-W08`)
80
+ - **Priorities:** Top 3-7 items pulled from the task board
81
+ - **Key Meetings:** Substantive meetings only (skip recurring standups)
82
+ - **Retrospective:** Filled at end-of-week only
83
+ - **All backlinks** use absolute paths: `[[People/Name]]`, `[[Projects/Name]]`,
84
+ `[[Tasks/Name]]`
85
+
86
+ ## Before Starting
87
+
88
+ 1. Read `USER.md` to identify the user.
89
+ 2. Determine the target person (default: current user from `USER.md`).
90
+ 3. Calculate the current ISO week number and date range:
91
+
92
+ ```bash
93
+ # Current ISO week
94
+ date +%G-W%V
95
+
96
+ # Monday and Friday of current week (macOS)
97
+ date -v-mon +%Y-%m-%d
98
+ date -v+fri +%Y-%m-%d
99
+ ```
100
+
101
+ 4. Check if a weekly already exists for this week:
102
+
103
+ ```bash
104
+ ls "knowledge/Weeklies/{Person Name}/" 2>/dev/null
105
+ ```
106
+
107
+ 5. Determine the mode:
108
+ - **No existing weekly:** Create new (start-of-week)
109
+ - **Existing weekly:** Update (mid-week or end-of-week)
110
+
111
+ ## Step 1: Gather Context
112
+
113
+ ### 1a. Read the task board
114
+
115
+ ```bash
116
+ cat "knowledge/Tasks/{Person Name}.md"
117
+ ```
118
+
119
+ Extract:
120
+
121
+ - `## In Progress` tasks → top priorities (already being worked on)
122
+ - `## Open` tasks with `high` priority or near due dates → candidate priorities
123
+ - `## Blocked` tasks → blockers section
124
+ - `## Recently Done` tasks completed this week → accomplishments
125
+
126
+ ### 1b. Read recent activity
127
+
128
+ ```bash
129
+ cat "knowledge/People/{Person Name}.md"
130
+ ```
131
+
132
+ Look at the `## Activity` section for entries from this week. These inform
133
+ accomplishments and provide context for the focus statement.
134
+
135
+ ### 1c. Read calendar for the week
136
+
137
+ Find events falling within the Monday–Friday range:
138
+
139
+ ```bash
140
+ ls ~/.cache/fit/basecamp/apple_calendar/
141
+ ```
142
+
143
+ Read each calendar event and filter by date. Extract:
144
+
145
+ - Meeting title
146
+ - Attendees (resolve to `[[People/Name]]` where possible)
147
+ - Time/day
148
+ - Description or agenda (if present)
149
+
150
+ Filter out:
151
+
152
+ - All-day placeholder events with no attendees ("Block", "OOO", "Focus time")
153
+ - Declined events
154
+ - Cancelled events
155
+
156
+ ### 1d. Read previous weekly (if exists)
157
+
158
+ Check for last week's document:
159
+
160
+ ```bash
161
+ ls "knowledge/Weeklies/{Person Name}/" | sort | tail -1
162
+ ```
163
+
164
+ If it exists, read it to:
165
+
166
+ - Carry forward any `[ ]` unchecked priorities
167
+ - Note retrospective items that affect this week
168
+ - Maintain continuity of ongoing themes
169
+
170
+ ## Step 2: Generate or Update
171
+
172
+ ### Creating a new weekly (start of week)
173
+
174
+ 1. **Focus:** Synthesize from highest-priority tasks and key meetings. What's
175
+ the main theme? Write one sentence.
176
+ 2. **Priorities:** Pull from task board:
177
+ - All `## In Progress` items first
178
+ - Then `high` priority `## Open` items
179
+ - Then items with due dates this week
180
+ - Carry forward incomplete priorities from last week
181
+ - Cap at 5-7 items. If more exist, prioritize ruthlessly.
182
+ 3. **Key Meetings:** From calendar. Format as
183
+ `**{Day}**: {title} with [[People/Name]] — {purpose}`. Look up attendees in
184
+ knowledge base to add context about purpose.
185
+ 4. **Blockers:** From task board's `## Blocked` section. Include what's needed
186
+ and from whom.
187
+ 5. **Accomplishments:** Leave empty (or pre-fill with anything completed Monday
188
+ morning).
189
+ 6. **Retrospective:** Leave empty.
190
+
191
+ ### Updating an existing weekly (mid-week)
192
+
193
+ 1. Re-read the task board for changes since the weekly was last updated.
194
+ 2. Mark completed priorities as `[x]`.
195
+ 3. Add new priorities that emerged (append to the list).
196
+ 4. Update blockers — remove resolved ones, add new ones.
197
+ 5. Add accomplishments as they happen.
198
+ 6. Do NOT touch the retrospective mid-week.
199
+
200
+ ### End-of-week update
201
+
202
+ 1. Final pass on priorities — mark all completed items `[x]`.
203
+ 2. Fill in accomplishments from the full week's activity (task board + People
204
+ note activity log).
205
+ 3. Write a brief retrospective:
206
+ - What went well?
207
+ - What didn't go as planned?
208
+ - What carries forward to next week?
209
+ 4. Note any unchecked priorities — these will carry forward to next week's
210
+ document.
211
+
212
+ ## Step 3: Write the Document
213
+
214
+ ### New weekly
215
+
216
+ Ensure the person's subdirectory exists:
217
+
218
+ ```bash
219
+ mkdir -p "knowledge/Weeklies/{Person Name}"
220
+ ```
221
+
222
+ Write the full document to: `knowledge/Weeklies/{Person Name}/{YYYY}-W{WW}.md`
223
+
224
+ ### Existing weekly
225
+
226
+ Use the Edit tool for targeted updates — mark items complete, add new entries,
227
+ fill sections. Do NOT rewrite the entire file.
228
+
229
+ ## Step 4: Cross-reference
230
+
231
+ After writing:
232
+
233
+ - If new priorities were identified that aren't on the task board, add them to
234
+ the task board (the task board is canonical, the weekly references it).
235
+ - If blockers were resolved, update the task board accordingly.
236
+ - The weekly is a **snapshot that references** the task board — the task board
237
+ is the source of truth for task status.
238
+
239
+ ## Quality Checklist
240
+
241
+ - [ ] ISO week number and date range are correct
242
+ - [ ] Focus statement reflects the actual week theme (not generic)
243
+ - [ ] Priorities pulled from task board (not invented)
244
+ - [ ] Priorities capped at 5-7 items
245
+ - [ ] Key meetings pulled from calendar (not guessed)
246
+ - [ ] Meeting attendees resolved to `[[People/Name]]` where known
247
+ - [ ] Blockers match task board's blocked items
248
+ - [ ] Previous week's carry-forward items included
249
+ - [ ] All backlinks use absolute paths
250
+ - [ ] Retrospective only filled at end-of-week