@h-ai/cli 1.0.0-beta.2 → 1.0.0-beta.20

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 (254) hide show
  1. package/README.en.md +74 -154
  2. package/README.ja.md +74 -154
  3. package/README.md +74 -154
  4. package/dist/{chunk-AKV2CQZV.js → chunk-2ZL5ORQ2.js} +316 -97
  5. package/dist/chunk-2ZL5ORQ2.js.map +1 -0
  6. package/dist/{chunk-EF7WOFWZ.js → chunk-L53P43B2.js} +1312 -163
  7. package/dist/chunk-L53P43B2.js.map +1 -0
  8. package/dist/cli-config-templates-LWMD2I6V.js +5 -0
  9. package/dist/{cli-config-templates-HHFHNXBN.js.map → cli-config-templates-LWMD2I6V.js.map} +1 -1
  10. package/dist/{cli-skill-templates-PN4FLGBC.js → cli-skill-templates-D6S2OQ6X.js} +3 -3
  11. package/dist/{cli-skill-templates-PN4FLGBC.js.map → cli-skill-templates-D6S2OQ6X.js.map} +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +30118 -3253
  14. package/dist/index.js.map +1 -1
  15. package/dist/metafile-esm.json +1 -1
  16. package/package.json +22 -18
  17. package/templates/README.md +45 -30
  18. package/templates/apps/admin/src/routes/+layout.svelte.hbs +16 -10
  19. package/templates/apps/admin/src/routes/+page.svelte.hbs +4 -4
  20. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +17 -7
  21. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +26 -6
  22. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +2 -2
  23. package/templates/apps/api/.dockerignore.hbs +10 -0
  24. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +8 -0
  25. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +6 -1
  26. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +13 -5
  27. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +13 -5
  28. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  29. package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +6 -2
  30. package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +24 -2
  31. package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +4 -4
  32. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +74 -24
  33. package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  34. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +153 -37
  35. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +39 -13
  36. package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +106 -33
  37. package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +3 -1
  38. package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  39. package/templates/apps/api/e2e/api-serv.spec.ts.hbs +20 -3
  40. package/templates/apps/api/e2e/capture-evidence.ts.hbs +4 -1
  41. package/templates/apps/api/eslint.config.js.hbs +3 -1
  42. package/templates/apps/api/images/serv.Dockerfile.hbs +15 -10
  43. package/templates/apps/api/playwright.config.ts.hbs +23 -19
  44. package/templates/apps/api/pnpm-workspace.yaml.hbs +27 -16
  45. package/templates/apps/fullstack/.dockerignore.hbs +10 -0
  46. package/templates/apps/fullstack/.gitignore.hbs +7 -2
  47. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +14 -12
  48. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +5 -3
  49. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +10 -2
  50. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +1 -1
  51. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +10 -2
  52. package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +0 -1
  53. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +0 -1
  54. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +4 -1
  55. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +16 -4
  56. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +10 -8
  57. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +3 -3
  58. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +8 -2
  59. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +0 -1
  60. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +0 -2
  61. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +4 -1
  62. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +16 -4
  63. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +2 -0
  64. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +9 -9
  65. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +10 -2
  66. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +1 -0
  67. package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +0 -1
  68. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +0 -2
  69. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +4 -1
  70. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +19 -5
  71. package/templates/apps/fullstack/docs/security-configuration.md.hbs +4 -1
  72. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +140 -28
  73. package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +19 -5
  74. package/templates/apps/fullstack/eslint.config.js.hbs +3 -1
  75. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +19 -11
  76. package/templates/apps/fullstack/images/web.Dockerfile.hbs +17 -8
  77. package/templates/apps/fullstack/package.json.hbs +2 -1
  78. package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +7 -5
  79. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +114 -23
  80. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +57 -11
  81. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  82. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +17 -7
  83. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +13 -7
  84. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +17 -7
  85. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +10 -4
  86. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +65 -30
  87. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  88. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +1 -2
  89. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +69 -21
  90. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +21 -5
  91. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +63 -11
  92. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +6 -1
  93. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +3 -1
  94. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +147 -33
  95. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +43 -12
  96. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +146 -30
  97. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +33 -10
  98. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +142 -26
  99. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +6 -2
  100. package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  101. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +48 -66
  102. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +1 -0
  103. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +1 -0
  104. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +1 -0
  105. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +9 -2
  106. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +0 -3
  107. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +15 -3
  108. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +33 -7
  109. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +16 -2
  110. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +104 -13
  111. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +37 -7
  112. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +9 -3
  113. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +25 -3
  114. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +133 -19
  115. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +14 -2
  116. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +66 -34
  117. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +132 -30
  118. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +8 -2
  119. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +23 -5
  120. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +143 -21
  121. package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -2
  122. package/templates/apps/fullstack/playwright.config.ts.hbs +25 -3
  123. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +30 -14
  124. package/templates/apps/h5/src/routes/+layout.svelte.hbs +74 -30
  125. package/templates/apps/h5/src/routes/+page.svelte.hbs +2 -2
  126. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +2 -2
  127. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +2 -2
  128. package/templates/apps/mobile-app/capacitor.config.ts.hbs +5 -2
  129. package/templates/apps/mobile-app/messages/en-US.json +2 -2
  130. package/templates/apps/mobile-app/messages/ja-JP.json +2 -2
  131. package/templates/apps/mobile-app/messages/zh-CN.json +2 -2
  132. package/templates/apps/mobile-app/src/App.svelte.hbs +17 -5
  133. package/templates/apps/mobile-app/src/lib/api.ts.hbs +20 -6
  134. package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +8 -1
  135. package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +6 -2
  136. package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -1
  137. package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +5 -1
  138. package/templates/apps/website/scripts/static-website.mjs.hbs +19 -6
  139. package/templates/apps/website/src/routes/+layout.svelte.hbs +56 -29
  140. package/templates/apps/website/src/routes/+page.svelte.hbs +4 -4
  141. package/templates/apps/website/src/routes/about/+page.svelte.hbs +2 -2
  142. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +2 -2
  143. package/templates/apps/website/src/routes/services/+page.svelte.hbs +20 -5
  144. package/templates/base/.dockerignore.hbs +10 -0
  145. package/templates/base/.gitignore.hbs +7 -2
  146. package/templates/base/e2e/app.spec.ts.hbs +130 -36
  147. package/templates/base/eslint-rules.js +44 -25
  148. package/templates/base/eslint.config.js.hbs +3 -1
  149. package/templates/base/images/web.Dockerfile.hbs +25 -14
  150. package/templates/base/package.json.hbs +13 -7
  151. package/templates/base/patches/daisyui-5.7.50.patch +8 -0
  152. package/templates/base/patches/deepmerge-4.3.1.patch +51 -0
  153. package/templates/base/playwright.config.ts +3 -1
  154. package/templates/base/pnpm-workspace.yaml.hbs +33 -16
  155. package/templates/base/src/app.d.ts.hbs +1 -1
  156. package/templates/base/src/app.html.hbs +1 -0
  157. package/templates/base/src/hooks.server.ts.hbs +44 -33
  158. package/templates/base/src/lib/build-metadata.ts.hbs +0 -1
  159. package/templates/base/src/lib/server/init.ts.hbs +146 -35
  160. package/templates/base/src/lib/server/kit-config.ts.hbs +7 -4
  161. package/templates/base/src/routes/+layout.server.ts.hbs +2 -2
  162. package/templates/base/svelte.config.js.hbs +10 -100
  163. package/templates/base/tests/scaffold.test.ts.hbs +12 -3
  164. package/templates/base/tsconfig.json.hbs +7 -4
  165. package/templates/base/vite.config.ts.hbs +108 -14
  166. package/templates/base/vitest.config.ts.hbs +6 -2
  167. package/templates/features/ai/routes/api/chat/+server.ts +3 -1
  168. package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +3 -3
  169. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +3 -3
  170. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +3 -3
  171. package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +3 -3
  172. package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +3 -3
  173. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +3 -3
  174. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +3 -3
  175. package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +3 -3
  176. package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +3 -3
  177. package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +3 -3
  178. package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +3 -3
  179. package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +3 -3
  180. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +14 -3
  181. package/templates/shared/browser-check/startup.js +115 -0
  182. package/templates/shared/browser-check/update.css +37 -0
  183. package/templates/shared/browser-check/update.html +19 -0
  184. package/templates/shared/browser-startup.spec.ts +23 -0
  185. package/templates/shared/build-metadata.ts +18 -4
  186. package/templates/shared/e2e-env.ts +22 -6
  187. package/templates/shared/native-name.d.mts +5 -0
  188. package/templates/shared/native-name.mjs +94 -0
  189. package/templates/shared/public-base-path.mjs +17 -4
  190. package/templates/shared/run-e2e.mjs +46 -12
  191. package/templates/shared/run-node.mjs +56 -0
  192. package/templates/shared/run-tauri.mjs +74 -0
  193. package/templates/shared/vite-runtime-config.ts +9 -3
  194. package/templates/skills/AGENTS.md +10 -73
  195. package/templates/skills/bridges/admin/AGENTS.md +9 -65
  196. package/templates/skills/bridges/api/AGENTS.md +8 -59
  197. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +9 -54
  198. package/templates/skills/bridges/h5/AGENTS.md +8 -63
  199. package/templates/skills/bridges/mobile-app/AGENTS.md +8 -62
  200. package/templates/skills/bridges/website/AGENTS.md +8 -63
  201. package/templates/skills/hai-ai/SKILL.md +6 -2
  202. package/templates/skills/hai-ai/acp.md +153 -0
  203. package/templates/skills/hai-ai/guide.md +27 -12
  204. package/templates/skills/hai-ai/reference.md +24 -15
  205. package/templates/skills/hai-ai/resources.md +69 -0
  206. package/templates/skills/hai-api-client/SKILL.md +1 -1
  207. package/templates/skills/hai-api-client/reference.md +3 -1
  208. package/templates/skills/hai-app-create/collaboration.md +7 -0
  209. package/templates/skills/hai-app-create/development.md +19 -10
  210. package/templates/skills/hai-app-create/project.md +33 -0
  211. package/templates/skills/hai-app-create/reference.md +10 -10
  212. package/templates/skills/hai-app-tests/reference.md +1 -1
  213. package/templates/skills/hai-app-tests/validation.md +1 -0
  214. package/templates/skills/hai-build/SKILL.md +19 -9
  215. package/templates/skills/hai-build/paths.md +4 -2
  216. package/templates/skills/hai-build/reference.md +26 -8
  217. package/templates/skills/hai-cache/reference.md +6 -2
  218. package/templates/skills/hai-capacitor/SKILL.md +1 -0
  219. package/templates/skills/hai-capacitor/reference.md +24 -0
  220. package/templates/skills/hai-ci/SKILL.md +3 -0
  221. package/templates/skills/hai-core/SKILL.md +9 -4
  222. package/templates/skills/hai-core/reference.md +40 -10
  223. package/templates/skills/hai-core/request-access.md +2 -2
  224. package/templates/skills/hai-crypto/SKILL.md +2 -2
  225. package/templates/skills/hai-crypto/reference.md +7 -3
  226. package/templates/skills/hai-deploy/SKILL.md +41 -5
  227. package/templates/skills/hai-deploy/middleware.md +26 -14
  228. package/templates/skills/hai-framework-sync/SKILL.md +13 -9
  229. package/templates/skills/hai-framework-sync/sync.md +2 -0
  230. package/templates/skills/hai-iam/reference.md +2 -2
  231. package/templates/skills/hai-kit/SKILL.md +1 -1
  232. package/templates/skills/hai-kit/reference.md +19 -5
  233. package/templates/skills/hai-payment/reference.md +41 -17
  234. package/templates/skills/hai-reach/SKILL.md +3 -1
  235. package/templates/skills/hai-reach/reference.md +29 -9
  236. package/templates/skills/hai-reldb/SKILL.md +1 -1
  237. package/templates/skills/hai-reldb/reference.md +9 -2
  238. package/templates/skills/hai-scheduler/reference.md +1 -1
  239. package/templates/skills/hai-serv/SKILL.md +2 -1
  240. package/templates/skills/hai-serv/reference.md +26 -15
  241. package/templates/skills/hai-storage/reference.md +23 -6
  242. package/templates/skills/hai-ui/SKILL.md +8 -5
  243. package/templates/skills/hai-ui/charts.md +51 -0
  244. package/templates/skills/hai-ui/guide.md +1 -1
  245. package/templates/skills/hai-ui/reference.md +29 -38
  246. package/templates/skills/hai-vecdb/reference.md +8 -3
  247. package/dist/chunk-AKV2CQZV.js.map +0 -1
  248. package/dist/chunk-EF7WOFWZ.js.map +0 -1
  249. package/dist/chunk-MUHRBJSW.js +0 -29272
  250. package/dist/chunk-MUHRBJSW.js.map +0 -1
  251. package/dist/cli-config-templates-HHFHNXBN.js +0 -5
  252. package/dist/src-TEBHR5I5.js +0 -5
  253. package/dist/src-TEBHR5I5.js.map +0 -1
  254. package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +0 -18
@@ -8,12 +8,25 @@ const basePathMessage = core.i18n.createMessageGetter({
8
8
  'ja-JP': { invalid: 'PUBLIC_BASE_PATHは空、または/で始まるサイト内ディレクトリーです。外部URL、末尾の/、クエリー、フラグメント、パス逸脱は使えません。' },
9
9
  })
10
10
 
11
- /** @param {string} [value] - 无末尾斜杠的公开目录;空字符串表示域名根目录。 */
11
+ /**
12
+ * @param {string} [value] - 无末尾斜杠的公开目录;空字符串表示域名根目录。
13
+ * @returns {'' | `/${string}`} 经校验的站内挂载目录,可直接用于 SvelteKit paths.base。
14
+ */
12
15
  export function resolvePublicBasePath(value = process.env.PUBLIC_BASE_PATH ?? '') {
13
16
  if (value && (!/^\/[\w.-]+(?:\/[\w.-]+)*$/.test(value) || value.split('/').some(segment => segment === '.' || segment === '..'))) {
14
- const language = [process.env.HAI_CORE_DEFAULTLOCALE, process.env.LC_ALL, process.env.LC_MESSAGES, process.env.LANG].find(item => item?.trim())?.split(/[_.-]/)[0]?.toLowerCase()
15
- const locale = language === 'en' || language === 'c' || language === 'posix' ? 'en-US' : language === 'ja' ? 'ja-JP' : 'zh-CN'
17
+ const language = [
18
+ process.env.HAI_CORE_DEFAULTLOCALE,
19
+ process.env.LC_ALL,
20
+ process.env.LC_MESSAGES,
21
+ process.env.LANG,
22
+ ].find(item => item?.trim())?.split(/[_.-]/)[0]?.toLowerCase()
23
+ const locale = language === 'en' || language === 'c' || language === 'posix'
24
+ ? 'en-US'
25
+ : language === 'ja'
26
+ ? 'ja-JP'
27
+ : 'zh-CN'
16
28
  throw new Error(basePathMessage('invalid', { locale }))
17
29
  }
18
- return value
30
+ // 已排除不以 / 开头的非空字符串;正则校验无法自动收窄 TypeScript 字符串类型。
31
+ return /** @type {'' | `/${string}`} */ (value)
19
32
  }
@@ -12,12 +12,16 @@ const cli = require.resolve('@playwright/test/cli')
12
12
  const dataParent = resolve(process.env.HAI_E2E_DATA_ROOT || tmpdir())
13
13
  mkdirSync(dataParent, { recursive: true })
14
14
  const dataRoot = mkdtempSync(join(dataParent, 'hai-browser-e2e-'))
15
- const groups = [[]]
15
+ const groups = [
16
+ { args: [], name: undefined },
17
+ ]
16
18
  for (const argument of process.argv.slice(2)) {
17
19
  if (argument === '--next')
18
- groups.push([])
20
+ groups.push({ args: [], name: undefined })
21
+ else if (argument.startsWith('--e2e-group='))
22
+ groups.at(-1).name = argument.slice('--e2e-group='.length)
19
23
  else
20
- groups.at(-1).push(argument)
24
+ groups.at(-1).args.push(argument)
21
25
  }
22
26
  let child
23
27
  let interrupted = false
@@ -37,7 +41,12 @@ function stop() {
37
41
  if (process.platform === 'win32' && child?.pid && child.exitCode === null) {
38
42
  // Windows 的 kill 不传递 SIGTERM;同时结束本次 Playwright 创建的浏览器与服务进程。
39
43
  stopping = new Promise((resolve) => {
40
- const killer = spawn('taskkill', ['/pid', String(child.pid), '/t', '/f'], { windowsHide: true, stdio: 'ignore' })
44
+ const killer = spawn('taskkill', [
45
+ '/pid',
46
+ String(child.pid),
47
+ '/t',
48
+ '/f',
49
+ ], { windowsHide: true, stdio: 'ignore' })
41
50
  killer.once('error', () => {
42
51
  child?.kill()
43
52
  resolve()
@@ -56,31 +65,49 @@ try {
56
65
  const evidenceParent = resolve(process.env.HAI_AUTH_EVIDENCE_DIR || join(cwd, 'test-results'))
57
66
  mkdirSync(evidenceParent, { recursive: true })
58
67
  const runRoot = mkdtempSync(join(evidenceParent, 'run-'))
59
- for (const [index, args] of groups.entries()) {
68
+ for (const [index, { args, name }] of groups.entries()) {
60
69
  const groupRoot = join(runRoot, `group-${index + 1}`)
61
70
  const groupDataRoot = join(dataRoot, `group-${index + 1}`)
62
71
  mkdirSync(groupDataRoot)
63
72
  const hasOutput = args.some(argument => argument === '--output' || argument.startsWith('--output='))
64
- const outputArgs = hasOutput ? [] : ['--output', join(groupRoot, 'results')]
73
+ const outputArgs = hasOutput
74
+ ? []
75
+ : [
76
+ '--output',
77
+ join(groupRoot, 'results'),
78
+ ]
65
79
  const html = process.env.PLAYWRIGHT_HTML_OUTPUT_DIR || process.env.PLAYWRIGHT_HTML_REPORT
66
80
  const code = await new Promise((resolve, reject) => {
67
- child = spawn(process.execPath, [cli, 'test', ...args, ...outputArgs], {
81
+ child = spawn(process.execPath, [
82
+ cli,
83
+ 'test',
84
+ ...args,
85
+ ...outputArgs,
86
+ ], {
68
87
  cwd,
69
88
  windowsHide: true,
70
89
  stdio: 'inherit',
71
90
  env: {
72
91
  ...process.env,
73
- ...(!html ? { PLAYWRIGHT_HTML_OUTPUT_DIR: join(groupRoot, 'html') } : {}),
92
+ ...(!html
93
+ ? {
94
+ PLAYWRIGHT_HTML_OUTPUT_DIR: join(groupRoot, 'html'),
95
+ }
96
+ : {}),
74
97
  HAI_AUTH_EVIDENCE_DIR: process.env.HAI_AUTH_EVIDENCE_DIR || join(groupRoot, 'evidence'),
75
98
  HAI_E2E_DATA_ROOT: groupDataRoot,
99
+ HAI_E2E_GROUP: name,
76
100
  },
77
101
  })
78
102
  child.once('error', reject)
79
103
  child.once('exit', resolve)
80
104
  })
81
105
  // 配置组互相独立,普通失败继续收集;保留首个失败码,中断才停止后续组。
82
- if (code !== 0)
83
- process.exitCode ||= typeof code === 'number' && code !== 0 ? code : 1
106
+ if (code !== 0) {
107
+ process.exitCode ||= typeof code === 'number' && code !== 0
108
+ ? code
109
+ : 1
110
+ }
84
111
  if (interrupted) {
85
112
  process.exitCode ||= 1
86
113
  break
@@ -93,10 +120,17 @@ finally {
93
120
  await stopping
94
121
  // Playwright 退出后服务进程已关闭,此时删除 SQLite / storage,避免 Windows 文件锁。
95
122
  try {
96
- rmSync(dataRoot, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })
123
+ rmSync(dataRoot, {
124
+ recursive: true,
125
+ force: true,
126
+ maxRetries: 3,
127
+ retryDelay: 100,
128
+ })
97
129
  }
98
130
  catch (error) {
99
- process.stderr.write(`E2E data cleanup failed: ${error instanceof Error ? error.message : String(error)}\n`)
131
+ process.stderr.write(`E2E data cleanup failed: ${error instanceof Error
132
+ ? error.message
133
+ : String(error)}\n`)
100
134
  // 清理错误不能把原始失败(如 exit 7)覆盖成另一状态,也不能让成功变为假成功。
101
135
  if (!process.exitCode)
102
136
  process.exitCode = 1
@@ -0,0 +1,56 @@
1
+ /** 所有模板共用环境来源规则启动 Node,让 NODE_OPTIONS 在子进程启动前生效。 */
2
+ import { spawn } from 'node:child_process'
3
+ import { createRequire } from 'node:module'
4
+ import { resolve } from 'node:path'
5
+ import process from 'node:process'
6
+ import { pathToFileURL } from 'node:url'
7
+
8
+ const [mode, environmentDirectory, entry, ...arguments_] = process.argv.slice(2)
9
+ if (!mode || !environmentDirectory || !entry)
10
+ throw new Error('Usage: node run-node.mjs <mode> <env-directory> <entry> [arguments]')
11
+
12
+ // 从实际应用解析公开 Core 入口,脚本可以放在 workspace 根目录。
13
+ const require = createRequire(resolve('package.json'))
14
+ const { core } = await import(pathToFileURL(require.resolve('@h-ai/core')).href)
15
+ const loaded = core.config.loadEnvFiles({
16
+ mode,
17
+ envDir: resolve(environmentDirectory),
18
+ })
19
+ if (!loaded.success)
20
+ throw new Error(loaded.error.message)
21
+
22
+ const child = spawn(process.execPath, [
23
+ resolve(entry),
24
+ ...arguments_,
25
+ ], {
26
+ cwd: process.cwd(),
27
+ env: {
28
+ ...process.env,
29
+ ...loaded.data,
30
+ },
31
+ stdio: 'inherit',
32
+ windowsHide: true,
33
+ })
34
+ function interrupt() {
35
+ child.kill('SIGINT')
36
+ }
37
+ function terminate() {
38
+ child.kill('SIGTERM')
39
+ }
40
+ process.on('SIGINT', interrupt)
41
+ process.on('SIGTERM', terminate)
42
+ try {
43
+ const result = await new Promise((resolve, reject) => {
44
+ child.once('error', reject)
45
+ child.once('close', (code, signal) => resolve({ code, signal }))
46
+ })
47
+ process.exitCode = result.code ?? (result.signal === 'SIGINT'
48
+ ? 130
49
+ : 143)
50
+ }
51
+ finally {
52
+ process.off('SIGINT', interrupt)
53
+ process.off('SIGTERM', terminate)
54
+ if (child.exitCode === null && child.signalCode === null)
55
+ child.kill('SIGTERM')
56
+ }
@@ -0,0 +1,74 @@
1
+ /** Tauri JSON 保留平台配置;名称通过 CLI 覆盖,不向源码写入环境值。 */
2
+ import { spawn } from 'node:child_process'
3
+ import { existsSync, readFileSync } from 'node:fs'
4
+ import { createRequire } from 'node:module'
5
+ import { resolve } from 'node:path'
6
+ import process from 'node:process'
7
+ import { resolveNativeName } from './native-name.mjs'
8
+
9
+ const [environmentDirectory, coreFile, ...args] = process.argv.slice(2)
10
+ if (!environmentDirectory || !coreFile)
11
+ throw new Error('Expected environment directory and Core YAML path before Tauri arguments')
12
+ const require = createRequire(resolve('package.json'))
13
+ const separator = args.indexOf('--')
14
+ const toolArgs = separator < 0
15
+ ? args
16
+ : args.slice(0, separator)
17
+ const command = toolArgs.find(argument => !argument.startsWith('-'))
18
+ if (['dev', 'build', 'bundle'].includes(command) && !toolArgs.some(argument => ['--help', '-h', '--version', '-V'].includes(argument))) {
19
+ const envDir = resolve(environmentDirectory)
20
+ const name = resolveNativeName(envDir, resolve(envDir, coreFile), command === 'dev'
21
+ ? 'dev'
22
+ : 'prod')
23
+ const config = JSON.parse(readFileSync(resolve('src-tauri/tauri.conf.json'), 'utf8'))
24
+ const platform = process.platform === 'win32'
25
+ ? 'windows'
26
+ : process.platform === 'darwin'
27
+ ? 'macos'
28
+ : 'linux'
29
+ const platformFile = resolve(`src-tauri/tauri.${platform}.conf.json`)
30
+ const patch = existsSync(platformFile)
31
+ ? JSON.parse(readFileSync(platformFile, 'utf8'))
32
+ : {}
33
+ // 与 Tauri 的 JSON Merge Patch 一致:平台数组整体替换,null 删除对应设置。
34
+ const app = patch.app === null
35
+ ? undefined
36
+ : {
37
+ ...config.app,
38
+ ...patch.app,
39
+ }
40
+ const main = app?.windows?.findIndex(window => (window.label ?? 'main') === 'main') ?? -1
41
+ const windows = app?.windows?.map((window, index) => index === (main < 0
42
+ ? 0
43
+ : main)
44
+ ? { ...window, title: name }
45
+ : window)
46
+ const overlay = {
47
+ productName: name,
48
+ ...(windows
49
+ ? {
50
+ app: { windows },
51
+ }
52
+ : {}),
53
+ }
54
+ // 名称是默认覆盖;调用方后续显式 --config 仍可覆盖它,保留 Tauri 原有优先级。
55
+ args.splice(args.indexOf(command) + 1, 0, '--config', JSON.stringify(overlay))
56
+ }
57
+ const child = spawn(process.execPath, [
58
+ require.resolve('@tauri-apps/cli/tauri.js'),
59
+ ...args,
60
+ ], { stdio: 'inherit', windowsHide: true })
61
+ const interrupt = () => child.kill('SIGINT')
62
+ const terminate = () => child.kill('SIGTERM')
63
+ process.on('SIGINT', interrupt)
64
+ process.on('SIGTERM', terminate)
65
+ try {
66
+ process.exitCode = await new Promise((resolveExit, reject) => {
67
+ child.once('error', reject)
68
+ child.once('close', code => resolveExit(code ?? 1))
69
+ })
70
+ }
71
+ finally {
72
+ process.off('SIGINT', interrupt)
73
+ process.off('SIGTERM', terminate)
74
+ }
@@ -32,7 +32,9 @@ export function publicRuntimeConfig(config: PublicRuntimeConfig): Plugin {
32
32
  version: metadata.version,
33
33
  env: metadata.env,
34
34
  defaultLocale: metadata.defaultLocale,
35
- logging: metadata.logging ? { level: metadata.logging.level, format: metadata.logging.format } : undefined,
35
+ logging: metadata.logging
36
+ ? { level: metadata.logging.level, format: metadata.logging.format }
37
+ : undefined,
36
38
  }
37
39
  : undefined,
38
40
  }
@@ -45,11 +47,15 @@ export function publicRuntimeConfig(config: PublicRuntimeConfig): Plugin {
45
47
  return {
46
48
  name: 'hai-public-runtime-config',
47
49
  configureServer(server) {
48
- const base = server.config.base.startsWith('/') ? server.config.base : '/'
50
+ const base = server.config.base.startsWith('/')
51
+ ? server.config.base
52
+ : '/'
49
53
  server.middlewares.use(`${base}runtime-config.js`, respond)
50
54
  },
51
55
  configurePreviewServer(server) {
52
- const base = server.config.base.startsWith('/') ? server.config.base : '/'
56
+ const base = server.config.base.startsWith('/')
57
+ ? server.config.base
58
+ : '/'
53
59
  server.middlewares.use(`${base}runtime-config.js`, respond)
54
60
  },
55
61
  }
@@ -1,85 +1,22 @@
1
1
  # AGENTS.md
2
2
 
3
- > 通用 AI 编程助手入口。优先阅读 `README.md`、现有测试与 `.agents/skills/`;本文件同时作为 `hai add` / AI 支持回填时的 generic fallback。
4
-
5
- ## 需求与模板
6
-
7
- - 业务行为以用户当前明确要求及其指定的需求/设计文档为准。本文件、README、skills、示例、生成代码及其测试中的模板默认行为是起点,不是不可变的业务约束;角色代码、权限模型、页面流程、字段、限额、存储方式与架构均可按实际需求调整。
8
- - 需求与模板不同,审查时记录为模板适配项,不据此判定需求错误或阻塞审查,也不要求用户额外授权“覆盖模板”;实施时在已有授权范围内修改或移除冲突逻辑,并同步 contract、鉴权、数据迁移、界面、配置、测试、文档及本文件中的过期规则。
9
- - 未说明的行为可参考现有实现并注明假设,不能升级为强制需求。只有业务要求自身矛盾、与已确认项目决策的优先级不明,或存在真实技术/安全障碍时才提出具体问题;已明确的规则不重复要求选择。
10
- - 业务规则与技术契约分别判断:可用 API 以当前安装版本的公开类型为准;输入校验、服务端授权、资源隔离和密钥保护仍须落实。需求涉及替换技术方案时说明影响并同步迁移,不能用保留模板默认值代替解决问题。
3
+ > 通用 AI 编程助手入口;hai add / AI 支持回填未能确定工程类型时使用。实际布局以当前 README、package.json 和目录为准。
11
4
 
12
5
  ## 行为契约
13
6
 
14
- 涉及框架数据结构、配置、核心流程或模块边界的新增、修改、删除,先读 [变更影响与方案确认](.agents/skills/hai-change-plan/SKILL.md),说明实际影响并等待用户决定。已有具体确认不重复要求;普通应用私有实现按当前业务授权执行。确认后的变更成套更新文档、配置、网站内容源、注释、模板与调用方。
15
-
16
- 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
17
-
18
- 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
19
-
20
- 根据文档规划、实施、继续、返修或按已提交文档变更同步实现时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):维护 docs 清单与任务记录,比较已验收与目标文档 Git 快照,更新原任务或新建任务,每项独立分支 TDD、验证并本地合并;全部差异与整体验收通过后才推进基线。返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
21
-
22
- 普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
7
+ 先读 [项目共同规则](.agents/skills/hai-app-create/project.md),按当前任务读取下面的入口;不要加载整个 skill 树。业务以用户当前明确要求及指定文档为准,模板行为是可调整的起点。
23
8
 
24
- - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
25
- - 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
26
- - 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
27
- - 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
28
- - 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
29
-
30
- 先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
31
-
32
- - 直接影响:修改 / 新建 / 删除哪些文件;哪些脚本、类型、配置或路由会变。
33
- - 间接影响:哪些测试、README、i18n、示例、共享类型、依赖方需要同步更新。
9
+ | 任务 | 入口 |
10
+ | --- | --- |
11
+ | 新增、修改、修复应用 | [hai-app-create](.agents/skills/hai-app-create/SKILL.md);配置、注释与能力选择按需查 [development.md](.agents/skills/hai-app-create/development.md) |
12
+ | 需求/设计文档审查 | [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md) |
13
+ | 文档驱动规划、实施或返修 | [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md) |
14
+ | 代码审查 / 测试 / 构建 / 升级 | 按任务读取同名 hai-app-review / hai-app-tests / hai-build / hai-framework-sync;模块按实际依赖选择 |
34
15
 
35
16
  ## 项目概述
36
17
 
37
- 本项目由 hai-framework CLI 生成。单应用工程通常在 `src/` 下开发;多包工程会同时包含 `packages/*` 与 `apps/*`。实际结构以当前项目目录为准。
38
-
39
- 如项目使用 SvelteKit,`+server.ts` 只能导出 HTTP handler 与 SvelteKit 允许的配置项;辅助函数放到 `src/lib/**`。
40
-
41
- ## 工作流程
42
-
43
- 开发、审查、测试和排错先读[沟通与同步维护](.agents/skills/hai-app-create/collaboration.md):结论优先,区分发现与待验证、计划与完成;按实际影响检查使用文档、配置示例、截图、测试、CLI 模板和调用方。每批说明解决什么、使用变化、验证及剩余问题。
44
-
45
- 1. 先搜索现有实现、引用点、测试和 README。
46
- 2. 小步修改,优先保持目录结构、公开 API 和脚本稳定。
47
- 3. 改动公共类型、配置、模板或共享逻辑时,同步更新所有调用方与文档。
48
- 4. 一轮修改完成后按影响范围收集全部可执行门禁结果,汇总问题再集中修复、复测;普通失败不立即从头重跑。
49
-
50
- ## 代码注释与示例
51
-
52
- - 尽可能补充有信息量的中文 JSDoc:所有 export 的函数/类/方法、核心算法与业务流程、所有数据库表/列、接口/type/schema 及其字段都必须说明用途、单位、约束和关联关系。核心逻辑解释决策原因、边界、权限与失败路径,不逐行复述代码。
53
- - 函数按实际契约写 @param、@returns,仅确实抛错时写 @throws;异步、HaiResult 与事务失败行为须说明。类型/表结构说明字段含义、可空性、默认值、主外键和唯一约束。
54
- - 上述函数和结构的 JSDoc 均提供可理解的 @example:函数给调用及结果判断,结构给合法数据,表给典型行或查询示例。省略上下文要标明,不使用真实凭据。示例随实现同步,不能只堆叠没有信息量的注释。
55
- - 调用及结构示例见 [.agents/skills/hai-app-create/development.md](.agents/skills/hai-app-create/development.md) 的 JSDoc 注释一节。
56
-
57
- ## 质量门禁
58
-
59
- AI 先分析差异、调用方和受影响流程,默认只选择相关 test/E2E 与必要门禁,用户明确要求时才全量。核对 package.json,按 [分轮验证与集中修复](.agents/skills/hai-app-tests/validation.md) 收集所选检查与日志,再归并修复、复测失败及受影响项;普通失败不中断独立检查,真实前置阻塞才暂停依赖项。文档检查引用,UI/路由变更加相关 E2E,未运行项说明原因。
60
-
61
- ```bash
62
- pnpm typecheck
63
- pnpm lint
64
- pnpm build
65
- pnpm test
66
- pnpm test:e2e
67
- ```
18
+ 本项目由 hai-framework CLI 生成,单应用通常位于 src/,多包工程位于 apps/ 与 packages/。不要按目录名猜测运行端或强行转换架构。
68
19
 
69
20
  ## 完成条件
70
21
 
71
- - typecheck / lint / build / test / test:e2e 状态明确;整轮收集后集中修复,最终必需门禁对最终代码有效通过,未执行或阻塞明确原因,不能宣称完成。
72
- - README、i18n、测试、代码注释与实现保持一致。
73
- - 最终回复说明执行过的门禁、已同步的文档 / 依赖方,以及未完成项。
74
-
75
- ## Skills 路由
76
-
77
- - `.agents/skills/hai-build/SKILL.md`:架构、构建和质量门禁。
78
- - `.agents/skills/hai-app-create/SKILL.md`:应用骨架、路由、页面与 API 模板。
79
- - `.agents/skills/hai-app-review/SKILL.md`:应用代码审查。
80
- - `.agents/skills/hai-app-tests/SKILL.md`:Vitest / Playwright 测试策略。
81
- - 具体模块按需读取对应 `hai-*` Skill。
82
-
83
- 前端项目已交付对应技能时,先按 hai-ui-design 确定任务、布局、状态与组件映射,使用 hai-ui 实现,再由 hai-ui-review 检查真实页面。窄范围修改复用已有设计;按实际语言/主题/尺寸验证。
84
-
85
- 工作流技能按 hai-领域-动作 命名,能力使用类沿用领域名。需求、验收、发现与当前版本证据按 [工作交接契约](.agents/skills/hai-spec-implement/handoff.md) 传递,沿既有清单恢复任务。
22
+ 按实际 package scripts 和 [分轮验证](.agents/skills/hai-app-tests/validation.md) 选择受影响范围,依次收集 typecheck → lint → build(需要时)→ test → 相关 E2E;例如 `pnpm typecheck`。普通失败不中断独立检查,汇总后集中修复并定向复测。报告实际结果、文档/调用方同步与未验证原因;不能用静态、mock 或 Web 结果代替真实业务、外部服务或原生验证。
@@ -2,35 +2,17 @@
2
2
 
3
3
  > 管理后台项目 AI 编程助手入口。优先结合 `README.md`、`.agents/skills/`、`src/routes/`、`src/lib/server/` 与 `messages/*` 工作。
4
4
 
5
- ## 需求与模板
6
-
7
- - 业务行为以用户当前明确要求及其指定的需求/设计文档为准。本文件、README、skills、示例、生成代码及其测试中的模板默认行为是起点,不是不可变的业务约束;角色代码、权限模型、页面流程、字段、限额、存储方式与架构均可按实际需求调整。
8
- - 需求与模板不同,审查时记录为模板适配项,不据此判定需求错误或阻塞审查,也不要求用户额外授权“覆盖模板”;实施时在已有授权范围内修改或移除冲突逻辑,并同步 contract、鉴权、数据迁移、界面、配置、测试、文档及本文件中的过期规则。
9
- - 未说明的行为可参考现有实现并注明假设,不能升级为强制需求。只有业务要求自身矛盾、与已确认项目决策的优先级不明,或存在真实技术/安全障碍时才提出具体问题;已明确的规则不重复要求选择。
10
- - 业务规则与技术契约分别判断:可用 API 以当前安装版本的公开类型为准;输入校验、服务端授权、资源隔离和密钥保护仍须落实。需求涉及替换技术方案时说明影响并同步迁移,不能用保留模板默认值代替解决问题。
11
5
 
12
6
  ## 行为契约
13
7
 
14
- 涉及框架结构、配置、核心流程或模块边界变更时,先按 [变更影响与方案确认](.agents/skills/hai-change-plan/SKILL.md) 说明影响并等待用户决定;已确认且未扩大的方案继续执行。
15
-
16
- 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
17
-
18
- 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
19
-
20
- 根据文档规划、实施、继续、返修或按已提交文档变更同步实现时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):维护 docs 清单与任务记录,比较已验收与目标文档 Git 快照,更新原任务或新建任务,每项独立分支 TDD、验证并本地合并;全部差异与整体验收通过后才推进基线。返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
21
-
22
- 普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
8
+ 先读 [项目共同规则](.agents/skills/hai-app-create/project.md),按当前任务读取下面的入口;不要加载整个 skill 树。业务以用户当前明确要求及指定文档为准,模板行为是可调整的起点。
23
9
 
24
- - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
25
- - 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
26
- - 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
27
- - 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
28
- - 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
29
-
30
- 先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
31
-
32
- - 直接影响:哪些 `+page.svelte`、`+layout.svelte`、`+page.server.ts`、`+server.ts`、service、messages、README、测试会变。
33
- - 间接影响:哪些角色权限、导航入口、共享组件、表单流程和依赖模块需要同步。
10
+ | 任务 | 入口 |
11
+ | --- | --- |
12
+ | 新增、修改、修复应用 | [hai-app-create](.agents/skills/hai-app-create/SKILL.md);配置、注释与能力选择按需查 [development.md](.agents/skills/hai-app-create/development.md) |
13
+ | 需求/设计文档审查 | [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md) |
14
+ | 文档驱动规划、实施或返修 | [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md) |
15
+ | 代码审查 / 测试 / 构建 / 升级 | 按任务读取同名 hai-app-review / hai-app-tests / hai-build / hai-framework-sync;模块按实际依赖选择 |
34
16
 
35
17
  ## 项目定位
36
18
 
@@ -40,50 +22,12 @@
40
22
 
41
23
  - 页面组件、layout、load 只负责渲染、权限态拼装和请求编排;业务逻辑放在 `src/lib/server/services` 或模块 API。
42
24
  - 认证授权使用 `@h-ai/iam` / `@h-ai/kit`;Web token 优先 httpOnly cookie。
43
- - 所有用户可见文本走 `$lib/paraglide/messages.js`,同步 `messages/zh-CN.json`、`messages/en-US.json`、`messages/ja-JP.json`。
25
+ - 所有用户可见文本走 `#lib/paraglide/messages.js`,同步 `messages/zh-CN.json`、`messages/en-US.json`、`messages/ja-JP.json`。
44
26
  - API 边界必须做 Zod 校验,HaiResult 错误用 kit response 转换。
45
27
  - `+server.ts` 只能导出 handler 和 SvelteKit 允许的配置项;helper 放到 `src/lib/server/**`。
46
28
  - 本样板默认不使用 `@h-ai/serv`、`@h-ai/api-contract`、`@h-ai/api-client`、`@h-ai/capacitor` 作为主架构。
47
29
 
48
- ## 工作流程
49
-
50
- 1. 先搜索现有路由、service、共享组件、messages 和测试。
51
- 2. 变更权限、登录、会话、导航或 CRUD 页面时,优先扩展现有 service / component,而不是临时散落逻辑。
52
- 3. 修改页面、API、认证流程后,同步测试、README 和 i18n。
53
-
54
- 页面统一继承根布局的 header/footer;新增页面沿用 SvelteKit 自动文件路由,刷新定位及服务端 load/鉴权保持一致。
55
-
56
- ## 代码注释与示例
57
-
58
- - 尽可能补充有信息量的中文 JSDoc:所有 export 的函数/类/方法、核心算法与业务流程、所有数据库表/列、接口/type/schema 及其字段都必须说明用途、单位、约束和关联关系。核心逻辑解释决策原因、边界、权限与失败路径,不逐行复述代码。
59
- - 函数按实际契约写 @param、@returns,仅确实抛错时写 @throws;异步、HaiResult 与事务失败行为须说明。类型/表结构说明字段含义、可空性、默认值、主外键和唯一约束。
60
- - 上述函数和结构的 JSDoc 均提供可理解的 @example:函数给调用及结果判断,结构给合法数据,表给典型行或查询示例。省略上下文要标明,不使用真实凭据。示例随实现同步,不能只堆叠没有信息量的注释。
61
- - 调用及结构示例见 [.agents/skills/hai-app-create/development.md](.agents/skills/hai-app-create/development.md) 的 JSDoc 注释一节。
62
-
63
- ## 质量门禁
64
-
65
- 先核对 package.json,按 [分轮验证与集中修复](.agents/skills/hai-app-tests/validation.md) 收集适用检查与日志,再归并修复、复测失败及受影响项;普通失败不中断独立检查,真实前置阻塞才暂停依赖项。文档检查引用,UI/路由变更加 E2E,未运行项说明原因。
66
-
67
- ```bash
68
- pnpm typecheck
69
- pnpm lint
70
- pnpm build
71
- pnpm test
72
- pnpm test:e2e
73
- ```
74
30
 
75
31
  ## 完成条件
76
32
 
77
- - 修改页面、API、认证流程时同步测试、README 和 i18n。
78
- - 修改公共模块用法或共享组件时,全局检索并同步依赖方。
79
- - 最终回复说明门禁状态、已更新页面 / API / 文档与未完成项。
80
-
81
- ## 优先 Skills
82
-
83
- - `hai-build`、`hai-app-create`、`hai-app-review`、`hai-app-tests`
84
- - `hai-kit`、`hai-ui`、`hai-iam`、`hai-reldb`、`hai-cache`、`hai-crypto`
85
- - 其它 `hai-*` 模块按需读取
86
-
87
- 前端页面先按 [hai-ui-design](.agents/skills/hai-ui-design/SKILL.md) 确定任务、布局、状态与组件映射,使用 [hai-ui](.agents/skills/hai-ui/SKILL.md) 实现,再由 [hai-ui-review](.agents/skills/hai-ui-review/SKILL.md) 检查真实页面。窄范围修改复用已有设计;按实际语言/主题/尺寸验证。
88
-
89
- 工作流技能按 hai-领域-动作 命名,能力使用类沿用领域名。需求、验收、发现与当前版本证据按 [工作交接契约](.agents/skills/hai-spec-implement/handoff.md) 传递,沿既有清单恢复任务。
33
+ 按实际 package scripts 和 [分轮验证](.agents/skills/hai-app-tests/validation.md) 选择受影响范围,依次收集 typecheck → lint → build(需要时)→ test → 相关 E2E;例如 `pnpm typecheck`。普通失败不中断独立检查,汇总后集中修复并定向复测。报告实际结果、文档/调用方同步与未验证原因;不能用静态、mock 或 Web 结果代替真实业务、外部服务或原生验证。
@@ -2,35 +2,17 @@
2
2
 
3
3
  > API 服务项目 AI 编程助手入口。优先结合 `README.md`、`.agents/skills/`、`apps/*-contract/src/**`、`apps/*-serv/src/**` 与测试工作。
4
4
 
5
- ## 需求与模板
6
-
7
- - 业务行为以用户当前明确要求及其指定的需求/设计文档为准。本文件、README、skills、示例、生成代码及其测试中的模板默认行为是起点,不是不可变的业务约束;角色代码、权限模型、页面流程、字段、限额、存储方式与架构均可按实际需求调整。
8
- - 需求与模板不同,审查时记录为模板适配项,不据此判定需求错误或阻塞审查,也不要求用户额外授权“覆盖模板”;实施时在已有授权范围内修改或移除冲突逻辑,并同步 contract、鉴权、数据迁移、界面、配置、测试、文档及本文件中的过期规则。
9
- - 未说明的行为可参考现有实现并注明假设,不能升级为强制需求。只有业务要求自身矛盾、与已确认项目决策的优先级不明,或存在真实技术/安全障碍时才提出具体问题;已明确的规则不重复要求选择。
10
- - 业务规则与技术契约分别判断:可用 API 以当前安装版本的公开类型为准;输入校验、服务端授权、资源隔离和密钥保护仍须落实。需求涉及替换技术方案时说明影响并同步迁移,不能用保留模板默认值代替解决问题。
11
5
 
12
6
  ## 行为契约
13
7
 
14
- 涉及框架结构、配置、核心流程或模块边界变更时,先按 [变更影响与方案确认](.agents/skills/hai-change-plan/SKILL.md) 说明影响并等待用户决定;已确认且未扩大的方案继续执行。
15
-
16
- 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
17
-
18
- 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
19
-
20
- 根据文档规划、实施、继续、返修或按已提交文档变更同步实现时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):维护 docs 清单与任务记录,比较已验收与目标文档 Git 快照,更新原任务或新建任务,每项独立分支 TDD、验证并本地合并;全部差异与整体验收通过后才推进基线。返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
8
+ 先读 [项目共同规则](.agents/skills/hai-app-create/project.md),按当前任务读取下面的入口;不要加载整个 skill 树。业务以用户当前明确要求及指定文档为准,模板行为是可调整的起点。
21
9
 
22
- 普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
23
-
24
- - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
25
- - 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
26
- - 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
27
- - 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
28
- - 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
29
-
30
- 先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
31
-
32
- - 直接影响:哪些 `apps/*-contract`、`apps/*-serv`、config、README、测试会变。
33
- - 间接影响:哪些 typed client、部署脚本、环境变量说明和断言需要同步。
10
+ | 任务 | 入口 |
11
+ | --- | --- |
12
+ | 新增、修改、修复应用 | [hai-app-create](.agents/skills/hai-app-create/SKILL.md);配置、注释与能力选择按需查 [development.md](.agents/skills/hai-app-create/development.md) |
13
+ | 需求/设计文档审查 | [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md) |
14
+ | 文档驱动规划、实施或返修 | [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md) |
15
+ | 代码审查 / 测试 / 构建 / 升级 | 按任务读取同名 hai-app-review / hai-app-tests / hai-build / hai-framework-sync;模块按实际依赖选择 |
34
16
 
35
17
  ## 项目定位
36
18
 
@@ -44,40 +26,7 @@
44
26
  - 纯 API 需求不生成用户页面或引入 UI 专属依赖;需求增加前端时,按实际架构补充应用及其文案和验证。
45
27
  - 配置和密钥来自 `apps/*-serv/config/` 与环境变量,禁止硬编码。
46
28
 
47
- ## 工作流程
48
-
49
- 1. 先搜索现有 contract、procedures、init、config 和测试。
50
- 2. 修改 contract、响应格式、安全策略或配置时,同步 README、typed client 调用方与测试。
51
- 3. 按改动范围验证,修复本次引入的失败;已有问题与未运行项明确报告。
52
-
53
- ## 代码注释与示例
54
-
55
- - 尽可能补充有信息量的中文 JSDoc:所有 export 的函数/类/方法、核心算法与业务流程、所有数据库表/列、接口/type/schema 及其字段都必须说明用途、单位、约束和关联关系。核心逻辑解释决策原因、边界、权限与失败路径,不逐行复述代码。
56
- - 函数按实际契约写 @param、@returns,仅确实抛错时写 @throws;异步、HaiResult 与事务失败行为须说明。类型/表结构说明字段含义、可空性、默认值、主外键和唯一约束。
57
- - 上述函数和结构的 JSDoc 均提供可理解的 @example:函数给调用及结果判断,结构给合法数据,表给典型行或查询示例。省略上下文要标明,不使用真实凭据。示例随实现同步,不能只堆叠没有信息量的注释。
58
- - 调用及结构示例见 [.agents/skills/hai-app-create/development.md](.agents/skills/hai-app-create/development.md) 的 JSDoc 注释一节。
59
-
60
- ## 质量门禁
61
-
62
- 先核对 package.json,按 [分轮验证与集中修复](.agents/skills/hai-app-tests/validation.md) 收集适用检查与日志,再归并修复、复测失败及受影响项;普通失败不中断独立检查,真实前置阻塞才暂停依赖项。文档检查引用,UI/路由变更加 E2E,未运行项说明原因。
63
-
64
- ```bash
65
- pnpm typecheck
66
- pnpm lint
67
- pnpm build
68
- pnpm test
69
- pnpm test:e2e
70
- ```
71
29
 
72
30
  ## 完成条件
73
31
 
74
- - 修改 contract、procedure、配置或环境变量说明后,同步测试、README 和调用方。
75
- - 最终回复说明门禁状态、已更新 contract / service / 配置 / 文档与未完成项。
76
-
77
- ## 优先 Skills
78
-
79
- - `hai-build`、`hai-app-create`、`hai-app-review`、`hai-app-tests`
80
- - `hai-serv`、`hai-api-contract`、`hai-api-client`
81
- - `hai-core`、`hai-reldb`、`hai-cache`、`hai-iam`、`hai-crypto`
82
-
83
- 工作流技能按 hai-领域-动作 命名,能力使用类沿用领域名。需求、验收、发现与当前版本证据按 [工作交接契约](.agents/skills/hai-spec-implement/handoff.md) 传递,沿既有清单恢复任务。
32
+ 按实际 package scripts 和 [分轮验证](.agents/skills/hai-app-tests/validation.md) 选择受影响范围,依次收集 typecheck → lint → build(需要时)→ test → 相关 E2E;例如 `pnpm typecheck`。普通失败不中断独立检查,汇总后集中修复并定向复测。报告实际结果、文档/调用方同步与未验证原因;不能用静态、mock 或 Web 结果代替真实业务、外部服务或原生验证。