构建标签参考
十个标签、两个方向、CI 判据
这一页是查表用的:ANet、ANetHub、ANetLink 三个仓库里每一个构建标签的名字、方向、 管辖的代码位置、去掉(或加上)之后具体失去什么,以及验证它的两条命令。
机制与设计理由在 可插拔,分档取舍在 发行版总览。这里只给事实。
一 · ANet daemon:十个标签
anet 有十个构建标签,九个减法、一个加法。
| 名字 | 标签 | 方向 | 代码位置 | 注册文件 |
|---|---|---|---|---|
service | no_service | 减法(默认在) | module/service | cmd/anet/module_service.go |
x402 | no_x402 | 减法 | module/x402 | cmd/anet/module_x402.go |
mcp | no_mcp | 减法 | internal/mcpserv、cmd/anet/mcp.go | cmd/anet/mcp.go、cmd/anet/module_mcp_declare.go |
p2p | no_p2p | 减法 | module/p2p | cmd/anet/module_p2p.go |
taskboard | no_taskboard | 减法 | module/taskboard | cmd/anet/module_taskboard.go |
cas | no_cas | 减法 | module/cas | cmd/anet/module_cas.go |
blackboard | no_blackboard | 减法 | module/blackboard | cmd/anet/module_blackboard.go |
org | no_org | 减法 | module/org | cmd/anet/module_org.go |
anetlink | no_anetlink | 减法 | module/anetlink、provider/anetlink | cmd/anet/module_anetlink.go |
shell | shell | 加法(默认不在) | module/shell | cmd/anet/module_shell.go |
注册文件本身带着模块的标签(//go:build !no_service 之类),里面只有一行 blank import
(mcp 是例外,见下面的说明)。
这就是标签成为开关的全部机制:文件不编译 → 包不被 import → init() 不跑 →
module.Register 没被调用 → 链接器没有理由留下这个包。
mcp 是九个减法名字里唯一不挂在 module.Host 上的。它是一个 northbound
(anet mcp,stdio 上的 MCP 服务),代码在 internal/mcpserv,由 cmd/anet/mcp.go
的 //go:build !no_mcp 管辖。它不进模块注册表,但仍然出现在 anet version 的
modules: 一行里:cmd/anet/module_mcp_declare.go 带同一个 //go:build !no_mcp,
里面只有一句 module.DeclareCompiled("mcp"),所以这一行报的是链接器留下了什么。
CI 数它的符号要特判成 internal/mcpserv。
二 · 九个减法标签逐条
体积数字取自 发行版总览 的实测表
(2026-09-03,go 1.26.7,linux/amd64,CGO_ENABLED=0,-trimpath -ldflags "-s -w")。
每一行都是从默认构建出发只加一个 no_<name> 量出来的,单位 KiB。
no_service
- 去掉:
module/service - 失去的能力:把本机已有的 HTTP 服务声明成 ANet 能力对外提供。daemon 收到调用后 把参数 POST 到配置里写的 URL、读回复,服务端不需要懂 AID、收据或 CBOR。
- 攻击面变化:少一条出站路径(向配置里写明的 HTTP URL 发请求)。不涉及监听口。
- 体积:省 12 K,依赖减 1
- 注意:这是"我有一个服务,怎么挂上网络"的唯一答案。去掉之后这个节点只能委派和接活, 不能以能力 id 对外提供服务。
no_x402
- 去掉:
module/x402全部 —— facilitator 客户端、报价、结算、凭证签发、 兑付路径、对账与发放链审计 - 失去的能力:标价、被付款、付款、
anet balance、anet redeem、anet reconcile、anet audit-hub - 攻击面变化:最大的一条。
x402是九个模块里唯一在anet进程里net.Listen的模块 ——module/x402/voucher.go的startRedeemFace, 只在配置里voucher_addr非空时执行。no_x402的构建里这个监听口的代码不存在。 - 体积:省 116 K,依赖减 1
- 无模块构建上的行为:五个付费控制面入口 ——
/balance、/redeem、/x402-authorize、/reconcile、/audit-hub—— 统一回答internal/daemon/paylink.go的errNoPayments():
被要求做标价的能力时答 UNAVAILABLE 并说明原因,不会免费替人干活。
UNAVAILABLE(做不了)与 FAILED(试了没成)是两种状态,不合并 ——
见 诚实效果状态。
no_mcp
- 去掉:
internal/mcpserv、cmd/anet/mcp.go与cmd/anet/module_mcp_declare.go, 连同 MCP Go SDK 及其 jsonschema 依赖树 - 失去的能力:
anet mcp的 MCP stdio 服务 - 攻击面变化:无监听口的变化。
anet mcp是本机 MCP 客户端通过 stdio 拉起的子进程, 只连本机 daemon 的回环控制口。 - 体积:省 1,896 K,依赖减 34 —— 占九个模块可省总量的 85%, 是唯一一个体积理由成立的标签。省下来的主要不是自己的代码,是 SDK 的依赖树。
anet mcp 这条命令在 no_mcp 构建里仍然存在,由 cmd/anet/mcp_stub.go 提供替身,
回答:
给出这句话而不是"未知命令",是因为一个在 MCP 客户端里配好了 anet mcp 的操作者
需要知道问题出在哪个构建上。
no_p2p
- 去掉:
module/p2p(daemon 侧的对等传输客户端) - 失去的能力:委派直连投递。去掉之后所有投递走 hub 中继。
- 攻击面变化:daemon 少一条出站 unix socket 连接。入站对等连接不在
anet里 —— daemon 只是通过 unix socket 连到anetpeer进程,真正监听的是anetpeer。 要拔掉"这台机器接受入站对等连接",停的是anetpeer进程。 - 体积:省 28 K,依赖减 1
- 注意:
anet p2p-advertise不在这个标签管辖之下。发布直连地址是一条 关于本节点身份的签名声明,发给自己的 hub,在内核里、无标签 (internal/daemon/hub_client.go的AdvertisePeerAddress)。 一个no_p2p的构建照样能发布地址;消费这个地址的才是模块。
no_taskboard
- 去掉:
module/taskboard(hub 共享任务板的客户端) - 失去的能力:三个能力
task.board(读板)、task.create(放活)、task.claim(领活) - 攻击面变化:少一条出站路径(向本节点的 hub 发签名请求)。无监听口。
- 体积:省 24 K,依赖减 1
- 注意:板本身在 hub 上(
ANetHub的no_taskboard管的是服务端,见第八节)。 hub 侧的板有读板、单卡查询和八个变更动作 (create/move/claim/submit/accept/reject/block/unblock, 见ANetHub/internal/taskboard/http.go);daemon 侧的模块只把其中三个做成能力。 移动、阻塞、拒绝这些协调动作是人在 UI 里做的, 它们仍然以 HTTP 端点形式向任何会签名的东西开放。
no_cas
- 去掉:
module/cas(内容寻址存储) - 失去的能力:四个能力
cas.put/cas.get/cas.has/cas.stat。 CID 构造是 CIDv1 dag-cbor sha2-256。 - 攻击面变化:无。这个包里没有
net/http也没有net.Dial。 - 体积:省 52 K,依赖减 1
no_blackboard
- 去掉:
module/blackboard(共享认知板) - 失去的能力:三个能力
blackboard.add/blackboard.snapshot/blackboard.conclude - 攻击面变化:无网络行为
- 体积:省 36 K,依赖减 1
- 注意:板上的贡献是逐条验签的(合并前要知道"是谁签的"),
这正是
module.Host上ResolveKEL()这一项存在的原因。
no_org
- 去掉:
module/org(组织成员凭证) - 失去的能力:两个能力
org.verify/org.info - 攻击面变化:无网络行为
- 体积:省 28 K,依赖减 1
- 注意:这是接缝存在的理由本身。v1 的组织功能长进 35 个 daemon 文件,
1.3.0-v3 开源时删掉 683,852 行才拔出来。现在它是一个
-tags no_org。
no_anetlink
- 去掉:
module/anetlink与provider/anetlink - 失去的能力:把 ANetLink 运行时触达的设备能力注册成本节点的能力
- 攻击面变化:少一条出站 unix socket 连接(连 ANetLink 的 C1 socket)。无监听口。
- 体积:省 12 K,依赖减 2
- 注意:去掉这个模块不会让 daemon "少懂一点设备" —— 按 C1,daemon 从来就不知道 "设备"这个概念,它只看见能力。见 五条契约。
三 · 加法标签 shell
- 加上:
module/shell - 得到的能力:
shell.list,以及每条运营者命名的命令各一个shell.run@<name>(前缀shell.run@定义在module/shell/shell.go)。shell.exec(任意命令)只在配置里allow_arbitrary为真时才注册: 编进来、配上了、开了任意命令,是三个独立的开关 - 参数:命名命令只接受
argv一个 args 键,shell.exec只接受command与dir; 其他键报错,不会被静默丢弃(module/shell/provider.go的onlyKnownArgs) - 体积:加 36 K,依赖加 1
- 公开面:不开端口。请求经 hub 中继或 p2p 到达常规委派入口。
- 提权:不提权。命令以 daemon 自己的用户身份运行。一个以 root 启动的 daemon 能跑 root 命令 —— 这是安装时写在 unit 文件里的决定,不是这个模块能授予的。
方向为什么反过来
因为两种写错的代价不对称:
| 写错的方式 | 后果 |
|---|---|
| 减法标签漏了(该去掉的没去掉) | 某人想去掉的模块留在了他自己的构建里 |
| 加法标签漏了(该不在的进去了) | 命令执行能力进了所有没要过它的构建 |
规则可以写成一句:默认构建应当是完整的,除非某个能力"进错构建"的后果比"缺失"更重。
目前套件里只有 shell 满足这个条件 —— 它是唯一一个把一次网络请求变成宿主机上一条命令的模块。
需要靠"记得去掉"来保护的人,恰好是没听说过这个标签的人。
no_shell 不存在,而这需要专门做一件事
一个操作者在配置里写了 modules.shell 而构建里没有它,如果错误信息说
"是不是用 no_shell 编的",他会去找一个从来不存在的标签。
解决办法是 cmd/anet/optin_tags.go —— 一个没有构建标签的文件,内容只有:
名字必须在不含这个模块的构建里也存在,否则没有任何东西能说出正确的修法。
于是 module.Build 的错误信息分成两种:
"编进去"不等于"开着"。 带 shell 的构建在没有 modules.shell 配置块时不注册任何能力;
配了但调用方名单为空时拒绝所有远程调用;只有运营者在配置里命名过的命令能跑。
三道闸门分别由发布方、机器运营者、运营者的名单文件把守 ——
见 shell 发行变体。
四 · 组合规则
一、减法标签之间可以自由叠加,用逗号连接,不分先后。
二、加法标签和减法标签写在同一个串里。
三、内核没有标签,拔不掉。 身份与多身份、能力注册表(C1)、委派生命周期、
委派验签、收据验证、第三方验证、证据链、hub 中继客户端、传输列表、对端 KEL 缓存、
回环控制面、CLI、自动回复、本地控制台 —— 这些没有对应的 no_ 标签,
想要一个"不带委派的 daemon"是做不到的。
四、配置了却没编进来的模块是错误,不是空操作。 module.Build 直接失败,
而不是让 daemon 读到 "p2p": {...} 之后默默忽略、留下一个操作者对着
"为什么没有在对等"发呆。
五、九个减法标签有 512 种组合,CI 只跑 18 种。 没被列进矩阵的组合可能编译不过。 自建裁剪版本时,把你的标签组合加进你自己的 CI。
CI 已验证的 18 种组合
下面是 .github/workflows/ci.yml 里 pluggable job 的完整矩阵,每次提交都跑:
| # | -tags | 覆盖意图 |
|---|---|---|
| 1 | no_anetlink | 单个 |
| 2 | no_p2p | 单个 |
| 3 | no_p2p,no_anetlink | 递增 |
| 4 | no_blackboard | 单个 |
| 5 | no_blackboard,no_p2p,no_anetlink | 递增 |
| 6 | no_org | 单个 |
| 7 | no_org,no_blackboard,no_p2p,no_anetlink | 递增 |
| 8 | no_cas | 单个 |
| 9 | no_cas,no_org,no_blackboard,no_p2p,no_anetlink | 递增 |
| 10 | no_service | 单个 |
| 11 | no_mcp | 单个 |
| 12 | no_x402 | 单个 |
| 13 | no_taskboard | 单个 |
| 14 | no_x402,no_service,no_mcp,no_taskboard,no_cas,no_org,no_blackboard,no_p2p,no_anetlink | 全部九个 = min |
| 15 | no_x402,no_mcp,no_taskboard,no_cas,no_org,no_blackboard,no_p2p,no_anetlink | standard |
| 16 | no_mcp,no_taskboard,no_cas,no_org,no_blackboard,no_p2p,no_anetlink | paid |
| 17 | no_x402,no_cas,no_org,no_blackboard,no_p2p,no_anetlink | agent |
| 18 | no_x402,no_mcp,no_cas,no_org,no_blackboard,no_anetlink | p2p |
九个减法标签每一个都有独立一行,所以每个模块都被单独数过符号。 第 15–18 行是发行版组合,专门列出来的理由写在文件注释里: 一个设计文档提出而没有人构建的组合,会在没有人注意的情况下停止编译。
加法方向不在这张表里 —— shell 由单独一个 job 验,见第六节。
五 · 判据:两条 go tool nm 命令,两个方向
判据是符号数,不是"运行时禁用"。对任意一个减法模块 <m>:
以 x402 为例,可以原样复制运行:
加法方向的判据一样是符号数,只是断言反过来:
两个方向都要验。 只验 lean == 0 会让一个从未被链接进任何构建的模块看起来"可插拔" ——
它在两种构建里都是 0,而检查只看其中一边,于是通过。full > 0 这一半证明的是
"检查确实看得见它要检查的代码"。
判据是 0 与非 0,不是具体数字。符号数会随实现变化,拿它当断言只会得到一堆脆弱的检查。
符号匹配的 pattern 在 CI 里是 provider/<mod>|module/<mod>,mcp 特判为
internal/mcpserv —— 大部分模块住在 module/ 或 provider/ 下,MCP northbound
住在 internal/mcpserv,一个看不见自己要检查的代码的检查会因为错误的理由通过。
六 · CI 的两个 job
.github/workflows/ci.yml 里有两个专门管标签的 job,方向相反。另有
test(gofmt / vet / go test ./...)、race(go test -race ./...)、
scenario(一个 hub 加三个节点的真实多进程联调)三个 job 与标签无关。
pluggable —— 减法方向
18 行矩阵(上表),每一行做四件事:
组合行只对第一个标签数符号(脚本里是 mod="${mod%%,*}")。这一点不影响覆盖:
九个模块各自都有独立一行,单独被数过。
optin —— 加法方向
单独一个 job,不是矩阵里多加一行。理由写在文件注释里: 一个坏掉的减法标签发出去的是"某人想删的模块没删掉",一个坏掉的加法标签发出去的是 "命令执行能力进了所有没要过它的构建",代价不同,所以断言也分开写:
为什么加法标签必须另有一条 go test -tags shell ./...
因为 go test ./... 根本看不见构建标签后面的代码。
module/shell/shell_test.go 自己也带 //go:build shell。一条不写标签的测试命令
不会编译它,更不会运行它 —— 于是这个模块的测试哪儿都不会跑,
而它是套件里唯一一个在宿主机上执行命令的模块,是最不该没有覆盖的那一个。
go vet 同理:不带标签的 vet 看不见这些文件。
这是加法标签相对减法标签多出来的一项义务:新增一个加法标签时,
必须同时在 CI 里加一条带这个标签的 vet 与 test,否则这段代码没有任何检查覆盖。
减法标签没有这个问题 —— 它的代码在默认构建里,默认的 go test ./... 就编译并运行了。
跨进程的覆盖由 scripts/joint-shell.sh 补(hub + 两个 daemon,
其中提供方用 -tags shell 构建),它还会检查提供方日志里
modules compiled in 一行确实含有 shell。
七 · 本地怎么验
在 ANet/ 仓库根目录跑。它做这些事,顺序如上:
| 步骤 | 命令 |
|---|---|
| 格式化 | gofmt -l -w internal cmd(自动改,并报告改了哪些文件) |
| 静态检查 | go vet ./... |
| 静态检查(加法方向) | go vet -tags shell ./... |
| 测试 | go test ./... |
| 测试(加法方向) | go test -tags shell ./... |
| 符号断言 | 构建默认二进制,断言 module/shell 符号数 == 0 |
最后一步放在本地而不只放在 CI,是因为这是开发者推送之前跑的脚本, 而"它默认不在"是整个加法标签所依赖的全部内容。
不加 --check 时 ./build.sh 只构建,不跑检查。CGO_ENABLED=0,无标签,
产物落在仓库根的 ./anet。
带标签构建
build.sh 不接受标签参数。要选标签用 scripts/build.sh 的 TAGS 环境变量:
scripts/build.sh 把 commit、构建时间与标签串本身用 -ldflags -X 打进二进制。
标签串被记下来的理由是:一次发布要跑这个脚本很多次,标签串是区分产物的唯一东西,
一个说不出自己是哪个变体的二进制,会把"这台机器接不接受远程命令"变成一个靠猜回答的问题。
但不要用这个字段判断一个二进制含不含 shell。go build -tags shell 而不加 -X
会产出一个含有 shell 模块、却报告"没有标签"的二进制。可靠的做法是问注册表:
这一行读的是 module.Compiled() —— 一个模块在列表里,是因为它的 init() 跑了,
而 init() 跑了,是因为链接器留下了它。注册表不会说错。
MCP 不走模块注册表,但由 module.DeclareCompiled("mcp") 补进这一行,所以它也在;
shell 默认不在这一行,带上 -tags shell 后会出现。九个减法标签全用上时(min 档)
这一行是 modules: (none)。
daemon 启动时把同一份清单写进日志:
compiled in 与 started 是两个数:前者是二进制里有什么,后者是本机配置里启用了几个。
mcp 只出现在前者 —— 它不是 module.Module,没有可启动的实例。
换一组标签重新构建后重启 daemon,不需要再显式跑一次 anet hub-register:启动时
internal/daemon/daemon.go 的 refreshRegistration 会在后台按当前模块提供的能力清单
重新注册,能力的增删跟着构建走。这次刷新是非致命的 —— hub 不可达时只记一行日志,
节点照常运行,显式注册仍然可用。
八 · ANetHub:两个标签
hub 的可选子系统挂在 cmd/anet-hub/mounts.go 的 mount 接缝上 ——
一个 name 加一个 wire func(*hubDeps) (func() error, error),
hubDeps 里是数据目录、store、hub 身份、aghub.Server 和根 mux。
模块看得见内核与 mux,看不见彼此。
| 名字 | 标签 | 方向 | 注册文件 | 去掉后失去 |
|---|---|---|---|---|
federation | no_federation | 减法 | cmd/anet-hub/wire_federation.go | /fed/v1/ 全部端点、跨 hub 目录同步、跨 hub 结算与清算、对等 KEL 解析、对等发放头见证 |
taskboard | no_taskboard | 减法 | cmd/anet-hub/wire_taskboard.go | /tasks/ 全部端点(共享任务板服务端) |
no_federation 去掉的东西比端点多:它同时拿走 SetForwarder(投递转发)、
SetPeerKELResolver、SetPeerEndpointResolver、SetFederatedDirectory
以及两个后台循环(目录同步 syncLoop、发放头见证 witnessLoop)。
一个 no_federation 的 hub 是一个只服务自己注册用户的孤立 hub。
CI(ANetHub/.github/workflows/ci.yml 的 unplug job)跑三种组合:
hub 侧的标签只验编译,不验符号数。 unplug job 只有一步 go build,
没有 go test -tags,也没有 go tool nm 的两方向断言。
也就是说 hub 的两个标签目前满足"去掉之后还能编译",不满足 ANet 那条
"full > 0 且 lean == 0"的判据。ANetHub 的 scripts/build.sh 也帮不上:
它构建 anet-hub 与 anet-hub-admin 两个二进制并重建嵌入的 web UI,
不接受标签参数,不做符号断言。
九 · ANetLink:十一个减法、四个加法
ANetLink 的可选单元是适配器,挂在 cmd/anetlinkd/plugins.go 的
adapterPlugin 槽上,注册文件是 cmd/anetlinkd/plugin_<name>.go。
十一个减法标签(协议适配器,默认在)
| 配置名 | 标签 | 适配器包 |
|---|---|---|
modbus | no_modbus | adapters/modbus |
mqtt | no_mqtt | adapters/mqttbridge |
homeassistant | no_ha | adapters/habridge |
opcua | no_opcua | adapters/opcua |
bacnet | no_bacnet | adapters/bacnet |
can | no_can | adapters/can |
ble | no_ble | adapters/ble |
zigbee | no_zigbee | adapters/zigbee |
btmesh | no_btmesh | adapters/btmesh |
thread | no_thread | adapters/thread |
sim | no_sim | adapters/sim |
注意配置名与标签名不总是一致:Home Assistant 桥的配置键是 homeassistant,
标签是 no_ha,包是 habridge。
sim 是唯一 defaultOn: true 的适配器 —— 没有配置块也会注册,
这样一个裸跑的 anetlinkd 总有东西可展示。no_sim 之后 --demo 输出
"no devices",这是预期的优雅退化。
四个加法标签(默认不在)
| 标签 | 加入 | 为什么反过来 |
|---|---|---|
onvif | ONVIF IP 摄像头(adapters/onvif) | 经厂商 HTTP 接口触达设备、要持有凭据 |
hikvision | 海康 ISAPI(adapters/hikvision) | 同上 |
dahua | 大华 CGI(adapters/dahua) | 同上 |
adap | 进程外适配器宿主(C4 over UDS,adap/) | 托管一个我们没有编译过、可能是别的语言写的、代我们触达硬件的进程 |
这四个名字登记在 cmd/anetlinkd/plugins.go 的 additiveTags 里,
作用与 ANet 的 DeclareOptIn 相同:让一个不含它们的构建也能说出正确的修法。
配置里写了没编进来的适配器,启动直接失败,并且两种方向给两种话:
另有一个测试专用标签
realworld —— 七个适配器加 RTSP、Matter 的真实服务测试
(adapters/*/realworld_test.go)。它不影响任何产物,只决定哪些测试被编译。
台架起停是 test/realworld/up.sh / run.sh / down.sh。
ANetLink 的 CI
| job | 内容 |
|---|---|
test | gofmt、go vet ./...,外加三条带标签的 vet:-tags realworld、-tags onvif,hikvision,dahua、两者合并;然后 go test ./... 与 go run ./cmd/anetlinkd --demo |
plugin | 加法矩阵五行:onvif / hikvision / dahua / adap / 四个一起。每行 vet + test + --demo 启动 |
unplug | 减法矩阵十三行:十一个标签各一行,加 no_btmesh,no_zigbee,加十一个一起。每行 go build + --demo 启动 |
realworld | 起真 mosquitto / Modbus / HA / OPC UA / 摄像头,跑 -tags realworld |
race | go test -race ./...,外加 -tags onvif,hikvision,dahua 的一遍 |
plugin job 存在的理由与 ANet 的 optin 相同:这四个适配器不在任何默认构建里,
没有这个 job 它们在 CI 上根本不会被编译、vet 或测试。
ANetLink 侧同样只验编译与启动,不验符号数。 unplug 与 plugin 两个 job 里
没有 go tool nm。全套件中只有 ANet 仓库做符号数断言 ——
位置是 .github/workflows/ci.yml、build.sh、deploy/release/build-release.sh 三处。
十 · 发布件与标签
deploy/release/build-release.sh 每个平台出两个件,四平台(linux/darwin × amd64/arm64)共八个:
| 文件名 | 标签 |
|---|---|
anet-<os>-<arch> | 无标签(即九个减法模块全在,不含 shell) |
anet-shell-<os>-<arch> | -tags shell |
一行安装脚本的 --shell 拉取的是另一个文件,不是同一个二进制的一个开关:
发布件用 -ldflags '-w' 而不是常见的 -s -w:-w 只去掉 DWARF 调试信息,
-s 会连符号表一起去掉,而那样 go tool nm 会回答"没有符号" ——
读起来像检查通过,实际什么也没有证明。代价是每个二进制多约 1.4 MB,这是有意付的:
不付,判据对下游就不成立了。发布脚本自己也把这条当成失败条件,
产物没有符号表就直接报错,而不是让检查空转着通过。
在自己下载到的文件上重做判据的完整流程见 自行核对二进制。
十一 · 已知缺口
- hub 与 ANetLink 的标签没有符号数判据。 两边的
unplugjob 只验编译 (ANetLink 另验--demo能启动)。"去掉之后还能编译"比"代码不在二进制里"弱一档。 - 组合矩阵不是全集。 ANet 九个减法标签共 512 种组合,CI 跑 18 种; ANetLink 十一个减法标签共 2048 种,CI 跑 13 种。没进矩阵的组合可能编译不过。
- 没有"发行版名字"这个字段。
anet version报模块列表,不报"这是 standard 档"。anet version --profile不存在:CLI 现在按cmd/anet/main.go的knownFlags表 拒绝未知 flag,这条命令答anet version takes no flags, and --profile is not one。 发行版名字是设计稿里的待做项。anet status不报模块 —— 它里面的 "profile" 指的是 agent 的自述资料。 ANet/docs/DISTRIBUTIONS-zh.md里的部分数字与本页不一致。 该文档正文有一处 "体积 17.6 MB" 与它自己的实测表(12,132 K)矛盾,并称"CI 跑 10 种 tag 组合" (实际 18 种)。本页数字以.github/workflows/ci.yml与 发行版总览 的 2026-09-03 实测为准。- 发行版档位的 tag 串内部不齐。 CI 矩阵里
agent与p2p两档的串没有no_taskboard,min/standard/paid三档有;而ANet/docs/DISTRIBUTIONS-zh.md列的五档串一个都没有no_taskboard, 与 CI 的前三档也对不上。这是taskboard加入较晚、只有一部分串跟着更新的实际差异, 不是设计意图。要不要统一,未决。 - 符号数只回答"代码在不在",不回答"它做了什么"。
full > 0 / lean == 0证明链接器去掉了这个包,不证明这个包的行为正确 —— 那是单元测试与scripts/joint.sh、scripts/joint-shell.sh、scripts/scenario.sh、scripts/prodtest.sh几条联调路径的事。