Agent-almanac monitor-binary-version-baselines

install
source · Clone the upstream repo
git clone https://github.com/pjt222/agent-almanac
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/zh-CN/skills/monitor-binary-version-baselines" ~/.claude/skills/pjt222-agent-almanac-monitor-binary-version-baselines-fae295 && rm -rf "$T"
manifest: i18n/zh-CN/skills/monitor-binary-version-baselines/SKILL.md
source content

监控二进制版本基线

为 CLI 测试台二进制中的特性系统标记建立可比较的、以版本为键的记录,让新增、移除与暗启动能力能够在跨版本间被机械化地检测出来。

何时使用

  • 在一个闭源 CLI 测试台的多个发布之间追踪某项特性的生命周期
  • 探测暗启动的能力(已发货但被闸门关闭)或悄然移除的能力
  • 验证标记扫描器仍能在旧二进制上检出已知良好的标记(对扫描器自身做回归测试)
  • 构建第 1 阶段的底座,供后续阶段(标志位发现、暗启动检测、线路抓包)消费
  • 任何临时用
    grep
    只能回答"X 今天在不在",而你真正需要的是"由 X、Y、Z 组成的系统如何在版本间演进"的场景

输入

  • 必需:同一个 CLI 测试台的一个或多个已安装二进制版本(或抽取出的打包产物)
  • 必需:一个工作中的目录文件,用于存放标记定义(首次运行时创建,跨版本逐步扩展)
  • 可选:来自先前运行的已记录基线文件(就地扩展,绝不重写)
  • 可选:已知从未发布的版本清单(被跳过的发布、被撤回的构建)
  • 可选:已经在追踪中的特性系统清单,用于扩展而不是重新发现

步骤

步骤 1:按类别选择标记

选择能在重新构建中幸存的字符串。挑选稳定、语义上有意义的标识符 — 不要挑选打包器在下个版本就会重命名的压缩名。

推荐的六个类别:

  • API — 端点路径、测试台网络表面暴露的方法名
  • 身份(Identity) — 内部产品名、代号、版本哨兵
  • 配置(Config) — 面向用户的配置文件中被识别的键
  • 遥测(Telemetry) — 发送到分析管道的事件名
  • 标志(Flag) — 被闸门谓词消费的特性闸门键
  • 函数(Function) — 特定处理器内部使用的著名字符串常量(错误消息、日志标签)

避免:看起来像被压缩过的短标识符(例如

_a1
bX
、两个字母后跟数字)、任何一次文本修订就会改变的内联字面量,以及任何匹配打包器自身内部命名惯例的字符串。

预期: 每个候选标记都带有一个类别标签和一段简短的理由说明("出现在面向用户的文档中"、"在前 N 个发布中稳定存在"等)。一次典型的初轮筛选能为每个系统产出 20-50 个标记。

失败时: 如果标记在相邻的小版本之间就消失了,说明目录捕获的是易受重新构建影响的易变字符串,而不是稳定的标识符。删除这些条目;改为采用更长、更具语义锚点的子串。

步骤 2:按特性系统对标记分组

把标记打包进每个独立演化能力对应的系统表中。一个"系统"是一组连贯的标记,它们的存在/缺失会协同移动,因为它们共享一次特性生命周期(例如,属于某个假想

acme_widget_v3
能力的全部标记)。

分组的意义:逐系统打分可防止交叉污染。某个系统的标记缺失绝不可压制对另一个系统的检测;不相关系统之间的聚合计数也没有信息量。

一个工作目录的形态(伪代码):

catalog:
  acme_widget_v3:
    markers:
      - { id: "acme_widget_v3_init",         category: function, weight: 10 }
      - { id: "acme.widget.v3.dialog.open",  category: telemetry, weight: 5 }
      - { id: "ACME_WIDGET_V3_DISABLE",      category: flag,     weight: 10 }
  acme_other_system:
    markers:
      - ...

预期: 每个系统拥有自己的标记清单;没有任何标记同时出现在两个系统中。添加一个新系统意味着新增一个顶级条目 — 绝不事后在系统之间搬运标记。

失败时: 如果标记难以归入某一个系统(重叠、模糊),说明系统定义太粗了。拆分该系统,或者接受某些标记是"共享底座"并把它们排除在逐系统打分之外。

步骤 3:按信号强度为标记赋权

为每个标记赋予一个权重,反映它的存在单独能在多大程度上确认该系统:

  • 10 = 单独即可确诊 — 足够独特,以至于仅凭发现这一个标记就足以确认该系统存在(例如一条很长的、系统专用的、其他代码路径不会发出的字符串)
  • 3-5 = 仅起佐证作用 — 单独过于普通,无法确诊,但会计入聚合得分(例如测试台在多个特性间复用的一个短遥测后缀)

要教授的是这一惯例,而非具体数字。"确诊"与"佐证"之间的落差比具体整数更重要 — 关键在于第 5 步的阈值能区分"单个强信号"与"多个弱信号"。

预期: 每个标记都有一个权重。目录的权重分布偏向佐证性标记(3-5),每个系统只有少量单独即可确诊的标记(10)。

失败时: 如果每个标记都被赋值为 10,打分就失去了分辨率 — 部分存在的发现将不可能被识别。降格那些在多个系统间反复出现、或出现在不相关处理器中的标记。

步骤 4:记录每个版本的基线

对扫描过的每个版本,都应记录存在的缺失的标记,以版本为键。两者都是证据:版本 N 中缺失的某个标记,与版本 N+1 重新引入它时同样具有信息量。

基线形态:

baselines:
  "1.4.0":
    acme_widget_v3:
      present: ["acme_widget_v3_init", "ACME_WIDGET_V3_DISABLE"]
      absent:  ["acme.widget.v3.dialog.open"]
      score:   20
  "1.5.0":
    acme_widget_v3:
      present: ["acme_widget_v3_init", "ACME_WIDGET_V3_DISABLE", "acme.widget.v3.dialog.open"]
      absent:  []
      score:   25
  "1.4.1":
    _annotation: "never-published; skipped from upstream release timeline"

从未发布的版本要显式加注,而不是默默省略。默默跳过的版本在下一位读者眼里就像数据丢失。

预期: 每个版本对每个被追踪系统都产出一条记录,填充

present
absent
score
;如从未发布则填入显式的
_annotation

失败时: 如果基线扫描在一个先前存在的系统上产出了零标记,在没有确认二进制路径正确、

strings
命令有输出、且标记 ID 与目录完全一致之前,不要假定它被移除了。错误的零值会污染纵向记录。

步骤 5:为完全与部分检测设置阈值

为每个系统定义两道闸门,作用于聚合得分:

  • full
    — 高于此分则该系统被视为在本版本中存在且激活
  • partial
    — 高于此分则该系统被视为已发货但不完整(部分标记存在,但未达
    full
    阈值)

低于

partial
= 缺失(或尚未存在,取决于时间推进方向)。

thresholds:
  acme_widget_v3:
    full:    25
    partial: 10

如何选阈值:把

full
设为一次健康安装预期会发出的权重之和;把
partial
设为一个诊断性标记加上一个佐证信号的分数。当你有了多个版本的证据后再重新调校。

预期: 每次扫描对每个系统产出一个带标签的发现:

full | partial | absent
partial
发现需要调查 — 它们正是暗启动与移除的候选。

失败时: 如果每个系统在每个版本都报告

partial
,说明阈值过于敏感(很可能被设置得比标记总和还高)。对照某个已验证处于激活状态的版本重新校准。

步骤 6:使用
strings -n 8
扫描

strings
配合最短长度过滤作为抽取原语。
-n 8
下限能滤掉多数噪声(短片段、填充、地址表垃圾),同时不丢失有意义的标识符 — 它们几乎总是长于 8 个字符。

strings -n 8 path/to/binary > /tmp/binary-strings.txt

然后对

/tmp/binary-strings.txt
运行目录匹配(任何面向行的匹配器:
grep -F -f markers.txt
ripgrep
或一个小脚本都可以)。

注意事项:

  • 更低的下限(
    -n 4
    -n 6
    )会让输出被二进制垃圾与压缩符号噪声淹没;诊断与佐证的区分会崩塌
  • 更高的下限(
    -n 12+
    )会漏掉较短的标志位标识符与配置键
  • 某些打包器会压缩或编码字符串;如果
    strings
    返回几乎空白的输出,二进制可能需要先做打包抽取(超出本技能范围)

预期: 每行一个字符串的输出,通常 1k-100k 行,取决于二进制大小。手工检视前 100 行应能辨认出可识别的标识符。

失败时: 如果输出为空或难以辨认,二进制很可能是被打包、加密、或以

strings
读不懂的字节码格式发货的。停在这里、先在抽取层解决;不要基于一次不可读的扫描记录基线。

步骤 7:向前扩展基线,而不重写过去的记录

当目录中新增系统或标记时,仅对其后的版本进行扫描。过去版本的记录保持原样。

为什么这样做:先前版本的基线是当时扫描到的经验证据,而不是对该过去版本实际内容的当前模型。用事后新发现的标记去回头改写它们,会把"我们现在知道什么"与"我们当时观察到了什么"混为一谈。两者都有用;基线文件里只应保留其中一者。

如果确实需要做一次事后扫描(例如测试某个新标记在版本 N-3 时是否已存在),把它作为独立的附录来记录:

addenda:
  "1.4.0":
    scan_date: "2026-04-15"
    catalog_revision: "v7"
    findings:
      acme_new_system:
        present: ["..."]

原本的

baselines["1.4.0"]
条目保持不动。读者既能看到原始记录,也能看到后来的事后扫描及各自使用的目录修订。

预期: 基线文件只向前单调增长;过去记录只追加、附带可选的附录块。目录修订版本化,使每次扫描都能追溯到它所用的目录状态。

失败时: 如果你感到冲动想要直接编辑某个过去版本的

present
清单,请停下。改为增加一条附录。篡改过去记录会失去检测扫描器回归的能力(后续任何扫描器校验环节的第 8 步都依赖历史记录的不可变性)。

校验

  • 目录对每个标记都显式标注了类别(API / 身份 / 配置 / 遥测 / 标志 / 函数 之一)
  • 每个标记都严格归属于一个系统;没有任何标记同时出现在两个系统中
  • 权重跨越真实区间(既有 10,也有 3-5);权重不是全都相同
  • 每个被扫描版本都对每个被追踪系统记录了
    present
    absent
    score
  • 从未发布的版本有显式加注,而非默默省略
  • 每个系统都有
    full
    partial
    两个阈值;发现被相应标注
  • 使用
    strings -n 8
    作为抽取原语(或对非文本二进制使用有文档记载的等价物)
  • 最新扫描未改变过去版本的记录;事后新发现放在附录块中

常见陷阱

  • 把具体发现当作目录。 目录应描述标记的类别与形态,而不是罗列绑定到具体版本的字面量。塞满"发现"形态条目的目录衰败极快,且如不慎公开发布,是最大的泄漏风险。
  • 捕获被压缩的标识符。
    _p3a
    q9X
    这样的名字在每次重新构建时都会重命名。即使今天匹配上,明天就是噪声。坚持采用语义上有意义的标识符。
  • 把遥测事件与特性标志混为一谈。 它们在许多测试台中共享命名惯例,但扮演不同角色。在第 1 步按类别打标签,以便逐类分析保持干净。
  • 默默跳过从未发布的版本。 版本序列中的无注释空洞看起来像是漏扫。显式加注:
    _annotation: "never-published"
  • 在有任何基线数据之前就设置阈值。 首次扫描确立经验上的权重总和;之后再对着它调校阈值,而不是提前拍脑袋。
  • 目录增长时重写先前版本的记录。 过去的记录是证据;附录才是事后扫描的受支持模式。
  • 信任空白扫描输出。 标记数为零并不总是意味着"缺失"。在宣布移除之前,先确认二进制可读、目录 ID 完全一致。
  • strings -n 4
    当成比
    -n 8
    更彻底。
    更低的下限加噪声的速度比加信号更快。诊断性标记几乎总是 8 个以上字符。

相关技能

  • security-audit-codebase
    — 共享的学术纪律;两条流水线都把标记存在当作发现,但下游消费者不同
  • audit-dependency-versions
    — 把相同的版本追踪严谨性扩展到外部依赖清单;本技能把它应用到二进制工件
  • probe-feature-flag-state
    — 第 2-3 阶段的后续;消费基线以对标志位推广状态(live / opt-in / dark / removed)进行分类
  • conduct-empirical-wire-capture
    — 第 4 阶段的后续;用真实测试台流量验证推断出的行为
  • redact-for-public-disclosure
    — 第 5 阶段的后续;规定哪些发现可以离开私有工作区