From 1bdff54c239751a19fdffb91b930bc9a63543eac Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:39:44 +0900 Subject: [PATCH 01/16] =?UTF-8?q?=F0=9F=93=84=20=E4=BF=AE=E5=A4=8D=20devel?= =?UTF-8?q?op-testing.md=20=E4=B8=AD=E7=9A=84=E8=AF=AD=E6=B3=95=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chrome APIs mocked → Chrome APIs are mocked;MockMessage available → is available; cost ~15% → costs ~15%(主谓一致)。 Co-Authored-By: Claude Sonnet 5 --- docs/references/develop-testing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/references/develop-testing.md b/docs/references/develop-testing.md index 2f381c40d..273fb366c 100644 --- a/docs/references/develop-testing.md +++ b/docs/references/develop-testing.md @@ -8,11 +8,11 @@ Vitest + happy-dom. Per-test budgets live in `vitest.config.ts` per project: non `renderHook` tests in `.ts` files) uses 850ms because a render + interaction case genuinely costs 100–200ms solo under coverage and worker parallelism multiplies that (fake-timer countdown cases have been observed at ~630ms under full local load). Don't pass `--test-timeout` on the CLI — it would override every project's -budget at once. Chrome APIs mocked via -`@Packages/chrome-extension-mock` (`tests/vitest.setup.ts`). `MockMessage` available for message-system tests. +budget at once. Chrome APIs are mocked via +`@Packages/chrome-extension-mock` (`tests/vitest.setup.ts`). `MockMessage` is available for message-system tests. `happy-dom` is patched via `patches/` (see `pnpm-workspace.yaml` `patchedDependencies`) to build its invalid-selector `DOMException` lazily — the upstream eager construction captures a deep stack on every -`matches()`/`querySelector()` call and cost ~15% of TSX suite time. +`matches()`/`querySelector()` call and costs ~15% of TSX suite time. - Write failing tests **before** implementation; co-locate `*.test.ts`/`*.test.tsx` next to source (or place in `tests`). - BDD-style Chinese `describe`/`it` titles. Use `describe.concurrent()` / `it.concurrent()` where independent. From 16a3fa5a516c21a8040a401c2f1cf433afc3959a Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:45:10 +0900 Subject: [PATCH 02/16] =?UTF-8?q?=F0=9F=93=84=20=E7=AA=81=E5=87=BA=20verif?= =?UTF-8?q?ication.md=20=E4=B8=AD"=E5=85=88=E5=BB=BA=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E5=86=8D=E8=B7=91=E6=B5=8F=E8=A7=88=E5=99=A8"=E7=9A=84?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=E8=A6=81=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 该要求原来埋在链接格式说明段落末尾,与 Step 1-4 的编号流程脱节, 容易被按步骤执行的读者/agent 跳过。拆成独立加粗句,内容不变。 Co-Authored-By: Claude Sonnet 5 --- docs/verification.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/verification.md b/docs/verification.md index 5a1af17b3..916f30246 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -89,8 +89,9 @@ sanitize them before saving evidence. Embed screenshots inline with `![alt](screenshots/…png)` plus a caption line, so `report.md` renders as a visual record you can skim without opening files. Link videos, logs, and resources instead — markdown can't inline them. -Never list bare links: every item carries a short note explaining what it proves and how to read it. Before running -the browser, create the record following the Evidence Index shape in the +Never list bare links: every item carries a short note explaining what it proves and how to read it. + +**Before running the browser**, create the record following the Evidence Index shape in the [verification record template](./references/verification-report-template.md). ### Minimal template (drive a UI page) From 65423a3089b5a3508539664c1e08cf700b1d301d Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:45:20 +0900 Subject: [PATCH 03/16] =?UTF-8?q?=F0=9F=93=84=20=E6=B6=88=E9=99=A4=20verif?= =?UTF-8?q?ication.md=20=E4=B8=AD=20"Scratch=20copying..."=20=E7=9A=84?= =?UTF-8?q?=E4=B8=BB=E8=AF=AD=E6=AD=A7=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原句 "Scratch copying the inline fixture won't read ..." 省略主语, "Scratch" 读作名词还是动名词短语不明确。补全为 "A scratch script that copies the inline fixture", 保留原有 E2E_RECORD_VIDEO_DIR 与 链接不变。 Co-Authored-By: Claude Sonnet 5 --- docs/verification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/verification.md b/docs/verification.md index 916f30246..eb09172c1 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -127,7 +127,7 @@ Playwright finalizes `.webm` files when pages/contexts close at the end of the t produce multiple videos because the harness may open setup pages as well as the page under verification; keep all of them beside the screenshots for the same scenario. -> Scratch copying the inline fixture won't read `E2E_RECORD_VIDEO_DIR` — see [gotchas](./references/verification-debugging.md#common-gotchas). +> A scratch script that copies the inline fixture won't read `E2E_RECORD_VIDEO_DIR` — see [gotchas](./references/verification-debugging.md#common-gotchas). ### Run only your scratch script From 321092e9d70952f30636b83c92835b756bb335fb Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:45:32 +0900 Subject: [PATCH 04/16] =?UTF-8?q?=F0=9F=93=84=20=E8=A1=A5=E5=85=A8=20archi?= =?UTF-8?q?tecture-gm-api.md=20=E6=96=B0=E5=A2=9E=20GM=20API=20=E6=AD=A5?= =?UTF-8?q?=E9=AA=A4=203/4=20=E7=9A=84=E5=85=B7=E4=BD=93=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 步骤 1、2 都点名了具体装饰器和文件,步骤 3(offscreen 路由)和步骤 4 (注册 @grant)却只给出泛化描述,读者/agent 需要额外翻回文档前部或 自行搜索才能定位实际文件。补上已验证存在的 src/app/service/offscreen/gm_api.ts 与 packages/eslint/linter-config.ts, 四个步骤具体程度保持一致。 Co-Authored-By: Claude Sonnet 5 --- docs/references/architecture-gm-api.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/references/architecture-gm-api.md b/docs/references/architecture-gm-api.md index 19bae745b..c144268a5 100644 --- a/docs/references/architecture-gm-api.md +++ b/docs/references/architecture-gm-api.md @@ -60,6 +60,7 @@ work. directly, for async ones forward via `sendMessage`/`connect`. 2. If it needs privilege (network, cookies, tabs), add the handler on the SW `GMApi` with `@PermissionVerify.API(...)`. -3. If it needs DOM, route through the offscreen GM API instead. -4. Register the `@grant` so the linter and the context builder recognize it (see - [`packages/eslint`](../../packages/eslint)). +3. If it needs DOM, route through the offscreen GM API instead + ([`src/app/service/offscreen/gm_api.ts`](../../src/app/service/offscreen/gm_api.ts)). +4. Register the `@grant` so the linter and the context builder recognize it + ([`packages/eslint/linter-config.ts`](../../packages/eslint/linter-config.ts)). From 77802927de5ff1fa7a91c1bc92db60addaaa9fcc Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:55:30 +0900 Subject: [PATCH 05/16] =?UTF-8?q?=F0=9F=93=84=20=E8=A1=A5=E5=85=85=20verif?= =?UTF-8?q?ication.md=20=E4=BD=95=E6=97=B6=E5=8F=AF=E8=B7=B3=E8=BF=87?= =?UTF-8?q?=E6=9C=AC=E6=8C=87=E5=8D=97=E7=9A=84=E8=BE=B9=E7=95=8C=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原文只说明如何做浏览器端验证,未说明哪些改动不需要(纯文档/注释/ type-only)或哪些 bug 应改用普通 Vitest 用例复现(纯 service/unit 逻辑、无跨 context 交互、无真实 Chrome API、无 DOM),导致 agent 可能 为逻辑 bug 过度搭建 E2E scratch,或为文档改动误判需要跑浏览器。 Co-Authored-By: Claude Sonnet 5 --- docs/verification.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/verification.md b/docs/verification.md index eb09172c1..bcf67ea47 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -9,6 +9,11 @@ > **What this is NOT.** It is *not* the test-suite reference. The mechanics of Vitest unit tests and the > permanent Playwright E2E suite live in [`DEVELOP.md`](./develop.md) → *Testing*; the TDD-first principle and > engineering rules live in [`../AGENTS.md`](../AGENTS.md). Read those for writing committed tests. +> +> **When to skip this guide.** Docs-only, comment-only, and type-only changes need no browser run. When a change +> or bug is fully reproducible in pure service/unit logic — no cross-context wiring, no real Chrome API, no DOM — +> reproduce and verify it with a throwaway Vitest case instead of a scratch script; reach for this guide only when +> the behavior only manifests through the built extension. ## The one rule: verification ≠ growing the E2E suite From 9e5b424310b41a4b537d63bf9be1f8d91b290e82 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:55:44 +0900 Subject: [PATCH 06/16] =?UTF-8?q?=F0=9F=93=84=20=E8=A1=A5=E4=B8=8A=20archi?= =?UTF-8?q?tecture-gm-api.md=20=E6=AD=A5=E9=AA=A4=201=20=E4=B8=AD=20sendMe?= =?UTF-8?q?ssage/connect=20=E7=9A=84=E9=80=89=E6=8B=A9=E4=BE=9D=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原文只列出两个选项,选择标准(流式/进度事件/大payload才用 connect) 埋在文档更靠前的 GM_xmlhttpRequest 案例里;只看编号步骤的读者会漏看。 直接把判断依据写进步骤 1,并保留指回原案例的链接。 Co-Authored-By: Claude Sonnet 5 --- docs/references/architecture-gm-api.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/references/architecture-gm-api.md b/docs/references/architecture-gm-api.md index c144268a5..e6da7f8a6 100644 --- a/docs/references/architecture-gm-api.md +++ b/docs/references/architecture-gm-api.md @@ -57,7 +57,8 @@ work. ### Adding a GM API (sketch) 1. Add the method to the content `GMApi` with `@GMContext.API({ alias: "GM.foo" })`; for sync APIs return - directly, for async ones forward via `sendMessage`/`connect`. + directly, for async ones forward via `sendMessage` (single request/reply) — or `connect` only when the reply + is streamed in chunks (progress events, large payloads; see the `GM_xmlhttpRequest` walkthrough above). 2. If it needs privilege (network, cookies, tabs), add the handler on the SW `GMApi` with `@PermissionVerify.API(...)`. 3. If it needs DOM, route through the offscreen GM API instead From 57e797936d703793a95d70359a36b389c4397363 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:56:00 +0900 Subject: [PATCH 07/16] =?UTF-8?q?=F0=9F=93=84=20=E8=A1=A5=E4=B8=8A=20verif?= =?UTF-8?q?ication.md=20=E4=B8=AD=E9=A9=B1=E5=8A=A8=E5=8F=8C=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E9=AA=8C=E8=AF=81=E7=9A=84=E5=85=B7=E4=BD=93=E5=86=99?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit design.md 要求"双主题都要验证",verification.md 负责用 scratch 脚本产出截图证据,但两者从未连接——没有任何示例说明怎样在 Playwright scratch 脚本里确定性地切换主题。补充已验证的 localStorage "lightMode" 写法(与 theme-provider.tsx / common.ts 的实现一致),并链接回 design.md 的机制说明,不重复其内容。 Co-Authored-By: Claude Sonnet 5 --- docs/verification.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/verification.md b/docs/verification.md index bcf67ea47..0ff875387 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -120,6 +120,13 @@ test("verify: options page opens and renders the script list area", async ({ con }); ``` +To verify a UI change in **both themes** ([design.md](./design.md#theming) requires it), set the theme before +navigating and capture one screenshot per theme: + +```ts +await context.addInitScript(() => localStorage.setItem("lightMode", "dark")); // or "light" +``` + If you need video evidence, enable it explicitly for the run. The shared fixture writes videos only when `E2E_RECORD_VIDEO_DIR` is set: From 72c93ee69a0de921be8e3e1d1c1c0996b23df224 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:56:15 +0900 Subject: [PATCH 08/16] =?UTF-8?q?=F0=9F=93=84=20translation.md=20=E8=A1=A5?= =?UTF-8?q?=E5=85=85=20i18n-usage.test.ts=20=E7=9A=84=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E4=B8=8E=E4=BD=9C=E7=94=A8=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 该测试静态校验代码中 t() 调用的 key 是否存在,但只解析 zh-CN 资源; 之前 translation.md 完全没提到它,导致翻译非 zh-CN locale 时得不到 任何自动化信号,也可能被误当作"翻译已验证"的证据。 Co-Authored-By: Claude Sonnet 5 --- docs/translation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/translation.md b/docs/translation.md index 600dc91bd..a7bbcc703 100644 --- a/docs/translation.md +++ b/docs/translation.md @@ -50,6 +50,7 @@ - **关键字冲突**:同一页面中关键字相同但翻译不同时,使用 `page.key` 的方式区分。 - 为满足部分扩展市场要求,`chrome.i18n` 语言文件位于 `src/assets/_locales`。 - i18n 方案的实现细节见 [`src/locales/README.md`](../src/locales/README.md)。 +- 自动检查:[`src/locales/i18n-usage.test.ts`](../src/locales/i18n-usage.test.ts)(`pnpm test`)静态扫描代码中的 `t()`/`i18n.t()` 调用,但只按 **zh-CN** 资源解析 key 是否存在;修改其它 locale 时该测试不会给出任何信号,仍需人工核对目标 locale 是否缺 key。 ## 提取翻译提示词 / Extract-translation prompt From fe089367bc3b26bb121b4b5f2a1ecffb2461c0fc Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:56:36 +0900 Subject: [PATCH 09/16] =?UTF-8?q?=F0=9F=93=84=20verification-debugging.md?= =?UTF-8?q?=20=E8=A1=A5=E5=85=85=20Firefox=20=E6=97=A0=E7=8B=AC=E7=AB=8B?= =?UTF-8?q?=20Offscreen=20=E4=B8=8A=E4=B8=8B=E6=96=87=E7=9A=84=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five-context 调试表把 Offscreen 行当作平台通用写法,但 src/service_worker.ts:77-85 显示 Firefox 上 chrome.offscreen.createDocument 不存在,offscreen.html 根本不会被加载——architecture.md 已记录这个平台 分歧,本文件之前没有引用它。按此表在 Firefox 上排障会找错上下文。 Co-Authored-By: Claude Sonnet 5 --- docs/references/verification-debugging.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/references/verification-debugging.md b/docs/references/verification-debugging.md index fa3fc6d4f..5a733e722 100644 --- a/docs/references/verification-debugging.md +++ b/docs/references/verification-debugging.md @@ -12,6 +12,11 @@ model in [`ARCHITECTURE.md`](../architecture.md)): | Background / scheduled script, DOM-needing GM APIs | **Offscreen** — `dist/ext/src/offscreen.html` context | | Cron scheduling, `with`-sandboxed execution | **Sandbox** — `dist/ext/src/sandbox.html` context | +> **Firefox has no separate Offscreen context.** `chrome.offscreen.createDocument` doesn't exist there, so +> `offscreen.html` is never loaded — `EventPageOffscreenManager` runs the same logic inside the background event +> page instead (see [`ARCHITECTURE.md`](../architecture.md#chrome-vs-firefox-the-offscreen-split)). On Firefox, +> inspect the background/event page, not `offscreen.html`. + In a scratch script, capture the page console (`page.on("console", …)`), take screenshots (`await page.screenshot({ path: "test-results/verify//screenshots/…png" })`), and write any manual notes to `test-results/verify//`. Playwright's automatic failure artifacts also go under From 7e84e92d818ac63afbdea0e7e0c574a180f6a81c Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:56:52 +0900 Subject: [PATCH 10/16] =?UTF-8?q?=F0=9F=93=84=20pull-request.md=20?= =?UTF-8?q?=E8=A1=A5=E5=85=85=20PR=20=E6=A0=87=E9=A2=98=E8=A7=84=E5=88=99?= =?UTF-8?q?=E7=9A=84=E4=BA=A4=E5=8F=89=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit develop.md 已规定 PR 标题用 gitmoji + 中文优先,但只从 develop.md 可达;AGENTS.md 的 "Pull Request Description Format" 直接指向 pull-request.md,走这条路径的读者永远看不到标题规则。加一句交叉 链接而非复制内容,避免与 develop.md 重复。 Co-Authored-By: Claude Sonnet 5 --- docs/pull-request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pull-request.md b/docs/pull-request.md index b3e4ce25c..620df153a 100644 --- a/docs/pull-request.md +++ b/docs/pull-request.md @@ -1,6 +1,6 @@ # Pull Request Description Guide -This guide defines the detailed PR description format for agents and contributors. The human-facing template at [`../.github/pull_request_template.md`](../.github/pull_request_template.md) intentionally remains lightweight; use it as the starting point and expand its `Description / 描述` section when the change needs more context. +This guide defines the detailed PR description format for agents and contributors. The human-facing template at [`../.github/pull_request_template.md`](../.github/pull_request_template.md) intentionally remains lightweight; use it as the starting point and expand its `Description / 描述` section when the change needs more context. This guide covers the description body only — for the PR **title** (gitmoji + Chinese preferred), see [`develop.md`](./develop.md#commit--pull-request-guidelines). ## Recommended structure From 3a6b5917ef17b716baf247dc75663dacd74849eb Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:03:27 +0900 Subject: [PATCH 11/16] =?UTF-8?q?=F0=9F=93=84=20=E7=A7=BB=E9=99=A4=206=20?= =?UTF-8?q?=E4=B8=AA=20references=20=E6=96=87=E6=A1=A3=E4=B8=AD=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E7=9A=84=E6=A0=87=E9=A2=98=EF=BC=88H1=20=E7=B4=A7?= =?UTF-8?q?=E8=B7=9F=E5=90=8C=E4=B9=89=20H2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit architecture-build/data/execution/gm-api/services.md 与 design-components.md 都是从旧的单体 architecture.md / design.md 拆分 出来时留下的产物:文件顶部新增了 H1 标题,但原来的段落 H2 标题(同一 个名字,只是大小写/措辞略有不同)没有删除,紧跟其后、中间无任何内容。 对 agent 而言,同一份文件里出现两个几乎相同的标题会造成: - grep/搜索标题时出现两个几乎相同的结果,不确定该看哪一个; - GitHub 渲染时两者 slug 冲突,第二个会被自动加 -1 后缀,导致任何人 凭标题文字手写的锚点链接可能命中错误的标题。 已用 git grep 确认现有文档中没有任何链接指向这些 H2 的锚点 (#the-service-layer 等),删除是安全的;每个文件正文的第一段本身也 已经把 H2 想额外表达的信息(如 design-components.md 的 "usage")说 清楚了,不存在信息丢失。 Co-Authored-By: Claude Sonnet 5 --- docs/references/architecture-build.md | 2 -- docs/references/architecture-data.md | 2 -- docs/references/architecture-execution.md | 2 -- docs/references/architecture-gm-api.md | 2 -- docs/references/architecture-services.md | 2 -- docs/references/design-components.md | 2 -- 6 files changed, 12 deletions(-) diff --git a/docs/references/architecture-build.md b/docs/references/architecture-build.md index 64f29ea00..c0b48ab1d 100644 --- a/docs/references/architecture-build.md +++ b/docs/references/architecture-build.md @@ -1,7 +1,5 @@ # Build pipeline & manifest -## Build Pipeline & Manifest - ### Rspack [`rspack.config.ts`](../../rspack.config.ts) emits one bundle per context/page. Entry points: diff --git a/docs/references/architecture-data.md b/docs/references/architecture-data.md index 171041664..05112f59d 100644 --- a/docs/references/architecture-data.md +++ b/docs/references/architecture-data.md @@ -1,7 +1,5 @@ # Data layer (Repo + DAOs) -## The Data Layer (`Repo` + DAOs) - Persistence is a thin generic over `chrome.storage.local` with an optional in-memory cache, in [`src/app/repo/repo.ts`](../../src/app/repo/repo.ts). diff --git a/docs/references/architecture-execution.md b/docs/references/architecture-execution.md index 717ea0f12..563e60047 100644 --- a/docs/references/architecture-execution.md +++ b/docs/references/architecture-execution.md @@ -1,7 +1,5 @@ # Script execution -## Script Execution - There are three execution paths; all share one **compilation** step. ### Compilation — the `with(){}` sandbox wrapper diff --git a/docs/references/architecture-gm-api.md b/docs/references/architecture-gm-api.md index e6da7f8a6..42f728f91 100644 --- a/docs/references/architecture-gm-api.md +++ b/docs/references/architecture-gm-api.md @@ -1,7 +1,5 @@ # GM API system -## The GM API System - The `GM_*` / `GM.*` functions a userscript calls are not one function — each is a small client that forwards across contexts to a privileged handler, then streams the result back. The implementation is split: diff --git a/docs/references/architecture-services.md b/docs/references/architecture-services.md index 2c2797bd3..7aeac49a4 100644 --- a/docs/references/architecture-services.md +++ b/docs/references/architecture-services.md @@ -1,7 +1,5 @@ # Service layer -## The Service Layer - Services live under `src/app/service//` — **split by the context they run in** — and hold the domain logic. They are deliberately "dumb plumbing on the outside, smart logic on the inside": construction is pure DI, wiring happens once in a manager, and message handlers are registered in `init()`. diff --git a/docs/references/design-components.md b/docs/references/design-components.md index 6f4ec4f6e..7234efee1 100644 --- a/docs/references/design-components.md +++ b/docs/references/design-components.md @@ -1,7 +1,5 @@ # Component palette -## Component palette & usage - The shadcn primitives live in [`src/pages/components/ui/`](../../src/pages/components/ui/) — `new-york` style, CSS variables enabled, no class prefix (`components.json`). Icons are always `lucide-react`; class merging is always `cn()` ([`src/pkg/utils/cn.ts`](../../src/pkg/utils/cn.ts)); variants are always CVA — these are the [`DEVELOP.md` UI section](../develop.md) hard rules, not repeated here. This section is "what exists and how to choose." ### Primitives & shared composites From c4c19ae650abffcaf0fd75effc6eec24706e2411 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:03:55 +0900 Subject: [PATCH 12/16] =?UTF-8?q?=F0=9F=93=84=20=E6=B6=88=E9=99=A4=20verif?= =?UTF-8?q?ication-report-template.md=20=E4=B8=AD=E4=B8=A4=E5=A4=84=20"Evi?= =?UTF-8?q?dence=20Index"=20=E6=A0=87=E9=A2=98=E9=87=8D=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 文件里有两个 fenced ```md``` 模板块:第一块只是 Evidence Index 这一节 填好后的排版示例(单独摘出来演示格式),第二块才是完整 report.md 骨架,其中的 Evidence Index 一节写的是"参见上面的样式",依赖第一块。 两块标题字面完全相同("## Evidence Index"),会让 agent: - 搜索"Evidence Index"时得到两个含义不同的命中,不确定哪个是真正要 填的位置; - 更危险的是,若把第一块整体当成 report.md 模板复制,会得到一份只有 Evidence Index、缺失 Mode/Goals/Task List/Execution Log/Result/ Blockers 等必需小节的残缺记录。 给第一块标题加上 "(filled-in example)" 后缀消除字面重复,并在两处 之间补一句说明区分两者用途;第二块的回指文字也同步改成精确匹配新 标题,避免"see the shape above"这种模糊指代。 Co-Authored-By: Claude Sonnet 5 --- docs/references/verification-report-template.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/references/verification-report-template.md b/docs/references/verification-report-template.md index 0ead5e653..9e5fd2f87 100644 --- a/docs/references/verification-report-template.md +++ b/docs/references/verification-report-template.md @@ -4,8 +4,11 @@ Before running the browser, create a short verification record in the scenario d `test-results/verify//report.md`. Keep the reusable template headings in English, but write the actual record content in the user's language. Update it as the run proceeds instead of filling it in only at the end. +This is the `Evidence Index` section alone, filled in, to show its shape — it is not the full report; the full +report shape (which reuses this same section) is below. + ```md -## Evidence Index +## Evidence Index (filled-in example) ### Screenshots @@ -81,7 +84,8 @@ Use this shape: ## Evidence Index -Embed screenshots inline, link videos / logs / resources, and annotate every item — see the shape above. +Embed screenshots inline, link videos / logs / resources, and annotate every item — see `Evidence Index +(filled-in example)` above. ``` Fill `Result` at the end — the honest verdict, per *Step 4 — Report honestly* in [`verification.md`](../verification.md). From fa34afe195d93f3746a66a95793279d725c91579 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:10:15 +0900 Subject: [PATCH 13/16] =?UTF-8?q?=F0=9F=93=84=20DOC-MAINTENANCE.md=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=94=9A=E7=82=B9=E5=AE=8C=E6=95=B4=E6=80=A7?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原有链接检查只验证目标文件是否存在,会把 `#anchor` 直接截掉,从不 校验锚点本身——标题改名/删除时,指向它的 file.md#anchor 链接可以 静默失效而不被任何检查发现。新增第二段脚本,用近似 GitHub slug 算法 (连续空格不合并成单个连字符,如 "Commit & Pull Request Guidelines" → commit--pull-request-guidelines)反推每个锚点应指向的标题并核对。 已用当前分支全部锚点链接跑过一次:仅一处已知限制(CJK 标题不做 ASCII 近似)产生误报,其余全部通过。 Co-Authored-By: Claude Sonnet 5 --- docs/DOC-MAINTENANCE.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/DOC-MAINTENANCE.md b/docs/DOC-MAINTENANCE.md index 64679645e..75608bec7 100644 --- a/docs/DOC-MAINTENANCE.md +++ b/docs/DOC-MAINTENANCE.md @@ -111,6 +111,29 @@ for doc in AGENTS.md docs/README.md docs/DOC-MAINTENANCE.md docs/develop.md docs done ``` +Anchor integrity — the check above only confirms the **target file** exists; a `file.md#anchor` link's fragment +can still rot silently if the target heading is renamed. This second pass re-derives each anchor from the +target's actual headings using a best-effort GitHub-slug approximation (lowercase; drop everything but letters, +digits, spaces, hyphens, underscores; each space becomes its own hyphen — consecutive spaces do **not** collapse, +which is why `## Commit & Pull Request Guidelines` slugs to `commit--pull-request-guidelines` with a double +hyphen). **ASCII-only:** it cannot slugify CJK/non-ASCII headings correctly, so anchors into those headings +(e.g. `translation.md#各语言术语规范--per-locale-terminology`) need manual verification instead. + +```bash +slugify() { printf '%s\n' "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[`]//g; s/[^a-z0-9 _-]//g; s/[[:space:]]/-/g'; } +for doc in AGENTS.md docs/README.md docs/DOC-MAINTENANCE.md docs/develop.md docs/references/develop-testing.md docs/design.md docs/references/design-tokens.md docs/references/design-components.md docs/references/design-patterns.md docs/architecture.md docs/references/architecture-services.md docs/references/architecture-data.md docs/references/architecture-gm-api.md docs/references/architecture-execution.md docs/references/architecture-build.md docs/verification.md docs/references/verification-debugging.md docs/references/verification-report-template.md docs/cloud-sync.md docs/translation.md; do + sed '/^```/,/^```/d' "$doc" | sed -E 's/`[^`]*`//g' | grep -oE '\]\([^)]+#[^)]+\)' | sed -E 's/^\]\(|\)$//g' | while read -r link; do + tf="${link%%#*}"; anchor="${link#*#}" + target="$doc"; [ -n "$tf" ] && target="$(dirname "$doc")/$tf" + [ -e "$target" ] || { echo "BROKEN-FILE $doc → $link"; continue; } + found=0 + while IFS= read -r h; do [ "$(slugify "$h")" = "$anchor" ] && found=1 && break; done \ + < <(grep -E "^#{1,6} " "$target" | sed -E 's/^#{1,6} +//') + [ "$found" -eq 1 ] && echo "ok $doc → $link" || echo "BROKEN-ANCHOR $doc → $link (target: $target)" + done +done +``` + ## When you find a discrepancy Fix the **doc** to match the code — the code on this branch is the source of truth. The exception: if the code From 6eea05ed84ce953912a3d246e246af8063e1cf5d Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:11:17 +0900 Subject: [PATCH 14/16] =?UTF-8?q?=F0=9F=93=84=20=E6=8A=8A=E6=8C=87?= =?UTF-8?q?=E5=90=8D=E5=85=B7=E4=BD=93=E7=AB=A0=E8=8A=82=E7=9A=84=E6=95=A3?= =?UTF-8?q?=E6=96=87=E8=A1=A5=E6=88=90=20file.md#anchor=20=E7=B2=BE?= =?UTF-8?q?=E7=A1=AE=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit develop-testing.md、architecture.md、verification-debugging.md、 verification.md 里有五处链接:正文已经用"→ Engineering Principles" "→ Testing""deep model in ARCHITECTURE.md"这类措辞点名了目标文件里 的具体章节,但链接本身只写到文件级别,agent 要打开整份 AGENTS.md / develop.md / architecture.md 自己找那一段。 补上 #engineering-principles、#testing、#the-five-contexts-process-model 锚点,用 DOC-MAINTENANCE.md 里新增的锚点校验脚本核对过,全部命中真实 标题;未触碰任何有意指向整份文件的链接(如 AGENTS.md 头部"读 docs/develop.md"这类横幅提示、docs/README.md 索引表)——那些本来就该 是整篇阅读,加锚点反而会误导范围。 Co-Authored-By: Claude Sonnet 5 --- docs/architecture.md | 2 +- docs/references/develop-testing.md | 2 +- docs/references/verification-debugging.md | 2 +- docs/verification.md | 14 ++++++++------ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index cbe6f5f7a..830502c73 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -219,7 +219,7 @@ Map a change onto the existing extension points instead of inventing new structu - **A new GM API.** Decorate the method with `@GMContext.API` on the content side, add a privileged/offscreen handler if needed, register the `@grant` (see [GM API system](./references/architecture-gm-api.md#adding-a-gm-api-sketch)). -Follow the engineering principles in [`AGENTS.md`](../AGENTS.md): fix root causes (no `as any` / swallowed +Follow the engineering principles in [`AGENTS.md`](../AGENTS.md#engineering-principles): fix root causes (no `as any` / swallowed errors), prefer direct replacement over adapter sandwiches, and keep scope tight — three similar lines beat a premature abstraction. diff --git a/docs/references/develop-testing.md b/docs/references/develop-testing.md index 273fb366c..cc8a40c28 100644 --- a/docs/references/develop-testing.md +++ b/docs/references/develop-testing.md @@ -1,7 +1,7 @@ # Testing > The **TDD/BDD-first principle** (write failing tests before implementation; fix code not tests) lives in -> [`AGENTS.md`](../../AGENTS.md) → *Engineering Principles*. This section is the mechanics. +> [`AGENTS.md`](../../AGENTS.md#engineering-principles) → *Engineering Principles*. This section is the mechanics. Vitest + happy-dom. Per-test budgets live in `vitest.config.ts` per project: non-UI projects (`fast`, `isolated`) use 340ms; the `ui` project (`src/pages/**/*.test.{ts,tsx}` — React renders, including diff --git a/docs/references/verification-debugging.md b/docs/references/verification-debugging.md index 5a733e722..fc0fb1b9d 100644 --- a/docs/references/verification-debugging.md +++ b/docs/references/verification-debugging.md @@ -3,7 +3,7 @@ ## Five-context debug map A feature can break in any of ScriptCat's five isolated contexts. Match the symptom to where its logs live (deep -model in [`ARCHITECTURE.md`](../architecture.md)): +model in [`ARCHITECTURE.md`](../architecture.md#the-five-contexts-process-model)): | Symptom | Where to look | | --- | --- | diff --git a/docs/verification.md b/docs/verification.md index 0ff875387..d47ea758c 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -7,8 +7,9 @@ > scripts and local-only evidence — kept out of Git and never deleted as part of a run; cleanup is the user's call. > > **What this is NOT.** It is *not* the test-suite reference. The mechanics of Vitest unit tests and the -> permanent Playwright E2E suite live in [`DEVELOP.md`](./develop.md) → *Testing*; the TDD-first principle and -> engineering rules live in [`../AGENTS.md`](../AGENTS.md). Read those for writing committed tests. +> permanent Playwright E2E suite live in [`DEVELOP.md`](./develop.md#testing) → *Testing*; the TDD-first principle +> and engineering rules live in [`../AGENTS.md`](../AGENTS.md#engineering-principles). Read those for writing +> committed tests. > > **When to skip this guide.** Docs-only, comment-only, and type-only changes need no browser run. When a change > or bug is fully reproducible in pure service/unit logic — no cross-context wiring, no real Chrome API, no DOM — @@ -25,12 +26,13 @@ you only want to *check that a feature works*, do not pay that cost and do not l - ✅ Write a **throwaway scratch script** under `e2e/scratch/` (git-ignored), run it, and keep any evidence local. Promoting a scenario into the permanent suite is a *separate, deliberate* decision — only when it deserves -permanent regression coverage. That path is owned by [`DEVELOP.md`](./develop.md), not this guide. +permanent regression coverage. That path is owned by [`DEVELOP.md`](./develop.md#testing), not this guide. **Reproducing a bug you intend to fix is *not* "casual verification."** A scratch reproduction is the *确定 bug -存在* step from [`../AGENTS.md`](../AGENTS.md) (确定 bug 存在 → 写测试 → 修复): it confirms the bug is real but does -**not** replace the test. Next, promote it into a *failing* committed test, then fix, then confirm it goes green — -that permanent test is owned by [`DEVELOP.md`](./develop.md) / [`../AGENTS.md`](../AGENTS.md). +存在* step from [`../AGENTS.md`](../AGENTS.md#engineering-principles) (确定 bug 存在 → 写测试 → 修复): it confirms the +bug is real but does **not** replace the test. Next, promote it into a *failing* committed test, then fix, then +confirm it goes green — that permanent test is owned by [`DEVELOP.md`](./develop.md#testing) / +[`../AGENTS.md`](../AGENTS.md#engineering-principles). ## Prerequisite gate (cheap signals first) From cf5d6d6c38a24154748986dcd9d635e5cce73a29 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:17:25 +0900 Subject: [PATCH 15/16] =?UTF-8?q?=F0=9F=93=84=20=E8=A1=A5=E4=B8=8A?= =?UTF-8?q?=E4=B8=89=E5=A4=84=20"UI=20section"=20=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E9=81=97=E6=BC=8F=E7=9A=84=20#ui=20=E9=94=9A=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit design.md、design-tokens.md、design-components.md 各有一处链接,可见 文字本身写的是 "DEVELOP.md UI section",但 href 只写到 ./develop.md 文件级别——链接文字已经点名了目标章节,href 却没跟上。develop.md 第 54 行确有 "## UI" 标题,补上 #ui 锚点使三者一致。 用重新跑过的锚点扫描(按目标文件真实标题列表反查每个链接文字,排除 命中目标文件自身标题的"整份文件引用")确认这是本轮唯一遗漏,其余全部 指向整份文件的链接维持不变。 Co-Authored-By: Claude Sonnet 5 --- docs/design.md | 2 +- docs/references/design-components.md | 2 +- docs/references/design-tokens.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/design.md b/docs/design.md index 54edc4f75..98a51eba3 100644 --- a/docs/design.md +++ b/docs/design.md @@ -10,7 +10,7 @@ | Owned here | Owned elsewhere | | --- | --- | -| Color-token values, semantics, usage → [`tokens.md`](./references/design-tokens.md) | The hard rules that mandate them (no hard-coded colors, hover via pseudo-classes, `cn()` / CVA / `lucide`) → [`DEVELOP.md` UI section](./develop.md) | +| Color-token values, semantics, usage → [`tokens.md`](./references/design-tokens.md) | The hard rules that mandate them (no hard-coded colors, hover via pseudo-classes, `cn()` / CVA / `lucide`) → [`DEVELOP.md` UI section](./develop.md#ui) | | Theming mechanism, `dark:` usage | Commands, structure, coding style, testing, i18n, commit/PR → [`DEVELOP.md`](./develop.md) | | Component palette, variants, selection guidance → [`components.md`](./references/design-components.md) | Process model, message passing, service layers, internals → [`ARCHITECTURE.md`](./architecture.md) | | Layout shell, responsive patterns, **layering (z-index)**, motion, state patterns, **accessibility** → [`patterns.md`](./references/design-patterns.md); **elevation (shadows)** → [`tokens.md`](./references/design-tokens.md#elevation-shadows); page recipe (this doc) | — | diff --git a/docs/references/design-components.md b/docs/references/design-components.md index 7234efee1..0ff8fc62c 100644 --- a/docs/references/design-components.md +++ b/docs/references/design-components.md @@ -1,6 +1,6 @@ # Component palette -The shadcn primitives live in [`src/pages/components/ui/`](../../src/pages/components/ui/) — `new-york` style, CSS variables enabled, no class prefix (`components.json`). Icons are always `lucide-react`; class merging is always `cn()` ([`src/pkg/utils/cn.ts`](../../src/pkg/utils/cn.ts)); variants are always CVA — these are the [`DEVELOP.md` UI section](../develop.md) hard rules, not repeated here. This section is "what exists and how to choose." +The shadcn primitives live in [`src/pages/components/ui/`](../../src/pages/components/ui/) — `new-york` style, CSS variables enabled, no class prefix (`components.json`). Icons are always `lucide-react`; class merging is always `cn()` ([`src/pkg/utils/cn.ts`](../../src/pkg/utils/cn.ts)); variants are always CVA — these are the [`DEVELOP.md` UI section](../develop.md#ui) hard rules, not repeated here. This section is "what exists and how to choose." ### Primitives & shared composites diff --git a/docs/references/design-tokens.md b/docs/references/design-tokens.md index 09c614a53..5557dea81 100644 --- a/docs/references/design-tokens.md +++ b/docs/references/design-tokens.md @@ -7,7 +7,7 @@ **Usage:** - Background `bg-`, text `text-`, border `border-`, focus ring `ring-ring`. - Opacity modifiers compose directly: `bg-primary-background/90` (solid primary hover), `ring-destructive/20`, `bg-input/30`. -- **Never hard-code a color value** — see Constraint 1 and [`DEVELOP.md` UI section](../develop.md). For dark-only tweaks use the `dark:` variant. +- **Never hard-code a color value** — see Constraint 1 and [`DEVELOP.md` UI section](../develop.md#ui). For dark-only tweaks use the `dark:` variant. ### Base surfaces & text From 8659100c1f23efb06ebf1b6fe87aa41a66738aa7 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:27:08 +0900 Subject: [PATCH 16/16] =?UTF-8?q?=F0=9F=93=84=20=E4=BF=AE=E5=A4=8D=20.gith?= =?UTF-8?q?ub/copilot-instructions.md=20=E4=B8=AD=E4=B8=A4=E5=A4=84?= =?UTF-8?q?=E6=9E=B6=E6=9E=84=E6=80=A7=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 这份文件是 GitHub Copilot 自己的入口指令,不在 AGENTS.md 的文档链路 里,本轮"重新扫描全部 agent 可读 markdown"时才发现;它独立复述了一份 架构说明,与 AGENTS.md / architecture.md 各自维护、互不链接,存在两处 与已核实代码不符的地方,且与本 PR 前几轮修复的问题属于同一类: 1. "Sandbox script execution isolated from page context - use unsafeWindow for page access" 把 Sandbox 和 Inject 两个不同 context 混为一谈——Sandbox 跑的是 background/scheduled 脚本,根本没有 page(见 architecture-execution.md:43 "`@background` scripts have no page");unsafeWindow 属于 Inject context(见 architecture.md:84 "Page (`MAIN`) world. Has `unsafeWindow`")。原句会让人误以为可以在 Sandbox 里用 unsafeWindow 访问页面。 2. "Browser Extension Specifics" 完全没提 Firefox 没有 Offscreen API 这件事——与本 PR 第二轮已经在 verification-debugging.md 修复过的 同一个事实缺口(已核对 src/service_worker.ts:77-85)。 Co-Authored-By: Claude Sonnet 5 --- .github/copilot-instructions.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 661d44371..135fa6d58 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -109,7 +109,8 @@ pnpm run coverage # Generate coverage reports ### Browser Extension Specifics - **Manifest V3** with service worker background - **User Scripts API** for script injection (Chrome/Edge) -- **Offscreen API** for DOM access in background contexts +- **Offscreen API** for DOM access in background contexts — **Firefox MV3 has no Offscreen API**; + `EventPageOffscreenManager` runs the same DOM-dependent logic inside the background event page instead - **Declarative Net Request** for script installation interception ## Critical Integration Points @@ -136,7 +137,8 @@ pnpm run coverage # Generate coverage reports - Use `pnpm run dev:noMap` for incognito window development - Background script changes require extension reload - Message passing debugging available in service worker console -- Sandbox script execution isolated from page context - use `unsafeWindow` for page access +- Sandbox (background/scheduled scripts) has no page at all — not "isolated from" a page, it never has one. + `unsafeWindow` belongs to the **Inject** context (page scripts), not Sandbox ## File Structure Patterns - Tests co-located with source files (`.test.ts` suffix)