@namewta/speculo 0.3.3 → 0.3.4

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 (35) hide show
  1. package/README.md +3 -2
  2. package/package.json +1 -1
  3. package/template/skills/typescript-engineering-standards/README.md +36 -0
  4. package/template/skills/typescript-engineering-standards/SKILL.md +158 -0
  5. package/template/skills/typescript-engineering-standards/examples/comment-patterns.md +47 -0
  6. package/template/skills/typescript-engineering-standards/examples/naming-patterns.md +42 -0
  7. package/template/skills/typescript-engineering-standards/examples/project-layouts.md +75 -0
  8. package/template/skills/typescript-engineering-standards/examples/review-output-example.md +25 -0
  9. package/template/skills/typescript-engineering-standards/examples/type-modeling-patterns.md +66 -0
  10. package/template/skills/typescript-engineering-standards/manifest.txt +33 -0
  11. package/template/skills/typescript-engineering-standards/references/00-standard-levels-and-precedence.md +51 -0
  12. package/template/skills/typescript-engineering-standards/references/01-project-architecture-and-directory-layout.md +105 -0
  13. package/template/skills/typescript-engineering-standards/references/02-file-directory-and-symbol-naming.md +117 -0
  14. package/template/skills/typescript-engineering-standards/references/03-modules-imports-exports-and-dependencies.md +111 -0
  15. package/template/skills/typescript-engineering-standards/references/04-typescript-type-system.md +150 -0
  16. package/template/skills/typescript-engineering-standards/references/05-functions-async-errors-and-resources.md +142 -0
  17. package/template/skills/typescript-engineering-standards/references/06-comments-jsdoc-and-documentation.md +104 -0
  18. package/template/skills/typescript-engineering-standards/references/07-testing-strategy.md +84 -0
  19. package/template/skills/typescript-engineering-standards/references/08-react-and-frontend.md +91 -0
  20. package/template/skills/typescript-engineering-standards/references/09-node-cli-and-cross-platform.md +92 -0
  21. package/template/skills/typescript-engineering-standards/references/10-formatting-lint-and-complexity.md +107 -0
  22. package/template/skills/typescript-engineering-standards/references/11-configuration-dependencies-and-ci.md +86 -0
  23. package/template/skills/typescript-engineering-standards/references/12-security-performance-and-i18n.md +65 -0
  24. package/template/skills/typescript-engineering-standards/references/13-git-review-and-delivery.md +79 -0
  25. package/template/skills/typescript-engineering-standards/references/14-adoption-exceptions-and-migration.md +84 -0
  26. package/template/skills/typescript-engineering-standards/references/15-orca-derived-observations.md +54 -0
  27. package/template/skills/typescript-engineering-standards/references/README.md +45 -0
  28. package/template/skills/typescript-engineering-standards/templates/.editorconfig +12 -0
  29. package/template/skills/typescript-engineering-standards/templates/AGENTS.typescript.md +21 -0
  30. package/template/skills/typescript-engineering-standards/templates/code-review-checklist.md +37 -0
  31. package/template/skills/typescript-engineering-standards/templates/package-scripts.json +11 -0
  32. package/template/skills/typescript-engineering-standards/templates/prettier.json +6 -0
  33. package/template/skills/typescript-engineering-standards/templates/pull-request-template.md +37 -0
  34. package/template/skills/typescript-engineering-standards/templates/tsconfig.base.json +17 -0
  35. package/template/skills/typescript-engineering-standards/templates/tsconfig.project-references.json +8 -0
@@ -0,0 +1,117 @@
1
+ # 文件、目录与标识符命名
2
+
3
+ ## 默认命名
4
+
5
+ | 对象 | 默认规则 | 示例 |
6
+ |---|---|---|
7
+ | 目录 | `kebab-case` | `user-auth/` |
8
+ | 普通 TypeScript 文件 | `kebab-case.ts` | `session-expiration-policy.ts` |
9
+ | React 业务组件 | `PascalCase.tsx` | `SessionExpiredDialog.tsx` |
10
+ | Hook | `use-*.ts` / `use-*.tsx` | `use-session-timeout.ts` |
11
+ | 单元测试 | 源文件名 + `.test` | `login-service.test.ts` |
12
+ | 集成测试 | `.integration.test` | `payment-flow.integration.test.ts` |
13
+ | E2E | `.e2e.spec` | `checkout.e2e.spec.ts` |
14
+ | 声明文件 | 环境或能力名 | `electron-api.d.ts` |
15
+ | 工程脚本 | 动宾结构 | `generate-icons.ts` |
16
+
17
+ 若仓库已统一使用 `kebab-case.tsx` 组件文件,应保持一致。不要在同一领域混用两种组件文件命名。
18
+
19
+ ## 文件名表达领域和职责
20
+
21
+ 推荐结构:
22
+
23
+ ```text
24
+ <domain>-<responsibility>.ts
25
+ ```
26
+
27
+ 例如:
28
+
29
+ - `user-session-store.ts`
30
+ - `payment-retry-policy.ts`
31
+ - `terminal-output-parser.ts`
32
+ - `github-auth-client.ts`
33
+ - `workspace-path-validator.ts`
34
+
35
+ ## 职责后缀
36
+
37
+ - `-service`:完成一个应用能力;不得成为万能类。
38
+ - `-repository`:领域对象的持久化抽象。
39
+ - `-client`:调用外部 HTTP、RPC 或 SDK。
40
+ - `-adapter`:在两个接口或模型间适配。
41
+ - `-gateway`:外部系统或资源边界。
42
+ - `-store`:状态存储与更新。
43
+ - `-selector`:从状态中派生数据。
44
+ - `-policy`:可替换的业务决策。
45
+ - `-validator`:校验并返回结果或错误。
46
+ - `-parser`:把外部格式转换为结构化数据。
47
+ - `-serializer`:把结构化数据转换为外部格式。
48
+ - `-mapper`:在两个明确模型之间映射。
49
+ - `-factory`:构造复杂对象或依赖图。
50
+ - `-registry`:注册和查找一组实现。
51
+ - `-scheduler`:计划或调度任务。
52
+ - `-coordinator`:协调多个独立流程。
53
+ - `-contract`:跨模块、跨进程或公开 API 契约。
54
+
55
+ 后缀不能替代领域信息。单独的 `service.ts`、`handler.ts`、`manager.ts` 仍然模糊。
56
+
57
+ ## 默认禁止的模糊名称
58
+
59
+ - `utils.ts`
60
+ - `helpers.ts`
61
+ - `common.ts`
62
+ - `misc.ts`
63
+ - `general.ts`
64
+ - `data.ts`
65
+ - `manager.ts`
66
+ - `processor.ts`
67
+ - `handler.ts`
68
+ - 全局 `types.ts`
69
+ - 全局 `constants.ts`
70
+
71
+ 若父目录已提供完整语义,局部 `types.ts` 或 `constants.ts` 可以存在,但更推荐 `payment-types.ts`、`terminal-constants.ts` 等可搜索名称。
72
+
73
+ ## 标识符
74
+
75
+ | 对象 | 规则 |
76
+ |---|---|
77
+ | 变量、函数、方法 | `camelCase` |
78
+ | 类型、类、组件 | `PascalCase` |
79
+ | 常量 | 真正全局稳定值用 `SCREAMING_SNAKE_CASE` |
80
+ | 私有字段 | 使用 `#field` 或普通 `private`,不加 `_` 前缀 |
81
+ | Hook | `useXxx` |
82
+ | 事件属性 | `onXxx` |
83
+ | 内部事件处理函数 | `handleXxx` |
84
+ | 泛型 | 简单时 `T`,复杂时 `TResult`、`TContext` |
85
+
86
+ ## 布尔命名
87
+
88
+ 优先使用:
89
+
90
+ - `isConnected`
91
+ - `hasPendingChanges`
92
+ - `canRetry`
93
+ - `shouldPersist`
94
+ - `didTimeout`
95
+ - `willReconnect`
96
+
97
+ 避免 `flag`、`enabled`、`notDisabled`、`isNotInvalid` 等含义弱或双重否定名称。
98
+
99
+ ## 单位进入名称
100
+
101
+ 数值变量必须尽量包含单位或语义:
102
+
103
+ ```ts
104
+ const timeoutMs = 30_000
105
+ const payloadSizeBytes = 1_024
106
+ const retryCount = 3
107
+ const pageOffset = 20
108
+ ```
109
+
110
+ ## 避免无信息变量
111
+
112
+ 除极短循环或数学表达式外,避免 `obj`、`data`、`info`、`value`、`result`、`temp`。使用角色名称:
113
+
114
+ - `parsedPayload`
115
+ - `validationResult`
116
+ - `pendingSession`
117
+ - `persistedWorkspace`
@@ -0,0 +1,111 @@
1
+ # 模块、导入、导出与依赖
2
+
3
+ ## 命名导出优先
4
+
5
+ 默认使用命名导出:
6
+
7
+ ```ts
8
+ export function parseTerminalOutput(input: string): ParsedOutput {
9
+ // ...
10
+ }
11
+ ```
12
+
13
+ 默认导出仅用于:
14
+
15
+ - 框架规定的页面、路由或配置入口。
16
+ - 工具链必须的默认导出。
17
+ - 仓库已形成明确且一致的入口惯例。
18
+
19
+ 命名导出便于搜索、自动导入、重构和统一引用名称。
20
+
21
+ ## 一个文件一个主要公开概念
22
+
23
+ 一个文件可包含少量私有辅助函数,但通常只公开一个主要能力或一组高度相关能力。辅助函数达到独立职责后,应拆成具有具体名称的文件。
24
+
25
+ 不要为了测试内部细节而导出私有辅助函数;优先通过公共行为测试,或将真正独立的纯逻辑抽出。
26
+
27
+ ## Barrel 文件
28
+
29
+ 允许 `index.ts`:
30
+
31
+ - 作为包或领域的明确公共入口。
32
+ - 隐藏内部实现并稳定外部 API。
33
+ - 作为依赖装配或框架入口。
34
+
35
+ 禁止:
36
+
37
+ - 每个目录机械创建 `index.ts`。
38
+ - 建立全项目万能 Barrel。
39
+ - 通过 Barrel 暴露内部实现。
40
+ - 通过 Barrel 形成循环依赖。
41
+
42
+ ## 导入顺序
43
+
44
+ 默认顺序:
45
+
46
+ 1. Node.js 内置模块。
47
+ 2. 第三方依赖。
48
+ 3. 项目别名。
49
+ 4. 相对路径实现。
50
+ 5. 类型导入按照工具规则分组或合并。
51
+
52
+ ```ts
53
+ import { readFile } from 'node:fs/promises'
54
+
55
+ import { z } from 'zod'
56
+
57
+ import { createLogger } from '@/shared/logger'
58
+
59
+ import { parseConfig } from './config-parser'
60
+
61
+ import type { AppConfig } from './app-config'
62
+ ```
63
+
64
+ 要求:
65
+
66
+ - Node 内置模块使用 `node:` 前缀。
67
+ - 仅作为类型使用时采用 `import type`。
68
+ - 不保留未使用或重复导入。
69
+ - 副作用导入必须有明确原因。
70
+ - 路径别名对应稳定边界,不用于任意跨层跳转。
71
+
72
+ ## 依赖方向
73
+
74
+ 推荐:
75
+
76
+ ```text
77
+ UI / Entry
78
+
79
+ Application orchestration
80
+
81
+ Domain
82
+
83
+ Ports / contracts
84
+
85
+ Infrastructure adapters
86
+ ```
87
+
88
+ - 领域逻辑不直接依赖数据库、HTTP、文件系统或 UI 框架。
89
+ - 共享模块不依赖具体领域。
90
+ - 底层模块不反向导入界面层。
91
+ - 跨环境调用通过显式契约和适配器。
92
+
93
+ ## 循环依赖
94
+
95
+ 循环依赖是架构问题,不应通过调整导入顺序或增加 Barrel 隐藏。解决方式:
96
+
97
+ - 提取真正共享的契约。
98
+ - 使用依赖注入反转方向。
99
+ - 合并实际属于同一职责的模块。
100
+ - 将端口放在需求方而非实现方。
101
+ - 缩小公共入口。
102
+
103
+ ## 公共 API
104
+
105
+ 公开库或跨包模块应:
106
+
107
+ - 明确列出允许导出的入口。
108
+ - 避免消费者导入内部路径。
109
+ - 不暴露框架、数据库或第三方 SDK 的内部类型,除非这是刻意的 API 设计。
110
+ - 保持输入、输出和错误契约稳定。
111
+ - 变更时考虑语义化版本和迁移说明。
@@ -0,0 +1,150 @@
1
+ # TypeScript 类型系统规范
2
+
3
+ ## 严格模式
4
+
5
+ 新项目必须启用 `strict`。建议逐步启用:
6
+
7
+ ```json
8
+ {
9
+ "compilerOptions": {
10
+ "strict": true,
11
+ "noUncheckedIndexedAccess": true,
12
+ "exactOptionalPropertyTypes": true,
13
+ "noImplicitOverride": true,
14
+ "noImplicitReturns": true,
15
+ "noFallthroughCasesInSwitch": true,
16
+ "useUnknownInCatchVariables": true,
17
+ "verbatimModuleSyntax": true,
18
+ "isolatedModules": true,
19
+ "forceConsistentCasingInFileNames": true
20
+ }
21
+ }
22
+ ```
23
+
24
+ 具体选项需与编译器版本、模块系统和构建工具兼容。
25
+
26
+ ## 禁止传播 `any`
27
+
28
+ 外部或未知值使用 `unknown`,在边界收窄:
29
+
30
+ ```ts
31
+ function parsePayload(input: unknown): ParsedPayload {
32
+ return payloadSchema.parse(input)
33
+ }
34
+ ```
35
+
36
+ `any` 只允许存在于极小的兼容层,例如第三方类型错误或遗留迁移,并必须:
37
+
38
+ - 限定最小作用域。
39
+ - 写明原因与退出条件。
40
+ - 经过运行时验证后再向内部传递。
41
+ - 不进入公共 API。
42
+
43
+ ## 外部输入必须验证
44
+
45
+ 以下数据默认不可信:
46
+
47
+ - HTTP、RPC、WebSocket、IPC 消息。
48
+ - CLI 参数和环境变量。
49
+ - JSON、数据库反序列化、本地存储。
50
+ - 第三方 SDK 返回值。
51
+ - 浏览器消息和插件输入。
52
+
53
+ 类型断言不是验证:
54
+
55
+ ```ts
56
+ // 错误
57
+ const config = JSON.parse(raw) as AppConfig
58
+
59
+ // 正确
60
+ const config = appConfigSchema.parse(JSON.parse(raw))
61
+ ```
62
+
63
+ ## 可辨识联合
64
+
65
+ 使用单一判别字段表达互斥状态:
66
+
67
+ ```ts
68
+ type ConnectionState =
69
+ | { kind: 'idle' }
70
+ | { kind: 'connecting'; startedAtMs: number }
71
+ | { kind: 'connected'; connectionId: string }
72
+ | { kind: 'failed'; error: Error }
73
+ ```
74
+
75
+ 避免多个可能互相矛盾的布尔字段。对状态分支执行穷尽检查;需要 `default` 时使用 `never` 断言。
76
+
77
+ ## `type` 与 `interface`
78
+
79
+ 默认策略可选择其一并保持一致。推荐默认使用 `type`,以下场景使用 `interface`:
80
+
81
+ - 需要声明合并。
82
+ - 公共库希望消费者扩展契约。
83
+ - 面向对象体系明确使用 `implements`。
84
+ - 框架生态已有强约定。
85
+
86
+ 不要在同一领域无理由混用。
87
+
88
+ ## 显式类型和推断
89
+
90
+ 必须显式标注:
91
+
92
+ - 导出函数返回类型。
93
+ - 跨模块公共 API。
94
+ - 插件、回调和扩展点。
95
+ - 递归函数。
96
+ - 权限、金额、状态转换等高风险函数。
97
+
98
+ 局部明显变量和短小私有函数可依赖推断。
99
+
100
+ ## 类型断言
101
+
102
+ 优先顺序:
103
+
104
+ 1. 控制流收窄。
105
+ 2. 类型守卫。
106
+ 3. 运行时 Schema 验证。
107
+ 4. `satisfies`。
108
+ 5. 最后才使用 `as`。
109
+
110
+ 禁止无理由双重断言:
111
+
112
+ ```ts
113
+ value as unknown as UserSession
114
+ ```
115
+
116
+ `@ts-ignore` 默认禁止。必须压制已知编译错误时,优先使用带原因的 `@ts-expect-error`,使错误消失后检查能够失败。
117
+
118
+ ## 空值语义
119
+
120
+ 明确区分:
121
+
122
+ - `property?: T`:属性可能不存在。
123
+ - `property: T | null`:属性存在,但值可以为空。
124
+ - `T | undefined`:查找可能没有结果。
125
+ - `Result<T, E>` 或异常:操作可能失败。
126
+
127
+ 除非外部协议明确区分,不要写 `property?: T | null | undefined`。
128
+
129
+ ## `.d.ts`
130
+
131
+ `.d.ts` 仅用于:
132
+
133
+ - 运行时已有但 TypeScript 不可见的全局声明。
134
+ - 无类型第三方模块声明。
135
+ - 框架或库声明扩展。
136
+ - 发布库生成的公共声明。
137
+
138
+ 普通业务类型放在 `.ts` 中,通过正常模块导入。
139
+
140
+ ## 枚举
141
+
142
+ 默认优先字符串联合或 `as const` 对象。`enum` 主要用于外部协议、位标记、既有 API 或团队明确统一的运行时枚举需求。
143
+
144
+ ## 不可变性
145
+
146
+ - 输入参数尽量使用只读结构。
147
+ - 对外返回 `ReadonlyArray<T>` 或只读对象。
148
+ - 不修改调用方传入对象。
149
+ - 需要排序或变更时先复制。
150
+ - 常量对象使用 `as const` 或 `satisfies`。
@@ -0,0 +1,142 @@
1
+ # 函数、异步、错误与资源生命周期
2
+
3
+ ## 函数职责
4
+
5
+ 函数应只处理一个可命名职责和一个抽象层级。软性目标:
6
+
7
+ - 普通函数尽量不超过约 40 行。
8
+ - 编排函数尽量不超过约 60 行。
9
+ - 嵌套通常不超过三层。
10
+ - 参数超过三个时考虑参数对象。
11
+
12
+ 这些数字用于触发审查,不是机械拆分标准。
13
+
14
+ ## 提前返回
15
+
16
+ 使用 Guard Clause 减少嵌套:
17
+
18
+ ```ts
19
+ function processSession(session: Session | undefined): Result {
20
+ if (!session) {
21
+ return emptyResult
22
+ }
23
+
24
+ if (!session.isActive || !session.userId) {
25
+ return emptyResult
26
+ }
27
+
28
+ return createResult(session)
29
+ }
30
+ ```
31
+
32
+ ## 参数对象
33
+
34
+ 长参数列表或布尔参数应改为具名选项:
35
+
36
+ ```ts
37
+ type CreateSessionOptions = {
38
+ userId: string
39
+ timeoutMs: number
40
+ persistence: 'memory' | 'disk'
41
+ logger: Logger
42
+ }
43
+ ```
44
+
45
+ 避免 `createSession(id, true, false)`。
46
+
47
+ ## 纯逻辑和副作用分离
48
+
49
+ 建议分离:
50
+
51
+ - 解析。
52
+ - 验证。
53
+ - 领域决策。
54
+ - 数据持久化。
55
+ - 流程编排。
56
+
57
+ 纯逻辑不读取隐藏全局状态、不修改输入、不直接访问网络、磁盘、时钟或随机源。将这些依赖作为参数或端口注入。
58
+
59
+ ## Promise 必须有归宿
60
+
61
+ 所有 Promise 必须被 `await`、`return`、显式收集,或用 `void` 明确表示有意脱离当前流程,并自行处理错误:
62
+
63
+ ```ts
64
+ void refreshCache().catch((error: unknown) => {
65
+ logger.error('Failed to refresh cache', { error })
66
+ })
67
+ ```
68
+
69
+ ## 并发
70
+
71
+ 只有相互独立的任务才使用 `Promise.all`。有顺序、共享副作用、速率限制或资源约束时,使用顺序执行、队列或并发限制器。
72
+
73
+ 不要无界并发处理大型输入集合。
74
+
75
+ ## 取消与超时
76
+
77
+ 网络、子进程、文件监听、Worker 和长任务应考虑:
78
+
79
+ - `AbortSignal`。
80
+ - 明确超时。
81
+ - 清理路径。
82
+ - 可识别的取消错误。
83
+ - 超时后底层资源是否真正停止。
84
+
85
+ ## 重试
86
+
87
+ 重试策略必须定义:
88
+
89
+ - 最大次数。
90
+ - 退避和抖动。
91
+ - 可重试错误范围。
92
+ - 幂等性。
93
+ - 最终失败的记录与反馈。
94
+
95
+ 不能对所有错误无限重试。
96
+
97
+ ## 错误处理
98
+
99
+ 不得吞掉异常。允许忽略时必须说明这是最佳努力操作,并保留必要诊断信息。
100
+
101
+ 错误应包含上下文并保留 `cause`:
102
+
103
+ ```ts
104
+ throw new Error(`Failed to load workspace config: ${configPath}`, {
105
+ cause: error
106
+ })
107
+ ```
108
+
109
+ 需要调用方分支处理的错误使用:
110
+
111
+ - 具名错误类。
112
+ - 带 `code` 的结构化错误。
113
+ - `Result<T, E>`。
114
+ - 可辨识联合。
115
+
116
+ 不要通过匹配错误消息字符串控制流程。
117
+
118
+ ## `catch` 值
119
+
120
+ 将 `catch` 值视为 `unknown`,先通过 `instanceof`、错误守卫或标准化函数收窄。
121
+
122
+ ## 资源清理
123
+
124
+ 以下资源必须有明确生命周期:
125
+
126
+ - 事件监听器。
127
+ - Timer 和 Interval。
128
+ - 文件句柄。
129
+ - Socket、数据库连接。
130
+ - Worker 和子进程。
131
+ - `AbortController`。
132
+ - React Effect 订阅。
133
+
134
+ 推荐返回清理函数或实现统一 `dispose()`:
135
+
136
+ ```ts
137
+ type Disposable = {
138
+ dispose(): void
139
+ }
140
+ ```
141
+
142
+ 创建资源的模块通常也应负责定义或暴露其清理方式。
@@ -0,0 +1,104 @@
1
+ # 注释、JSDoc 与文档
2
+
3
+ ## 注释解释原因
4
+
5
+ 注释用于解释代码本身无法清楚表达的:
6
+
7
+ - 为什么必须采用此顺序。
8
+ - 为什么不能删除看似多余的逻辑。
9
+ - 平台、协议、性能或安全约束。
10
+ - 第三方缺陷和规避方案。
11
+ - 竞态条件和资源生命周期。
12
+ - 非直观产品规则。
13
+
14
+ 不应逐行翻译代码。
15
+
16
+ ```ts
17
+ // 不推荐:Increment retry count.
18
+ retryCount += 1
19
+
20
+ // 推荐:Provider replication can briefly return 409 after a successful write.
21
+ retryCount += 1
22
+ ```
23
+
24
+ ## 注释风格
25
+
26
+ - 优先一行或一个短段落。
27
+ - 靠近被解释的逻辑。
28
+ - 使用完整、可验证的原因。
29
+ - 修改实现时同步更新。
30
+ - 能用命名和拆分表达时,不靠注释补救。
31
+
32
+ ## 应写注释的场景
33
+
34
+ - 跨平台差异。
35
+ - 第三方类型或运行时缺陷。
36
+ - 兼容旧协议的临时分支。
37
+ - 性能关键路径的非直观优化。
38
+ - 安全检查顺序。
39
+ - 并发和竞态约束。
40
+ - 清理顺序。
41
+ - 特殊算法或领域公式。
42
+
43
+ ## 不应写的注释
44
+
45
+ - 复述变量名或控制流。
46
+ - 注释掉的旧代码。
47
+ - 无跟踪信息的“以后优化”。
48
+ - 与实现重复的大篇教程。
49
+ - 无法验证的猜测。
50
+
51
+ 历史实现由版本控制保存,不应长期留在源码中。
52
+
53
+ ## JSDoc 使用范围
54
+
55
+ JSDoc 主要用于:
56
+
57
+ - 公共库 API。
58
+ - 插件和扩展点。
59
+ - 跨团队或跨进程契约。
60
+ - 参数具有单位、边界或特殊格式。
61
+ - 函数有重要副作用、取消、异常或线程安全语义。
62
+
63
+ ```ts
64
+ /**
65
+ * Resolves a workspace path without following symbolic links.
66
+ *
67
+ * @throws {WorkspacePathError} When the path escapes the configured root.
68
+ */
69
+ export function resolveWorkspacePath(
70
+ rootPath: string,
71
+ candidatePath: string
72
+ ): string {
73
+ // ...
74
+ }
75
+ ```
76
+
77
+ 内部显而易见的函数不需要机械补全 JSDoc。
78
+
79
+ ## TODO
80
+
81
+ TODO 必须包含负责人约定或可追踪编号,并说明删除条件:
82
+
83
+ ```ts
84
+ // TODO(PROJ-1423): Remove after all clients send protocol v3.
85
+ ```
86
+
87
+ 禁止:
88
+
89
+ ```ts
90
+ // TODO: fix later
91
+ ```
92
+
93
+ ## 设计文档
94
+
95
+ 以下内容更适合放入 `docs/` 或 ADR,而非源码注释:
96
+
97
+ - 多方案权衡。
98
+ - 跨服务架构。
99
+ - 数据迁移计划。
100
+ - 兼容性策略。
101
+ - 长期安全模型。
102
+ - 复杂协议说明。
103
+
104
+ 源码注释可以引用相应 ADR 或问题编号,但应保留理解当前代码所需的最小上下文。
@@ -0,0 +1,84 @@
1
+ # 测试策略
2
+
3
+ ## 测试分层
4
+
5
+ | 类型 | 目标 | 默认位置 |
6
+ |---|---|---|
7
+ | 单元测试 | 函数、策略、解析器、状态转换 | 与源码同目录 |
8
+ | 集成测试 | 多个真实模块协作 | `tests/integration/` |
9
+ | 契约测试 | API、IPC、插件、适配器契约 | 源码旁或 `tests/contracts/` |
10
+ | E2E | 用户关键路径 | `tests/e2e/` |
11
+ | 基准测试 | 性能关键路径 | `*.bench.ts` |
12
+
13
+ ## 测试命名
14
+
15
+ 测试名描述可观察行为,而不是实现方法:
16
+
17
+ ```ts
18
+ describe('quoteShellArgument', () => {
19
+ it('preserves an empty argument as an explicit empty string', () => {
20
+ // ...
21
+ })
22
+ })
23
+ ```
24
+
25
+ 避免 `it('works')`、`describe('utils')`。
26
+
27
+ ## 覆盖范围
28
+
29
+ 关键模块应考虑:
30
+
31
+ - 正常路径。
32
+ - 边界值和空输入。
33
+ - 无效输入。
34
+ - 错误传播。
35
+ - 取消和超时。
36
+ - 并发或重复调用。
37
+ - 资源清理。
38
+ - 已修复缺陷的回归场景。
39
+
40
+ 覆盖率数字不能替代风险导向的场景设计。
41
+
42
+ ## 缺陷修复流程
43
+
44
+ 1. 添加可稳定复现问题的失败测试。
45
+ 2. 确认测试在修复前失败。
46
+ 3. 实施最小修复。
47
+ 4. 确认回归测试和相关测试通过。
48
+ 5. 必要时增加跨平台或集成测试。
49
+
50
+ ## 确定性
51
+
52
+ 测试不应依赖:
53
+
54
+ - 真实当前时间。
55
+ - 外部不稳定网络。
56
+ - 测试执行顺序。
57
+ - 共享可变全局状态。
58
+ - 本机特定路径或环境配置。
59
+ - 无种子的随机数据。
60
+
61
+ 通过注入时钟、随机源、文件系统和网络端口,或使用临时目录与隔离夹具保持确定性。
62
+
63
+ ## Mock 原则
64
+
65
+ - 优先测试真实纯函数。
66
+ - Mock 系统边界,不 Mock 被测模块内部每个调用。
67
+ - 测试行为与输出,不锁死实现步骤。
68
+ - 不因 Mock 方便而跳过关键集成测试。
69
+ - 使用小而可读的夹具。
70
+
71
+ ## 快照
72
+
73
+ 快照适合结构稳定、人工审查有价值的输出。避免巨型快照、频繁无脑更新和对动态数据的快照。
74
+
75
+ ## 测试代码质量
76
+
77
+ 测试也是生产资产:
78
+
79
+ - 命名清晰。
80
+ - 无隐藏共享状态。
81
+ - 失败信息可诊断。
82
+ - 夹具具有领域含义。
83
+ - 清理临时资源。
84
+ - 不复制大量生产实现来计算期望值。