Skip to content
Conduit

skill

job-matcher-skill

Match your CV to live job postings and generate an interactive HTML report. Agent-native skill for Claude Code & Codex (WebSearch + subagents, zero-dependency).

sangowu/job-matcher-skillcommunitylistedunreviewednot running here yet

Set up

Skills are installed by placing their folder where your agent loads skills.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below; one-click install arrives with accounts.

README

synced Oct 14, 2026

job-matcher

English | 中文

版本文档:更新记录 · v2.4.0 发布说明 · v2.3.0 发布说明 · v2.2.0 发布说明 · v2.1.0 发布说明 · v2.0.0 发布说明

一个 agent skill(Claude Code 与 Codex 通用):输入简历(CV) + 求职意向,自动抽取简历字段、组合使用模型/Web 搜索与 BrowserOS Neo 或用户浏览器检索匹配职位,生成一份可交互的 HTML 报告。

是 JobRadar 的轻量版——默认同时使用模型搜索和可用的本机浏览器;浏览器提供者优先选择 Agent 已连接的 BrowserOS Neo,再降级到已授权用户浏览器,也可选接入 BYOK 隔离浏览器作为抓取兜底。


✨ 功能

  • 📄 简历解析:支持 PDF / DOCX / TXT / MD,或直接粘贴文本(不做 OCR)。
  • 🧠 结构化抽取:抽取目标职位、技能、资历(seniority)、地点、语言等,自动按相关年限定级。
  • 🌍 全球地区:6 个精选市场(ie / uk / cn / de / us / nl,带本地招聘站与城市目录)+ 212 个通用市场(geo_countries.json 中的每个国家/地区,含主要城市别名)。通用市场经 ATS 结构化通道与 Web 搜索覆盖;职位最多的 10 个通用市场(印度、加拿大、法国、新加坡、日本、西班牙、澳大利亚、波兰、巴西、意大利)另有已验证的本地招聘站,浏览器通道也可用;地点无法识别时仍会停下追问。
  • 🗣️ 按市场语言搜索与初筛:法国用法语、日本用日语、巴西用葡语、西语国家用西语、韩国用韩语、意大利用意大利语、波兰用波兰语,荷兰与比利时加上荷兰语,并保留英语;当地语言的职位标题与资历词(Sénior、Pleno、シニア、Stage…)都能识别。词表外的角色由 agent 翻译后经 localized_roles 进入搜索和初筛。地点也按各语言写法识别(Varsovie、Múnich、ワルシャワ、밀라노、Monachium),带不带重音都行。报告界面支持同样的 11 种语言。
  • 🔎 实时职位检索:默认并行运行浏览器平台搜索与模型/Web 搜索;浏览器按 Neo → 用户浏览器选择提供者,平台由地区来源目录动态规划,不在代码中硬编码站点 selector。
  • 🎯 5 维匹配打分:title / seniority / skills / location / must-have,输出五档投递建议(强烈投递→跳过)。资历硬规则与契约校验拦截打分漂移。
  • 🗂️ 增量缓存:CV、JD、匹配分三层缓存;多来源同职位自动聚合(含区域平台 job-id 强命中);换 query 自动失效重算。
  • 🛡️ 不可信输入隔离:搜索结果与 JD 正文按纯数据处理并忽略其中指令;报告内嵌 JSON 转义、链接限 http(s)。
  • 📊 可交互报告:两栏布局(左职位列表 30% + 右详情 70%)+ 评分徽章 + 深色模式 + 排序/搜索 + 市场/来源/验证状态筛选 + 多来源发现证据 + 7/30 天运行健康快照 + 界面支持中/英/德/法/西/葡/日(随 report_language,页内可切换),自包含单文件 HTML。
  • 🌐 可选隔离浏览器:Kernel BYOK 作为最终抓取兜底,支持受限列表翻页、视觉控制和 Live View 人工接管;默认关闭,CI 使用 Fake Provider。

