From 8388487ab653be1f5892cdab711764fde1908ef4 Mon Sep 17 00:00:00 2001
From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com>
Date: Tue, 7 Jul 2026 02:12:47 +0900
Subject: [PATCH 01/10] docs: add technical proposal for structure refactor +
i18n completion
Captures the current-state audit (URL contract, title/H1 mismatches,
translation gaps, broken links/anchors) and the phased plan to fix
folder structure, sidebar/title consistency, and English translation
without changing any published URL.
---
REFACTOR_PROPOSAL.md | 300 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 300 insertions(+)
create mode 100644 REFACTOR_PROPOSAL.md
diff --git a/REFACTOR_PROPOSAL.md b/REFACTOR_PROPOSAL.md
new file mode 100644
index 0000000..880ed35
--- /dev/null
+++ b/REFACTOR_PROPOSAL.md
@@ -0,0 +1,300 @@
+# Technical Proposal — Docs Structure Refactor, Title Consistency & Full English Translation
+
+Repo: `scriptscat/scriptcat.org` (docs.scriptcat.org) · Branch: `refactor-001` · Date: 2026-07-07
+Stack: Docusaurus 3.10 (classic preset), pnpm, Gitea Actions → Docker/nginx → Helm/k8s
+
+## 0. Goals & Non-Goals
+
+**Goals**
+
+1. Make the folder structure self-describing: **file path = doc ID = published URL**, with zero frontmatter indirection.
+2. Eliminate the sidebar-label / page-title mismatch class (e.g. `使用文档` sidebar shows "VSCode 扩展开发脚本" but the page H1 is "使用 VSCode 开发脚本") — by construction, not by discipline.
+3. Complete the English translation (25 files currently missing) and keep it complete with a CI parity gate.
+4. Improve workflow/config so regressions (URL changes, broken links, missing translations) are caught mechanically.
+5. Optimize for maintainability by **both humans and coding agents**: one greppable convention per concern, documented in-repo.
+
+**Hard constraint (non-negotiable)**
+
+> **No published URL may change.** All 43 zh-Hans routes, their 43 `/en/` mirrors, plus `/uninstall/`, `/404.html`, `/opensearch.xml` must be byte-identical in the sitemap/route inventory before and after every phase. Several URLs are load-bearing (opened programmatically by the ScriptCat extension): `/docs/script_installation/`, `/docs/use/install_comple/`, `/uninstall/`.
+
+**Non-goals (explicitly out of scope)**
+
+- URL beautification (`/docs/use/use/` → `/docs/use/`, fixing the `install_comple` typo). Listed as an optional, separately-approved Phase 6 using redirects only.
+- Content rewrites beyond title alignment and translation.
+
+---
+
+## 1. Current-State Audit (verified against a local `pnpm run build` on this branch)
+
+### 1.1 The URL contract (baseline, from `build/sitemap.xml`)
+
+43 zh URLs; `build/en/sitemap.xml` mirrors them 1:1 under `/en/` (verified by diff). Key routes and how they are derived today:
+
+| URL | Source file | Derivation quirk |
+|---|---|---|
+| `/docs/use/use/` | `docs/use/1.README.md` | number prefix `1.` stripped; `id: use` overrides filename; **not** an index page — `/docs/use/` itself 404s today |
+| `/docs/use/script_installation/` | `docs/use/2.script_installation.md` | prefix stripped |
+| `/docs/use/sync/` | `docs/use/2.sync.md` | duplicate `2.` prefix (ordering collision with the above) |
+| `/docs/use/QA/` | `docs/use/3.QA.md` | prefix stripped |
+| `/docs/use/from-other/...` | `docs/use/4.from-other/...` | dir prefix stripped; label via `_category_.json` |
+| `/docs/use/open-dev/`, `/docs/use/vscode/` | `5.open-dev.md`, `6.vscode.md` | prefix stripped |
+| `/docs/use/policy/...` | `docs/use/99.policy/...` | dir prefix stripped |
+| `/docs/use/install_comple/` | `docs/use/install_comple.md` | typo (`comple`) is live; **hardcoded in the extension** |
+| `/docs/dev/` | `docs/dev/README.md` | README-as-index convention + `id: dev` |
+| `/docs/dev/agent/` | `docs/dev/agent/index.md` | index convention + `id: agent` |
+| `/docs/dev/agent/agent-conversation/` etc. | `docs/dev/agent/conversation.md` etc. | `id: agent-conversation` frontmatter renames every agent doc |
+| `/docs/change/` | `docs/change/README.md` | index convention + `id: change` |
+| `/docs/change/beta-changelog/` | `docs/change/beta.md` | `id: beta-changelog` |
+| `/docs/change/v1.4/` … | `docs/change/v1.4.md` … | descending `sidebar_position: 9995…10000` hack for newest-first ordering |
+| `/docs/script_installation/` | `docs/script_installation.md` | extension install intermediate page |
+| `/docs/about/` | `docs/about/README.md` | carries dead VuePress-era keys (`sidebar: false`, `icon: info`) |
+| `/uninstall/` | `src/pages/uninstall.tsx` | extension uninstall-feedback page |
+
+**Three URL-derivation mechanisms coexist** (number-prefix stripping, `id:` overrides, README/index convention). An agent or new contributor cannot map URL → file without reading frontmatter of every candidate. This is the root maintainability problem.
+
+### 1.2 Sidebar/ordering mechanisms — three coexist
+
+- `use`: autogenerated from number prefixes (already collided: two `2.` files).
+- `dev`: explicit list in `sidebars.js`, referencing frontmatter-overridden IDs.
+- `change`: autogenerated + descending `sidebar_position` hack.
+
+### 1.3 Title/label mismatches (frontmatter `title` drives the sidebar; body `# H1` drives the page)
+
+Found by script (zh; mirrored in en where translated):
+
+| File | `title` (sidebar/`
`) | Body H1 (page heading) |
+|---|---|---|
+| `docs/use/6.vscode.md` | VSCode 扩展开发脚本 | 使用 VSCode 开发脚本 |
+| `docs/use/99.policy/disclaimer.md` | 免责声明 | ScriptCat 免责协议 |
+| `docs/use/99.policy/privacy.md` | 隐私政策 | ScriptCat 隐私政策 |
+| `docs/use/99.policy/privacy_website.md` | 脚本站点 隐私政策 | ScriptCat 脚本站点 隐私政策 |
+| `docs/use/install_comple.md` | 安装完成 | 🎉 欢迎使用脚本猫 (intentional: `hide_title: true`) |
+
+Root cause: two competing sources of truth with no rule and no lint.
+
+### 1.4 Translation gaps (en)
+
+Missing entirely (falls back to Chinese on `/en/` pages): **all 13 `dev/` docs** (incl. the whole `agent/` section), `about/README.md`, and changelogs `v0.16`, `v0.17`, `v1.1`, `v1.2`, `v1.4` — 25 files. Additionally the en asset tree diverges from zh in naming (`i18n/en/.../use/4.from-other/img/migrate-from-violentmonkey.assets/` vs zh `img/migrate-from-violentmonkey/`).
+
+### 1.5 Broken links/anchors already shipping (build warns; `onBrokenLinks: "warn"` lets them through)
+
+- `/en/docs/use/vscode/` → links `/en/docs/use/` (**404 — `/docs/use/` and `/en/docs/use/` do not exist**; the site footer also links `/docs/use`).
+- `docs/dev/agent/skill-install.md` uses URL-style relative links (`./agent-skill/`) that resolve incorrectly.
+- 7 broken anchors across `/docs/dev/`, `/docs/dev/api/`, `/docs/dev/meta/`, `/docs/change/` (stale `#定时脚本`/`#后台脚本`/`#gm_cookie`/`#storagename-🧪` targets).
+
+### 1.6 Repo/CI hygiene
+
+- 15+ `.DS_Store` files committed; not in `.gitignore`.
+- No PR/CI validation workflow — only the deploy workflow, which builds and ships without link/translation/URL checks.
+- Deprecation warning: `onBrokenMarkdownLinks` must move to `markdown.hooks.onBrokenMarkdownLinks` (removed in Docusaurus v4).
+- Asset conventions: four patterns coexist (`X.assets/` sibling, `img/X.assets/`, `img/X/`, section-level `img/`).
+- `editUrl` does not set `editLocalizedFiles`, so "Edit this page" on `/en/` pages edits the zh source.
+
+---
+
+## 2. Target Design
+
+### 2.1 Principle: one convention per concern
+
+| Concern | Single source of truth |
+|---|---|
+| URL / doc ID | File path, verbatim (no `id:`, no number prefixes) |
+| Page title, sidebar label, `` | Frontmatter `title:` (+ optional `sidebar_label:` for deliberate short labels) |
+| Sidebar ordering | `sidebars.js`, explicit for all three sidebars |
+| Images | `.assets/` sibling folder |
+| Internal links | File-relative paths to the `.md` file (Docusaurus validates them at build time) |
+| URL contract | Committed `scripts/url-inventory.txt`, enforced in CI |
+
+### 2.2 File renames (path ⇒ today's URL, then delete all `id:` overrides)
+
+All renames use `git mv`. The i18n/en tree is renamed identically in the same commit. Resulting doc IDs equal today's IDs, so URLs are provably unchanged.
+
+```text
+docs/use/1.README.md → docs/use/use.md # id use/use, URL /docs/use/use/ (unchanged)
+docs/use/2.script_installation.md → docs/use/script_installation.md
+docs/use/2.sync.md → docs/use/sync.md
+docs/use/3.QA.md → docs/use/QA.md # keep exact case
+docs/use/4.from-other/ → docs/use/from-other/
+docs/use/5.open-dev.md → docs/use/open-dev.md
+docs/use/6.vscode.md → docs/use/vscode.md
+docs/use/99.policy/ → docs/use/policy/
+docs/use/install_comple.md → (keep; URL typo is load-bearing — add a NOTE comment in the file)
+
+docs/dev/README.md → docs/dev/index.md # id dev/index, URL /docs/dev/ (unchanged)
+docs/dev/agent/index.md → (keep name; drop id: agent → id dev/agent/index, URL /docs/dev/agent/)
+docs/dev/agent/conversation.md → docs/dev/agent/agent-conversation.md
+docs/dev/agent/dom.md → docs/dev/agent/agent-dom.md
+docs/dev/agent/skill-install.md → docs/dev/agent/agent-skill-install.md
+docs/dev/agent/skill.md → docs/dev/agent/agent-skill.md
+docs/dev/agent/skill-dev.md → docs/dev/agent/agent-skill-dev.md
+docs/dev/agent/task.md → docs/dev/agent/agent-task.md
+docs/dev/agent/model.md → docs/dev/agent/agent-model.md
+docs/dev/agent/opfs.md → docs/dev/agent/agent-opfs.md
+docs/dev/agent/mcp.md → docs/dev/agent/agent-mcp.md
+docs/dev/agent/builtin-tools.md → docs/dev/agent/agent-builtin-tools.md
+
+docs/change/README.md → docs/change/index.md # id change/index, URL /docs/change/
+docs/change/beta.md → docs/change/beta-changelog.md
+
+docs/about/README.md → docs/about/index.md # URL /docs/about/; delete dead keys sidebar:/icon:
+```
+
+Then delete **every** `id:` and `sidebar_position:` frontmatter key repo-wide. The `agent/agent-*.md` names look redundant, but the alternative (keeping short filenames + `id:` overrides) preserves exactly the indirection we are removing; filename==URL is worth the redundancy. (Renaming URLs to drop the `agent-` prefix is forbidden by the constraint.)
+
+`docs/use/use.md` is admittedly an odd name — it is the price of the pre-existing `/docs/use/use/` URL. Phase 6 (optional) can promote it to `index.md` + redirect later.
+
+### 2.3 Sidebars: fully explicit `sidebars.js`
+
+Replace all autogeneration and `sidebar_position` with three explicit arrays (dev is already explicit — just update IDs):
+
+```js
+const sidebars = {
+ use: [
+ "use/use",
+ "use/script_installation",
+ "use/sync",
+ "use/QA",
+ {
+ type: "category",
+ label: "从其它管理器迁移", // translation key format unchanged:
+ items: [ // sidebar.use.category.从其它管理器迁移
+ "use/from-other/migrate-from-tampermonkey",
+ "use/from-other/migrate-from-violentmonkey",
+ ],
+ },
+ "use/open-dev",
+ "use/vscode",
+ {
+ type: "category",
+ label: "服务协议", // sidebar.use.category.服务协议
+ items: ["use/policy/disclaimer", "use/policy/privacy", "use/policy/privacy_website"],
+ },
+ // use/install_comple intentionally unlisted (hidden page)
+ ],
+ dev: [
+ "dev/index", "dev/background", "dev/cloudcat", "dev/subscribe",
+ "dev/config", "dev/api", "dev/cat-api",
+ {
+ type: "category",
+ label: "Agent 智能助手",
+ link: { type: "doc", id: "dev/agent/index" },
+ items: [
+ "dev/agent/agent-conversation", "dev/agent/agent-dom",
+ "dev/agent/agent-skill-install", "dev/agent/agent-skill",
+ "dev/agent/agent-task", "dev/agent/agent-model",
+ "dev/agent/agent-opfs", "dev/agent/agent-mcp",
+ "dev/agent/agent-skill-dev", "dev/agent/agent-builtin-tools",
+ ],
+ },
+ "dev/meta",
+ ],
+ change: [
+ "change/index",
+ "change/beta-changelog",
+ "change/v1.4", "change/v1.3", "change/v1.2", "change/v1.1",
+ "change/v0.17", "change/v0.16", // newest-first; adding a release = insert one line
+ ],
+};
+```
+
+Consequences: delete both `_category_.json` files; delete the `9995…10000` position hack; `use/install_comple.md` no longer needs `sidebar_class_name: hidden` CSS hackery (unlisted docs are simply not in the sidebar — verify the hidden behavior is preserved, else keep the class). Category-label translation keys in `i18n/*/docusaurus-plugin-content-docs/current.json` keep the same `sidebar.use.category.