Skip to content

fix(docs): 修 6 处指向不存在实体的文档硬伤——迁移文件名、ACP 审批链(Responder 在 edge-server 0 命中)、SDK 适配器注册事实(sdkAdapterIDs/IsSDKAdapter 0 命中)、run.error→run.failed、projectQueries 归属 Web,并把 known-flaky 自写的 300 行拆分阈值对齐门禁真实的 170(5 文件净 0 行) - #2289

Merged
DeliciousBuding merged 3 commits into
masterfrom
docs/hygiene-round71
Sep 3, 2026

Conversation

@DeliciousBuding

Copy link
Copy Markdown
Collaborator

做了什么

文档屎山批(round-71):把活跃文档里指向不存在实体的 6 处硬伤改成事实,并修掉 1 处「文档自己写的规则与门禁不一致」。5 files changed, 6 insertions(+), 6 deletions(-) —— 全是同行替换,不增行(各文件仍在自己的行数预算内)。

文件 原文(假) 改成(真) 主机核验
docs/architecture/05-deployment.md hub-server/migrations/00620063 0062_agent_team_runs_indexes.up.sql0063_agent_run_events_unique_seq.up.sql ls hub-server/migrations/ 两个文件都在 ✅
docs/architecture/03-runtime-adapters.md 审批链 request_permissionResponder → broker session/request_permissionPermissionDecisionBrokerRequestPermission 桥接) git grep Responder -- edge-server = 0 命中acp.go:122-124acp_client.go:46 写的正是 session/request_permission → RequestPermission
同上 SDK 适配器「属于 sdkAdapterIDsIsSDKAdapter() 返回 true」 注册 ID anthropic-sdk/openai-sdk,由 cmd/agenthub-edgeregisterSDKAdapters--anthropic-sdk-path/--openai-sdk-path 注册 git grep "sdkAdapterIDs|IsSDKAdapter" = 0 命中adapter_registry.go:62,140 = registerSDKAdapters
docs/architecture/06-auth-identity.md 「所有 Desktop 的 Hub API 查询(… projectQueries.ts)」 Desktop 三个查询文件 + 明写 projectQueries.tsapp/web app/desktop/src/api/projectQueries.ts 不存在app/web/src/api/projectQueries.ts 存在 ✅
docs/architecture/11-protocol-capability-mapping.md Run lifecycle 事件 run.error run.failed api/events.mdedge-server/internal/httpserver/server.golifecycle/* 用的都是 run.failedrun.errorapi/、edge 生产代码里 0 命中 ✅
docs/governance/known-flaky.md 「本文件超过 300 行时拆分」 「超过 170 行(verify-doc-ssot.py 行数预算)时拆分」 verify-doc-ssot.py:304 = "docs/governance/known-flaky.md": 170;文件当前 167 行 ⇒ 原文档给的自拆阈值比门禁晚 130 行,按它做必然先撞门禁 ✅

普查分母(车道实测,主机抽查复核)

门禁(主机独立复跑)

$ python3 scripts/verify/verify-doc-ssot.py                       rc=0(AGENTS path check 99 / script mirror ok / self-test wiring 29 ok / doc SSOT ok)
$ python3 scripts/verify/tests/verify-doc-entrypoints.Tests.py    rc=0(OK;被测 verifier = verify-doc-ssot.py)
$ bash /tmp/run-validate.sh <worktree>                            PASS=61 FAIL=0 SKIP(merge-ref)=1
$ git diff --check origin/master...HEAD                           rc=0
$ bash scripts/verify/verify-commit-messages.sh master HEAD       rc=0(3 commits)
$ bash scripts/verify/check-secrets.sh --range origin/master...HEAD → Secret guard passed
$ git diff --name-only origin/master...HEAD | grep -E '^(AGENTS\.md|scripts/|\.github/|Makefile|CHANGELOG\.md|docs/archives/|reference/|app/|api/openapi\.yaml)' → 空(禁区 0 命中)

行数预算最紧的 5 个文件(改后仍在预算内):05-deployment 200/200、11-protocol 200/200、04-frontend 150/150、developer-quickstart 170/170、07-design 141/150。

暗卷:植入 2 个假实体(DockerfileX 路径 + doRequestWithRetryX 符号)后,扫描器输出 PATH_MISS / SYM_MISS 两条红;revert 后复跑 0 命中 ⇒ 扫描方法不是摆设。

只报未做(需要裁决或属技术口径讨论)

docs/decisions.md 里的 deployments/dev/(历史裁决的条件句,不是当前路径声明)、EnvSanitizer 概念标签、Available=false 伪代码、05-deploymentACCESS EXCLUSIVE 锁技术口径(要不要细化到「哪些表多大」需实测数据)、ArtifactCard 功能代称、以及 docs/archives 删留 / Mobile 口径 / owner 取值域(#2258、operator 裁决)。

诚实记账

任务书里写的自测文件名 scripts/verify/tests/verify-doc-ssot.Tests.py 在本仓全历史都不存在;真实的 doc 门禁自测是 verify-doc-entrypoints.Tests.py(主机已复跑 rc=0)。这是任务书的错,不是车道的错,记在这里避免下一轮再抄错。

@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: 663abec6-7951-4043-bf4e-c4c34613af0b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@DeliciousBuding
DeliciousBuding enabled auto-merge (squash) September 3, 2026 13:07
@DeliciousBuding
DeliciousBuding merged commit 07f8926 into master Sep 3, 2026
37 checks passed
@DeliciousBuding
DeliciousBuding deleted the docs/hygiene-round71 branch September 3, 2026 13:30
DeliciousBuding added a commit that referenced this pull request Sep 3, 2026
…ktop 9 处「打不中任何缓存条目」的失效按各 handler 语义重指到真实键(用户可见后果:desktop 已读回执此前不刷新任何缓存、未读角标一直陈旧),并收敛两端分岔的会话列表键与私设字面量(#2261) (#2306)

## 缺陷本体(实测,不是推断)

`invalidateQueries` 是**前缀匹配**,而 `['hub','threads','detail',<id>]` 既不是
`['hub','threads',<id>,'messages']` 的前缀、也不是任何 shell 真实注册的键
⇒ `hubEventBridge.ts` 里 9 处失效**匹配不到任何缓存条目**:

- 5 处语义上该刷会话列表(`onMessageNew` 的 last-message 预览与未读数、`onMessageRead`
  的 unread_count、`onSessionMemberJoined`/`Left` 的成员数、`onSessionInfoUpdated` 的
  名称头像)→ 改指 `hubQueryKeys.threads.list`;
- 4 处**冗余**(紧邻的真键已覆盖)→ 直接删:`onMessagePin`/`onMessageUnpin` 上一行就是
  `threads.pins(sessionId)`;`onSessionDissolved` 两行后是宽前缀 `threads.root`(它同时
  覆盖 list/messages/pins);`onAgentDone` 下一行就是 `threads.messages(threadId)`。

用户可见的那一条是 `onMessageRead`:它的注释原文写着「read receipts affect thread-level
unread_count → invalidate thread detail」,而它**只**失效这一个幽灵键 ⇒ desktop 上收到
已读回执不刷新任何缓存、未读数保持陈旧。与 #2252 修掉的 6 处 MESSAGE_* 失效同一故障
模式,只换了个键。

同时删掉 `threads.all(projectId)`:**hub 家族**的它同样是幽灵(生产 0 消费者——唯一在用的
`threads.all` 是 `desktop/src/api/threadQueries.ts:18` 的 **edge** 家族,那一族有真消费者、
一字未动),且它无参时返回值 == `root`,正是「拿 root 当查询键」这条被 ADR-029 禁掉的形状。

## 两端分岔收敛(同一个后端集合 `/client/sessions`,此前两个键)

- 新增 `hubQueryKeys.threads.list = ['hub','threads','list']`,并在 queryKeys.ts 就地写下
  canonical 形状(root 只作宽失效前缀、集合用 list、子资源必须有工厂、无消费者的工厂不得存在)。
- desktop `sessionQueries.ts` 的私设 `hubSessionsListKey = ['hub','sessions']` → `threads.list`
  (平台包不得私设 key 数组);同文件 `queryKey: ['hub','threads',sessionId,'pins']` 字面量 →
  `threads.pins(sessionId)` 工厂。
- web `contactQueries.ts` 的 `sessionsQueryKey = hubQueryKeys.threads.root` → `threads.list`。
  这一条正是分岔的根因:同一个 `root` 前缀在 web 承担「会话列表」、在 desktop 承担
  「所有 transcript」,于是「刷新会话列表」在两端语义相反。

## 测试(`desktop/src/stores/hubEventBridge.test.tsx` 新增 7 例,14/14 全绿)

断言链**刻意做成两环**,因为用自造键播种的测试什么都证明不了(#2252 的原始教训):
① `sessionQueries.test.tsx` 钉住 live 的 `useHubSessions` 注册的正是 `threads.list`;
② 本套件钉住 bridge 对 5 类帧(MESSAGE_READ / MESSAGE_NEW / SESSION_MEMBER_JOINED /
SESSION_MEMBER_LEFT / SESSION_INFO_UPDATED)失效的正是同一个工厂键 ⇒ 合起来才是
「帧落在 UI 真读的那个缓存条目上」。另加 MESSAGE_PIN → `threads.pins` 命中,
以及一例把「幽灵工厂不许回来」钉死(`threads.detail` / `threads.all` 必须 undefined、
`list` 形状正确、root 仍是 list 的前缀所以宽失效不退化)。

被改到的既有断言只有**钉字面量**的那些,行为断言一条未动:
`queryKeys.test.ts` 的 `threads.detail`/hub 侧 `threads.all` 形状断言(工厂已删)、
`sessionQueries.test.tsx` 的 `SESSIONS_LIST_KEY`(从私设字面量改为工厂,反而更强:
它现在钉的是「hook 的键 == 共享工厂」)、`normalizeHubMessages.ts:90` 注释里点名的
`threads.detail`(改成 `threads.messages`,避免留下指向已删实体的注释=#2289 那一类)。

## 门禁

三个包 typecheck 干净(删掉两个工厂**没有**造成任何编译错误,这本身就是「0 消费者」的
机器证明);`@agenthub/shared` src/stores **87 例**、desktop src/api+src/stores
**14 文件/182 例**、web src/api+src/platform **20 文件/199 例**全绿;本地复跑 validate
结果见 PR。

Refs #2261(S1 裁决 = ADR-029,已落 docs/decisions.md)

Co-authored-by: DeliciousBuding <DeliciousBuding@users.noreply.github.com>
Co-authored-by: Cursor <cursor@vectorcontrol.tech>
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