@h-ai/cli 0.1.0-alpha.56 → 0.1.0-alpha.58

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 (208) hide show
  1. package/README.en.md +239 -0
  2. package/README.ja.md +239 -0
  3. package/README.md +51 -1
  4. package/dist/chunk-2H7UOFLK.js +0 -0
  5. package/dist/chunk-F4IBPVZ5.js +355 -0
  6. package/dist/chunk-F4IBPVZ5.js.map +1 -0
  7. package/dist/{chunk-O3ANVICQ.js → chunk-WUSFJFW5.js} +13 -7
  8. package/dist/chunk-WUSFJFW5.js.map +1 -0
  9. package/dist/cli-config-templates-6XA7V6CC.js +5 -0
  10. package/dist/{cli-config-templates-OWBEGBZQ.js.map → cli-config-templates-6XA7V6CC.js.map} +1 -1
  11. package/dist/{cli-skill-templates-ZIWYMS4Y.js → cli-skill-templates-45CK4RQ2.js} +3 -3
  12. package/dist/{cli-skill-templates-ZIWYMS4Y.js.map → cli-skill-templates-45CK4RQ2.js.map} +1 -1
  13. package/dist/index.js +134 -125
  14. package/dist/index.js.map +1 -1
  15. package/dist/{src-TBIET7YU.js → src-DUGLX4YB.js} +7270 -2119
  16. package/dist/src-DUGLX4YB.js.map +1 -0
  17. package/package.json +17 -17
  18. package/templates/README.md +4 -4
  19. package/templates/apps/admin/src/routes/+layout.svelte.hbs +7 -0
  20. package/templates/apps/admin/src/routes/+page.svelte.hbs +5 -4
  21. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +2 -2
  22. package/templates/apps/api/.gitignore.hbs +13 -0
  23. package/templates/apps/api/.npmrc.hbs +1 -0
  24. package/templates/apps/api/Dockerfile.hbs +6 -5
  25. package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +1 -1
  26. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +2 -0
  27. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +1 -1
  28. package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +8 -0
  29. package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +1 -1
  30. package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +7 -8
  31. package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +4 -3
  32. package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +0 -1
  33. package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/app-procedures.ts.hbs +4 -0
  34. package/templates/apps/api/apps/{{projectName}}-service/tests/service.test.ts.hbs +3 -1
  35. package/templates/apps/api/e2e/api-service.spec.ts.hbs +4 -2
  36. package/templates/apps/api/{eslint.config.js → eslint.config.js.hbs} +6 -8
  37. package/templates/apps/api/package.json.hbs +3 -3
  38. package/templates/apps/api/pnpm-workspace.yaml.hbs +26 -0
  39. package/templates/apps/api/tsconfig.base.json +0 -1
  40. package/templates/apps/fullstack/.dockerignore.hbs +3 -0
  41. package/templates/apps/fullstack/.gitignore.hbs +16 -0
  42. package/templates/apps/fullstack/.npmrc.hbs +1 -0
  43. package/templates/apps/fullstack/Dockerfile.hbs +6 -5
  44. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +2 -2
  45. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +1 -1
  46. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +5 -8
  47. package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +7 -2
  48. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +1 -34
  49. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +1 -34
  50. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +2 -2
  51. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +30 -170
  52. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +1 -1
  53. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +6 -5
  54. package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +1 -1
  55. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +48 -22
  56. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +3 -1
  57. package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +5 -8
  58. package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +6 -1
  59. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +1 -28
  60. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +1 -28
  61. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +5 -4
  62. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +10 -141
  63. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +5 -5
  64. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +3 -3
  65. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +21 -2
  66. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +2 -2
  67. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +5 -8
  68. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +6 -1
  69. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +1 -28
  70. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +1 -28
  71. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +2 -2
  72. package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +5 -143
  73. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +1 -1
  74. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +1 -1
  75. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +48 -22
  76. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +207 -17
  77. package/templates/apps/fullstack/{eslint.config.js → eslint.config.js.hbs} +6 -8
  78. package/templates/apps/fullstack/package.json.hbs +3 -3
  79. package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +2 -0
  80. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +1 -1
  81. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +66 -0
  82. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +96 -0
  83. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +3 -0
  84. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +3 -1
  85. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +5 -0
  86. package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +3 -0
  87. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +1 -1
  88. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +13 -3
  89. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_audit.yml.hbs +3 -0
  90. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_cache.yml.hbs +2 -0
  91. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +10 -3
  92. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_db.yml.hbs +3 -0
  93. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_iam.yml.hbs +21 -0
  94. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +10 -3
  95. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_storage.yml.hbs +3 -0
  96. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +10 -3
  97. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +63 -28
  98. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +26 -11
  99. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +276 -0
  100. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +29 -0
  101. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +94 -0
  102. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +6 -0
  103. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +5 -1
  104. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +98 -0
  105. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +446 -33
  106. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +48 -0
  107. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +1 -1
  108. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +19 -26
  109. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +78 -15
  110. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +78 -15
  111. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +4 -1
  112. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +3 -4
  113. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +53 -27
  114. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +73 -0
  115. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +55 -45
  116. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AuditManagement.svelte.hbs +61 -0
  117. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ProfileSettings.svelte.hbs +57 -0
  118. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/RoleManagement.svelte.hbs +49 -0
  119. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/UserManagement.svelte.hbs +174 -0
  120. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +399 -0
  121. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +7 -39
  122. package/templates/apps/fullstack/packages/{{projectName}}-shared/svelte.config.js.hbs +1 -0
  123. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +151 -0
  124. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +101 -0
  125. package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -0
  126. package/templates/apps/fullstack/playwright.config.ts.hbs +6 -0
  127. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +24 -0
  128. package/templates/apps/fullstack/tsconfig.base.json +0 -1
  129. package/templates/apps/h5/src/routes/+layout.svelte.hbs +4 -0
  130. package/templates/apps/h5/src/routes/+page.svelte.hbs +3 -2
  131. package/templates/apps/mobile-app/index.html.hbs +2 -2
  132. package/templates/apps/mobile-app/src/App.svelte.hbs +6 -2
  133. package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +13 -0
  134. package/templates/apps/website/src/routes/+layout.svelte.hbs +8 -2
  135. package/templates/apps/website/src/routes/+page.svelte.hbs +4 -3
  136. package/templates/base/.npmrc.hbs +1 -0
  137. package/templates/base/Dockerfile.hbs +9 -8
  138. package/templates/base/e2e/app.spec.ts.hbs +1 -0
  139. package/templates/base/eslint-rules.js +45 -0
  140. package/templates/base/eslint.config.js.hbs +6 -8
  141. package/templates/base/package.json.hbs +39 -42
  142. package/templates/base/pnpm-workspace.yaml.hbs +26 -0
  143. package/templates/base/src/app.d.ts.hbs +4 -0
  144. package/templates/base/src/hooks.server.ts.hbs +0 -8
  145. package/templates/base/src/lib/server/init.ts.hbs +26 -5
  146. package/templates/base/src/routes/+layout.server.ts.hbs +18 -0
  147. package/templates/base/tests/scaffold.test.ts.hbs +21 -1
  148. package/templates/base/vite.config.ts.hbs +21 -0
  149. package/templates/features/ai/routes/api/chat/+server.ts +6 -7
  150. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +1 -1
  151. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +1 -1
  152. package/templates/features/iam/routes-shared/api/auth/login/+server.ts +14 -10
  153. package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +6 -4
  154. package/templates/features/storage/routes/api/upload/+server.ts +10 -8
  155. package/templates/skills/AGENTS.md +9 -8
  156. package/templates/skills/CLAUDE.md +0 -10
  157. package/templates/skills/bridges/admin/AGENTS.md +8 -0
  158. package/templates/skills/bridges/admin/copilot-instructions.md +2 -0
  159. package/templates/skills/bridges/api/AGENTS.md +8 -1
  160. package/templates/skills/bridges/api/copilot-instructions.md +2 -0
  161. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +21 -4
  162. package/templates/skills/bridges/fullstack/copilot-instructions.md.hbs +5 -0
  163. package/templates/skills/bridges/h5/AGENTS.md +8 -0
  164. package/templates/skills/bridges/h5/copilot-instructions.md +2 -0
  165. package/templates/skills/bridges/mobile-app/AGENTS.md +8 -0
  166. package/templates/skills/bridges/mobile-app/copilot-instructions.md +2 -0
  167. package/templates/skills/bridges/website/AGENTS.md +8 -0
  168. package/templates/skills/bridges/website/copilot-instructions.md +2 -0
  169. package/templates/skills/copilot-instructions.md +2 -0
  170. package/templates/skills/hai-api-client/SKILL.md +2 -0
  171. package/templates/skills/hai-app-create/SKILL.md +9 -7
  172. package/templates/skills/hai-app-create/development.md +72 -0
  173. package/templates/skills/hai-app-create/reference.md +44 -32
  174. package/templates/skills/hai-app-review/SKILL.md +50 -144
  175. package/templates/skills/hai-app-tests/SKILL.md +3 -1
  176. package/templates/skills/hai-app-tests/reference.md +47 -27
  177. package/templates/skills/hai-build/SKILL.md +5 -4
  178. package/templates/skills/hai-build/reference.md +56 -34
  179. package/templates/skills/hai-ci/SKILL.md +8 -15
  180. package/templates/skills/hai-core/SKILL.md +2 -0
  181. package/templates/skills/hai-core/reference.md +6 -4
  182. package/templates/skills/hai-framework-sync/SKILL.md +8 -2
  183. package/templates/skills/hai-pr-review/SKILL.md +5 -4
  184. package/templates/skills/hai-reldb/SKILL.md +1 -0
  185. package/templates/skills/hai-reldb/reference.md +3 -0
  186. package/templates/skills/hai-scheduler/SKILL.md +3 -0
  187. package/templates/skills/hai-serv/SKILL.md +2 -0
  188. package/templates/skills/hai-serv/reference.md +18 -2
  189. package/templates/skills/hai-storage/SKILL.md +3 -1
  190. package/templates/skills/hai-ui/SKILL.md +6 -0
  191. package/templates/skills/hai-ui/reference.md +7 -4
  192. package/templates/skills/hai-vecdb/reference.md +53 -49
  193. package/dist/chunk-O3ANVICQ.js.map +0 -1
  194. package/dist/chunk-WUYLYCW2.js +0 -237
  195. package/dist/chunk-WUYLYCW2.js.map +0 -1
  196. package/dist/cli-config-templates-OWBEGBZQ.js +0 -5
  197. package/dist/src-TBIET7YU.js.map +0 -1
  198. package/templates/apps/fullstack/apps/{{projectName}}-app/tests/api.test.ts.hbs +0 -28
  199. package/templates/apps/fullstack/apps/{{projectName}}-desktop/tests/api.test.ts.hbs +0 -28
  200. package/templates/apps/fullstack/apps/{{projectName}}-web/tests/api.test.ts.hbs +0 -55
  201. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/LanguageSwitcher.svelte.hbs +0 -27
  202. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +0 -18
  203. package/templates/skills/bridges/admin/CLAUDE.md +0 -11
  204. package/templates/skills/bridges/api/CLAUDE.md +0 -11
  205. package/templates/skills/bridges/fullstack/CLAUDE.md.hbs +0 -5
  206. package/templates/skills/bridges/h5/CLAUDE.md +0 -11
  207. package/templates/skills/bridges/mobile-app/CLAUDE.md +0 -11
  208. package/templates/skills/bridges/website/CLAUDE.md +0 -11
