---
name: Website Rebuild
slug: website-rebuild
category: Frontend
description: "Website Rebuild recreates creative websites with evidence-driven reverse engineering, mirror-first capture, and verification gates. Use it when you need a 1:1 rebuild, archival mirror, or source-level understanding of a public creative site."
github: "https://github.com/boyang-hu/website-rebuild-skill/tree/main/skills/website-rebuild"
language: JavaScript
stars: 840
forks: 169
install: "npx degit https://github.com/boyang-hu/website-rebuild-skill/tree/main/skills/website-rebuild ~/.claude/skills/website-rebuild"
installs_to: ~/.claude/skills/website-rebuild
source_path: skills/website-rebuild/SKILL.md
collection_size: 2
category_size: 621
collection_url: "https://dirskills.com/collections/boyang-hu/website-rebuild-skill"
added: 2026-09-03T06:03:19.646Z
last_synced: 2026-09-03T06:03:19.646Z
canonical_url: "https://dirskills.com/skills/website-rebuild"
---

# Website Rebuild

Website Rebuild recreates creative websites with evidence-driven reverse engineering, mirror-first capture, and verification gates. Use it when you need a 1:1 rebuild, archival mirror, or source-level understanding of a public creative site.

**Install:**

```bash
npx degit https://github.com/boyang-hu/website-rebuild-skill/tree/main/skills/website-rebuild ~/.claude/skills/website-rebuild
```

## README

# Website Rebuild（获奖创意站 1:1 复刻）

把一个获奖创意网站（WebGL / 滚动叙事 / 作品集站）以**取证式方法**复刻为可独立运行、可验证还原度的工程。不是"看着像"的仿制——是以源站 bundle 为唯一规格书、以量化验收门收口的逐行为移植。

本方法论提炼自六个连续实践项目（工期从 6.5 周收敛到 1 天），后经 **22 个完整复刻 + 5 个死站存档抢救**持续回填、43 站边界探测实测校准适用范围（清单见仓库 README「已验证过的网站」）。

## 使用前提与授权 ⛔ 必读

本 skill 面向**学习与研究目的**的保真复刻，用于研究获奖创意站的实现手法。适用对象是你**自有的、已获授权的，或公开可访问且允许学习临摹**的网站。它不是用于未授权地采集受保护内容、规避访问控制、或商业性盗用他人作品的工具。

执行时遵守下列边界：
- **尊重目标站规则**：遵守其 `robots.txt`、服务条款与版权；抓取保持低频、单会话，不对目标站施加异常负载。⛔ **`robots.txt` 是逐路径的许可声明，不是全站开关**——逐 URL 判定（选组 → 最长匹配 → 无匹配即允许），**不得因为存在任何 `Disallow` 行就判"整站禁止"**（几乎每个商业站都有 `/cart`、`/checkout`、`/admin` 的 `Disallow`）；禁令要按行为类别归类，**只有针对"抓取"的禁令才影响镜像范围**，针对交易的禁令只意味着"别去点结账"。⭐ **"读不懂 / 拿不准"不等于"禁止"**：走呈交，不走停工，更不自行缩小抓取范围。读法见 [references/legal-and-deploy.md](references/legal-and-deploy.md) §0.3。
- **不触碰受保护边界**：不采集需要登录态、付费墙或授权才能访问的内容；本 skill 只处理匿名可公开访问的资源。若目标站明确禁止此类复制，停止并告知用户——**何为"明确禁止"见 `legal-and-deploy.md` §0.3.6 写死的四条门槛，其余一切不确定性走呈交不走停工**。
- **产出默认私有**：默认 noindex、不公开部署。任何公开前必须完成逐资产版权取证，并显著标注"非官方复刻"与原作者归属（见 [references/legal-and-deploy.md](references/legal-and-deploy.md)）。

⛔ **法务判断归用户，skill 只取证与呈现**（三条，全程有效）：

1. **决定权在用户**：skill 收集事实（逐资产归属、许可状态、第三方权利人、源站是否仍在营业、产物内第三方标识符）、列出选项与各自的风险边界、给出建议与理由；凡涉及"能不能公开 / 部署 / 再分发 / 对外展示"，**必须用下文「User Input Tools」显式交回用户**，不许 agent 自行下法律结论后继续往下走。
2. **未获用户明确决定前按安全默认执行**：私有仓库 + `noindex` + 不公开部署 + 不再分发。写给用户时说明这是**默认动作**（"在你决定之前我不会把它发出去"），**不是** agent 已作出的法务结论——两者责任归属完全不同。agent 只能往保守侧执行默认，往公开侧走必须有用户的明确决定。
3. ⛔ **法务考量不得削减镜像完整性或门的覆盖面**：镜像是证据基座，**完整性是技术不变量**（四遍法、闭包门、GAP=0 全建立在它之上）。不抓只能有**技术性理由**（不是文件 / 服务端不提供 / 需授权或登录态 / 源站明令禁止），一律登记；**不得**以"反正不公开""不该多存一份"这类法务理由留洞【objectarchive】（实证：`references/case-studies/skill.md`「使用前提与授权」）。法务决定作用于**产出怎么被使用**，不是证据基座是否完整。

