252 lines
9.4 KiB
Markdown
252 lines
9.4 KiB
Markdown
---
|
||
name: get-tg-jobs
|
||
description: Full autonomous end-to-end job pipeline. Fetches fresh vacancies from Oleg's Telegram "Jobs" folder, handles new/pending channels, runs the full triage cycle (triage-jobs), pushes APPLY verdicts to Trello, then reports results in the chat session AND sends a Telegram notification to Oleg via telegram-helper. Trigger on "забери из Jobs", "что нового в каналах", "запусти pipeline", or similar.
|
||
---
|
||
|
||
# get-tg-jobs
|
||
|
||
Autonomous end-to-end pipeline: fetch → curate new channels → triage → Trello → report. Does everything without stopping for confirmation. Only halts if a hard error occurs (auth failure, script crash, etc.).
|
||
|
||
**Trigger only when Oleg explicitly asks** — e.g. "забери свежее из Jobs", "что нового в каналах", "запусти pipeline". No background polling.
|
||
|
||
---
|
||
|
||
## Notification targets
|
||
|
||
All pipeline reports go to the **"New cool job"** Telegram group. The `telegram-helper` account (samuishechka) is a member of that group and sends messages there.
|
||
|
||
| Target | chat_id | When |
|
||
|---|---|---|
|
||
| "New cool job" group | `-4783500394` | All reports — success and errors |
|
||
|
||
Tool to use: `mcp__telegram-helper__send_message(chat_id=-4783500394, message="...", parse_mode="html")`
|
||
|
||
This section is the canonical reference for notification targets. Update here if the group changes.
|
||
|
||
---
|
||
|
||
## Step 1 — Run the pipeline
|
||
|
||
```bash
|
||
~/.local/bin/uv run scripts/list_telegram_channels.py \
|
||
| ~/.local/bin/uv run scripts/fetch_telegram_jobs.py -
|
||
```
|
||
|
||
Run from the project root. The script prints a per-channel summary to stdout — echo it to the session so Oleg can see raw progress.
|
||
|
||
**If the script fails:**
|
||
- `TELEGRAM_SESSION_STRING not set` or auth error → `.env` is missing or the session is expired. Regenerate with `scripts/regen_telegram_session.sh` and tell Oleg.
|
||
- `TELEGRAM_API_ID / TELEGRAM_API_HASH not set` → same `.env` issue.
|
||
- `Could not find folder "Jobs"` → the folder was renamed or the wrong session is in `.env`. Must be the **usulsu** session, not samuishechka.
|
||
- Any other exception → paste the error and stop. Don't retry blindly.
|
||
|
||
---
|
||
|
||
## Step 2 — Check for pending (new) channels
|
||
|
||
```bash
|
||
test -f tracking/telegram_pending_channels.json && echo PENDING || echo OK
|
||
```
|
||
|
||
**If OK**: skip to Step 3.
|
||
|
||
**If PENDING**: curate each new channel using the procedure below, then rerun Step 1.
|
||
|
||
---
|
||
|
||
### New-channel curation procedure
|
||
|
||
For each channel in `telegram_pending_channels.json`:
|
||
|
||
#### 2a — Read keyword frequency scan
|
||
|
||
```bash
|
||
jq -r 'to_entries[] | "\n=== \(.key) ===\nmessages_scanned: \(.value.messages_scanned)\ntruncated: \(.value.truncated)\ntop keywords:\n\(.value.keyword_counts_from_other_channels | to_entries | sort_by(-.value) | .[:20] | .[] | " \(.key): \(.value)")"' \
|
||
tracking/telegram_pending_channels.json
|
||
```
|
||
|
||
#### 2b — Sample messages
|
||
|
||
```bash
|
||
jq -r '.channels["<channel>"].messages[:6] | .[] | "── \(.date[0:16])\n\(.text[0:400])\n"' \
|
||
tracking/telegram_inbox.json
|
||
```
|
||
|
||
Look for: hashtag patterns, language, post structure (single role / digest / chat), recurring noise.
|
||
|
||
#### 2c — Decide lang, priority, filter shape
|
||
|
||
**Priority:**
|
||
- `p1` — strong stack hits (JS/TS/React/Node/AI/LLM) AND global-remote culture
|
||
- `p2` — stack OK but CIS/RUB market, or occasional gems; recruiter/market-intel content
|
||
- `p3` — wrong stack, off-market, noise, dead channels
|
||
|
||
Base priority on the **best** vacancy in the sample, not the average.
|
||
|
||
**Filter shape:**
|
||
|
||
| Channel pattern | Filter |
|
||
|---|---|
|
||
| Consistent `#vacancy` + `#remote` hashtags | AND-of-OR hashtag filter |
|
||
| Vacancy text without consistent hashtags | Positive stack include + Oleg-stack excludes |
|
||
| Low-volume personal/curated digest | Trust-all (no `include`/`exclude`) |
|
||
| Mixes resumes and vacancies | Trust-all |
|
||
| Mostly noise but worth keeping | Strict positive filter |
|
||
|
||
Standard Oleg-stack excludes: `["kafka", "golang", "kotlin", "android", "swift"]`
|
||
|
||
For `*_jobs` channels add resume excludes: `["#резюме", "#resume", "#cv", "#ищуработу"]`
|
||
|
||
Positive stack include: `["javascript", "typescript", " react", "node.js", "nodejs", "fullstack", "full-stack", "tech lead", "techlead", "ai engineer", " llm"]`
|
||
|
||
#### 2d — Add entry to telegram_channels.json
|
||
|
||
Insert in correct priority block (p1 → p2 → p3, alphabetically within each group):
|
||
|
||
```jsonc
|
||
"<channel_id>": {
|
||
"lang": "ru" | "en" | "mixed",
|
||
"priority": "p1" | "p2" | "p3",
|
||
"include": [["kw1","kw2"], ["kw3"]], // optional
|
||
"exclude": ["kw4", "kw5"] // optional
|
||
}
|
||
```
|
||
|
||
#### 2e — Rerun and confirm clean
|
||
|
||
```bash
|
||
~/.local/bin/uv run scripts/list_telegram_channels.py \
|
||
| ~/.local/bin/uv run scripts/fetch_telegram_jobs.py -
|
||
|
||
test -f tracking/telegram_pending_channels.json && echo "STILL PENDING" || echo "Clean"
|
||
```
|
||
|
||
#### 2f — Validate the filter
|
||
|
||
```bash
|
||
jq -r '.channels["<channel>"] | "kept \(.kept)/\(.seen)" + (.messages | map("\n── \(.date[0:16])\n\(.text[0:300])") | join(""))' \
|
||
tracking/telegram_inbox.json
|
||
```
|
||
|
||
If `kept == 0` and a filter is set — verify the filter isn't too strict before accepting zero as correct.
|
||
|
||
---
|
||
|
||
## Step 3 — Run full triage
|
||
|
||
Follow the complete `triage-jobs` skill procedure on `tracking/telegram_inbox.json`.
|
||
|
||
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
|
||
```
|
||
Also fetch Trello card titles from all BestJob board lists. Pass the merged list into every Haiku subagent prompt.
|
||
|
||
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
|
||
|
||
5. **QUICK-APPLY verdicts**: note them explicitly in the session report; do not auto-add to Trello. Ask Oleg if he wants to proceed.
|
||
|
||
Full triage playbook: `base/reference/vacancy-filter-and-triage-2026.md`. Full batch instructions: `.claude/skills/triage-jobs/SKILL.md`.
|
||
|
||
---
|
||
|
||
## Step 4 — Report in session
|
||
|
||
After triage is complete, output a consolidated summary to the chat:
|
||
|
||
```
|
||
Pipeline done — <date>
|
||
|
||
Fetch: N messages from X channels (Y with results)
|
||
[⚠️ Truncated: channel_name (kept K/500, p2/ru)]
|
||
|
||
Triage results:
|
||
✅ APPLY: N roles → added to Trello
|
||
🔍 VERIFY: N roles → resolved / still open
|
||
⚡ QUICK-APPLY: N roles (ask Oleg before adding)
|
||
❌ SKIP: N roles
|
||
|
||
APPLY roles:
|
||
- Company A — Role Title (Track A) → [Trello card]
|
||
- Company B — Role Title (Track B) → [Trello card]
|
||
|
||
New channels curated: N [or: none]
|
||
```
|
||
|
||
---
|
||
|
||
## Step 5 — Send Telegram notification
|
||
|
||
After the session report, send a summary to the **"New cool job"** group via telegram-helper.
|
||
|
||
### Success message format
|
||
|
||
```
|
||
mcp__telegram-helper__send_message(
|
||
chat_id=-4783500394,
|
||
parse_mode="html",
|
||
message="""<b>Jobs pipeline done</b> · 2026-06-07
|
||
|
||
✅ APPLY: N роли → Trello
|
||
🔍 VERIFY: N (нужен ресёрч)
|
||
⚡ Quick-apply: N (нужно ок)
|
||
❌ SKIP: N
|
||
📥 Всего: N сообщений из X каналов
|
||
|
||
<b>APPLY:</b>
|
||
– <a href="https://trello.com/c/...">Company A — Role (Track A)</a>
|
||
– <a href="https://trello.com/c/...">Company B — Role (Track B)</a>"""
|
||
)
|
||
```
|
||
|
||
Rules:
|
||
- Always include Trello links for APPLY roles — это главная ценность уведомления.
|
||
- If QUICK-APPLY roles exist, list them with direct JD links (not Trello — для быстрого решения):
|
||
```
|
||
⚡ Quick-apply (нужно ок):
|
||
– Company X — Role → wantapply.com/...
|
||
– Company Y — Role → linkedin.com/jobs/...
|
||
```
|
||
- Keep VERIFY as a count only (no list) — they need more research, not immediate action.
|
||
- If zero APPLY and zero QUICK-APPLY: still send the message — "всё просмотрено, ничего релевантного в этот раз".
|
||
|
||
### Error message format
|
||
|
||
If the pipeline failed at any step and cannot complete — send a short error notification to the **same group**:
|
||
|
||
```
|
||
mcp__telegram-helper__send_message(
|
||
chat_id=-4783500394,
|
||
parse_mode="html",
|
||
message="""<b>⚠️ Pipeline error</b> · 2026-06-07
|
||
|
||
Упало на шаге: <step name>
|
||
Причина: <one-line error summary>
|
||
|
||
Что сделано до ошибки: <brief — e.g. "fetch OK, 12 msgs, triage не запустился">
|
||
Что нужно: <action — e.g. "обнови TELEGRAM_SESSION_STRING в .env">"""
|
||
)
|
||
```
|
||
|
||
Send the error notification **even if only partial work was done**. Better to have an incomplete notification than silence when something breaks.
|
||
|
||
---
|
||
|
||
## Sanity notes
|
||
|
||
- `telegram_state.json` is not in git — per-machine cursor. If lost, next run fetches 30 days back per channel (slow but correct).
|
||
- To reset a single channel's cursor for filter re-validation:
|
||
```bash
|
||
jq 'del(.["<channel>"])' tracking/telegram_state.json > /tmp/s.json && mv /tmp/s.json tracking/telegram_state.json
|
||
```
|
||
- `telegram_inbox.json` is overwritten every run — it's the current snapshot only.
|
||
- The pipeline reads the live "Jobs" folder — new channels Oleg added in Telegram are automatically included in the next run.
|