# Mode: followup -- Follow-up Cadence Tracker > **Read `voice-dna.md` (if present) and apply it to every generated email/LinkedIn draft.** This mode is standalone — it does NOT load `_shared.md`, so read `voice-dna.md` directly. Follow-up drafts are conversational, so apply the full guardrail: banned words/phrases/patterns, no em-dashes, no negative parallelisms (§3-4) AND conversational voice — contractions, varied rhythm, direct "I"/"you" (§1-2). Never drop or soften a real metric from `cv.md` for style. ## Purpose Track follow-up cadence for active applications. Flag overdue follow-ups, extract contacts from notes, and generate tailored follow-up email/LinkedIn drafts using report context. ## Inputs - `data/applications.md` — Application tracker - `data/follow-ups.md` — Follow-up history (created on first use) - `reports/` — Evaluation reports (for context in drafts) - `config/profile.yml` — User profile (name, identity) - `cv.md` — CV for proof points in drafts ## Step 1 — Run Cadence Script Execute: ```bash node followup-cadence.mjs ``` Parse the JSON output. It contains: | Key | Contents | |-----|----------| | `metadata` | Analysis date, total tracked, actionable count, overdue/urgent/cold/waiting counts | | `entries` | Per-application: company, role, status, days since application, follow-up count, urgency, next follow-up date, extracted contacts, report path | | `cadenceConfig` | Cadence rules (applied: 7 days, responded: 3 days, interview: 1 day) | If no actionable entries, tell the user: > "No active applications to follow up on. Apply to some roles first with `/career-ops` and come back when they're aging." ## Step 2 — Display Dashboard Show a cadence dashboard sorted by urgency (urgent > overdue > waiting > cold): ``` Follow-up Cadence Dashboard — {date} {N} applications tracked, {N} actionable | # | Company | Role | Status | Days | Follow-ups | Next | Urgency | Contact | ``` Use visual indicators: - **URGENT** — respond within 24 hours (company replied) - **OVERDUE** — follow-up is past due - **waiting (X days)** — on track, follow-up scheduled - **COLD** — 2+ follow-ups sent, suggest closing ## Step 3 — Generate Follow-up Drafts For each **overdue** or **urgent** entry only: 1. Read the linked report (`reportPath` from JSON) for company context 2. Read `cv.md` for proof points 3. Read `config/profile.yml` for candidate name and identity ### Email Follow-up Framework (first follow-up, followupCount == 0) Generate a 3-4 sentence email: 1. **Sentence 1:** Reference the specific role + when you applied. Be specific — mention the company name and role title. 2. **Sentence 2:** One concrete value-add from the report's Block B match or a proof point from cv.md. Quantify if possible. 3. **Sentence 3:** Soft ask + availability. Offer a specific time window ("this week" or "next Tuesday"). 4. **Sentence 4 (optional):** Brief mention of a relevant recent project or achievement. **Rules:** - Professional but warm, NOT desperate - **NEVER** use "just checking in", "just following up", "touching base", or "circling back" - Lead with value, not with the ask - Reference something specific to THAT company (from report Block A) - Keep under 150 words - Include a subject line - Use the candidate's name from `config/profile.yml` **Example tone:** > Subject: Re: Senior PHP/Laravel Developer — IxDF > > Hi [contact name or "team"], > > I submitted my application for the Senior PHP/Laravel Developer role on April 7th. I wanted to share that my production Laravel app (Barbeiro.app — 120 models, 315 API endpoints, full test suite) closely mirrors the TDD-driven culture described in the posting. > > I'd love to discuss how my 15 years of PHP experience and hands-on AI tooling workflow could contribute to IxDF's platform. Would any time this week work for a brief conversation? > > Best, > [Name] ### LinkedIn Follow-up (if no email contact found) Reuse the contacto framework: 3 sentences, 300 character max. - Hook specific to company → proof point → soft ask - Suggest the user run `/career-ops contacto {company}` to find the right person first ### Second Follow-up (followupCount == 1) Shorter than first (2-3 sentences). Take a **new angle**: - Share a relevant insight, article, or project update - Don't repeat the first follow-up's content - Still reference the role specifically ### Cold Application (followupCount >= 2) Do NOT generate another follow-up. Instead suggest: > "This application has had {N} follow-ups with no response. Consider: > - Updating status to `Discarded` if the role seems filled > - Trying a different contact via `/career-ops contacto` > - Keeping in `Applied` status but deprioritizing" ## Step 4 — Present Drafts For each draft, show: ``` ## Follow-up: {Company} — {Role} (#{num}) **To:** {email or "No contact found — run `/career-ops contacto` first"} **Subject:** {subject line} **Days since application:** {N} **Follow-ups sent:** {N} **Channel:** Email / LinkedIn {draft text} ``` ## Step 5 — Record Follow-ups After the user reviews and says they've sent a follow-up, record it: 1. If `data/follow-ups.md` doesn't exist, create it (this exact header — the same one the web UI writes; `followup-cadence.mjs` parses these columns): ```markdown # Follow-ups | num | appNum | date | company | role | channel | contact | notes | |---|---|---|---|---|---|---|---| ``` 2. Append a row with: - `num` = next sequential number in the follow-ups table - `appNum` = application number from tracker - `date` = today's date (YYYY-MM-DD) - `company` = company name - `role` = role title - `channel` = Email / LinkedIn / Other - `contact` = who it was sent to - `notes` = brief note (e.g., "First follow-up, referenced Barbeiro.app") 3. Optionally update the Notes column in `data/applications.md` with "Follow-up {N} sent {YYYY-MM-DD}" **IMPORTANT:** Only record follow-ups the user confirms they actually sent. Never record a draft as sent. ### Pinned next dates & automatic seeding `data/follow-ups.md` also supports pin lines that override the computed schedule for a single application: ```text - next #42 2026-07-10 (set 2026-07-02) ``` `#42` is the application number, the first date is the pinned NEXT follow-up date, and `(set …)` is the day the pin was made. Pins take precedence over the computed schedule until a follow-up is logged on or after the set-date; the latest pin per application wins; deleting the line clears the pin. Pins may be seeded AUTOMATICALLY when an application turns Applied — `node followup-seed.mjs ` (run by the `apply` mode's Step 9) appends a pin scheduling the first follow-up at apply date + the `applied_first` cadence. Seeding is idempotent, and a stale pin left behind by a later Rejected/Discarded transition is harmless because the cadence analysis ignores non-actionable statuses. ## Step 6 — Summary After showing all drafts, summarize: > **Follow-up Dashboard** ({date}) > - {N} applications being tracked > - {N} overdue — drafts generated above > - {N} urgent — respond today > - {N} waiting — next follow-up dates shown > - {N} cold — consider closing > > Review the drafts above and tell me which ones you've sent so I can record them. ## Cadence Rules Reference | Status | First follow-up | Subsequent | Max attempts | |--------|----------------|------------|-------------| | Applied | 7 days after application | Every 7 days | 2 (then mark cold) | | Responded | 1 day (urgent reply) | Every 3 days | No limit | | Interview | 1 day after (thank-you) | Every 3 days | No limit | These defaults can be overridden via `node followup-cadence.mjs --applied-days N`.