Skip to content

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

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

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.md、docs/verification.md、docs/references/design-patterns.md 等文档
存在过期事实(Firefox Offscreen、path alias 示例、固定 locale 数量、未经测量的百分比断言)与政策前后不一致
(TDD 例外未在 architecture/verification 中同步)。

本次改动

  • AGENTS.md / .github/copilot-instructions.md / docs/architecture.md 及 docs/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 清单补上 common、json.worker。
  • docs/references/architecture-gm-api.md: 明确 sendMessage 与 connect 的选择依据,以及 DOM handler /
    linter 注册的准确落点路径。
  • docs/develop.md: 记录 toast.ts 对 no-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.md、docs/cloud-sync.md、九份 docs/references/terminology-*.md、
    .github/pull_request_template.md、example/agent/README.md、
    packages/chrome-extension-mock/README.md、CONTRIBUTING*.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/repo、src/app/service/、rspack.config.ts、
    eslint.config.mjs、tsconfig.json、src/locales/、src/service_worker.ts、
    src/app/service/offscreen/event_page_manager.ts、packages/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) 写成 AgentChatService、TaskService、AgentCompactService;实际为 ChatService、AgentTaskService、CompactService。同处还把 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.md;AGENTS.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" 并修正为 ChatService、AgentTaskService、CompactService(原文误写 AgentChatService/TaskService/AgentCompactService),并把 navigation 的归属改为 dom.ts/chrome.tabs,dom_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 二选一。 observed — architecture-agent.md L105-L114、dom.ts L108-L178 screenshot() 不走 chrome.scripting.executeScript;monitoring 始终走 CDP。这会误述 debugger 权限边界及实现位置。 只把 default/trusted 分支用于 click/fill;分别描述 screenshot 与 monitoring 的真实路径。 T1:逐句对照对应方法。 high 源码后续变化仍需重新核对。
medium 全量 Markdown link checker 会把合法 mailto: 当成本机相对路径。 measured — DOC-MAINTENANCE.md L166-L180;原命令实际产生 3 条错误的 BROKEN 正确的文档树也会失败,agents 容易开始忽略检查输出。 排除 mailto:、app:,并保留方案中的 ~~~ fenced-block 处理。 T1:修正后应无 BROKEN;再注入一个无效相对链接确认检查仍能失败。 high 仍然只是 file-target quick check,不验证完整 anchor。
medium PR 描述仍称 Copilot instructions “未缩减为纯 router”,与最新文件及最新说明相反。 observed — PR 描述、最新说明 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,并使用不存在的 AgentChatService、TaskService。 observed — architecture.md L224-L236、architecture-services.md L70-L108;实际为 ChatService、AgentTaskService 这是 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 声称已验证的 ~~~ 处理。 observed — PR 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.ts、subscribe.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:ScriptService 与 SubscribeService 各自构造 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(如 LogService、AgentService),应改成“按需创建 Group/传入 mq”。
  6. OffscreenManager、SandboxManager 和 content/inject 的 ScriptRuntime 只是在 composition/handler registration 角色上相似,并不遵循同一依赖和初始化形状;ScriptRuntime 还有 contentInit()/externalMessage()。

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

…例失真、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(TInstallScript、TDeleteScript 等),实现在 packages/message/message_queue.ts 已核对 queue.ts 全文——只有 type 定义,无实例化。两处描述(Cross-cutting subsystems 段落 + 目录树注释)都改为"shared MessageQueue payload/type definitions",并链接到真正的实现文件
2 "跨 service 使用的 DAO 必须注入并共享同一实例"与实现矛盾:ScriptService 与 SubscribeService 各自构造 SubscribeDAO,SubscribeService 也自建 ScriptDAO 而非复用 manager 传给其他 service 的 scriptDAO 已核对 script.ts/subscribe.ts 确认矛盾成立。删除该推导,改为"是否共享实例按 cache/lifetime/测试替换需求个案决定,不是可机械套用的规则,以最近邻实现为准"
3 MockMessage 被误当作 IMessageQueue 的替身;实际实现的是 Message transport 已核对 mock_message.ts 与 script.test.ts:MockMessage 用于构造 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 + mq;LogService、AgentService 都没有 mq 已核对 log.ts((group, systemConfig))与 agent.ts((group, sender, resourceService?),无 mq)。改写为"按需创建 Group / 按需传 mq",并在示例代码补上两者真实构造签名
6 OffscreenManager、SandboxManager、ScriptRuntime 被称"遵循同一 shape",但依赖与初始化形状均不同,ScriptRuntime 还有额外的 contentInit()/externalMessage() 已核对三处源码确认差异:OffscreenManager 把 WindowMessage + 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 都接收 Group、IMessageQueue、DAO 并在 init() 注册 handlers;而最新 architecture-services.md 已列出 LogService、AgentService 与其他 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-L13、L129-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.ts、offscreen/base.ts、sandbox/runtime.ts,确认文档列出的 lifecycle 例外完整。
Low MessageQueue 被描述为在每个 entry point/manager 实例化,范围仍过宽。 observed — architecture-services.md 写 implementation “is instantiated per entry point/manager”;但 src/content.ts、src/inject.ts 和 SandboxManager 都没有实例化 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.ts、src/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) 使用真实 MessageQueue,MockMessage 只用于构造 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.ts、script.test.ts、resource.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 内部构造可选 AgentModelRepo,AgentChatRepo 还是模块级 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.ts、message_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 图注称 MessageQueue 向 ALL 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.ts、offscreen/base.ts、pages/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.ts、src/app/service/offscreen/base.ts、src/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.md 中 All contexts、every context、any 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.on、this.api.on、this.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
@cyfung1031
cyfung1031 deleted the claude/scriptcat-docs-update-59bb37 branch October 10, 2026 23:32
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