| name | life-screener |
| description | wiki-life 专用 inbox 筛选与评分入库。扫描 raw/inbox/{rss,newsletter,wechat}/,对每篇候选做 life 领域红线过滤 + DeepSeek 评分(v×c≥45)+ 领域相关性检查,过线则入库 raw/articles/+entities/concepts+index.md+log.md 并 git commit。区别于 wiki/inbox-screener(AI/ML 领域、v×c≥49)。 |
| version | 1.6.1 — +Stats 不一致诊断: [WARN] index.md 条目验证失败 → raw entry 缺失 → 只 bump Sources 不 bump Total(2026-08-06) |
| category | wiki-life |
| related_skills | ["llm-wiki","wiki-pipeline","wiki/inbox-screener"] |
Life Screener — wiki-life inbox 评分入库
统一筛选 ~/wiki-life 自动抓取 pipeline 沉淀到 inbox 的候选文章,做 life 领域评分与入库。
与 wiki/inbox-screener 的关系:工程模式(blacklist/DeepSeek fallback/candidates 清理/git 显式路径)复用自主 wiki inbox-screener,但领域逻辑完全不同——本 skill 面向个人成长内容,门槛 v×c≥45(非 49),关键词是自律/职业/心理/关系/认知/财务(非 agent/llm/transformer),红线是鸡汤/软文/营销号(非低价值技术新闻)。不要把 AI 关键词预过滤套到 life 内容上——会误杀几乎所有候选。
背景
| Pipeline | 输出位置 | 内容类型 |
|---|
| wiki-life-rss-scan (每 6h) | raw/inbox/rss/ | RSS 全文(Cal Newport / Psyche 等),文件已含完整正文 |
| wiki-life-newsletter-scan (每 6h) | raw/inbox/newsletter/candidates.md | Newsletter URL 列表(FS Brain Food / TLDR 等),需 fetch |
| (预留) wechat | raw/inbox/wechat/ | 微信公众号全文 |
本 cron(wiki-life-inbox-scan,每日 9:00)是消费端:读取上述 inbox → 评分 → 入库 → 清理。上游 cron 只负责抓取放 inbox。
领域定义(SCHEMA.md / AGENTS.md)
wiki-life 焦点领域:
- 自律 & 习惯养成:habit, willpower, time-management, self-discipline, energy-management
- 认知提升:mental-model, decision-making, cognitive-bias, learning-method, meta-cognition
- 心理健康:emotion-regulation, anxiety, mindfulness, cbt, act, mbsr, mental-health
- 亲密关系:communication, nvc, conflict-resolution, intimacy, family
- 职业发展:career, interview, job-search, skill-development, side-project
- 财务:personal-finance, investment, frugality, financial-independence
与 ~/wiki(AI/ML)的边界:纯 AI/ML/工程技术内容归 ~/wiki(v×c≥49),不进本库。若 life 来源文章主轴是 AI/技术(如 Psyche 写 AI 伦理),路由到 ~/wiki,不在本库评分入库。
评分门槛
review_value × review_confidence ≥ 45 → 入库(life 内容比技术内容主观,门槛比 ~/wiki 的 49 低 4 分)
review_stars ≥ 4(独特洞察/框架)→ 入库(但仍须过领域相关性检查)
review_stars ≤ 2 → 一票否决,不入库
- Borderline (v×c 42-44) + 命中已有深度 entity + ≥3 互补角度 → MERGE 作 Nth source;否则 REJECT
frontmatter 字段(SCHEMA.md):
review_value: 8
review_confidence: 7
review_stars: 4
review_recommendation: strong | worth-reading | reference
Life 红线 — 7 类无条件 REJECT(QUALITY.md)
评分之前先做红线快检,命中任一 → 直接 REJECT,不送 LLM(省 API):
| 类型 | 识别方法 | 典型信号 |
|---|
| 鸡汤文 | 读完只有情绪起伏,没有认知增量 | "你要相信..." / "坚持就是胜利" / "努力就会成功" |
| 毒鸡汤 | 复杂问题归因单一因素,制造焦虑/优越感 | "穷是因为懒惰" / "焦虑是因为想太多" |
| 软文/营销文 | 80% 故事铺垫,结尾突然推销 | 个人困境 → 偶遇产品 → 生活巨变 → 限时优惠二维码 |
| 营销号 | 所有文章都是导流入口 | 每篇结尾"加我微信"/"限时特惠"/"仅限前50名" |
| 标题党 | 标题承诺与正文严重不符 | "年薪百万的秘密" / "这才是真正的自律" |
| 投射文 | N=1 个人经验当普适真理 | "我就是这么做的,你也可以" |
| 情绪包 | 专刺激情绪(愤怒/焦虑/感动)无信息价值 | 极端个案、对立话题、纯发泄 |
快检方法:读标题 + 前 500 字。问 3 问(AGENTS.md):
- 核心论点一句话能概括吗?不能 → REJECT
- 作者提供了什么证据?纯断言 → REJECT
- 能从今天开始做什么具体的事?只有"要改变心态" → REJECT
5 维度质量标准(QUALITY.md)— 入库须满足 ≥2 项
| 维度 | 检验标准 |
|---|
| 有论证 | 引用研究/数据/逻辑链(如"根据 Duckworth grit 研究 N=3998...") |
| 有框架 | 可复制方法论(如"OODA:观察→调整→决策→行动") |
| 有边界 | 明确适用范围("适用于 X,不适用于 Y") |
| 有实践 | 具体步骤/工具/模板 |
| 有批判性 | 承认局限/反例/替代解释 |
LLM 评分 prompt 应要求模型按这 5 维度 + value/confidence/stars 打分,并在 reason 里点明命中了哪几维。
领域相关性检查(评分通过后的后置过滤)
LLM 对"写得好"的非 life 文章也会给 v×c≥45(如有框架的纯技术教程)。评分通过 ≠ 入库通过。入库前逐一检查:
入库:文章主轴在 life 焦点领域内(自律/认知/心理/关系/职业/财务)。
跳过(路由 ~/wiki):纯 AI/ML/工程/编程技术内容 → 不在本库评分入库,可提示用户转 ~/wiki。
跳过(reject):纯娱乐/八卦/时事政治/与个人成长无关。
判断方法:问"这篇文章的知识能否直接应用于个人成长/自律/心理/关系/职业/财务?"否 → 跳过。
用户直接发链接的快速评估流程
当用户在对话中直接发送 URL(非 cron pipeline 自动抓取)时,走以下快速判断:
1. 来源识别
| 来源 | 常见内容 | 路由 |
|---|
| 阿里云开发者、腾讯云、美团技术、字节技术 | AI/ML 工程实践 | ~/wiki |
| 叶小钗 | 产研管理、AI 工具落地 | ~/wiki(工程管理,非个人成长) |
| Hyman的杂货铺 | AI/ML 论文解读 | ~/wiki |
| L先生说、KnowYourself、简单心理 | 认知/心理 | wiki-life |
| 暂停实验室、开智学堂 | 心理/认知/行动 | wiki-life |
2. 标题关键词预判
标题不含以下 life 关键词 → 大概率不在本库范围:
自律、习惯、意志力、情绪、焦虑、沟通、亲密关系、认知、职业、决策、财务、心态、拖延、专注
含 Agent、LLM、模型、开源、注意力、训练、推理 等技术关键词 → 路由 ~/wiki
3. 内容快速确认
抓取正文后确认主轴:
- 主轴在 life 焦点领域(自律/认知/心理/关系/职业/财务)→ 评分入库
- 纯 AI/ML/工程/编程技术 → 路由 ~/wiki
- 娱乐/八卦/时事 → reject
4. 批量场景
用户一次发多个 URL 时,统一列举判断结论而非逐篇评分。所有 URL 均不在 life 领域时,汇总说明并征求用户意见(路由 ~/wiki / 忽略 / 备用)。
评分流程
wiki-life-inbox-scan (本 cron)
├── 1. 扫描 raw/inbox/ 递归(rss/ + newsletter/ + wechat/,⚠️ 不是只 glob 顶层)
│
├── 2. URL/标题 blacklist 预检查
│ 扫描 raw/articles/ 的 source_url:/url: 构建黑名单
│ ⚠️ strip YAML 引号 + strip query params(?source=rss----xxx)+ normalize www./http↔https
│ 命中 → 跳过(已入库)
│
├── 3. RSS / WeChat inbox(文件已含完整正文)
│ <3KB → 跳过(摘要太短)
│ ≥3KB → life 红线快检(7 类)→ life 关键词预过滤 → LLM 评分
│ (RSS 文件已含正文,无需 Jina fetch)
│
│ ⚡ life 关键词预过滤(送 LLM 前的廉价过滤)
│ LIFE_KEYWORDS = ['自律','习惯','意志力','时间管理','精力','拖延','专注','心流',
│ '职业','面试','求职','简历','副业','晋升','离职','职场',
│ '焦虑','情绪','压力','正念','冥想','抑郁','认知行为','接纳承诺',
│ '沟通','非暴力沟通','冲突','亲密关系','婚姻','夫妻','家庭','育儿',
│ '决策','认知偏差','心智模型','学习','元认知','复利','思考',
│ '理财','投资','储蓄','财务自由','消费','保险',
│ 'grit','willpower','habit','procrastination','mindfulness','cbt','nvc',
│ 'decision','bias','mental-model','productivity','burnout','boundary']
│ 命中 ≥2 个关键词 → 送 LLM 评分
│ 命中 0-1 个 → 跳过(大概率非 life 焦点,如纯科技产品评测/时事)
│ ⚠️ 这是 domain relevance 的廉价近似,不是替代。通过预过滤的仍须做领域检查。
│
└── 4. Newsletter candidates.md(URL 列表,需 fetch)
blacklist 命中 → 跳过(已入库)
域名 blocklist 命中 → 跳过(见下方域名过滤)
URL 启发式命中(convertkit-mail4 重定向 / 营销 utm / 产品落地页)→ 跳过
QUICK_SKIP_PATTERNS 命中(播客链接/FSA 周报/Amazon 重定向/非 life 主题网站)→ 跳过
其他 → urllib Jina fetch(r.jina.ai)→ 内容 ≥2KB → 红线快检 → LLM 评分
ingest=true → 入库 → 从 candidates.md 精确删除该 URL
⚠️ blacklist 必须在 fetch 之前!
域名过滤(Newsletter)
低价值(直接跳过):convertkit-mail4.com(邮件追踪重定向,需先解 base64 再判断真实 URL;含大量营销落地页)、clickup.com/brain(产品广告)、x.com / twitter.com / youtube.com(社交媒体)、linkedin.com、各种 ?utm_* 纯营销落地页。
处理 convertkit 重定向:candidates.md 里大量 https://a4d65a79.click.convertkit-mail4.com/.../aHR0cHM6... 形式,尾部 base64 解码后才是真实 URL。脚本应解码 base64 提取真实 URL 再做域名判断。
高价值(直接抓取):fs.blog(Farnam Street)、calnewport.com、psyche.co、aeon.co、jamesclear.com、thedecisionlab.com、nesslabs.com、zapier.com/blog、nesslabs。
LLM 评分 API
主力:OpenCode Go(复用主 provider,无需额外 API 配置)
评分由 cron agent 自身完成。agent 运行在 OpenCode Go(deepseek-v4-flash)上,直接使用自己的 LLM 对文章评分,不需要额外 API key。
流程:
- agent 读取 inbox 文件全文(或 Jina fetch newsletter URL)
- 红线快检 → life 关键词预过滤 → 使用自身 LLM 按 5 维度评分
- 返回 JSON:
{"value":0-10, "confidence":0-10, "stars":1-5, "reason":"..."}
- v×c ≥ 45 + stars ≥ 3 → 入库
评分 prompt(life 5 维度):
你是个人成长内容评审。按以下标准评分(0-10):
- value: 对个人成长的价值(有论证/框架/边界/实践/批判性 中满足几维)
- confidence: 论证可信度(研究引用>逻辑推理>个人经验>纯断言)
- stars: 1-5(5=独特洞见框架,4=有效方法,3=有参考,2=浅,1=鸡汤/营销)
- reason: 一句话说明命中哪几维 + 是否触发红线
红线触发 → stars≤2 一票否决。
只返回 JSON:{"value":N,"confidence":N,"stars":N,"reason":"..."}
批量:5 篇/批。
响应解析:从 agent 自身 LLM 响应中提取 JSON,确保 value/confidence 在 0-10 范围。
兜底:Manual Heuristic(OpenCode Go 不可用时)
读前 4000 字符分类:
- 明显鸡汤/营销/标题党 →
v≤3,stars≤2 → reject
- life 关键词 ≥5 → 保守
v=7,c=7=49 → 倾向入库
- life 关键词 3-4 →
v=6,c=6=36 < 45 → 不通过(避免中文科技文章常见词专注/学习/决策的假阳性)
- life 关键词 1-2 →
v=5,c=6=30 → reject
- 无 life 关键词 → reject
记录
manual heuristic (LLM API unavailable)。不要因 API 不可用就阻塞整个 pipeline。自 2026-07-21 起:heuristic 收紧,≥5 关键词才给 v×c=49,防止 sspai 类中文科技文的误判。
入库流程
评分通过(v×c≥45 + 过领域检查)后:
- raw/articles/{slug}.md — 原文存档,frontmatter 加
type: source + ingested 日期 + 保留原 source_url/sha256。slug 从标题生成(lowercase-hyphens,中文保留)。
- entities/{slug}.md 或 concepts/{slug}.md — 合成页:
- frontmatter:title/created/updated/type/tags/sources(指向 raw)/confidence/review_value/review_confidence/review_stars/review_recommendation
- 中文正文 + 英文术语,每段 prose 末尾
^[raw/articles/slug.md] 引用(单源文末单一回链即可)
→ [[raw/articles/slug|原文存档]] 回链
- ⚠️ 写
[[entities/xxx]]/[[concepts/xxx]] 前先 ls 确认目标存在,不存在用纯文本反引号(避免 BROKEN LINK)
- type 选择:系统/方法论/人物 → entity;认知模型/心智工具 → concept;方法论对比 → comparison
- index.md — 加 entity/concept 条目(
- [[entities/slug|标题]] — 摘要)+ raw 条目(追加到末尾)。⚠️ 用 split+insert+join,每条独占一行,写后 grep -n slug index.md 验证。
- log.md — append
## [YYYY-MM-DD] ingest | {slug} + 评分 + 来源
- 清理 inbox — 删除已处理的 RSS/wechat inbox 文件(无论 ingest/reject/skip);candidates.md 精确删除所有已处理 URL(ingest + reject + skip,不只 ingest),写回。
- git commit — 显式路径
git add entities/X.md raw/articles/X.md index.md log.md(不要 git add -A,会扫入未处理文件);用 /usr/bin/git(subprocess PATH 缺 git);pre-commit hook 有 pre-existing error 时 --no-verify(先确认新文件 0 lint error)。
工程踩坑(精选,复用主 wiki inbox-screener 验证过的)
| 坑 | 规避 |
|---|
| inbox_scanner.py 只 glob 顶层 | 扫描必须 rglob("*.md") 递归 rss/newsletter/wechat 子目录。本 skill 的 score_life_inbox.py 已处理 |
| blacklist 漏检 RSS query param | URL 匹配前 url.split('?')[0].rstrip('/'),strip www.,normalize http↔https |
| blacklist 只搜 frontmatter 前 1000 字节 | 读至少 2000 字节 + 也搜 body 中的 source_url |
| candidates.md 只删 ingest 的 URL | 评分完成(无论 ingest/reject/skip)后,所有已处理 URL 都从 candidates.md 删除,否则下轮重复处理 |
git add -A 扫入未处理文件 | 始终显式路径 add;同进程多 inbox 文件时第 1 篇 commit 会带进第 2 篇 |
| subprocess 找不到 git | 用 /usr/bin/git 绝对路径 |
| execute_code 在 cron 被阻塞 | 用 write_file 写 .py 到 /tmp + terminal("python3 /tmp/x.py");或直接跑仓库内 scripts/score_life_inbox.py |
| MiniMax 2056 配额耗尽 | life wiki 直接用 DeepSeek,不依赖 MiniMax,规避此问题 |
| DeepSeek 返回 0-100 scale | 解析后 if value>10: value/=10 |
| DeepSeek batch reason 过长截断 | 含 reason 字段用 max_tokens=1500;无 reason 用 500 |
| index.md 条目拼接 | 用 split+insert+join;写后 grep -n slug index.md 验证独占一行 |
| wikilink 指向不存在页 | 写 [[entities/x]] 前 ls entities/ 确认;不存在用反引号纯文本 |
| 中文文件名空格 | shell 用 find -exec / xargs,不要直接 cp 包含空格的文件名 |
| import hashlib 缺失 | hashlib.sha256() 在 ingest() 中调用但未 import,首次运行即 NameError crash。hashlib 是标准库,cron 环境同样可用,在 import 行追加 hashlib 即可 |
| index 条目 entitys typo | update_index() 中 f-strings 拼接 {type_}s 对 type_=entity 产生 entitys/ 而非 entities/。修正:单独处理 entity 的 plural 形式 entities,其余加 s |
| Newsletter candidates 累积 50+ URL 耗时超标 | cron 5min 超时时,50 URL × 30s Jina fetch = 25min worst case。脚本现在有 QUICK_SKIP_PATTERNS 在 fetch 前跳过播客/周报/重定向/非 life 类 URL(命中率 ~60%),大幅缩短批处理时间。若仍超时,先手动预过滤 candidates.md 再跑脚本 |
主力脚本
scripts/score_life_inbox.py — 自包含评分入库脚本,cron 直接调用:
cd ~/wiki-life && source ~/.wiki-cron.env && /usr/bin/python3 ~/.hermes/skills/wiki-life/life-screener/scripts/score_life_inbox.py
脚本完成:扫描递归 → blacklist → 红线快检 → 关键词预过滤 → DeepSeek 评分 → 领域检查 → 入库 → 清理 inbox → git commit。agent 处理脚本无法覆盖的边缘情况(API 全挂、fetch 全失败)时参考本 skill 的兜底逻辑。
⚠️ 脚本输出后必须修复的 4 个问题
score_life_inbox.py 的 entity 生成是裸模板:title=URL、正文仅复制 raw 第一行。每次脚本完成后 agent 必须做以下修复:
-
修复 entity title — 将 frontmatter title: "URL" 改为有意义的中文/英文标题;H1 同理
-
改进 entity 内容 — 将空白「核心要点」替换为真正合成:提炼框架、对比表、关键要点,每段加 ^[raw/...] 引用(单源文末单一回链即可)。目标 size ≥2KB
-
移动 entity 条目到 index.md 正确位置 — 脚本将 entity 条目插入在 ## Core Areas (MOCs) 的「职业发展」小节中间,破坏当前子 MOC 的列表完整性。life wiki 的 index.md 没有 ## Sources / ## Entities 分段,独立 entity 条目应放在文件末尾(与其他 standalone entry 并列),而不是插在 MOC 小节内。移动步骤:
lines = [l for l in lines if 'slug' not in l]
lines.append('- [[entities/slug|标题]] — 摘要\n')
操作后 grep -n "slug" index.md 确认实体条目只出现在文件末尾。
-
验证 index.md raw 条目 — 脚本可能漏加 raw source 条目。运行 grep -n "<slug>" index.md,确认 entity 条目 + raw 条目各 1 行、各占独立一行。缺少 → 追加行到文件末尾;注意文件最后一行可能无 \n 导致拼接(见下方「拼接修复」)。更新 header Total pages + Sources 计数。
Stats 不一致诊断(2026-08-06 实战):脚本输出出现 [WARN] index.md 条目验证失败: <slug> 时,raw 条目几乎肯定没写进 index.md(验证失败即 grep 不到)。此时 Stats 的签名是 Total pages +2、Entities +1、但 Sources 不变 —— 脚本把 raw 算进了 Total pages,却没插入 raw 条目也没 bump Sources。修复:grep 确认 raw 缺失 → 追加 raw 条目到文件末尾 → 只把 **Sources**: N 加 1。Total pages 已是正确值,不要按"+2/+1/+1"全覆盖(那是理想情况),否则 Total pages 会多 1 变成 54。
拼接修复:life wiki 的 index.md 最后一行不一定有 trailing \n。用 Python lines.append(entry) 时,需要确保前一行已 \n 结尾:
if lines and not lines[-1].endswith('\n'):
lines[-1] = lines[-1] + '\n'
lines.append(raw_entry)
如果忘了做,grep 会发现两条条目在同一行——用 Python content.replace('来源- [[raw/articles/', '来源\n- [[raw/articles/') 修复。
life wiki index header 格式:header 位置在 ## Stats section,格式为多计数器同一行:
- **Total pages**: N
- **Entities**: M | **Concepts**: P | **Comparisons**: Q | **Cases**: R | **Queries**: S | **Sources**: T | **Reviews**: U
- **Last updated**: YYYY-MM-DD
⚠️ **Sources**: N 与其他计数器在同一行,不是独立一行。以下方法会失败(前面没有 - 前缀):
content.replace("- **Sources**: 11", "- **Sources**: 12")
正确做法:
content = content.replace("**Sources**: 11", "**Sources**: 12")
content = content.replace(
"- **Entities**: 12 | **Concepts**: 4 | **Comparisons**: 5 | **Cases**: 6 | **Queries**: 7 | **Sources**: 11 | **Reviews**: 2",
"- **Entities**: 13 | **Concepts**: 4 | **Comparisons**: 5 | **Cases**: 6 | **Queries**: 7 | **Sources**: 12 | **Reviews**: 2"
)
同时更新 **Last updated**: 日期:
content = content.replace(
"**Last updated**: 2026-07-09",
"**Last updated**: 2026-07-27"
)
Verification(header 更新后立刻检查):
cd ~/wiki-life && head -10 index.md
⚠️ Stats 行 label 带 ** 包裹,regex 必须匹配 **(2026-07-31 实战):行格式是 - **Total pages**: 49,label 在 **...** 内。re.sub(r"(Total pages):\s*(\d+)", ...) 不匹配(** 位于 label 与冒号之间)——必须 re.sub(r"(\*\*?Total pages\*\*?):\s*(\d+)", ...)。新入库 entity+raw 时 Total pages +2(entity +1 + raw source +1)、Entities +1、Sources +1。score_life_inbox.py 的 Stats regex 已于 2026-07-31 修复(原 regex 对 ** 格式完全不匹配,Stats 从不更新,需 agent 手动补)。编辑 index.md 后 grep -n "^|- " index.md 检查 |- 前缀损坏(本库无 linter,全靠手动 grep 验证)。
life wiki 没有 linter:与 ~/wiki(技术库)不同,~/wiki-life 目录下没有 wiki-lint.mjs。验证完全依赖手动 grep:grep -n "slug" index.md 确认格式正确、无拼接。
修复后建议重新 commit:用 git commit --amend 或新 commit,确保 entity 有合成价值而非纯 URL 拷贝。
跨库路由到 ~/wiki(用户同意后)
当用户同意将判定为 tech 的文章路由到 ~/wiki 时,直接走手动加工程序:
-
获取全文 — 使用 browser_navigate + browser_console(document.body.innerText) 抓取完整正文(Jina fetch 在 WeChat URL 常超时,浏览器更可靠)
-
评分并入库(实用模式):
- 使用
delegate_task 并行处理多篇文章(上限 3 并发),每篇一个子 agent
- 子 agent 读 ~/.wiki-cron.env 中 DEEPSEEK_API_KEY,调用 DeepSeek API 评分
- 评分 prompt 用 AI/ML 技术维度(非 life 维度):技术深度、独特洞察、引用/数据、框架实用性、批判性
- 阈值:v×c ≥ 49(技术库门槛,比 life 的 45 高)
- 通过后:写 raw/articles/(frontmatter + 全文)→ 可选 entity/concept → 更新 index.md → 更新 log.md → git commit
-
Git commit 注意事项:
- 显式路径
git add raw/articles/X.md entities/X.md index.md log.md
- 用
/usr/bin/git 绝对路径
- pre-commit hook 有 pre-existing error 时
--no-verify
-
子 agent 输出验证:子 agent 自报的结果可能不准确。收到 summary 后检查:
- commit 是否存在:
cd ~/wiki && git log --oneline -5
- entity 文件是否合理:
cat ~/wiki/entities/<slug>.md | head -20
-
跨库路由的典型场景:
- 用户从 wechat 发来多篇技术文章 URL(阿里云开发者、Hyman的杂货铺等),会话上下文在 wiki-life 目录
- 用户确认 "转投 ~/wiki" 后执行本流程
报告输出规则
- ✅ 新入库文章(标题 + slug + v×c 分数 + commit hash)
- ✅ 真正错误(API 失败、脚本崩溃、文件损坏)
- ✅ 无新内容/无入库 →
[SILENT](抑制投递)
- ❌ 不报 DeepSeek provider 细节(内部实现)