From 731cb5d831fadc535a1e59e8b25bf22a2f20ac3b Mon Sep 17 00:00:00 2001 From: usulpro Date: Tue, 9 Jun 2026 00:19:57 +0700 Subject: [PATCH] docs: make Trello the source of truth for applications Freeze tracking/applications.md (kept for backward compat, no longer read or written) and route all application tracking through the Trello BestJob board: - Write path: a Trello card in TODO is the application record; carries a Tracking footer (date, channel, CV used, JD link, status). Column = funnel status. - Read/dedup path: build known_applied from card titles via Trello MCP across the vacancy-bearing lists, titles-only to protect context; REST fields=name fallback documented for when the board grows. - Sync board columns: add In touch + Rejected (with IDs) to the canonical column table and to the dedup/funnel specs. Touches CLAUDE.md, tracking/CLAUDE.md, triage-jobs and get-tg-jobs skills. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/get-tg-jobs/SKILL.md | 17 +++++---- .claude/skills/triage-jobs/SKILL.md | 55 +++++++++++++++++++++++------ CLAUDE.md | 33 +++++++++-------- tracking/CLAUDE.md | 4 +-- 4 files changed, 75 insertions(+), 34 deletions(-) diff --git a/.claude/skills/get-tg-jobs/SKILL.md b/.claude/skills/get-tg-jobs/SKILL.md index e83d3dc..f19ba08 100644 --- a/.claude/skills/get-tg-jobs/SKILL.md +++ b/.claude/skills/get-tg-jobs/SKILL.md @@ -138,19 +138,22 @@ Follow the complete `triage-jobs` skill procedure on `tracking/telegram_inbox.js Key points from that skill: -1. **Pre-step**: build `known_applied` list before spawning Haiku: - ```bash - grep -E '^\|' tracking/applications.md | tail -n +2 | awk -F'|' '{print $3}' | sort -u +1. **Pre-step**: build the `known_applied` list from **Trello** (the source of truth) before spawning Haiku. Fetch the vacancy-bearing lists and keep **only card titles**: ``` - Also fetch Trello card titles from all BestJob board lists. Pass the merged list into every Haiku subagent prompt. + mcp__trello__set_active_board(boardId="6a1a9a5af082cb0526b22704") + mcp__trello__get_cards_by_list_id(listId="6a1aa59555aab72a261c42aa") # TODO + mcp__trello__get_cards_by_list_id(listId="6a1aa59a5e7e651b1352895b") # In Progress + mcp__trello__get_cards_by_list_id(listId="6a267e2e9ed02737346dc047") # In touch + mcp__trello__get_cards_by_list_id(listId="6a1aa5a1d8bcb0ed7234987b") # Applyed + mcp__trello__get_cards_by_list_id(listId="6a245a328452976c0d1fcca1") # Rejected + ``` + Distill to titles only, then pass that list into every Haiku subagent prompt. See the triage-jobs batch pre-step for the context-safety rules and the REST fallback when the board grows. `tracking/applications.md` is frozen/legacy — don't grep it. 2. **Stratify by priority**: all p1, p2, p3 go through Haiku first pass. Main session reviews only APPLY and VERIFY verdicts from Haiku. SKIP verdicts from Haiku accepted without re-review. 3. **VERIFY verdicts**: run a fast `WebSearch "{company} remote hiring countries"` to resolve geo, then apply Gate 1. -4. **APPLY verdicts**: for every confirmed APPLY — - - Add a row to `tracking/applications.md` with status `todo` - - Create a Trello card in the TODO column (`6a1aa59555aab72a261c42aa`) on board `6a1a9a5af082cb0526b22704` with: company, role, track, verdict summary, JD link +4. **APPLY verdicts**: for every confirmed APPLY — create a Trello card in the TODO column (`6a1aa59555aab72a261c42aa`) on board `6a1a9a5af082cb0526b22704`. The card **is** the application record (replaces the old applications.md row): title `Company — Role (Track X)`, description = verdict summary + a `Tracking` footer (date added, channel, CV used, JD link, status). See the triage-jobs skill ("After triage — update tracking") for the exact card schema. Do not write to `tracking/applications.md` (frozen/legacy). 5. **QUICK-APPLY verdicts**: note them explicitly in the session report; do not auto-add to Trello. Ask Oleg if he wants to proceed. diff --git a/.claude/skills/triage-jobs/SKILL.md b/.claude/skills/triage-jobs/SKILL.md index 9e288bc..d206b56 100644 --- a/.claude/skills/triage-jobs/SKILL.md +++ b/.claude/skills/triage-jobs/SKILL.md @@ -135,12 +135,15 @@ Run for all roles that cleared the gates (and for borderline cases to resolve am ### 5.0 — Check for prior application -Before deep research, check whether Oleg already applied to this role or company: +Before deep research, check whether Oleg already applied to this role or company. **Trello is the source of truth** (cards may sit in any column depending on stage): -- **Trello** (`mcp__trello__set_active_board` → board `6a1a9a5af082cb0526b22704`, then search cards or scan the "Applyed" list). -- **`tracking/applications.md`** — grep for company name. +- **Trello (primary)** — `mcp__trello__set_active_board(boardId="6a1a9a5af082cb0526b22704")`, then `get_cards_by_list_id` for the vacancy-bearing lists and match the company against card titles: + - TODO `6a1aa59555aab72a261c42aa` · In Progress `6a1aa59a5e7e651b1352895b` · In touch `6a267e2e9ed02737346dc047` · Applyed `6a1aa5a1d8bcb0ed7234987b` · Rejected `6a245a328452976c0d1fcca1` + - Include **Rejected** too — a previously-rejected company still counts as "already processed", don't re-surface it as new. + - Extract **only** each card's `name` + `shortUrl` — don't carry the full card JSON forward (see the context note in the batch pre-step). - **Telegram** — search in job-tracking chats if applicable. - **Gmail** — search for company name if accessible. +- `tracking/applications.md` is **frozen/legacy** — kept for backward compatibility only. Do **not** read or write it. If already applied → note it in the output, don't re-triage as new. @@ -233,11 +236,30 @@ When triaging `tracking/telegram_inbox.json`: ### Pre-step: build prior-applications list (do this once before spawning any subagent) -```bash -grep -E '^\|' tracking/applications.md | tail -n +2 | awk -F'|' '{print $3}' | sort -u +**Trello is the source of truth.** Build `known_applied` from card titles in the vacancy-bearing lists: + +``` +mcp__trello__set_active_board(boardId="6a1a9a5af082cb0526b22704") +mcp__trello__get_cards_by_list_id(listId="6a1aa59555aab72a261c42aa") # TODO +mcp__trello__get_cards_by_list_id(listId="6a1aa59a5e7e651b1352895b") # In Progress +mcp__trello__get_cards_by_list_id(listId="6a267e2e9ed02737346dc047") # In touch +mcp__trello__get_cards_by_list_id(listId="6a1aa5a1d8bcb0ed7234987b") # Applyed +mcp__trello__get_cards_by_list_id(listId="6a245a328452976c0d1fcca1") # Rejected ``` -Also call `mcp__trello__get_cards_by_list_id` for all BestJob board lists to extract card titles. Merge both into a `known_applied` list (company name → date/status where available). Pass this list to every Haiku subagent prompt (see template below). +From the results keep **only** each card's `name` (the "Company — Role" title); discard everything else. That titles-only list is `known_applied` — pass it into every Haiku subagent prompt (see template). Match new vacancies by company-name substring. (Rejected is included on purpose — a rejected company is still "already processed".) + +**Context safety (important).** This MCP has no full-text card search and no field-limited fetch — `get_cards_by_list_id` returns the full ~1.5 KB JSON per card. So: +- Fetch only the five vacancy lists above (not Base / Boards / Artifactes), and do it **once** per run. +- Distill to titles immediately; never feed full card JSON into a subagent. +- When the **Applyed** list grows large (hundreds of cards), use the lean equivalent instead — one Trello REST call returning names only: + ```bash + source .env && curl -s "https://api.trello.com/1/boards/6a1a9a5af082cb0526b22704/cards?fields=name,idList&filter=visible&key=$TRELLO_API_KEY&token=$TRELLO_TOKEN" \ + | jq -r '.[].name' + ``` + This returns every card name on the board in one compact payload — the direct successor to the old `applications.md` grep. + +`tracking/applications.md` is **frozen/legacy** — no longer read for dedup. ### Stratification rules @@ -247,7 +269,7 @@ Also call `mcp__trello__get_cards_by_list_id` for all BestJob board lists to ext - Subagent returns a structured verdict list (APPLY / SKIP / QUICK-APPLY / VERIFY). - SKIP verdicts from Haiku are accepted without re-review. 3. **Main session reviews only** APPLY and VERIFY verdicts from Haiku — runs full Step 1–8 per entry. -4. After all verdicts: promote confirmed APPLY entries to `tracking/applications.md`. +4. After all verdicts: promote confirmed APPLY entries to **Trello** (a card per application — see "After triage — update tracking"). Never write to `tracking/applications.md`. 5. For QUICK-APPLY entries: note explicitly, ask Oleg if he wants to proceed. 6. For VERIFY entries: run a fast WebSearch `"{company} remote hiring countries"` to resolve geo; then apply the gate. @@ -293,8 +315,19 @@ Vacancies: ## After triage — update tracking -For every APPLY verdict: -- Add a row to `tracking/applications.md` with status `todo` (not yet applied) or `applied` if Oleg confirms. -- Create a Trello card in the TODO column (`6a1aa59555aab72a261c42aa`) on board `6a1a9a5af082cb0526b22704` with: company, role, track, verdict summary, link to JD. +**A Trello card is the application record** (this replaces the old `applications.md` row — that file is frozen/legacy, do not write to it). For every APPLY verdict, create one card in the TODO column (`6a1aa59555aab72a261c42aa`) on board `6a1a9a5af082cb0526b22704`: -For SKIP: no tracking entry needed unless Oleg says to keep it for reference. +- **Title:** `Company — Role (Track X)` +- **Column = status.** The funnel is the columns: TODO (to apply) → In Progress (applying) → In touch (recruiter contact / screening) → Applyed (submitted); Rejected (closed). New cards land in TODO; Oleg moves them as stages change. +- **Description:** the triage verdict block, plus a `Tracking` footer carrying everything the old applications.md row held: + ``` + --- + **Tracking** + - Date added: + - Channel: + - CV used: + - JD: + - Status: + ``` + +For SKIP: no card needed unless Oleg says to keep it for reference. diff --git a/CLAUDE.md b/CLAUDE.md index a86bc2a..e122ed7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,16 +38,20 @@ mcp__trello__set_active_board(boardId="6a1a9a5af082cb0526b22704") Columns (left → right, with IDs for `add_card_to_list` / `move_card`): -| Order | Name | List ID | -|---|---|---| -| 1 | Base | `6a1aa5807487ac0da53f85e1` | -| 2 | TODO | `6a1aa59555aab72a261c42aa` | -| 3 | In Progress | `6a1aa59a5e7e651b1352895b` | -| 4 | Applyed | `6a1aa5a1d8bcb0ed7234987b` | -| 5 | Artifactes | `6a1aa5b12963a48bb0880528` | -| 6 | Boards | `6a1af7ec9bc4bc8df2ba93c3` | +| Order | Name | List ID | Role | +|---|---|---|---| +| 1 | Base | `6a1aa5807487ac0da53f85e1` | meta | +| 2 | TODO | `6a1aa59555aab72a261c42aa` | vacancy funnel — to apply | +| 3 | In Progress | `6a1aa59a5e7e651b1352895b` | vacancy funnel — applying | +| 4 | Applyed | `6a1aa5a1d8bcb0ed7234987b` | vacancy funnel — submitted | +| 5 | In touch | `6a267e2e9ed02737346dc047` | vacancy funnel — recruiter contact / screening | +| 6 | Rejected | `6a245a328452976c0d1fcca1` | vacancy funnel — closed (rejected / dead) | +| 7 | Boards | `6a1af7ec9bc4bc8df2ba93c3` | meta | +| 8 | Artifactes | `6a1aa5b12963a48bb0880528` | meta | -The list names "Applyed" and "Artifactes" are the actual spellings on the board — don't auto-correct them in API calls. +The list names "Applyed", "Artifactes", and "In touch" are the actual spellings/casing on the board — don't auto-correct them in API calls. + +**Vacancy-bearing lists** (where an application card can live, for dedup / prior-application checks): TODO, In Progress, In touch, Applyed, Rejected. Base / Boards / Artifactes are meta and hold no applications. --- @@ -132,7 +136,7 @@ Quick orientation: - **Output**: [`tracking/telegram_inbox.json`](tracking/telegram_inbox.json) — filtered messages, overwritten each run. - **Trigger**: manual only — run when Oleg explicitly asks (e.g. "забери свежее из Jobs"). No background polling. -After a run, triage `telegram_inbox.json` and promote promising postings to [`tracking/applications.md`](tracking/applications.md). For the triage itself, use the **[`triage-jobs` skill](.claude/skills/triage-jobs/SKILL.md)** — it stratifies by priority and delegates p2/p3 (the bulk) to a Haiku subagent so the main session stays lean. +After a run, triage `telegram_inbox.json` and promote promising postings to the **Trello BestJob board** (TODO column) — a card per application is the source of truth. For the triage itself, use the **[`triage-jobs` skill](.claude/skills/triage-jobs/SKILL.md)** — it stratifies by priority and delegates p2/p3 (the bulk) to a Haiku subagent so the main session stays lean. (`tracking/applications.md` is frozen/legacy — kept for backward compatibility, no longer written.) --- @@ -204,7 +208,7 @@ tailored/ cv.pdf # final PDF notes.md # job posting, contact, decisions log tracking/ - applications.md # one row per application + applications.md # frozen/legacy log — Trello (BestJob board) is the source of truth now outreach.md # cold outreach + recruiter conversations scripts/ generate-pdf.mjs # HTML -> PDF (puppeteer) @@ -255,15 +259,16 @@ Steps: pnpm pdf tailored//cv.html tailored/ ``` That writes `tailored//cv.pdf`. -7. Add a row to `tracking/applications.md`. +7. Create a Trello card for the application on the BestJob board (TODO column) — see the `triage-jobs` skill ("After triage — update tracking") for the card schema. (`tracking/applications.md` is frozen/legacy; don't write to it.) --- ## Workflow 3 — Tracking -- **`tracking/applications.md`**: one row per application. Status column drives the funnel (applied, screen, interview, offer, rejected, withdrawn). Always store absolute dates (e.g. `2026-05-24`). +- **Trello BestJob board = source of truth for applications.** One card per application. The funnel is the columns (TODO → In Progress → In touch → Applyed; Rejected for closed); moving a card between columns is how status changes. New applications land in TODO. See the `triage-jobs` skill ("After triage — update tracking") for the canonical card schema (title `Company — Role (Track X)` + a `Tracking` footer with date, channel, CV used, JD link, status). Always store absolute dates (e.g. `2026-05-24`). +- **`tracking/applications.md`**: **frozen/legacy** — historical log only, kept for backward compatibility. Do not read it for dedup or write new rows to it; use Trello instead. - **`tracking/outreach.md`**: log cold messages, recruiter pings, and follow-ups. One row per touchpoint; group by company. -- When asked to "log this application" or similar, append to the right file — never rewrite existing rows unless explicitly asked. +- When asked to "log this application" or similar → create/update the Trello card. Never write to `applications.md`. --- diff --git a/tracking/CLAUDE.md b/tracking/CLAUDE.md index 618c778..4ef13b3 100644 --- a/tracking/CLAUDE.md +++ b/tracking/CLAUDE.md @@ -14,7 +14,7 @@ If you (Claude) are about to do anything related to "find vacancies in Telegram" | `telegram_state.json` | Per-machine cursor — `last_message_id` and `last_seen_date` per channel. Regenerated automatically. | ❌ gitignored | | `telegram_inbox.json` | Output of the last fetch run — kept messages only, per channel, with `lang`/`priority` injected. Overwritten each run. | ❌ gitignored | | `telegram_pending_channels.json` | Generated only when the last run had **new** (untriaged) channels — keyword-frequency scan to bootstrap their curation. Deleted on the next run if no pending. | ❌ gitignored | -| `applications.md` | One row per application — manually maintained, append-only. | ✅ committed | +| `applications.md` | **Frozen/legacy** — historical application log. Superseded by Trello (BestJob board) as the source of truth. Kept for backward compatibility; no longer read or written. | ✅ committed (frozen) | | `outreach.md` | Cold messages, recruiter pings, follow-ups. One row per touchpoint. | ✅ committed | --- @@ -222,7 +222,7 @@ jq -r '.channels | to_entries | map(select(.value.truncated)) ## After triage -Promising postings → append a row to `applications.md`. Don't accumulate a "seen but skipped" log — the state cursor already prevents re-reading. +Promising postings → **create a Trello card** on the BestJob board (TODO column). The card is the application record — see the `triage-jobs` skill ("After triage — update tracking") for the card schema. Trello is the source of truth for applications; `applications.md` is frozen/legacy and is neither read nor written. Don't accumulate a "seen but skipped" log — the state cursor already prevents re-reading. For outreach (cold DMs, recruiter conversations) → `outreach.md`, one row per touchpoint.