300 lines
14 KiB
Markdown
300 lines
14 KiB
Markdown
---
|
||
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:00–22:00 GMT+7**. Comfortable day: 11:00–20:00.
|
||
|
||
| Required overlap | Pass condition |
|
||
|---|---|
|
||
| Fits within 9:00–22: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:00–22:00 GMT+7.
|
||
|
||
### Gate 3 — Compensation
|
||
|
||
| Tier | Range | Treatment |
|
||
|---|---|---|
|
||
| Target | $8–12k/month | Main funnel |
|
||
| Floor | $6–8k/month | Normal lower bound |
|
||
| Fallback | $4.5–6k/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 A–B 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 2–3 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): ✅ $X–Yk (target) / ⚠️ floor / ❌
|
||
- Gate 4 (Level): ✅ Senior / ❌ Junior
|
||
|
||
**Track:** A / B / Backend-first / Hybrid — CV: [filename]
|
||
|
||
**Strong matches:** [2–4 bullets: specific tech/scope from JD that map directly to Oleg's background]
|
||
|
||
**Open questions:** [missing skills to ask Oleg about; 1–2 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:** [2–3 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`:
|
||
|
||
### 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
|
||
```
|
||
|
||
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).
|
||
|
||
### Stratification rules
|
||
|
||
1. Read the file. Group entries by channel `priority` field (`p1` / `p2` / `p3`).
|
||
2. **p1 entries — ≤ 15 messages**: triage fully in the main session (full Step 1–8 per entry).
|
||
3. **p1 entries — > 15 messages**: Haiku first pass (same prompt as p2/p3). Main session then reviews only APPLY and VERIFY verdicts; SKIP verdicts from Haiku are accepted without re-review.
|
||
4. **p2 and p3 entries**: delegate to a Haiku subagent to protect main context.
|
||
- Pass the raw entries, the playbook summary, and the `known_applied` list to the subagent.
|
||
- Subagent returns a structured verdict list.
|
||
- Review, escalate any APPLY and VERIFY passes to main session for full triage.
|
||
5. After all verdicts: promote confirmed APPLY entries to `tracking/applications.md`.
|
||
6. For QUICK-APPLY entries: note explicitly, ask Oleg if he wants to proceed.
|
||
7. For VERIFY entries: run a fast WebSearch `"{company} remote hiring countries"` to resolve geo; then apply the gate.
|
||
|
||
### Haiku subagent prompt template
|
||
|
||
```
|
||
You are triaging job vacancies for Oleg Proskurin (Tech Lead / AI Engineer, based in Thailand GMT+7, 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:00–22: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 $6–8k, target $8–12k.
|
||
Gate 4 (Level): Skip if explicitly Junior or mid with no growth ceiling.
|
||
|
||
Posture: trying-friendly when data IS PRESENT and borderline. When key gate data is ABSENT from the message text, return VERIFY — not APPLY. Lean toward APPLY only when geo and comp are explicitly stated and borderline (e.g. "global remote", "$7k/month").
|
||
|
||
Geo rules (Gate 1):
|
||
- Message explicitly says "global remote" / "worldwide" / "anywhere" / "любой город" / contractor-friendly → Gate 1 passes, proceed.
|
||
- Message says "United States" / "US only" / "United Kingdom only" / specific country list excluding Thailand → SKIP Gate 1.
|
||
- Message says "Remote" with no geo qualifier → VERIFY geo (cannot confirm Thailand eligibility without JD).
|
||
- Message has no location info at all → VERIFY geo.
|
||
|
||
Comp rules (Gate 3):
|
||
- Explicit salary ≥ $4.5k/month or ≥ $54k/year → Gate 3 passes, proceed.
|
||
- Explicit salary < $4.5k/month → SKIP Gate 3.
|
||
- No salary mentioned → VERIFY comp.
|
||
- Timezone offset explicitly stated (e.g. GMT-GMT+6) → treat as geo restriction, apply Gate 1.
|
||
|
||
Known applied companies — flag these as SKIP (already applied):
|
||
[INSERT known_applied LIST HERE — one line per company]
|
||
|
||
For each vacancy below, output one line:
|
||
APPLY | SKIP | QUICK-APPLY | VERIFY — [company/role] — [gate failed or what's missing] — [track: A/B/Backend-first/Hybrid]
|
||
|
||
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.
|