cv-2026/.claude/skills/triage-jobs/SKILL.md

276 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: triage-jobs
description: Triage one or more job vacancies using Oleg's canonical apply/skip playbook (vacancy-filter-and-triage-2026.md). Applies 4 hard gates, classifies the CV track, runs the research protocol, checks for prior applications, and outputs a consolidated verdict. For batch runs from telegram_inbox.json, stratifies by priority and delegates p2/p3 bulk to a Haiku subagent to protect the main session.
---
# triage-jobs
Operational implementation of `base/reference/vacancy-filter-and-triage-2026.md`. That file is the authoritative playbook — read it before running this skill if you don't have it in context.
Posture: **trying-friendly, not filtering-friendly.** Hard skip is rare and requires a concrete objective blocker. On every ambiguous case, default to "подаём".
---
## When to use
- Oleg provides a job posting URL, raw JD text, or says "разбери вакансию".
- After running `scripts/fetch_telegram_jobs.py` — triage `tracking/telegram_inbox.json`.
- Any "should we apply?" question about a specific role.
---
## Input modes
| Mode | What Oleg provides |
|---|---|
| **Single URL** | One job posting link — fetch, triage, output verdict |
| **Raw JD** | Pasted text — triage directly |
| **Batch (inbox)** | No specific job — triage all entries in `tracking/telegram_inbox.json` |
---
## Step 0 — Read the playbook (if needed)
If `vacancy-filter-and-triage-2026.md` is not already in context:
```
Read: base/reference/vacancy-filter-and-triage-2026.md
```
---
## Step 1 — Fetch the JD
For URL input:
1. Try `WebFetch` first.
2. If blocked (403, bot wall, login wall, JS-only, empty body) → switch to `chrome-session` skill immediately, no confirmation needed.
3. If neither works → halt and report. **Never reconstruct a JD from memory.**
For Greenhouse / Lever / Ashby / Freshteam ATS: SSR usually works; confirm the "Apply" button is active (not a JS overlay saying "not accepting applications").
---
## Step 2 — Extract fast facts (< 1 min)
Pull from the JD:
- Role title and seniority signals
- Must-have stack (vs. nice-to-have)
- AI involvement: **must-have** / nice-to-have / not mentioned
- Location & remote policy
- Timezone / overlap requirements (explicit or inferable from location)
- Compensation signals (range, equity framing, "scrappy" language, funding stage)
---
## Step 3 — Run 4 hard gates
Evaluate gates in order. First failure → `SKIP` with one objective reason. All four pass → continue.
### Gate 1 — Geography / hiring
Passes if the role can hire Oleg via **any** of:
- Global remote (non-US/UK/EU-restricted)
- Contractor via Deel or equivalent EOR covering Thailand
- B2B contract for remote work
- Russian-speaking team / Russian-speaking founders, hiring remotely (excluding RU/BY companies explicitly requiring presence)
- Russian companies hiring remotely (presence in RU not required)
- Relocation offered **AND** comp ≥ $10k/month
- Temporary contract fully geography-agnostic (Mira, Algery, similar aggregators)
Skip if: location-locked / US-only / UK-only / EOR doesn't cover Thailand and no contractor option.
### Gate 2 — Timezone (comp-scaled, not binary)
Oleg's flexible window: **9:0022:00 GMT+7**. Comfortable day: 11:0020:00.
| Required overlap | Pass condition |
|---|---|
| Fits within 9:0022:00 GMT+7 | Passes at any comp ≥ floor |
| Partially outside the window | Passes if comp > $9k |
| Full US-day / PST core hours / night work | Passes if comp > $10k |
Skip only if: comp ≤ $9k **AND** required overlap falls outside 9:0022:00 GMT+7.
### Gate 3 — Compensation
| Tier | Range | Treatment |
|---|---|---|
| Target | $812k/month | Main funnel |
| Floor | $68k/month | Normal lower bound |
| Fallback | $4.56k/month | Temporary bridge only — штучно и осознанно |
| Skip | < $4.5k/month | Hard skip |
No explicit comp? Read signals: pre-seed + equity-heavy framing + "scrappy team" → likely below floor. Founding-engineer at Series AB AI startup can stretch to $15k+ if profile matches.
### Gate 4 — Seniority
Passes for: Senior / Staff / Tech Lead / experienced middle+.
- **Skip** if: explicitly Junior or mid with no growth ceiling.
- **Do NOT skip** if: role title is Lead / Principal / Head of — treat as "they don't have that person internally, try it."
- **Do NOT skip** if: role looks like middle but comp fits floor/target AND the role offers interesting new experience (AI, client-facing, English immersion).
---
## Step 4 — Anti-pattern self-check
Before marking skip, run through the false-blocker list. If you're about to skip on any of these, escalate to the next tier instead:
1. Role looks senior-heavy (Lead/Principal/Head) → that's a try signal.
2. One missing skill → ask Oleg first (see Step 6), not skip.
3. "Not an AI-first company" → Track B or Hybrid, not skip.
4. Superficial domain mismatch → look at actual technical tasks (orchestration, LLM workflows, structured extraction).
5. "Not a Russian-speaking scale-up" → neutral, not negative.
6. Timeline outside 8-week window → affects sequencing, not eligibility.
7. Comp below $8k but in floor/fallback → consider, especially strategic or interesting roles.
8. Tech stack mismatch with fast ramp → lean toward apply, mention ramp honestly.
9. Doesn't fully pass triage but ≥50% match + low application effort (LinkedIn Easy Apply, simple form, DM) → **quick-apply** mode: note it explicitly as "fast/training apply."
---
## Step 5 — Research protocol
Run for all roles that cleared the gates (and for borderline cases to resolve ambiguity).
### 5.0 — Check for prior application
Before deep research, check whether Oleg already applied to this role or company:
- **Trello** (`mcp__trello__set_active_board` → board `6a1a9a5af082cb0526b22704`, then search cards or scan the "Applyed" list).
- **`tracking/applications.md`** — grep for company name.
- **Telegram** — search in job-tracking chats if applicable.
- **Gmail** — search for company name if accessible.
If already applied → note it in the output, don't re-triage as new.
### 5.1 — Research the company
What the company does, product, stage, funding, team size, recent news, reputation (Glassdoor / Blind if available). Goal: context + ghost/red-flag filter.
### 5.2 — Cross-platform posting check
Find the same vacancy on: company careers page, LinkedIn, ATS link (Greenhouse/Lever/Ashby/etc.), job boards, aggregators. Consolidate:
- **Posting date** — earliest appearance. 90+ days without update = ghost signal.
- **Comp range** — different platforms often show different bands. Collect all.
- **Geo restrictions** — any platform saying US Only / UK Only / location-locked / eligible countries list?
### 5.3 — Restriction priority rule
**Restrictions are authoritative.** If one source says "remote" and another says "US only" → US only wins → Gate 1 skip. Less restrictive wording wins **only** if it explicitly and clearly overrides/removes the restriction.
---
## Step 6 — Missing skills
One missing skill is **not** a skip if it isn't flagged as explicit MUST HAVE.
Action: **ask Oleg before applying** — "JD asks for X, I don't see it in your materials — did you have any experience with it?" Many skills exist but were trimmed from CV (examples: Redux Toolkit/RTK Query, Vitest, Playwright, Jest, eCommerce/CMS work).
Real gaps — can name without checking: Go, Rust, Java, C++, Ruby, PHP, heavy DevOps (K8s orchestration at scale, SRE), native mobile (Swift, Kotlin). React Native and Python are bridgeable, not gaps.
**Never flag a gap explicitly in a cover letter** — don't write "one thing to flag" or "I notice a gap here."
---
## Step 7 — Classify track (for roles that cleared gates)
| JD condition | Track | CV file |
|---|---|---|
| AI in **must-have**: LLM / agents / MCP / RAG / orchestration / embeddings in core requirements | **Track A** | `base/cv-2026-05-base.md` |
| Pure Node.js / backend, AI as nice-to-have or "significant plus" | **Backend-first** | `base/cv-backend-variant-hostinger-2026-05.md` |
| Senior / full-stack / frontend, no AI in must-have | **Track B** | `base/oleg_proskurin_fullstack_techlead_cv.md` |
| Senior + AI-tooling fluency as requirement (build with AI assistance, not AI product) | **Hybrid** | CV-B with AI moved up 23 positions in Skills |
Russian-speaking scale-ups (Manychat, inDrive, Wheely, Joom, Adapty, similar) → **Track B by default**, even if AI not mentioned.
Tiebreakers:
- Track B vs. skip → Track B wins.
- Track A vs. Track B for hybrid JD → AI in must-have → A; otherwise → B.
---
## Step 8 — Output format
One consolidated block per vacancy. No separate research section — merge everything.
```
## [Company] — [Role Title]
**Verdict:** APPLY (Track A) | SKIP | QUICK-APPLY
**Gate check:**
- Gate 1 (Geo): ✅ global remote / ❌ US-only
- Gate 2 (TZ): ✅ EMEA overlap fits / ⚠️ partial, comp > $9k ok / ❌
- Gate 3 (Comp): ✅ $XYk (target) / ⚠️ floor / ❌
- Gate 4 (Level): ✅ Senior / ❌ Junior
**Track:** A / B / Backend-first / Hybrid — CV: [filename]
**Strong matches:** [24 bullets: specific tech/scope from JD that map directly to Oleg's background]
**Open questions:** [missing skills to ask Oleg about; 12 items max]
**Research notes:**
- Company: [stage, product, funding, red flags if any]
- Posting date: [earliest found] — [fresh / stale signal]
- Comp across platforms: [consolidate bands found]
- Geo/restrictions: [what each platform says; which is authoritative]
**Prior application:** none found / ⚠️ already applied on [date], see Trello card [name]
**Proof-points for letter:** [23 concrete bullets that directly answer the JD's key asks]
```
For SKIP: one-liner after gate check explaining the objective blocker. No research section needed unless it was needed to determine the gate outcome.
---
## Batch mode — stratified triage from telegram_inbox.json
When triaging `tracking/telegram_inbox.json`:
1. Read the file. Group entries by channel `priority` field (`p1` / `p2` / `p3`).
2. **p1 entries**: triage in the main session (full Step 18 per entry).
3. **p2 and p3 entries**: delegate to a Haiku subagent to protect main context.
- Pass the raw entries and the playbook summary to the subagent.
- Subagent returns a structured verdict list.
- Review, escalate any surprising p2/p3 passes to main session for full triage.
4. After all verdicts: promote APPLY entries to `tracking/applications.md`.
5. For QUICK-APPLY entries: note explicitly, ask Oleg if he wants to proceed.
### Haiku subagent prompt template
```
You are triaging job vacancies for Oleg Proskurin (Tech Lead / AI Engineer, based in Thailand, available for remote work).
Apply these 4 hard gates — SKIP on first failure:
Gate 1 (Geo): Must allow: global remote non-US/UK/EU, contractor via Deel/EOR from Thailand, B2B remote, Russian-speaking teams hiring remotely (not RU/BY presence-required), relocation with comp ≥$10k, geography-agnostic temp contracts.
Gate 2 (TZ): Oleg's window 9:0022:00 GMT+7. Outside window: ok if comp > $9k. Night/PST core: ok if comp > $10k. Skip only if comp ≤ $9k AND overlap is outside window.
Gate 3 (Comp): Skip if < $4.5k/month. Floor $68k, target $812k.
Gate 4 (Level): Skip if explicitly Junior or mid with no growth ceiling.
Posture: trying-friendly. On ambiguous cases, lean toward APPLY.
For each vacancy below, output:
- APPLY, SKIP, or QUICK-APPLY (≥50% match + easy application)
- Gate that failed (for SKIP)
- Probable track: A (AI must-have), B (full-stack/frontend), Backend-first, Hybrid
- 1-line reason
Vacancies:
[paste entries from telegram_inbox.json]
```
---
## 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.
For SKIP: no tracking entry needed unless Oleg says to keep it for reference.