# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## 项目概述

HarmonyOS NEXT（API 12+，目标 SDK `6.1.1(24)`，runtimeOS `HarmonyOS`）上的 **TSGame 游戏大厅原生外壳**。目标：用 ArkTS / ArkUI 声明式 / Stage 模型重写原 Android WebView 外壳，使现有 H5（大厅 + 全部子游戏 + 活动/收银台等网页）**一行不改**即可运行。

当前处于 **M0 脚手架阶段**：`entry/` 仍是 DevEco 默认模板（`Index.ets` 为 Hello World），尚未落地设计文档中的多模块架构。实现工作以 `docs/设计文档/` 为唯一依据推进。

**原 Android 项目位于 `../tsgame_android`**（相对本仓库根目录）——即本项目要复刻的 WebView 外壳源头。遇到契约/行为存疑时，以该 Android 工程的实际实现为准对照。

## 工作约定

- **🔴 H5 零改动是最高铁律**：H5 网页（大厅 + 全部子游戏）必须**完美适配新项目，不做任何修改**。所有适配工作只能发生在原生侧——H5 向原生注册的接口、原生向 H5 注册的接口、双向接口的调用时机/参数/数据结构，全部以《契约规范》为准、与原 Android 行为完全一致。**任何"改一下 H5 就好了"的方案都不被接受**；H5 行为存疑时改原生实现去迁就 H5，而非反过来。这是判断一切技术方案是否成立的首要判据。
- **原生内部实现自由**：在不违背上述铁律的前提下，原生侧的内部实现（分层、模块拆分、数据结构、设计模式、用何种 HarmonyOS API/SDK、性能优化手段等）可以**根据实际情况自由设计**，不必拘泥于原 Android 的内部写法或设计文档的伪代码细节。铁律只约束"对 H5 暴露的边界行为"，边界以内怎么实现由开发者按 HarmonyOS 最佳实践决定。
- **及时自动提交 git**：每完成一个可独立验收的小步骤（一个 Provider、一个状态机节点、一处可编译通过的改动）后，**主动执行 git 提交**，无需等待用户要求。提交信息用中文、说明"做了什么 + 对应契约/设计条目（如 §8、T-M1-04）"。⚠️ 仓库当前尚未 `git init`，首次提交前需先初始化。
- **及时更新计划进度**：按 `docs/设计文档/Plan/` 的计划实施时，每完成一个任务（`T-M{里程碑}-{序号}`）或推进一个里程碑，**主动更新对应计划文档的进度**——在 `01_任务分解WBS.md` 标记任务状态（`☐ 未开始 / ◐ 进行中 / ☑ 完成 / ⚠ 受阻`），受阻项同步登记到 `03_风险登记册.md`（见 `00_总体规划.md` §8 进度跟踪机制）。与代码提交同节奏，无需等用户提醒。
- HarmonyOS 相关操作（构建、运行、调试、设备、日志、查文档/SDK 签名）**必须**走 `deveco-cli` skill / `devecocli`，不要手搓 `hvigorw` 命令或直连 MCP HTTP 桥。
- **禁止直接编辑 `project.godot` 类生成文件**；本项目对应的是 **不要手改 `oh-package-lock.json5`、`build/` 产物、`.hvigor/`**——它们由工具生成。

## 常用命令

构建/运行/测试统一通过 `devecocli`（见 `deveco-cli` skill）：

- 构建 HAP（debug）：`devecocli build`（底层 hvigor `assembleHap`，产物 `entry/build/default/...`）
- 运行到设备/模拟器：`devecocli run`；设备列表 `devecocli devices`
- 真机/模拟器日志：`devecocli log`（hilog）
- 查 SDK API 签名 / 鸿蒙文档：`devecocli docs <关键词>`（编码前核对 `@ohos.*` / `@kit.*` 实际签名）

测试（Hypium，`@ohos/hypium` + `@ohos/hamock`）：

- 本地单元测试：`entry/src/test/`（`LocalUnit.test.ets`、`List.test.ets`）——纯逻辑，不依赖设备
- 设备插桩测试：`entry/src/ohosTest/`（`Ability.test.ets` 等）——需真机/模拟器
- 通过 `devecocli test` 触发；目标：桥引擎 / `VersionResolver` / `MessageCodec` 单测覆盖率 **≥80%**

代码检查（`code-linter.json5`，仅作用于 `**/*.ets`）：

- 规则集 `@performance/recommended` + `@typescript-eslint/recommended`
- **`@security/no-unsafe-*` 一组加密规则为 `error`**：禁用不安全的 AES/Hash/MAC/DH/DSA/ECDSA/RSA/3DES，写加密代码时务必遵守

## 架构（big picture，需读多文件才能掌握）

> 真正的架构在设计文档里，代码尚未落地。三份 SSOT 文档（修改实现前必读对应章节）：
> - `docs/设计文档/TSGame_原生与H5接口契约总规范.md` —— **对外不可变契约**（H5 零改动的判据：handler 名、参数、数据结构、调用时机）
> - `docs/设计文档/TSGame_HarmonyOS框架设计与开发指南.md` —— HarmonyOS 侧如何实现（分层、桥、容器、启动）
> - `docs/设计文档/Plan/` —— 落地计划：`00_总体规划` / `01_任务分解WBS`（任务 ID `T-M{里程碑}-{序号}`）/ `02_测试与验收` / `03_风险登记册`

### 分层（依赖单向向下，跨层只依赖接口）

```
① 应用/编排层  EntryAbility · StartupOrchestrator · 路由 · DI 组装根(AppModule)
② 容器层       BridgeGameContainer(大厅/子游戏) │ GenericWebContainer(通用网页)
③ 桥引擎层     BridgeController · MessageCodec · HandlerRegistry · SettingsProxy
④ 能力层       每个原生能力 = 一个 CapabilityProvider 插件(share/login/location/...)
⑤ 领域服务层   ConfigManager · ResourceManager · AppDataInjector · VersionResolver
⑥ 平台服务层   HttpClient · Downloader · Unzipper · KvStore · LocalUploadServer · TaskScheduler
横切层         Logger/Tracer · ErrorCenter · EventBus · DIContainer · Contracts(TS类型 SSOT)
```

目标多模块拆分（HAR/HSP）：`entry`(①②) / `feature_bridge`(③) / `feature_capabilities`(④) / `domain_resource`(⑤) / `platform`(⑥) / `contracts`(契约类型) / `common`(横切)。

### 三条不可违背的关键约束

1. **桥核心对能力零感知**：`feature_bridge` 不 import 任何具体能力，只持 `HandlerRegistry`；能力启动时把自己的 handler 注册进去。新增能力 = 新增一个 `CapabilityProvider`，零侵入桥核心。`contracts` HAR 用 `enum`/`interface` 固化所有 handler 名与 DTO，是全工程唯一来源（杜绝 `finsh`/`getcameraaAddress` 等拼写漂移）。
2. **出站下发必须在 UI 线程**（§5.5）：`runJavaScript` 只能在 UI 线程调用，而能力回调常在非 UI 线程。`BridgeController.dispatch` 内置 UI 线程守卫；Provider 不关心线程，任意线程 `callHandler` 最终都在 UI 线程下发。
3. **TaskPool 只搬 Sendable**（§9.1）：`@Concurrent` 任务跨线程传参/返回值必须是 Sendable，**不能传** callback / `WebviewController` / `UIAbilityContext`。下载/解压进度一律经 `emitter`/`AppStorage` 回 UI 线程，不要跨线程传函数。

### 桥协议核心（"H5 零改动"命门，100% 复刻 lzyzsd/JsBridge）

- H5→原生：`Web().onLoadIntercept` 拦截 `yy://`（含 iframe 导航）；`yy://return/` 前缀走回执，其余触发 `flushMessageQueue()`。
- **队列回传不靠 `runJavaScript` 返回值**：`_fetchQueue()` 在 H5 内把 `iframe.src` 置为 `yy://return/_fetchQueue/<队列JSON>`，再次经 `onLoadIntercept` → `handleReturnData` 路由到预登记的 `_fetchQueue` 回调。务必忠实复刻此机制。
- 原生→H5：`controller.runJavaScript("WebViewJavascriptBridge._handleMessageFromNative('"+json+"');")`；桥 JS 在 `onPageEnd` 注入（直接复用库原文件）。
- **必须设 `DefaultHandler`（空实现）**：未注册的 handler 名落到默认空实现而不抛错，是"H5 调用永不报错"的最后防线。

### 双容器模型

- **BridgeGameContainer**（大厅/子游戏，对应 Android `webviewActivity`）：挂桥协议；`app_data.js` 必须在**加载页面之前**由 `AppDataInjector` 写入（H5 同步 `<script src>` 读取），切勿放到 `onPageEnd`；`setPostUrl`/`appservice` 在首次进度 100% 时下发。子游戏切换 = 同容器 `loadUrl`，不重建组件。
- **GenericWebContainer**（通用网页，对应 `openwebActivity1`）：**不挂桥**，用 `javaScriptProxy` 注入 `settings` 对象（6 方法）+ `runJavaScript` 直调；回传走结果码 101 语义经 `emitter`/路由投回上层 Bridge 容器。

### 本期范围与占位桩

本期实现分享/登录/定位/音频/摇一摇/扫码/相机/震动/剪贴板/网络/设备等 Provider。**视频房（声网）与支付用占位桩**（`RoomStubProvider`/`PayStubProvider`，§6.5）：仍注册 handler，但 void 型空实现、有同步返回的回安全默认值、绝不触发出站推送——保证 H5 调用不报错、不卡死。**闲聊不涉及**（无 H5 桥接口）。组装根 `buildCapabilities()` 是唯一知道"全部能力"的地方，未来换回真实 Provider 即可。

### 两个最高风险"阻塞性验证"（必须最先证伪）

- **M1**：`yy://` 的 iframe 导航是否稳定触发 `onLoadIntercept`（不同 ArkWeb 版本有差异）。失败回退：`onInterceptRequest`+`WebSchemeHandler` → 或改注入 `javaScriptProxy` 同步通道（对 H5 仍透明）。
- **M2**：`file://` 加载下 H5 的 XHR/fetch 取本地资源是否可用。失败启用官方跨域方案（自定义协议 / `onInterceptRequest`）。

### 生产加固红线（附录 B）

- `setWebDebuggingAccess(true)` **仅 debug 包**（`BuildProfile.DEBUG` 守卫），release 必关。
- 密钥（微信 `AppSecret`、支付 `API_KEY`）**不入客户端**：登录走 code、支付签名走服务端。
- 明文 HTTP 域名需在 `module.json5` 网络安全配置显式放行；`gamepaywelcome` 等外部唤起 scheme 在 `abilities.skills.uris` 声明。
