@ttmg/cli 0.4.1-beta.wasm1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/dist/index.js +170 -19
  2. package/dist/index.js.map +1 -1
  3. package/dist/package.json +1 -1
  4. package/dist/public/assets/Detail-DNF1PK-R.js +1 -0
  5. package/dist/public/assets/Detail-DNF1PK-R.js.br +0 -0
  6. package/dist/public/assets/MonetizationMode-C59U6Ari.js +1 -0
  7. package/dist/public/assets/MonetizationModeSummary-BR2LJFsU.js +1 -0
  8. package/dist/public/assets/SectionHeader-CCjfBKcF.js +1 -0
  9. package/dist/public/assets/Tag-DON36Of0.js +1 -0
  10. package/dist/public/assets/baseForm-B3oZF8Vp.js +10 -0
  11. package/dist/public/assets/baseForm-B3oZF8Vp.js.br +0 -0
  12. package/dist/public/assets/baseForm-BAvk37jF.css +1 -0
  13. package/dist/public/assets/baseForm-BAvk37jF.css.br +0 -0
  14. package/dist/public/assets/{boxes-C7RoIbId.js → boxes-EbMNfQ6U.js} +1 -1
  15. package/dist/public/assets/{chevron-right-B1WBZrrD.js → chevron-right-CsmjM7t0.js} +1 -1
  16. package/dist/public/assets/col-BXewy14r.css +1 -0
  17. package/dist/public/assets/col-BXewy14r.css.br +0 -0
  18. package/dist/public/assets/col-DWGIx7fj.js +1 -0
  19. package/dist/public/assets/{compass-VJNhHwqW.js → compass-bMD5nDM8.js} +1 -1
  20. package/dist/public/assets/index-B4j49Ts7.js +1 -0
  21. package/dist/public/assets/index-B4j49Ts7.js.br +0 -0
  22. package/dist/public/assets/{index-a-rMUS2V.js → index-B5JnznvI.js} +1 -1
  23. package/dist/public/assets/index-BCV7VBUL.js +1 -0
  24. package/dist/public/assets/index-BCV7VBUL.js.br +0 -0
  25. package/dist/public/assets/index-BKOO94x-.css +1 -0
  26. package/dist/public/assets/index-BPqSXmk6.js +1 -0
  27. package/dist/public/assets/index-Bn_Zugqv.js +1 -0
  28. package/dist/public/assets/index-Bn_Zugqv.js.br +0 -0
  29. package/dist/public/assets/index-BtO50Nho.js +1 -0
  30. package/dist/public/assets/index-BtO50Nho.js.br +0 -0
  31. package/dist/public/assets/{index-C_npSvtQ.js → index-BzEQAUVA.js} +1 -1
  32. package/dist/public/assets/{index-Dn5HHf-0.js → index-CAoj7RMM.js} +1 -1
  33. package/dist/public/assets/index-CKUVWl_O.css +1 -0
  34. package/dist/public/assets/index-CMwzPrAh.css +1 -0
  35. package/dist/public/assets/index-CMwzPrAh.css.br +0 -0
  36. package/dist/public/assets/index-CYnulX57.css +1 -0
  37. package/dist/public/assets/index-CYnulX57.css.br +0 -0
  38. package/dist/public/assets/{index-BH099q_U.js → index-Ca-cQ1Oq.js} +1 -1
  39. package/dist/public/assets/{index-s_30KWiA.js → index-CdJUBcSF.js} +1 -1
  40. package/dist/public/assets/{index-bQUQ2Wmz.js → index-Cf8aH-xI.js} +1 -1
  41. package/dist/public/assets/{index-DMsjcIN8.js → index-D4lGRib1.js} +1 -1
  42. package/dist/public/assets/index-D5-FwYf-.js +1 -0
  43. package/dist/public/assets/index-D5-FwYf-.js.br +0 -0
  44. package/dist/public/assets/{index-BO5MBsdm.js → index-DH7hBDqZ.js} +1 -1
  45. package/dist/public/assets/index-DKxf26_O.css +1 -0
  46. package/dist/public/assets/index-DOMxPC_v.css +1 -0
  47. package/dist/public/assets/index-DOMxPC_v.css.br +0 -0
  48. package/dist/public/assets/index-DRr-Punk.js +1 -0
  49. package/dist/public/assets/index-DV0N-QmJ.js +1 -0
  50. package/dist/public/assets/index-DV0N-QmJ.js.br +0 -0
  51. package/dist/public/assets/index-DXEfgIqc.js +1 -0
  52. package/dist/public/assets/{index-BBR3CPkN.js → index-DaOr2P0A.js} +1 -1
  53. package/dist/public/assets/index-DaOr2P0A.js.br +0 -0
  54. package/dist/public/assets/index-Dv0bhjYp.js +1 -0
  55. package/dist/public/assets/{index-qqnHwFjO.js → index-Dx-boSFk.js} +1 -1
  56. package/dist/public/assets/{index-C1C34gtn.js → index-FYgsnJbm.js} +1 -1
  57. package/dist/public/assets/index-HqjZ5P-l.css +1 -0
  58. package/dist/public/assets/{index-BJZ4gOGZ.css → index-V1Go68Vw.css} +1 -1
  59. package/dist/public/assets/index-V1Go68Vw.css.br +0 -0
  60. package/dist/public/assets/index-VvBtuIHK.css +1 -0
  61. package/dist/public/assets/index-VvBtuIHK.css.br +0 -0
  62. package/dist/public/assets/index-VvUpVuij.js +21 -0
  63. package/dist/public/assets/index-VvUpVuij.js.br +0 -0
  64. package/dist/public/assets/index-VzIFpCiL.js +1 -0
  65. package/dist/public/assets/{index-DbxY65Om.js → index-bASdAMHs.js} +1 -1
  66. package/dist/public/assets/index-q7fKJFmZ.js +1 -0
  67. package/dist/public/assets/index-vlN_-PRJ.css +1 -0
  68. package/dist/public/assets/{layers-Biv61qtE.js → layers-C8HCSIXn.js} +1 -1
  69. package/dist/public/assets/list-checks-B6t2uu5m.js +1 -0
  70. package/dist/public/assets/{sparkles-Bv2GxrFr.js → sparkles-pLu1TMVV.js} +1 -1
  71. package/dist/public/assets/triangle-alert-Dm4_sEwV.js +1 -0
  72. package/dist/public/assets/{zap-CjkC_qWZ.js → zap-tefJh46p.js} +1 -1
  73. package/dist/public/index.html +2 -2
  74. package/dist/scripts/docs/README.md +80 -0
  75. package/dist/scripts/docs/capture.js +84 -6
  76. package/dist/scripts/docs/check.js +184 -0
  77. package/dist/scripts/docs/render.js +283 -6
  78. package/dist/scripts/docs/scenarios/devtool-guide.mjs +802 -0
  79. package/package.json +1 -1
  80. package/CHANGELOG.md +0 -256
  81. package/dist/public/assets/Card-ASGGlJ8S.js +0 -1
  82. package/dist/public/assets/Detail-DY__Zw0r.js +0 -1
  83. package/dist/public/assets/Detail-DY__Zw0r.js.br +0 -0
  84. package/dist/public/assets/MonetizationMode-sHN_4ybQ.js +0 -1
  85. package/dist/public/assets/MonetizationModeSummary-DLvyriLM.js +0 -1
  86. package/dist/public/assets/SectionHeader-B7dueBCf.js +0 -1
  87. package/dist/public/assets/Tag-BsX0d6UL.js +0 -1
  88. package/dist/public/assets/arrow-left-uixm7Sd1.js +0 -1
  89. package/dist/public/assets/baseForm-C8XfTFyG.js +0 -10
  90. package/dist/public/assets/baseForm-C8XfTFyG.js.br +0 -0
  91. package/dist/public/assets/baseForm-Dl4zA6hU.css +0 -1
  92. package/dist/public/assets/baseForm-Dl4zA6hU.css.br +0 -0
  93. package/dist/public/assets/circle-check-wUxXeINd.js +0 -1
  94. package/dist/public/assets/index-BAud2cRu.css +0 -1
  95. package/dist/public/assets/index-BBR3CPkN.js.br +0 -0
  96. package/dist/public/assets/index-BJZ4gOGZ.css.br +0 -0
  97. package/dist/public/assets/index-BNc8JtET.js +0 -1
  98. package/dist/public/assets/index-Bd-f8ERX.js +0 -1
  99. package/dist/public/assets/index-ByX5RuFA.css +0 -1
  100. package/dist/public/assets/index-C7Tmy9g3.js +0 -1
  101. package/dist/public/assets/index-CCKb9Y-j.js +0 -14
  102. package/dist/public/assets/index-CCKb9Y-j.js.br +0 -0
  103. package/dist/public/assets/index-CFd8iglC.css +0 -1
  104. package/dist/public/assets/index-CFd8iglC.css.br +0 -0
  105. package/dist/public/assets/index-CKhfKyA3.js +0 -1
  106. package/dist/public/assets/index-CKhfKyA3.js.br +0 -0
  107. package/dist/public/assets/index-Cc1ilXmc.css +0 -1
  108. package/dist/public/assets/index-DHXlsTU6.css +0 -1
  109. package/dist/public/assets/index-DHXlsTU6.css.br +0 -0
  110. package/dist/public/assets/index-DNd8ZTok.js +0 -1
  111. package/dist/public/assets/index-DNd8ZTok.js.br +0 -0
  112. package/dist/public/assets/index-DpkktYot.css +0 -1
  113. package/dist/public/assets/index-DtoDrber.js +0 -1
  114. package/dist/public/assets/index-DtoDrber.js.br +0 -0
  115. package/dist/public/assets/index-ZHPtAdJM.js +0 -1
  116. package/dist/public/assets/index-ZHPtAdJM.js.br +0 -0
  117. package/dist/public/assets/index-ZtlCPCV9.js +0 -1
  118. package/dist/public/assets/index-_6n0s04V.css +0 -1
  119. package/dist/public/assets/index-_6n0s04V.css.br +0 -0
  120. package/dist/public/assets/index-r3aSeNL1.js +0 -1
  121. package/dist/public/assets/index-t4JeqZ4a.js +0 -1
@@ -0,0 +1,802 @@
1
+ export const schemaVersion = 1;
2
+
3
+ export const locales = ['zh-CN', 'en-US'];
4
+
5
+ export const guideTitle = 'TikTok Mini Games DevTool Usage Guide';
6
+
7
+ export const guideSource = {
8
+ type: 'lark-wiki',
9
+ title: 'DevTool 使用指南',
10
+ url: 'https://bytedance.larkoffice.com/wiki/Pu01wnThsiyCl2kff2mcvDaannc',
11
+ token: 'Pu01wnThsiyCl2kff2mcvDaannc',
12
+ documentId: 'EDxrdwTxfoekL0x3c1xlNj2ygRe',
13
+ observedRevisionId: 2821,
14
+ outline: [
15
+ '中文 / English',
16
+ '开始之前 / Before You Start',
17
+ '使用链路 / Usage Flow',
18
+ '关键模块 / Key Modules',
19
+ '模式边界 / Mode Boundaries',
20
+ '常见问题 / FAQ',
21
+ '更多参考 / More References',
22
+ ],
23
+ };
24
+
25
+ export const docVersion = {
26
+ id: 'ttmg-devtool-usage-guide',
27
+ status: 'draft',
28
+ ownerReviewRequired: true,
29
+ sourceOfTruth: 'DevTool UI + scenario manifest + latest captured screenshots',
30
+ publishTiming: 'before a DevTool release or when screenshots in the public guide are refreshed',
31
+ };
32
+
33
+ export const documentationContract = {
34
+ audience: 'external mini-game developers using DevTool',
35
+ intent: [
36
+ 'Help developers finish debugging and release tasks with the current UI.',
37
+ 'Expose only developer-visible behavior, not internal architecture or implementation details.',
38
+ 'Keep screenshots, UI copy, commands, and troubleshooting guidance synchronized.',
39
+ ],
40
+ writingRules: [
41
+ 'Start from the developer task or visible symptom.',
42
+ 'Explain what to do next before adding background.',
43
+ 'Keep commands contextual; do not turn the guide into a CLI reference.',
44
+ 'Separate permission, proxy/network, and project-configuration issues.',
45
+ 'Do not publish screenshots that depend on private accounts, tokens, or real QR payloads.',
46
+ ],
47
+ screenshotRules: [
48
+ 'Use docMode fixtures and stable data-doc-shot anchors whenever possible.',
49
+ 'Capture both zh-CN and en-US for every published screenshot.',
50
+ 'Refresh screenshots after layout, copy, permission-state, or network-state changes.',
51
+ ],
52
+ };
53
+
54
+ export const guideReleaseChecks = [
55
+ 'The generated guide draft matches the latest scenario manifest.',
56
+ 'Every published screenshot has zh-CN and en-US variants.',
57
+ 'capture-report.json matches the current scenario fingerprint.',
58
+ 'Permission and proxy/network fallback states are covered in FAQ or page notes.',
59
+ 'No internal-only route, account, token, or private QR payload is visible.',
60
+ ];
61
+
62
+ export const screenshotInventory = [
63
+ {
64
+ id: 'start-debug.qr-idle',
65
+ recipeId: 'home',
66
+ guideSection: 'Start debugging',
67
+ publishInGuide: true,
68
+ purpose: 'QR entry, launch-mode switch, and local Node status',
69
+ },
70
+ {
71
+ id: 'launch-mode.default',
72
+ recipeId: 'launch-mode',
73
+ guideSection: 'Start debugging',
74
+ publishInGuide: true,
75
+ purpose: 'custom launch package, scene, and launch parameters',
76
+ },
77
+ {
78
+ id: 'project.ready',
79
+ recipeId: 'project-detail',
80
+ guideSection: 'Project overview',
81
+ publishInGuide: true,
82
+ purpose: 'project metadata, package status, Trust Domain, Terms, and Privacy',
83
+ },
84
+ {
85
+ id: 'integration.map',
86
+ recipeId: 'integration-assistant-map',
87
+ guideSection: 'Integration assistant',
88
+ publishInGuide: true,
89
+ purpose: 'business-model choice and capability grouping',
90
+ },
91
+ {
92
+ id: 'upload.precheck',
93
+ recipeId: 'upload-publish',
94
+ guideSection: 'Upload & publish',
95
+ publishInGuide: true,
96
+ purpose: 'precheck summary, version note, upload action, and preview history',
97
+ },
98
+ {
99
+ id: 'upload.permission-restricted',
100
+ recipeId: 'upload-game-restricted',
101
+ guideSection: 'Upload & publish',
102
+ publishInGuide: true,
103
+ purpose: 'account permission fallback for platform-dependent modules',
104
+ },
105
+ {
106
+ id: 'network.client-unreachable',
107
+ recipeId: 'network-diagnostics',
108
+ guideSection: 'FAQ / troubleshooting',
109
+ publishInGuide: true,
110
+ purpose: 'client HTTP and WS unreachable guidance',
111
+ },
112
+ {
113
+ id: 'subpackage.collect-ready',
114
+ recipeId: 'subpackage-collect',
115
+ guideSection: 'Performance optimization',
116
+ publishInGuide: false,
117
+ purpose: 'non-Unity subpackage collection prerequisites and flow',
118
+ },
119
+ {
120
+ id: 'wasm.prepare',
121
+ recipeId: 'wasm-split',
122
+ guideSection: 'Performance optimization',
123
+ publishInGuide: false,
124
+ purpose: 'Unity Wasm split prerequisites and flow',
125
+ },
126
+ ];
127
+
128
+ export const defaultLocalStorage = {
129
+ TTMG_DOCS_CAPTURE: '1',
130
+ };
131
+
132
+ const desktopViewport = { width: 1440, height: 1200 };
133
+ const tallViewport = { width: 1440, height: 1600 };
134
+
135
+ const zhFaqs = [
136
+ {
137
+ question: '扫码后没有连接上怎么办?',
138
+ answer: [
139
+ '先确认手机和电脑在同一网络,TikTok 页面停留在调试加载页。',
140
+ '如果公司网络、VPN 或代理比较复杂,可以进入网络诊断查看 HTTP 与 WS 链路。',
141
+ '仍然无法自动连接时,使用手动指定客户端地址填写 Client IP、HTTP 端口和 WS 端口。',
142
+ ],
143
+ },
144
+ {
145
+ question: '为什么项目概览没有平台配置?',
146
+ answer: [
147
+ '通常是当前账号没有目标游戏的开发权限,或本地终端代理没有正确生效。',
148
+ '先确认 `ttmg login` 使用的是目标游戏的开发者账号。',
149
+ '如果账号没问题,再检查 CLI 代理配置和公司网络访问。',
150
+ ],
151
+ },
152
+ {
153
+ question: '什么时候需要看上传发布?',
154
+ answer: [
155
+ '准备生成预览版本、测试构建结果或提交平台审核前,都应该先看上传发布。',
156
+ '这里会集中展示包体、配置、API 与性能预检结果,并提供上传后的预览版本记录。',
157
+ ],
158
+ },
159
+ {
160
+ question: 'Trust Domain 没拉到或平台配置为空时怎么办?',
161
+ answer: [
162
+ '先区分账号权限和终端代理:没有游戏权限时需要去开发者平台申请权限;账号有权限但配置为空时,多半是终端代理或公司网络没有生效。',
163
+ '确认代理后重新运行 `ttmg dev`,再回到项目概览检查 Trust Domain、Terms URL 和 Privacy URL。',
164
+ ],
165
+ },
166
+ {
167
+ question: 'Unity 和非 Unity 的分包能力有什么区别?',
168
+ answer: [
169
+ '非 Unity 小游戏使用“子包收集”采集启动阶段预下载的子包;Unity 小游戏使用 Wasm 分包链路。',
170
+ 'Unity 由于 wasmcode 形态暂不能完整预先检查,当前仍需要继续调研并关注页面里的 Wasm Code Split 提示。',
171
+ ],
172
+ },
173
+ ];
174
+
175
+ const enFaqs = [
176
+ {
177
+ question: 'What should I do if scanning the QR code does not connect?',
178
+ answer: [
179
+ 'Make sure the phone and computer are on the same network and TikTok stays on the debug loading page.',
180
+ 'If your office network, VPN, or proxy is complex, open Network diagnostics to inspect HTTP and WS connectivity.',
181
+ 'If automatic connection still fails, use manual client address setup with Client IP, HTTP port, and WS port.',
182
+ ],
183
+ },
184
+ {
185
+ question: 'Why is platform configuration missing in Project Overview?',
186
+ answer: [
187
+ 'The usual causes are missing developer permission for the target game or a terminal proxy that is not active.',
188
+ 'First confirm that `ttmg login` uses the developer account for the target game.',
189
+ 'If the account is correct, check CLI proxy configuration and company network access.',
190
+ ],
191
+ },
192
+ {
193
+ question: 'When should I use Upload & Publish?',
194
+ answer: [
195
+ 'Use it before generating a preview build, validating a build result, or submitting to platform review.',
196
+ 'It centralizes package, configuration, API, and performance prechecks, then keeps preview-build records after upload.',
197
+ ],
198
+ },
199
+ {
200
+ question: 'What should I do if Trust Domain or platform configuration is missing?',
201
+ answer: [
202
+ 'Separate permission issues from terminal proxy issues first. Missing game permission should be fixed in the developer platform. Empty configuration with the right account usually means the terminal proxy or company network is not active.',
203
+ 'After fixing the proxy, rerun `ttmg dev` and check Trust Domain, Terms URL, and Privacy URL in Project Overview again.',
204
+ ],
205
+ },
206
+ {
207
+ question: 'How are Unity and non-Unity subpackage flows different?',
208
+ answer: [
209
+ 'Non-Unity mini-games use Subpackage Collection to collect subpackages downloaded during startup. Unity mini-games use the Wasm Split flow.',
210
+ 'Because Unity uses wasmcode, full precheck is not available yet and still needs investigation. Watch the Wasm Code Split prompts on the page.',
211
+ ],
212
+ },
213
+ ];
214
+
215
+ export const guideFaqs = {
216
+ 'zh-CN': zhFaqs,
217
+ 'en-US': enFaqs,
218
+ };
219
+
220
+ export const guideSections = {
221
+ 'zh-CN': [
222
+ '开始之前',
223
+ '开始调试',
224
+ '项目概览',
225
+ '接入助手',
226
+ '上传发布',
227
+ '网络诊断',
228
+ '性能优化',
229
+ ],
230
+ 'en-US': [
231
+ 'Before you start',
232
+ 'Start debugging',
233
+ 'Project overview',
234
+ 'Integration assistant',
235
+ 'Upload & publish',
236
+ 'Network diagnostics',
237
+ 'Performance optimization',
238
+ ],
239
+ };
240
+
241
+ function notes(zh, en) {
242
+ return {
243
+ 'zh-CN': zh,
244
+ 'en-US': en,
245
+ };
246
+ }
247
+
248
+ function recipe(config) {
249
+ return {
250
+ captureMode: 'fullPage',
251
+ capture: {
252
+ selector: config.selector,
253
+ viewport: config.viewport || desktopViewport,
254
+ mode: 'fullPage',
255
+ },
256
+ waitFor: {
257
+ selector: config.selector,
258
+ timeoutMs: config.timeoutMs || 20000,
259
+ },
260
+ privacy: {
261
+ masks: [
262
+ 'account avatar',
263
+ 'developer email',
264
+ 'session token',
265
+ 'preview QR payload',
266
+ ],
267
+ },
268
+ updatePolicy: {
269
+ owner: 'DevTool',
270
+ refreshWhen: [
271
+ 'page layout changes',
272
+ 'core workflow copy changes',
273
+ 'permission or network state changes',
274
+ ],
275
+ },
276
+ ...config,
277
+ };
278
+ }
279
+
280
+ export const recipes = [
281
+ recipe({
282
+ id: 'home',
283
+ title: 'Start debugging QR code',
284
+ page: 'Start Debugging',
285
+ productArea: 'debug',
286
+ route: '/?docMode=1&docScenario=start-debug.qr-idle',
287
+ selector: '[data-doc-shot="start-debug-qr-idle"]',
288
+ fixture: {
289
+ kind: 'local',
290
+ scenario: 'node-connected-device-disconnected',
291
+ required: ['localNodeConfig', 'qrCode'],
292
+ },
293
+ doc: {
294
+ section: 'Start debugging',
295
+ anchor: 'start-debugging',
296
+ intent: 'show launch mode selection and QR entry',
297
+ },
298
+ acceptance: [
299
+ 'status banner shows local Node service state',
300
+ 'QR card is visible without page scroll pressure',
301
+ 'remote debug and client preview mode switch is clear',
302
+ ],
303
+ notes: notes(
304
+ {
305
+ title: '开始调试',
306
+ purpose: '从本地 Node 调试服务生成二维码,让 TikTok 客户端扫码进入调试或真机预览。',
307
+ whenToUse: '第一次启动项目、切换设备、验证远程调试或真机预览时使用。',
308
+ steps: [
309
+ '确认本地调试服务已启动。',
310
+ '选择需要的启动模式。',
311
+ '用 TikTok 客户端扫码进入游戏。',
312
+ ],
313
+ keyChecks: [
314
+ '二维码下方的远程调试 / 真机预览选择是否符合当前目标。',
315
+ '扫码无响应时是否能进入网络诊断。',
316
+ ],
317
+ },
318
+ {
319
+ title: 'Start Debugging',
320
+ purpose: 'Generate a QR code from the local Node debugging service so the TikTok client can open debugging or device preview.',
321
+ whenToUse: 'Use it when starting a project, switching devices, or validating remote debugging and device preview.',
322
+ steps: [
323
+ 'Confirm that the local debugging service is running.',
324
+ 'Select the launch mode you need.',
325
+ 'Scan the QR code with the TikTok client to open the game.',
326
+ ],
327
+ keyChecks: [
328
+ 'Remote debug and client preview options match the current goal.',
329
+ 'Network diagnostics is reachable when scanning does not respond.',
330
+ ],
331
+ },
332
+ ),
333
+ }),
334
+ recipe({
335
+ id: 'launch-mode',
336
+ title: 'Launch mode configuration',
337
+ page: 'Launch Mode',
338
+ productArea: 'debug',
339
+ route: '/launch_mode?docMode=1&docScenario=launch-mode.default',
340
+ selector: '.launch-mode-page',
341
+ fixture: {
342
+ kind: 'local',
343
+ scenario: 'default-launch-mode',
344
+ required: ['launchModeList', 'packageList', 'sceneList'],
345
+ },
346
+ doc: {
347
+ section: 'Start debugging',
348
+ anchor: 'launch-mode',
349
+ intent: 'configure package, scene and startup parameters before scanning',
350
+ },
351
+ acceptance: [
352
+ 'current mode and custom mode are visually separated',
353
+ 'required fields are scannable',
354
+ 'primary action does not dominate the form',
355
+ ],
356
+ notes: notes(
357
+ {
358
+ title: '启动模式',
359
+ purpose: '配置启动包、进入场景和启动参数,保证扫码后进入预期游戏状态。',
360
+ whenToUse: '需要复现指定入口、投流参数、分包路径或测试场景时使用。',
361
+ steps: [
362
+ '选择已有启动模式,或创建一个新的自定义模式。',
363
+ '补充启动包、进入场景和启动参数。',
364
+ '保存后回到开始调试页扫码。',
365
+ ],
366
+ keyChecks: [
367
+ '启动包是否与测试目标一致。',
368
+ '进入场景和启动参数是否覆盖本次调试 case。',
369
+ ],
370
+ },
371
+ {
372
+ title: 'Launch Mode',
373
+ purpose: 'Configure package, entry scene, and launch parameters so scanning opens the expected game state.',
374
+ whenToUse: 'Use it to reproduce a specific entry, campaign parameter, subpackage path, or test scenario.',
375
+ steps: [
376
+ 'Select an existing launch mode or create a custom one.',
377
+ 'Fill in package, entry scene, and launch parameters.',
378
+ 'Save it and return to Start Debugging to scan.',
379
+ ],
380
+ keyChecks: [
381
+ 'The launch package matches the target scenario.',
382
+ 'Entry scene and launch parameters cover the test case.',
383
+ ],
384
+ },
385
+ ),
386
+ }),
387
+ recipe({
388
+ id: 'project-detail',
389
+ title: 'Project overview',
390
+ page: 'Project Overview',
391
+ productArea: 'project',
392
+ route: '/project_overview?docMode=1&docScenario=project.ready',
393
+ selector: '[data-doc-shot="project-ready"]',
394
+ viewport: tallViewport,
395
+ capture: {
396
+ selector: '[data-doc-shot="project-ready"]',
397
+ viewport: tallViewport,
398
+ mode: 'fullPage',
399
+ },
400
+ fixture: {
401
+ kind: 'platform',
402
+ scenario: 'permissioned-project-with-partial-platform-config',
403
+ required: ['gameDetail', 'packageSize', 'trustDomain', 'termsPrivacy'],
404
+ },
405
+ doc: {
406
+ section: 'Project overview',
407
+ anchor: 'project-overview',
408
+ intent: 'show project metadata and platform configuration health',
409
+ },
410
+ acceptance: [
411
+ 'basic information, package status and platform configuration use the same section rhythm',
412
+ 'missing platform configuration is shown as actionable guidance',
413
+ 'network proxy and permission states are distinguishable',
414
+ ],
415
+ notes: notes(
416
+ {
417
+ title: '项目概览',
418
+ purpose: '核对项目基础信息、包体状态、信任域名、用户协议和隐私政策。',
419
+ whenToUse: '上传发布前、能力调试异常或怀疑平台配置缺失时使用。',
420
+ steps: [
421
+ '确认基础信息和 Client Key 是否匹配当前项目。',
422
+ '查看包体大小是否超限。',
423
+ '检查 Trust Domain、Terms URL 和 Privacy URL 是否齐全。',
424
+ ],
425
+ keyChecks: [
426
+ '账号无权限和终端代理异常需要给出不同提示。',
427
+ '缺失配置要说明影响和下一步补齐方式。',
428
+ ],
429
+ },
430
+ {
431
+ title: 'Project Overview',
432
+ purpose: 'Check project metadata, package status, trusted domains, Terms URL, and Privacy URL.',
433
+ whenToUse: 'Use it before upload, when capability debugging fails, or when platform configuration may be missing.',
434
+ steps: [
435
+ 'Confirm that project metadata and Client Key match the current project.',
436
+ 'Check whether package size exceeds limits.',
437
+ 'Verify Trust Domain, Terms URL, and Privacy URL.',
438
+ ],
439
+ keyChecks: [
440
+ 'Missing permission and terminal proxy issues use different guidance.',
441
+ 'Missing configuration explains impact and next action.',
442
+ ],
443
+ },
444
+ ),
445
+ }),
446
+ recipe({
447
+ id: 'integration-assistant-map',
448
+ title: 'Integration assistant overview',
449
+ page: 'Integration Assistant',
450
+ productArea: 'capability',
451
+ route: '/integration_assistant?docMode=1&docScenario=integration.map',
452
+ selector: '.ia-page',
453
+ viewport: tallViewport,
454
+ capture: {
455
+ selector: '.ia-page',
456
+ viewport: tallViewport,
457
+ mode: 'fullPage',
458
+ },
459
+ fixture: {
460
+ kind: 'static',
461
+ scenario: 'capability-map',
462
+ required: ['monetizationModes', 'capabilitySections'],
463
+ },
464
+ doc: {
465
+ section: 'Integration assistant',
466
+ anchor: 'integration-assistant',
467
+ intent: 'explain capability grouping and business model selection',
468
+ },
469
+ acceptance: [
470
+ 'monetization mode cards are lighter than primary task buttons',
471
+ 'expand actions are low-pressure secondary controls',
472
+ 'capability grouping is scannable without dense blue emphasis',
473
+ ],
474
+ notes: notes(
475
+ {
476
+ title: '接入助手',
477
+ purpose: '按变现模式和能力类别给出接入建议,帮助判断当前项目应该先接哪些能力。',
478
+ whenToUse: '规划登录、授权、广告、支付、分享、复访等能力接入时使用。',
479
+ steps: [
480
+ '先选择更接近当前项目的变现模式。',
481
+ '查看必接、推荐和配套能力。',
482
+ '进入具体能力详情确认调试路径。',
483
+ ],
484
+ keyChecks: [
485
+ '按钮视觉不能压过内容层级。',
486
+ '能力文案需要说明为什么接,而不是只列 API。',
487
+ ],
488
+ },
489
+ {
490
+ title: 'Integration Assistant',
491
+ purpose: 'Recommend capabilities by monetization model and capability group so teams know what to integrate first.',
492
+ whenToUse: 'Use it when planning login, authorization, ads, payment, sharing, revisit, or other capability work.',
493
+ steps: [
494
+ 'Choose the monetization model closest to the current game.',
495
+ 'Review required, recommended, and supporting capabilities.',
496
+ 'Open a capability detail page to confirm the debugging path.',
497
+ ],
498
+ keyChecks: [
499
+ 'Buttons do not visually overpower the content hierarchy.',
500
+ 'Capability copy explains why to integrate, not only which API to call.',
501
+ ],
502
+ },
503
+ ),
504
+ }),
505
+ recipe({
506
+ id: 'upload-publish',
507
+ title: 'Upload and publish',
508
+ page: 'Upload & Publish',
509
+ productArea: 'release',
510
+ route: '/upload_publish?docMode=1&docScenario=upload.precheck',
511
+ selector: '.upload-game-page',
512
+ viewport: tallViewport,
513
+ capture: {
514
+ selector: '.upload-game-page',
515
+ viewport: tallViewport,
516
+ mode: 'fullPage',
517
+ },
518
+ fixture: {
519
+ kind: 'hybrid',
520
+ scenario: 'precheck-warning-upload-ready',
521
+ required: ['precheckSummary', 'uploadPermission', 'previewHistory'],
522
+ },
523
+ doc: {
524
+ section: 'Upload & publish',
525
+ anchor: 'upload-publish',
526
+ intent: 'show precheck, version note and preview build history',
527
+ },
528
+ acceptance: [
529
+ 'precheck warning is above the workflow, not buried inside the form',
530
+ 'upload action is a clear primary task but not oversized',
531
+ 'version note and preview records are separate modules',
532
+ ],
533
+ notes: notes(
534
+ {
535
+ title: '上传发布',
536
+ purpose: '在上传前集中处理代码预检、版本说明、上传动作和预览版本记录。',
537
+ whenToUse: '准备生成平台预览版本或提审前验证构建结果时使用。',
538
+ steps: [
539
+ '先查看预检提示和关键摘要。',
540
+ '展开详情处理阻塞项。',
541
+ '填写版本说明后上传至平台。',
542
+ '上传完成后在预览版本记录中继续扫码验证。',
543
+ ],
544
+ keyChecks: [
545
+ '性能类风险如果顶部已经提示,详情区避免重复制造压力。',
546
+ '分割线和重边框不应打断主流程。',
547
+ ],
548
+ },
549
+ {
550
+ title: 'Upload & Publish',
551
+ purpose: 'Handle code precheck, version note, upload action, and preview-build records before release.',
552
+ whenToUse: 'Use it before generating a platform preview build or validating a build before review.',
553
+ steps: [
554
+ 'Review the precheck prompt and key summary first.',
555
+ 'Expand details to resolve blockers.',
556
+ 'Enter a version note and upload to the platform.',
557
+ 'After upload, continue validation from preview-build records.',
558
+ ],
559
+ keyChecks: [
560
+ 'Performance risks are not repeated heavily when already shown in the top summary.',
561
+ 'Dividers and heavy borders do not interrupt the main workflow.',
562
+ ],
563
+ },
564
+ ),
565
+ }),
566
+ recipe({
567
+ id: 'upload-game-restricted',
568
+ title: 'Upload restricted state',
569
+ page: 'Upload & Publish',
570
+ productArea: 'release',
571
+ route: '/upload_publish?docMode=1&docScenario=upload.permission-restricted',
572
+ selector: '.upload-game-page',
573
+ viewport: tallViewport,
574
+ capture: {
575
+ selector: '.upload-game-page',
576
+ viewport: tallViewport,
577
+ mode: 'fullPage',
578
+ },
579
+ fixture: {
580
+ kind: 'platform',
581
+ scenario: 'account-without-upload-permission',
582
+ required: ['gameDetailAccessState', 'uploadPermission'],
583
+ },
584
+ doc: {
585
+ section: 'Upload & publish',
586
+ anchor: 'upload-permission',
587
+ intent: 'explain how upload behaves when platform permission is missing',
588
+ },
589
+ acceptance: [
590
+ 'permission issue uses warning color, not primary theme color',
591
+ 'copy says the module cannot be operated, not merely cannot be viewed',
592
+ 'recovery steps point to account and developer-platform permission',
593
+ ],
594
+ notes: notes(
595
+ {
596
+ title: '上传权限受限',
597
+ purpose: '说明当前账号没有目标游戏权限时,上传发布模块为什么不能继续操作。',
598
+ whenToUse: '账号能启动本地项目,但无法读取平台配置或执行上传发布时使用。',
599
+ steps: [
600
+ '确认 `ttmg login` 的账号是否属于目标游戏。',
601
+ '在开发者平台申请或补齐该游戏的开发权限。',
602
+ '权限开通后重新运行 `ttmg dev` 进入新会话。',
603
+ ],
604
+ keyChecks: [
605
+ '标题要表达“无法操作当前模块”。',
606
+ '提示需要说明这通常不是本地工程问题。',
607
+ ],
608
+ },
609
+ {
610
+ title: 'Upload Permission Restricted',
611
+ purpose: 'Explain why Upload & Publish cannot continue when the current account lacks permission for the target game.',
612
+ whenToUse: 'Use it when the local project can start but platform configuration or upload actions are blocked.',
613
+ steps: [
614
+ 'Confirm whether the `ttmg login` account belongs to the target game.',
615
+ 'Request or restore developer permission for the game in the developer platform.',
616
+ 'After permission is granted, rerun `ttmg dev` to start a new session.',
617
+ ],
618
+ keyChecks: [
619
+ 'The title says the module cannot be operated.',
620
+ 'The guidance explains that this is usually not a local project issue.',
621
+ ],
622
+ },
623
+ ),
624
+ }),
625
+ recipe({
626
+ id: 'network-diagnostics',
627
+ title: 'Network diagnostics',
628
+ page: 'Network Diagnostics',
629
+ productArea: 'debug',
630
+ route: '/network_diagnostics?docMode=1&docScenario=network.client-unreachable',
631
+ selector: '.check-network-container',
632
+ viewport: tallViewport,
633
+ capture: {
634
+ selector: '.check-network-container',
635
+ viewport: tallViewport,
636
+ mode: 'fullPage',
637
+ },
638
+ fixture: {
639
+ kind: 'runtime',
640
+ scenario: 'client-http-and-ws-unreachable',
641
+ required: ['nodeStatus', 'clientAddress', 'connectivityResults'],
642
+ },
643
+ doc: {
644
+ section: 'Network diagnostics',
645
+ anchor: 'network-diagnostics',
646
+ intent: 'guide developers when QR scan stalls or client connection fails',
647
+ },
648
+ acceptance: [
649
+ 'current conclusion comes before raw link evidence',
650
+ 'manual address entry is a separate action, not a long inline form',
651
+ 'proxy-to-computer-network suggestion is visible for hard network cases',
652
+ ],
653
+ notes: notes(
654
+ {
655
+ title: '网络诊断',
656
+ purpose: '定位扫码卡住、连接失败、HTTP/WS 端口不可达等本地网络问题。',
657
+ whenToUse: '扫码没有返回客户端地址、远程调试连不上或多网卡/VPN 环境复杂时使用。',
658
+ steps: [
659
+ '先看当前结论,确认问题发生在本机、客户端还是二者之间。',
660
+ '按建议处理网络、VPN、代理、防火墙或端口监听问题。',
661
+ '必要时手动填写客户端地址并重新检测。',
662
+ ],
663
+ keyChecks: [
664
+ '检测结果要保留证据,但不能压过处理建议。',
665
+ '实在连不上时提示可将手机网络代理到电脑网络后再扫码。',
666
+ ],
667
+ },
668
+ {
669
+ title: 'Network Diagnostics',
670
+ purpose: 'Diagnose local network issues such as stalled scanning, connection failure, and unreachable HTTP or WS ports.',
671
+ whenToUse: 'Use it when scanning does not return a client address, remote debugging cannot connect, or VPN / multi-network setup is complex.',
672
+ steps: [
673
+ 'Read the current conclusion first to locate whether the issue is on the computer, client, or path between them.',
674
+ 'Follow the suggestion for network, VPN, proxy, firewall, or port listener issues.',
675
+ 'Enter the client address manually and rerun detection when needed.',
676
+ ],
677
+ keyChecks: [
678
+ 'Raw detection evidence remains available without overwhelming the guidance.',
679
+ 'For hard network cases, suggest proxying the phone network to the computer network and scanning again.',
680
+ ],
681
+ },
682
+ ),
683
+ }),
684
+ recipe({
685
+ id: 'subpackage-collect',
686
+ title: 'Subpackage collection',
687
+ page: 'Subpackage Collection',
688
+ productArea: 'performance',
689
+ route: '/subpackage_collect?docMode=1&docScenario=subpackage.collect-ready',
690
+ selector: '.subpkg-page',
691
+ viewport: tallViewport,
692
+ capture: {
693
+ selector: '.subpkg-page',
694
+ viewport: tallViewport,
695
+ mode: 'fullPage',
696
+ },
697
+ fixture: {
698
+ kind: 'runtime',
699
+ scenario: 'non-unity-game-collect-ready',
700
+ required: ['subpackageEntries', 'clientVersion', 'tiktokRegion'],
701
+ },
702
+ doc: {
703
+ section: 'Performance optimization',
704
+ anchor: 'subpackage-collection',
705
+ intent: 'collect startup subpackages for preload configuration',
706
+ },
707
+ acceptance: [
708
+ 'Unity projects do not show the collection operation area',
709
+ 'requirements mention non-US TikTok account and client support version',
710
+ 'collection status and upload progress stay in the same state module',
711
+ ],
712
+ notes: notes(
713
+ {
714
+ title: '子包收集',
715
+ purpose: '采集启动阶段被预下载的子包,并转换为预加载配置。',
716
+ whenToUse: '非 Unity 小游戏需要优化首屏冷启动、沉淀预加载配置时使用。',
717
+ steps: [
718
+ '确认 TikTok 客户端版本和账号地区满足要求。',
719
+ '扫码后按真实启动路径操作游戏。',
720
+ '进入可交互后触发 `reportScene({sceneId:9999})` 完成收集。',
721
+ ],
722
+ keyChecks: [
723
+ 'US 账号无法收集函数,需要直接提示。',
724
+ 'Unity 小游戏不支持该收集链路。',
725
+ ],
726
+ },
727
+ {
728
+ title: 'Subpackage Collection',
729
+ purpose: 'Collect subpackages downloaded during startup and convert them into preload configuration.',
730
+ whenToUse: 'Use it for non-Unity mini-games that need to optimize cold start and generate preload configuration.',
731
+ steps: [
732
+ 'Confirm that the TikTok client version and account region meet the requirement.',
733
+ 'Scan and operate the game through the real startup path.',
734
+ 'After the game becomes interactive, call `reportScene({sceneId:9999})` to finish collection.',
735
+ ],
736
+ keyChecks: [
737
+ 'US accounts cannot collect functions and must be called out directly.',
738
+ 'Unity mini-games are not supported by this collection flow.',
739
+ ],
740
+ },
741
+ ),
742
+ }),
743
+ recipe({
744
+ id: 'wasm-split',
745
+ title: 'Wasm split',
746
+ page: 'Wasm Split',
747
+ productArea: 'performance',
748
+ route: '/wasm_split?docMode=1&docScenario=wasm.prepare',
749
+ selector: '.tt-wasm-split-page',
750
+ viewport: tallViewport,
751
+ capture: {
752
+ selector: '.tt-wasm-split-page',
753
+ viewport: tallViewport,
754
+ mode: 'fullPage',
755
+ },
756
+ fixture: {
757
+ kind: 'local',
758
+ scenario: 'unity-wasm-split-ready',
759
+ required: ['unityPluginVersion', 'wasmArchive', 'collectResult'],
760
+ },
761
+ doc: {
762
+ section: 'Performance optimization',
763
+ anchor: 'wasm-split',
764
+ intent: 'split Unity Wasm code into load-on-demand subpackages',
765
+ },
766
+ acceptance: [
767
+ 'requirements are above the main workflow',
768
+ 'Unity plugin update is visible as a prerequisite',
769
+ 'collection and split stages are visually distinct',
770
+ ],
771
+ notes: notes(
772
+ {
773
+ title: 'Wasm 分包',
774
+ purpose: '将 Unity Wasm 代码拆成按需加载的子包,降低首屏体积。',
775
+ whenToUse: 'Unity 小游戏需要优化冷启动或 Wasm 函数数量过多时使用。',
776
+ steps: [
777
+ '先更新 Unity 最新插件。',
778
+ '按页面要求完成函数收集。',
779
+ '生成分包配置后写回项目。',
780
+ ],
781
+ keyChecks: [
782
+ 'Unity 由于 wasmcode 形态暂不能完整预先检查,需要继续调研。',
783
+ '插件版本、客户端版本和入口配置要作为前置条件展示。',
784
+ ],
785
+ },
786
+ {
787
+ title: 'Wasm Split',
788
+ purpose: 'Split Unity Wasm code into on-demand subpackages to reduce first-screen size.',
789
+ whenToUse: 'Use it when Unity mini-games need cold-start optimization or have too many Wasm functions.',
790
+ steps: [
791
+ 'Update to the latest Unity plugin first.',
792
+ 'Complete function collection as required on the page.',
793
+ 'Generate subpackage configuration and write it back to the project.',
794
+ ],
795
+ keyChecks: [
796
+ 'Unity wasmcode cannot be fully prechecked yet and still needs investigation.',
797
+ 'Plugin version, client version, and entry configuration are visible prerequisites.',
798
+ ],
799
+ },
800
+ ),
801
+ }),
802
+ ];