## 适用范围 ⛔ 必读

**主场（A 类）**：内容静态托管、签名行为（动画/交互）全部存放在客户端静态资产里的站——命令式 WebGL/Canvas 场景、GSAP 时间轴、烘焙数据文件（GLB/.buf/.riv）、minified 或未混淆的 bundle。绝大多数 Awwwards 风格创意站属于此类。

**有条件支持（B 类）**：管线成立但需要额外场景处理（Shopify 平台层剥离、第三方存储桶资产、运行时 API 快照、SSG payload 展开）。当前版本的指南覆盖大部分 B 类场景，遇到未覆盖的要向用户明示风险。

**明确拒绝（C/D 类）**：
- **C1（v0.3 起可做：重构式逆向）**：服务端组件源确实不下发，但**它的完整输出（flight 流）内联在每页 HTML 里，是可对拍的规格书**。路线：flight-decode 建坐标系 → 重构一个可构建的 Next 工程（客户端一方组件按 C2 逐字译，服务端组件从 flight 树反推为显式登记的推断物）→ verify-flight 语义门收口（模块 id 全局双射；实证：`references/case-studies/skill.md`「适用范围」）。⚠ C1 的 L2/L3 合并——第一份产物就是「人写的源码 + 门证明的等价」。全流程见 [references/rsc-reconstruction.md](references/rsc-reconstruction.md)。
- **C2（可做，按 A 类跑）**：⭐ 写法是声明式但**源码下发**（R3F / Theatre / Vue SFC 编译产物）。**切片器不关心范式——它切的是字节。** 渲染器当平台层从镜像伺服（实证：`references/case-studies/skill.md`「适用范围」）。⛔ 判别器不是库名，是「客户端是否持有行为源」（`scope-and-fingerprint.md` §4.0.1）。
- **D**：行为主体在服务端（CMS 内容站、电商 cart/库存、A/B 实验分桶、个性化注水）——客户端没有可移植的目标物，且确定性验收无基准。

**X 类（可抢救）**：原站已消失（域名易主 / 平台回收 / 路径移除 / 原地被替换），但 Internet Archive 往往有捕获——`scripts/wayback-mirror.mjs` 从 CDX 索引按**锚点 + 时间窗**选一个连贯时刻、以 `id_` 原始字节抓成**标准镜像**（下游门原样工作），洞按既成事实登记进 `wayback-holes.txt`（读法与流程见 [references/archival-rescue.md](references/archival-rescue.md)）。⭐ 抢救产出是**标准镜像**——X 类可走完 L3 全程（实证：`references/case-studies/skill.md`「适用范围」）。⛔ **"CDX 无覆盖才是真不可做"按资产层读，不按站读**：IA 爬虫不执行 JS，清单/拼接驱动的站可以代码层覆盖 100% 而画面层为零（实证：`references/case-studies/skill.md`「适用范围」）——Step 0 先做分层覆盖侦察（推导 + CDX 前缀查询）预判抢救深度,见 `archival-rescue.md` §1.9。历年获奖站实测消失率约 29%——这也是"第一时间镜像"是本 skill 第一纪律的原因。

判级由 Step 0 指纹侦察决定，完整判定树见 [references/scope-and-fingerprint.md](references/scope-and-fingerprint.md)。**拒绝时要解释原因并说明该站属于哪一类**，不要硬跑。

## User Input Tools

需要向用户提问时（确认范围、**法务决定**、外部依赖决策）：优先使用当前运行时的内置提问工具（如 `AskUserQuestion`）；没有则输出编号问题清单让用户回复编号。支持多问合并时一次问完。法务类提问按 `legal-and-deploy.md` §0.1 的五段式写：事实 / 查不清的 / 选项 / 每个选项的风险边界 / 建议与当前默认动作。

## 宪法（六条纪律，全程有效）

以下六条在六个源项目中被称为"宪法级"，违反任何一条都会在后续阶段以 bug 形式偿还：

1. **镜像神圣不可污染**：`mirror/` 磁盘文件永不修改；一切本地化适配（CDN 改写、外链 stub）在服务层响应时动态完成。
2. **源站代码是唯一裁决，不凭观感修**：每个改动先在 bundle/CSS/镜像 HTML 里找到归属行号再落地。Do not tune visuals, motion, or interaction by eye.
3. **源站有的都要有，源站没有的不做**：不自创补偿性 CSS/JS。宁可先不像，也不要发明规则——自创补丁会在机制对齐后反转成 bug。
4. **bug / 死代码 / 怪写法照抄不修**：压缩代码里的每个怪写法都可能是行为本身。"好心修正" no-op bug 曾导致转场崩溃（实证见 porting-discipline.md）。
5. **有意偏差必须登记**：写清"源站怎么做 / 我们怎么做 / 为什么 / 什么条件下重新考虑"。**没登记的差异一律视为 bug**。
6. **代码与文档同一次提交**：每个里程碑成对提交（`Port xxx` + `Update rebuild plan: xxx`），日志固定含产出 / 验收 / 教训 / 下一步断点（带行号）。

