@h-ai/cli 0.1.0-alpha.61 → 0.1.0-alpha.63

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 (71) hide show
  1. package/README.en.md +21 -3
  2. package/README.ja.md +21 -3
  3. package/README.md +21 -3
  4. package/dist/{chunk-WWG3U5ZD.js → chunk-X3RSYNBG.js} +8 -3
  5. package/dist/chunk-X3RSYNBG.js.map +1 -0
  6. package/dist/{cli-skill-templates-2KDUACT6.js → cli-skill-templates-EZFW7D43.js} +3 -3
  7. package/dist/{cli-skill-templates-2KDUACT6.js.map → cli-skill-templates-EZFW7D43.js.map} +1 -1
  8. package/dist/index.js +7 -5
  9. package/dist/index.js.map +1 -1
  10. package/package.json +7 -7
  11. package/templates/README.md +9 -4
  12. package/templates/apps/api/e2e/capture-evidence.ts.hbs +23 -0
  13. package/templates/apps/api/playwright.config.ts.hbs +1 -0
  14. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +123 -4
  15. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +2 -0
  16. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +1 -21
  17. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +1 -1
  18. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +11 -1
  19. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +19 -1
  20. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +19 -1
  21. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +7 -2
  22. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +5 -3
  23. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ProfileSettings.svelte.hbs +5 -5
  24. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/UserManagement.svelte.hbs +20 -18
  25. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +55 -0
  26. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +2 -2
  27. package/templates/apps/fullstack/playwright.config.ts.hbs +21 -10
  28. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +24 -22
  29. package/templates/base/e2e/app.spec.ts.hbs +10 -6
  30. package/templates/base/package.json.hbs +1 -1
  31. package/templates/skills/AGENTS.md +6 -0
  32. package/templates/skills/bridges/admin/AGENTS.md +6 -0
  33. package/templates/skills/bridges/api/AGENTS.md +6 -0
  34. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +6 -0
  35. package/templates/skills/bridges/h5/AGENTS.md +6 -0
  36. package/templates/skills/bridges/mobile-app/AGENTS.md +6 -0
  37. package/templates/skills/bridges/website/AGENTS.md +6 -0
  38. package/templates/skills/copilot-instructions.md +3 -9
  39. package/templates/skills/hai-app-create/SKILL.md +6 -0
  40. package/templates/skills/hai-app-create/development.md +10 -6
  41. package/templates/skills/hai-audit/SKILL.md +1 -1
  42. package/templates/skills/hai-build/SKILL.md +1 -0
  43. package/templates/skills/hai-build/reference.md +1 -1
  44. package/templates/skills/hai-ci/SKILL.md +1 -1
  45. package/templates/skills/hai-framework-sync/SKILL.md +67 -70
  46. package/templates/skills/hai-framework-sync/sync.md +49 -0
  47. package/templates/skills/hai-iam/SKILL.md +5 -0
  48. package/templates/skills/hai-iam/reference.md +88 -7
  49. package/templates/skills/hai-kit/SKILL.md +4 -0
  50. package/templates/skills/hai-pr-review/SKILL.md +1 -1
  51. package/templates/skills/hai-reach/SKILL.md +1 -1
  52. package/templates/skills/hai-reach/reference.md +4 -5
  53. package/templates/skills/hai-serv/SKILL.md +1 -1
  54. package/templates/skills/hai-serv/reference.md +9 -6
  55. package/templates/skills/hai-spec-implement/SKILL.md +41 -0
  56. package/templates/skills/hai-spec-implement/templates.md +90 -0
  57. package/templates/skills/hai-spec-implement/workflow.md +53 -0
  58. package/templates/skills/hai-spec-review/SKILL.md +44 -0
  59. package/templates/skills/hai-spec-review/checklist.md +70 -0
  60. package/templates/skills/hai-storage/SKILL.md +9 -2
  61. package/templates/skills/hai-ui/SKILL.md +13 -1
  62. package/templates/skills/hai-ui/guide.md +79 -0
  63. package/templates/skills/hai-ui/reference.md +36 -2
  64. package/templates/skills/opencode.json +1 -1
  65. package/dist/chunk-WWG3U5ZD.js.map +0 -1
  66. package/templates/skills/bridges/admin/copilot-instructions.md +0 -11
  67. package/templates/skills/bridges/api/copilot-instructions.md +0 -13
  68. package/templates/skills/bridges/fullstack/copilot-instructions.md.hbs +0 -19
  69. package/templates/skills/bridges/h5/copilot-instructions.md +0 -11
  70. package/templates/skills/bridges/mobile-app/copilot-instructions.md +0 -11
  71. package/templates/skills/bridges/website/copilot-instructions.md +0 -11
@@ -0,0 +1,55 @@
1
+ import type { NavAdapter } from '@h-ai/ui'
2
+ import type { ManagementStore } from './management-store.svelte.js'
3
+ import { createGuide } from '@h-ai/ui/guide'
4
+ import * as m from '../paraglide/messages.js'
5
+
6
+ /** Web/App/Desktop 共用内容;宿主只提供当前页面和平台持久化方式。 */
7
+ export function createManagementGuide(store: ManagementStore, platform: 'web' | 'app' | 'desktop') {
8
+ const nav: NavAdapter = {
9
+ get pathname() {
10
+ return `/${store.page}`
11
+ },
12
+ navigate(route) {
13
+ if (route === '/settings')
14
+ return store.navigate('settings')
15
+ },
16
+ }
17
+ return createGuide({
18
+ nav,
19
+ persistKey: '{{projectName}}-guide',
20
+ persistence: platform === 'web' ? 'cookie' : 'localStorage',
21
+ tours: [{
22
+ id: 'overview',
23
+ title: () => m.guide_overview_title(),
24
+ description: () => m.guide_overview_description(),
25
+ steps: [
26
+ { target: 'admin-content', title: () => m.guide_content_title(), description: () => m.guide_content_description() },
27
+ { target: 'admin-profile', title: () => m.guide_profile_title(), description: () => m.guide_profile_description() },
28
+ { target: 'admin-help', title: () => m.guide_help_title(), description: () => m.guide_help_description() },
29
+ ],
30
+ }, {
31
+ id: 'profile',
32
+ title: () => m.guide_profile_tour_title(),
33
+ description: () => m.guide_profile_tour_description(),
34
+ route: '/settings',
35
+ steps: [
36
+ { target: 'admin-profile-form', title: () => m.guide_profile_title(), description: () => m.guide_profile_form_description() },
37
+ { target: 'admin-preferences', title: () => m.preferences_title(), description: () => m.guide_preferences_description() },
38
+ { target: 'admin-password', title: () => m.guide_password_title(), description: () => m.guide_password_description() },
39
+ ],
40
+ }],
41
+ articles: [{
42
+ id: 'overview',
43
+ title: () => m.guide_overview_title(),
44
+ description: () => m.guide_overview_description(),
45
+ content: () => m.guide_overview_article(),
46
+ tourId: 'overview',
47
+ }, {
48
+ id: 'profile',
49
+ title: () => m.guide_profile_tour_title(),
50
+ description: () => m.guide_profile_tour_description(),
51
+ content: () => m.guide_profile_article(),
52
+ tourId: 'profile',
53
+ }],
54
+ })
55
+ }
@@ -4,7 +4,7 @@ import type { ChangePasswordFormData, UserProfileSubmitData } from '@h-ai/ui'
4
4
  import type { AdminAuditLog, AdminCreateUser, AdminRole, AdminUpdateUser, AdminUser, AvatarUpload, ProfileUpdate } from '{{fullstack.contractPackageName}}'
5
5
  import type { AppInfo, ManagementApiOptions } from '../api/api-client.js'
6
6
  import { HaiApiClientError } from '@h-ai/api-client'
7
- import { core } from '@h-ai/core'
7
+ import { setGlobalLocale } from '@h-ai/ui/i18n'
8
8
  import { SvelteDate } from 'svelte/reactivity'
9
9
  import { initializeManagementApi, managementApi, resolveAvatarUrl } from '../api/api-client.js'
10
10
  import * as m from '../paraglide/messages.js'
@@ -305,7 +305,7 @@ export class ManagementStore {
305
305
  return
306
306
  this.locale = locale
307
307
  setLocale(locale, { reload: false })
308
- core.i18n.setGlobalLocale(locale)
308
+ setGlobalLocale(locale)
309
309
  if (typeof document !== 'undefined')
310
310
  document.documentElement.lang = locale
311
311
  this.onLocaleChange?.(locale)
@@ -4,8 +4,16 @@ import { defineConfig } from '@playwright/test'
4
4
  const defaultBaseURL = '{{#if fullstack.e2eFrontend}}http://127.0.0.1:{{fullstack.e2eFrontend.port}}{{else}}http://127.0.0.1:3000{{/if}}'
5
5
  const defaultServiceBaseURL = 'http://127.0.0.1:3000'
6
6
  const baseURL = process.env.BASE_URL || defaultBaseURL
7
- const frontendHost = resolveHostFromBaseUrl(baseURL, '127.0.0.1')
8
- const frontendPort = resolvePortFromBaseUrl(baseURL, '{{#if fullstack.e2eFrontend}}{{fullstack.e2eFrontend.port}}{{else}}3000{{/if}}')
7
+ const primaryFrontend = '{{fullstack.e2eFrontend.target}}'
8
+ const frontends: { target: string, name: string, url: string }[] = [
9
+ {{#each fullstack.frontendApps}}
10
+ {
11
+ target: '{{target}}',
12
+ name: '{{packageName}}',
13
+ url: process.env.HAI_E2E_{{target}}_URL || 'http://127.0.0.1:{{port}}',
14
+ },
15
+ {{/each}}
16
+ ]
9
17
  const serviceBaseURL = process.env.SERVICE_BASE_URL || defaultServiceBaseURL
10
18
  const serviceHost = resolveHostFromBaseUrl(serviceBaseURL, '127.0.0.1')
11
19
  const servicePort = resolvePortFromBaseUrl(serviceBaseURL, '3000')
@@ -65,13 +73,16 @@ export default defineConfig({
65
73
  url: `${serviceBaseURL}/health`,
66
74
  reuseExistingServer: false,
67
75
  timeout: 120_000,
68
- }{{#if fullstack.e2eFrontend}},
69
- {
70
- name: '{{fullstack.e2eFrontend.packageName}}',
71
- command: `pnpm --filter {{fullstack.e2eFrontend.packageName}} exec vite preview --host ${frontendHost} --port ${frontendPort} --strictPort`,
72
- url: baseURL,
73
- reuseExistingServer: false,
74
- timeout: 120_000,
75
- }{{/if}},
76
+ },
77
+ ...frontends.map((frontend) => {
78
+ const url = frontend.target === primaryFrontend ? baseURL : frontend.url
79
+ return {
80
+ name: frontend.name,
81
+ command: `pnpm --filter ${frontend.name} exec vite preview --host ${resolveHostFromBaseUrl(url, '127.0.0.1')} --port ${resolvePortFromBaseUrl(url, '3000')} --strictPort`,
82
+ url,
83
+ reuseExistingServer: false,
84
+ timeout: 120_000,
85
+ }
86
+ }),
76
87
  ],
77
88
  })
@@ -6,7 +6,7 @@
6
6
  {{#if hasI18n}}
7
7
  import * as m from '$lib/paraglide/messages'
8
8
  {{/if}}
9
- import { Button, Card, FormField, Input, PageHeader } from '@h-ai/ui'
9
+ import { Button, Card, FormField, FormLayout, Input, PageHeader, Textarea } from '@h-ai/ui'
10
10
 
11
11
  let name = $state('')
12
12
  let email = $state('')
@@ -33,30 +33,32 @@
33
33
  {{/if}}
34
34
 
35
35
  <Card shadow='sm' class='bg-base-100'>
36
- <form class='space-y-4' onsubmit={handleSubmit}>
36
+ <form onsubmit={handleSubmit}>
37
+ <FormLayout columns={2} labelPosition='top'>
37
38
  {{#if hasI18n}}
38
- <FormField label={m.page_contact_name()} required>
39
- <Input id='name' type='text' bind:value={name} required />
40
- </FormField>
41
- <FormField label={m.page_contact_email()} required>
42
- <Input id='email' type='email' bind:value={email} required />
43
- </FormField>
44
- <FormField label={m.page_contact_message()} required>
45
- <textarea id='message' class='textarea textarea-bordered w-full' rows='4' bind:value={message}></textarea>
46
- </FormField>
47
- <Button type='submit' variant='primary' class='w-full'>{m.page_contact_submit()}</Button>
39
+ <FormField for='name' label={m.page_contact_name()} required>
40
+ <Input id='name' type='text' bind:value={name} required />
41
+ </FormField>
42
+ <FormField for='email' label={m.page_contact_email()} required>
43
+ <Input id='email' type='email' bind:value={email} required />
44
+ </FormField>
45
+ <FormField for='message' label={m.page_contact_message()} required>
46
+ <Textarea id='message' rows={4} bind:value={message} required />
47
+ </FormField>
48
+ <Button type='submit' variant='primary' class='w-full'>{m.page_contact_submit()}</Button>
48
49
  {{else}}
49
- <FormField label='姓名' required>
50
- <Input id='name' type='text' bind:value={name} required />
51
- </FormField>
52
- <FormField label='邮箱' required>
53
- <Input id='email' type='email' bind:value={email} required />
54
- </FormField>
55
- <FormField label='留言' required>
56
- <textarea id='message' class='textarea textarea-bordered w-full' rows='4' bind:value={message}></textarea>
57
- </FormField>
58
- <Button type='submit' variant='primary' class='w-full'>发送</Button>
50
+ <FormField for='name' label='姓名' required>
51
+ <Input id='name' type='text' bind:value={name} required />
52
+ </FormField>
53
+ <FormField for='email' label='邮箱' required>
54
+ <Input id='email' type='email' bind:value={email} required />
55
+ </FormField>
56
+ <FormField for='message' label='留言' required>
57
+ <Textarea id='message' rows={4} bind:value={message} required />
58
+ </FormField>
59
+ <Button type='submit' variant='primary' class='w-full'>发送</Button>
59
60
  {{/if}}
61
+ </FormLayout>
60
62
  </form>
61
63
  </Card>
62
64
  </section>
@@ -1,10 +1,15 @@
1
- {{#if features.iam}}
2
1
  import { mkdir } from 'node:fs/promises'
3
2
  import path from 'node:path'
4
- {{/if}}
5
3
  import process from 'node:process'
6
4
  import { expect, test } from '@playwright/test'
7
5
 
6
+ {{#if_eq appType 'h5'}}
7
+ test.use({ viewport: { width: 390, height: 844 } })
8
+ {{/if_eq}}
9
+ {{#if isCapacitorApp}}
10
+ test.use({ viewport: { width: 390, height: 844 } })
11
+ {{/if}}
12
+
8
13
  /** 首页从真实浏览器页面发起,覆盖基础渲染链路。 */
9
14
  test('home page renders from browser', async ({ page }) => {
10
15
  {{#if_eq appType 'h5'}}
@@ -24,12 +29,11 @@ test('home page renders from browser', async ({ page }) => {
24
29
  await nav.getByRole('button', { name: /首页|Home/i, exact: true }).click()
25
30
  await expect(page).toHaveURL(/\/$/)
26
31
  expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
27
- {{#if features.iam}}
32
+ {{/if_eq}}
28
33
  const evidence = process.env.HAI_AUTH_EVIDENCE_DIR || path.resolve('test-results/auth-screenshots')
29
34
  await mkdir(evidence, { recursive: true })
30
- await page.screenshot({ path: path.join(evidence, '{{projectName}}-home.png'), fullPage: true })
31
- {{/if}}
32
- {{/if_eq}}
35
+ await page.evaluate(() => document.fonts.ready)
36
+ await page.screenshot({ path: path.join(evidence, '{{projectName}}-home.png'), fullPage: true, animations: 'disabled' })
33
37
  })
34
38
  {{#if features.iam}}
35
39
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "engines": { "node": "^22.22.2 || ^24.15.0 || >=26.0.0" },
3
3
  "name": "{{projectName}}",
4
- "version": "0.1.0-alpha.61",
4
+ "version": "0.1.0-alpha.63",
5
5
  "private": true,
6
6
  "packageManager": "pnpm@12.11.2",
7
7
  "description": "{{#if_eq appType 'admin'}}Enterprise management system built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'website'}}Enterprise website built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'h5'}}Mobile H5 app built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'api'}}REST API service built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'mobile-app'}}Mobile app built with hai Agent Framework{{/if_eq}}",
@@ -4,6 +4,12 @@
4
4
 
5
5
  ## 行为契约
6
6
 
7
+ 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
8
+
9
+ 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
10
+
11
+ 根据文档规划、实施、继续或返修任务时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):审查后按可验收功能和依赖拆分,维护 docs 下的清单及 docs/tasks 下的任务信息,每项独立分支 TDD、验证并本地合并;返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
12
+
7
13
  普通新增、修改、修复任务开始前,先读 [应用开发 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
14
 
9
15
  - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
@@ -4,6 +4,12 @@
4
4
 
5
5
  ## 行为契约
6
6
 
7
+ 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
8
+
9
+ 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
10
+
11
+ 根据文档规划、实施、继续或返修任务时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):审查后按可验收功能和依赖拆分,维护 docs 下的清单及 docs/tasks 下的任务信息,每项独立分支 TDD、验证并本地合并;返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
12
+
7
13
  普通新增、修改、修复任务开始前,先读 [应用开发 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
14
 
9
15
  - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
@@ -4,6 +4,12 @@
4
4
 
5
5
  ## 行为契约
6
6
 
7
+ 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
8
+
9
+ 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
10
+
11
+ 根据文档规划、实施、继续或返修任务时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):审查后按可验收功能和依赖拆分,维护 docs 下的清单及 docs/tasks 下的任务信息,每项独立分支 TDD、验证并本地合并;返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
12
+
7
13
  普通新增、修改、修复任务开始前,先读 [应用开发 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
14
 
9
15
  - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
@@ -4,6 +4,12 @@ Fullstack 多包工程入口。先读 README、根 workspace 脚本与相关 pac
4
4
 
5
5
  ## 行为契约
6
6
 
7
+ 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
8
+
9
+ 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
10
+
11
+ 根据文档规划、实施、继续或返修任务时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):审查后按可验收功能和依赖拆分,维护 docs 下的清单及 docs/tasks 下的任务信息,每项独立分支 TDD、验证并本地合并;返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
12
+
7
13
  普通新增、修改、修复任务开始前,先读 [应用开发 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
14
 
9
15
  - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
@@ -4,6 +4,12 @@
4
4
 
5
5
  ## 行为契约
6
6
 
7
+ 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
8
+
9
+ 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
10
+
11
+ 根据文档规划、实施、继续或返修任务时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):审查后按可验收功能和依赖拆分,维护 docs 下的清单及 docs/tasks 下的任务信息,每项独立分支 TDD、验证并本地合并;返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
12
+
7
13
  普通新增、修改、修复任务开始前,先读 [应用开发 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
14
 
9
15
  - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
@@ -4,6 +4,12 @@
4
4
 
5
5
  ## 行为契约
6
6
 
7
+ 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
8
+
9
+ 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
10
+
11
+ 根据文档规划、实施、继续或返修任务时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):审查后按可验收功能和依赖拆分,维护 docs 下的清单及 docs/tasks 下的任务信息,每项独立分支 TDD、验证并本地合并;返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
12
+
7
13
  普通新增、修改、修复任务开始前,先读 [应用开发 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
14
 
9
15
  - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
@@ -4,6 +4,12 @@
4
4
 
5
5
  ## 行为契约
6
6
 
7
+ 需求/设计文档审查或从文档生成代码时,读取 [hai-spec-review](.agents/skills/hai-spec-review/SKILL.md),严格确认完备性、歧义、技术正确性与命名一致性;影响行为的问题未解决前不判定文档可生成。普通小改动不重审无关文档。
8
+
9
+ 升级 hai-framework 到最新/指定版本、比较版本差异或同步框架 skills 时,先读 [框架升级与同步 Skill](.agents/skills/hai-framework-sync/SKILL.md),执行版本发现、差异分析、用户选择/阻塞处理、迁移与验证;仅要求比较时不修改应用。
10
+
11
+ 根据文档规划、实施、继续或返修任务时,读取 [hai-spec-implement](.agents/skills/hai-spec-implement/SKILL.md):审查后按可验收功能和依赖拆分,维护 docs 下的清单及 docs/tasks 下的任务信息,每项独立分支 TDD、验证并本地合并;返修复用原任务与分支。仅规划不实施,指定任务先核验依赖。
12
+
7
13
  普通新增、修改、修复任务开始前,先读 [应用开发 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
14
 
9
15
  - 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
@@ -1,11 +1,5 @@
1
- # GitHub Copilot 项目指令
1
+ # GitHub Copilot 入口
2
2
 
3
- > 本文件作为 Copilot 项目级指引;当缺少 appType 专属桥接时,使用本文件作为 generic fallback。详细用法按需读取 `.agents/skills/`。
3
+ 先读取共享入口 [AGENTS.md](../AGENTS.md),按其中的项目架构、行为契约、质量门禁和完成条件执行任务。模块与工作流按需读取 `.agents/skills/` 的正文和相邻参考文件。
4
4
 
5
- 共享规则见项目根 [AGENTS.md](../AGENTS.md);若未自动加载,先读取该文件。模块/流程按需读取项目根 .agents/skills/<name>/SKILL.md 及其相邻参考文件。
6
-
7
- ## 质量门禁
8
-
9
- 按 AGENTS.md 和实际 package.json 选择 typecheck、lint、build、test、test:e2e;最终说明已执行结果、未运行原因及同步文档/依赖方。
10
-
11
- 普通新增、修改、修复任务先读 [应用开发 Skill](../.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](../.agents/skills/hai-app-create/development.md),依照 AGENTS.md 的默认规则复用框架并完成安全与质量验证。
5
+ 项目规则统一在 `AGENTS.md` 维护;本文件仅提供工具入口。
@@ -17,6 +17,10 @@ description: "在 hai 应用中新增、修改或修复功能,按需求复用
17
17
 
18
18
  ## 使用路径
19
19
 
20
+ 从需求/设计文档开始生成项目或功能前,使用 [hai-spec-review](../hai-spec-review/SKILL.md) 检查文档是否足以确定实现;修正影响行为的缺项、歧义和技术错误后再进入生成。普通小改动按本次范围确认规则,不要求重审无关文档。
21
+
22
+ 需要按文档规划/执行任务或返修已交付任务时,使用 [hai-spec-implement](../hai-spec-implement/SKILL.md) 管理 docs 清单、任务记录、TDD 和任务分支;本 skill 负责其中的具体应用实现,复用记录中的范围与验收。
23
+
20
24
  需要新建项目、添加模块、补齐配置或生成代码时,先按 [CLI 安装与命令](development.md#cli-安装与命令) 全局安装 `@h-ai/cli`,再执行 `hai` 命令。
21
25
 
22
26
  1. 读取 [development.md](development.md):先按真实需求匹配框架能力、已安装版本与应用架构,再确定改动。适用能力包括同一模块已有 feature、配置和扩展点,不以导入包作为复用完成的证据。
@@ -26,6 +30,8 @@ description: "在 hai 应用中新增、修改或修复功能,按需求复用
26
30
 
27
31
  ## 按需参考
28
32
 
33
+ 新增新手引导或帮助说明时读取 [UI 引导指南](../hai-ui/guide.md),复用 fullstack 默认的共享 guide-store、locale 和稳定 data-guide 锚点。
34
+
29
35
  详细配置、API 签名、错误码和范本在 [reference.md](reference.md)。按下列标题定位所需小节,不默认通读;用例中的业务变量需结合当前应用补齐。
30
36
 
31
37
  - 适用场景
@@ -4,10 +4,12 @@
4
4
 
5
5
  ## 先确认应用与版本
6
6
 
7
+ - 新手引导与帮助中心使用 `@h-ai/ui/guide`,按 [UI 引导指南](../hai-ui/guide.md) 接入。fullstack 的共享管理界面已有默认帮助入口;业务内容放共享 guide-store,使用应用 i18n 和稳定 data-guide 锚点,不重复实现浮层。
8
+
7
9
  - 读取当前 `AGENTS.md`、README、`package.json`、lockfile、初始化入口和已有相似功能;用 `rg` 查实现、引用、测试。保留已有改动,沿用项目分层、命名、ESLint、i18n 与测试入口。
8
10
  - 确认架构:SvelteKit 使用 `kit` 和文件路由;API workspace 使用 contract/service;fullstack 使用 contract/serv/shared 与所选前端;Vite SPA/原生端通过 typed API 客户端调用服务。不要把服务端目录、DB、密钥或 Node 初始化复制到浏览器。
9
11
  - 从所属 workspace 的依赖与 lockfile 确认 `@h-ai/*` 实际解析版本和 npm/local 模式。模板 skill 提供导航,**当前安装包的 `package.json.exports`、公开 `.d.ts` 与随包文档决定可用 API**;本地框架源码只在版本匹配或显式联调时作实现证据。
10
- - 若 skill 与安装版本不符,以公开类型和实际行为核验。先使用已支持能力;任务确需新版本时列明版本变更、调用方与验证范围。不能直接复制未发布源码的 API,也不能为绕过差异添加虚构兼容层。
12
+ - 若 skill 与安装版本不符,以公开类型和实际行为核验。先使用已支持能力;任务要求升级时按 [hai-framework-sync](../hai-framework-sync/SKILL.md) 发现目标、比较差异并完成迁移验证。不能直接复制未发布源码的 API,也不能为绕过差异添加虚构兼容层。
11
13
 
12
14
  ## CLI 安装与命令
13
15
 
@@ -28,7 +30,7 @@ hai create my-app
28
30
 
29
31
  应用元信息只有一份配置来源:名称、版本、环境、默认语言与日志设置来自 `_core.yml`,使用 `core.config` 与 `core.logger`;Node 启动时不通过固定 `logging` 覆盖 YAML。SvelteKit 服务端 layout 和 fullstack `app.info` 仅公开必要元信息,不能下发整个 core 或模块配置。独立 Vite mobile-app 在 Node 构建阶段经 core 加载 YAML/环境覆盖并注入公开字段,配置变化需重新构建。环境覆盖使用 `HAI_CORE_NAME`、`HAI_CORE_VERSION`、`HAI_CORE_ENV`、`HAI_CORE_LOGGING_LEVEL` 等既有规则;容器明确配置生产环境,不能用另一个状态来源代替 `core.env`。
30
32
 
31
- 开发前,对本次涉及的需求简述“需求 → 现有应用实现/框架能力 → 版本与契约依据 → 修改位置与验收”。简单任务可用几句话;跨模块任务用表格。查找顺序:已有应用实现 → 框架公开能力和配置 → 最小业务补充。
33
+ 开发前,对本次涉及的需求简述“需求 → 现有应用实现/框架能力 → 已安装版本与公开契约依据 → 最小业务补充/修改位置 → 成功、权限与失败验收”。简单任务可用几句话;跨模块任务用表格。查找顺序:已有应用实现 → 框架公开能力和配置 → 最小业务补充。
32
34
 
33
35
  下表技能名用于能力导航;先确认 `.agents/skills/<name>/SKILL.md` 存在再读取。CLI 按应用类型/已选模块交付技能,缺目录不代表框架没有该能力:继续查已安装包的公开 exports/types;确需补充模块/技能时按当前 CLI 帮助和项目依赖策略处理,不能跳过需求匹配或猜测不存在的 API。
34
36
 
@@ -37,20 +39,20 @@ hai create my-app
37
39
  | 配置、日志、ID、结果/错误、i18n | `hai-core` | getter、logger、ID 是直接值;ID 不作为密钥 |
38
40
  | 数据库查询、CRUD、事务、分页 | `hai-reldb` | 先检查现有 CRUD/Repository 与事务支持,不另建 DB 连接层 |
39
41
  | 缓存、TTL、共享锁 | `hai-cache` | 区分 memory 与共享后端;单进程状态不能承担跨节点防重 |
40
- | 注册、登录、会话、角色/权限 | `hai-iam` | 优先配置内置认证能力;业务资源/租户授权仍由应用检查 |
42
+ | 注册、登录、会话、角色/权限 | `hai-iam` | 优先配置内置认证能力;受保护请求使用 iam.auth.verifyToken,serv 注入 IAM 时自动使用;批量用户与角色筛选复用公开 API;业务资源/租户授权仍由应用检查 |
41
43
  | SvelteKit Hook、守卫、校验、响应 | `hai-kit` | 只用于 SvelteKit;沿用已有认证/transport 管道 |
42
44
  | 共享输入输出和 HTTP contract | `hai-api-contract` | 扩展已有 contract 与 schema,不维护第二份业务路径 |
43
45
  | API 运行时、内置 feature、route guard | `hai-serv` | 先检查内置 procedures/features 与 route auth/permission;不另写平行服务器 |
44
46
  | 浏览器/原生 API、刷新会话 | `hai-api-client` | 已支持接口复用 typed client、认证与 transport;额外 fetch/刷新封装需有缺口依据 |
45
47
  | 页面、表单、表格、弹窗、移动 UI | `hai-ui` | 按实际导出选择场景/组合/原子组件;应用补业务交互 |
46
- | 文件上传、下载、元数据、预签名 URL | `hai-storage` | 检查已有 storage feature;资源授权、大小/类型/路径限制不可省略 |
48
+ | 文件上传、下载、元数据、预签名 URL | `hai-storage` | 检查已有 storage feature;大文件用流式读写,checksum 按实际字节计算,ifNoneMatch 拒覆盖;资源授权、大小/类型/路径限制不可省略 |
47
49
  | 加密、签名、哈希 | `hai-crypto` | 复用公开 API 与密钥配置,不自创加密或硬编码密钥 |
48
50
  | LLM、流式、Embedding、RAG、Agent/MCP | `hai-ai` | 先检查内置能力与 provider 配置,再补应用编排 |
49
51
  | 文本清洗、分块、管线 | `hai-datapipe` | 纯函数无生命周期;分块不代表已经生成向量 |
50
52
  | 向量集合与检索 | `hai-vecdb` | 后端、维度与过滤条件使用实际契约 |
51
- | 邮件/短信/通知触达 | `hai-reach` | 复用已有 provider;投递状态不等于 HTTP 成功 |
53
+ | 邮件/短信/通知触达 | `hai-reach` | 模板已绑定 provider 时只传 template/to/vars;直接发送才指定 provider;投递状态不等于 HTTP 成功 |
52
54
  | 支付、订单、订阅、回调 | `hai-payment` | 验签、金额/订单绑定、幂等与状态迁移仍需业务验收 |
53
- | 操作审计 | `hai-audit` | 复用审计记录/查询;应用决定脱敏、保留期及失败策略 |
55
+ | 操作审计 | `hai-audit` | 复用审计记录/查询与 PaginatedResult 元数据;应用决定脱敏、保留期及失败策略 |
54
56
  | cron、持久任务、重试、手工触发 | `hai-scheduler` | 复用任务模型;明确取消、幂等、共享锁及可信代码边界 |
55
57
  | 原生设备与安全 token 存储 | `hai-capacitor` | 仅在适用平台启用;桌面/小程序依当前项目适配 |
56
58
 
@@ -62,6 +64,8 @@ Fullstack 创建时在被 Git 与容器构建忽略的根 `.env` 写入独立随
62
64
 
63
65
  ## 落实契约与安全边界
64
66
 
67
+ 沿现有服务层按顺序落实 schema → 当前授权与操作权限 → 从资源 ID 查所有者/范围 → 需要时核验对应操作凭据 → 存储/通知等副作用 → HaiResult 与审计。框架身份授权不能替代业务资源范围,数据库实体/存储 key 不交给客户端决定。文件失败、checksum 不匹配、不可覆盖冲突及通知失败/延迟分别向调用方反馈,并按业务一致性要求事务回滚或补偿;不能静默返回成功。
68
+
65
69
  按本次真实输入、资源和副作用选取下面检查,并把适用项变成可观察验收。不能用“已遵循安全规范”或 lint 通过替代行为证据。
66
70
 
67
71
  | 边界 | 实现要求 | 验收证据 |
@@ -83,7 +83,7 @@ if (!closeResult.success) {
83
83
  | 方法 | 签名 | 说明 |
84
84
  | --------------------- | ----------------------------------------------------------------------------------- | -------------------- |
85
85
  | `audit.log` | `(input: CreateAuditLogInput) => Promise<HaiResult<AuditLog>>` | 记录审计日志 |
86
- | `audit.list` | `(options?: ListAuditLogsOptions) => Promise<HaiResult<{ items, total }>>` | 分页查询(含用户名) |
86
+ | `audit.list` | `(options?: ListAuditLogsOptions) => Promise<HaiResult<PaginatedResult<AuditLogWithUser>>>` | 分页查询(items/total/page/pageSize,含用户名;使用返回的规范化元数据,默认 pageSize 20) |
87
87
  | `audit.getUserRecent` | `(userId: string, limit?: number) => Promise<HaiResult<AuditLog[]>>` | 用户最近活动 |
88
88
  | `audit.cleanup` | `(olderThanDays?: number) => Promise<HaiResult<number>>` | 清理旧日志 |
89
89
  | `audit.getStats` | `(days?: number) => Promise<HaiResult<AuditStatItem[]>>` | 操作统计 |
@@ -18,6 +18,7 @@ description: "定位 hai 应用架构、模块依赖、初始化顺序、构建
18
18
  ## 使用路径
19
19
 
20
20
  - 先读当前 package.json、lockfile 与 README,识别 SvelteKit / API workspace / fullstack / Vite SPA / 原生 App,按实际 scripts 验证。
21
+ - 升级 hai-framework、比较版本差异或同步框架 skills 时,使用 [hai-framework-sync](../hai-framework-sync/SKILL.md) 完成版本发现、差异分析、选择/阻塞处理、迁移与验证。
21
22
  - 功能开发先用 [development.md](../hai-app-create/development.md) 把需求匹配到当前版本的框架能力与配置;再读取所选模块 skill 和公开类型。
22
23
  - 有生命周期的模块按真实依赖初始化、检查结果并反序清理;core、纯函数和工厂不套用相同生命周期。
23
24
  - 构建任务检查当前 engines、适配器、环境变量、缓存与目标产物,不能照搬框架仓库私有构建命令。
@@ -243,7 +243,7 @@ logging:
243
243
  | 编写/补充测试 | `hai-app-tests` | 测试, test, 单测, 覆盖率, TDD, E2E |
244
244
  | CI/CD 与质量门禁 | `hai-ci` | CI, CD, GitHub Actions, workflow, secret scan |
245
245
  | PR / Issue 交付审查 | `hai-pr-review` | PR, pull request, issue, CODEOWNERS, 自动 Review, AI Review |
246
- | hai-framework 同步 | `hai-framework-sync` | hai-framework, skills 同步, framework:use:local, framework:watch |
246
+ | hai-framework 升级与同步 | `hai-framework-sync` | 升级框架, 最新版本, 版本差异, skills 同步, npm/local 漂移 |
247
247
 
248
248
  ## 行为开发工作流
249
249
 
@@ -107,6 +107,6 @@ lint/typecheck 只能执行已配置的规则。新增开发规范时区分可
107
107
  - `hai-app-tests` — Vitest / Playwright 测试规范
108
108
  - `hai-pr-review` — PR 审查与 AI Review 策略
109
109
  - `hai-deploy` — 应用部署与云服务开通
110
- - `hai-framework-sync` — hai-framework 与应用仓库同步策略
110
+ - `hai-framework-sync` — 框架版本升级、差异分析与 npm/本地同步
111
111
 
112
112
  涉及发布时按本应用实际 registry/镜像/部署目标核验精确版本与提交,不以 tag 或 CI 绿灯代替发布产物;未经授权不发布。原生/容器交付按当前项目入口单独构建与启动验收,保存产物、平台和行为证据;缺平台写未验证,Web E2E 不代替原生验收。