代码标签扫描与任务创建技能Skill skill-learn

这个技能用于自动扫描代码库中的FIX:、NOTE:、TODO:标签,通过交互式界面展示扫描结果,让用户选择任务类型,并创建结构化任务。它支持任务分组、依赖管理和状态更新,适用于软件开发中的自动化任务管理,提高开发效率。关键词:代码扫描、标签提取、任务自动化、DevOps、FIX NOTE TODO、交互式选择、任务管理、软件开发工具。

DevOps 0 次安装 0 次浏览 更新于 3/22/2026

名称: 技能学习 描述: 扫描代码库中的FIX:/NOTE:/TODO:标签并创建结构化任务,支持交互式选择。用于/learn命令调用。 允许工具: Bash, Grep, Read, Write, Edit, AskUserQuestion

学习技能(直接执行)

直接执行技能,用于扫描文件、交互式展示发现并创建用户选择的任务。替换了之前的基于委派的方法,采用同步执行和AskUserQuestion提示。

关键行为: 用户在创建任何任务之前总是先看到标签扫描结果。用户通过交互式提示选择创建哪些任务类型。

上下文引用

引用(不急于加载):

  • 路径: @specs/TODO.md - 当前任务列表
  • 路径: @specs/state.json - 机器状态

执行

步骤1: 解析参数

从命令输入中提取路径:

# 从命令输入中解析
paths="$ARGUMENTS"

# 如果未指定路径,默认为项目根目录
if [ -z "$paths" ]; then
  paths="."
fi

注意: --dry-run 标志不再支持。交互式流程本质上是“先预览” - 用户在创建任务之前总是先看到发现。

步骤2: 生成会话ID

生成会话ID用于跟踪:

session_id="sess_$(date +%s)_$(od -An -N3 -tx1 /dev/urandom | tr -d ' ')"

步骤3: 执行标签提取

使用文件类型特定模式扫描标签。使用Bash和grep以确保输出解析一致。

3.1: 提取FIX:标签

Lua文件(Neovim配置):

grep -rn --include="*.lua" "-- FIX:" $paths 2>/dev/null || true

LaTeX文件:

grep -rn --include="*.tex" "% FIX:" $paths 2>/dev/null || true

Markdown文件:

grep -rn --include="*.md" "<!-- FIX:" $paths 2>/dev/null || true

Python/Shell/YAML文件:

grep -rn --include="*.py" --include="*.sh" --include="*.yaml" --include="*.yml" "# FIX:" $paths 2>/dev/null || true

3.2: 提取NOTE:标签

与上述相同模式,将FIX:替换为NOTE:

3.3: 提取TODO:标签

与上述相同模式,将FIX:替换为TODO:

3.4: 解析结果

对于每个grep匹配,提取:

  • 文件路径
  • 行号
  • 标签类型(FIX, NOTE, TODO)
  • 标签内容(标签后的文本)

示例原始输出:

nvim/lua/plugins/telescope.lua:67:-- TODO: Add custom picker for git worktrees
docs/KEYMAPS.md:89:<!-- FIX: Update keymap table with new bindings -->

分类为三个数组:

  • fix_tags[] - 所有FIX:标签
  • note_tags[] - 所有NOTE:标签
  • todo_tags[] - 所有TODO:标签

步骤4: 显示标签摘要

在用户选择之前展示发现:

## 标签扫描结果

**扫描的文件**: {paths}
**找到的标签**: {total_count}

### FIX:标签 ({count})
- `{file}:{line}` - {content}
- ...

### NOTE:标签 ({count})
- `{file}:{line}` - {content}
- ...

### TODO:标签 ({count})
- `{file}:{line}` - {content}
- ...

步骤5: 处理边界情况

未找到标签

如果未找到标签:

## 未找到标签

扫描的文件: {paths}
未检测到FIX:, NOTE:, 或TODO:标签。

无需创建。

优雅退出,无提示。

仅某些标签类型存在

仅显示存在的标签类型的任务类型选项:

  • 存在FIX:标签 -> 提供“修复任务”
  • 存在NOTE:标签 -> 提供“修复任务”和“学习任务”
  • 存在TODO:标签 -> 提供“TODO任务”

步骤6: 任务类型选择

如果找到标签,提示用户选择任务类型:

{
  "question": "应该创建哪些任务类型?",
  "header": "任务类型",
  "multiSelect": true,
  "options": [
    {
      "label": "修复任务",
      "description": "将{N}个FIX:/NOTE:标签合并为单个任务"
    },
    {
      "label": "学习任务",
      "description": "根据{N}个NOTE:标签更新上下文"
    },
    {
      "label": "TODO任务",
      "description": "为{N}个TODO:项创建任务"
    }
  ]
}

重要: 仅包含标签类型存在的选项:

  • 仅当FIX:或NOTE:标签存在时包含“修复任务”
  • 仅当NOTE:标签存在时包含“学习任务”
  • 仅当TODO:标签存在时包含“TODO任务”

如果用户未选择任何内容,优雅退出:

未选择任务类型。未创建任务。

步骤7: 单个TODO选择

如果选择了“TODO任务”并且有TODO:标签:

标准情况(<=20个TODO)

{
  "question": "选择要创建为任务的TODO项:",
  "header": "TODO选择",
  "multiSelect": true,
  "options": [
    {
      "label": "{内容截断至50字符}",
      "description": "{file}:{line}"
    },
    ...
  ]
}

大量TODO(>20个)

在顶部添加“选择所有”选项:

{
  "question": "选择要创建为任务的TODO项:",
  "header": "TODO选择(多项)",
  "multiSelect": true,
  "options": [
    {
      "label": "选择所有({N}项)",
      "description": "为每个TODO标签创建任务"
    },
    {
      "label": "{内容截断至50字符}",
      "description": "{file}:{line}"
    },
    ...
  ]
}

如果选择了“选择所有”,包含所有TODO。否则,仅包含选定的项。

步骤7.5: TODO项的主题分组

条件: 用户选择了“TODO任务”并且选择了多于1个TODO项

如果只选择了1个TODO项,跳转到步骤8(无分组优势)。

7.5.1: 提取主题指示符

对于每个选定的TODO项,提取主题指示符:

关键术语: 从TODO内容中提取重要词语(名词、动词)。忽略停用词(the, a, is, to, for, 等)。

文件部分: 按文件路径前缀分组(例如Logos/Layer1/ vs Logos/Shared/)。

操作类型: 识别常见操作模式:

  • “添加/实现/创建” → 实现任务
  • “修复/处理/纠正” → 修复任务
  • “文档/更新文档” → 文档任务
  • “测试/验证” → 测试任务
  • “重构/优化” → 改进任务

示例提取:

TODO: “为工作树添加自定义选择器” 在 nvim/lua/plugins/telescope.lua:67
  → 关键术语: [“选择器”, “工作树”, “telescope”]
  → 文件部分: “nvim/lua/plugins/”
  → 操作类型: “实现”

TODO: “为工作树添加预览窗口” 在 nvim/lua/plugins/telescope.lua:89
  → 关键术语: [“预览”, “工作树”, “telescope”]
  → 文件部分: “nvim/lua/plugins/”
  → 操作类型: “实现”

TODO: “优化懒加载” 在 nvim/lua/config/lazy.lua:23
  → 关键术语: [“优化”, “懒”, “加载”]
  → 文件部分: “nvim/lua/config/”
  → 操作类型: “改进”

7.5.2: 通过共享术语聚类TODO

分组共享2个或更多重要术语或共享文件部分 + 操作类型的TODO。

聚类算法:

  1. 以第一个TODO作为初始组
  2. 对于每个剩余的TODO:
    • 如果与现有组共享2+个关键术语 → 添加到组
    • 如果与现有组共享文件_section AND action_type → 添加到组
    • 否则 → 开始新组
  3. 从组中最常见的共享术语生成主题标签

示例聚类:

组1: “Telescope 工作树” (共享: 工作树, telescope, nvim/lua/plugins/, 实现)
  - 为工作树添加自定义选择器
  - 为工作树添加预览窗口

组2: “配置优化” (共享: nvim/lua/config/, 改进)
  - 优化懒加载

单项目组: 如果一个TODO未与其他聚类,则成为自己的单项目组。

7.5.3: 存储分组主题

存储主题组以用于步骤7.5.4:

topic_groups = [
  {
    label: “Telescope 工作树”,
    items: [
      {file: “nvim/lua/plugins/telescope.lua”, line: 67, content: “为工作树添加自定义选择器”},
      {file: “nvim/lua/plugins/telescope.lua”, line: 89, content: “为工作树添加预览窗口”}
    ],
    shared_terms: [“工作树”, “telescope”],
    action_type: “实现”
  },
  {
    label: “配置优化”,
    items: [
      {file: “nvim/lua/config/lazy.lua”, line: 23, content: “优化懒加载”}
    ],
    shared_terms: [],
    action_type: “改进”
  }
]

步骤7.5.4: 主题组确认

条件: topic_groups包含至少一个拥有2+个项目的组

如果所有组都只有1个项目,跳转到步骤8(无分组优势)。

通过AskUserQuestion展示主题组:

{
  "question": "应该如何将TODO项分组到任务中?",
  "header": "TODO主题分组",
  "multiSelect": false,
  "options": [
    {
      "label": "接受建议的主题组",
      "description": "创建{N}个分组任务: {group_summaries}"
    },
    {
      "label": "保持为单独任务",
      "description": "创建{M}个单独任务(每个TODO项一个)"
    },
    {
      "label": "创建单个合并任务",
      "description": "创建1个任务包含所有{M}个TODO项"
    }
  ]
}

其中:

  • {N} = 主题组数量
  • {M} = 选定的TODO项总数
  • {group_summaries} = 逗号分隔的列表,如“S5 Theorems (2项), Utility Optimization (1项)”

存储用户选择: grouping_mode = “grouped” | “separate” | “combined”

步骤8: 创建选定的任务

对于每个选定的任务类型,创建任务。重要: 当NOTE:标签存在并且同时选择了修复任务和学习任务时,首先创建学习任务,以便修复任务可以依赖它。

8.1: 获取下一个任务编号

next_num=$(jq -r '.next_project_number' specs/state.json)

8.2: 依赖感知的任务创建顺序

检查NOTE:依赖条件:

has_note_dependency = (存在NOTE:标签) AND (用户同时选择了“修复任务”和“学习任务”)

如果has_note_dependency为TRUE:

  • 首先创建学习任务(步骤8.2a)
  • 存储学习任务编号为learn_it_task_num
  • 其次创建修复任务,带依赖(步骤8.2b)

如果has_note_dependency为FALSE:

  • 首先创建修复任务(如果选中)
  • 其次创建学习任务(如果选中)
  • 无依赖关系

8.2a: 学习任务(当首先创建以用于依赖时)

条件: has_note_dependency为TRUE

{
  "title": "根据NOTE:标签更新上下文文件",
  "description": "根据学习更新{N}个上下文文件:

{按目标上下文分组}",
  "language": "meta",
  "effort": "1-2小时"
}

存储任务编号: learn_it_task_num = next_num 递增: next_num = next_num + 1

8.2b: 修复任务(当has_note_dependency时有依赖)

条件: 用户选择了“修复任务”并且(存在FIX:或NOTE:标签)

当has_note_dependency为TRUE时:

{
  "title": "修复来自FIX:/NOTE:标签的问题",
  "description": "处理来自嵌入标签的{N}个项:

{带文件:行引用的项列表}

**重要**: 进行更改时,从源文件中移除FIX:和NOTE:标签。保留TODO:标签不变(它们创建单独的任务)。",
  "language": "{从源文件中检测的主要语言}",
  "effort": "2-4小时",
  "dependencies": [learn_it_task_num]
}

当has_note_dependency为FALSE时:

{
  "title": "修复来自FIX:/NOTE:标签的问题",
  "description": "处理来自嵌入标签的{N}个项:

{带文件:行引用的项列表}

**重要**: 进行更改时,从源文件中移除FIX:和NOTE:标签。保留TODO:标签不变(它们创建单独的任务)。",
  "language": "{从源文件中检测的主要语言}",
  "effort": "2-4小时"
}

语言检测:

如果大多数标签来自.lean文件 -> “lean”
否则如果大多数来自.tex文件 -> “latex”
否则如果大多数来自.claude/文件 -> “meta”
否则 -> “general”

8.3: 学习任务(当创建时无依赖)

条件: 用户选择了“学习任务”并且存在NOTE:标签并且has_note_dependency为FALSE

{
  "title": "根据NOTE:标签更新上下文文件",
  "description": "根据学习更新{N}个上下文文件:

{按目标上下文分组}",
  "language": "meta",
  "effort": "1-2小时"
}

8.4: TODO任务(如果选中)

条件: 用户选择了“TODO任务”并且用户选择了特定的TODO项

检查grouping_mode(来自步骤7.5.4,如果跳过了步骤7.5.4,则默认为“separate”):

8.4.1: 分组模式(grouping_mode == “grouped”)

对于topic_groups中的每个主题组:

{
  "title": "{topic_label}: {item_count}个TODO项",
  "description": "处理与{topic_label}相关的TODO项:

{item_list}

---

共享上下文: {shared_terms_description}",
  "language": "{从组中大多数文件类型检测}",
  "effort": "{scaled_effort}"
}

其中:

  • {topic_label} = 生成的标签(例如“Telescope 工作树”)
  • {item_count} = 组中项目数
  • {item_list} = 格式化的项目列表:
    - [ ] {content} (`{file}:{line}`)
    - [ ] {content} (`{file}:{line}`)
    
  • {shared_terms_description} = 为什么项目被分组的简要描述(例如“与telescope工作树功能相关”)

努力缩放公式:

基础努力 = 1小时
缩放努力 = 基础努力 + (30分钟 * (item_count - 1))

示例:
  1项 → 1小时
  2项 → 1.5小时 (1h + 30min)
  3项 → 2小时 (1h + 60min)
  4项 → 2.5小时 (1h + 90min)
8.4.2: 合并模式(grouping_mode == “combined”)

创建包含所有选定TODO项的单个任务:

{
  "title": "处理{item_count}个TODO项",
  "description": "来自扫描的合并TODO项:

{all_items_list}

---

文件: {unique_files_list}",
  "language": "{从大多数文件类型检测}",
  "effort": "{scaled_effort}"
}

其中:

  • {item_count} = 选定的TODO项总数
  • {all_items_list} = 所有项目的格式化列表,带复选框
  • {unique_files_list} = 涉及的唯文件的逗号分隔列表

努力缩放: 与分组模式相同公式。

8.4.3: 单独模式(grouping_mode == “separate”或默认)

对于每个选定的TODO项单独:

{
  "title": "{标签内容,截断至60字符}",
  "description": "{完整标签内容}

来源: {file}:{line}",
  "language": "{从文件类型检测}",
  "effort": "1小时"
}

TODO任务的语言检测(所有模式):

.lua (nvim/) -> “neovim”
.tex  -> “latex”
.md   -> “markdown”
.py/.sh -> “general”
.claude/* -> “meta”

步骤9: 更新状态文件

对于每个创建的任务:

9.1: 更新state.json

读取当前状态,添加新任务条目,递增next_project_number:

# 从标题创建slug
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '_' | tr -cd 'a-z0-9_' | cut -c1-50)

# 读取当前状态
current=$(cat specs/state.json)

# 使用jq添加任务(使用两步模式避免转义问题)
# 步骤1: 将任务数据写入临时文件
# 步骤2: 使用jq和slurpfile

对于当has_note_dependency为TRUE时的修复任务,包含依赖数组:

{
  "project_number": {N},
  "project_name": "{slug}",
  "status": "not_started",
  "language": "{language}",
  "dependencies": [learn_it_task_num]
}

对于所有其他任务,不需要依赖字段。

9.2: 更新TODO.md

## 任务部分前添加新任务条目(新任务在顶部):

标准格式(无依赖):

### {N}. {标题}
- **努力**: {估计}
- **状态**: [未开始]
- **语言**: {语言}
- **开始**: {时间戳}

**描述**: {描述}

---

当has_note_dependency为TRUE时的修复任务格式:

### {N}. {标题}
- **努力**: {估计}
- **状态**: [未开始]
- **语言**: {语言}
- **依赖**: {learn_it_task_num}
- **开始**: {时间戳}

**描述**: {描述}

---

步骤10: 显示结果

展示创建的任务摘要:

## 从标签创建的任务

**处理的标签**: {N}个,跨扫描文件

### 创建的任务

| # | 类型 | 标题 | 语言 |
|---|------|-------|----------|
| {N} | 修复 | 修复来自FIX:/NOTE:标签的问题 | {语言} |
| {N+1} | 学习 | 根据NOTE:标签更新上下文文件 | meta |
| {N+2} | TODO | {标题} | {语言} |

---

**下一步**:
1. 在TODO.md中审查任务
2. 运行`/research {first_task}`开始
3. 通过/research -> /plan -> /implement循环进展

步骤11: Git提交(后处理)

如果创建了任务,提交更改:

task_count={创建的任务数量}
git add specs/TODO.md specs/state.json
git commit -m "learn: 从标签创建$task_count个任务

会话: $session_id

共同作者: Claude Opus 4.5 <noreply@anthropic.com>"

错误处理

路径访问错误

当路径不存在或无法访问时:

  1. 为每个无效路径记录警告
  2. 继续使用有效路径
  3. 如果没有有效路径剩余,报告并退出

未找到标签

这不是错误条件:

  • 报告信息性消息
  • 退出,无提示

state.json更新失败

如果jq失败:

  1. 记录错误,包括命令和输出
  2. 尝试两步jq模式
  3. 如果仍然失败,报告部分成功(找到标签但任务未创建)

TODO.md解析错误

如果TODO.md格式损坏:

  1. 记录错误
  2. 跳过TODO.md更新
  3. State.json更新可能仍然成功
  4. 报告部分成功

Git提交失败

非阻塞:

  1. 记录失败
  2. 任务仍然成功创建
  3. 报告提交失败但任务存在

标准参考

此技能实现了多任务创建模式。参见.claude/docs/reference/standards/multi-task-creation-standard.md获取完整标准。

合规级别: 完全(所有必需组件)

组件 状态 备注
发现 标签扫描(FIX:, NOTE:, TODO:)
选择 AskUserQuestion与multiSelect
分组 主题聚类(步骤7.5)
依赖 部分 仅内部(学习任务 -> 修复任务在步骤8.2)
排序 顺序创建
可视化 未实现
确认 通过选择隐式确认
状态更新 原子更新(步骤9)

限制: 外部依赖(TODO任务依赖现有任务)未实现。考虑作为未来增强。