@@ -2,18 +2,20 @@
2
2
 
3
3
  从 [SKILL.md](SKILL.md) 选择主题后读取对应小节。代码片段展示 API 用法;省略的业务变量、schema、依赖与 return 上下文需由应用补齐。
4
4
 
5
- > 面向 AI 助手的 TDD 测试指南。**测试先行**:先写测试定义行为,再写实现让测试通过。涵盖 Vitest 单元测试与 Playwright E2E 测试。
5
+ 新增/改变业务行为或修复缺陷时先用目标用例定义行为,再实现。按 [development.md](../hai-app-create/development.md) 的需求与安全边界选择测试层;纯文案、格式、文档或无行为变化的可逆低影响修改按影响验证,不补只匹配文本/结构的镜像测试。
6
6
 
7
7
  ## 适用场景
8
8
 
9
9
  - 以 TDD 方式开发新功能(先写测试 → 确认失败 → 再实现 → 确认通过)
10
- - 为 `$lib/server/services/` 编写服务层单元测试
10
+ - 为当前架构的公共服务入口编写单元/集成测试
11
11
  - 为 API 端点编写 E2E 测试(Playwright)
12
12
  - 为页面交互编写 UI E2E 测试(Playwright)
13
13
  - 为工具函数、Schema 校验编写单元测试
14
- - 需要提升测试覆盖率
14
+ - 补齐有具体行为风险的验证缺口;覆盖率是定位线索,不是验收目标
15
15
 
16
- ## TDD 核心工作流(必须严格遵循)
16
+ ## 行为验证与 TDD 工作流
17
+
18
+ 不要求每个改动同时新增单元与 E2E。先复用现有 fixture 与目标用例,按变化选最小适用层;跨 contract/服务/客户端或 UI 的关键流程仍需相应集成/端到端验证。
17
19
 
18
20
  ### 阶段一:需求分析(Red 前准备)
19
21
 
@@ -21,16 +23,17 @@
21
23
  2. **拆分测试点**:将需求转化为可验证的测试用例清单
22
24
  3. **确定测试类型**:
23
25
  - **单元测试(Vitest)**:服务层、工具函数、Schema 校验、HaiResult 处理
24
- - **E2E 测试(Playwright)**:API 端点、页面交互、认证流程、跨模块集成
26
+ - **集成测试**:contract/procedure、事务、持久化、生命周期/失败清理、模块配置的真实组合
27
+ - **E2E 测试(Playwright)**:API 边界、页面交互、认证流程与跨层用户路径
25
28
 
26
29
  ### 阶段二:Red — 编写失败的测试
27
30
 
28
- 1. **编写单元测试**:覆盖正常路径、边界路径、权限路径、错误路径
29
- 2. **编写 E2E 测试**:覆盖 API 端点和关键用户交互流程
31
+ 1. **编写目标用例**:在适用的单元/集成/E2E 层验证目标变化,不重复创建其它层仅为打勾
32
+ 2. 对本次相关的正常、输入边界、越权/跨租户、依赖失败、事务/幂等/清理场景给出可观察断言;纯工具无需添加无关权限路径
30
33
  3. **运行测试确认新增目标用例因预期行为缺失而失败(既有回归保持通过)**:
31
34
  ```bash
32
- pnpm --filter <app-name> test # 单元测试 — 新增目标用例应 FAIL,既有回归应 PASS
33
- pnpm --filter <app-name> test:e2e # E2E 测试 — 新增目标用例应 FAIL,既有回归应 PASS
35
+ pnpm --filter <app-name> test # 目标位于单元/集成时使用
36
+ pnpm --filter <app-name> test:e2e # 目标位于 E2E 时使用;脚本以实际 package.json 为准
34
37
  ```
35
38
  4. 新增用例若已通过,先确认现有实现是否已满足需求;仅在用例没有覆盖目标行为时修正
36
39
 
@@ -39,7 +42,7 @@
39
42
  1. 参照 `hai-app-create` 技能编写实现代码
40
43
  2. 每实现一个功能点,立即运行对应测试确认通过
41
44
  3. 只写让测试通过的最小代码,不做过度设计
42
- 4. 运行全部测试确认通过:
45
+ 4. 运行受影响测试及必要回归确认通过(按影响选择范围):
43
46
  ```bash
44
47
  pnpm --filter <app-name> test # 单元测试 — 应全部 PASS
45
48
  pnpm --filter <app-name> test:e2e # E2E 测试 — 应全部 PASS
@@ -48,11 +51,13 @@
48
51
  ### 阶段四:Refactor — 重构优化
49
52
 
50
53
  1. 参照 `hai-app-review` 技能审查代码规范
51
- 2. 重构后再次运行所有测试确认仍然通过
52
- 3. 运行质量门禁:`pnpm typecheck && pnpm lint && pnpm test`
54
+ 2. 重构后执行受影响测试与必要回归,确认已有行为保持通过
55
+ 3. 从当前 scripts 选择门禁,按 `typecheck → lint → build(构建/配置/跨包变更)→ test → 相关 E2E` 执行;PowerShell 使用 `pnpm.cmd`
53
56
 
54
57
  ## 测试目录约定
55
58
 
59
+ 以下是常见组织方式;沿当前应用/workspace 的测试目录、alias 与脚本,不为目录一致性移动已有测试。
60
+
56
61
  ```
57
62
  tests/ # 单元测试(Vitest)
58
63
  services/
@@ -73,27 +78,27 @@ e2e/ # E2E 测试(Playwright)
73
78
 
74
79
  ## 核心规则
75
80
 
76
- 1. **测试先行**:先写测试定义预期行为,再写实现代码。
81
+ 1. **行为测试先行**:新增/改变业务行为和修复缺陷时先定义目标用例;纯文案/格式/文档按影响验证。
77
82
  2. **统一入口**:通过框架模块公共 API 测试(`reldb.sql`、`iam.auth`),不直接调用内部实现。
78
83
  3. **从实际场景出发**:测试用例验证真实业务行为,不做形式覆盖。
79
84
  4. **先审查后修复**:测试不通过时先审查业务逻辑是否有问题,不直接修改测试迎合通过。
80
- 5. **Mock 外部依赖**:单元测试中,数据库、缓存、网络请求使用 mock,不直连真实服务。
81
- 6. **E2E 真实环境**:E2E 测试运行在完整应用环境中,不使用 mock。
85
+ 5. **明确隔离层**:单元测试沿真实注入边界 mock 外部依赖;DB/缓存集成用内存 SQLite 或隔离环境/Testcontainers,不能用 mock 证明真实持久化/事务。
86
+ 6. **区分证据**:端到端运行完整应用;可用受控外部依赖验证确定性错误路径,但报告替身范围。浏览器通过不等于真实 provider 通过;真实数据库/付费 provider/原生平台各自保留实际执行结果,缺环境说明未验证。
82
87
 
83
88
  ## 覆盖范围
84
89
 
85
- 每个功能至少覆盖以下路径(单元测试 + E2E 按需):
90
+ 按本次改变的行为选择适用路径;下表是设计依据,不要求每个路径在单元与 E2E 重复一遍。纯函数不必虚构权限场景,受保护资源则不能省掉未登录/缺权限与跨用户/租户验收:
86
91
 
87
92
  | 路径 | 说明 | 单元测试示例 | E2E 测试示例 |
88
93
  | -------- | ------------------------ | ------------------ | ----------------------- |
89
94
  | 正常路径 | 核心功能可用 | 创建用户成功 | POST /api/users → 201 |
90
95
  | 边界路径 | 非法输入、空值、格式错误 | 空名称、超长字符串 | 空表单提交 → 校验提示 |
91
- | 权限路径 | 未认证、无权限 | 未登录调用服务 | 未登录访问 → 401/重定向 |
96
+ | 权限路径 | 未认证、无权限 | 未登录调用服务 | 检查真实失败包络/HTTP 状态,kit 页面按实际策略重定向 |
92
97
  | 错误路径 | 服务异常、数据库错误 | DB 失败时的 HaiResult | 服务不可用 → 错误提示页 |
93
98
 
94
99
  ## 单元测试(Vitest)
95
100
 
96
- ### 服务层测试模板
101
+ ### SQLite 持久化集成示例
97
102
 
98
103
  ```typescript
99
104
  import { reldb } from '@h-ai/reldb'
@@ -109,7 +114,10 @@ beforeAll(async () => {
109
114
  })
110
115
  expect(table.success).toBe(true)
111
116
  })
112
- afterAll(async () => { await reldb.close() })
117
+ afterAll(async () => {
118
+ const closed = await reldb.close()
119
+ expect(closed.success).toBe(true)
120
+ })
113
121
 
114
122
  describe('article persistence', () => {
115
123
  it('creates and reads the stored article', async () => {
@@ -123,7 +131,7 @@ describe('article persistence', () => {
123
131
  })
124
132
  ```
125
133
 
126
- 服务层另测权限、校验和 DB 失败透传;mock 必须沿真实注入边界或 CRUD 仓库实例配置,create 返回 ExecuteResult,不能伪造为实体。
134
+ 本例验证框架真实持久化,不代替应用服务验收。应用另测相关权限、校验和 DB 失败透传;mock 必须沿真实注入边界或 CRUD 仓库实例配置,create 返回 ExecuteResult,不能伪造为实体。
127
135
 
128
136
  ### Schema 校验测试模板
129
137
 
@@ -166,7 +174,7 @@ describe('CreateUserSchema', () => {
166
174
 
167
175
  ### Playwright 配置
168
176
 
169
- 项目中应有 `playwright.config.ts`(由 CLI 生成):
177
+ 优先复用 CLI 已生成的 `playwright.config.ts`。下列为 SvelteKit preview 示例;API/fullstack/Vite 使用自身已有 webServer/服务组合与 scripts,不照搬 `pnpm preview`:
170
178
 
171
179
  ```typescript
172
180
  // playwright.config.ts
@@ -226,6 +234,8 @@ export default defineConfig({
226
234
 
227
235
  ### E2E 工具函数模板
228
236
 
237
+ 以下登录路径、表单字段与 API 仅作 SvelteKit 示例,必须替换为当前应用路由/认证流程;API service/typed client 测试从现有 contract 读取路径,不维护第二份路由常量。
238
+
229
239
  ```typescript
230
240
  // e2e/helpers.ts
231
241
  import type { APIRequestContext, Page } from '@playwright/test'
@@ -277,6 +287,8 @@ export async function registerAndLogin(
277
287
 
278
288
  ### API 端点 E2E 测试模板
279
289
 
290
+ 下例是返回 kit Response 的 SvelteKit 端点。serv/oRPC 普通 procedure 可能以 HTTP 200 返回失败 HaiResult,需同时检查 `success/error.code`;不能把 `error.httpStatus` 当作 response.status,也不能统一套用下列 401/201 断言。输入校验与传输错误另按实际状态测试。
291
+
280
292
  ```typescript
281
293
  // e2e/articles-api.spec.ts
282
294
  import { expect, test } from '@playwright/test'
@@ -359,6 +371,8 @@ test.describe('Articles Page', () => {
359
371
 
360
372
  ## TDD 用例设计策略
361
373
 
374
+ 以下展示候选验证点,实际按职责和已有用例选择;不要求将同一输入规则在所有层重复实现和测试。
375
+
362
376
  ### 从需求到测试用例的转换
363
377
 
364
378
  ```
@@ -367,9 +381,9 @@ test.describe('Articles Page', () => {
367
381
  ↓ 拆分测试点
368
382
 
369
383
  单元测试(Vitest):
370
- ✅ 创建文章成功返回 HaiResult.ok
371
- ✅ 空标题返回 HaiResult.err + VALIDATION_FAILED
372
- ✅ 超长标题(>100 字符)返回 HaiResult.err
384
+ ✅ 创建文章成功返回 ok(data)
385
+ ✅ 空标题被当前边界 Schema 拒绝
386
+ ✅ 超长标题(>100 字符)被拒绝
373
387
  ✅ DB 异常时透传错误
374
388
 
375
389
  Schema 测试(Vitest):
@@ -388,10 +402,11 @@ E2E 测试(Playwright):
388
402
 
389
403
  ## 断言规范
390
404
 
391
- - 始终校验 `result.success`
405
+ - HaiResult 型 API 校验 `result.success`;其它返回、显式抛错与流式 API 按实际签名验证
392
406
  - 失败时校验 `error.code`(不只检查 `success === false`)
393
407
  - 使用类型缩窄后访问 data 或 error
394
- - E2E 断言使用 Playwright 内置 expect 匹配器
408
+ - E2E 断言使用 Playwright 内置 expect 匹配器;同时检查用户可见结果和必要持久化状态,不能只断言 HTTP 200、按钮点击或成功提示
409
+ - 失败验收检查错误码/状态与“没有副作用”;事务中途失败、重复回调/写入、取消/关闭等按需求检查一致性与资源退出
395
410
 
396
411
  ```typescript
397
412
  // ✅ 单元测试断言
@@ -421,6 +436,8 @@ await expect(page).toHaveURL('/admin/articles')
421
436
 
422
437
  ## 质量门禁
423
438
 
439
+ 从当前 package.json 确认实际脚本和 workspace 名称,按变更影响选择;不要为格式/文档改动运行无关 provider 或新增镜像测试。记录执行范围、mock/真实环境、退出结果与未验证原因。
440
+
424
441
  ```bash
425
442
  # 运行单元测试
426
443
  pnpm --filter <app-name> test
@@ -432,7 +449,10 @@ pnpm --filter <app-name> test:e2e
432
449
  pnpm --filter <app-name> test:coverage
433
450
 
434
451
  # 全量门禁
435
- pnpm typecheck && pnpm lint && pnpm test
452
+ pnpm typecheck
453
+ pnpm lint
454
+ pnpm build # 构建/配置/跨包变更
455
+ pnpm test
436
456
  ```
437
457
 
438
458
  ## 相关 Skills
@@ -17,9 +17,10 @@ description: "定位 hai 应用架构、模块依赖、初始化顺序、构建
17
17
 
18
18
  ## 使用路径
19
19
 
20
- - 先读当前 package.json 和 README,识别 SvelteKit / API workspace / Vite SPA / 原生 App,按实际 scripts 验证。
21
- - core → reldb/cache 等基础依赖 → iam/ai 等业务模块;逐步检查初始化,失败清理已创建资源。
22
- - Node 最低版本、Turbo 缓存 env/globalDependencies、build:clean 与框架构建模板保持同步。
20
+ - 先读当前 package.json、lockfile 与 README,识别 SvelteKit / API workspace / fullstack / Vite SPA / 原生 App,按实际 scripts 验证。
21
+ - 功能开发先用 [development.md](../hai-app-create/development.md) 把需求匹配到当前版本的框架能力与配置;再读取所选模块 skill 和公开类型。
22
+ - 有生命周期的模块按真实依赖初始化、检查结果并反序清理;core、纯函数和工厂不套用相同生命周期。
23
+ - 构建任务检查当前 engines、适配器、环境变量、缓存与目标产物,不能照搬框架仓库私有构建命令。
23
24
 
24
25
  ## 按需参考
25
26
 
@@ -28,6 +29,6 @@ description: "定位 hai 应用架构、模块依赖、初始化顺序、构建
28
29
  - 适用场景
29
30
  - 项目架构
30
31
  - 技能导航
31
- - TDD 开发工作流(强制)
32
+ - 行为开发工作流
32
33
  - 统一编码规范
33
34
  - 标准工作流
@@ -2,13 +2,9 @@
2
2
 
3
3
  从 [SKILL.md](SKILL.md) 选择主题后读取对应小节。代码片段展示 API 用法;省略的业务变量、schema、依赖与 return 上下文需由应用补齐。
4
4
 
5
- 框架开发、CLI、服务端最低 Node.js 版本统一为 22.12.0;包与脚手架 engines、共享 node22 编译目标和 CI 最低版本必须同步。不再按 Node 20 编写兼容分支。
5
+ 应用 Node/工具链要求以当前 `package.json.engines`、lockfile 与 CI 为准。使用 Turbo 时核对影响产物的环境变量、共享配置和模式切换清理策略,并验证实际产物;不要假定应用使用框架仓库的 tsup/Turbo 私有脚本。
6
6
 
7
- tsup 包的 Turbo `build` 依赖不缓存的 `build:clean`(仅清本包 dist),再执行构建或恢复缓存。不要移除此步骤:Turbo 缓存恢复不会自动移除另一模式的多余文件。
8
-
9
- 使用 Turbo 时,影响构建的环境变量必须进入任务 `env`,共享构建配置进入 `globalDependencies`。框架的 `HAI_DOCKER_PROD_BUILD=true` 关闭声明和 sourcemap,应与普通构建使用不同缓存;PUBLIC/VITE/TAURI 变量同样参与构建缓存。切换后验证实际产物并恢复普通开发构建。
10
-
11
- > 本技能是 hai-framework 应用开发的起点。帮助理解项目结构、定位正确的技能、并遵循 **TDD 驱动的标准工作流**。支持 SSR Web、SPA、Android/iOS 原生 App 等多端构建。
7
+ 本技能帮助识别应用架构、依赖和技能。日常开发决策、安全边界与能力选择见 [development.md](../hai-app-create/development.md)。
12
8
 
13
9
  ## 适用场景
14
10
 
@@ -20,26 +16,41 @@ tsup 包的 Turbo `build` 依赖不缓存的 `build:clean`(仅清本包 dist
20
16
 
21
17
  ## 项目架构
22
18
 
19
+ ### 先辨别当前项目
20
+
21
+ | 架构 | 接口/服务 | UI 与客户端 | 常见位置(以当前项目为准) |
22
+ | --- | --- | --- | --- |
23
+ | SvelteKit | `@h-ai/kit`、文件路由与 server services | Svelte 组件与既有数据加载 | `src/routes/`、`src/lib/server/` |
24
+ | API workspace | `@h-ai/api-contract` + `@h-ai/serv` | 无需页面 | `apps/*-contract`、`apps/*-service` |
25
+ | fullstack | contract + serv,共享业务结构 | Vite Svelte Web/所选原生前端,typed client | `packages/*-contract`、`packages/*-serv`、`packages/*-shared`、`apps/*` |
26
+ | Vite SPA/原生 | 远端服务 contract | `@h-ai/api-client` 与适用平台适配 | `src/App.svelte`、`src/lib/api.ts` 或 shared 客户端 |
27
+
28
+ 不要从目录名称推断运行环境;沿入口、导入与 scripts 核实。下列 SvelteKit 示例只适用于对应项目。
29
+
23
30
  ### 技术栈
24
31
 
25
32
  | 层次 | 技术 |
26
33
  | -------- | ------------------------------ |
27
- | 框架 | SvelteKit 2 + Svelte 5 (Runes) |
34
+ | UI | Svelte 5 (Runes);SvelteKit 或 Vite 以项目为准 |
28
35
  | 样式 | TailwindCSS 4 + DaisyUI 5 |
29
- | 语言 | TypeScript 5.7+ (strict) |
36
+ | 语言 | TypeScript 6 / 7 (strict) |
30
37
  | 构建 | Vite + tsup |
31
- | 包管理 | pnpm |
38
+ | 包管理 | pnpm 12 |
32
39
  | 单元测试 | Vitest |
33
40
  | E2E 测试 | Playwright |
34
- | 原生 App | Capacitor 7 |
41
+ | 原生 App | Capacitor / Tauri / 小程序适配按当前项目选择 |
35
42
  | 公共 API | oRPC contract + Hono + typed client |
36
43
  | 认证 | Bearer access token + httpOnly refresh cookie(浏览器推荐) |
37
44
 
38
- ### 多端构建模式
45
+ pnpm 专属配置放在 `pnpm-workspace.yaml`,`.npmrc` 仅用于注册表与认证。Docker 缓存层使用 `pnpm fetch` 读取锁文件;pnpm 12 的该命令不支持 `--frozen-lockfile`。后续仍通过 `pnpm install --offline --frozen-lockfile` 校验清单与锁文件一致。容器裁剪用 `pnpm pm deploy --filter <服务包> --prod <目标目录>`,确保执行内置命令,避免项目同名 `deploy` 脚本覆盖它。
46
+
47
+ ### SvelteKit Adapter 模式
48
+
49
+ 仅在项目实际使用 SvelteKit 和 `@h-ai/kit/adapter` 时使用;Vite SPA 不配置 SvelteKit adapter,fullstack 各前端按自身 scripts 构建。
39
50
 
40
51
  | 模式 | Adapter | 认证方式 | 部署目标 |
41
52
  | ------- | -------------- | --------------------- | ----------------------- |
42
- | SSR Web | adapter-node | Bearer access token + Cookie | Node.js 服务器 |
53
+ | SSR Web | adapter-node | 项目现有 Cookie/会话管道 | Node.js 服务器 |
43
54
  | SPA | adapter-static | Bearer access token + httpOnly refresh cookie | CDN / 静态托管 |
44
55
  | Android | adapter-static | Bearer access token + Capacitor secure storage | Capacitor → Android APK |
45
56
  | iOS | adapter-static | Bearer access token + Capacitor secure storage | Capacitor → iOS IPA |
@@ -60,7 +71,7 @@ const config = {
60
71
  - `VITE_ADAPTER=node`(默认)→ adapter-node(SSR)
61
72
  - `VITE_ADAPTER=static` → adapter-static(SPA / 原生 App)
62
73
 
63
- ### 目录结构
74
+ ### SvelteKit 目录示例
64
75
 
65
76
  ```
66
77
  项目根/
@@ -80,7 +91,6 @@ const config = {
80
91
  capacitor.ts # Capacitor 初始化(原生 App)
81
92
  server/
82
93
  init.ts # 模块初始化入口(单例,SSR)
83
- procedures/ # 应用私有 oRPC procedures(仅 API Service 场景)
84
94
  paraglide/ # i18n 生成文件(禁止手动修改)
85
95
  components/ # 应用组件
86
96
  routes/
@@ -100,12 +110,12 @@ const config = {
100
110
  ```
101
111
  core(基础能力:配置、日志、i18n、HaiResult)
102
112
  ├── crypto(加密:SM2/SM3/SM4)
103
- ├── db(数据库:SQLite/PostgreSQL/MySQL)
113
+ ├── reldb(数据库:SQLite/PostgreSQL/MySQL)
104
114
  ├── cache(缓存:内存/Redis)
105
115
  ├── storage(存储:本地/S3)
106
116
  ├── ai(AI:LLM/MCP/Agent)
107
- ├── iam(身份管理)← 依赖 crypto + db + cache
108
- ├── payment(支付)← 依赖 db + crypto
117
+ ├── iam(身份管理)← 依赖 crypto + reldb + cache
118
+ ├── payment(支付)← 依赖 reldb + crypto
109
119
  ├── api-contract(公共 HTTP API 契约)← 纯定义,依赖 core + zod + oRPC contract
110
120
  ├── serv(Hono + oRPC API Service)← 依赖 api-contract;features 按需依赖 iam/storage/ai
111
121
  ├── kit(SvelteKit 集成)← Hook / guard / validate / response,不定义公共 contract
@@ -114,6 +124,8 @@ core(基础能力:配置、日志、i18n、HaiResult)
114
124
  └── ui(UI 组件库)← 依赖 core
115
125
  ```
116
126
 
127
+ 这是常见关联;具体配置/依赖以所选模块当前版本为准。其它能力(reach/audit/scheduler/datapipe/vecdb)及同模块 feature 的任务导航见 [需求能力表](../hai-app-create/development.md#将需求映射到现有能力)。
128
+
117
129
  ### 模块初始化顺序
118
130
 
119
131
  #### SSR 模式(hooks.server.ts)
@@ -151,14 +163,16 @@ if (!identity.success) {
151
163
  // 检查关闭结果;core 无 close,kit/api-contract/serv 不需要 init。
152
164
  ```
153
165
 
154
- #### SPA / 原生 App 模式(src/lib/api.ts)
166
+ #### SPA / 原生 App 模式(已有 api.ts 或 shared 客户端)
167
+
168
+ 复用当前项目初始化函数、API base 运行时配置和 TokenStorage;以下仅展示浏览器 Cookie 模式。原生端按 `hai-api-client` / `hai-capacitor` 配置安全存储,不用 localStorage 持久化敏感 token。
155
169
 
156
170
  ```typescript
157
171
  import { apiClient } from '@h-ai/api-client'
158
172
 
159
173
  export async function initApi() {
160
174
  return apiClient.init({
161
- baseUrl: import.meta.env.VITE_API_BASE_URL,
175
+ baseUrl: configuredApiBase, // 来自当前项目已校验的运行时配置
162
176
  auth: {}, // 浏览器默认 httpOnly cookie;原生 App 传入 Capacitor TokenStorage
163
177
  timeout: 15_000,
164
178
  })
@@ -201,6 +215,8 @@ logging:
201
215
 
202
216
  ### 模块使用(API 与集成)
203
217
 
218
+ 先按 [development.md 的需求能力表](../hai-app-create/development.md#将需求映射到现有能力) 匹配需求,再查以下 API 入口;不用通读所有技能。
219
+
204
220
  | 任务 | 技能 | 触发关键词 |
205
221
  | --------------------- | ---------------- | ------------------------------------------------- |
206
222
  | 配置/日志/i18n/HaiResult | `hai-core` | core.init, core.logger, core.config, HaiResult |
@@ -222,16 +238,16 @@ logging:
222
238
 
223
239
  | 任务 | 技能 | 触发关键词 |
224
240
  | ---------------------- | ---------------- | -------------------------------------- |
225
- | 创建页面/组件/API/模型 | `hai-app-create` | 新建页面, 添加组件, API 端点, 数据模型 |
241
+ | 新增/修改/修复应用功能 | `hai-app-create` | 页面, 组件, API, 模型, 功能修复 |
226
242
  | 代码审查与规范化 | `hai-app-review` | 审查, review, 规范, 优化 |
227
243
  | 编写/补充测试 | `hai-app-tests` | 测试, test, 单测, 覆盖率, TDD, E2E |
228
244
  | CI/CD 与质量门禁 | `hai-ci` | CI, CD, GitHub Actions, workflow, secret scan |
229
245
  | PR / Issue 交付审查 | `hai-pr-review` | PR, pull request, issue, CODEOWNERS, 自动 Review, AI Review |
230
246
  | hai-framework 同步 | `hai-framework-sync` | hai-framework, skills 同步, framework:use:local, framework:watch |
231
247
 
232
- ## TDD 开发工作流(强制)
248
+ ## 行为开发工作流
233
249
 
234
- > 所有新功能开发必须遵循 TDD:**先写测试 → 确认失败 → 再实现 → 确认通过 → 重构**。
250
+ 新增/改变行为时:先写有意义的目标用例 → 确认因目标行为缺失失败 → 实现 → 通过 → 审查。纯文案、格式和文档变化按影响验证,不机械新增单元与 E2E 测试。
235
251
 
236
252
  ### 完整流程
237
253
 
@@ -262,7 +278,9 @@ pnpm --filter <app-name> test
262
278
  pnpm --filter <app-name> test:e2e
263
279
 
264
280
  # Refactor:质量门禁
265
- pnpm typecheck && pnpm lint && pnpm test
281
+ pnpm typecheck
282
+ pnpm lint
283
+ pnpm test
266
284
  ```
267
285
 
268
286
  ## 统一编码规范
@@ -271,7 +289,8 @@ pnpm typecheck && pnpm lint && pnpm test
271
289
 
272
290
  - **禁止 `any`**:不确定类型用 `unknown`,在边界处做类型缩窄
273
291
  - **禁止 `console.log`**:使用 `core.logger`(trace/debug/info/warn/error/fatal)
274
- - **禁止硬编码密钥**:使用环境变量,新增变量需在 `.env` 中写入占位符
292
+ - **禁止硬编码密钥**:使用服务端配置/环境变量;新增变量在 `.env.example` 中写入占位符,PUBLIC/VITE 变量不得包含密钥
293
+ - **禁止无说明的 `as unknown as T`**:必要第三方断言写明依据;代码注释中文、日志英文并脱敏
275
294
  - **禁止硬编码用户文案**:所有用户可见文本必须使用 i18n key
276
295
  - **禁止修改 `src/lib/paraglide`** 生成文件
277
296
 
@@ -292,11 +311,12 @@ return kit.response.ok(result.data)
292
311
 
293
312
  ### 质量门禁
294
313
 
295
- 每次变更后按顺序执行:
314
+ 按当前项目已定义的 scripts 和变更影响执行;PowerShell 使用 `pnpm.cmd`:
296
315
 
297
316
  ```bash
298
317
  pnpm typecheck # TypeScript 类型检查
299
318
  pnpm lint # ESLint 检查
319
+ pnpm build # 构建/配置/模板/跨包契约变更
300
320
  pnpm test # Vitest 单元测试
301
321
  ```
302
322
 
@@ -304,14 +324,15 @@ pnpm test # Vitest 单元测试
304
324
 
305
325
  ### 变更前:需求分析 + 测试设计
306
326
 
307
- 1. 列出将修改的文件路径
308
- 2. 确认哪些类型/接口会变
309
- 3. 搜索确认引用关系(避免遗漏)
310
- 4. **设计测试用例清单**(单元测试 + E2E 测试)
327
+ 1. 按 development.md 匹配适用框架能力、已有 feature/配置和实际版本,说明必要自定义缺口
328
+ 2. 列出将修改的文件路径
329
+ 3. 确认哪些类型/接口会变
330
+ 4. 搜索确认引用关系(避免遗漏)
331
+ 5. 按行为风险设计测试与安全验收场景
311
332
 
312
333
  ### 变更中:TDD 三步走
313
334
 
314
- 1. **Red**:编写单元测试(Vitest)+ E2E 测试(Playwright),确认新增目标用例失败、既有回归通过
335
+ 1. **Red**:为新增/改变行为编写适用的单元/集成/E2E 测试,确认目标用例失败、既有回归通过
315
336
  2. **Green**:按技能指引完成功能实现,逐步让测试通过
316
337
  3. **Refactor**:审查代码规范、重构优化
317
338
 
@@ -319,8 +340,9 @@ pnpm test # Vitest 单元测试
319
340
 
320
341
  1. `pnpm typecheck` 通过
321
342
  2. `pnpm lint` 通过
322
- 3. `pnpm test` 通过(单元测试)
323
- 4. `pnpm --filter <app-name> test:e2e` 通过(E2E 测试)
324
- 5. 搜索确认所有引用点已更新
343
+ 3. 构建/配置/跨包变更 `pnpm build` 通过
344
+ 4. `pnpm test` 通过(单元测试)
345
+ 5. UI/路由/端到端改动执行相应 `test:e2e`;从 package.json 确认入口
346
+ 6. 搜索确认所有引用点已更新,报告未验证边界
325
347
 
326
- 原生交付必须单独执行 Tauri/Gradle/Xcode 打包,并在目标 OS/设备验证安装启动、登录/退出、重启会话、安全 TokenStore、真实 API 域名与覆盖升级。Web 构建/E2E 不代替原生验收。保存提交、包 hash、平台/工具链及逐项结果;缺平台写未验证,禁止静默 skip。hai-framework 仓库参考 `.github/workflows/native.yml` 与 desktop-app / mobile-app README 的「原生交付与验收」章节。
348
+ 涉及原生交付时按当前项目 Tauri/Gradle/Xcode 等实际入口打包,在目标 OS/设备验证安装启动、会话、安全 TokenStorage、API 域名及覆盖升级。Web 构建/E2E 不代替原生验收;记录平台/工具链与结果,缺平台写未验证。
@@ -7,14 +7,6 @@ description: "维护 hai 应用的 CI/CD、GitHub Actions、质量门禁和凭
7
7
 
8
8
  ## 能力契约
9
9
 
10
- 框架完整质量门禁在 Node.js 22.12.0(声明的最低版本)执行;升级 engines 时同步 CI、README 和脚手架,不能只在更高版本通过后宣称最低版本通过。
11
-
12
- 框架发布通过实际 npm 精确版本和 GitHub Release 判断完成,不能只看 tag。部分失败重跑原提交,只补发缺失包;npm 全部成功后再建 tag/Release。查询异常与 404 必须区分,tag 指向其他提交时停止补发,禁止将新源码混入旧版本。
13
-
14
- Turbo 的 `build.env` 必须列出影响产物的变量;框架包含容器构建开关、E2E 构建模式及 PUBLIC/VITE/TAURI 前缀,共享 tsup 配置也纳入依赖。Docker/Testcontainers 连接变量通过测试任务透传。验证缓存须切换变量检查哈希和真实产物,不能只检查配置文本。
15
-
16
- 框架仓库发布验收使用 `pnpm test:release-local`;其 E2E 与 CI 共用根 `pnpm e2e`,覆盖 CLI 和全部 Web 应用,不能缩减为仅 Admin Console。应用仓库应在自己的根 E2E 命令集中维护所有端到端入口。容器和原生验收须独立记录实际结果。
17
-
18
10
  | 项目 | 契约 |
19
11
  | --- | --- |
20
12
  | 能力 | 维护 hai 应用的 CI/CD、GitHub Actions、质量门禁和凭据泄漏扫描 |
@@ -41,7 +33,7 @@ Turbo 的 `build.env` 必须列出影响产物的变量;框架包含容器构
41
33
  2. **最小权限**:默认 `permissions: contents: read`,只有 release、comment、pages 等明确场景才提升权限。
42
34
  3. **PR 不使用 secrets**:来自 fork 或不可信分支的 PR 不得运行读取 secrets 的 workflow。
43
35
  4. **禁用高风险组合**:禁止 `pull_request_target` + checkout PR 代码 + secrets/写权限。
44
- 5. **先轻后重**:核心 CI 必须稳定;E2E、发布、安全深扫可以拆成 manual/nightly 或独立 workflow。
36
+ 5. **按风险选择门禁**:核心 CI 必须稳定;E2E、发布、安全深扫可拆为独立 workflow,但关键权限/数据完整性路径不能因不稳定而长期没有验收。
45
37
  6. **可追溯**:workflow 改动必须说明触发条件、权限、缓存、失败路径和验证命令。
46
38
 
47
39
  ## 标准 CI 工作流
@@ -54,11 +46,13 @@ Turbo 的 `build.env` 必须列出影响产物的变量;框架包含容器构
54
46
  pnpm install --frozen-lockfile
55
47
  pnpm typecheck
56
48
  pnpm lint
57
- pnpm test
58
49
  pnpm build
50
+ pnpm test
59
51
  ```
60
52
 
61
- 测试覆盖范围与 TDD 断言由 `hai-app-tests` 定义;本技能只决定这些命令如何在 workflow 中稳定执行。
53
+ 从当前 package.json 确认实际 scripts,使用声明的最低 Node 版本验证并与 engines/README 同步;PowerShell 使用 `pnpm.cmd`。测试内容由 `hai-app-tests` 定义;本技能决定门禁如何稳定执行。
54
+
55
+ lint/typecheck 只能执行已配置的规则。新增开发规范时区分可静态检测项(如显式 any/console.log)与必须行为验收项(如资源越权、事务/幂等、失败结果、生命周期清理),后者在适用单元/集成/E2E 中验证。禁止通过关闭规则、添加无依据忽略或把 `|| true` 加到门禁来“统一风格”。
62
56
 
63
57
  ### E2E 策略
64
58
 
@@ -69,7 +63,7 @@ pnpm build
69
63
  ### hai-framework 依赖策略
70
64
 
71
65
  - CI 默认使用 `pnpm-lock.yaml` 中的 npm/published 依赖,确保与真实安装环境一致。
72
- - 本地联调使用 `framework:use:local` / `framework:watch`,但不要让默认 PR CI 隐式依赖本机路径。
66
+ - 本地联调先查项目是否定义 `framework:use:local` / `framework:watch`;没有时按本项目 README 操作,不要让默认 PR CI 隐式依赖本机路径。
73
67
  - 需要验证本地 framework 改动时,创建显式的 sync/drift check 或双仓联动 PR。
74
68
 
75
69
  ## GitHub Actions 安全清单
@@ -88,7 +82,7 @@ pnpm build
88
82
  ### 推荐
89
83
 
90
84
  - 用无 secrets 的高置信正则扫描常见密钥形态。
91
- - 排除示例 skill、锁文件、图片等容易误报的路径。
85
+ - 技能/文档与配置同样可能泄漏凭据,不按目录整体排除;只对已确认的测试占位和固定误报做有依据的最小忽略,检查修改是否掩盖真实密钥。
92
86
  - 需要私有关键词表时,仅在受信任分支的独立 workflow 中运行,不对 fork PR 暴露。
93
87
 
94
88
  ### 禁止
@@ -115,5 +109,4 @@ pnpm build
115
109
  - `hai-deploy` — 应用部署与云服务开通
116
110
  - `hai-framework-sync` — hai-framework 与应用仓库同步策略
117
111
 
118
- 发布完成判定始终查询根版本的 npm 包;发布 job 同步包版本但不提交,标签固定指向触发质量验收的源码提交。发布成功后由独立 job 提交版本同步;完整重跑即使无需补发也会执行同步,远端已存在相同内容时成功退出,分支有新源码时拒绝覆盖并要求从最新 main 重跑。
119
- 原生交付必须单独执行 Tauri/Gradle/Xcode 打包,并在目标 OS/设备验证安装启动、登录/退出、重启会话、安全 TokenStore、真实 API 域名与覆盖升级。Web 构建/E2E 不代替原生验收。保存提交、包 hash、平台/工具链及逐项结果;缺平台写未验证,禁止静默 skip。hai-framework 仓库参考 `.github/workflows/native.yml` 与 desktop-app / mobile-app README 的「原生交付与验收」章节。
112
+ 涉及发布时按本应用实际 registry/镜像/部署目标核验精确版本与提交,不以 tag 或 CI 绿灯代替发布产物;未经授权不发布。原生/容器交付按当前项目入口单独构建与启动验收,保存产物、平台和行为证据;缺平台写未验证,Web E2E 不代替原生验收。
@@ -18,8 +18,10 @@ description: "使用 @h-ai/core 配置、日志、i18n、ID、Zod 错误本地
18
18
  ## 使用路径
19
19
 
20
20
  - Node 启动用 core.init({ configDir }) 加载配置;勿传 logging 覆盖 _core.yml 中的日志设置,除非任务明确要求。
21
+ - 应用名称、版本、环境、默认语言和日志设置统一从 `_core.yml` 经 core.config 获取,日志使用 core.logger;UI 不另维护硬编码副本。SvelteKit layout / fullstack app.info 仅下发公开字段白名单;独立 Vite mobile-app 在 Node 构建时解析并注入公开值,修改配置后重新构建。浏览器不加载 YAML,不接收完整模块配置、密钥或日志脱敏上下文。
21
22
  - HAI_<配置名>_<路径> 可整体覆盖根/对象/数组;父节点优先,未覆盖时才遍历已有叶子。camelCase 不拆词,约定变量优先于显式插值。
22
23
  - 配置 getter 与 ID/logger 方法不是 HaiResult;validate/load 等须检查 success。
24
+ - 初始化前创建的默认、模块与嵌套 child Logger 在后续输出中应用当前全局 logging;configure/setLevel 也作用于已有实例。create 的显式 level/format/context 优先,未指定项动态继承。浏览器 json/pretty 与附加 redact 路径实际生效,消息文本仍由调用方脱敏。
23
25
 
24
26
  ## 按需参考
25
27
 
@@ -140,6 +140,8 @@ feature:
140
140
 
141
141
  `core.logger` 既是默认 Logger 实例,也是日志管理的统一入口。
142
142
 
143
+ `core.init` 加载 `_core.yml.logging`、`configure` 和 `setLevel` 会改变已有默认、模块及嵌套 child Logger 的后续实际输出;不需要重新创建模块 Logger。`create` 显式指定的 level/format/context 保持优先,未指定选项动态继承全局配置;调用时 context 覆盖固定 context,附加 redact 规则统一生效。
144
+
143
145
  **日志记录**(实例方法):`trace` / `debug` / `info` / `warn` / `error` / `fatal`
144
146
 
145
147
  ```typescript
@@ -525,9 +527,9 @@ logger.debug('Data fetched', { count: items.length })
525
527
  | 功能 | 行为 |
526
528
  |------|------|
527
529
  | `core.config` 文件配置 | 不支持;文件相关方法返回 `SERVICE_UNAVAILABLE`,配置应由服务端读取后下发 |
528
- | `format: 'json' \| 'pretty'` | 被忽略(始终输出到 DevTools console) |
529
- | 自定义 `redact` 配置 | 浏览器不使用该配置,但默认 sanitizeSensitiveFields 仍会清理上下文敏感字段;消息文本需调用方脱敏 |
530
- | `fatal` 级别 | 映射为 `console.error`(带 `[FATAL]` 前缀) |
531
- | context 输出 | JSON 字符串追加到消息末尾(非结构化对象) |
530
+ | `format: 'json' \| 'pretty'` | 始终输出到 DevTools console;json 为包含 level/msg 的 JSON 字符串,pretty 为可读消息与上下文 |
531
+ | 自定义 `redact` 配置 | 与默认 sanitizeSensitiveFields 同时生效;支持嵌套点/括号路径与 `*`,不修改调用方对象;消息文本需调用方脱敏 |
532
+ | `fatal` 级别 | 映射为 console.error;pretty 带 `[FATAL]` 前缀,json 使用 `level: 'fatal'` |
533
+ | context 输出 | pretty 追加 JSON 上下文,json 合并上下文到结构化 JSON 字符串 |
532
534
 
533
535
  云资源输出格式与部署配置消费见 [hai-deploy](../hai-deploy/SKILL.md);这里的父节点覆盖规则同样适用。
@@ -38,6 +38,8 @@ description: "同步 hai-framework 通用 skills、AI 入口与应用依赖,
38
38
 
39
39
  ### 1. 判断来源
40
40
 
41
+ 先读取当前应用入口与 package.json/lockfile,记录实际 npm/local 模式及解析版本。同步 skill 不能证明新 API 已安装或可用:以目标依赖的公开 exports/types 验证示例与配置,未发布框架能力仅用于已授权本地联调。
42
+
41
43
  | 变更类型 | 首选位置 |
42
44
  | --- | --- |
43
45
  | 通用 hai 模块用法 | `hai-framework/packages/cli/templates/skills/hai-*/SKILL.md` |
@@ -55,14 +57,16 @@ description: "同步 hai-framework 通用 skills、AI 入口与应用依赖,
55
57
 
56
58
  - `AGENTS.md`
57
59
  - `.github/copilot-instructions.md`
58
- - `CLAUDE.md`(如存在)
60
+ - `CLAUDE.md`(如存在,通过 `@AGENTS.md` 复用共享规则;不另复制 `.claude/skills/`,保留用户已有规则和技能)
59
61
  - `opencode.json`(如结构变化)
60
62
 
63
+ 新增/修改/修复任务入口必须能到达 `hai-app-create` 与其 `development.md`;审查入口能到达 `hai-app-review`。按目标架构/依赖交付所需模块技能,不把 SvelteKit 指令套到 API/Vite 项目。复制前比对应用私有覆盖,合并通用修正并保留差异,不能直接覆盖业务规则。
64
+
61
65
  ### 4. 验证
62
66
 
63
67
  按变更类型选择验证方式:
64
68
 
65
- - 仅模板 / skill 变更:检查 diff、入口引用与模板泛化程度。
69
+ - 仅模板 / skill 变更:检查 diff、目标中实际存在的入口/相邻资源及其相对引用,确认没有框架仓库私有路径/命令;本地能力导航对可选 skill 先检查存在,不把目录缺失当成能力缺失。
66
70
  - 同步到应用仓库:按 `hai-ci` 定义的质量门禁运行。
67
71
  - 涉及 framework runtime 时,先确认应用 package.json 已定义下列脚本;没有时按 README 的本地联调方式操作:
68
72
 
@@ -75,6 +79,8 @@ pnpm framework:watch <package>
75
79
  ## 漂移检查清单
76
80
 
77
81
  - [ ] framework 模板和应用 `.agents/skills` 对同名 skill 内容一致,除非 PR 明确说明本地覆盖
82
+ - [ ] 普通功能修改/修复也路由到能力匹配与安全/质量自查,不仅“创建项目”或手工调用 skill 才生效
83
+ - [ ] 技能示例与目标实际依赖版本、架构、公开 API 一致;没有把模板更新当成 runtime 升级
78
84
  - [ ] `AGENTS.md` 的 skill 列表包含新增/重命名 skill
79
85
  - [ ] Copilot/Claude/OpenCode 入口能找到新增 skill
80
86
  - [ ] CI 默认不依赖 `/home/.../hai-framework` 本地路径
@@ -27,7 +27,7 @@ description: "审查 PR 范围、风险、验证证据和合并准备度。"
27
27
  - 设计 AI PR Review 方案
28
28
  - 选择 Copilot、CodeRabbit、reviewdog、DangerJS、Claude Code Action、Codex Action 等工具
29
29
 
30
- 不负责:代码级质量审查(用 `hai-app-review` / 模块审查技能)、测试用例设计(用 `hai-app-tests`)、workflow 触发/权限/secret 细节(用 `hai-ci`)。
30
+ 代码级框架复用、安全与风格审查交给 [hai-app-review](../hai-app-review/SKILL.md),测试用例设计交给 `hai-app-tests`,workflow 触发/权限/secret 细节交给 `hai-ci`。
31
31
 
32
32
  ## 审查分层
33
33
 
@@ -41,7 +41,8 @@ description: "审查 PR 范围、风险、验证证据和合并准备度。"
41
41
 
42
42
  - scope 是否清晰且与 issue 对齐
43
43
  - 测试是否覆盖成功路径、失败路径、边界条件
44
- - 是否符合 hai-framework 约定:HaiResult、i18n、日志、分层、TDD
44
+ - 本次需求是否复用适用框架能力/feature/配置,自定义或新依赖是否有已安装版本的缺口依据(见 [development.md](../hai-app-create/development.md))
45
+ - 是否符合实际返回契约、i18n、日志、分层、当前 lint 风格,以及输入/越权/失败等适用行为验收;不能以导入包数量或 CI 全绿替代代码与安全审查
45
46
  - 是否引入密钥、权限扩大、workflow 风险或两仓漂移
46
47
 
47
48
  ### 第 3 层:AI Review(默认 advisory)
@@ -91,7 +92,7 @@ PR 描述必须说明:
91
92
  - [ ] PR 模板完整填写
92
93
  - [ ] CI required checks 全绿
93
94
  - [ ] 新行为有测试,失败路径有覆盖
94
- - [ ] 代码级质量问题已由 `hai-app-review` / 模块审查技能覆盖
95
+ - [ ] 框架能力选择、代码风格与适用安全边界已由 `hai-app-review` 覆盖,有行为证据或明确未验证项
95
96
  - [ ] 文档 / skill / README 与代码同步
96
97
  - [ ] workflow 权限或 secrets 变化已由 `hai-ci` 审查
97
98
  - [ ] AI-assisted 内容已由人类复核
@@ -99,5 +100,5 @@ PR 描述必须说明:
99
100
  ## 相关 Skills
100
101
 
101
102
  - `hai-ci` — CI/CD 与 workflow 安全
102
- - `hai-review-module` / `hai-app-review` — 代码质量审查
103
+ - `hai-app-review` — 应用代码质量与框架复用审查
103
104
  - `hai-framework-sync` — 两仓同步审查
@@ -18,6 +18,7 @@ description: "使用 @h-ai/reldb 访问 SQLite/PostgreSQL/MySQL,编写 SQL、C
18
18
  ## 使用路径
19
19
 
20
20
  - `_db.yml` 对应 core.config 的 db;先校验 ReldbConfigSchema,再 init 并检查 success。
21
+ - `reldb.crud.table` / `tx.crud.table` 的 `dbType` 必填并与实际后端一致;`BaseReldbCrudRepository` 自动读取已初始化的配置。
21
22
  - 事务每步检查结果,避免把失败当普通返回值提交;同一事务操作须共享 tx。
22
23
  - SQL 值参数化;where/orderBy/json 列名不是任意用户输入。分页使用 PaginatedResult。
23
24