Skip to content

t1k:cocos:base:migrate

FieldValue
Modulebase
Version3.3.2
Efforthigh
Tools—

Keywords: atomic, idempotent, js2ts, manifest, orchestrator, pipeline, rollback

/t1k:cocos:base:migrate

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).

  1. Resolve target: --scene <path> (mọi component custom scene tham chiếu) HOẶC danh sách <file.js>.
  2. Closure = extends + require transitive (internal): base class + mọi require-dep được thêm để convert TRƯỚC (tsc-validate cần dep là module .cv mới type-check sạch; gate attach cần @property inherited). Topo-sort base+require-first.
  3. Phase 0 PRECONDITION (smart-refresh hash-gated): dep-graph + 4 .d.ts CHỈ regenerate khi nguồn đổi (hoặc --force-refresh). Stamp hash vào manifest.
  4. 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).
  5. 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.
  6. 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.
  7. 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ệngen-metaattach (re-point prefab)
A Component CÓ prefab-refisComponent && uuid trong prefab/scene✅✅ (blast-radius DUY NHẤT)
B Component KHÔNG prefab-refisComponent && 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ác require/import resolve 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:

Terminal window
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:

ModeStage script thiếuRegistry thiếu
--rollbackbỏ qua — rollback chỉ đọc manifest (git checkout + xoá .meta), KHÔNG chạy stage nàobỏ 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 staleexit 2
--runexit 2, liệt kê từng path, KHÔNG ghi gìexit 2
--run --writenhư trên + BẮT BUỘC có compref (Phase 1.5)exit 2

--rollback KHÔ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.

  • 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. Manifest tmp/migrate-state.json ghi 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.

  1. Mặc định KHÔNG chạy gì — --plan chỉ đọc + in. Phải --run mới chạy stage; --run --write --editor-closed mới ghi. An toàn theo preview-first.
  2. 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.
  3. 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).
  4. isPlugin auto-fix nằm ở gen-meta/attach (uuid-verify) — orchestrator hưởng sẵn.
  5. Phase 4 verify cần editor đã reimport để library entry phản ánh đúng (editor-compile-verify). Chạy --write với editor đóng → mở editor lại → reload → rồi tin kết quả verify.
  6. 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 (EffectManager 2 cc.Class/file, LeaderboardData statics-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-holdout bypass. --allow-holdout CHỈ 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).
  7. 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.meta persist thì re-run giữ nguyên uuid (idempotent). --editor-closed BẮ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-verify gotcha 10.
  8. Manifest tmp/migrate-state.json là 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.ts persist); dry-run luôn write-real→cleanup nên không “current-skip”.
  9. 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); --rollback thực thi theo manifest.lastRun.repointed. JS + .js.meta KHÔNG bao giờ bị đụng.
  • 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/requires dùng để topo-sort).
  • plans/reports/2026-05-29-js-to-ts-migration-brainstorm.md §5.2/§9 — vai trò orchestrator.