Skip to content

docs: docs/ 里 13 条 cli.ts 行号引用改钉符号锚(22 → 9,改前 11/11 全错) - #857

Merged
vansin merged 4 commits into
mainfrom
docs/cli-symbol-anchors
Aug 17, 2026
Merged

docs: docs/ 里 13 条 cli.ts 行号引用改钉符号锚(22 → 9,改前 11/11 全错)#857
vansin merged 4 commits into
mainfrom
docs/cli-symbol-anchors

Conversation

@vansin

@vansin vansin commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

推进 #852docs/ 下的 cli.ts 行号引用 22 → 9,13 条改钉符号锚。

为什么必须改

#852 量过:docs/ 下锚文本带符号名、因而可机器判定的引用有 11 条 ——
漂移 11 条,仍然对的 0 条。这批引用现有的任何一道门都照不到:

改法(照 #845 已确立的形状)

改前  [`cli.ts:228 loadProfile`](…/blob/main/agent-network/bin/cli.ts#L228)
改后  [`cli.ts`](…/blob/main/agent-network/bin/cli.ts) —— 搜 `function loadProfile(`

行号会漂,符号不会。读者用 git grep 一次定位。

改之前它们错到什么程度

符号 文档声称 origin/main 实际
adminUtokPath 28 138
saveGlobal 77-81 1000
saveServerConfig 89-95 1047
saveAdminUtok 105-111 1062
loadProfile 228 1208
saveProfile 246-273 1272
setupCommand 556 1860
ensureMcpJson 1644 4300
runCommand 2044 5641
renameCommand 2583 / 2629 6911

不是漂了几行,是差了几千行 —— 点进去看到的是完全无关的代码。

承重复核:每条新锚串在 cli.ts 里唯一

新锚串 13 条,非唯一 0 条

RuntimeName 那条故意没改:它在 cli.ts 里出现 13 次,做不出唯一锚。
与其钉一个含糊的锚(那正是 #845 踩过的坑:锚串确实存在,只是落在别的地方),
不如留着行号,等有人给它一个能唯一定位的写法。

剩下的 9 条:机械改不了,留给 #852

它们的锚文本里根本没有符号名:

docs/architecture.md:316   [cli.ts:1724](…#L1724)
docs/architecture.md:326   [cli.ts:1679-1680](…#L1679)
docs/architecture.md:328   [RuntimeName type cli.ts:145](…#L145)     ← 有名字但不唯一
docs/architecture.md:520   [`agent-network/bin/cli.ts:2386`](…#L2386)
docs/node-lifecycle.md:206 [cli.ts:2725-2750](…#L2725)
docs/node-lifecycle.md:213 [cli.ts:2831-2835](…#L2831)
docs/node-lifecycle.md:383 [`cli.ts:198`](…#L198)
docs/pitfalls.md:80        [`agent-network/bin/cli.ts:1658-1674`](…#L1658)
docs/rfcs/RFC-002-…:37     [`agent-network/bin/cli.ts:2685-2788`](…#L2685)

要修它们得人读源码,判断当初那段话想指的是什么 —— 没有机械办法。
这正是 #852 说的「剩下 9/11 要符号级校验」的那部分工作量。

顺带发现(不在本 PR 范围)

docs/qa/weekly/2026-W19.md 不是 UTF-8(position 2467 处 invalid continuation byte),
任何按 UTF-8 读全目录的脚本都会在它上面炸。本 PR 的处理是跳过它。

#852 量过:docs/ 下按 blob/main 钉 cli.ts 行号的引用,锚文本带符号名、可机器判定的
11 条里 **漂移 11、仍对 0**。这次把能确定唯一锚串的都改掉。

改法照 #845 已确立的形状:

  改前  [`cli.ts:228 loadProfile`](…/blob/main/agent-network/bin/cli.ts#L228)
  改后  [`cli.ts`](…/blob/main/agent-network/bin/cli.ts) —— 搜 `function loadProfile(`

13 条的真实位置(改之前它们全都指错了):

  adminUtokPath        文档说 28      实际 138
  saveGlobal           文档说 77-81   实际 1000
  saveServerConfig     文档说 89-95   实际 1047
  saveAdminUtok        文档说 105-111 实际 1062
  loadProfile          文档说 228     实际 1208
  saveProfile          文档说 246-273 实际 1272
  setupCommand         文档说 556     实际 1860
  ensureMcpJson        文档说 1644    实际 4300
  runCommand           文档说 2044    实际 5641
  renameCommand        文档说 2583 / 2629  实际 6911
  deleteCommand        文档说 2800-2840    实际另处
  dashboardReleaseTag  文档说 347          实际另处

每一条新锚串都逐条核过在 cli.ts 里**唯一**(13 条,非唯一 0 条)。
`RuntimeName` 那条**没有改**:它在 cli.ts 里出现 13 次,做不出唯一锚 —— 与其钉一个
含糊的锚,不如留着行号,等有人给它一个能唯一定位的写法。

剩下 9 条锚文本里没有符号名(形如 `[cli.ts:1724](…#L1724)`),机械改不了,
需要人读源码判断它当初想指的是什么。留给 #852
接上一提交。这 6 条的锚文本里没有符号名,机械改不了,是逐条读上下文判出它当初
想指什么、再去源码里定位的:

  node-lifecycle.md:206  正文说 notifyServerOffline  → 搜 `async function notifyServerOffline(`
  node-lifecycle.md:213  正文说「确认流程」          → 搜 `This will delete "${displayName}" (node_id:`
  node-lifecycle.md:383  正文直接写了 resolveNodeRef → 搜 `function resolveNodeRef(`
  architecture.md:316    正文说写 .mcp.json          → 搜 `.mcp.json: commhub → .anet/node-server.js`
  architecture.md:326    正文引了 compare-by-content → 搜 `if (src !== dst)`
  architecture.md:328    RuntimeName type            → 🔴 它已经不在 cli.ts 里了

最后一条值得单说:文档写「RuntimeName type cli.ts:145」,但 cli.ts 里
`type RuntimeName =` 出现 **0 次** —— 这个类型已经搬到
`agent-network/src/normalize-runtime.ts:16`。这不是行号漂移,是文件都换了。
所以这条改的是链接目标,不只是锚。

「确认流程」那条要小心:`Run again with --force to confirm.` 在 cli.ts 里出现 **2 次**
(deleteCommand 8143 / networkCommand 10173),不能拿它当锚。读上下文确认文档说的是
节点删除,才选了 deleteCommand 里唯一的那句。

每条锚串都核过唯一。node-lifecycle.md 的行号 pin 已归零。
@vansin

vansin commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

追加一个提交(025b461e):把「机械改不了、要人读源码」的那批也做掉了 —— docs/ 的 cli.ts 行号 pin 现在 22 → 3

新修的 6 条,每条都是读上下文判出它当初想指什么、再去源码定位的:

位置 正文线索 新锚串
node-lifecycle.md:206 正文说 notifyServerOffline async function notifyServerOffline(
node-lifecycle.md:213 正文说「确认流程」 This will delete "${displayName}" (node_id:
node-lifecycle.md:383 正文直接写了 resolveNodeRef function resolveNodeRef(
architecture.md:316 正文说写 .mcp.json .mcp.json: commhub → .anet/node-server.js
architecture.md:326 正文引了 compare-by-content if (src !== dst)
architecture.md:328 RuntimeName type 🔴 见下

🔴 RuntimeName 那条不是行号漂移,是文件都换了。 文档写「RuntimeName type cli.ts:145」,但 cli.ts 里 type RuntimeName = 出现 0 次 —— 这个类型已经搬到 agent-network/src/normalize-runtime.ts:16。所以这条改的是链接目标,不只是锚。上一轮我把它当成「不唯一所以跳过」,那个判断本身就建立在错误前提上(以为它还在 cli.ts 里)。

「确认流程」那条差点选错锚:Run again with --force to confirm. 在 cli.ts 里出现 2 次 —— deleteCommand(8143)和 networkCommand(10173)。读上下文确认文档说的是节点删除,才选了 deleteCommand 段里唯一的那句。拿那个出现两次的串当锚,就会复现 #845 踩过的坑。

docs/node-lifecycle.md 的行号 pin 已归零。

剩余 3 条(锚文本无任何线索,连正文都没说它指什么函数):

docs/rfcs/RFC-002-channel-bind-cli.md:37   cli.ts#L2685   「参考实现」
docs/architecture.md:520                  cli.ts#L2386
docs/pitfalls.md:80                       cli.ts#L1658   「candidates 数组:源文件搜索顺序」

pitfalls 那条我已定位到候选:const candidates 在 cli.ts 里有 4 处(1024/1463/4333/…),其中 1024 与 4333 都是 node-server.js 解析顺序,要读 pitfalls 正文才能判是哪一个 —— 留到下一轮,不猜。

这 3 条的锚文本里没有符号名,是逐条读正文判出来的:

  architecture.md:520  正文自己就写着「`sub === "dashboard"` 分支」
                       → 链接去掉行号即可,锚已经在正文里(唯一,cli.ts:6092)
  RFC-002:37           「参考实现」指的是 anet channel add/ls
                       → 搜 `async function channelCommand(`(唯一,cli.ts:8159)
  pitfalls.md:80       「candidates 数组:源文件搜索顺序」
                       → cli.ts 里 `const candidates` 有 4 处,其中 1024 与 4333
                         都是 node-server.js 解析顺序。判据是 4333 那处的注释
                         `// dist/src/node-server.js(npm 包混淆后产物,优先)`
                         与 pitfalls 正文第 1 条逐字对应,1024 那处不是。
                       → 搜那条注释(唯一)

至此 docs/ 下 blob/main 形式的 cli.ts 行号引用为 0。每条锚串都核过在源码里唯一。
@vansin

vansin commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

再追加一个提交(0b09dd5b):最后 3 条也收掉了 —— docs/ 下 blob/main 形式的 cli.ts 行号引用现在为 0(22 → 0)

这 3 条锚文本里没有符号名,是逐条读正文判出来的:

  • architecture.md:520 —— 正文自己就写着「sub === "dashboard" 分支」,所以链接去掉行号即可,锚已经在正文里(唯一,cli.ts:6092)。
  • RFC-002:37 —— 「参考实现」指的是 anet channel add/ls → 搜 async function channelCommand((唯一,cli.ts:8159)。
  • pitfalls.md:80 —— 「candidates 数组:源文件搜索顺序」。cli.ts 里 const candidates4 处,其中 1024 与 4333 都是 node-server.js 解析顺序。判据是 4333 那处的注释 // dist/src/node-server.js(npm 包混淆后产物,优先) 与 pitfalls 正文第 1 条逐字对应,而 1024 那处的注释是 // installed npm package layout,对不上。所以选 4333。

这是这批里唯一一条两个候选都长得像的,如果按「找个差不多的就钉上」处理,就会钉错一个 —— 而钉错之后它仍然是「锚串存在、链接能开」,没有任何门会报。

仓内其余 8 条(不在本 PR 范围)

docs-site/docs/changelog.md:713      cli.ts#L61 / #L2589   ← PR #851 正在修
docs-site/docs/en/changelog.md:712   cli.ts#L61 / #L2589   ← 同上
tests/qa-cli-02-network-create/README.md:44,54   cli.ts#L3166 / #L3055
tests/qa-cli-01-hub-start/README.md:37,56        cli.ts#L1893 / #L1925

#851 合了之后只剩 tests/qa-cli-*/README.md 那 4 条 —— 那个目录此前没有任何盘点覆盖到(#831 管 docs-site/、#852 管 docs/,都不含 tests/)。已在 #852 记一笔。

@vansin

vansin commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

复核:本条结论仍成立,但范围之外还有同类的 6 条,全部也是错的

一、结论仍成立(2026-08-14 复核)

origin/main 上,docs/ 里指向 agent-network/bin/cli.ts 的行号引用仍是 22 条 ——
标题里的"改前 22"没有变,这个 PR/改动还没落地。

git grep -o 'blob/main/agent-network/bin/cli\.ts#L[0-9-]*' origin/main -- docs/ | wc -l
→ 22

🔴 二、我按更宽的范围数了一遍:docs/ 下的 cli.ts 引用其实是 28 条

22  agent-network/bin/cli.ts     ← 本条覆盖
 6  agent-node/src/cli.ts        ← 本条**不覆盖**

标题写的是「docs/ 里 13 条 cli.ts 行号引用」,但 agent-node/src/cli.ts 也叫 cli.ts
按名字读会以为都算上了;实际那 6 条在范围之外。

三、那 6 条我逐条核了:6/6 全错,和本条要修的是同一种病

agent-node/src/cli.ts 现在 6133 行。逐条把「锚文本声称的符号」与「那一行实际内容」对照:

引用位置 声称 该行现在是什么 那个符号实际在第几行
docs/architecture.md:48 cli.ts:558-598 settingSources: [] // "Reached maximum number of turns (5)" … 2238
docs/message-lifecycle.md:41 cli.ts:864 msgType !== "task" … inboxDir: string; 该表达式已不存在
docs/message-lifecycle.md:142 cli.ts:864 同上 inboxDir: string; 同上
docs/message-lifecycle.md:198 cli.ts:1102 ["new_task","broadcast"].includes(ev.type) if (AUTH_TOKEN) headers["Authorization"] = … 5687
docs/message-lifecycle.md:199 cli.ts:836 shouldSkipMessage warn(\cleared ${key} …`)` 4610 / 4695
docs/node-lifecycle.md:196 cli.ts:1159 心跳 setInterval try { 1231 / 5942 / 5993

漂移幅度不小:settingSources 声称 558,实际 2238;includes(ev.type) 声称 1102,实际 5687。
其中 msgType !== "task" 这个表达式在当前代码里已经找不到了 ——
那两处引用不只是行号漂了,是它描述的判断本身可能已经改写,需要人看一眼再决定钉哪。

建议

不必扩大本条的范围(小范围是它能做完的原因),但标题/正文最好把范围写死
agent-network/bin/cli.ts 的 22 条」,否则读者会以为 docs/ 下的 cli.ts 引用都处理过了 ——
改一半比不改更糟,因为看起来像已经修过了。

那 6 条我不在这里动,建议另开一条跟踪(或在本条里显式写"不含 agent-node/src/cli.ts 的 6 条")。

(只读:全部读 origin/main,临时 worktree 用完即 remove;未改任何文档。)

@vansin

vansin commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

核过了,。前提比 PR 描述说得还严重,而新锚点我逐条验了。

① 旧行号 pin:我抽查的 13 条,13 条全错

origin/mainagent-network/bin/cli.ts(13753 行)逐条对:

doc 写的 那一行实际是什么 符号真正在
cli.ts:228 loadProfile const got = await tryOne(p); 1274
cli.ts:246-273 saveProfile 一句 capture-pane 的注释 1338
cli.ts:556 setupCommand console.error(...identityPrep.remedy...) 1945
cli.ts:2044 runCommand console.log("⚠ codex 需要登录") 5812
cli.ts:1644 ensureMcpJson 空行 4413
cli.ts:145 RuntimeName function shellQuote(...) 已不在本文件
cli.ts:105 saveAdminUtok formatSecretAssignment, 1128
cli.ts:89 saveServerConfig grokBuildCliCreationFields, 1113
cli.ts:77 saveGlobal } from "../src/opencode-package-binary"; 1066
cli.ts:347 dashboardReleaseTag } 1569

没有一条是「差几行」—— 全是指向完全无关的代码。 而它们都长得像有效引用(格式对、行号在文件范围内、点开能打开),所以读的人不会怀疑。

🔴 RuntimeName 那条尤其值得说:本 PR 发现它已经搬出 cli.ts,现在在 agent-network/src/normalize-runtime.ts。我验了 —— 该文件第 16 行 export type RuntimeName =这不是修行号,这是修「文件都换了」。

② 新锚点:21 条,我逐条 grep 过

把 diff 里所有 搜 \…`的内容抽出来,在origin/main` 的源码里找:

21 条锚点 → 20 条在 cli.ts 里命中
剩 1 条(`export type RuntimeName =`)不在 cli.ts —— 因为它指的就是 normalize-runtime.ts,
已单独验过在第 16 行。

21/21 有效。 🔴 这一步不能省:把一个错的行号换成一个错的搜索串,读起来会更可信,坏得更彻底。

③ 一个这个 PR 没解决、也不该由它解决的问题

行号 pin 有 #843 那道门在数(守住不再变多)。符号锚点没有任何门在看。

它们确实不会因为「上面插了几行」而失效 —— 但会因为改名而失效,而且失效之后同样没有任何东西会喊。我上面那段 grep 就是一次性写的,不在仓里。

建议单开一道门:扫 docs/** 里所有 搜 \…`` 锚点,断言每一条在它自己点名的那个文件里存在。判据现成,今天这次的输出就是它的第一组期望值。这比继续数行号 pin 更有价值 —— 行号 pin 的数量在降,符号锚点的数量在升。

冲突全是同一形状:本分支把 `[cli.ts:228 loadProfile](…#L228)` 换成
`[cli.ts](…) —— 搜 \`function loadProfile(\``,而 main 上 #869 改了同文件别处
(runtime 表、目录树),git 判成重叠。

八处一律取本分支侧。核过没有连带丢东西:

  merged 与 origin/main 的逐行 diff = 12 删 / 12 增,**每一条被删的 main 行都含
  `cli.ts` 引用** —— 也就是说改动只落在 pin 上,#869 的 runtime 表和目录树改动
  一个字都没动。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vansin

vansin commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

合并 main 之后 CI 全绿,已合。

八处冲突全是同一形状(本分支换成符号锚点 vs main 上 #869 改了同文件别处),一律取本分支侧

核过没有连带丢东西:merged 与 origin/main 的逐行 diff = 12 删 / 12 增,每一条被删的 main 行都含 cli.ts 引用 —— #869 那次改的 runtime 表和目录树一个字都没动。

@vansin
vansin merged commit 46829d4 into main Aug 17, 2026
7 checks passed
vansin added a commit that referenced this pull request Aug 17, 2026
#857 把 docs 里的行号 pin 换成了符号锚点。换得对:那 13 条行号逐条对下来
**13 条全错** —— `loadProfile` 实际在 cli.ts:1274(doc 写 228),`runCommand`
在 5812(doc 写 2044),`ensureMcpJson` 指的那一行是**空行**。而它们全都长得像
有效引用:格式对、行号在文件范围内、点开能打开,所以读的人不会怀疑。

但换完之后留了一格没人看:**符号锚点不会因为「上面插了几行」失效,却会因为
改名而失效,而失效之后同样没有任何东西会喊。** #843 那道门在数行号 pin(守住
不再变多),符号锚点在变多,一直没有对应的门。

判据:每一条 `搜 \`X\`` 里的 X,必须在**它左边最近的那个源码链接**指向的文件里
逐字存在。两类失败都报 —— 找不到(改名/删除/写错),以及前面根本没有链接
(无法判定它指哪个文件,这本身就是缺陷)。

## 起点(与手工核对一致)

    checked 21 symbol anchor(s) across 262 tracked doc(s); 21 resolved
    every symbol anchor exists in the file it names.

21 这个数是先手工数出来的,再让脚本跑 —— 两边对上才用。

## 见红(三种坏法,三种输出,互不相同)

    A 改一个锚点为源码里不存在的名字   → rc=1  "not found in 'agent-network/bin/cli.ts'"
    B 去掉锚点前面的链接               → rc=1  "no source link precedes this anchor"
    C 把扫描范围改成一个不存在的目录   → rc=2  "0 tracked .md … 扫描范围塌了"

三份输出的 md5 两两不同。C 是分母承重:🔴 这道门最可能的坏法不是判据写错,
是**一条都没扫到然后打印一片绿** —— 那种假绿和真绿逐字相同。所以扫到 0 个 md
或 0 条锚点一律 exit 2,让「没问题」和「没有看」在输出上长得不一样。

变异做完全部还原:`cmp docs/architecture.md` 与 main 逐字节相同。

## 🔴 刻意不加 paths 过滤

这道门的主要失效场景是**有人在 cli.ts 里把一个函数改名**,不是有人改了 doc。
按 `docs/**` 过滤的话,改源码的 PR 不会触发它 —— 门在、判据也对,但在最需要它
的那一类改动上永远不会被触发。整个脚本跑完不到一秒,省这点没有意义。

`--selftest` 8 条,含「无锚点文本 → 计数必须为 0」。job 名 `doc-symbol-anchors`
全仓唯一(25 个 job,25 个不同的名字)。

Co-authored-by: t <t@x>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
vansin pushed a commit that referenced this pull request Aug 17, 2026
main 上已经动过这两行,方向和本 PR **不同**:

  main:  链接改成 blob/main/…(不带 #L),行号退回正文「(当时在 61 行)」
  #851:  链接钉到当时的提交 blob/3a387204/…#L61

两个都成立,但各解决了一半:

  - main 那版**链接永远打得开**,但点开是今天 13753 行的 cli.ts —— 第 61 行现在
    是一句 import,读者拿不到那句话说的东西;
  - #851 那版**点开就是** `const PINNED_SERVER_VERSION = "0.8.0";`,但链接文字
    还是裸的 `cli.ts:2589`,不说明那处是干什么的。

取并集:**URL 用 #851 的提交钉法,链接文字用 main 的描述性写法**,并在正文里
写清「钉在当时的提交 3a38720,第 61 行」。

实跑核过(该提交下 cli.ts 共 7203 行):
    L61   const PINNED_SERVER_VERSION = "0.8.0";
    L2589 const serverArgs = ["--bun", `@sleep2agi/commhub-server@${PINNED_SERVER_VERSION}`];
对照 main 上同样两行:L61 是 `} from "../src/opencode-preset";`,L2589 是 `}`。

🔴 顺带记一条判断:同样是「行号 pin 失效」,#857 那批指向**当前**代码,正确修法是
换符号锚点(跟着代码走);本 PR 这两条在 **changelog** 里,描述的是当时的状态,
正确修法是**钉提交**。`PINNED_SERVER_VERSION = "0.8.0"` 这个事实只在那个提交上
成立 —— 换符号锚点反而会指向一个今天已经不是 0.8.0 的常量。
**症状一样,修法取决于那句话说的是「现在」还是「当时」。**

合并后跑过:
  check-docs-integrity.py     no problems(6 个 changelog 的 main 行锚点 = 0)
  check-doc-symbol-anchors.py 21/21

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
vansin pushed a commit that referenced this pull request Aug 18, 2026
doc claim freshness 红了,红得对:我在 agent-node/src/cli.ts ~:462 插了 12 行,
docs/stale-issue-review.md 里三条按行号 pin 的断言整体下移 12 行。

  3468 → 3480   video_gen
  4291 → 4303   Expose CURRENT_TASK_ID
  2388 → 2400   total_cost_usd

三个都恰好 +12,等于我的插入量 —— 是纯位移,不是内容变了。

顺带在清单上方留了一条注释说明这次为什么会漂,并指出:这正是 #857 用「符号
锚点」替换行号 pin 想解决的事,而这份清单仍是行号制,**任何在上方的插入都会
让它红,而红的原因和「文档说错了」在输出上长得一样**。换成符号锚点要动
tests/test846-doc-claims 的判据,属于另一条。

  scripts/check-doc-claims.py   rc=0   claims_checked=8 claims_failed=0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
vansin added a commit that referenced this pull request Aug 18, 2026
* fix(agent-node): 拒绝 claude-code-cli 时说清它住在哪 (#909)

#917 修好了 `--help`:`--runtime` 的取值列表不再列 claude-code-cli,Runtime
段里标明它由 `anet` 提供。但同一句错话留在了**用户真正撞上的那一处**:

  $ agent-node --alias t --runtime claude-code-cli
  [t] Unsupported runtime "claude-code-cli". Supported: claude-agent-sdk, ...

"unsupported" 对这个二进制是真的,对产品是假的 —— claude-code-cli 已实现、
有 e2e(qa-180-rename-ghost)、在出货,只是执行道在 launcher 里
(agent-network/bin/cli.ts ~:5096,`anet node start` → launchAgent → 真的
claude CLI)。跟一个用户说"unsupported",是把他推去找一个不存在的 runtime,
而不是推去隔壁那条命令。

现在:

  [t] "claude-code-cli" does not run through agent-node — it is provided and launched by `anet` itself.
  [t] Use: anet node start <node>   (with runtime "claude-code-cli" in that node's config.json)
  [t] Runtimes agent-node can take directly: claude-agent-sdk, ...

行为没变(仍然 exit 1,RUNTIME_MAP 一个键都没加 —— 加键会让 CLI-login 用户
被静默降级到 SDK 通道,那正是上面注释警告过的)。

测试加在 #917 建的那个文件里,红绿都亲手见过:
  用 origin/main 的 cli.ts 跑 → 1 fail(打印出旧那句 Unsupported runtime)
  用本 PR 的 cli.ts 跑        → 4 pass
带一条负对照:真正不存在的 runtime 仍走原来那句,且不泄漏 `anet node start`。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(docs): 同步被本 PR 撞漂的三条行号 pin (#909)

doc claim freshness 红了,红得对:我在 agent-node/src/cli.ts ~:462 插了 12 行,
docs/stale-issue-review.md 里三条按行号 pin 的断言整体下移 12 行。

  3468 → 3480   video_gen
  4291 → 4303   Expose CURRENT_TASK_ID
  2388 → 2400   total_cost_usd

三个都恰好 +12,等于我的插入量 —— 是纯位移,不是内容变了。

顺带在清单上方留了一条注释说明这次为什么会漂,并指出:这正是 #857 用「符号
锚点」替换行号 pin 想解决的事,而这份清单仍是行号制,**任何在上方的插入都会
让它红,而红的原因和「文档说错了」在输出上长得一样**。换成符号锚点要动
tests/test846-doc-claims 的判据,属于另一条。

  scripts/check-doc-claims.py   rc=0   claims_checked=8 claims_failed=0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: t <t@t>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
vansin added a commit that referenced this pull request Aug 18, 2026
共存运行时把 Grok CLI 钉在精确 build `grok 0.2.93 (f00f96316d)`,而官方不带版本的
安装器给的是当前 stable —— #876 立案时是 1.0.4,2026-08-18 实测已是 **1.0.5**。
它一直在走,钉子不走。

原文的问题在于它是一句**现在时断言**:

  - The exact Grok CLI build `grok 0.2.93 (f00f96316d)`; the known stable installer
    may append ` [stable]` to that output.

写下时 stable 就是 0.2.93,这句是对的;今天它让读者以为跑一遍官方安装器就能得到
钉死那一版。而全文**没有任何一处**说怎么装到 0.2.93(grep 核过)。
排障段的 `Install the pinned build` 同样只说了要装,没说怎么装。

修法不是那条 issue 里建议的手拼产物 URL —— 官方安装器**自己就收版本参数**
(`TARGET="$1"`),所以走它支持的路:

    curl -fsSL https://x.ai/cli/install.sh | bash -s 0.2.93
    grok --version   # grok 0.2.93 (f00f96316d)

实测(隔离 HOME,2026-08-18):
    Grok 0.2.93 installed to …/.grok/bin/grok
    grok --version → grok 0.2.93 (f00f96316d)     ← 与钉死的串逐字相同

同时补了两件原文没说的事:
- 那个安装器**不做校验和**(对它 grep sha256/checksum 零命中)。是 xAI 的安装器不是
  我们的,写出来让信任边界显式,而不是默认。
- `docs/grok-build-runtime.md` 教的不带版本安装**对它自己讲的 grok-build-acp 是对的**
  (那条路不受钉子约束),加了交叉引用说明共存那条路不一样。两份文档各自没写错,
  合起来读才会把人带沟里 —— 这正是 #876 的形状。

引用用符号锚点不用行号:#857 把这个仓的 13 条行号 pin 换掉时,实测 **13 条全部已漂**。

Co-authored-by: t <t@t>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
vansin pushed a commit that referenced this pull request Aug 18, 2026
CI 上两条红,都是这个 PR 自己造成的,且都被仓里已有的门当场抓住:

① home-path-baseline
   新夹具里写了 `/home/dev` 和 `/home/d`。改成 `/home/user`(该名字在
   check-home-path-baseline.py 的 NOT_A_PERSON 里),201 → 198,rc=0。

② doc claim freshness(test846)
   docs/stale-issue-review.md 的 doc-claims 清单里三条 agent-node/src/cli.ts
   的行号漂了:3480→3481 / 4303→4302 / 2400→2401。

   🔴 值得记的是量级:本 PR 对 cli.ts 只有 +12/-11、净 +1 行(两个 denyPaths
   调用点从内联字面量换成 grokCliDenyPaths(...)),却让三条本来正确的文档引用
   同时变错,而且**两个方向都有**——增删发生在不同位置。

   这正是 #857 用符号锚点替换行号 pin 想解决的那件事。那份清单是行号制,
   任何在上方的增删都会让它红,而**红的原因和「文档说错了」在输出上长得一样**。
   注释里把这次的位移量记下来了,和上一次 #950 的 +12 放在一起。
vansin added a commit that referenced this pull request Aug 18, 2026
* test(grok-cli): put a gate on the sandbox deny list cli.ts passes (#885)

#885 verified that the isolated GROK_HOME is absent from every sandbox deny
profile, tried the one-line fix, and then withdrew it — because nothing in the
repo watches this list:

    grok-copresence suite        165 pass  ← never touches cli.ts or denyPaths
    grok-build-cli-home suite     41 pass  ← tests the callee, which faithfully
                                             writes whatever it is handed

That is the right call and the right reason. A caller that forgets a path sails
through every test of the mechanism, so the fix could not be reviewed as a
behaviour change. This commit builds the missing gate so it can be.

- `grokCliDenyPaths()` is now the single place the list is decided; both call
  sites in cli.ts (the co-presence leader and prepareRuntime) go through it.
  The list itself is byte-for-byte what it was, including the `configFilePath
  || ""` placeholder, so prepareGrokCliHome still receives the same arity.
- The call-site test asserts on shape rather than on an import: zero
  `denyPaths: [` literals, exactly two `denyPaths: grokCliDenyPaths(`. Merely
  checking that the helper is imported would pass with a literal array sitting
  next to it.
- One test states the open gap out loud — the isolated GROK_HOME is still not
  denied. It fails the moment someone adds it, which forces the decision to be
  written down instead of landing silently.

Witnessed red first: before cli.ts was rewired, the call-site test failed with
2 literals found where 0 were expected.

Full agent-node suite: 1285 pass / 0 fail across 92 files
(TMPDIR=/run/user/1000/anet-tests, see #884/#865).

Not done here: the deny entry itself. Reading the code, sandbox.toml constrains
Grok's *tool* sandbox and the isolated home holds the generated sandbox.toml,
requirements.toml and an agent_id credential link — so denying it looks both
safe and correct. I have not verified that at runtime, and a sandbox change
should not land on a code reading.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(#984): 夹具改用占位家目录名;同步被本 PR 撞漂的三条文档行号 pin

CI 上两条红,都是这个 PR 自己造成的,且都被仓里已有的门当场抓住:

① home-path-baseline
   新夹具里写了 `/home/dev` 和 `/home/d`。改成 `/home/user`(该名字在
   check-home-path-baseline.py 的 NOT_A_PERSON 里),201 → 198,rc=0。

② doc claim freshness(test846)
   docs/stale-issue-review.md 的 doc-claims 清单里三条 agent-node/src/cli.ts
   的行号漂了:3480→3481 / 4303→4302 / 2400→2401。

   🔴 值得记的是量级:本 PR 对 cli.ts 只有 +12/-11、净 +1 行(两个 denyPaths
   调用点从内联字面量换成 grokCliDenyPaths(...)),却让三条本来正确的文档引用
   同时变错,而且**两个方向都有**——增删发生在不同位置。

   这正是 #857 用符号锚点替换行号 pin 想解决的那件事。那份清单是行号制,
   任何在上方的增删都会让它红,而**红的原因和「文档说错了」在输出上长得一样**。
   注释里把这次的位移量记下来了,和上一次 #950 的 +12 放在一起。

---------

Co-authored-by: t <t@t>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant