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) <noreply@anthropic.com>
This commit is contained in:
parent
325ff334bb
commit
731cb5d831
|
|
@ -138,19 +138,22 @@ Follow the complete `triage-jobs` skill procedure on `tracking/telegram_inbox.js
|
||||||
|
|
||||||
Key points from that skill:
|
Key points from that skill:
|
||||||
|
|
||||||
1. **Pre-step**: build `known_applied` list before spawning Haiku:
|
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**:
|
||||||
```bash
|
|
||||||
grep -E '^\|' tracking/applications.md | tail -n +2 | awk -F'|' '{print $3}' | sort -u
|
|
||||||
```
|
```
|
||||||
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.
|
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.
|
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 —
|
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).
|
||||||
- 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
|
|
||||||
|
|
||||||
5. **QUICK-APPLY verdicts**: note them explicitly in the session report; do not auto-add to Trello. Ask Oleg if he wants to proceed.
|
5. **QUICK-APPLY verdicts**: note them explicitly in the session report; do not auto-add to Trello. Ask Oleg if he wants to proceed.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
### 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).
|
- **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:
|
||||||
- **`tracking/applications.md`** — grep for company name.
|
- 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.
|
- **Telegram** — search in job-tracking chats if applicable.
|
||||||
- **Gmail** — search for company name if accessible.
|
- **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.
|
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)
|
### Pre-step: build prior-applications list (do this once before spawning any subagent)
|
||||||
|
|
||||||
```bash
|
**Trello is the source of truth.** Build `known_applied` from card titles in the vacancy-bearing lists:
|
||||||
grep -E '^\|' tracking/applications.md | tail -n +2 | awk -F'|' '{print $3}' | sort -u
|
|
||||||
|
```
|
||||||
|
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
|
### 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).
|
- Subagent returns a structured verdict list (APPLY / SKIP / QUICK-APPLY / VERIFY).
|
||||||
- SKIP verdicts from Haiku are accepted without re-review.
|
- 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.
|
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.
|
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.
|
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
|
## After triage — update tracking
|
||||||
|
|
||||||
For every APPLY verdict:
|
**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`:
|
||||||
- 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.
|
|
||||||
|
|
||||||
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: <YYYY-MM-DD>
|
||||||
|
- Channel: <e.g. TG @serbia_jobs · direct (Ashby) · LinkedIn>
|
||||||
|
- CV used: <track> — <path to pdf>
|
||||||
|
- JD: <url>
|
||||||
|
- Status: <todo | applied YYYY-MM-DD via …>
|
||||||
|
```
|
||||||
|
|
||||||
|
For SKIP: no card needed unless Oleg says to keep it for reference.
|
||||||
|
|
|
||||||
33
CLAUDE.md
33
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`):
|
Columns (left → right, with IDs for `add_card_to_list` / `move_card`):
|
||||||
|
|
||||||
| Order | Name | List ID |
|
| Order | Name | List ID | Role |
|
||||||
|---|---|---|
|
|---|---|---|---|
|
||||||
| 1 | Base | `6a1aa5807487ac0da53f85e1` |
|
| 1 | Base | `6a1aa5807487ac0da53f85e1` | meta |
|
||||||
| 2 | TODO | `6a1aa59555aab72a261c42aa` |
|
| 2 | TODO | `6a1aa59555aab72a261c42aa` | vacancy funnel — to apply |
|
||||||
| 3 | In Progress | `6a1aa59a5e7e651b1352895b` |
|
| 3 | In Progress | `6a1aa59a5e7e651b1352895b` | vacancy funnel — applying |
|
||||||
| 4 | Applyed | `6a1aa5a1d8bcb0ed7234987b` |
|
| 4 | Applyed | `6a1aa5a1d8bcb0ed7234987b` | vacancy funnel — submitted |
|
||||||
| 5 | Artifactes | `6a1aa5b12963a48bb0880528` |
|
| 5 | In touch | `6a267e2e9ed02737346dc047` | vacancy funnel — recruiter contact / screening |
|
||||||
| 6 | Boards | `6a1af7ec9bc4bc8df2ba93c3` |
|
| 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.
|
- **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.
|
- **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
|
cv.pdf # final PDF
|
||||||
notes.md # job posting, contact, decisions log
|
notes.md # job posting, contact, decisions log
|
||||||
tracking/
|
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
|
outreach.md # cold outreach + recruiter conversations
|
||||||
scripts/
|
scripts/
|
||||||
generate-pdf.mjs # HTML -> PDF (puppeteer)
|
generate-pdf.mjs # HTML -> PDF (puppeteer)
|
||||||
|
|
@ -255,15 +259,16 @@ Steps:
|
||||||
pnpm pdf tailored/<company-slug>/cv.html tailored/<company-slug>
|
pnpm pdf tailored/<company-slug>/cv.html tailored/<company-slug>
|
||||||
```
|
```
|
||||||
That writes `tailored/<company-slug>/cv.pdf`.
|
That writes `tailored/<company-slug>/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
|
## 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.
|
- **`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`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_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_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 |
|
| `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 |
|
| `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
|
## 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.
|
For outreach (cold DMs, recruiter conversations) → `outreach.md`, one row per touchpoint.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue