last30days v3.0.9「Self-Debug Release」技术解读引擎拒绝门、跨平台顶级热评与多 Harness 部署【免费下载链接】last30days-skillAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary项目地址: https://gitcode.com/GitHub_Trending/la/last30days-skill导读本文围绕仓库中的历史发布说明 docs/releases/v3.0.9.md 展开解读 last30days 这款「跨 Reddit、X、YouTube、HN、Polymarket 与 Web 的 30 天话题研究 Agent Skill」在 v3.0.9 这一次被命名为The Self-Debug Release的版本中做了什么。你将看到三个可复用的关键能力①引擎如何在「40 岁生日礼物」这类人口统计式购物查询上主动拒绝并反问问清上下文对应今天的 skills/last30days/scripts/lib/preflight.py 源码②TikTok/YouTube 顶级热评如何获得与 Reddit 同等的渲染地位③一种「让模型自己调试自己的输出违约」的工程方法以及该版本把部署面扩张到 Hermes、Windows、claude.ai、Codex CLI 等多个宿主平台的全部细节。说明docs/releases/v3.0.9.md是一份历史版本发布说明。仓库主线此后持续迭代聚合 CHANGELOG.md 目前顶部版本已远高于 v3.0.9但本文所有实现证据均来自当前仓库中仍然存在、可核验的文件与代码。版本概览一次由「五个 Opus 自己给自己找病根」驱动的发布发布说明在 Highlights 里给出了两个核心结论头号修复引擎对birthday gift for 40 year old这类查询不再埋头跑 5 分钟垃圾检索而是先抛出一个澄清问题头号功能TikTok 与 YouTube 的顶级评论现在与 Reddit 一样以第一等的醒目程度渲染进最终综述。而「Self-Debug自我调试」这个标签指的是v3.0.9 的修复方式是让 5 个彼此独立的 Opus 4.7 实例分别拿到自己先前失败v3.0.7 / v3.0.8的输出然后自己调试自己。结果是其中3 个收敛到同一诊断SKILL.md体积太大、VOICE CONTRACT 里的 LAWs 放得太深模型根本读不到一个实例甚至明确说试图 Read 时撞上 25K token 上限就放弃了而不是分块读完其中2 个收敛到同一条建议引擎应当直接拒绝人口统计式购物查询而不是指望模型自觉遵守另有 2 个指出WebSearch 工具自带的「Sources: 必须」提示在优先级上压过了 LAW 1导致输出尾巴上反复泄漏无关来源列表。作者把这些诊断原样变成代码I copy-pasted their diagnoses into code最终在先前失败的话题上拿到5/5 规范合规。这条叙事与聚合版 CHANGELOG.md 中 v3.0.9 条目的记录一致发布说明还额外给出了当时出现的0/8 公共回归连续 8 次调用 Opus 把 Skill 当成通用关键词即兴发挥、违反 LAW 2/LAW 4作为背景——Self-Debug 正是对这 0/8 的回应。引擎侧 Class 1 拒绝门把「不该跑」变成代码而不是措辞为什么需要一道硬拒绝门发布说明给出了核心推理birthday gift for 40 year old这类人口统计式购物字面短语并不是 Reddit、X、TikTok 上真实礼物讨论会使用的词汇。让引擎照常检索返回的只会是低信号、泛泛而谈的内容——文档记录了一次真实失败2026-04-18 的验证运行最终返回的是r/todayilearned与一批无关 drama 帖子。与其继续在 SKILL.md 里用越来越重的措辞约束托管模型「别去跑这类查询」v3.0.9 选择在引擎前端物理拦截由两个 Opus 实例共同给出的「engine should refuse demographic-shopping queries outright」诊断被实现为一个新的前端模块。实现preflight.py 与 main() 前门的配合当前仓库中该模块仍在即 skills/last30days/scripts/lib/preflight.py。其模块 docstring 明确写着检测 Class 1人口统计式购物关键词陷阱并返回结构化 REFUSE 消息调用方在 skills/last30days/scripts/last30days.py 的 main() 入口把消息写到 stderr 并以退出码 2结束一条注定失败的查询不会触发任何 pipeline 工作。模式注释说明这套规则来自 SKILL.md Step 0.45 的散文描述且「只有 Class 1 被实现因为只有它在 v3.0.8 有被验证过的失败模式」。代码层面拦截逻辑分两类模式_CLASS_1_PATTERNS与_QUALIFIER_PATTERNS类别匹配目标正则语义非完整字面效果Class 1 命中拒绝候选以(birthday)? gift(s)/present(s) for N-year-old、best/top … for men/women/kids/teens/dads/moms/husbands/wives/brothers/sisters/friends、what to buy/get/gift for …、gift(s)/present(s) for 丈夫/父亲/朋友/老板…等开头的查询触发check_class_1_trap()的拒绝逻辑限定词放行候选含$金额、budget、who loves/likes/is into/enjoys、hobbies或N-year-old 兴趣名词如year old runner只要该名词不是关系称谓视为用户已补齐上下文跳过拒绝门放行_RELATIONSHIP_WORDShusband/wife/dad/mom/brother/sister/friend/boss/coworker/son/daughter/grandma…的存在是为了区分两种情况year old runner是兴趣、可放行year old husband只是把人口统计式购物换了个说法仍然拒绝。调用点确认于 skills/last30days/scripts/last30days.py#L3356-L3361if not os.environ.get(LAST30DAYS_SKIP_PREFLIGHT): from lib import preflight refuse_msg preflight.check_class_1_trap(topic) if refuse_msg: sys.stderr.write(refuse_msg) return 2即只有显式设置LAST30DAYS_SKIP_PREFLIGHT1时拒绝门才被绕过其余情况命中即写 stderr 并return 2。REFUSE 消息内容与冒烟测试命中后写给 stderr 的结构化消息preflight.py 中_refuse_message()生成包含三部分说明该查询命中 Class 1 模式、为何引擎跑它会产出低信号内容引用 2026-04-18 返回r/todayilearned的实证提示托管模型向用户追问至少一项上下文hobbiescooks / runs / reads / gaming / outdoors / golf / music、relationshiphusband / dad / friend / boss / brother、budget range给出两条出路用户补齐信息后以丰富化查询重跑或用户坚持「直接跑」则以LAST30DAYS_SKIP_PREFLIGHT1显式绕过。发布说明中的冒烟测试正是围绕它设计的执行/last30days birthday gift for 40 year old应当先抛出澄清问题而不是启动引擎如果引擎照常运行说明本地插件缓存是旧的需要重复一次/plugin update。这一行为在当前仓库的 tests/test_preflight.py 中有成体系的回归覆盖围绕正向命中、带限定词放行、空 topic 等场景保证「拒绝门」这个结构约束不会在后续迭代中被悄悄放松。顶级热评成为一等公民从 Reddit 推广到 TikTok 与 YouTube发布说明把「TikTok 和 YouTube 的顶级评论现在和 Reddit 一样渲染」称为v3.0.0 以来最大的一次用户可见输出变化。溯源链路是社区最初推动的是 Reddit 富评论PR #143 的原始推动——它种下了「 Top comment醒目处理」这个模式PR #260 把这个模式泛化到每个 TikTok 视频与 YouTube 视频上各自取互动最高的那条评论获得与 Reddit 顶级评论相同的视觉地位PR #265 紧随其后修复了 ScrapeCreators 的url参数与 YouTube 评论/字幕的新响应结构否则富集根本不会真正生效——这正是「功能 修管道」成对发布的典型样板。从当前仓库的渲染层可以印证这套输出契约确实存在skills/last30days/scripts/lib/render.py 在紧凑渲染的证据区对Reddit、YouTube、TikTok、HackerNews统一消费item.metadata[top_comments]输出形如Top comment {attribution}{vote_part}: {截断到 200 字符的评论摘录}见 render.py#L1860-L1876。也就是说最受讨论的声音必须进入综述这条产品原则在 v3.0.9 从单一 Reddit 来源扩展为所有支持评论富集的主流来源。配套输出契约BADGE 前置与 END-OF-CANONICAL-OUTPUT顶级评论是输出内容的一等公民而输出本身的规范化则是同一枚硬币的另一面。Self-Debug 的三个 Opus 实例都指出「LAWs 放得太深、SKILL.md 太大」于是 v3.0.9 做了结构性搬迁OUTPUT CONTRACTBADGE LAWS从第 1094 行附近移到文件顶部。这一改动在当前仓库的 skills/last30days/SKILL.md 中依然可见——文件在开篇约 98-113 行就放置了 SKILL CONTRACT 与 OUTPUT CONTRACT并明确警告模型不要把/last30days当成可以即兴发挥的通用检索关键词。同时引擎侧由渲染层保证每段输出以规范徽标开头render_compact的第一行输出是 last30days v{version} · synced {today}见 render.py#L71-L75并新增END-OF-CANONICAL-OUTPUT 边界——聚合 CHANGELOG 称之为要求二次合成必须先主动无视一个可见边界才能继续把不得追加多余 Sources 尾巴从一句建议变成引擎产物的物理边界。针对WebSearch 工具自带的 MANDATORY Sources 提醒覆盖了 LAW 1的诊断LAW 1 现在直接引用那条提醒的原话并在 last30days 输出域内声明其已被 OVERRIDE。部署面的一次大扩张六个宿主平台与更多首装路径v3.0.9 一个被低估的主题是表面面积扩张Skill 从Claude Code 专用走向Claude Code、Codex、Hermes、Gemini、claude.ai、OpenClaw 都能跑。逐条拆解Hermes AI Agent 成为一等部署目标PR #228scripts/sync.sh会检测~/.hermes/skills/research并把完整 SkillSKILL.md、scripts、lib 模块、fixtures同步进 Hermes 的技能目录与 Claude Code / Codex 并列。同步分支统一使用根目录 SKILL.md修掉了此前.hermes-plugin/SKILL.md回退造成的读到错文件隐患。Windows 原生可用PR #227 #225PR #227 稳定了内置的 Bird X 搜索客户端在 Windows 终端上的运行时问题PR #225 修复了保存输出的 UTF-8 编码两者叠加后Windows 用户无需变通即可获得完整 v3 体验。Linux 权限检查停止误报PR #216check_perms此前固定调用 BSD 风格stat导致 Linux 上已经正确 chmod 600 的.env仍收到虚假的权限告警。修复为优先使用 GNUstat语法让检查与实际文件权限一致。claude.ai 直接安装PR #242 / #244新增scripts/build-skill.sh配合.gitattributes的export-ignore管道把 Skill 打包成可上传 claude.ai 的.skill文件文件数上限 200。注意这与Claude Code/plugin install拉取同一份 git archive曾经互相踩踏——v3.0.1/v3.0.2 曾因.gitattributes把skills/与插件清单一起排除出 tarball 而导致安装包损坏v3.0.3 回退后才恢复。这个版本的历史教训值得后来者在调整打包排除规则时反复核对。OpenAI Codex CLI 原生发现PR #219.agents/skills/last30days/SKILL.md以真实文件而非符号链接Codex 的加载器会跳过 symlink存在配合.codex-plugin/plugin.json作为命名空间标记使 Skill 在 Codex 于仓库目录内运行时以last30days:last30days注册。当前仓库根目录下仍可找到 .claude-plugin/plugin.json 与 .codex-plugin/plugin.json 等插件清单。/last30days斜杠命令PR #267插件用户直接键入/last30days topicClaude Code 的自动补全会前缀匹配到规范的/last30days:last30days双命名空间形式——不必再手打完整命名空间。配置默认值与版本元数据对齐INCLUDE_SOURCES从未设置改为默认空字符串PR #223新安装缺环境变量不再导致来源包含逻辑出错SKILL.md 版本头与同步目标版本对齐PR #217再关闭 SKILL.md 头与 plugin.json 之间残留的漂移PR #229——我到底装在哪个版本上不再靠猜。稳定性与贡献者基建一次不性感但防止六个月后六份 bug 报告的扫尾发布说明特意点明了一批不显眼但关键的可靠性/基建改动多密钥 SCRAPECREATORS_API_KEY 轮换PR #268设置SCRAPECREATORS_API_KEY_1、SCRAPECREATORS_API_KEY_2… 后密钥撞上速率限制时引擎自动轮换而不是整次运行失败。对每天跑查询的重度用户这是429 随机出现与零接触可靠之间的差别。注聚合 CHANGELOG 也记载了更早版本曾误删多密钥轮换、之后又恢复的历史v3.3.0 条目Restored multi-key rotation… via random.choice per run说明这条能力是社区反复守护的契约之一。Reddit HTTP 层重构PR #207/#208/#209统一为http.get(params...)助手、让_parse_date干净地拒绝垃圾输入、把_sc_headers收敛为http.scrapecreators_headers。当前仓库可以同时看到这两处落点http.py#L880-L882 的get()与 http.py#L1222-L1225 的scrapecreators_headers()返回x-api-key JSON Content-Type 头。发布说明的评价很实在这类 PR 防止的是未来六个 bug 报告。Bird X 互动字典硬化PR #234bird_x遇到全None的 engagement 字典时改为跳过而不是崩溃。当前仓库 bird_x.py#L729-L753 中可以看到这段防御逐字段尝试转 int、转不动则置None最后engagement if any(v is not None for v in engagement.values()) else None——互动数据全部为空的极端情况不再杀死整个运行。离线质量评估PR #233新增 fixtures/eval_topics.json 作为评估夹具。文件里是一组带query_typecomparison / how_to / breaking_news / product / opinion / prediction / concept / factual与rationale的话题清单例如 best budget noise cancelling headphones 2026product、odds of US recession 2026prediction。贡献者与维护者可以用它在不烧线上 API 额度的前提下对综述质量做回归检查——文档明确指出正是这套夹具让每次发布都验证 5/5 规范合规变得在财务上可行。兼容性守护PR #230恢复遗留--days别名的向后兼容任何在 2.x 时代已针对它写脚本的用户升级到 v3 不会断。仓库卫生PR #232.venv、.coverage、htmlcov、.memsearch移出跟踪树保持 PR diff 干净。社区致谢的范围发布说明还单列了两张感谢名单一张是 v3.0.0 以来的 PR 作者j-sperling、stephenmcconnachie、zaydiscold、iliaal、Chelebii、george231224、Gujiassh、hnshah、shalomma、BryanTegomoh 等另一张是塑造 v3 功能集的 roadmap 贡献者uppinote20 的富评论、zerone0x 的 GitHub 来源、thinkun 的 Reddit 富集超时、thomasmktong 的纯 Python Reddit 回退、zl190 的 HN 趋势合并等以及那 5 个自我调试的 Opus 4.7 实例。升级、验证与冒烟测试发布说明为使用者提供了完整的操作路径以下命令按 v3.0.9 时代的 Claude Code 插件工作流原样给出若仓库主线已升级插件实际安装的版本以官方 marketplace 为准全新安装/plugin marketplace add mvanhorn/last30days-skill /plugin install last30dayslast30days-skill已安装则更新/plugin update last30days /reload-plugins验证版本应输出version: 3.0.9cat ~/.claude/plugins/cache/last30days-skill/last30days/*/.claude-plugin/plugin.json | grep version冒烟测试/last30days birthday gift for 40 year old预期行为先抛出澄清问题再决定是否运行。若引擎仍然照常跑了说明本地缓存是旧的——重复一次插件更新。把这条冒烟测试与上面 preflight.py 的代码对照看就能完整理解结构约束引擎拒绝 措辞约束SKILL.md 提示这句话在这个项目里的含义。回到方法论当编排下的 LLM 反复违约去问它为什么v3.0.9 最值得被搬运到别的项目的东西不是任何单个修复而是发布说明末尾那套自调试问答——作者没有去猜模型为什么无视规则而是把失败输出交给模型自己审你读 SKILL.md 了吗 → 我试着 Read撞上 25K token 上限就放弃了而不是分块读完。为什么尾巴上多出 Sources 块 → WebSearch 工具自己的提醒写着 MANDATORY优先级不清楚。为什么冒出自拟章节标题 → 我对 Peter Steinberger 有很强的先验直接写了篇小论文而不是透传证据。为什么读了错误的文件 → path glob里先出现了.agents/skills/last30days/SKILL.md。五个实例中三个说把 LAWs 移到顶部两个说让引擎强制让模型想不遵守都不行。作者两个都做了。完整的手法就是一句话当受编排的 LLM 持续破坏契约时不要跟它争辩——让它调试自己然后把它们点名的根因转写成结构性的强制约束代码门、可见边界、文件搬迁、输出徽标。这既解释了本发布说明中拒绝门与 BADGE 前置的由来也是当前仓库 skills/last30days/SKILL.md 里那些反向指着失败模式说话的契约段落的共同设计逻辑。【免费下载链接】last30days-skillAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary项目地址: https://gitcode.com/GitHub_Trending/la/last30days-skill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考