Releases: Da6ka/tech-sourcing-skill
Release list
v2.3.0 — the user picks who outreach is written for
Phase 1a of DESIGN-checkpoints.md. New behavior, backwards-compatible: the default is unchanged, so existing runs behave as before unless you say otherwise.
What changed
Module 4 used to hardcode its target — outreach went to "the single highest-confidence profile", and you could only redirect it after three variants for the wrong person had been written. The waste wasn't really tokens; outreach for a candidate you didn't want is worth nothing.
You now pick at Checkpoint 2, before Module 4 runs:
Continue to the scorecard and outreach — continuing, I'll write outreach for #1 (Marina B.); name other rows if you'd rather, up to three
Name a row number, a name, or paste a profile. Say nothing and the top-confidence profile is still used — stated in one line, then the run continues.
Not a new checkpoint
The design doc proposed a dedicated "who should I write to?" pause. That wasn't built. SKILL.md already runs Modules 3 and 4 together with no checkpoint between them because both are cheap, and a new pause would have contradicted that for no saving.
Checkpoint 2 already stops the run, and you're already looking at the profile table — numbered, confidence-rated, with a rationale per row. That's the same information a dedicated pause would have shown, so the invitation costs one clause instead of a turn, and no new rule competes for the model's attention. The doc records the deviation.
Cap of three
Three candidates is nine messages, already more than anyone reads carefully. Name more and the three highest-confidence win, with the omission stated.
Verified on a live conversational run
Five rows named — two High-confidence, three Medium:
- Wrote outreach for #3, #4, #5 — not the #1 default
- Took both High-confidence profiles plus the strongest Medium
- Named the two it left out, with reasons, and offered to write theirs on request
- Cited the cap unprompted: "I'll write full variants for three, per the skill's cap"
The hosted demo has no Checkpoint 2, so the harness note resolves the choice to its documented default rather than leaving room to ask a question nobody can answer.
Full changelog: v2.2.2...v2.3.0
v2.2.2 — a JD is source material, not a language signal
Corrects v2.2.1, which fixed the wrong half of the rule. If you are on v2.2.1, upgrade.
The bug is older than v2.2.1
"Output language" said: write in English by default, and match another language if either the user is clearly writing in one or the JD/briefing is in one.
Two different signals joined by an or — and the JD half let a piece of input data decide what language the user got spoken to in. Paste a Russian JD while writing in English, get a Russian report. The live run said so outright:
«Вакансия на русском языке, поэтому весь прогон веду по-русски.»
v2.2.1 made that branch work more reliably, which was the wrong direction.
The fix
The JD branch is gone. Only the user's own messages set the output language:
A JD, briefing, or profile is source material, not a language signal. Only the user's own messages decide the output language. A Russian JD pasted by someone who writes to you in English gets an English run: the posting is data to work from, not a sample of how they want to be spoken to. When a JD is the only input and there is no user message to judge — a hosted API call, for example — use the English default.
The Module 4 exception is unchanged: outreach still follows the candidate's likely language, with a one-line note when it differs. Its example was realigned — it described a Russian JD producing a Russian persona, which is what this release removes.
isCyrillicJd, added in v2.2.1, is removed: with the JD no longer a language signal there is nothing to detect, and the demo's turn-cap note is unconditionally English.
Anglicism rule
The banned list is unchanged («наблюдение», not «финдинг»). What is new is an explicit carve-out for established IT and recruiting usage — «кандидат», «гипотеза», «воронка», «локация», «стек», «аутрич», «сеньорность» are ordinary Russian and stay.
The rule previously carried one example, too few to generalise from, leaving the model to guess which borrowings count as jargon. A naive "no anglicisms" reading over-corrects into «соискатель» and «предположение», which is worse than any drift it would fix. Spelling is pinned to «сеньорность» over «сениорность».
Verification
Live run against the deployed demo with the same 3470-character Russian JD used to find the bug:
| v2.2.1 | v2.2.2 | |
|---|---|---|
| headings | 11 RU / 3 EN | 15 EN / 0 RU |
| addressed to the user | Russian | English |
| mixed-language headings | none | none |
| hh.ru consent gate | held | held |
| outreach (Module 4) | candidate's language | candidate's language |
The consent gate still declines explicitly and states why — "a Russian-language JD alone is not sufficient to fire that branch" — so the language change did not weaken it.
Full changelog: v2.2.1...v2.2.2
v2.2.1 — output language judged by the JD's body text
Superseded by v2.2.2 — do not rely on the behavior described below.
This release made the JD's language decide the output language. That was the wrong call: a JD is source material, not a signal for how the user wants to be addressed, so pasting a Russian JD while writing in English produced a Russian report. v2.2.2 removes that branch — only the user's own messages set the output language.
What still holds from this release: section headings are named explicitly in the rule, and mixing languages mid-phrase is forbidden.
The original notes are kept below for history.
Corrects existing behavior; no new features.
Output language follows the JD's body text
A Russian JD came back with English section headings over Russian prose — in the worst cases mixed mid-phrase ("Part A — Boolean строки").
SKILL.md's "Output language" rule already said to match the JD's language, but it had two gaps: it listed persona, tables, and the Cowork block without naming headings, and it never said how to determine the JD's language.
Both closed:
- Section headings are named explicitly, and mixed output is forbidden — a Russian run gets Russian headings, not English ones over Russian prose.
- The JD is judged by its body prose, not its job title. Role titles are routinely English inside an otherwise non-English posting ("Lead Generation Manager" heading a Russian JD), as are tool and platform names (dbt, Snowflake, LinkedIn). None of those make it an English JD.
The Module 4 exception is unchanged: outreach still follows the candidate's likely language, with a one-line note when it differs from the rest of the run.
Demo: the turn-cap note follows the JD too
The hosted demo's turn-cap note was hardcoded English, so a Russian run ended on an English sentence. It is appended by the Worker once the agent is out of turns, so no model call can write it — the language is now decided in code from the JD's script, judged on the body's letters rather than the title.
Known limitation: this distinguishes Russian from English only, where the model-side rule covers every language. A Russian JD consisting almost entirely of English tool names would still get an English note; prose-bearing JDs do not trigger this in practice. It affects a cosmetic note on a rare path.
Verification
Live run against the deployed demo with a real 3470-character Russian JD:
| run | headings | mixed-language headings |
|---|---|---|
| before the drift | 11 RU / 3 EN | none |
| with the drift | 13 EN / 2 RU | yes |
| v2.2.1 | 11 RU / 3 EN | none |
The three English headings that remain are the outreach variants, which should be English under the Module 4 exception — the rule is discriminating, not blanket-forcing.
Heading language was non-deterministic before this change, so a single run is good evidence rather than proof.
Full changelog: v2.2.0...v2.2.1
v2.2.0 – Hosted web-app demo, hardening, and profile enrichment
The skill's prompt content is unchanged since v2.1.0 — SKILL.md and references/ carry no diff. Everything here is the new hosted harness around it, so if you run the skill in Claude Code there's nothing behavioral to pick up; pull for the docs.
Live demo
The skill now runs as a web app at tech-sourcing-webapp.pages.dev — paste a JD, get persona → live X-ray search → scorecard → outreach in the browser, without installing Claude Code. Same skill, same rules (real search, no invented URLs); a Cloudflare Worker calling the Claude API replaces Claude Code as the harness. (#56, #58)
Profile enrichment
The agent gained a second tool, fetch_profile(url), so candidates are scored on dated employment history instead of search snippets alone: LinkedIn routes to Apollo, everything else to Firecrawl scrape. Profile data only — no email or phone reveal. Enrichment is capped per run to bound credit spend. (#68)
Hardening
A review pass over the public demo endpoint closed a set of abuse and disclosure paths:
jobDescriptionsize is capped, so a large body can't be billed as Opus input tokens (#60)- upstream error text is no longer relayed to callers, via 500s or tool results (#62)
- CORS is an allowlist rather than
*(#63) - the rate limiter uses a sliding window, closing the hour-boundary burst (#64)
- CI typechecks the Worker, which caught a real bug within the day (#61)
Fixes
Boolean search strings — the main copy-pasteable deliverable — no longer render as a run-on paragraph, and fenced code blocks render at all (#65). The Worker's smoke test verifies from the response body after wrangler tail proved unreliable non-interactively (#69).
Full changelog: v2.1.0...v2.2.0
v2.1.0 – Worked-example wiring and consistency fixes
What's changed
Skill behavior
- Outreach CTA fixed from "15-minute call" to "30-minute call", matching the worked examples in
references/outreach-examples.md(#40) references/example-walkthrough.mdis now wired into SKILL.md's References section — the skill reads it when reasoning through ambiguous scoring or verification judgment calls mid-run (#40)- The walkthrough's scoring language now matches SKILL.md's 3-tier scorecard, so the worked example no longer models a scoring scheme the skill doesn't use (#48)
- Tech-role Boolean examples added to
references/boolean-search-guide.md(#52)
Documentation
- New DESIGN.md: as-built design doc covering motivation, high-level behavior, the multi-platform architecture, the optional Cowork step, error handling, and file structure (#43, #49)
- CHANGELOG backfilled for all previously undocumented PRs (#45, #46)
- Threads added to the README platform lists; Variant 2 heading aligned with SKILL.md; CONTRIBUTING.md and the PR template now describe all reference files (#47, #53, #50)
Tooling
- Prettier no longer touches Markdown or JS files, stopping emphasis-style rewrites (#42, #44)
validate-skill.mjshandles multiple blank lines before frontmatter (#40)- CI actions bumped to latest majors (#51)
Full changelog: v2.0.1...v2.1.0
v2.0.1 - Edge-case hardening
Six follow-up PRs since the v2.0.0 rename, all guardrails and validator robustness fixes — no changes to default behavior:
- #28 — bare-word exclusion caveat in Google x-ray tips
- #30 — full worked example walkthrough
- #32 — geekjob.ru and Twitter/X legal/safety notes
- #34 — region-trigger ambiguity and Telegram consent gap
- #36 — malformed-JD guardrails, two validator false-fail fixes
- #38 — remaining edge cases across SKILL.md, references, and the validator
See CHANGELOG.md for full details.
v2.0.0 – Renamed to tech-sourcing-skill (breaking)
Breaking change: rename
The repo, local install folder, and skill name are renamed from linkedin-sourcing /
linkedin-sourcing-skill to tech-sourcing / tech-sourcing-skill, to match the mostly-IT
platform mix added in v1.1.0.
If you have this skill installed:
mv ~/.claude/skills/linkedin-sourcing ~/.claude/skills/tech-sourcingcd ~/.claude/skills/tech-sourcing && git remote set-url origin https://github.com/Da6ka/tech-sourcing-skill.git && git pull- Restart Claude Code (or start a new session) — the skill now loads as
tech-sourcing.
The old repo URL (Da6ka/linkedin-sourcing-skill) redirects automatically, so existing clone
remotes keep working even without step 2 — but updating them avoids relying on the redirect.
No functional changes
This is a pure rename. Everything from v1.1.0 (Checkpoint 0, the platform decision table and
recipes in references/other-platforms.md, LinkedIn as the always-on baseline) is unchanged.
See CHANGELOG.md for full details. PR: #26.
v1.1.0 – General candidate sourcing, beyond LinkedIn
Highlights
The skill now sources beyond LinkedIn when the role calls for it, while keeping LinkedIn as the always-on baseline and every existing LinkedIn-only workflow unchanged.
New
- Checkpoint 0 — before building the persona, the skill asks what type of candidates you're sourcing (tech, design, data/ML, algorithm-heavy, commercial/general, RU/CIS market) and picks the matching platform(s) accordingly, or infers it from an unambiguous JD.
- references/other-platforms.md — decision table and search recipes for GitHub, Stack Overflow, Kaggle, Codeforces, Dribbble, Behance, hh.ru, geekjob.ru, Reddit, Twitter/X, Telegram, and Threads.
- Module 2 Part D — runs the selected platform(s) alongside LinkedIn, output as its own labeled table.
- Run footer now lists unused sources so a follow-up round on a different platform doesn't require re-answering Checkpoint 0.
Safety
- hh.ru gets a stronger safety note than every other platform: its User Agreement explicitly bans automated parsing, and unauthorized data collection is criminal under Russian law (ст. 272.1 УК РФ, in force since 11.12.2024) on top of 152-ФЗ fines. The recipe is X-ray-search-only — never a scraper or unofficial API wrapper.
- README (install, example output, FAQ, disclaimer) now documents the multi-platform behavior and each platform's own ToS obligations.
Compatibility
No breaking changes — LinkedIn Parts A–C are untouched, and Checkpoint 0 is skippable when the JD makes the candidate type obvious. The skill's identity (name, repo path) is unchanged in this release; a separate rename to reflect the broader scope is under consideration.
See CHANGELOG.md for full details. PRs: #23, #24, #25.
v1.0.0 – Initial Release
🎉 Initial Release
The first public release of LinkedIn Sourcing Skill.
Features
- Scenario-based recruiting workflow
- LinkedIn sourcing strategy
- Boolean search generation
- Candidate assessment
- Outreach message generation
- Validation script
- Comprehensive documentation
This project is open source under the MIT License.
Feedback, issues, and contributions are welcome!