t1k:cocos:base:migrate
| Field | Value |
|---|---|
| Module | base |
| Version | 3.3.2 |
| Effort | high |
| Tools | — |
Keywords: atomic, idempotent, js2ts, manifest, orchestrator, pipeline, rollback
How to invoke
Section titled “How to invoke”/t1k:cocos:base:migrateWhen to use
Section titled “When to use”Khi muốn chạy CẢ pipeline JS->TS cho nhiều file/1 scene bằng 1 lệnh, thay vì gọi tay từng stage. Orchestrator MỎNG: chỉ điều phối + closure + topo-sort + gate + manifest, mọi logic nằm ở skill stage.
Pipeline 5 pha: dep-graph + 4 .d.ts (Phase0) → js2ts (Phase1) → tsc-validate (Phase2) → uuid-verify gen-meta+attach (Phase3, editor ĐÓNG) → uuid-verify verify=editor-compile-verify (Phase4).
Cách hoạt động — 5 PHA ĐỒNG BỘ (atomic theo closure)
Section titled “Cách hoạt động — 5 PHA ĐỒNG BỘ (atomic theo closure)”Khác bản cũ (1 vòng for trộn gate + side-effect mỗi file): tách thành các pha; pha side-effect (Phase3) CHỈ chạy khi pha validate (Phase2) xanh toàn bộ closure. Sai thì sai đồng bộ (STOP cả batch, prefab chưa đụng — sửa rule 1 chỗ, áp lại); đúng thì đúng đồng bộ (attach cả closure).
- Resolve target:
--scene <path>(mọi component custom scene tham chiếu) HOẶC danh sách<file.js>. - Closure = extends + require transitive (internal): base class + mọi require-dep được thêm để convert TRƯỚC (tsc-validate cần dep là module
.cvmới type-check sạch; gate attach cần @property inherited). Topo-sort base+require-first. - Phase 0 PRECONDITION (smart-refresh hash-gated): dep-graph + 4
.d.tsCHỈ regenerate khi nguồn đổi (hoặc--force-refresh). Stamp hash vào manifest. - Phase 1 CONVERT (js2ts cả closure). GATE 1 (100% convert) + GATE dependency-holdout (§ Gotcha 6): holdout CÓ consumer trong closure → STOP NGAY Phase 1 (KHÔNG bypass).
- Phase 2 VALIDATE (tsc-validate cả closure, 1 lượt filter-arg). GATE 2: 0 SYNTAX (TS1xxx) → else STOP (chưa attach gì). [dry-run] write-real
.cv.ts→ validate → cleanup. - Phase 3 ATTACH (chỉ
--write+--editor-closed): gen-meta single-writer cả closure → attach re-point CHỈ nhóm A. GATE 3: @property completeness → fail → STOP + ROLLBACK. - Phase 4 VERIFY: mở editor lại → dangling + isPlugin + editor-compile-verify.
Trạng thái mỗi file lưu ở manifest tmp/migrate-state.json (SSOT): file “current” (mọi hash khớp) → skip; “stale” → redo. Idempotent: re-run --write cho kết quả y hệt (uuid đã persist). --resync ép coi mọi file stale → reprocess đồng loạt.
Định tuyến nhóm file A/B/C (DATA-driven theo registry)
Section titled “Định tuyến nhóm file A/B/C (DATA-driven theo registry)”| Nhóm | Điều kiện | gen-meta | attach (re-point prefab) |
|---|---|---|---|
| A Component CÓ prefab-ref | isComponent && uuid trong prefab/scene | ✅ | ✅ (blast-radius DUY NHẤT) |
| B Component KHÔNG prefab-ref | isComponent && 0 ref (logic/base/runtime-add) | ✅ | ❌ n/a |
| C Non-component | !isComponent (object/class/global/ES) | ✅ | ❌ n/a |
- gen-meta CHO MỌI nhóm — non-component vẫn cần
.cv.ts.metađể file TS khácrequire/importresolve runtime. Không attach ≠ không gen-meta. - attach CHỈ nhóm A = phần DUY NHẤT sửa prefab. B/C revert = chỉ xoá
.cv.ts/.meta. - single-writer/editor-đóng áp MỌI nhóm (gen-meta là một lần GHI single-writer).
6 chế độ gọi lệnh (plan mặc định / dry-run / thực thi / full-434 liền mạch / 2-pha / rollback) và
toàn bộ flag (--all, --editor-closed, --no-attach, --allow-holdout, --resync,
--force-refresh, --rollback, …): references/usage-examples.md. --editor-closed BẮT
BUỘC trước Phase 3 --write (single-writer uuid — editor mở lúc attach → 2 writer → uuid
khác/mất đồng bộ) — chi tiết: t1k-cocos-base-uuid-verify gotcha 10.
Config — .claude/cocos-migrate.json (SSOT đường dẫn, KHÔNG hardcode)
Section titled “Config — .claude/cocos-migrate.json (SSOT đường dẫn, KHÔNG hardcode)”Mọi đường dẫn project lấy từ .claude/cocos-migrate.json (dùng chung cho t1k-cocos-base-uuid-verify + t1k-cocos-base-tsc-validate). Thứ tự ưu tiên: CLI flag > config > built-in fallback. Project khác chỉ cần sửa file này, KHÔNG đụng code skill:
{ "scriptRoot": "Client/assets/script", "assetsRoot": "Client/assets", "registry": "tmp/dep-registry.json", "creatorDts": "Client/creator.d.ts", "tsconfig": "Client/tsconfig.json" }Thiếu config → dùng fallback (giá trị trên). Sai 1 key → CLI flag tương ứng override.
Skills root — --skills-root / skillsRoot
Section titled “Skills root — --skills-root / skillsRoot”Orchestrator gọi các stage script sibling qua .claude/skills/t1k-cocos-base-<x>/scripts/ (layout
CI flatten ra consumer disk). Disk khác layout → override:
node .../migrate.cjs --all --run --skills-root <path-to-.claude/skills>hoặc { "skillsRoot": "<path>" } trong .claude/cocos-migrate.json.
Preflight: trước khi ghi BẤT KỲ file nào, orchestrator verify stage script + registry tồn tại.
Trước đây stage thiếu chỉ nổ giữa pipeline (Phase 1.5) sau khi Phase 1 đã ghi .cv.ts → project
half-migrated. Preflight scope theo ĐÚNG cái mode đó chạy — over-block cũng là defect:
| Mode | Stage script thiếu | Registry thiếu |
|---|---|---|
--rollback | bỏ qua — rollback chỉ đọc manifest (git checkout + xoá .meta), KHÔNG chạy stage nào | bỏ qua |
--plan (mặc định) | WARN, vẫn chạy (read-only). Cột cur không tin được vì thiếu js2ts → mọi file đọc ra stale | exit 2 |
--run | exit 2, liệt kê từng path, KHÔNG ghi gì | exit 2 |
--run --write | như trên + BẮT BUỘC có compref (Phase 1.5) | exit 2 |
--rollbackKHÔNG bao giờ bị gate: nó chính là đường recovery cho cái run half-applied mà stage thiếu gây ra — chặn nó là chặn đúng lối thoát.
compref ship trong module base (hấp thụ từ module migration đã ngừng, 2026-08-15). Phase 1.5
(--write) cần nó; orchestrator resolve theo thứ tự t1k-cocos-base-compref →
t1k-cocos-migration-compref → t1k-cocos-compref (2 tên sau chỉ để tương thích disk chưa chạy
t1k modules update). Preflight báo thiếu compref và dừng nếu không resolve được tên nào.
Output
Section titled “Output”- Plan: bảng topo-order —
# | grp(A/B/C) | isComp | .cv.ts | JS-ref | cur(manifest-current) | base/req-dep | file+ tổng A/B/C. - Run: từng Phase 0–4 với gate; SUMMARY
file | grp | phase1 | phase2 | phase3. Manifesttmp/migrate-state.jsonghi trạng thái +lastRun.repointed(cho rollback).
⚠️ Blast radius (đọc trước khi —write)
Section titled “⚠️ Blast radius (đọc trước khi —write)”attach re-point component ở MỌI prefab/scene tham chiếu nó (class uuid phải nhất quán toàn cục), KHÔNG chỉ scene bạn truyền. VD --scene main.fire nhưng LocalLabel/ClickButton/FullScreenWidget dùng khắp project → —write sẽ sửa hàng chục file. Luôn chạy --plan rồi --run (dry) trước --run --write. Revert = git checkout các prefab/scene.
Gotchas
Section titled “Gotchas”- Mặc định KHÔNG chạy gì —
--planchỉ đọc + in. Phải--runmới chạy stage;--run --write --editor-closedmới ghi. An toàn theo preview-first. - Base+require-first BẮT BUỘC — closure = extends + require transitive (internal). gate attach cần @property inherited; tsc-validate cần dep là module
.cv(bare cc.Class.js= TS2306). Orchestrator tự convert dep TRƯỚC. Base engine (cc.*, extendsAbs=null) → bỏ qua đúng. - SYNTAX-FAIL (TS1xxx) chặn cả batch ở Gate 2 (không —force) — Phase 3 KHÔNG chạy, 0 prefab bị đụng. Type residual (TS2xxx) KHÔNG chặn (any-safe).
- isPlugin auto-fix nằm ở
gen-meta/attach(uuid-verify) — orchestrator hưởng sẵn. - Phase 4 verify cần editor đã reimport để library entry phản ánh đúng (editor-compile-verify). Chạy
--writevới editor đóng → mở editor lại → reload → rồi tin kết quảverify. - GATE dependency-holdout (§ Cách hoạt động bước 4) — chặn RẺ ở Phase 1. 5 holdout js2ts đã biết: leaf (
Item,ItemAdvanced,DraftMenu—requiredBy=0) vs dependency (EffectManager2 cc.Class/file,LeaderboardDatastatics-getter). Dependency-holdout missing-module = TS2xxx NON-blocking → lọt Gate 2, chỉ lộ ở Phase 4 (đắt, SAU side-effect) → vì vậy GATE đặt ở Phase 1: holdout CÓ consumer trong closure → STOP NGAY, KHÔNG cho--allow-holdoutbypass.--allow-holdoutCHỈ tách leaf. EffectManager/LeaderboardData cần thêm js2ts support TRƯỚC khi closure chứa chúng chạy (chưa làm — gate sẽ STOP an toàn). - Chạy với editor ĐÓNG (single-writer uuid — canonical 2026-06-01). uuid là
crypto.randomUUID()→ KHÔNG value-reproducible; “tất định” ở đây = single-writer / process-deterministic / stateful-idempotent: một khi.cv.ts.metapersist thì re-run giữ nguyên uuid (idempotent).--editor-closedBẮT BUỘC trước Phase 3--write(tool là writer DUY NHẤT). Editor mở lúc attach → 2 writer → uuid khác/isPlugin:true→ mất đồng bộ. Chi tiết:t1k-cocos-base-uuid-verifygotcha 10. - Manifest
tmp/migrate-state.jsonlà SSOT trạng thái — file “current” (srcHash + codemodHash + dtsHash + registryHash khớp) → skip; lệch → STALE → redo.--resyncép redo toàn bộ. Idempotent chỉ ở--write(.cv.tspersist); dry-run luôn write-real→cleanup nên không “current-skip”. - Rollback dựa
git checkout— yêu cầu prefab/scene SẠCH trước--write(commit/stash trước). Gate-fail Phase 3 → in lệnh rollback (KHÔNG tự chạy);--rollbackthực thi theomanifest.lastRun.repointed. JS +.js.metaKHÔNG bao giờ bị đụng.
See also
Section titled “See also”t1k-cocos-base-js2ts·t1k-cocos-base-tsc-validate·t1k-cocos-base-uuid-verify(các stage).t1k-cocos-base-dep-graph— registry (results[].extendsAbs/requiresdùng để topo-sort).plans/reports/2026-05-29-js-to-ts-migration-brainstorm.md§5.2/§9 — vai trò orchestrator.