🏗️ 架构

  • 主 agent = 编排者:调脚本、融合 query、追问用户、spawn subagent。
  • subagent 承担重上下文工作(CV 抽取 / 搜索 / 打分):大块原始文本留在 subagent,主上下文只搬「路径 + 小 JSON」,保持整洁。
  • Python 脚本承担确定性工作:解析、校验、去重聚合缓存、失效验证、渲染。
  • 并行计算、串行提交:第 N 批评估与第 N+1 批搜索并行发出(批间重叠);jobs_table.json 只有一个写入路径,使用评估快照、跨进程锁和原子替换防止丢失更新。超龄未完成的快照会在下次 merge 时作废回收,职位不会永久卡在评估中。
CV + query
   │ [脚本] extract_cv          → 纯文本 + cv_hash
   │ [缓存检查]                 → 命中则跳过抽取
   │ [subagent] 抽取 CVProfile  → [脚本] validate_profile
   │ [主agent] 融合 query       → search_plan + candidate_profile
   │ [发现计划] 浏览器平台+模型/Web+可选ATS → [脚本] merge_jobs(去重/聚合/缓存+评估快照)
   │ [并行 subagent] 粗排→精排抓JD+5维打分 + 失效验证 → [脚本] 条件化回写
   │ [脚本] render_html         → report.html + report_data.js(自动打开)
   ▼
可交互 HTML 报告

容错阶梯(失效验证 & JD 抓取共用):WebFetch → requests 静态抓 → 本机 headless → 可选远程隔离浏览器 → 标注未验证不阻塞。

📁 结构

job-matcher/
├── SKILL.md              # 触发描述 + 本运行时的能力映射
├── WORKFLOW.md           # agent-中立完整流程(只写做什么,每轮都读)
├── config.json           # 配置旋钮
├── docs/rationale.md      # 每条编号规则的理由与实测(只在改规则/排查时读)
├── docs/ats-protocol.md   # ATS/结构化通道协议(由脚本执行)
├── docs/remote-browser-protocol.md  # Kernel 远程浏览器(默认关闭)
├── docs/phase-c-legacy.md # 已被取代的双 route 入口
├── docs/shadow-and-smoke.md  # Phase D2 smoke 与 Phase E shadow 门
├── docs/monitoring.md     # 运行指标、阈值与健康汇总
├── docs/roadmap.md        # 版本更新期望:已知缺口与下一版验收标准
├── tools/                # 门禁与基准;正常一轮一条都不跑
│   ├── _bootstrap.py     # 把 scripts/ 放上 import 路径(工具测的就是生产模块)
│   ├── browser_candidate_smoke.py # 临时 store 验证浏览器候选与 merge,不污染正式数据
│   ├── multi_region_smoke.py # 显式、计数型每市场一槽的公开来源 smoke
│   ├── global_coverage_smoke.py # 显式、计数型:注册表 ATS board 实际覆盖哪些国家(精选 vs 加通用市场)
│   ├── shadow_gate.py        # Phase E 幂等 shadow 台账与逐市场发布门
│   ├── shadow_compare.py     # 只读计算增量、交集、JD 与潜在 Top-N
│   ├── benchmark_pipeline.py # 固定小数据集核心/Fake Provider 基准
│   ├── benchmark_ats.py      # 复用生产适配器的公开 ATS 有界回归
│   ├── benchmark_ats_e2e.py  # 固定 Web 对照组与 Web+ATS 受控 A/B
│   ├── benchmark_ats_quality.py # 三供应商 JD/评分质量审计
│   └── benchmark_ats_compression.py # ATS HTTP 压缩交错 A/B
├── references/           # subagent 按需读取的指令
│   ├── cv_schema.md          # CV 抽取规则
│   ├── scoring_rubric.md     # 5 维打分 + 五档阈值
│   ├── search_playbook.md    # fan-out / 分市场 / 自适应分批
│   ├── markets.json          # 精选市场的城市、语言与 query 模板
│   ├── geo_countries.json    # 通用市场:精选市场以外的每个国家/地区,含主要城市、搜索语言、行政区
│   ├── role_taxonomy.json    # 角色族:每种语言的标题/同义词(搜索与初筛共用)与技能门槛泛化边
│   ├── languages.json        # 可搜索语言:代码、别名、Web 搜索模板(语言集以本文件为准)
│   ├── model_tiers.json      # 型号 ↔ 档位映射,供子代理按 min_tier 选型
│   ├── source_seeds.json     # 已验证的公开来源种子(不含凭据);市场由 markets.json 决定
│   ├── multi_region_smoke_plan.json # Phase D2 固定来源与请求硬上限
│   ├── shadow_run.schema.json # Phase E 计数型 shadow 证据契约
│   ├── shadow_compare.schema.json # Phase E 临时候选对照输入契约
│   ├── shadow_run_v2.schema.json # Phase E shadow 证据契约 v2
│   ├── shadow_compare_v2.schema.json # Phase E 候选对照输入契约 v2
│   ├── candidate_envelope.schema.json # Phase C 发现候选契约
│   ├── ats_phase1_boards.json # ATS 小基线公开公司样本
│   └── ats_phase5_quality_boards.json # 三供应商质量小样本
├── scripts/              # 确定性 Python 脚本
│   ├── extract_cv.py         # 解析 CV → 文本 + hash
│   ├── validate_profile.py   # 校验 + seniority→levels 映射
│   ├── market_plan.py        # 校验市场资源并生成确定性多地区计划
│   ├── discovery_mode.py     # 只读能力状态的发现模式选择与安全降级
│   ├── discovery_plan.py     # 连接市场/健康/来源目录并生成多通道执行任务
│   ├── discovery_batch.py    # 校验所有任务结果,一次 merge 并决定是否扩展下一批
│   ├── local_browser_probe.py # 校验 Agent 已观察到的本机浏览器工具面
│   ├── local_browser_panel.py # localhost 设置、状态与闪烁人工提醒面板
│   ├── cookie_consent.py    # accessibility Cookie 语义分类;仅必要或暂停
│   ├── source_registry.py    # 来源种子校验、健康状态、迁移与确定性来源计划
│   ├── candidate_contract.py # 严格校验 Phase C CandidateEnvelope
│   ├── candidate_handoff.py  # 【已弃用】旧双 route 入口,被 discovery_batch.py 取代
│   ├── analysis_contract.py  # 校验 JDProfile/MatchScore worker 输出
│   ├── merge_jobs.py         # 单写入器:去重/缓存/评估快照/条件化回写
│   ├── runtime_metrics.py    # PII-safe JSONL 指标与健康计算
│   ├── search_metrics.py     # Web Search 页级计数与耗时指标
│   ├── summarize_metrics.py  # 7/30 天 Markdown/JSON 健康报告
│   ├── round_timer.py        # 整轮计时,按编排模式对比墙钟
│   ├── subagent_metrics.py   # 按档位为子代理选型号、记录实际执行指标
│   ├── browser_provider.py   # Kernel/Fake Provider 与安全配置
│   ├── browser_control.py    # 远程视觉浏览器控制命令;本机浏览器动作的指标自报路径
│   ├── browser_setup.py      # 一次性 localhost 配置页面
│   ├── browser_workflow.py   # 列表翻页/暂停状态机
│   ├── ats_provider.py       # Ashby/Greenhouse/Lever/Workday + amazon.jobs 公开只读适配器与 Fake
│   ├── job_prefilter.py      # 角色/地点/资历确定性初筛,三个通道共用一份规则
│   ├── rejected_log.py       # 被初筛拒过的身份标记(只用于统计重复,从不用来跳过初筛)
│   ├── ats_pipeline.py       # ATS 标识库、同步与候选归一化
│   ├── ats_handoff.py        # ATS 正文内存直送统一 merge,避免主上下文暴露
│   ├── source_reverify.py   # 过期网页来源续期:查 robots 后 GET 入口页一次,经注册表事件写回
│   ├── board_harvest.py      # 从职位 URL 反推 ATS board,复验后写入来源注册表
│   ├── seed_promotion.py    # 把已复验的采集来源提升进版本控制的种子目录
│   ├── cp_hash.py            # 稳定的 candidate_profile hash
│   ├── verify_jobs.py        # 失效职位状态码检测
│   ├── check_robots.py      # 按 RFC 9309 读 robots.txt,回答某个 URL 站点是否允许抓取
│   ├── fetch_rendered.py     # headless 渲染兜底(复用系统浏览器)
│   ├── render_html.py        # 渲染 HTML 报告
│   ├── _jobutil.py           # 共享:归一化/去重键/URL 规范化
│   ├── _filelock.py          # 共享:跨进程独占文件锁(所有本地存储)
│   └── _stdio.py             # 共享:stdout/stderr 钉成 UTF-8;stdin 读取有上限,不会无限等待
├── assets/template.html  # 静态报告模板(Tailwind + 纯 JS),原样复制为 report.html
├── assets/report_strings.json  # 报告界面文字,每种语言一张表,每轮写入 report_data.js
└── data/                 # 运行时数据(.gitignore,含 PII)

多地区 Phase A/B/C 目前仍是显式入口:python scripts/market_plan.py validate 校验版本化市场/角色配置,python scripts/market_plan.py plan 从 stdin 接收 {cv_profile,user_intent} 并生成 markets.json 所列市场的市场、语言、地点与 Web query 计划,同时报告 target_roles 与 roles_source; python scripts/market_plan.py effective-profile 吃同一份输入,输出把已解析角色写入 roles 键的 profile——确定性初筛读的就是这一份,不经过它就会出现「按用户意图去搜、 按 CV 角色去筛」的两套答案。python scripts/source_registry.py validate 校验公开来源种子;init 在 data/source_registry.json 原子合并种子,并在旧 data/ats_companies.json 存在时只读迁移; plan --markets ie uk 只返回 enabled + verified + TTL 未过期 的确定性来源(结构化来源过期仍列入,抓取即复验;网页来源由 source_reverify.py 续期),每个全球来源 只出现一次。它们都不执行搜索或修改职位表,因此旧单地区 Web Search/ATS/merge/报告流程 保持兼容。Phase C 编排者可让 regional_registry 与 agent_web_search 同时开始,待两条 route 都回报成功、失败或跳过后,把同一 batch_id 的严格 CandidateEnvelope 交给 candidate_handoff.py;它先经唯一 merge_jobs.py 写职位与评估快照,再幂等提交来源状态。 契约与回滚见 docs/multi-region-phase0-baseline.md、 docs/source-registry-phase-b.md 和 docs/multi-region-phase-c.md。 Phase D1 的离线报告契约见 docs/multi-region-phase-d1.md。 Phase D2 的有界公开来源 smoke、隐私边界与本次证据见 docs/multi-region-phase-d2.md;它必须显式传 --live,不会进入默认 CI 或生产发现路径。 Phase E 的 count-only shadow 契约、逐市场门槛和当前未达标状态见 docs/multi-region-phase-e.md。 multi_region_enabled 默认仍是 false;因此 Phase C 不会自动替换现有单地区流程。

发现模式 Phase 1+2 提供 discovery_mode.py plan|event 与 local_browser_probe.py probe 的确定性契约。默认 coverage 同时运行模型/Web 搜索与一个 已连接、已授权且可执行的浏览器提供者,浏览器内部按 BrowserOS Neo → 用户浏览器选择;旧 auto 保留单 route 兼容行为,browser_only 绝不静默改用模型搜索。discovery_plan.py 再把 market plan、URL-free 健康计划和公开来源目录连接成有界 browser/Web/structured 任务。探测基于 Agent 已暴露的工具面,不扫描端口、浏览器配置、Cookie 或现有标签页;实际发现使用专用标签页, 候选仍进入同一 CandidateEnvelope/merge 主表。详见 docs/discovery-mode-phase1.md 与 docs/local-browser-phase2.md。浏览器 route 可运行 python scripts/local_browser_panel.py serve 打开 loopback 控制面板:它只保存模式和低基数状态, 登录/验证/consent/限流时闪烁并等待用户恢复;详细契约见 docs/local-browser-phase3-panel.md。现有 Kernel 远程浏览器仍只是 单独的可选抓取兜底,不会代替用户本机的登录会话。

DiscoveryPlan 把跨通道任务分成确定性波次;Agent 先只执行 initial_wave_id。每个当前波次 task 完成后,discovery_batch.py 要求其恰有一个终态,校验候选与 task 的 route/source/market/language 一致性,再把该波次所有通道候选一次性交给现有单写入 merge。 它的脱敏 manifest 支持中断恢复,并按新增唯一候选、计划内剩余波次和现有停止阈值决定是否返回 next_wave_id;调用方不能自行覆盖。该决策只控制发现扩展,不等同于 JD 完整或 CV 匹配合格。 2026-09-21 的有界运行时 smoke 已分别验证 BrowserOS Neo MCP 主路径和用户 Chrome 降级路径的 专用标签页 create/navigate/read/close;当 Neo 可用时浏览器提供者会选择 Neo。LinkedIn 实测还验证了 登录暂停、面板提醒/恢复、登录态复用和同标签页受限搜索;后续单候选 smoke 已通过受限主区域读取、 详情存活验证、CandidateEnvelope 和临时 merge;三候选同页批次也完成 3/3 provenance 保留。 2026-09-22 又完成了一次真实 CV、Dublin-first Ireland 的三波生产运行:12 个任务全部到达终态, 两个强身份候选进入正式 merge、JD 评分和 HTML 报告。该运行同时发现,Neo MCP 直接操作尚未写入 仓库 browser 指标,因此报告健康状态会正确显示 unknown;站点 host alias、歧义 consent、 自定义 combobox、跨页翻页、CAPTCHA 和限流恢复仍是 gate。证据边界见 docs/local-browser-phase4-smoke.md。确定性首波的 Neo + Web Search 联合 smoke、consent 暂停、三波继续/停止决策以及临时单写入 merge 的证据见 docs/discovery-wave-live-smoke.md;完整生产试运行见 docs/browseros-neo-production-trial-2026-09-22.md。

脚本分工

scripts/ 共 19,900 行,不是一条路径。改动前先看清一个脚本属于哪一类:

类别行数是什么
关键路径~13,700 (69%)一轮匹配真正会跑的:CV 解析、market/discovery 规划、来源注册表、初筛、ATS 拉取、merge/update、渲染、指标
门禁与基准~4,300 (22%)benchmark_*(公开小样本回归)、shadow_* 与 multi_region_smoke(发布门禁)、browser_candidate_smoke(首次接入验证)。正常一轮不跑,改解析器或提版本时才跑
运维~1,900 (9%)本机面板、浏览器配置、种子提升、board 采集、版本检查、指标汇总

弃用中:candidate_handoff.py(旧双 route 入口,已被 discovery_plan.py + discovery_batch.py 取代,输出带 deprecated: true)、search_metrics.py(只剩不经 discovery batch 的独立诊断用途)。

🚀 使用

克隆到个人 skill 目录(目录名用 job-matcher,与 skill 名一致):

# Claude Code
git clone https://github.com/sangowu/job-matcher-skill ~/.claude/skills/job-matcher
# Codex
git clone https://github.com/sangowu/job-matcher-skill ~/.agents/skills/job-matcher

agent 会自动识别。然后在对话里:

这是我的简历 D:\cv.pdf,帮我找远程后端职位

或直接粘贴简历文本 + 求职意向。skill 会走完整流程并在浏览器打开报告。

⚙️ 配置

config.json 集中所有旋钮:

键默认说明
top_n15最终展示职位数
precise_buffer5精排多抓缓冲
version_check_enabledtrue启动时是否检查本地 skill 与 GitHub main 是否同步
version_check_interval_hours24GitHub 版本检查缓存时长;缓存期内不发网络请求
version_check_timeout_seconds3单次只读 GitHub 请求超时秒数
max_parallel_subagents3批内并行上限
subagent_profiles见配置各角色的档位下限 min_tier、reasoning effort 与隔离上下文策略;可选 model 钉死型号
max_websearch_calls6WebSearch 总次数上限
discovery_modecoveragecoverage 默认并行浏览器+模型搜索;auto 保留单 route 兼容;也支持 model_only、browser_only、combined
cookie_consent_policynecessary_only只在唯一明确语义按钮上自动拒绝可选 Cookie;也可设 ask_every_time
discovery_max_waves3单次计划最多生成的确定性发现波次数
browser_sources_per_market4每个市场、每个波次的浏览器来源上限;浏览器首个波次内先保证来源类型多样性
browser_first_wave2浏览器从第几个波次开始;默认让结构化通道先跑一波,浏览器退为兜底
web_first_wave3Web Search 从第几个波次开始;实测 22 次调用只换来 2 个新候选、最近五轮为 0,因此排在结构化与浏览器之后
browser_queries_per_source2单个浏览器来源本轮执行的地区化查询上限
web_queries_per_market_per_wave2每市场、每波次执行的 Web Search 查询上限
web_source_hints_per_task6每条 Web Search 任务携带的公开来源提示上限
multi_region_enabledfalse只管 Phase E shadow 门禁;只有 shadow_gate.py 读它,live 发现路径不读,因此它不是多市场总闸
multi_region_rollout已列出的市场均 off每市场独立设置 off / shadow / opt_in / default;default 必须通过 Phase E 门禁。同样只作用于 shadow 门禁
stop_threshold20累计唯一候选达标即停(continuation.reason=target_reached)。计的是 merge 新增的唯一候选,发生在评分与 JD 补全之前;取 top_n + precise_buffer,使刚好触线停下的一轮仍够填满报告
consecutive_empty_stop2连续 N 批 0 结果则停止
ats_enabledtrue是否启用公开 ATS 增强管道
ats_defer_jdtrue先读不含 JD 正文的职位列表,再只为本轮保留的候选各取一次正文;false 恢复每个 board 一次请求、正文随列表一起下载
ats_max_concurrency3跨 ATS board 并发硬上限
ats_boards_per_round60单轮每波次 board 数上限;超出的 board 记入 omitted_by_wave_budget.structured
ats_requests_per_round100单轮 ATS HTTP 请求硬上限
ats_page_size50Lever 每页请求数量
ats_max_pages10单个 Lever board 顺序翻页硬上限
ats_timeout_seconds30单次公开 ATS GET 超时秒数
ats_registry_ttl_days30unavailable board 的重试退避间隔
ats_fetch_interval_minutes60已验证 board 再次取职位的最小间隔(分钟);0 表示每轮都取
jd_ttl_days30JD 缓存有效期
verify_ttl_hours24链接有效性核对的复用时长;alive 且未过期的行不再复验
seniority_modebalancedstrict / balanced / stretch
enable_headless_fallbacktrueheadless 兜底开关
headless_budget3每次运行 headless 上限
remote_browser_enabledfalse是否启用远程隔离浏览器最终兜底
browser_providerkernelkernel;fake 仅供测试
browser_max_concurrency2远程浏览器并发硬上限
browser_max_pages3单个招聘列表串行翻页硬上限
browser_min_source_interval_ms5000同一来源两次浏览器动作的最小间隔,只能调高;间隔不足的动作记为失败且不计入轮次完整性
browser_jitter_ms2000在最小间隔之上叠加的随机等待上限,用于分散请求;只会让等待变长,不用于伪装流量
browser_max_requests_per_minute120同一来源滚动 60 秒内的请求数上限,只能调低;这是站点实际感受到的单位——一次点击实测 14 个请求,所以动作间隔并不是请求速率上限
browser_assumed_requests_per_action10未实测请求数的动作按这个数计费,只能调高;120 / 10 = 每分钟 12 个动作,正好等于 5000ms 的间隔,两条上限同时到顶
browser_session_budget10单轮新建远程会话硬上限
browser_cost_limit_usd1.0单轮估算费用硬上限(美元)
browser_handoff_timeout_minutes10人工接管等待硬上限(分钟)
browser_allow_handofftrue是否允许通过临时 Live View 交给用户处理
browser_timeout_seconds600单个远程会话超时硬上限
browser_headlessfalseProvider 是否隐藏浏览器;默认保留可接管视图
browser_stealthfalsestealth 开关;默认关闭且不用于绕过验证
table_lock_timeout_seconds10等待主表写锁的最长秒数
stale_lock_seconds120回收异常遗留锁的时间阈值
eval_run_stale_hours2作废未完成评估快照的时间阈值
monitoring_default_window_days7默认健康报告窗口
monitoring_thresholds见配置冲突、拒绝、成功率、锁等待和积压阈值

python scripts/version_check.py 会比较本地 pyproject.toml 版本、Git commit 与 GitHub main,结果缓存到已忽略的 data/version_check.json。它不读取或上传 CV/JD/搜索数据,不需要 GitHub token,也不会自动更新文件;离线、超时或限流只返回 unknown,不阻断职位流程。需要绕过缓存做只读诊断时使用 python scripts/version_check.py --force。

运行时只保留一个职位主表 data/jobs_table.json。record_id 是稳定记录/评估主键,identity_keys 保存平台职位 ID;公司 + 标题 dedup_key 仅作兼容弱匹配。两个不相交的强 ID 不会因同公司同标题而误合并,弱键匹配还要求地点兼容且结果唯一。旧表会在下一次 merge/update 时原位补齐身份字段。每轮待评估职位写入最小化快照 data/eval_runs/<run_id>.json;ATS 已返回 JD 时,正文只临时存在对应任务快照,主表只保存内容 hash,worker 可直接分析并跳过网页抓取。单个任务完成即清除正文,整轮完成后快照释放,仅在 history.jsonl 留下不含 CV/JD 正文的摘要。每次 merge/update 另写一条 PII-safe data/metrics.jsonl 事件。

远程浏览器为可选功能。安装依赖后运行一次性本地设置页;页面只绑定 127.0.0.1,连接测试成功后把 API Key 保存到系统密钥库,非敏感设置保存到已忽略的 data/browser_provider.json:

python -m pip install "kernel>=0.94,<1" keyring
python scripts/browser_setup.py
python scripts/browser_control.py test

无界面环境也可通过 KERNEL_API_KEY 提供密钥。控制脚本的 create/screenshot/click/type/press/scroll/close 供 browser 子代理进行视觉控制;Live View URL 只临时返回,不写入指标或文件。

📈 运行监控

python scripts/summarize_metrics.py --days 7 --format markdown
python scripts/summarize_metrics.py --days 30 --format json
python scripts/summarize_metrics.py --fail-on-breach

报告包含 run 完整性、Web Search 调用/有效候选、吞吐/缓存、评估成功/拒绝/冲突率、子代理实际模型/effort/token/成本覆盖、浏览器与 ATS 计数、命令与锁等待分位数及积压状态。阈值违规为 degraded;缺失必需事件时健康状态为 unknown,不会误报 healthy。CLI 的 --fail-on-breach 对两种情况都返回退出码 2。字段定义见 运行时监控文档,设计与后续 A/B 门槛见 run-scoped 指标契约。

整轮墙钟另行采集——脚本级耗时相比编排者在两次调用之间的搜索与评估工作可以忽略,无法回答「批间重叠值不值」:

python scripts/round_timer.py start          # → {"run_id": "round-...", "round_id": "round-..."}
python scripts/search_metrics.py --ok --run-id <R> --query-slot q1 --duration-ms 120
python scripts/round_timer.py finish --round-id <R> --orchestration overlapped|serial --expect subagent

汇总按编排模式给出 p50/p95 与 overlap_saving_pct;两种模式都有样本前显示 n/a。

monitoring_thresholds.unfinished_run_age_minutes_max 控制未完成 run 何时被判为陈旧并令健康状态变为 unknown;默认 120 分钟。

版本性能回归使用固定 15 职位冷数据集和 10 个 Fake 会话:python tools/benchmark_pipeline.py --output <json> --baseline docs/performance/v2.2.0-small-baseline.json。输出同时包含原始迭代、p50/p95、绝对变化和相对变化;不会调用真实 Web Search 或云 Provider,并验证三家 Fake ATS 的 JD 均进入临时任务、主表零正文。强身份迁移基准见 docs/performance/strong-job-identity-baseline.md,三家 ATS 离线管道基准见 docs/performance/ats-phase2-fake-baseline.md,Phase 4 交接基准见 docs/performance/ats-phase4-jd-handoff.md,真实三条五维抽检见 docs/performance/ats-phase4-live-quality.md。固定 Web 候选对照组与受限真实 ATS 的 discovery-to-merge A/B 使用 python tools/benchmark_ats_e2e.py --web-candidates <json> --profile <json> --output <json>;它会发出公开 ATS 请求,必须显式提供本地输入并遵守生产硬上限。结果与限制见 docs/performance/ats-phase3-controlled-e2e.md。三供应商 JD 质量复核可先用 python tools/benchmark_ats_quality.py collect ... 创建不提交的本地样本,再用 audit 生成计数型门禁报告;本次小样本结果与限制见 docs/performance/ats-phase5-multiprovider-quality.md。ATS HTTP 压缩可用 python tools/benchmark_ats_compression.py --output <json> --pairs 3 做相同结果集的交错 A/B;本次三供应商实测中位传输量减少 79.31%,内容指纹、职位数与请求数均相同,详见 docs/performance/ats-http-compression-ab.md。

ATS Phase 2 的生产增强管道由 ats_enabled 控制(当前默认开启;是否派发 structured 任务由本轮市场在来源目录里有没有 structured 来源决定,false 只是关闭开关)。Web Search 或浏览器候选里的官方 ATS 职位 URL,由 discovery_batch.py 在每波合并后自动经 board_harvest 复验并登记进来源注册表,无需手动操作;不经 discovery batch 的旧路径仍可用 python scripts/ats_pipeline.py discover 写入本地标识库;Greenhouse 同时识别 job-boards.eu.greenhouse.io 的公开职位页,但公开 API 仍使用官方 boards-api.greenhouse.io。启用后用 sync --profile <cv-profile.json> 同步已到期 board,或用 run --profile ... 一次完成发现与同步。管道只做公开 GET,默认请求 gzip 并同时限制压缩响应与解压后正文大小,按标题/地点/资历确定性初筛;单独的 AI 产品/团队后缀不是有效岗位匹配,明确的 AI evaluation、AI systems、agent systems 等岗位短语才作为 AI 方向信号。Phase 4 会把 ATS 已提供的 JD 清洗并限制为 50,000 字符,通过同一 merge_jobs.py 的本地 run 快照交给精排 worker;有正文的任务跳过网页抓取,没有正文的任务继续走原容错阶梯。Web 与 ATS 仍共用职位主表和分析缓存,主表只留 JD hash。Phase B 初始化通用 data/source_registry.json 后,ATS 控制状态只写通用 registry,旧 data/ats_companies.json 保持只读;通用 registry 不存在时仍回退旧文件。data/ats_sync_state.json 继续保存低敏同步摘要。ATS 预算独立于 Web Search;跨 board 可并发,Lever 单 board内顺序翻页。Greenhouse 的 content=true 响应超过 25 MB 时可在同一全局请求预算内降级重试不含正文的列表,并记录 content_fallback。公开 API 回归仍使用 python tools/benchmark_ats.py --output <json> --page-size 50 --max-pages 10,且脱敏证据不保存职位正文、标题或 URL。详见 docs/ats-provider-phase1.md。

🔧 依赖

  • Python 3.10+
  • 必需:pdfplumber python-docx requests
  • 可选:playwright(headless 兜底,复用系统已装的 Chromium 系浏览器,无需 playwright install)
  • 可选远程浏览器:kernel、keyring
pip install pdfplumber python-docx requests
pip install playwright   # 可选
pip install "kernel>=0.94,<1" keyring  # 可选远程浏览器

Built with Claude Code.

↑↓ navigate openesc close