ethan-skill 1.15.2 → 1.15.3

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.
@@ -4,10 +4,10 @@ globs:
4
4
  alwaysApply: true
5
5
  ---
6
6
 
7
- # Ethan v1.15.0
7
+ # Ethan v1.15.2
8
8
 
9
9
  > 自动生成 - 请勿手动修改,源文件:src/skills/
10
- > Generated at: 2026-04-11T16:46:27.639Z
10
+ > Generated at: 2026-04-14T03:12:49.305Z
11
11
 
12
12
  ## 重要:Skill 激活规则
13
13
 
@@ -59,6 +59,8 @@ alwaysApply: true
59
59
  | 移动端专项审查 | `移动端审查` |
60
60
  | 数据管道设计 | `数据管道` |
61
61
  | ML 实验管理 | `ml experiment` |
62
+ | 自动修复 | `自动修复` |
63
+ | Agent 记忆 | `agent 记忆` |
62
64
 
63
65
  ---
64
66
 
@@ -6985,4 +6987,402 @@ if drift_detected:
6985
6987
 
6986
6988
  ---
6987
6989
 
6990
+ ## Skill 37:自动修复
6991
+
6992
+ **触发词**:`自动修复`、`auto fix`、`auto-fix`、`CI 失败`、`ci failed`、`测试失败`、`test failed`、`lint 报错`、`lint error`、`修复失败`、`fix failing tests`、`自动迭代修复`、`@ethan fix`、`@ethan auto-fix`、`/auto-fix`
6993
+
6994
+ **描述**:读取 CI/测试/Lint 失败信息,自动分析根因、生成修复方案并迭代验证,直到通过(最多 3 轮)
6995
+
6996
+ ### 1. 收集失败信息
6997
+
6998
+ 收集所有可用的失败上下文:
6999
+
7000
+ **信息来源(优先级从高到低)**
7001
+ - CI 流水线日志(完整 stderr/stdout,不截断)
7002
+ - 测试框架输出(Jest / Vitest / PyTest / Go test)
7003
+ - Lint 报告(ESLint / Prettier / tsc / pylint)
7004
+ - 构建错误(webpack / vite / tsc)
7005
+ - 运行时异常(stack trace + 上下文代码)
7006
+
7007
+ **必须提取的字段**
7008
+ ```
7009
+ 失败类型: [ 测试失败 | Lint | 类型错误 | 构建失败 | 运行时错误 ]
7010
+ 失败文件: [文件路径:行号]
7011
+ 错误信息: [原始错误文本,保留完整 stack trace]
7012
+ 触发条件: [哪个命令/步骤触发]
7013
+ 上次绿灯: [最近一次通过的 commit / 时间(如可获取)]
7014
+ ```
7015
+
7016
+ > 如果日志超长,提取前 100 行 + 最后 50 行,优先保留 "FAILED"、"ERROR"、"at " 行。
7017
+
7018
+ ### 2. 根因分析
7019
+
7020
+ 对每个失败逐一诊断根因,区分「直接原因」和「根本原因」:
7021
+
7022
+ **失败类型与常见根因速查**
7023
+
7024
+ | 失败类型 | 直接原因 | 根本原因示例 |
7025
+ |---------|---------|------------|
7026
+ | 测试断言失败 | 返回值与预期不符 | 业务逻辑变更未同步更新测试 |
7027
+ | 测试超时 | 异步未正确 resolve | 缺少 await 或 mock 配置不当 |
7028
+ | 类型错误 | interface 不匹配 | API 变更未更新消费方类型 |
7029
+ | Lint 报错 | 代码风格违规 | 缺少 import、未使用变量、规则变更 |
7030
+ | 构建失败 | 模块未找到 | 路径别名配置、缺少依赖 |
7031
+ | 运行时错误 | 空指针/未定义 | 边界条件未处理 |
7032
+
7033
+ **输出根因诊断表**
7034
+ ```
7035
+ 失败 #1
7036
+ 文件: src/auth/login.test.ts:42
7037
+ 错误: Expected "invalid" but received "error"
7038
+ 直接原因: 返回值从 "error" 改为 "invalid"
7039
+ 根本原因: auth.ts 第 89 行修改了错误码但未同步测试
7040
+ 修复难度: 🟢 简单(更新测试断言)
7041
+ 可自动修复: ✅
7042
+
7043
+ 失败 #2
7044
+ 文件: src/utils/parser.ts:15
7045
+ 错误: Type 'string | null' is not assignable to 'string'
7046
+ 直接原因: getUser() 返回值新增了 null 类型
7047
+ 根本原因: API 层变更未向下传播 null 处理
7048
+ 修复难度: 🟡 中等(需添加 null guard)
7049
+ 可自动修复: ✅
7050
+ ```
7051
+
7052
+ ### 3. 生成修复方案(Round 1)
7053
+
7054
+ 针对每个可自动修复的失败,生成最小化修复方案:
7055
+
7056
+ **修复原则**
7057
+ - 最小改动原则:只修改必须改的代码
7058
+ - 不引入新问题:修复后不能导致其他测试失败
7059
+ - 保持语义一致:修复逻辑应符合原始意图
7060
+ - 优先修代码而非修测试(除非测试本身写错了)
7061
+
7062
+ **分优先级处理**
7063
+ 1. 🔴 **先修 Blocker**:类型错误、构建失败(影响所有后续步骤)
7064
+ 2. 🟡 **再修测试**:断言失败、Mock 配置(影响覆盖率报告)
7065
+ 3. 🟢 **最后修 Lint**:风格问题(不影响功能,可批量修复)
7066
+
7067
+ **Lint 批量自动修复命令**
7068
+ ```bash
7069
+ npx eslint src --fix
7070
+ npx prettier src --write
7071
+ ```
7072
+
7073
+ **输出修复 Diff(每个失败一个代码块)**
7074
+ ```diff
7075
+ // 修复 #1:更新测试断言
7076
+ - expect(result).toBe('error');
7077
+ + expect(result).toBe('invalid');
7078
+
7079
+ // 修复 #2:添加 null guard
7080
+ - const name = getUser().name;
7081
+ + const user = getUser();
7082
+ + const name = user?.name ?? '';
7083
+ ```
7084
+
7085
+ ### 4. 应用修复并验证
7086
+
7087
+ 应用修复方案后立即验证:
7088
+
7089
+ **验证步骤(按失败类型)**
7090
+ ```bash
7091
+ # 测试失败
7092
+ npx vitest run [changed-test-file] # 先跑单文件,快速反馈
7093
+ npx vitest run # 再跑全量,确认无新增失败
7094
+
7095
+ # 类型错误
7096
+ npx tsc --noEmit # 全量类型检查
7097
+
7098
+ # Lint 错误
7099
+ npx eslint src --max-warnings 0 # 不允许遗留 warning
7100
+
7101
+ # 构建失败
7102
+ npm run build # 完整构建验证
7103
+ ```
7104
+
7105
+ **验证结果记录**
7106
+ ```
7107
+ Round 1 结果:
7108
+ 修复前:❌ 3 失败(2 测试 + 1 类型错误)
7109
+ 修复后:
7110
+ ✅ 测试失败 #1 — 已修复(断言更新)
7111
+ ✅ 类型错误 #2 — 已修复(null guard)
7112
+ ❌ 测试失败 #3 — 仍失败(需进入 Round 2)
7113
+ ```
7114
+
7115
+ ### 5. 迭代修复(Round 2-3)
7116
+
7117
+ 如果 Round 1 仍有失败,进入迭代模式:
7118
+
7119
+ **迭代策略**
7120
+ - **Round 2**:针对剩余失败,进行更深入的根因分析(可能是 Round 1 修复引入了副作用)
7121
+ - **Round 3**:最终尝试,优先保证 CI 通过(允许临时 skip 不稳定测试,但必须标注 @todo)
7122
+
7123
+ **副作用检测**(重要)
7124
+ ```
7125
+ 检查 Round 1 修复后的新增失败:
7126
+ - 是否有原本通过的测试现在失败了?
7127
+ - 如果有,优先回退引入副作用的修改,重新设计方案
7128
+ ```
7129
+
7130
+ **Round 3 后仍失败的处理**
7131
+ ```markdown
7132
+ ## ⚠️ 需要人工介入
7133
+
7134
+ 以下失败无法通过自动修复解决:
7135
+
7136
+ ### 失败 #X
7137
+ - **错误**:[原始错误]
7138
+ - **已尝试**:[已尝试的修复方案]
7139
+ - **失败原因**:[为什么自动修复不可行]
7140
+ - **建议人工处理**:[具体建议步骤]
7141
+ - **最低可行方案**:暂时 skip 此测试,添加 TODO 注释:
7142
+ `// TODO(@owner): fix in #issue-number — [简短原因]`
7143
+ ```
7144
+
7145
+ **迭代上限约束**
7146
+ - 最多 3 轮迭代,防止无限循环
7147
+ - 每轮必须有至少 1 个失败被修复,否则停止并输出人工介入指引
7148
+
7149
+ ### 6. 输出修复报告
7150
+
7151
+ 所有轮次完成后,输出结构化修复报告:
7152
+
7153
+ ```markdown
7154
+ ## Auto-Fix 修复报告
7155
+
7156
+ ### 修复概览
7157
+ - **总失败数**:X
7158
+ - **自动修复**:Y(Y/X)
7159
+ - **需人工处理**:Z
7160
+ - **迭代轮次**:N 轮
7161
+
7162
+ ### 修复详情
7163
+
7164
+ | # | 文件 | 错误类型 | 修复方式 | 状态 |
7165
+ |---|------|---------|---------|------|
7166
+ | 1 | src/auth.ts:42 | 断言失败 | 更新期望值 | ✅ Round 1 |
7167
+ | 2 | src/utils.ts:15 | 类型错误 | 添加 null guard | ✅ Round 1 |
7168
+ | 3 | src/api.ts:88 | 集成测试 | 更新 Mock 配置 | ✅ Round 2 |
7169
+
7170
+ ### 代码变更摘要
7171
+ [修改的文件列表 + 每处修改的简短说明]
7172
+
7173
+ ### 需要人工介入
7174
+ [如有,列出无法自动修复的项目 + 建议]
7175
+
7176
+ ### 预防建议
7177
+ - [导致此次失败的系统性问题]
7178
+ - [建议的规范或流程改进]
7179
+ ```
7180
+
7181
+ **输出格式**:Markdown 修复报告:根因诊断表 + 分 Round 修复 Diff + 验证结果 + 人工介入指引(如有)
7182
+
7183
+ **注意事项**:
7184
+ - 优先修代码而非修测试——除非测试本身写错了
7185
+ - 每轮修复后必须验证,确认无副作用后再继续
7186
+ - 3 轮迭代上限是硬约束,防止循环修复
7187
+ - 临时 skip 测试时必须留下 TODO 注释,不允许无理由 skip
7188
+ - Lint 可以批量 --fix,但需检查 fix 后的语义是否正确
7189
+
7190
+ ---
7191
+
7192
+ ## Skill 38:Agent 记忆
7193
+
7194
+ **触发词**:`agent 记忆`、`agent memory`、`持久化记忆`、`persistent memory`、`记住这个`、`remember this`、`跨会话记忆`、`项目决策记录`、`注入上下文`、`inject context`、`@ethan memory`、`@ethan agent-memory`、`/agent-memory`
7195
+
7196
+ **描述**:提取并持久化项目关键决策、架构约束与已解决问题,跨会话注入 Agent 上下文,消除重复探索
7197
+
7198
+ ### 1. 识别值得记忆的信息
7199
+
7200
+ 并非所有信息都值得持久化,聚焦以下四类高价值记忆:
7201
+
7202
+ **四类核心记忆**
7203
+
7204
+ | 类型 | 描述 | 示例 |
7205
+ |------|------|------|
7206
+ | 🏗️ **架构决策** | 重要的技术选型和设计取舍 | "使用 Zustand 而非 Redux,因为项目规模小、不需要 devtools" |
7207
+ | ⚠️ **已知陷阱** | 踩过的坑、避坑经验 | "直接调用 /api/v1/user 会 401,必须先刷新 token" |
7208
+ | 📐 **项目约定** | 命名规范、目录结构、代码约束 | "所有异步操作用 useQuery,禁止裸 fetch" |
7209
+ | ✅ **已解决问题** | 解决了的复杂 bug 和方案 | "iOS Safari 下 flex gap 不生效,用 margin 替代" |
7210
+
7211
+ **识别触发条件**
7212
+ - 对话中出现「为什么要这样」「这个项目的约定是」「上次解决这个问题的方法是」
7213
+ - 重要的 ADR(架构决策记录)产出
7214
+ - 排查超过 30 分钟的 bug 及其解决方案
7215
+ - 用户明确说「记住这个」
7216
+
7217
+ **不值得记忆的信息**
7218
+ - 一次性任务的临时上下文
7219
+ - 可以从代码本身读出的信息
7220
+ - 过于宽泛的"最佳实践"(已在 CLAUDE.md 中)
7221
+
7222
+ ### 2. 结构化记忆条目
7223
+
7224
+ 将识别到的信息格式化为标准记忆条目:
7225
+
7226
+ **记忆条目格式(YAML)**
7227
+ ```yaml
7228
+ # .ethan/agent-memory/architecture.yaml
7229
+ entries:
7230
+ - id: mem_001
7231
+ type: architecture_decision # architecture_decision | gotcha | convention | resolved_bug
7232
+ title: 状态管理选型:Zustand over Redux
7233
+ content: |
7234
+ 本项目使用 Zustand 进行全局状态管理。
7235
+ 原因:组件树层级浅(≤3层),不需要时间旅行调试,Redux 模板代码过多。
7236
+ 影响:所有跨组件状态通过 useXxxStore() hook 访问,不使用 Context API。
7237
+ tags: [state-management, zustand, frontend]
7238
+ created_at: 2024-01-15
7239
+ confidence: high # high | medium | low
7240
+ scope: global # global | module:<name> | file:<path>
7241
+ ```
7242
+
7243
+ **文件组织结构**
7244
+ ```
7245
+ .ethan/agent-memory/
7246
+ ├── architecture.yaml # 架构决策
7247
+ ├── gotchas.yaml # 已知陷阱
7248
+ ├── conventions.yaml # 项目约定
7249
+ ├── resolved-bugs.yaml # 已解决问题
7250
+ └── index.yaml # 记忆索引(供快速检索)
7251
+ ```
7252
+
7253
+ **记忆条目质量标准**
7254
+ - title:一句话,包含关键词(方便检索)
7255
+ - content:5-10 行,包含决策背景 + 结论 + 影响范围
7256
+ - tags:3-5 个,技术栈 + 模块 + 问题类型
7257
+ - confidence:high=已验证可重用,medium=上下文相关,low=存疑待确认
7258
+
7259
+ ### 3. 写入持久化存储
7260
+
7261
+ 将格式化的记忆条目追加写入对应文件:
7262
+
7263
+ **写入操作**
7264
+ ```bash
7265
+ # 目录不存在时自动创建
7266
+ mkdir -p .ethan/agent-memory
7267
+
7268
+ # 在 index.yaml 更新记忆摘要(用于快速检索)
7269
+ # index.yaml 格式:
7270
+ # entries:
7271
+ # - id: mem_001
7272
+ # title: "状态管理选型:Zustand over Redux"
7273
+ # type: architecture_decision
7274
+ # tags: [state-management, zustand]
7275
+ # file: architecture.yaml
7276
+ ```
7277
+
7278
+ **记忆维护规则**
7279
+ - 同一主题新记忆覆盖旧记忆(更新 content + updated_at)
7280
+ - 标记为 low confidence 的记忆,3 个月未访问则删除
7281
+ - 每次成功使用后,将 confidence 升级(low → medium → high)
7282
+ - 发现记忆内容已过时时,立即更新或标记 deprecated
7283
+
7284
+ **与 .ethan/team-knowledge/ 的区别**
7285
+ | | agent-memory | team-knowledge |
7286
+ |--|---|---|
7287
+ | 写入者 | AI(自动提取) | 人工(ethan knowledge add)|
7288
+ | 格式 | 结构化 YAML | 自由文本 Markdown |
7289
+ | 粒度 | 单条决策/问题 | 完整知识文档 |
7290
+ | 检索 | 按 tags + type 自动匹配 | 按关键词全文搜索 |
7291
+
7292
+ ### 4. 记忆检索与上下文注入
7293
+
7294
+ 在新会话开始或 Agent 执行前,检索相关记忆注入上下文:
7295
+
7296
+ **检索策略(多维度匹配)**
7297
+ ```
7298
+ 1. 任务关键词 ↔ 记忆 tags(精确匹配)
7299
+ 2. 当前工作文件路径 ↔ 记忆 scope(前缀匹配)
7300
+ 3. 失败信息中的技术词 ↔ 记忆 title(模糊匹配)
7301
+ 4. 最近 7 天被访问的记忆(时间权重提升)
7302
+ ```
7303
+
7304
+ **注入格式(添加到系统提示词开头)**
7305
+ ```markdown
7306
+ ## 📚 项目记忆上下文(来自 .ethan/agent-memory/)
7307
+
7308
+ ### 架构决策
7309
+ - **状态管理**:使用 Zustand,不用 Redux。所有跨组件状态通过 useXxxStore() 访问。
7310
+ - **API 层**:统一使用 React Query,禁止裸 fetch 调用。
7311
+
7312
+ ### 已知陷阱
7313
+ - ⚠️ iOS Safari 下 flex gap 不生效,用 margin-right/bottom 替代
7314
+ - ⚠️ /api/v1/user 接口在 token 过期时返回 200 + {error: "token_expired"},非标准 401
7315
+
7316
+ ### 项目约定
7317
+ - 组件文件统一 PascalCase,工具函数 camelCase
7318
+ - 单元测试覆盖率要求 ≥ 80%(核心业务)
7319
+
7320
+ > ⓘ 以上记忆来自 .ethan/agent-memory/(共 N 条)。如有不准确,请更新记忆文件。
7321
+ ```
7322
+
7323
+ **记忆命中反馈**
7324
+ 每次使用记忆后,记录命中情况:
7325
+ ```yaml
7326
+ # .ethan/agent-memory/index.yaml
7327
+ - id: mem_003
7328
+ last_hit: 2024-03-20
7329
+ hit_count: 7
7330
+ confidence: high # 命中多次后自动升级
7331
+ ```
7332
+
7333
+ ### 5. 记忆审计与清理
7334
+
7335
+ 定期维护记忆库,确保记忆的准确性和有效性:
7336
+
7337
+ **审计清单**
7338
+ ```bash
7339
+ # 查看所有记忆
7340
+ ethan memory list
7341
+
7342
+ # 统计记忆健康度
7343
+ ethan memory stats
7344
+ # 输出:
7345
+ # 总记忆条数:48
7346
+ # 高置信度:32 | 中:12 | 低:4
7347
+ # 30天未命中:8条(建议清理)
7348
+ # 重复/矛盾:2组(需合并)
7349
+ ```
7350
+
7351
+ **记忆衰减策略**
7352
+ - 90 天未命中:自动降级 confidence(high → medium → low)
7353
+ - 180 天未命中的 low confidence 记忆:标记为 deprecated,下次审计删除
7354
+ - 代码库重大重构后:批量检查相关记忆是否仍有效
7355
+
7356
+ **记忆冲突处理**
7357
+ ```
7358
+ 如发现两条矛盾的记忆:
7359
+ 1. 保留更新的(created_at 更晚)
7360
+ 2. 将旧的标记为 deprecated
7361
+ 3. 在新记忆的 content 中注明「取代了 mem_xxx」
7362
+ ```
7363
+
7364
+ **团队共享记忆**
7365
+ ```bash
7366
+ # 将记忆同步到 git(团队共享)
7367
+ ethan sync push --include agent-memory
7368
+
7369
+ # 拉取团队记忆
7370
+ ethan sync pull
7371
+
7372
+ # 记忆文件建议加入 .gitignore 的例外
7373
+ # .gitignore:
7374
+ # !.ethan/agent-memory/*.yaml
7375
+ ```
7376
+
7377
+ **输出格式**:YAML 记忆条目文件(写入 .ethan/agent-memory/)+ Markdown 注入格式的上下文摘要
7378
+
7379
+ **注意事项**:
7380
+ - 记忆要精不要多——50 条高质量记忆 > 500 条低质量记忆
7381
+ - 每次新会话开始前运行"记忆检索",将相关记忆注入为背景
7382
+ - 记忆不能替代代码本身——代码变更后记忆也要更新
7383
+ - 团队共享记忆文件建议提交到 git,个人临时记忆可以 .gitignore
7384
+ - 使用 ethan memory search <keyword> 快速检索历史经验
7385
+
7386
+ ---
7387
+
6988
7388
  *Ethan - Your AI Workflow Assistant | 让每一步都有据可依*