⭐ **纪律 3 在 M(n+1) 的边界**：`src/` 是显式登记的衍生物，不是对源站的断言，所以**在 `src/` 里重命名、拆模块、写注释不算"发明"**——纪律 3 约束的是"为了让它看起来像而自创行为"，不是"让已证明等价的代码变得可读"。但两条硬边界不动：**① 结构性重写默认禁止**（合并重复、提取公共函数、改算法——它们让等价不可判定）；**② 注释里的推测必须标注为推测**，不许把逆向笔记里的猜测写成陈述句。`port/` 与 `mirror/` 仍然一个字节都不许动。详见 [references/readable-source.md](references/readable-source.md) §3.4 与 §5。

## Workflow

### Progress Checklist

```
[ ] Step 0  指纹侦察与范围门 ⛔（判级 A/B/C/D/X；C/D/X 拒绝或引导，不进入下一步）
[ ] Step 1  开工评级（架构证否、分项难度打星、工期预估、与用户确认范围 + 终点 L1/L2/L3）
[ ] M0      镜像取证 ⛔（BFS 爬虫 + CDP 补录 + manifest 账本；GAP=0）
[ ] M0.5    镜像断网跑通 ⛔（零 404 / 零控制台错误 / 零外联；serve.mjs 伺服）← L1 镜像存档 终点
[ ] M1      逆向建坐标系 ⛔（_pretty 钉版本展开；engine-notes 先于任何代码；技术栈钉死；REBUILD_PLAN 建立）
[ ] M2+     严格溯源移植（依赖序里程碑推进；先竖切一条端到端链路；每里程碑冷启动实测 + CLEAN 门）
[ ] M(n-1)  对拍验收（按 verification-gates.md 决策树选门型；根因修复，不调参糊平）
[ ] M(n)    收口 ⛔（冷头评审 / 模块清单对账；版权取证 + 呈交用户决定——公开部署前必须完成）← L2 工程化复刻 终点
[ ] M(n+1)  源码化（port/ → src/：拆模块、去混淆重命名、补注释、自包含）← L3 源码化 终点
```

⛔ = 阻塞门：验收标准未达成不得进入下一阶段。

标记约定（全部文档通用）：⛔ 硬规则，违反即 bug · ⛔⛔ 已在实战里付过高代价的硬规则 · ⭐ 经验证的做法 · ⭐⭐ 反直觉但已被数据证实的做法 · ⚠ 陷阱 / 边界 · 【代号】= 实证来源项目（对应 README「已验证过的网站」）。

### Flow

**Step 0 — 指纹侦察与范围门**。加载 [references/scope-and-fingerprint.md](references/scope-and-fingerprint.md)，对用户给的 URL 执行探测协议（GET 到路径粒度、最终 URL 同一性、双抓 diff、物种/年代校验、bundle 初检），输出判级与依据。A/B 类继续；C/D/X 类向用户解释后停止或引导。

**Step 1 — 开工评级**。加载 [references/recon-and-rating.md](references/recon-and-rating.md)。架构假设先证否（依赖表会撒谎），分项难度打星（素材/3D/滚动编排/私有格式/平台层），向用户确认复刻范围（整站或指定页面）与预期。

⭐ **同一次提问里让用户选终点**（三级梯子，带着判级结论与分级成本估计问，不要干巴巴列选项）：

| 终点 | 回答的问题 | 止于 | 典型用途 |
|---|---|---|---|
| **L1 镜像存档** | 它长什么样 | M0.5 | 存档、离线欣赏（获奖站年消失率约 29%） |
| **L2 工程化复刻** | 它在做什么 | M(n) | 可部署、可验证的 1:1（含版权取证与部署评估） |
| **L3 源码化** | 它怎么做的 | M(n+1) | 研究与学习实现手法 |

**梯子单调，选低不亏**：每一级都是下一级的前缀，镜像纪律保证时间敏感的部分永远最先完成——今天选 L1，以后想升级随时续跑（向用户说明这一点）。**"拿它做自己的项目"（脚手架化）不是本 skill 的阶段**——用户问起时指向 [references/beyond-the-rebuild.md](references/beyond-the-rebuild.md) 交接，那是他的工程，skill 到"人能读懂的真实"为止。

**M0 / M0.5 — 镜像取证**。加载 [references/mirroring.md](references/mirroring.md)。用 `scripts/mirror-site.mjs` BFS 爬取 + `scripts/netcapture.mjs` 真实浏览器补录，manifest 逐文件登记 sha256，`redirect: manual` 纪律，外部依赖逐项决策。`scripts/verify-mirror.mjs` 是**镜像自己的门**（五项断言，跑在断网门之前——下游所有门问的都是"渲染得出来吗"，错的镜像能让它们全绿；**一个 HTTP 200 也不是"你拿到了那个资源"的证据**）。`scripts/serve.mjs` 伺服镜像，断网验收。**这一步永远最先做**——原站随时可能消失或改版，镜像是全项目唯一证据基准，也是后续一切对拍的参照服。

**M1 — 逆向建坐标系**。加载 [references/reverse-engineering.md](references/reverse-engineering.md)。⛔ **第一个动作是判 bundle 形态**（扁平拼接 / 模块化打包 / 多 chunk），再选工具——分层表扫顶层声明，而 webpack 打包产物的顶层声明数是 **0**，边界与依赖边由打包器给定（用 `scripts/module-map.mjs`；实证：`references/case-studies/skill.md`「Workflow / Flow — M1」）。认不出容器时 FATAL，**禁止回退到分层表**（§0.5）。`scripts/beautify-bundle.mjs`（js-beautify 钉 1.15.1）展开 bundle 到 `_pretty/`，此后行号是全项目唯一溯源坐标系。先写 `docs/engine-notes.md`（模板：[assets/templates/engine-notes.md](assets/templates/engine-notes.md)）再写任何代码。技术栈从 bundle 取证钉死精确版本。数据驱动动画先 dump 数值账本。建立 `REBUILD_PLAN.md`（模板：[assets/templates/rebuild-plan.md](assets/templates/rebuild-plan.md)）。

**M2+ — 严格溯源移植**。加载 [references/porting-discipline.md](references/porting-discipline.md)，并按分支路由表加载对应场景指南。每个移植文件头部注明源行号区间；GLSL/魔数/数据逐字提取；数据资产脚本抽取入库不手抄。

**M(n-1) — 对拍验收**。加载 [references/verification-gates.md](references/verification-gates.md) 与 [references/determinism.md](references/determinism.md)；门红了或残差需要归类时再加载 [references/gate-failure-modes.md](references/gate-failure-modes.md)，不要开局读。全站渲染**广度**用 `scripts/sweep-routes.mjs`（全路由一个浏览器,逐路由 0 错误/0 失败/0 外联 + 交互钩子与逐路由采集）,单路由**深度**才用 `probe.mjs`——⛔ 不要手搓逐路由起 Chrome 的循环,成本按浏览器启动次数计,且并发探针会互相收割孤儿。⚠ **归因残差之前先建自比带宽**（`pixelcompare --self`，逐侧 ≥4 次、交错跑）——没有带宽的残差一律 UNCLASSIFIED，而 UNCLASSIFIED 是失败不是通过。门型选择：有 SSR/静态 HTML 产物先建字节门 → DOM 静态场景冻结熵源走 byte-equal → 活场景（WebGL/视频/随机相位）降级量化指标 + 噪声归类 → 数据驱动动画补数值探针门 → CLEAN 门全程兜底。判定时序 bug 前先校准探针（[references/environment-traps.md](references/environment-traps.md)）。

**M(n) — 收口**。冷头评审：对 bundle 顶层类/模块清单逐一核对落点（功能测试测不出整块遗漏，只有清单式核对能）。加载 [references/legal-and-deploy.md](references/legal-and-deploy.md) 完成版权**取证**并把决定**呈交用户**——在用户决定之前按安全默认执行（**私有 + noindex + 不部署**），公开前必须逐资产取证、显著标注非官方复刻。

**M(n+1) — 源码化**。加载 [references/readable-source.md](references/readable-source.md)。到 M(n) 为止产物**已证明正确但人读不了**（实证：`references/case-studies/skill.md`「Workflow / Flow — M(n+1)」）。本阶段把 `port/` 重写成 `src/`：拆模块 → 作用域安全地去混淆重命名 → 补分档注释 → 复制资产做到自包含。⛔ **拆分粒度不是自由选择**——扁平脚本的声明顺序即求值顺序，粒度由三条硬约束决定（互相引用 / 求值顺序 / import 绑定不可赋值），**先出划分方案让人过目，再切**；遇到巨型模块时**先测「延迟绑定少数末尾单例」的收益曲线再决定**（换模块系统要赔上整条工具链才换来同样粒度；实证：`references/case-studies/skill.md`「Workflow / Flow — M(n+1)」）。⭐ **"这件事做不到"这个判断极不可靠**（实证：`references/case-studies/skill.md`「Workflow / Flow — M(n+1)」）——先怀疑测量它的工具，再怀疑对象（`readable-source.md` §3.1–3.1.3）。⛔ **前置条件不可协商：必须先有全绿的门。** 没有裁判的重构是盲改；有了 `meanAbsDiff 0.00` 的裁判，每一步都能被证死——**这是重构能有的最好条件，也是它必须排在最后的原因**。现有门全部原样复用（目标换成 `src/` 构建产物，**容差不许放宽**），另加符号映射门与自包含门。⛔ 结构性重写（合并重复、提取公共函数、改算法）**默认禁止**——它会让门从"证明等价"退化为"没测出不等价"。⭐ **纪律 4 在本阶段依然有效**：你现在读得懂了，"这明显是个 bug"的冲动会比任何阶段都强，而它依然可能是行为本身。

⭐ **无容器 scope-hoisted 产物（Vite/esbuild,逐字分层交付的站）走另一条路：不重写,切**——拼接式分解（`scripts/census-bundles.mjs` 出 chunk 图与坐标 → `scripts/slice-esm.mjs` 按声明切成语义命名的部件,按序拼接逐字节等于原件 → `scripts/verify-reassembly.mjs` 一门定案,字节等价成立时全部运行时门的裁决免费转移）。执行侧不变,浏览器继续跑原 chunk。详见 `readable-source.md` §3.0.6。

### 分支路由表

Step 1 侦察结果决定加载哪些场景指南（按需，不要全量加载）：

| 侦察发现 | 加载 |
|---|---|
| Next.js App Router / RSC(`self.__next_f` flight 流)——C1 重构式逆向 | [references/rsc-reconstruction.md](references/rsc-reconstruction.md) |
| WebGL / Canvas 场景（three.js、自研引擎、GLSL） | [references/webgl-scenes.md](references/webgl-scenes.md) |
| GSAP / 烘焙动画数据 / CSS 变量动画 / 自研输入状态机 | [references/animation-recovery.md](references/animation-recovery.md) |
| 私有二进制格式（.buf / .sog / VAT / GLB 时间线 / .riv） | [references/binary-formats.md](references/binary-formats.md) |
| Shopify 店铺（指纹见 `cdn/shop`、`Shopify.theme`、`cdn.shopify.com`） | [references/shopify-platform.md](references/shopify-platform.md) |
| Sanity CMS（指纹见 `cdn.sanity.io/images/<projectId>/`、`*.api.sanity.io`、载荷里成片 `_key`/`_type`/`_ref`）——⛔ 判级看内容烘焙时点不看库名，且 `auto=format` 资产按 Accept 协商返回不同字节 | [references/sanity-platform.md](references/sanity-platform.md) |
| 门红了、或像素 / 数值残差需要归类（真差异 vs 方法学噪声） | [references/gate-failure-modes.md](references/gate-failure-modes.md) |
| 数值门 / 跨侧门 / 采集基线的用例设计；M(n) 清单式核对 | [references/gate-case-design.md](references/gate-case-design.md) |
| 内联序列化载荷（flight / `__NUXT__` / devalue 数据岛）或策略 A 外壳构建 | [references/payload-gates.md](references/payload-gates.md) |
| DOM 层策略选型（所有站必经；Webflow 导出 / 静态单页 / 框架 SSR 分支不同，另有"DOM 被 3D 引擎当坐标源读"的正交约束） | [references/dom-shell-strategies.md](references/dom-shell-strategies.md) |
| 大体量资产（百 MB 级媒体 / 授权字体） | [references/asset-management.md](references/asset-management.md) |
| 无头探测行为异常 / 疑似环境问题 | [references/environment-traps.md](references/environment-traps.md) |

### Step Summary

| 阶段 | 关键动作 | 阻塞门验收 | 产出物 |
|---|---|---|---|
| Step 0 | 指纹探测判级 | 判级明确且已告知用户 | 判级结论与依据 |
| Step 1 | 证否 + 评级 + 确认范围 | 用户确认 | 难度评级表、范围共识 |
| M0/M0.5 | 镜像 + 账本 + 断网跑通 | **`verify-mirror` 五项全绿**；GAP=0；零 404/零错误/零外联 | `mirror/`（只读）、manifest、`serve.mjs` 参照服 |
| M1 | 展开 bundle、逆向笔记、钉栈 | engine-notes 完成；版本钉死表完成 | `_pretty/`、`docs/engine-notes.md`、`REBUILD_PLAN.md` |
| M2+ | 溯源移植、里程碑成对提交 | 每里程碑冷启动实测 + CLEAN 门绿 | 带行号注释的源码、三张登记表滚动更新 |
| M(n-1) | 对拍验收 | 所选门型全绿或差异全部登记 | 验证脚本 + 对拍产物入库（`docs/compare/`） |
| M(n) | 冷头评审 + 版权取证 + 呈交用户 | 清单对账零缺口；用户已作出部署决定（未决则维持安全默认） | 审计记录、DEPLOY.md |
| M(n+1) | 拆模块 + 去混淆 + 注释 + 自包含 | 现有门全绿且**容差未放宽**；符号门双向单射零孤儿；自包含门（复制出去、断网、构建）过 | `src/`（可读工程）、`docs/rename-map.json`、`src/README.md` |

## Script Directory

Node 22+，路径相对本 skill 目录。每个脚本都认 `--help`（打印头注用法 + 旗标清单）与 `--version`（skill 版本），**未知旗标一律 FATAL**（`lib/cli.mjs`）。本表只列一句话用途；每个脚本的完整说明、旗标、实证与成熟度见 [scripts/README.md](scripts/README.md) 与 [tools/README.md](tools/README.md)（含自本表迁出的速查表）。

⭐⭐ **依赖纪律是按阶段划的，不是按目录划的：源码化之前，整条流水线零依赖。**

Step 0 → M(n) 全程不装任何东西；**复刻项目要到 M(n+1) 才获得 devDependencies**（作用域安全的重命名需要真正的 parser）。`scripts/`（零依赖）与 `tools/`（允许 devDeps）只是这条阶段线在目录上的投影——**判据住 `scripts/`，源码化阶段的重构器住 `tools/`**。

⛔ **任何门不许 import 任何工具**（`verification-gates.md` §2.1.2）——检查者不能是生产者。

⭐ **前面的阶段需要真正的 parser 怎么办？外挂，不要 import。** `beautify-bundle.mjs`（js-beautify）与 `module-map.mjs`（acorn）都是 `spawn` 一个**钉死版本的 npx**，脚本自身仍然零依赖、仍然可独立审查。⛔ **不要改成手写词法器**（实证：`references/case-studies/skill.md`「Script Directory」）。**token 流上的括号匹配是精确的，文本上的括号匹配是对字符串/正则/注释的猜测。**

⚠ 这条线是**被违反之后才被发现的**（实证：`references/case-studies/skill.md`「Script Directory」）。**一条只写在文档里、没有任何东西去查的规矩，会安静地失效。**

| 脚本 | 用途 | 使用阶段 |
|---|---|---|
| `scripts/fingerprint.mjs` | Step 0 探测协议的零依赖等价实现：存活 / 重定向终点 / 双抓 diff / 技术指纹 / bundle 初检 + Sanity 证据采集（只采证据，不出判级） | Step 0 |
| `scripts/mirror-site.mjs` | BFS 爬虫镜像：资产白名单、`redirect:manual`、三本账（含 sha256）跨运行累积、off-host 普查；`--scope` 只限页面不限资产 | M0 第一遍 |
| `scripts/netcapture.mjs` | 真实浏览器 CDP 抓包，对账补录运行时资源（CDN 站必须传 `--hosts`） | M0 第二遍 |
| `scripts/verify-mirror.mjs` | 镜像自己的门：映射单射 / 账本 sha256 / 真实性（魔数 + 挑战页）/ 闭包 / 抽样回源，跑在断网门之前 | M0 关账前 |
| `scripts/gapfill-video.mjs` | HLS/DASH 流媒体阶梯补录（master → rendition → 分片） | M0（有流媒体时） |
| `scripts/reconcile-gaps.mjs` | 运行时缺口对账：netcapture 的 GAP 行 + 字节推导全集逐条补进镜像；请求头梯子 + 浏览器同款图片 Accept | M0（运行时资源多的站） |
| `scripts/wayback-mirror.mjs` | X 类抢救：从 CDX 按锚点 + 时间窗选一个连贯时刻，以 `id_` 原始字节抓成标准镜像，洞登记 `wayback-holes.txt` | M0（X 类） |
| `scripts/serve.mjs` | 零依赖静态服务器兼参照服：MIME / Range / 服务层改写 / 重定向回放；`--fallback-root` 回落链、`--stub-ext-hosts` 桩、`--rewrite` 登记式替换；未知旗标响亮失败 | M0.5 起全程 |
| `scripts/probe.mjs` | CDP 无头探针：console / 异常 / 网络 CLEAN 判定进 CI，`--no-external` 零外联，`--walk` 全滚动走查 | M0.5 起每 commit |
| `scripts/sweep-routes.mjs` | 渲染广度门：全路由一个浏览器，逐路由 0 错误 / 0 失败 / 0 外联 + 交互钩子；不要手搓逐路由起 Chrome | M0.5 起（多路由站） |
| `scripts/verify-offline.mjs` | 零外联门的静态一半：枚举产出里每个外部绝对 URL 并逐条裁决 | M0.5 起每 commit |
| `scripts/verify-payload.mjs` | SSG payload 门：内联序列化数据块（Nuxt / flight）求值展开后按结构对拍 | M0.5 起（有 SSG payload 时） |
| `scripts/verify-nextdata.mjs` | pages router 载荷门：`__NEXT_DATA__` 与 `/_next/data/*.json` 单侧自洽 + 双侧深比较 | M0.5 起（pages router 站） |
| `scripts/verify-lenprefix.mjs` | 自带长度的载荷门：flight 流逐行按 `T<hex>` 字节数前进，改写后落点仍须是行首 | M0.5 起（有 flight 载荷时） |
| `scripts/flight-decode.mjs` | C1 坐标系：把每页 flight 流解成模块引用表 / 预载 / 元素树 / JSX outline | M1（C1） |
| `scripts/beautify-bundle.mjs` | js-beautify@1.15.1 钉死展开 bundle 到 `_pretty/`，排版后 token 流自查，撞名断言 | M1 |
| `scripts/module-map.mjs` | 模块化 bundle 的分层表（spawn 钉死 acorn）：认 webpack 容器与 Turbopack 扁平列表，认不出即 FATAL，覆盖率守卫 | M1（模块化打包产物） |
| `scripts/census-bundles.mjs` | 无容器产物的 chunk 级坐标账本（sha256 / 行数 / ESM 边），拼接式分解的第一步 | M1（scope-hoisted 产物） |
| `scripts/dump-timelines.mjs` | GLB 动画曲线 dump 成 JSON 数值账本 | M1（数据驱动动画时） |
| `scripts/closure.mjs` | 从种子模块算传递依赖闭包，竖切边界的唯一依据；未知种子 FATAL + did-you-mean | M2+（模块化打包产物） |
| `scripts/slice-modules.mjs` | 按模块 id 逐字切片，容器外字节（前奏 / 尾注）逐字带走，`--check` 重切须字节一致 | M2+（模块化打包产物） |
| `scripts/extract-source.mjs` | 字节切片器：按钉死行号区间切 `_pretty/` 拼成生成文件，sha256 守卫 + `--check` | M2+（逐字移植期） |
| `scripts/emit-webpack-chunk.mjs` | 多 chunk webpack 站的逐字再发射：按 module-map 边界切成部件再按源站容器形态拼回，`--check` 逐字节 | M2+（webpack 多 chunk 站） |
| `scripts/slice-esm.mjs` | 拼接式分解切片器：按声明把 ESM chunk 切成语义命名部件，按序拼接逐字节等于原件 | M2+ / M(n+1)（scope-hoisted 产物） |
| `scripts/verify-reassembly.mjs` | 重拼门：逐部件 sha + 按序拼接 sha + `--against` 对活原件三重比对 | M2+ / M(n+1)（scope-hoisted 产物） |
| `scripts/build-site.mjs` | 策略 A 构建层：按 `shell-config.mjs` 变换表从镜像生成 `site/`，逐条命中下限 + `--check` | M2+（策略 A） |
| `scripts/verify-shell.mjs` | 外壳字节门：逐文档 patience diff，每个差异块须能被变换表重放解释（不 import 构建器） | M2+（策略 A） |
| `scripts/verify-tokens.mjs` | token 流等价门：排版 / 再发射件 ≟ 源站原件逐 token 相等；凡以 `_pretty` 字节交付必跑 | M2+（排版字节交付时每 commit） |
| `scripts/verify-refs-served.mjs` | 引用可达门：产出字节里每条资源引用逐条问服务器（不再实现一遍解析） | M2+ 起每 commit |
| `scripts/verify-routes.mjs` | 路由 / 重定向 / 状态码契约门 | M2+ |
| `scripts/verify-ssr.mjs` | SSR / DOM 逐字节门 | M2+（有 SSR 产物时最先建） |
| `scripts/verify-tween.mjs` | 竖切的数值门：同一关键帧规格喂两侧，逐点比补间值与缓动曲线 | M2+（有补间 / 时间轴引擎时） |
| `scripts/harvest-cases.mjs` | 从源站活引擎采用例（`harvest.config.mjs`），只产出 A 侧 | M2+（源站引擎可达时） |
| `scripts/verify-harvest.mjs` | 采集基线的 B 侧：每条身份在移植侧恰好匹配一个，按行为把名字找回来 | M2+（有采集基线时） |
| `scripts/verify-crossside.mjs` | 跨侧门：同一份输入串行喂镜像与移植逐条比（`crossside.config.mjs`），URL 相同直接 FATAL | M2+（源站有可直接调用的接缝时） |
| `scripts/pixelcompare.mjs` | 量化像素对拍：自比带宽 `--self`、状态对齐 `--ready / --after-ready / --chunk`、到达等待 `--hold*`、`--freeze-css`；非空帧前置条件；大视口用 jpeg | M(n-1) |
| `scripts/pixel-walk.mjs` | 检查点巡航：N 个滚动位置各跑一次像素门，滚两次、重复帧逐格报出，先 `--self` 测带宽 | M(n-1) |
| `scripts/side-by-side.mjs` | 双侧截图并排合成图（对拍产物留证） | M(n-1) |
| `scripts/frame-census.mjs` | 截图普查：颜色数与主色占比，证明帧里有东西 | M(n-1) |
| `scripts/probe-shim.js` | 确定性驱动 shim：接管 rAF / timer / 时钟 / `Math.random` / IntersectionObserver，手动泵到任意 t，双侧同位注入 | M(n-1) |
| `scripts/verify-flight.mjs` | C1 语义门：构建产物 flight 树 ≟ 镜像 flight 树，模块 id 全局双射，自带解析器 | M(n-1)（C1） |
| `scripts/cold-audit-modules.mjs` | M(n) 冷头清点（模块化产物）：逐模块对账 + 计算型 require 扫描，必须报 `n/N examined` | M(n)（模块化打包产物） |
| `scripts/cold-audit-decls.mjs` | M(n) 冷头点名（扁平产物）：深度 0 声明逐条判 cited / override / named / UNKNOWN | M(n)（扁平产物） |
| `scripts/verify-module-map.mjs` | M(n+1) 等价门（模块化产物）：一模块一文件且与打包器字节 token 级一致 | M(n+1)（模块化打包产物） |
| `scripts/verify-symbols.mjs` | 符号映射门：`port/` 每个顶层声明在 `src/` 有且仅有一个对应（读 `rename-map.json`） | M(n+1)（扁平产物） |
| `scripts/verify-fresh.mjs` | 新鲜度门：`src/` → `dist/` → `site/` 是否同步；时间戳不是判据 | M(n+1)（有构建步骤时每次） |
| `scripts/verify-standalone.mjs` | 自包含门：`src/` 复制到临时目录 → 断网 → 安装 → 构建 → CLEAN 与零外联 | M(n+1) |
| `scripts/verify-zerodep.mjs` | 依赖分界门：`scripts/` 只许 node: / 相对 import，且没有门 import `tools/` | 每次新增脚本 |
| `scripts/lib/urlpath.mjs` | 唯一的 url → 本地路径映射（查询感知），爬虫 / 抓包 / 服务 / 门四方共用 | lib |
| `scripts/lib/extract-refs.mjs` | 唯一的资产引用提取器（五种写法 × 原文 / 解码两遍），爬虫与闭包门共用 | lib |
| `scripts/lib/negotiate.mjs` | 内容协商 Accept 策略（浏览器同款图片 Accept）+ Sanity 证据提取 | lib |
| `scripts/lib/ports.mjs` | 端口分配与实例身份（`21000 + slot×1000 + lane×10 + side`），占用即响亮失败 | lib |
| `scripts/lib/chrome.mjs` | 无头浏览器生命周期：进程组收割 + 孤儿自检 + CDP 载荷硬顶常量 | lib |
| `scripts/lib/png.mjs` | 零依赖 PNG 编解码 | lib |
| `scripts/lib/tokens.mjs` | token 流读法（acorn 钉死 spawn）+ 首分歧定位 | lib |
| `scripts/lib/cli.mjs` | 唯一的 argv 合同：`--help` / `--version` / 未知旗标 FATAL，`EXIT` 退出码表 | lib |
| `scripts/lib/hash.mjs` | 唯一的 sha256 拼写（字符串 / Buffer / 流式文件） | lib |
| `scripts/lib/ledger.mjs` | 镜像三本账（manifest / inventory / redirects）的唯一读写实现 + `LEDGER_FILES` | lib |
| `scripts/lib/cdp.mjs` | 唯一的 CDP 客户端：逐调用超时、断连响亮失败、事件订阅 | lib |
| `tools/name-modules.mjs` | 模块提名：按 0–4 级证据给内容哈希 id 起名并记依据，无证据保留 id | M(n+1)（模块化打包产物） |
| `tools/accept-names.mjs` | 命名的接受步：默认只接受 tier-1（打包器声明的导出名），其余保留 id | M(n+1) |
| `tools/modules-to-src.mjs` | 按接受后的命名逐模块生成 `src/modules/`（作用域安全的重命名器） | M(n+1)（模块化打包产物） |
| `tools/sourcify-chunk.mjs` | 多 chunk 站的 M(n+1) 驱动：逐 chunk 跑 name-modules → accept-names → modules-to-src → verify-module-map | M(n+1)（多 chunk 站） |
| `tools/group-parts.mjs` | 把 slice-esm 部件按域折进目录（只按 classy 证据分组） | M(n+1)（scope-hoisted 产物） |
| `tools/make-standalone.mjs` | 交付物生成：按账本复制资产、生成 package.json / verify-bytes；`--mirror a,b` 回落链 | M(n+1) |
| `tools/flight-to-mdx.mjs` | 从 flight 树反推 MDX / 页面骨架 | M2+（C1 重构工程） |
| `tools/assemble-static.mjs` | 把 `next build` 产物摊成静态树供 serve.mjs 伺服（像素门两侧同经 serve） | M(n-1)（C1 重构工程） |
| `tools/harvest-optimized-images.mjs` | next/image 优化器产物补齐（镜像字节优先，本机优化器兜底） | M(n-1)（C1 重构工程） |
| `tools/verify-fresh-next.mjs` | verify-fresh 的 Next 形态：src → `next build` → assemble-static 链重建比字节（前提 `generateBuildId` 钉死） | M(n+1)（C1 重构工程） |

## 复刻工程目录结构

三个阶段性产物，**单向依赖，读作「证据 → 移植 → 源码」**：

```
<site>-rebuild/
├── mirror/               # ① 只读证据：源站 URL 空间的字节级还原。永不修改
│   └── _pretty/          #    beautify 展开产物 + 再生成说明 README
├── port/                 # ② 逐字移植：机器读，extract-source --check 守着字节一致。永不手改
│   └── _gen/             #    切片器产物（行号头指回 mirror/_pretty/）
├── src/                  # ③ 人写的工程：可读、可改、自包含（复制到任何地方都能跑）
│   ├── package.json      #    ⛔ 自己的 package.json——自包含门要把它复制出去单独跑
│   ├── assets/           #    资产在这里（③ 阶段必须复制，见 readable-source.md §2）
│   └── README.md         #    怎么跑 / 坐标系怎么读 / 哪些注释是我们写的
├── docs/
│   ├── engine-notes.md   # 逆向笔记（事实/怪癖/复刻结论三段式）
│   ├── rename-map.json
