作者:互联网 时间: 2026-07-29 08:46:07
前两篇讨论了 LLM 调用过多与 subagent 切换成本过高,效率专题的第三个问题则来自工具入口:用户若每次仍需判断运行 lint、trigger 还是 check,系统使用起来就不够顺手。
sentry-static 的入口收敛并非只是减少一个命令名,而是用稳定入口承接用户一次完整的静态分析意图。本文的原则是按照用户意图划定工具边界,而非依据内部检查项划分。
| 版本 | 工具形态 | 用户操作 |
|---|---|---|
| v5.x-v6.x | sentry-lint + sentry-trigger(两个独立工具) | 说两次、跑两次、看两份报告 |
| v7.1 | sentry-check(两者合并) | 说一次、跑一次、看一份报告(含两部分) |
| 稳定形态 | sentry-static(Lint + Trigger + Summary + 后续检查组) | 发布建议随一份报告呈现:一次说明、一次运行、一次查看 |
看起来只是名称调整、入口合并与检查维度增加,实际上每次形态变化背后都对应一个工程决策点。
lint 与 trigger 在 v6.x 里互不隶属,完全是两个工具:
sentry-lint→ 静态结构检查,~30ssentry-trigger → 触发率 AI 模拟(TP/TN),~2min
实际使用暴露出三个问题:
1. 几乎无人只运行其中一个
内部统计的依据,是对真实测评中 20+ 次调用模式所作的复盘:
用户在 92% 的时间里只有「帮我看看这个 Skill 写得好不好」这一个意图,却要面对两次 spawn、两次 yield/resume 和两份回执,因为工具共有两个。
2. 报告彼此割裂,用户必须自行建立关联
「TN 不触发率只有 40%」出现在 trigger 报告中;「description 太短,缺少不触发场景」则是 lint 报告的结论。
两个结论具有因果联系:description 没有描述「不触发场景」,使 AI 判断是否触发时缺乏足够的排除信号;然而,用户无法从两份独立报告中看到这种关联。
3. 编排器要用额外逻辑确定执行顺序
如果 description 根本不存在,运行 trigger 没有意义,因此主编排器要把 lint 放在前面,再执行 trigger。编排器的复杂度由这种「条件跳过 + 先后依赖」逻辑推高。
sentry-check:Part 1: 静态检查,~30sPart 2: 触发率评估(TP/TN),~2min支持子模式:lint <Skill名>→ 只跑 Part 1测触发率 <Skill名> → 只跑 Part 2check <Skill名> → 两项都跑
向后兼容——旧的 lint 和 测触发率 命令继续有效。
合并判断标准是:两个工具在 >80% 的调用场景中总是共同出现,而且输入一致(都读取 SKILL.md),通常就应该合并。
用户在 v7.1 的 sentry-check 中看到的是以下内容,而它的本质仅是拼合两个工具的输出:
## Part 1 · 静态检查L1: ✅ / ⚠️ / ...L2: ...L3: ...L4: ...L5: ...## Part 2 · 触发率评估TP: 80%TN: 67%
然后用户自己判断:「L1 说 description 没问题,但 TN 只有 67%,说明不触发场景虽然有,但写得不够精准。」
问题是,这项推理本应由工具自动完成。
sentry-static:Sub-step 1: Lint(静态规则检查)Sub-step 2: Trigger(TP/TN 触发率评估)Sub-step 3: Summary(交叉分析 + 综合发布建议)
Sub-step 3 的逻辑:
| Lint 信号 | Trigger 信号 | 综合建议 |
|---|---|---|
| L1 description 完整 | TP ≥ 80%, TN ≥ 80% | ✅ 静态检查通过,建议进入测评 |
| L1 description 完整 | TP ≥ 80%, TN < 80% | ⚠️ 触发精度不足:补充不触发场景描述 |
| L1 description 不完整 | TP < 80% | ❌ 先补足 description 信息再测试,这是问题根源 |
| L2 缺少 HiL | — | ❌ 安全问题:不可逆操作必须加确认节点 |
| L3 复杂度 > 20 | — | ⚠️ 建议拆分,否则执行稳定性难保证 |
核心变化是由「提供两组数据」转为「给出一个判断 + 理由」。两份报告之间的关联由工具完成,用户无需自行处理。
sentry-check 的含义是「检查」,暗示输出由多项检查结果构成。sentry-static 输出被暗示为分析结论,因为其语义指向「静态分析」。
工具定位从「数据展示」转向「分析判断」,名称变化正是这一转变的体现。
在当前实现中,原 sentry-check 属于兼容入口,并非推荐入口:
# sentry-check(兼容入口)此工具已被 sentry-static 替代。如果你是通过旧命令到达这里,请改用 sentry-static。所有旧命令仍然有效:- lint <Skill名> → sentry-static --lint-only- 测触发率 <Skill名> → sentry-static --trigger-only- check <Skill名> → sentry-static(完整模式)
为什么保留兼容入口而不直接删除?因为用户(和 AI 编排器)可能对 sentry-check 有肌肉记忆。兼容入口起到重定向作用,零成本地处理旧路径。
入口合并不等于放弃精细控制:
sentry-static --lint-only → 只跑 Sub-step 1(~30s)sentry-static --trigger-only→ 只跑 Sub-step 2(~2min)sentry-static → 三步全跑(~2.5min)
保留独立模式的场景:
一套判断标准,来自我对 sentry-lint/trigger → sentry-check → sentry-static 这段演进的总结:
| 信号 | 强度 |
|---|---|
| >80% 调用场景里一起使用 | 强信号 |
| 输入完全相同(同一份文件) | 强信号 |
| 输出之间存在因果联系,需要交叉分析 | 强信号 |
| spawn/yield 可在合并后少执行 1 次 | 中信号 |
| 用户无法区分两个工具 | 弱信号 |
| 信号 | 强度 |
|---|---|
| 执行时间差异 >10x | 强信号 |
| 其中一个失败不应妨碍另一个执行 | 强信号 |
| 输入来自不同来源 | 中信号 |
| 所需权限不同 | 中信号 |
| 复用场景完全不同(由不同上游调用) | 弱信号 |
为什么 sentry-static 和 cases 步骤不合并?
三个拆分信号全部命中,因此不合并才是正确选择。
状态机阶段 Pipeline 的设计因 sentry-static 被引入而产生一个关键影响:
Pipeline 数组的第一步由 check 调整为 static:
// v7.x(非正式 pipeline)["check", "cases", "executor", "grader", "report"]// 状态机阶段+ 正式 Pipeline["static", "cases", "sync-pull", "sync-push-cases", "executor-with", "grader", "sync-push-results", "report", "publish"]
状态机只认 Pipeline 数组里的 step name。当工具改名时,Pipeline 数组必须同步更新。这就是为什么当前主流程只写 static,不再把 lint、trigger、check 写成正式 pipeline step。
从 v5.x 走向稳定形态,SkillSentry 的工具经历了如下演进:
v5.x: 5 个独立工具(lint, trigger, cases, executor, grader)v6.x: 5 个 + sync + report = 7 个v7.1: 合并 → check + cases + executor + grader + report = 5 个状态机阶段: 重组 → static + cases + executor + grader(含report) + report(独立)+ comparator + analyzer + openclaw = 8 个稳定形态: 收敛 → static 是推荐入口;grader-report 是主流程评分报告;sentry-report 仅用于已有 grading 后独立重出报告
工具数量不是越少越好,也不是越多越好。判断标准是:每个工具对应一个「用户意图的最小完整单元」。
「意图完整」与「原子可组合」之间的平衡点,构成了最终形态。
“用户只需要记一个静态分析入口”是入口收敛所解决的问题:后续检查组以及 Summary、Trigger、Lint 都纳入 sentry-static。这个稳定入口内部增加了 L6 这一检查维度,并未产生新增入口;它要回答的,是更基础的 SKILL.md 结构完整性问题。
一个真实案例是:某个 Skill 虽通过 L1-L5 全部检查,新人接手后却完全不清楚它解决的问题、依赖的环境变量、输入输出格式以及覆盖或不覆盖的场景。这些内容属于“结构”而非“规则”,决定 Skill 能否被团队理解与维护。
一份标准 SKILL.md 需要以《MIT AI Skill 撰写规范 V1.1-beta》为对照,覆盖的章节共有 13 个,各自用于回答一个实际问题:
| 章节 | 对应的实际问题 |
|---|---|
| 问题描述 | 新人不理解这个 Skill 存在的原因 |
| 触发场景 | AI 不清楚应在何时激活 |
| 交互契约 | Agent 可能擅自执行危险操作 |
| 架构概览 | 维护者不清楚修改哪个文件会产生什么影响 |
| 端到端示例 | 开发者不了解“跑一次”的具体形态 |
| 输入/输出契约 | 集成方不清楚传入与接收的内容 |
| 健壮性能力 | 无人了解失败后会发生什么 |
| 限制与边界 | 用户误以为它无所不能 |
每缺少一个章节,就会增加一个“凭感觉”处理的环节。
L6a:Frontmatter 9 字段——name、display_name、version、description、author、track、platform、spec、tags。缺 name/version 会影响 CI 缓存命中(sentry_preflight.py 用 name + hash 判断复用)。
L6b:13 章节覆盖率——逐项确认是否包含对应内容,判断依据是实质内容而非标题:
L6c:合规度评级:
≥ 90% → ✅ 合规70-89% → ⚠️ 基本合规50-69% → ⚠️ 部分合规< 50% → ❌ 不合规
L6 不替代 L1-L5。一个 Skill 可以 L1-L5 全绿但 L6 只有 35%——能跑,但别人接不住。反过来 L6 100% 但 L2 红(写操作没确认),也不能发布。六组一起看才是完整的静态质量画像。
结构化诊断产物或报告可以记录 L6 评级,但 PASS/FAIL 不由它否决。发布决策者可把这项参考指标用于判断“这个 Skill 是否已经准备好交给别人用”。如果已有 Skill 能正常工作,就不能仅凭“文档不全”将其卡住。
Q:AI 判断的不确定性会因 sentry-static 的 Sub-step 3 而出现吗?
Sub-step 3 采用规则化判断逻辑,以静态检查项及 TP/TN 数值阈值为依据,并非让 AI 自由判断。AI 只生成自然语言解释,判断结果本身具有确定性。
Q:迁移工作从 sentry-check 转向 sentry-static 时涉及哪些改动?
用户侧:将推荐入口统一为 sentry-static。lint、测触发率、check 此类旧说法仍可兼容或重定向,但不再被推荐为正式入口。
Pipeline 侧:自定义 pipeline 配置如果存在,需要调整其中的 step name,把原名称从 check 修改为 static 即可。
Q:兼容入口是否会永久保留?
兼容入口目前仍然保留。删除与否要由日志中是否存在旧命令调用来决定,不能只凭版本号;调用只要尚未消失,重定向就须继续保留,文档也应标明目前推荐的入口为 sentry-static。
sentry-static 设计文档、历史 sentry-check/SKILL.md、SkillSentry contract 为资料来源。