Skip to content

📄 修正架构/测试/i18n 文档过期事实并解决跨文档政策冲突#1616

Merged
CodFrm merged 13 commits into
scriptscat:mainfrom
cyfung1031:claude/scriptcat-docs-update-59bb37
Jul 20, 2026
Merged

📄 修正架构/测试/i18n 文档过期事实并解决跨文档政策冲突#1616
CodFrm merged 13 commits into
scriptscat:mainfrom
cyfung1031:claude/scriptcat-docs-update-59bb37

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes ... / 已修复或实现文档过期事实与跨文档政策冲突
  • reviewed by human / 通过人工检查
  • Changes tested / 已完成测试 —— 见下方"验证"

背景

AGENTS.md/架构文档等仍把"新实体一律 Repo<T>"、"service 都在 src/app/service/<context>/"当作普遍规则,
但当前树已经有 DAO<T>(Dexie)、OPFSRepo(OPFS)、custom repository,以及 src/app/service/agent/
extension/ 等跨 context 组织方式。当前架构文档也完全没有覆盖已合入的 Agent 子系统。此外,
.github/copilot-instructions.mddocs/verification.mddocs/references/design-patterns.md 等文档
存在过期事实(Firefox Offscreen、path alias 示例、固定 locale 数量、未经测量的百分比断言)与政策前后不一致
(TDD 例外未在 architecture/verification 中同步)。

本次改动

  • AGENTS.md / .github/copilot-instructions.md / docs/architecture.mddocs/references/architecture-*.md:
    Repo<T> / DAO<T> / OPFSRepo 的后端分类替换过期的"一律 Repo<T>"规则;架构速览补充 agent/
    extension/queue.ts;新增 docs/references/architecture-agent.md 覆盖 Agent 子系统(工具注册表、
    LLM 工具循环、后台会话/子代理/定时任务生命周期、存储后端选择、跨 context 委派边界)。
  • docs/references/architecture-build.md: rspack entry 清单补上 commonjson.worker
  • docs/references/architecture-gm-api.md: 明确 sendMessageconnect 的选择依据,以及 DOM handler /
    linter 注册的准确落点路径。
  • docs/develop.md: 记录 toast.tsno-restricted-imports 的完整豁免(同时覆盖 Sonner 与 Radix
    两类限制,不是只豁免 Sonner)。
  • docs/verification.md: 补充"何时可跳过本指南"的路由说明、按比例的前置检查(而非机械要求全量 Vitest)、
    bug 复现分支与 TDD 例外的同步、可见化的"先建 report.md"步骤、双主题 UI 验证的注意事项与证据要求。
  • docs/references/verification-debugging.md: 补充 Firefox 无独立 Offscreen 页面的调试提示。
  • docs/references/design-patterns.md: 移除过期的固定 8 locale 数与未经测量支持的德语/俄语约 30% 更长的
    断言,改为要求用当前 locale 表中的真实长字符串 fixture 验证。
  • docs/translation.md / src/locales/README.md: 记录 i18n-usage.test.ts 的真实扫描范围与盲区;
    修正 i8next 拼写;翻译工作流改为链接 translation.md,不重复维护第二份流程。
  • docs/DOC-MAINTENANCE.md: 扩大到全部 tracked 的 agent/contributor Markdown(含 .github/*.md
    package-local README);新增 baseline/working-diff/proposed-final-tree 的区分、跨文档政策一致性检查、
    lint/config 记录深度要求、批量编辑建议、隐私/来源清理 gate、link-checker 的 best-effort 边界说明、
    duplicate heading 的 review-queue 处理方式,以及"完成声明需匹配实际证据范围"的要求。
  • docs/README.md / docs/pull-request.md: 更新维护范围摘要与 owner 关系;PR 指南明确只拥有 PR body,
    title/commit 规则链接到 develop.md,并补充文档类 PR 的按比例验证要求。
  • packages/message/README.md: 按当前 API 重写传输方式说明(单次调用用 sendMessage、流式/长连接用
    connect、广播用 MessageQueue),并链接 SW→Offscreen 的 Chrome/Firefox 差异。
  • packages/filesystem/README.md: 补齐当前 provider 清单(Google Drive、Dropbox、S3),并说明 Zip 是同一
    抽象的归档/本地备份实现,不是远端 provider。
  • packages/cloudscript/README.md: 修正标题与用途描述,说明当前只有 local target,产出可执行归档而非
    上传云端。
  • 删除未被任何 tracked 文件引用、且已过期(仍标注"7 个 locale"迁移快照,当前实际为 9 个)的
    src/pages/options/routes/Setting/i18nKeys.md

已知限制

  • 本轮范围为 agent/contributor 向 Markdown 的事实与政策一致性审计;README.md、四份 localized README、
    SECURITY.mddocs/cloud-sync.md、九份 docs/references/terminology-*.md
    .github/pull_request_template.mdexample/agent/README.md
    packages/chrome-extension-mock/README.mdCONTRIBUTING*.md 未改动 —— 未发现与当前树矛盾的具体错误,
    或需要产品/安全 owner 确认才能改动的内容,不属本轮范围。
  • .github/copilot-instructions.md 已在 review 迭代中缩减为纯 router(只保留 Chinese review 与全量
    diff review 的 Copilot 专属规则,共享架构/命令/测试内容链接到 AGENTS.md);未做的是验证目标 Copilot
    surface 是否会可靠跟随该链接,这一点仍标记为待确认,不代表文件结构本身未缩减。

Review 迭代记录

  • 第一轮(commit 8525a8ee)后收到 8 项 review 发现(AGENTS.md/copilot-instructions.md 常驻文档冗余、
    DOC-MAINTENANCE.md 固定文件清单遗漏新增文档、toast.ts override 措辞误导、architecture-agent.md 三处
    错误 class 名、retry 4xx 排除范围失准、architecture-data.md 重复 heading、cloudscript README 可运行性
    失实、develop-testing.md 不可审计的 ~15% 数字),已在 commit d6f33294 全部修复。
  • 第二轮(对 d6f33294 的 review)后收到 3 项 medium 发现(architecture-agent.md 把 screenshot/monitoring
    错误套进 default/trusted 二选一模型、link-checker 排除模式漏掉 mailto:/app: 导致 3 条合法链接被
    误报 BROKEN、PR 描述本节的"未缩减为纯 router"说法与最新文件矛盾),已在 commit dc5cf980 修复,并已
    更新本节。
  • 第三轮(对 dc5cf980 的 review)后收到 1 项 high、1 项 low 发现(architecture.md 的 "A new service" 配方
    仍规定统一 Group + IMessageQueue + DAOs constructor,与 architecture-services.md 的 nearest-neighbor
    原则矛盾;architecture-services.md 遗留上一轮未改到的错误 class 名 AgentChatService/TaskService;
    以及本节"验证"里的复现命令没跟上最终 ~~~ fence 处理版本),已在 commit 70c54667 修复,并已更新本节与
    下方"验证"。
  • 第四轮(对 70c54667 的 review)后收到 1 项 medium 发现(architecture-services.md 把 context service
    描述成统一 "pure DI / never new internally / no work in constructor",但 ResourceService 会字段初始化
    内部创建 ResourceDAO 并在 constructor body 做 logger/cache 初始化、SubscribeService 同样内部创建两个
    DAO,三处绝对表述与实现矛盾),已在 commit 7d3e6da5 修复:改为"共享/外部拥有的 collaborator 通常经
    constructor 注入,service 本地专用的 DAO/helper 是否内部 new 因 service 而异",并以两个反例佐证。
  • 第五轮(对 7d3e6da5 的完整 PR review)后收到 6 项事实问题(queue.ts 被误写成 MessageQueue wiring,
    实际只有 payload/type 定义;"跨 service DAO 必须共享同一实例"的推导与 ScriptService/SubscribeService
    各自构造独立 SubscribeDAO/ScriptDAO 矛盾;MockMessage 被误当作 IMessageQueue 替身,实为
    Message transport;ScriptService 示例写成空 constructor 且 handler 数标成会漂移的 ~20;
    ServiceWorkerManager 被描述成给每个 service 都传 Group + mq,但 LogService/AgentService 都没有
    mq;OffscreenManager/SandboxManager/ScriptRuntime 被误称"遵循同一 shape"),已在 commit
    09fe390e 全部修复,逐条对照源码核实。
  • 第六轮(对 09fe390e 的完整 PR review)后收到 2 项 medium、2 项 low 发现(architecture.md 仍保留统一
    constructor/init() 断言,与 service reference 已列出的反例矛盾;architecture-services.md 把 handler
    注册绝对写成发生在 init(),但 ScriptRuntime.contentInit() 会在 init() 之前单独注册 handler;
    MessageQueue 实例化范围被写成过宽的"per entry point/manager",实际只有 service_worker.ts、
    offscreen/base.ts、以及订阅广播的 UI 页面会实例化;DAO 共享/自建的原因被写成已证实的实现事实,但源码只
    证明是 case-by-case),已在 commit a310dc80 全部修复,并已用 git grep 确认仓库内不再有统一
    constructor/init() 措辞残留。
  • 第七轮(对 a310dc80 的 review comment)后收到 1 项 high、2 项 medium、1 项 low 发现(architecture.md
    的 Testing 段在另一处重复了刚被否定的"service 统一经 constructor 收 IMessageQueue/DAO、用 MockMessage
    构造 service"说法;Big Picture 图注称 MessageQueue 向 ALL contexts 广播,与本轮已确立的实例化边界矛盾;
    "A new persisted entity" recipe 仍统一要求 construct in manager + group.on,与 AgentModelService/
    AgentChatRepo 的实际 ownership 矛盾;建议的 git grep "new MessageQueue" 命令会误命中
    MessageQueueGroup 与测试文件),已在 commit 2ca37683 全部修复。

验证

相对链接检查的权威、可复现命令唯一存放在 docs/DOC-MAINTENANCE.md § Link integrity
——本节不再复制一份可能与之漂移的副本(上一轮已发生过一次:PR body 里的命令缺了最终版本的 ~~~ fence 处理)。
其余检查:

git diff --check   # 无空白/合并冲突标记问题
  • 逐条事实核对依据 git grep/git ls-tree 对当前树(src/app/reposrc/app/service/rspack.config.ts
    eslint.config.mjstsconfig.jsonsrc/locales/src/service_worker.ts
    src/app/service/offscreen/event_page_manager.tspackages/filesystem/)的直接查询结果,详见各文件 diff。
  • 未运行 pnpm test/pnpm run lint:本次改动仅涉及 Markdown,不涉及可执行代码路径。
  • 已按 DOC-MAINTENANCE.md 的权威命令在最终树重跑一次:输出 0 条 BROKEN;并注入一条无效相对链接确认检查
    仍会正确报错(验证后已还原,未保留在 diff 中)。
  • 已核对仓库内不再有 AgentChatService/AgentCompactService/裸 TaskService(误指 Agent 服务时)的残留
    引用。
  • 最终树 ref:2ca376838919bb397725b77661b89868ab0a317b(2ca37683)。

- AGENTS.md/copilot-instructions.md/architecture*.md: 用 Repo<T>/DAO<T>/OPFSRepo 后端分类
  替换"新实体一律 Repo<T>"的过期普遍规则;架构速览补充 agent/、extension/、queue.ts;
  新增 docs/references/architecture-agent.md 覆盖 Agent 子系统(工具注册表、LLM 工具循环、
  后台会话/子代理/定时任务生命周期、存储后端、跨 context 委派边界)
- architecture-build.md: rspack entry 补上 common、json.worker
- architecture-gm-api.md: 明确 sendMessage vs connect 的选择依据与 DOM/linter 落点路径
- develop.md: 记录 toast.ts 对 no-restricted-imports 的完整豁免(同时覆盖 Sonner 与 Radix)
- verification.md: 补充"何时可跳过本指南"、按比例的前置检查、TDD 例外与 bug 复现的同步、
  可见的 report.md 创建步骤、双主题验证注意事项
- verification-debugging.md: 补充 Firefox 无独立 Offscreen 页面的调试提示
- design-patterns.md: 移除过期的固定 locale 数与未经测量的百分比断言
- translation.md/src/locales/README.md: 记录 i18n-usage.test.ts 的真实扫描范围与盲区;
  修正 i8next 拼写;翻译工作流去重指向 translation.md
- DOC-MAINTENANCE.md: 扩大到全部 tracked agent/contributor Markdown,新增
  baseline/working-diff/final-tree 区分、政策一致性检查、隐私扫描、批量编辑建议
- packages/{message,filesystem,cloudscript}/README.md: 修正过期/模糊的实现描述
- 删除未被引用且已过期的 src/pages/options/routes/Setting/Setting/i18nKeys.md 迁移快照

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

Copy link
Copy Markdown
Collaborator Author
严重度 Finding 证据 为什么 最小修正 验证
High 常驻文档反而显著增长,Copilot 副本还保留错误的统一 service 模式。 measured — [AGENTS.md](/AGENTS.md:58) 增长 21.4%;[copilot-instructions.md](/.github/copilot-instructions.md:7) 增长 14.9%,其中共享架构/命令/测试内容占全文约 79%。 每次 agent 任务都承担重复 token;Copilot 仍会把 Agent service 错套成统一 Group/IMessageQueue/DAO constructor。 AGENTS.md 只保留 invariant/router;Copilot 只保留工具特有规则、中文 review 与完整 diff review,并路由到 owner docs。若目标 surface 不能可靠读取链接,只保留经验证的最小 fallback。 重新计算字符/词数,并搜索两份常驻文件中的重复 inventory。
High 文档维护“harness”没有覆盖其宣称的全部 tracked Markdown。 observed — [DOC-MAINTENANCE.md](/docs/DOC-MAINTENANCE.md:169) 仍使用固定列表,遗漏 .github、package/source README 和新增 Agent reference;[docs/README.md](/docs/README.md:14) 也未索引新文件。 校验可能输出 clean,却根本没检查声明范围,造成 false confidence。 git ls-files '*.md' 生成 inventory;明确每项检查读取 final-tree ref 还是 proposed worktree;把 architecture-agent.md 加入 index、ownership table。 比较实际检查集合与 tracked inventory,并在最终树重跑 link check。
High 把 lint 漏洞写成了 Radix 单包 import 的许可。 observed — [develop.md](/docs/develop.md:71) 说 toast.ts 可使用 @radix-ui/react-*;[eslint.config.mjs](/eslint.config.mjs:97) 实际是整个 rule 被关闭,而 [harness.test.mjs](/eslint-rules/harness.test.mjs:74) 没覆盖该路径。 Agent 可引入违反 merged radix-ui 约定、但能通过 lint 的代码。 说明只有 Sonner toast 是有意例外,Radix 约束仍适用;最好收窄 override,并增加 toast.ts 的 Radix harness case。 toast.ts 分别运行 Sonner/Radix fixture。
Medium 新 Agent 文档包含不存在的 class 名和错误职责。 observed — [architecture-agent.md](/docs/references/architecture-agent.md:20) 写成 AgentChatServiceTaskServiceAgentCompactService;实际为 ChatServiceAgentTaskServiceCompactService。同处还把 navigation 归给 dom_cdp.ts 精确 identifier 是 agent 的查找入口,错误名称会直接导致错误定位和修改。 修正 class 名;navigation 应归于 dom.ts/chrome.tabs,CDP 描述限定为 trusted input/特定截图路径。 对表中每项执行 git grep 'export class',并检查 navigate 落点。
Medium Agent 文档高估 retry contract 与测试覆盖。 observed — [architecture-agent.md](/docs/references/architecture-agent.md:59) 声称排除全部 4xx,但实现只显式排除 400/401/403/404;[测试段](/docs/references/architecture-agent.md:110) 声称每个列出文件都有 co-located test,文件 inventory 不支持该结论。 会让 reviewer/agent 对错误重试边界及 regression coverage 产生虚假信心。 按已测试粒度描述 retry;测试段改成代表性 coverage,并明确不能由文件名推断完整覆盖。 增加 4xx boundary tests;比较 production/test inventory。
Low 重复 Repo<T> heading。 observed — [architecture-data.md](/docs/references/architecture-data.md:16) 连续出现两次。 产生重复 anchor 与维护噪声。 删除一个 heading,保留现有主 anchor。 重跑 duplicate-heading 与 inbound-anchor 检查。
Low Cloudscript 不是解压后即可直接用 Node 运行。 observed — [README](/packages/cloudscript/README.md:8) 如此描述,但模板声明外部 scriptcat-nodejs dependency。 使用者跳过依赖安装会首跑失败。 改为“安装声明依赖后可在本地运行”,并写稳定的 run command。 导出到临时目录,安装依赖后实际运行。
Low 保留了不可审计的 ~15% 性能数字。 observed — [develop-testing.md](/docs/references/develop-testing.md:13);PR 证据没有对应命令、环境或重复测量。 历史数字会逐渐变成看似权威的错误事实。 删除百分比,或补充可重复测量条件。 同环境重复 before/after TSX suite 测量。

回应 PR review (scriptscat#1616 review comment):

- .github/copilot-instructions.md: 缩减为纯 router + Copilot 专属规则(中文 review、
  全量 diff review),共享架构/命令/测试内容改为链接 AGENTS.md,消除与常驻文档的重复
- AGENTS.md: 精简 Service & Data Layers 与 SOLID 条目的内联细节,改为更短的指针链接,
  降低常驻文件的 token 增长
- docs/develop.md: 修正 toast.ts override 的措辞——只有 Sonner 例外是有意的,Radix
  限制仍是约定但当前未被 harness 覆盖,不应读作"允许导入 Radix 单包"
- docs/references/architecture-agent.md:
  - 修正三处错误 class 名(ChatService、AgentTaskService、CompactService,
    而非 AgentChatService/TaskService/AgentCompactService)
  - 修正 retry 排除条件的精确描述(只排除 400/401/403/404,不是全部 4xx)
  - 修正导航实现归属(chrome.tabs,在 dom.ts 中,与 trusted 模式无关)并澄清
    dom_cdp.ts 是 dom.ts 调用的 helper 而非独立服务
  - 修正测试覆盖声称,改为要求现场核对 test 清单而非假设完整覆盖
- docs/references/architecture-data.md: 删除重复的 `Repo<T>` heading
- docs/DOC-MAINTENANCE.md: link-integrity 脚本改用 `git ls-files '*.md'` 动态发现,
  而不是遗漏 .github/package README 与新增 reference 的固定列表;架构 owner 行补上
  architecture-agent.md
- docs/README.md: 索引补上 architecture-agent.md
- docs/references/develop-testing.md: 删除不可审计的 "~15%" 性能数字,改为要求
  同环境实测
- packages/cloudscript/README.md: 修正导出包并非解压即可运行——package.json 声明了
  外部依赖 scriptcat-nodejs,需要先 npm install

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

Copy link
Copy Markdown
Collaborator Author

Addressed in d6f3329 (pushed):

严重度 Finding 处理
High AGENTS.md/copilot-instructions.md 常驻内容显著增长、重复 copilot-instructions.md 缩减为纯 router + Copilot 专属规则(中文 review、全量 diff review),共享架构/命令/测试内容改链接 AGENTS.mdAGENTS.md 的 Service & Data Layers、SOLID 条目精简为更短指针链接
High DOC-MAINTENANCE.md link-integrity 用固定列表,漏掉 .github、package/source README 与新增 reference 改用 git ls-files '*.md' 动态发现;docs/README.md 与 DOC-MAINTENANCE.md 的 architecture owner 行补上 architecture-agent.md
High develop.md 把 toast.ts 的 lint 漏洞写成 Radix 单包 import 许可 改为:只有 Sonner 例外是有意的;Radix 限制仍是约定但 harness.test.mjs 当前未覆盖该文件,不应读作"允许导入"
Medium architecture-agent.md 三个 class 名不存在 已核对 git grep "export class" 并修正为 ChatServiceAgentTaskServiceCompactService(原文误写 AgentChatService/TaskService/AgentCompactService),并把 navigation 的归属改为 dom.ts/chrome.tabsdom_cdp.ts 说明为 dom.ts 调用的 helper 而非独立服务
Medium retry contract 与测试覆盖被高估 retry 排除条件改为精确描述(只排除 400/401/403/404,不是全部 4xx);测试段改为要求现场核对 test 清单,列出几个当前无匹配测试文件的模块
Low architecture-data.md 重复 Repo<T> heading 已删除重复项
Low cloudscript README 声称解压即可用 Node 运行 已核对 package.json 声明外部依赖 scriptcat-nodejs,改为需要先 npm install
Low develop-testing.md 保留不可审计的 ~15% 数字 已删除该数字,改为要求同环境实测复现

未改动项:无(全部 8 条均已处理)。

@cyfung1031

cyfung1031 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

补充:结合 #1603@CodFrm 提到 Copilot 使用较少的情况,本 PR 也精简了 .github/copilot-instructions.md:仅保留 Copilot 专属的代码审查规则、文档路由和最小 fallback,其余架构、开发及测试说明统一由 AGENTS.md 和相关文档维护。这样既保留了现有 Copilot 工作流,也减少了重复上下文和双份文档的维护成本,避免规则长期不一致。

相关讨论:#1603 (comment)

@cyfung1031

Copy link
Copy Markdown
Collaborator Author

结论:建议继续修改。最新提交已解决前一轮大部分问题,但仍有 3 项中等优先级问题;其中两项会直接误导 agents 执行。

Severity Finding Evidence tag + locator Why it matters Better amendment Validation Confidence Residual risk
medium Agent DOM 文档错误地把 screenshot、monitoring 纳入 default/trusted 二选一。 observedarchitecture-agent.md L105-L114dom.ts L108-L178 screenshot() 不走 chrome.scripting.executeScript;monitoring 始终走 CDP。这会误述 debugger 权限边界及实现位置。 只把 default/trusted 分支用于 click/fill;分别描述 screenshot 与 monitoring 的真实路径。 T1:逐句对照对应方法。 high 源码后续变化仍需重新核对。
medium 全量 Markdown link checker 会把合法 mailto: 当成本机相对路径。 measuredDOC-MAINTENANCE.md L166-L180;原命令实际产生 3 条错误的 BROKEN 正确的文档树也会失败,agents 容易开始忽略检查输出。 排除 mailto:app:,并保留方案中的 ~~~ fenced-block 处理。 T1:修正后应无 BROKEN;再注入一个无效相对链接确认检查仍能失败。 high 仍然只是 file-target quick check,不验证完整 anchor。
medium PR 描述仍称 Copilot instructions “未缩减为纯 router”,与最新文件及最新说明相反。 observedPR 描述最新说明 completion record 自相矛盾,也会让 reviewer 误判 token-efficiency 要求尚未完成。 删除或重写该“已知限制”,并按最终 SHA 更新验证摘要。 T1:逐项比较 PR body、最新 SHA 和实际文件。 high 后续 push 后仍需再次检查 PR body。

建议仅修正上述三项,并在最终 SHA 再跑 link checker、重读 PR body;其他已修部分应保留。

回应 PR review 第二轮 (issuecomment-5016140703):

- architecture-agent.md: screenshot() 不受 trusted 选项控制(selector 截图/后台 tab
  优先用 CDP,前台 tab 用 captureVisibleTab);tab monitoring 始终走 CDP,没有
  非 CDP 路径;只有 click/fill 真正按 trusted 分支。逐条核对 dom.ts 后重写该段,
  不再把四类动作统一套进 default/trusted 二选一模型
- DOC-MAINTENANCE.md: link-integrity 脚本的排除模式补上 mailto: 与 app:(原来只排除
  https?:/#,导致 3 处合法的 mailto: 链接被误报 BROKEN),并让 fenced-block 剔除同时
  处理 ``` 与 ~~~;已验证修正后跑出 0 条 BROKEN,且对手动注入的无效链接仍能正确报错

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

Copy link
Copy Markdown
Collaborator Author

Addressed in dc5cf98 (pushed), plus a PR-body fix:

Severity Finding 处理
medium architecture-agent.md 把 screenshot/monitoring 错误套进 default/trusted 二选一 逐条对照 dom.ts 重写该段:click/fill 才真正按 trusted 分支;screenshot() 按 selector/前台后台状态自行决定(selector→CDP,后台 tab 优先 CDP 失败降级 captureVisibleTab,前台直接 captureVisibleTab),不受 trusted 影响;tab monitoring(startMonitor/stopMonitor/peekMonitor)始终走 CDP,没有非 CDP 路径
medium link checker 排除模式漏掉 mailto:/app:,误报 3 条 BROKEN 已补上 mailto:/app: 到排除模式,并让 fenced-block 剔除同时处理 ```~~~。已验证:修正后跑出 0 条 BROKEN;注入一条无效相对链接后检查仍正确报错(验证后已还原)
medium PR 描述"已知限制"仍称 copilot-instructions.md 未缩减为纯 router,与最新文件矛盾 已更新 PR body:改为准确描述当前状态(已缩减为纯 router),并新增"Review 迭代记录"小节记录两轮 review 的发现与对应修复 commit

最终树 ref:dc5cf9800cb66f9ee22c2aad97d8fca14a1129e2 (dc5cf980)。其余已修复部分未改动。

@cyfung1031

Copy link
Copy Markdown
Collaborator Author

结论:dc5cf980 已修复上一轮 3 项问题,但完整复审 26 个 Markdown 后仍发现 1 项 High、1 项 Low。建议继续修改。

Severity Finding Evidence tag + locator Why it matters Better amendment Validation Confidence Residual risk
high Service-shape 修正仍自相矛盾:总览继续规定所有新 service 使用 Group + IMessageQueue + DAOs;service reference 又称该 triple 适用于 context services,并使用不存在的 AgentChatServiceTaskService observedarchitecture.md L224-L236architecture-services.md L70-L108;实际为 ChatServiceAgentTaskService 这是 agents 会直接执行的 “Adding a service” 配方,可能强加无用依赖或搜索不存在的 class;也与 AGENTS.md、Agent guide 的 nearest-neighbor 原则冲突。 总览先分类 context/Agent/cross-cutting,再链接 #adding-a-service;不要规定统一 constructor。Reference 改正两个 class 名,并明确 context services 的依赖集合也会变化。 T1:搜索 stale identifiers/blanket triple,并逐个比较代表性 constructor。 high 新 subsystem 仍需重新检查最近邻模式。
low PR body 展示的 link-check 命令仍只剔除三反引号 fenced block,未包含最终 guide 与最新 comment 声称已验证的 ~~~ 处理。 observedPR body ## 验证最终 checker L171-L176 PR 中的复现命令不是声称实际运行的最终版本;复制后可能重新产生 tilde-fenced 示例的误报。 将 PR body 同步为最终 sed 命令,或只链接 authoritative guide,避免复制。 T1:逐字比较两处命令,并测试 ~~~ fixture。 high Checker 仍不完整验证 reference links/anchors。

验证结果:

  • 最新修正的 DOM/CDP 分支、mailto:/app: 排除、双 fence 处理及 PR 已知限制均已正确更新。
  • Corrected checker:0 条 BROKEN;坏链接负向 fixture 仍能报错。
  • Always-loaded 合计由 16,058 降至 12,166 字符,减少 24.2%;词数减少 25.8%。Token off-loading 通过。

建议保留其他修正,仅处理上述两项。

回应 PR review 第三轮 (issuecomment-5016202376):

- docs/architecture.md: "A new service" recipe 不再规定统一 `Group + IMessageQueue +
  DAOs` constructor;改为先判断 context/Agent/cross-cutting 类别,再链接
  architecture-services.md#adding-a-service 的决策路径
- docs/references/architecture-services.md:
  - 修正遗漏的错误 class 名(`ChatService`、`AgentTaskService`,而非
    `AgentChatService`/`TaskService`——上一轮只改了 architecture-agent.md,
    漏改本文件里的同一处引用)
  - 明确 context services 的依赖集合本身也会随服务变化(ResourceService 只需
    (Group, mq),PopupService 需要五个参数),"Group + IMessageQueue + DAOs"
    是构造器注入原则的简写,不是固定参数清单

已核对 `git grep` 确认仓库内不再有 `AgentChatService`/`AgentCompactService`/裸
`TaskService` 的残留引用。

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

Copy link
Copy Markdown
Collaborator Author

Addressed in 70c5466 (pushed), plus a PR-body fix:

Severity Finding 处理
high architecture.md 的 "A new service" 配方仍规定统一 Group + IMessageQueue + DAOs constructor,与 architecture-services.md 的 nearest-neighbor 原则矛盾;同时该文件遗留上一轮未改到的错误 class 名 AgentChatService/TaskService architecture.md:配方改为先判断 context/Agent/cross-cutting 类别,再链接 architecture-services.md#adding-a-service 的决策路径,不再规定统一 constructor。architecture-services.md:修正为 ChatService/AgentTaskService(上一轮只改了 architecture-agent.md,漏改这里的同一处引用——已用 git grep 确认仓库内不再有残留);并说明 context services 的依赖集合本身也会变化(ResourceService 只需 (Group, mq)PopupService 需要五个参数),"Group + IMessageQueue + DAOs" 是构造器注入原则的简写,不是固定参数清单
low PR body 的 link-check 命令仍只剔除三反引号 fenced block,未同步最终版本的 ~~~ 处理 不再在 PR body 复制一份会漂移的命令副本,改为直接链接 docs/DOC-MAINTENANCE.md § Link integrity 的权威命令;已按该权威命令在最终树重跑:0 条 BROKEN,注入无效链接仍能正确报错(已还原)

最终树 ref:70c546678d42e1dbf7654a5ecede09ece035a620 (70c54667)。其余已修复部分未改动。

@cyfung1031

Copy link
Copy Markdown
Collaborator Author
Severity Finding Evidence Why Better amendment Validation Confidence Residual risk
medium Context service 被描述成统一的 pure DI、禁止内部 new、constructor 不做任何工作;但文档举例的 ResourceService 会内部创建 ResourceDAO,并在 constructor 初始化 logger/cache;SubscribeService 也内部创建两个 DAO。 observed — 文档通则constructor 通则最新改动ResourceService 反例SubscribeService 反例 Agent 可能把合法的本地 ownership/初始化误判为违规,进行不必要的 DI 重构、增加耦合,或错误阻挡现有模式;这与 nearest-neighbor 原则相冲突。 建议缩窄为:共享或外部拥有的 collaborators 通常经 constructor 注入,但 ownership 随 service 而异,部分 service 自建本地 DAO/helper;handler 注册、跨服务订阅及依赖完整 object graph 的 late wiring 才应放进 init()。具体措辞仍应重新核对全部近邻实现。 搜索各 context service 的内部 new 与 constructor body;删除三处绝对表述;以两个反例回读,再跑链接检查和 CI。 high 三处都修正后为 low;仅修改最新段落会留下前文冲突。

回应 PR review 第四轮 (issuecomment-5016264308):

architecture-services.md 把 context service 描述成统一的 "pure DI"、"never new
internally"、"no work in constructor",但 ResourceService 会以字段初始化器内部
创建 ResourceDAO 并在 constructor body 里做 logger/cache 初始化;SubscribeService
同样内部创建 SubscribeDAO 与 ScriptDAO。三处绝对表述改为:共享/外部拥有的
collaborator 通常经 constructor 注入;service 本地专用的 DAO/helper 是否内部
`new` 因 service 而异(举 ResourceService/SubscribeService 为反例);init() 用于
handler 注册、跨 service 订阅及依赖完整 object graph 的 late wiring,而非"constructor
不能做任何事"。

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

Copy link
Copy Markdown
Collaborator Author

Addressed in 7d3e6da (pushed):

Severity Finding 处理
medium architecture-services.md 把 context service 描述成统一的 "pure DI"、"never new internally"、"no work in constructor",但 ResourceService/SubscribeService 均在内部创建自己的 DAO 且 constructor body 做了初始化工作 已核对两处源码(resource.tssubscribe.ts)确认矛盾成立:ResourceService 以字段初始化器内部 new ResourceDAO(),并在 constructor 里做 logger 赋值与 enableCache()SubscribeService 同样内部创建 SubscribeDAO/ScriptDAO。三处绝对表述(General rule / constructor 通则 / 上一轮新增段落)已统一改写:共享或外部拥有的 collaborator(其他 service、Group、被多个 service 共用的 DAO)通常经 constructor 注入;service 本地专用、无人共享的 DAO/helper 是否内部 new 因 service 而异,以这两个反例佐证;init() 用于 handler 注册、跨 service 订阅及依赖完整 object graph 的 late wiring,不是"constructor 不能做任何事"

最终树 ref:7d3e6da5dea032b421d6f262fed012d32b748425 (7d3e6da5)。其余已修复部分未改动。

@cyfung1031
cyfung1031 requested a review from CodFrm July 19, 2026 15:27
@cyfung1031 cyfung1031 added P0 🚑 需要紧急处理的内容 documentation Improvements or additions to documentation labels Jul 19, 2026
@cyfung1031 cyfung1031 added this to the 2026七月 Milestone milestone Jul 19, 2026

@cyfung1031 cyfung1031 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已对 docs/references/architecture-services.md 做了多轮事实复核(目录/职责、构造与依赖、组合根、测试替身、跨 context 生命周期)。当前仍有会直接误导贡献者的事实问题:

  1. src/app/service/queue.ts 被误写成 MessageQueue wiring,实际仅包含消息 payload/type;实现和实例化在别处。
  2. 文档推导的“跨 service 使用的 DAO 必须注入并共享同一实例”并非现有 invariant:ScriptServiceSubscribeService 各自构造 SubscribeDAO,后者也自建 ScriptDAO
  3. MockMessage 实现的是 Message transport,不是 IMessageQueue;测试中它用于构造 Server/Group,传给 service 的 pub/sub 依赖仍是 MessageQueue 或应为单独的 fake。
  4. ScriptService 示例写成空 constructor 且标注 ~20 more handlers;真实 constructor 有 logger/cache/ScriptUpdateCheck 初始化,init() 当前约有 32 个 handler。建议标注 local setup omitted,并把数量改成不漂移的 many more
  5. ServiceWorkerManager 不是给每个 service 都传 Group + mq(如 LogServiceAgentService),应改成“按需创建 Group/传入 mq”。
  6. OffscreenManagerSandboxManager 和 content/inject 的 ScriptRuntime 只是在 composition/handler registration 角色上相似,并不遵循同一依赖和初始化形状;ScriptRuntime 还有 contentInit()/externalMessage()

目录、类名和文档相对链接本轮均已核对可解析。建议修正以上事实表述后再合并。

Comment thread docs/references/architecture-services.md
Comment thread docs/references/architecture-services.md Outdated
Comment thread docs/references/architecture-services.md
…例失真、manager 构造与跨 context 假设)

回应 PR review (#pullrequestreview-4731038208):

- queue.ts 只定义 MessageQueue payload/type(如 TInstallScript、TDeleteScript),
  不是 wiring 本身——实现在 packages/message/message_queue.ts,各入口/manager 自行
  实例化。已修正两处(quick map 描述 + 目录树注释)。
- 删除"跨 service 使用的 DAO 必须注入并共享同一实例"的推导:ScriptService 与
  SubscribeService 各自构造 SubscribeDAO,SubscribeService 也自建 ScriptDAO 而非复用
  manager 传给其他 service 的 scriptDAO。改为"是否共享实例按 cache/lifetime/测试替换
  需求个案决定,以最近邻实现为准"。
- 修正 MockMessage 误用:它实现的是 Message transport(用于测试中构造
  Server/Group),不是 IMessageQueue 的替身;测试传给 service 的仍是真实
  MessageQueue(个别方法用 vi.fn() mock)。
- ScriptService 示例 constructor 补注释说明并非空 body,handler 数量改成
  "many more"(原 "~20 more" 与实际 31 个不符且会漂移),并提示用 git grep 现查。
- ServiceWorkerManager 的"每个 service 都拿 Group + 共享 mq"说法改正:LogService
  无 mq,AgentService 也无 mq(拿 offscreenSend);示例代码补上两者的真实构造签名。
- 删除 OffscreenManager/SandboxManager/ScriptRuntime "遵循同一 shape" 的说法,改为
  说明三者只是角色相似(wire deps + register handlers),构造/依赖形状互不相同,
  ScriptRuntime 还有其他两者没有的 contentInit()/externalMessage()。

以上均已对照实际源码(script.ts、resource.ts、subscribe.ts、log.ts、agent.ts、
offscreen/index.ts、sandbox/index.ts、content/script_runtime.ts、
packages/message/mock_message.ts、script.test.ts)逐条核实。

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

Copy link
Copy Markdown
Collaborator Author

Addressed in 09fe390 (pushed):

# Finding 处理
1 queue.ts 被误写成 MessageQueue wiring;实际只含 payload/type(TInstallScriptTDeleteScript 等),实现在 packages/message/message_queue.ts 已核对 queue.ts 全文——只有 type 定义,无实例化。两处描述(Cross-cutting subsystems 段落 + 目录树注释)都改为"shared MessageQueue payload/type definitions",并链接到真正的实现文件
2 "跨 service 使用的 DAO 必须注入并共享同一实例"与实现矛盾:ScriptServiceSubscribeService 各自构造 SubscribeDAOSubscribeService 也自建 ScriptDAO 而非复用 manager 传给其他 service 的 scriptDAO 已核对 script.ts/subscribe.ts 确认矛盾成立。删除该推导,改为"是否共享实例按 cache/lifetime/测试替换需求个案决定,不是可机械套用的规则,以最近邻实现为准"
3 MockMessage 被误当作 IMessageQueue 的替身;实际实现的是 Message transport 已核对 mock_message.tsscript.test.tsMockMessage 用于构造 Server/Group,传给 service 的 IMessageQueue 仍是真实 MessageQueue(部分方法用 vi.fn() mock)。已改写为准确说明,并提示需要 fake 时应针对 IMessageQueue 窄接口自己写
4 ScriptService 示例写成空 constructor 且标注 ~20 more handlers;真实 constructor 有 logger/cache/ScriptUpdateCheck 初始化,init() 实测 31 个 handler 示例加注释说明是简化插图、非字面复制;handler 数改成不漂移的 "many more" 并提示用 git grep -c 现查;正文补充 ScriptService 自身也内部构造 5 个 DAO 并在 constructor 做真实初始化的反例
5 ServiceWorkerManager 被描述成给每个 service 都传 Group + mqLogServiceAgentService 都没有 mq 已核对 log.ts(group, systemConfig))与 agent.ts(group, sender, resourceService?),无 mq)。改写为"按需创建 Group / 按需传 mq",并在示例代码补上两者真实构造签名
6 OffscreenManagerSandboxManagerScriptRuntime 被称"遵循同一 shape",但依赖与初始化形状均不同,ScriptRuntime 还有额外的 contentInit()/externalMessage() 已核对三处源码确认差异:OffscreenManagerWindowMessage + Server + ServiceWorkerClient 包进共享基类,SandboxManager 自建 Server 并交给单个 Runtime。改写为"角色相似但形状不同,逐个看源码"

最终树 ref:09fe390e7c27d60a1cfb8299433c6ced4f5c209c (09fe390e)。其余已修复部分未改动。

@cyfung1031 cyfung1031 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

针对最新树 09fe390e 的复审。上一轮 6 项 finding 的对应修改均已落地;以下是最新文本仍残留的事实/一致性问题。

严重度 Finding 证据 为什么 最小修正 验证
Medium 主架构页仍保留已被 service reference 否定的统一 constructor / init() 模式。 observed — docs/architecture.md 仍称 services 都接收 GroupIMessageQueue、DAO 并在 init() 注册 handlers;而最新 architecture-services.md 已列出 LogServiceAgentService 与其他 context 的反例。 两份 owner 文档给出相反 invariant;读者从主入口进入时仍会套用已知错误的统一模板。 把主架构页该 bullet 改为“service 依赖与 lifecycle 因 context/subsystem 而异;常见模式是 constructor wiring + explicit lifecycle hook”,并链接 service reference,不再枚举统一 Group/IMessageQueue/DAO 形状。 git grep -n "Services are constructor-injected|receive their.*Group|register message handlers in an.*init" -- docs AGENTS.md,逐条确认没有把示例重新写成全局规则。
Medium architecture-services.md 仍把 context service 的 handler/subscription 注册绝对化为发生在 init() observed — 文件开头与 Agent composition 段分别写 handlers/subscriptions “are registered in init()” (L9-L13L129-L140);但 ScriptRuntime.contentInit() 注册 runtime/addElement handler,content 入口在 init() 前单独调用它。 文档刚强调各 context lifecycle shape 不同,却仍在总则中保留统一 lifecycle invariant,会误导新增 content/inject wiring。 改为“handlers/subscriptions 通常在显式 lifecycle methods 中注册(常见为 init(),content 另有 contentInit(),inject 另有 externalMessage())”;Agent 段同样避免概括全部 context services。 搜索 \.on( / \.subscribe( 所在方法,至少核对 service_worker/content/script_runtime.tsoffscreen/base.tssandbox/runtime.ts,确认文档列出的 lifecycle 例外完整。
Low MessageQueue 被描述为在每个 entry point/manager 实例化,范围仍过宽。 observed — architecture-services.md 写 implementation “is instantiated per entry point/manager”;但 src/content.tssrc/inject.tsSandboxManager 都没有实例化 MessageQueue “per entry point/manager”看起来是全称断言;实际只有需要 pub/sub 的部分 composition roots 持有实例。 改为“is instantiated by the composition roots that need pub/sub (for example Service Worker and Offscreen)”。 git grep -n "new MessageQueue" -- src packages,把实际实例化点与文档示例逐项比对。
Low DAO 实例选择原因被写成已证实的实现事实,但源码只证明它是 case-by-case。 observed — architecture-services.md 断言选择 “is decided … by caching needs, lifetime, and whether tests need to substitute it”;当前源码能证明注入/自建并存,但没有记录每个选择均由这三项驱动。 合理的设计考量被写成历史事实,后续 contributor 可能据此虚构现有代码的 ownership/lifetime contract。 改成规范性措辞:“When deciding, consider cache ownership, lifetime, and test substitution needs; existing choices are case-by-case, so check the nearest implementation.” 对列出的 ScriptDAO/SubscribeDAO/ResourceDAO 实例化点检查注释、cache 开关和测试替换方式;没有证据的原因不要用陈述式归因。

回应 PR review (#pullrequestreview-4731478283):

- docs/architecture.md: "Services are constructor-injected" 一条仍称所有 service 统一
  接收 Group/IMessageQueue/DAO 并在 init() 注册 handler,与 architecture-services.md
  已列出的 LogService/AgentService/ScriptRuntime 反例矛盾。改为陈述依赖与 lifecycle
  因 context/subsystem 而异,链接到 service reference 而不是自己重新枚举统一形状。
- docs/references/architecture-services.md:
  - handler/subscription 注册不再绝对写成发生在 init():补充 ScriptRuntime.contentInit()
    在 content 入口 init() 之前单独注册 runtime/addElement handler 的反例,
    "Agent composition" 段同样改措辞。
  - MessageQueue 实现的实例化范围从过宽的"per entry point/manager"改为准确列出实际
    实例化点:service_worker.ts、offscreen/base.ts、src/pages/store/global.ts
    (UI 页面订阅广播);content/inject/sandbox 均不实例化,并给出可复核的
    git grep 命令。
  - DAO 共享 vs 自建的原因不再写成已证实的实现事实(源码只证明是 case-by-case),
    改为规范性决策指南(cache ownership/lifetime/test substitution 是决策时应考虑的
    因素,不是每个现有实例背后已记录的理由)。

已用 git grep 确认仓库内不再有 "Services are constructor-injected"/"receive their...Group"/
"register message handlers in an...init" 等统一措辞残留。

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

Copy link
Copy Markdown
Collaborator Author

Addressed in a310dc8 (pushed):

Severity Finding 处理
medium architecture.md 仍保留统一 constructor/init() 断言,与 service reference 已列出的 LogService/AgentService 等反例矛盾,两份 owner 文档给出相反 invariant 已核对 architecture.md#L43-45。"Services are constructor-injected" 一条改为陈述依赖与 lifecycle 因 context/subsystem 而异,链接到 architecture-services.md 而不是重新枚举一个统一形状
medium architecture-services.md 把 handler/subscription 注册绝对写成发生在 init(),但 ScriptRuntime.contentInit() 会在 init() 之前单独注册 runtime/addElement handler 已核对 script_runtime.ts 确认矛盾成立。两处(General rule 段 + Agent composition 段)改为"通常在显式 lifecycle method 中注册——常见是 init(),content 另有 contentInit(),Agent 有自己的等效方法",并给出 contentInit() 反例
low MessageQueue 实现被描述为"instantiated per entry point/manager",范围过宽 已用 git grep -n "new MessageQueue" -- src packages 核对:实际只有 src/service_worker.tssrc/app/service/offscreen/base.ts、以及订阅广播的 src/pages/store/global.ts(UI 页面)会实例化;content/inject/sandbox 都不会。已改为准确列出这三处并附核查命令
low DAO 共享 vs 自建的原因(cache/lifetime/test substitution)被写成已证实的实现事实,但源码只证明是 case-by-case,没有记录每个选择的具体原因 已改为规范性措辞:这三项是决策时应考虑的因素,不是每个现有实例背后已记录的理由;现有选择仍是 case-by-case,需查最近邻实现

最终树 ref:a310dc809a765ba3727d008d8036dbb74dce9ae7 (a310dc80)。其余已修复部分未改动。

Copy link
Copy Markdown
Collaborator Author

Reviewed against a310dc80 / issuecomment-5017423473.

严重度 Finding 证据 为什么 最小修正 验证
High docs/architecture.md 的测试段仍重复上一轮已否定的统一 constructor / MockMessage 模型。 observed — [architecture.md](/docs/architecture.md:255) 仍写“message-bus behavior uses MockMessage”,并在 [同段](/docs/architecture.md:266) 声称 service 都通过 constructor 接收 IMessageQueue/DAO、测试用 MockMessage 构造 service;但 [architecture-services.md](/docs/references/architecture-services.md:96) 已明确 MockMessage 只是底层 Message transport。实际 [script.test.ts](/src/app/service/service_worker/script.test.ts:48) 使用真实 MessageQueueMockMessage 只用于构造 Server/Group 这会重新引入本 PR 第五轮刚修掉的同一误解,并指导贡献者把 RPC transport fake 当成 pub/sub queue 或 service constructor 参数。 将测试段拆成两层:MockMessage 用于 Server/Group transport 测试;IMessageQueue 根据测试使用真实 MessageQueue、窄 fake 或 cast stub。删除“所有 service 都接收 IMessageQueue/DAO”以及“用 MockMessage 构造 service”的统一表述。 git grep -n 'MockMessage' -- '*.md',逐处对照 mock_message.tsscript.test.tsresource.test.ts;运行 pnpm test -- --run src/app/service/service_worker/script.test.ts
Medium 主架构图仍称 MessageQueue 会向 ALL contexts 广播,与本轮新增的实例化边界直接矛盾。 observed — [architecture.md](/docs/architecture.md:76) 写 MessageQueue ... across ALL contexts;而 [architecture-services.md](/docs/references/architecture-services.md:20) 已明确只有 Service Worker、Offscreen 与 UI store 实例化,content/inject/sandbox 不实例化。仓库中 msgQueue 消费入口也只在 packages/message/message_queue.ts 读者会误以为 content/inject/sandbox 可直接订阅 MQ topic,绕过它们实际使用的 Server/转发桥接路径。 把图注改为“broadcasts among extension contexts that instantiate MessageQueue(当前为 SW、Offscreen、UI pages)”,或移除 ALL contexts 搜索 new MessageQueue(msgQueue 的生产代码使用点,并确认 content/inject/sandbox 入口均没有 MQ 实例。
Medium “A new persisted entity” 配方仍把所有 backend 统一要求为“在 manager 构造 + group.on 暴露”。 observed — [architecture.md](/docs/architecture.md:235) 在选择 Repo<T>/DAO<T>/OPFSRepo 后统一要求 construct it in the manager, expose ops via group.on;但 [architecture-data.md](/docs/references/architecture-data.md:111) 已说明 DAO<T>/OPFSRepo 的 construction/access pattern 不同,且 [AgentModelService](/src/app/service/agent/service_worker/model_service.ts:9) 默认在 service 内部构造可选 AgentModelRepoAgentChatRepo 还是模块级 singleton。 该 recipe 与本 PR 强调的 nearest-neighbor / context-specific 原则冲突,会迫使 Agent 或本地 service 数据层套入并不存在的 manager/RPC 形状。 改为:选 backend 后再确认 owner/lifetime;复制同 backend、同 subsystem 的最近邻实例。只有需要由 context composition root 共享且通过 RPC 暴露时,才放进 manager 并注册 group.on Repo<T>、Dexie DAO<T>OPFSRepo 各抽查至少一个实际 owner/构造点,并确保 recipe 不再对三类给出同一 wiring 指令。
Low 新增的 MessageQueue 核验命令不能得到前文所说的生产实例清单。 observed — [architecture-services.md](/docs/references/architecture-services.md:25) 建议运行 git grep -n "new MessageQueue" -- src packages;该字符串同时匹配 [message_queue.ts](/packages/message/message_queue.ts:92) 的 new MessageQueueGroup(...),也会列出 script.test.tsmessage_queue.test.ts 等测试实例。 reviewer 按文档运行会得到大量非生产结果,无法直接验证“当前只有三个生产实例化点”的声明。 使用能排除 MessageQueueGroup 和测试文件的命令,或明确写成“搜索后人工区分 production/tests”。例如:`git grep -n -E 'new MessageQueue\s*\(' -- src packages grep -vE '\.(test

回应 PR review comment (issuecomment-5017464125):

- Testing the Internals: 测试段仍写 "message-bus behavior uses MockMessage" 并称
  service 统一经 constructor 收 IMessageQueue/DAO、用 MockMessage 构造 service ——
  这是本 PR 第五轮刚在 architecture-services.md 修正过的同一误解在另一处重现。
  已核对 mock_message.ts/script.test.ts 拆成两层:MockMessage 只是 Server/Group
  的 transport fake;service 的 IMessageQueue 依赖测试中用真实 MessageQueue(个别
  方法 spy)或窄 fake,不是 MockMessage。
- Big Picture 图注:"MessageQueue ... broadcasts ... across ALL contexts" 与本 PR
  刚确立的实例化边界矛盾,改为准确指向"当前只有 SW/Offscreen/UI pages 会实例化"。
- "A new persisted entity" recipe 仍统一要求"construct in manager, expose via
  group.on";已核对 AgentModelService(内部默认 new AgentModelRepo())与
  AgentChatRepo(模块级 singleton `agentChatRepo`)两个反例,改为按 backend +
  subsystem 找最近邻,只有真正由 context composition root 拥有且需要 RPC 暴露时
  才走 manager/group.on。
- architecture-services.md 里建议的 `git grep -n "new MessageQueue"` 命令会误命中
  MessageQueueGroup 与测试文件;已验证换成
  `git grep -n -E 'new MessageQueue\s*\(' -- src packages | grep -vE '\.(test|spec)\.[cm]?[jt]sx?:'`
  精确返回三处生产实例化点(service_worker.ts、offscreen/base.ts、
  pages/store/global.ts)。

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

Copy link
Copy Markdown
Collaborator Author

Addressed in 2ca3768 (pushed):

Severity Finding 处理
high architecture.md 的 Testing 段在另一处重复了刚被否定的"service 统一经 constructor 收 IMessageQueue/DAO、用 MockMessage 构造 service"说法 已核对 mock_message.ts/script.test.ts 拆成两层:MockMessage 只是 Server/Group 的 transport fake;service 的 IMessageQueue 依赖测试中用真实 MessageQueue(个别方法 spy)或窄 fake。两处("message-bus behavior uses MockMessage" 一句 + 段末的 DI 说明段落)均已改写
medium Big Picture 图注称 MessageQueueALL contexts 广播,与本轮已确立的实例化边界矛盾 改为"broadcasts among the contexts that instantiate it",并指向 architecture-services.md 的准确清单(SW/Offscreen/UI pages;content/inject/sandbox 不持有实例)
medium "A new persisted entity" recipe 仍统一要求 construct in manager + group.on,与 Agent 数据层的实际 ownership 矛盾 已核对 AgentModelService(内部默认 new AgentModelRepo())与 AgentChatRepo(模块级 singleton agentChatRepo)两个反例。改为按 backend + subsystem 找最近邻,只有真正由 context composition root 拥有且需要 RPC 暴露时才走 manager/group.on
low 建议的 git grep -n "new MessageQueue" 命令会误命中 MessageQueueGroup 与测试文件 已验证换成 git grep -n -E 'new MessageQueue\s*\(' -- src packages | grep -vE '\.(test|spec)\.[cm]?[jt]sx?:',精确返回三处生产实例化点(service_worker.tsoffscreen/base.tspages/store/global.ts),无噪声

最终树 ref:2ca376838919bb397725b77661b89868ab0a317b (2ca37683)。其余已修复部分未改动。

cyfung1031 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

2ca37683 的上一轮四项修正逐项复核后,测试分层、实体 ownership 示例、Big Picture 图注和精确 MessageQueue grep 命令均已按 review 落实。完整树仍有以下跨段落残留:

严重度 Finding 证据 为什么 最小修正 验证
High MessageQueue 的覆盖范围在同一文档中仍自相矛盾。 observed — Big Picture 已正确说明只有 Service Worker、Offscreen 和 UI pages 实例化 MessageQueue,content/inject/sandbox 不持有实例;但 [Message Passing transport 表](/docs/architecture.md:151) 仍写 MessageQueue connects “All contexts”,[pub/sub 正文](/docs/architecture.md:186) 又称任何 context 都可使用,并说 publish 会把消息发送给 “every context”。实际实例化点只有 src/service_worker.tssrc/app/service/offscreen/base.tssrc/pages/store/global.ts 读者会继续把 MessageQueue 当成五个执行 context 都具备的统一 transport,与本轮刚建立的实例化边界冲突;新增 content/inject/sandbox 代码时可能错误引入 MessageQueue transport 表的 Connects 改为当前实例化者,例如 Service Worker ↔ Offscreen ↔ UI pages;正文改为 publish 通过 chrome.runtime.sendMessage 广播,但只有已实例化 MessageQueue 并注册 listener 的 context 会作为 queue participant 处理。链接到 service reference 的精确实例清单,避免再写 “all/every context”。 搜索 docs/architecture.mdAll contextsevery contextany context;再运行 git grep -n -E 'new MessageQueue\s*\(' -- src packages | grep -vE '\.(test|spec)\.[cm]?[jt]sx?:',确认文档范围与三个生产实例化点一致。
Medium “新增 cross-context RPC” recipe 仍把所有 handler 强制套成 group.on(...) + init() observed — [Extending ScriptCat recipe](/docs/architecture.md:236) 要求在 owning service 的 init() 中添加 this.group.on(...)。但 [ScriptRuntime.contentInit()](/src/app/service/content/script_runtime.ts:23) 会在 init() 之外用 server.on("runtime/addElement", ...) 注册 handler;ServiceWorkerManager.initManager() 也直接在 manager-owned server 上调用 this.api.on(...),而不是 service 的 group.on(...) 该 recipe 会把刚在 service reference 中明确记录的 lifecycle/context variance 再次压平成统一模板,尤其会误导 content 和 manager-level RPC 的新增方式。 改为:先找到该 context/subsystem 的 owning Server/Group 与最近邻 handler,再在其实际 lifecycle hook 中注册;service-worker domain services 通常是 group.on(...) + init(),但 content 可使用 contentInit(),manager-owned actions 可在 initManager() 中直接注册。 搜索所有 server.onthis.api.onthis.group.on 的生产落点;确认 recipe 不再声称唯一合法形状是 service init() 内的 group.on(...)
Medium Chrome/Firefox offscreen 段把 IOffscreenSend.init() 的调用责任归给了 services。 observed — [architecture.md](/docs/architecture.md:134) 写 “Services … receive an IOffscreenSend and call .init()”;实际 [ServiceWorkerManager.initManager()](/src/app/service/service_worker/index.ts:13) 在 manager 层调用 this.offscreenSend.init(),包括启动时调用以及处理 preparationOffscreen 时再次等待初始化。下游 services 接收 sender 用于发送请求,但不负责初始化 transport。 这会让新增或修改 service 的贡献者重复调用 .init()、改变 readiness 顺序,或误以为每个 service 都拥有 offscreen transport lifecycle。 改为:services 不感知 Chrome/Firefox 的具体 sender 实现,只依赖 IOffscreenSend 发送请求;transport readiness 由 ServiceWorkerManager 集中调用 .init() 管理。 搜索 offscreenSend.init() 的生产调用点,并检查所有接收 IOffscreenSend/MessageSend 的 service,确认文档没有把初始化 ownership 分散给 services。

@cyfung1031

Copy link
Copy Markdown
Collaborator Author

@CodFrm 不理AI的review了。合并吧

cyfung1031 and others added 4 commits July 20, 2026 17:42
报告是给人读来判断实现是否正确的,所以截图、视频、日志、资源都直接嵌进
report.md:视频用 <video> 并配上运行中截下的关键帧(video 既不可跳读,
也不是每个 viewer 都能播),日志与短 fixture 用代码块贴出决定结论的那几行。
仅归档/二进制/超大日志保留裸链接。
- CAT.agent.* 并非「不走 @GMContext.API/@grant/@PermissionVerify.API」:
  cat_agent.ts 用 @GMContext.API({follow})、gm_agent.ts 用 @PermissionVerify.API、
  compat-grant.js 里五个 CAT.agent.* 都是注册过的 grant。改写为「同一套注册路径,
  区别在点号 grant + follow/dotAlias + connect() 流式」,两处重复表述一并修正。
- grant/compat 表在 packages/eslint/compat-grant.js,不在 linter-config.ts
  (后者只有 rules/globals/env)。
- 配方已是 5 步,删掉残留的「four-step recipe」措辞。
- 工具名按 name: 字段更正:sub_agent.ts 注册为 agent,tab_tools.ts 无 tab_* 前缀。
- architecture.md 传输表 MessageQueue 行的「All contexts」与本文件 76-78 行
  刚确立的实例化边界矛盾,改为 SW/Offscreen/UI 页面。
task/sub_agent 是模块简写,grep 不到;实际注册名是 create_task
(task_tools.ts)与 agent(sub_agent.ts:26)。仅改注释,无行为变更。
@CodFrm
CodFrm merged commit 3461fd4 into scriptscat:main Jul 20, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation P0 🚑 需要紧急处理的内容

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants