| name | website-rebuild |
| description | 1:1 rebuild of award-winning creative websites (WebGL / scroll-animation / portfolio sites). Evidence-driven pipeline - mirror-first forensics, line-number-traceable reverse engineering of minified bundles, verbatim porting, quantitative verification gates. Use when user asks to "复刻网站", "重建网站", "1:1 rebuild", "clone this site", or provides a URL of a creative/award site to reproduce. |
| compatibility | Requires Node 22+ (bundled scripts use built-in WebSocket to talk to CDP), npx, and a local Chrome/Chromium for headless comparison. POSIX shell optional - the Step 0 probe protocol has a zero-dependency Node equivalent (scripts/fingerprint.mjs) for shells without curl/cmp/tr/perl (e.g. Windows PowerShell). Agent-agnostic - works in any Agent Skills-compatible runtime. |
| metadata | {"version":"0.3.6"} |
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 §0.3。
- 不触碰受保护边界:不采集需要登录态、付费墙或授权才能访问的内容;本 skill 只处理匿名可公开访问的资源。若目标站明确禁止此类复制,停止并告知用户——何为"明确禁止"见
legal-and-deploy.md §0.3.6 写死的四条门槛,其余一切不确定性走呈交不走停工。
- 产出默认私有:默认 noindex、不公开部署。任何公开前必须完成逐资产版权取证,并显著标注"非官方复刻"与原作者归属(见 references/legal-and-deploy.md)。
⛔ 法务判断归用户,skill 只取证与呈现(三条,全程有效):
- 决定权在用户:skill 收集事实(逐资产归属、许可状态、第三方权利人、源站是否仍在营业、产物内第三方标识符)、列出选项与各自的风险边界、给出建议与理由;凡涉及"能不能公开 / 部署 / 再分发 / 对外展示",必须用下文「User Input Tools」显式交回用户,不许 agent 自行下法律结论后继续往下走。
- 未获用户明确决定前按安全默认执行:私有仓库 +
noindex + 不公开部署 + 不再分发。写给用户时说明这是默认动作("在你决定之前我不会把它发出去"),不是 agent 已作出的法务结论——两者责任归属完全不同。agent 只能往保守侧执行默认,往公开侧走必须有用户的明确决定。
- ⛔ 法务考量不得削减镜像完整性或门的覆盖面:镜像是证据基座,完整性是技术不变量(四遍法、闭包门、GAP=0 全建立在它之上)。不抓只能有技术性理由(不是文件 / 服务端不提供 / 需授权或登录态 / 源站明令禁止),一律登记;不得以"反正不公开""不该多存一份"这类法务理由留洞。实证:某项目以"产出永不公开"为由对一类资产"登记、不补抓",缺了约 60% 的资产而五道门始终全绿,藏了四个里程碑【objectarchive】。法务决定作用于产出怎么被使用,不是证据基座是否完整。
适用范围 ⛔ 必读
主场(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 全局双射)。实测 rauchg.com(Next 16/Turbopack):18/18 路由语义一致,盲逆向对答案结构 ≈95%/行为 ≈98%。⚠ C1 的 L2/L3 合并——第一份产物就是「人写的源码 + 门证明的等价」。全流程见 references/rsc-reconstruction.md。
- C2(可做,按 A 类跑):⭐ 写法是声明式但源码下发(R3F / Theatre / Vue SFC 编译产物)。实测一个 R3F 站:
useFrame 回调里就是 MathUtils.damp(x, y, 7, t) 这样的普通命令式代码,逐字切片 18 个模块换进页面后 CLEAN、8 个 canvas 齐全、跨侧 99.5%。切片器不关心范式——它切的是字节。 渲染器当平台层从镜像伺服。⛔ 判别器不是库名,是「客户端是否持有行为源」(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)。⭐ 抢救产出是标准镜像——X 类可走完 L3 全程(实测 first-launch:策略 A 外壳 + 数值门 9,856 样本全等 + 像素带宽内 + 自包含门,无一道门需改语义)。⛔ "CDX 无覆盖才是真不可做"按资产层读,不按站读:IA 爬虫不执行 JS,清单/拼接驱动的站可以代码层覆盖 100% 而画面层为零(实测 157/160 资产任何年代零捕获,断网即白屏)——Step 0 先做分层覆盖侦察(推导 + CDX 前缀查询)预判抢救深度,见 archival-rescue.md §1.9。历年获奖站实测消失率约 29%——这也是"第一时间镜像"是本 skill 第一纪律的原因。
判级由 Step 0 指纹侦察决定,完整判定树见 references/scope-and-fingerprint.md。拒绝时要解释原因并说明该站属于哪一类,不要硬跑。
User Input Tools
需要向用户提问时(确认范围、法务决定、外部依赖决策):优先使用当前运行时的内置提问工具(如 AskUserQuestion);没有则输出编号问题清单让用户回复编号。支持多问合并时一次问完。法务类提问按 legal-and-deploy.md §0.1 的五段式写:事实 / 查不清的 / 选项 / 每个选项的风险边界 / 建议与当前默认动作。
宪法(六条纪律,全程有效)
以下六条在六个源项目中被称为"宪法级",违反任何一条都会在后续阶段以 bug 形式偿还:
- 镜像神圣不可污染:
mirror/ 磁盘文件永不修改;一切本地化适配(CDN 改写、外链 stub)在服务层响应时动态完成。
- 源站代码是唯一裁决,不凭观感修:每个改动先在 bundle/CSS/镜像 HTML 里找到归属行号再落地。Do not tune visuals, motion, or interaction by eye.
- 源站有的都要有,源站没有的不做:不自创补偿性 CSS/JS。宁可先不像,也不要发明规则——自创补丁会在机制对齐后反转成 bug。
- bug / 死代码 / 怪写法照抄不修:压缩代码里的每个怪写法都可能是行为本身。"好心修正" no-op bug 曾导致转场崩溃(实证见 porting-discipline.md)。
- 有意偏差必须登记:写清"源站怎么做 / 我们怎么做 / 为什么 / 什么条件下重新考虑"。没登记的差异一律视为 bug。
- 代码与文档同一次提交:每个里程碑成对提交(
Port xxx + Update rebuild plan: xxx),日志固定含产出 / 验收 / 教训 / 下一步断点(带行号)。
⭐ 纪律 3 在 M(n+1) 的边界:src/ 是显式登记的衍生物,不是对源站的断言,所以在 src/ 里重命名、拆模块、写注释不算"发明"——纪律 3 约束的是"为了让它看起来像而自创行为",不是"让已证明等价的代码变得可读"。但两条硬边界不动:① 结构性重写默认禁止(合并重复、提取公共函数、改算法——它们让等价不可判定);② 注释里的推测必须标注为推测,不许把逆向笔记里的猜测写成陈述句。port/ 与 mirror/ 仍然一个字节都不许动。详见 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 源码化 终点
⛔ = 阻塞门:验收标准未达成不得进入下一阶段。
Flow
Step 0 — 指纹侦察与范围门。加载 references/scope-and-fingerprint.md,对用户给的 URL 执行探测协议(GET 到路径粒度、最终 URL 同一性、双抓 diff、物种/年代校验、bundle 初检),输出判级与依据。A/B 类继续;C/D/X 类向用户解释后停止或引导。
Step 1 — 开工评级。加载 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 交接,那是他的工程,skill 到"人能读懂的真实"为止。
M0 / M0.5 — 镜像取证。加载 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。⛔ 第一个动作是判 bundle 形态(扁平拼接 / 模块化打包 / 多 chunk),再选工具——分层表扫顶层声明,而 webpack 打包产物的顶层声明数是 0,边界与依赖边由打包器给定(实测 24,378 行 → 569 个现成模块,用 scripts/module-map.mjs)。认不出容器时 FATAL,禁止回退到分层表(§0.5)。scripts/beautify-bundle.mjs(js-beautify 钉 1.15.1)展开 bundle 到 _pretty/,此后行号是全项目唯一溯源坐标系。先写 docs/engine-notes.md(模板:assets/templates/engine-notes.md)再写任何代码。技术栈从 bundle 取证钉死精确版本。数据驱动动画先 dump 数值账本。建立 REBUILD_PLAN.md(模板:assets/templates/rebuild-plan.md)。
M2+ — 严格溯源移植。加载 references/porting-discipline.md,并按分支路由表加载对应场景指南。每个移植文件头部注明源行号区间;GLSL/魔数/数据逐字提取;数据资产脚本抽取入库不手抄。
M(n-1) — 对拍验收。加载 references/verification-gates.md 与 references/determinism.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)。
M(n) — 收口。冷头评审:对 bundle 顶层类/模块清单逐一核对落点(功能测试测不出整块遗漏,只有清单式核对能)。加载 references/legal-and-deploy.md 完成版权取证并把决定呈交用户——在用户决定之前按安全默认执行(私有 + noindex + 不部署),公开前必须逐资产取证、显著标注非官方复刻。
M(n+1) — 源码化。加载 references/readable-source.md。到 M(n) 为止产物已证明正确但人读不了(实测:14,271 行挤在一个文件里,e 出现 2962 次,注释占 0.2%)。本阶段把 port/ 重写成 src/:拆模块 → 作用域安全地去混淆重命名 → 补分档注释 → 复制资产做到自包含。⛔ 拆分粒度不是自由选择——扁平脚本的声明顺序即求值顺序,粒度由三条硬约束决定(互相引用 / 求值顺序 / import 绑定不可赋值),先出划分方案让人过目,再切;遇到巨型模块时先测「延迟绑定少数末尾单例」的收益曲线再决定(实测 6 个绑定即从 11,246 行降到 1,013 行,而换模块系统要赔上整条工具链才换来同样粒度)。⭐ "这件事做不到"这个判断极不可靠——实测两次判为结构性不可能,两次真凶都是自己工具里的一行 bug;先怀疑测量它的工具,再怀疑对象(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 侦察结果决定加载哪些场景指南(按需,不要全量加载):
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 目录。用法与成熟度详见 scripts/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,脚本自身仍然零依赖、仍然可独立审查。⛔ 不要改成手写词法器——本 skill 里试过,一个含引号的正则字面量把它带偏了 16,177 行(F27)。token 流上的括号匹配是精确的,文本上的括号匹配是对字符串/正则/注释的猜测。
⚠ 这条线是被违反之后才被发现的:module-map.mjs 依赖 @babel/*,却在 scripts/ 里住了整整八个版本,而同一份纪律的原话就写在它上面三行。一条只写在文档里、没有任何东西去查的规矩,会安静地失效。
| 脚本 | 用途 | 使用阶段 |
|---|
scripts/fingerprint.mjs | Step 0 六步探测协议的跨平台等价实现(GET 存活 + 重定向链与终点域同一性、双抓 diff、物种/年代、HTML 技术指纹、bundle 初检;出现次数计数与 <1KB Referer 重试内置)。只采证据不出判级——判级仍走 scope-and-fingerprint.md §3 判定树 | Step 0(无 POSIX 工具链时) |
scripts/mirror-site.mjs | BFS 爬虫镜像(资产白名单 + 迭代到不动点;redirect:manual + 三本账,含逐文件 sha256)。--scope <前缀> 把页面队列限制在目标路径下(微站挂在企业 CMS 域下时必用;⛔ 只限页面不限资产)。账本累积(--seeds 补漏不再截短上一轮的行)+ off-host 普查(不跟的主机逐个计数并告警——静默丢弃曾让 827 条媒体引用消失而报告写着"57 files saved") | M0 第一遍 |
scripts/netcapture.mjs | 真实浏览器 CDP 抓包对账补录运行时资源(CDN 站必须传 --hosts,否则只观测同源流量、会报假 GAP=0) | M0 第二遍 |
scripts/verify-mirror.mjs | 镜像自己的门,跑在断网门之前。五项断言:映射单射性 / 账本与磁盘 sha256 / 真实性(挑战页正文 + 声明类型对魔数——一个 200 不是"你拿到了那个资源"的证据) / 闭包 / 可选抽样回源。下游所有门问的都是"渲染得出来吗",错的镜像能让它们全绿 | M0 关账前,每次重抓镜像后 |
scripts/gapfill-video.mjs | HLS/DASH 流媒体阶梯补录(master → rendition → 分片),静态爬虫的结构性盲区 | M0(有流媒体时) |
scripts/reconcile-gaps.mjs | 运行时缺口对账器:把 netcapture 记下的 GAP 行与字节推导的全集清单(如 next/image 的 srcset 阶梯穷举——实测 1,078 vs 浏览器碰到 217)逐条补进镜像。⭐ 请求头梯子(标准 profile 4xx → 裸 profile 重试:同一个 403 有两种相反的药,landonorris 要 Referer、video.twimg 恨 Referer)+ 逐 URL 容错 + 分批记账(一次崩溃不留账外文件) | M0(运行时资源多的站) |
scripts/flight-decode.mjs | C1 的坐标系:把每页 self.__next_f.push 流解成模块引用表(I 行导出名=白送的 tier-1 命名证据)、HL 预载、已解引用的元素树 + JSX 式 outline。T 行按声明字节数走;:HL 空 id 行不许断链 | M1(C1) |
scripts/verify-flight.mjs | C1 语义门:构建产物 flight 树 ≟ 镜像 flight 树。自带解析器(⛔ 不 import flight-decode——检查者不能是生产者);规范化只收「证明不携带行为」的构建哈希命名空间(chunk 名/css-module 类/媒体哈希/可提升资源挂载点/编码自由度),模块 id 做全局双射(一对多即红);站点登记项走 --normalize-props(ISR 纪元字段)与 --normalize-class(库渲染子树);其余一切差异照红 | M(n-1)(C1) |
scripts/serve.mjs | 零依赖静态服务器(MIME/Range/服务层改写/重定向回放),兼任源站参照服。 是,为的是一类本地化触及不到的东西——(,镜像不在那个域名上于是整个子系统走空路径);,因为沉默与生效此前无法区分。 让复刻侧只放产出、资产全部从只读镜像读( 的不复制策略);——被静默忽略的旗标是一次没人知道的降级 |
复刻工程目录结构
三个阶段性产物,单向依赖,读作「证据 → 移植 → 源码」:
<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 # ③ 阶段符号映射(port 位置 → 旧名 → 新名 → 依据档位)
│ └── compare/ # 对拍产物留证
├── REBUILD_PLAN.md # §0 纪律 / 阶段计划 / §6 偏差表 / §Q 怪癖表 / §7 里程碑日志
├── mirror-manifest.json # 镜像账本(sha256 逐文件)
├── scripts/ # 判据与前置工序:零依赖,从本 skill 拷入
└── tools/ # 重构器:③ 阶段专用,允许 devDependencies(见下)
⛔ src/ 里发现行为不对,答案在 port/ 或 mirror/,不在 src/。 就地"改到对"会把移植 bug 变成无法追溯的本地补丁,而且门会变绿——这是纪律 2 在三段坐标系下的形式。port/ 在 src/ 建成后不删除,它是等价性的另一端。
⭐ 依赖分界按阶段:源码化之前零依赖——项目到 M(n+1) 才有 devDependencies。scripts/(判据与前置工序)零依赖,必要时 spawn 钉死版本的 npx;tools/(源码化重构器)允许 devDependencies。任何门不许 import 任何重构器。由 scripts/verify-zerodep.mjs 守。
References
按需加载(Step 0/1 与分支路由表决定),不要开局全量读入:
Notes
- 版权红线:本 skill 用于学习目的的复刻。产出默认私有 + noindex(安全默认,不是法务结论);公开部署前必须完成逐资产版权取证、把决定交回用户、并显著标注非官方复刻与原作者归属。最大风险是法务不是技术——但法务判断由用户作出,且永不用于削减镜像完整性或门的覆盖面。
- 工期预期:方法论成熟形态下,单页创意站 1-3 天(数十个 commit);多场景 WebGL 作品集站按周计。向用户给预估时参考 Step 1 的难度评级。
- 对拍失败先怀疑环境:后台节流、HMR 幽灵模块、探针时钟、headless 字体缺失都会伪装成代码 bug。判定源码问题前先过 environment-traps.md 的校准清单。
- 遇到本 skill 未覆盖的场景(B 类缺口),明确告诉用户"这一段没有既成指南,按通用纪律推进",并把新经验记入项目文档——它们是 skill 下一版的输入。