mcpField
A
agile-tdd

agile-tdd

github.com/djalmajr测试与质量4130 次安装5 周前更新
代码仓库

关于 agile-tdd

agile-tdd 是面向软件开发 Agent 的测试驱动开发流程技能,指导按 Red-Green-Refactor 编写测试并选择测试层级。它还提供可选钩子模板,用于对源文件缺少配套测试的情况发出警告或阻止写入。

主要功能

  1. 01引导 Red-Green-Refactor 循环
  2. 02按行为选择单元、集成或端到端测试
  3. 03规定测试命名与文件布局
  4. 04提供覆盖率目标和测试反模式
  5. 05可选钩子检查源文件配套测试
  6. 06支持 warn 或 block 执行模式

适用场景

  1. 01为新功能规划 TDD 测试
  2. 02为现有模块补充测试
  3. 03判断功能适合的测试层级
  4. 04为项目配置测试文件护栏

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/djalmajr/skills --skill agile-tdd

安装后在 Claude Code 中输入/agile-tdd确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

templates/
agents-block.md.tmpl
opencode-plugin.js.tmpl
tdd-guardrails.yml.tmpl
templates/hooks/
tdd-announce.sh.tmpl
tdd-pre-write.sh.tmpl
tdd-session-audit.sh.tmpl
templates/lib/
audit-helpers.sh.tmpl
templates/project-types/
README.md
templates/project-types/desktop/
README.md
templates/project-types/mobile/
README.md
templates/project-types/pwa/
README.md
templates/project-types/tauri/
agents-block.partial.md
audit.partial.sh
detect.sh
guardrails.partial.yml
README.md
templates/project-types/tauri/hooks/
tdd-record-mcp.sh.tmpl

详细介绍

TDD(测试驱动开发)

引导 Red-Green-Refactor 循环和务实的测试策略。“编写测试。不必太多。主要写集成测试。”

通过斜杠命令收到的初始上下文:$ARGUMENTS

如果 $ARGUMENTS 不为空(例如模块名称、功能描述),请以此为起点。 如果为空,请询问要测试什么。

语言

使用用户的语言编写产物和测试描述。如有疑问,请询问。测试代码本身(函数名、断言)保持英文。

项目根目录

此技能会在相对于项目根目录(开展工作的仓库)的路径下编写产物,而非 Agent 当前工作目录。

  • 如果从项目内部调用,请使用此技能中列出的相对路径。
  • 如果从其他目录调用(例如同级仓库,或项目位于其他位置),请在每个产物路径前加上 <project-root>/。
  • 如果项目根目录不明确,请在写入前通过 harness 的提问工具向用户确认。

提问

遵循 CLAUDE.md / AGENTS.md 中的项目级约定(“技能提问约定”)。在以下决策点使用 harness 的结构化提问工具——AskUserQuestion(Claude Code)、ask_user_question(Codex)或 question(OpenCode)。

决策点采用结构化提问的原因建议选项
强制模式(安装时)难以撤销的策略选择警告 · 阻止 · 保持当前设置
测试策略(存在歧义时)影响文件布局同级文件 · 同级目录 · tests 根目录
豁免特定路径修改防护配置是 · 否 · 稍后审核

自由文本提示(不使用结构化工具):

  • 测试描述
  • 豁免理由

无暂停模式:如果用户明确禁用了技能执行过程中的澄清,则将每个结构化提示转换为 待确认问题(或等效内容)中的条目,并继续执行,不要暂停等待回复。

适用场景

  • 使用 TDD 开始开发新功能
  • 为现有代码添加测试
  • 为模块建立测试覆盖率
  • 不确定某项内容需要单元测试、集成测试还是 E2E 测试

不适用场景

  • 测试无益的快速原型——使用 /agile-proto
  • 一次性脚本
  • 纯文档修改

TDD 循环

  1. Red(红)——编写一个描述预期行为的失败测试
  2. Green(绿)——编写使测试通过的最少代码
  3. Refactor(重构)——在不改变行为的前提下改进结构
  4. 重复

明确展示每个步骤。不要跳过 Red——测试必须先失败。

测试金字塔(务实版)

层级目标占比重点
单元60%纯函数、转换器、工具函数
集成30%服务、数据库交互、API 路由
E2E10%关键用户流程

整体覆盖率目标:75% 以上。

对于前端工作,应将这些比例视为风险参考,而非配额。优先编写能够覆盖用户行为、验证、本地状态、API 契约、权限、离线/同步行为和关键流程的集成测试。避免只断言静态文本、按钮是否渲染,或设计系统组件的实现细节的测试。

如果项目将业务规则保存在 planning/<initiative>/business/*.md 中,请使用这些规则 ID 判断哪些内容值得测试。测试应验证重要规则背后的行为,而不是复述规则文本。

文件结构

  • 单元: 与源文件放在一起(foo.test.ts 与 foo.ts 并列)
  • 集成/E2E: 使用 tests/,并包含 integration/、e2e/、helpers/、fixtures/、mocks/
  • 命名: .test.ts(单元/集成),.e2e.test.ts(E2E)
  • 绝不使用 .spec.ts

规则

  • AAA 模式(Arrange / Act / Assert,即准备 / 执行 / 断言)
  • 每个测试只验证一个概念
  • 使用读起来像句子的描述性名称
  • 始终使用工厂(例如 faker),避免使用硬编码数据
  • 使用 beforeEach 隔离测试——测试之间不得共享状态
  • 测试行为,而非实现细节

反模式(应避免)

  • 相互依赖的测试(测试 A 依赖测试 B 先运行)
  • 随意使用 sleep(ms)——应使用适当的等待方式
  • 测试私有方法——应通过公共 API 测试
  • 在测试中使用 console.log——应使用适当的断言
  • 依赖执行顺序的测试
  • 模拟自己编写的代码(模拟外部依赖,而不是自己的代码)

覆盖率目标(细分)

区域目标
转换器 / 纯函数90%+
工具函数85%+
服务80%+
路由 / 处理程序70%+

命令(Bun)

bun test
bun test --watch
bun test --coverage
bun test --filter "name"
bun test src/dir/

根据需要调整为其他运行时(vitest、jest)。建议命令前,先从 package.json 或配置文件中检测项目使用的测试运行器。

流程

1. 明确测试内容

浏览代码,了解:

  • 哪个模块或功能需要测试
  • 哪些行为至关重要
  • 已覆盖哪些内容(检查现有测试)
  • 此次更改必须满足哪些业务规则 ID、验收标准或原型流程

对于前端工作,在开始 Red 阶段前,先找出所有实际存在的原型来源。项目可能有 Agile-Proto 浏览器原型、Agile-Design 设计工具原型、两者都有,或两者都没有。原型证据有助于选择组件并明确可观察行为;它不会授权或阻止实施。

Agile-Proto 来源

在项目中已确定的位置查找浏览器原型,例如 planning/*/proto/ 和 {app}/client-proto/。读取其稳定的场景 ID / 路由,并检查实际的 htm-ui/<module>.js 导入。这些导入是直接的组件证据:

  • htm-ui/button.js 对应维护中的 HTM UI Button 模块;
  • 原型专用的组合文件属于组合,而不是复制来的基础组件目录;
  • 未导入维护中组件的自定义标记属于尚未解决的映射警告,而不是停止工作的理由。

使用原型中可观察到的行为和路由流程作为交互证据。根据目标应用已安装的组件系统和仓库惯例,确认生产环境中的对应实现,而不是机械地复制仅用于原型的标记。

Agile-Design 来源

阅读 planning/<initiative>/design/README.md(原型索引)及其总结的配套说明。屏幕和状态 ID、触发条件、操作目标和可见规则都是测试的行为证据。设计文件本身仅供视觉参考:它没有从设计到代码的组件映射,因此组件选择应依据目标应用已安装的组件系统和 /design-workflow。

两种来源都存在时

为目标用户故事或屏幕建立合并后的来源映射:

  1. 根据稳定的规划 / 用户故事 / 需求 ID 以及屏幕 / 场景用途进行匹配;
  2. 使用 Agile-Design 说明了解状态、转换和可见规则;
  3. 使用 Agile-Proto 导入和运行时交互了解浏览器行为及 HTM UI 标识;
  4. 任一来源映射到已安装的生产组件时,优先使用该组件;
  5. 来源不一致时,发出警告,并选择最贴近目标验收标准和当前产品代码的来源。只有当分歧会实质性改变用户可见行为或范围时,才询问用户。

绝不要仅仅因为原型缺失、不完整、过时或以多种格式呈现就拒绝实施。AI 应利用所有可用信号,在有帮助时说明判断的可信度,并依据最充分的证据选择组件后继续推进。

TDD 仍以可观察行为为准:测试屏幕流程、验证、权限、状态变化和集成契约,而不是设计系统组件的内部标记。

2. 选择合适的测试类型

以测试金字塔为指导:

  • 没有副作用的纯函数?单元测试。
  • 与数据库或外部 API 通信的服务?集成测试。
  • 跨多个系统的关键用户流程?端到端测试。
  • 涉及验证、API 契约、权限、乐观更新或离线/同步状态的前端行为?集成测试。
  • 静态文案、简单渲染或没有规则的纯视觉细节?通常无需测试,除非测试能防止已知回归。

对于本地优先产品,优先编写覆盖命令验证、乐观状态、离线队列持久化、协调、冲突处理、权限和审计事件的测试。

3. 执行 TDD 循环

针对每种行为:

  1. 编写失败的测试(Red)
  2. 编写最少量的实现代码(Green)
  3. 按需重构
  4. 验证测试仍然通过

如果有助于后续完善,可在测试描述或相关故事文档中记录业务规则 ID 或验收标准。

4. 验证覆盖率

运行覆盖率检查并对照目标。优先填补关键领域的覆盖缺口。

衔接

  • 实现功能期间:在 /agile-story 检查清单中开展工作
  • 实现完成后:使用 /agile-refinement 审查测试质量
  • 关闭之前:确保测试纳入 /agile-status(关闭模式)验证
  • 如果 TDD 工作流暴露出反复出现的阻碍、缺失的指导、薄弱的模板或不清晰的验证方式,请记录一条简明的技能反馈说明,注明受影响的技能/模板、证据、建议的修改和验证材料。
  • 如果反复出现的 TDD 阻碍表明需要修改技能/模板,请先起草提案供人工审查,再修改流程库。

强制执行(可选,按项目启用)

除了提供建议外,此技能还附带钩子模板,可将 TDD 规则转化为项目级防护措施。项目启用后,每次实现会话都会在文件写入层面接受检查,无需 Agent 记得调用此技能。

强制执行的内容
  • Write|Edit|MultiEdit 上的 PreToolUse — 如果目标文件符合 .tdd-guardrails.yml 中的 source_paths,且不存在对应测试,钩子会发出警告(mode: warn)或阻止工具调用(mode: block)。
  • Stop 钩子 — 在会话结束时扫描 git diff,并报告有修改但没有对应测试的源文件。
  • SessionStart 钩子 — 提示“已启用 TDD 强制执行”,让 Agent 知晓规则正在生效。

钩子模板位于 skills/agile-tdd/templates/hooks/*.sh.tmpl,配置架构位于 skills/agile-tdd/templates/tdd-guardrails.yml.tmpl。

配置(.tdd-guardrails.yml)
键含义
enabled全局开/关
modewarn(仅输出到 stderr)或 block(PreToolUse 拒绝调用)
source_paths必须有对应测试的 glob 模式
test_strategysibling(foo.ts → foo.test.ts)、sibling_dir(__tests__/foo.test.ts)或 tests_root(<app>/tests/integration/foo.test.ts)
exemptions允许没有测试的 glob 模式(入口点、生成文件、UI 基础组件)

**模式语义:**钩子脚本使用 bash case glob,而非扩展 globstar。在 bash case 模式中,* 匹配包括 / 在内的任意字符序列;不存在 **。因此,apps/*/src/*.ts 同时匹配 apps/server/src/handler.ts 和 apps/server/src/auth/handler.ts。不要在 source_paths 或 exemptions 中使用 **。

强制执行的注意事项

钩子会检查文件对是否存在,但不会也无法验证:

  • 测试是否在源代码之前编写(不会检查 Red-before-Green 顺序)。
  • 测试是否确实覆盖源代码(不会进行语义匹配)。
  • 测试当前是否通过(不会运行测试)。

语义层面的规范(每个测试覆盖一种行为、优先使用工厂而非硬编码数据、使用描述性名称、遵循 AAA)仍由 Agent 负责。钩子只是防护措施,并非保证。

手动安装(在 tdd-init 脚本推出之前)

各运行环境的操作方式有所不同——Claude Code 和 Codex 会直接运行 shell 钩子;OpenCode 则运行一个 JS 插件,由它来编排相同的 shell 脚本。

  1. 将 templates/tdd-guardrails.yml.tmpl 复制到 <project-root>/.tdd-guardrails.yml,并编辑 source_paths 和 exemptions,使其符合仓库布局。

    然后运行项目类型检测器,以填充 project_types:

    for type in .claude/skills/agile-tdd/templates/project-types/*/; do
      name="$(basename "$type")"
      [ -f "$type/detect.sh" ] || continue
      bash "$type/detect.sh" "$PWD" && echo "detected: $name"
    done
    

    对于每种检测到的类型,将其 guardrails.partial.yml 追加到新建的 .tdd-guardrails.yml 中(如果该区块已存在,则进行合并),并将类型 slug 添加到 project_types 列表中。

  2. 复制钩子模板。从 templates/hooks/ 复制到 <project-root>/.claude/hooks/、<project-root>/.codex/hooks/、以及 <project-root>/.opencode/hooks/(OpenCode 插件会通过 node:child_process.spawn 调用相同的脚本)。移除 .tmpl 后缀,并运行 chmod +x。

    还要复制共享辅助文件:

    templates/lib/audit-helpers.sh.tmpl → .claude/hooks/lib/audit-helpers.sh
    

    以及项目类型目录:

    templates/project-types/ → .claude/hooks/project-types/
    

    会话审计脚本会在这两个位置查找。Codex/OpenCode 也应分别镜像到 .codex/hooks/ 和 .opencode/hooks/ 下。

  3. 在各运行环境的配置中注册钩子:

    • Claude Code(.claude/settings.json):添加一个匹配 Write|Edit|MultiEdit、调用 $CLAUDE_PROJECT_DIR/.claude/hooks/tdd-pre-write.sh 的 PreToolUse 条目,一个调用 tdd-session-audit.sh 的 Stop 条目,以及一个调用 tdd-announce.sh 的 SessionStart 条目。与现有钩子合并——不要替换。
    • Codex(.codex/hooks.json):添加匹配 apply_patch|Edit|Write|MultiEdit 的 PreToolUse 条目,以及 Stop 和 SessionStart 条目。命令形式使用 bash "$(git rev-parse --show-toplevel)/.codex/hooks/<script>.sh"(Codex 模式)。每个条目都包含 statusMessage 字段。
    • OpenCode:将 templates/opencode-plugin.js.tmpl 复制到 <project-root>/.opencode/plugins/tdd-guardrails.js。该插件订阅 tool.execute.before(相当于 PreToolUse)、session.created(相当于 SessionStart)和 session.idle(最接近 Stop——审计 shell 通过临时状态文件实现幂等,因此多次触发也安全)。插件通过 node:child_process.spawn 启动相同的 .opencode/hooks/tdd-*.sh 脚本。OpenCode 不会直接调用 shell 脚本;插件是入口。
  4. 将 templates/agents-block.md.tmpl 的内容追加到 AGENTS.md 和 CLAUDE.md,告知 Agent 项目已启用 TDD 强制检查。

    对于每种检测到的项目类型,还要将其 templates/project-types/<type>/agents-block.partial.md 追加到相同的 文件中(保留 / :end 标记,以便重新安装时能原位更新)。

  5. 在 .claude/settings.json 中注册特定类型的匹配器:

    • 对于 tauri:添加一个匹配 mcp__tauri__webview_screenshot|mcp__tauri__webview_execute_js|mcp__tauri__webview_dom_snapshot|mcp__tauri__manage_window 并调用 $CLAUDE_PROJECT_DIR/.claude/hooks/tdd-record-mcp.sh 的 PostToolUse 条目。

    Codex 对应的配置放在 .codex/hooks.json 中;对于 OpenCode, 订阅按工具名称筛选的 tool.execute.after,并通过 node:child_process.spawn 启动相同的 shell 脚本。

这些钩子是防护措施,并非保证——它们检查的是文件对是否存在,而不是测试质量。语义层面的规范(每个测试只验证一种行为、优先使用工厂而非硬编码数据)仍由 Agent 负责。

运行环境兼容性矩阵
运行环境入口点写入前事件Stop 等效项会话开始
Claude Code.claude/settings.json hooksPreToolUse(匹配器 Write|Edit|MultiEdit)StopSessionStart
Codex.codex/hooks.json hooksPreToolUse(匹配器 apply_patch|Edit|Write|MultiEdit)StopSessionStart
OpenCode.opencode/plugins/tdd-guardrails.js JS 插件tool.execute.beforesession.idle(最接近的可用事件;审计具有幂等性)session.created
有意绕过
  • 针对某个路径:将其添加到 .tdd-guardrails.yml → exemptions。
  • 针对某个会话:临时设置 enabled: false(并在提交前恢复)。
  • 切勿为了让钩子静默而删除测试文件——这会违背初衷。

项目类型模板

除了基础的伴随测试规则外,agile-tdd 还在 templates/project-types/<type>/ 下提供项目类型模板。每个模板都会启用特定于项目的证据检查,Stop 钩子会在检查伴随测试的基础上执行这些检查。会话审计脚本会将基础检查与每个启用类型的片段组合起来——每种类型的模式相互独立,因此你可以让 TDD 以 warn 模式运行,同时让更严格的类型以 block 模式运行。

可用类型
类型检测内容强制要求(除伴随测试外)
taurisrc-tauri/Cargo.toml(单仓库或单体仓库)cargo check 结果为最新 + bun run typecheck 结果为最新 + 每个受影响应用在最后一次编辑后至少执行 1 次 mcp__tauri__webview_screenshot
pwa(计划中)manifest.webmanifest + service worker重新构建 service worker + 离线冒烟测试
mobile(计划中)app.json(Expo)/ Podfile / android/build.gradle平台构建通过 + 模拟器截图
desktop(计划中)electron/forge 配置electron-builder 验证 + 窗口截图

启用的类型列在 .tdd-guardrails.yml → project_types 中。安装时,会针对仓库运行每个 templates/project-types/<type>/detect.sh;检测成功的类型会连同其 guardrails.partial.yml 配置块一起追加到配置文件中。

类型的组成

一个类型是一个包含以下内容的文件夹:

  • detect.sh — 当该类型适用于仓库时,退出码为 0。
  • guardrails.partial.yml — 追加到 .tdd-guardrails.yml 的配置块。
  • agents-block.partial.md — 在标记之间追加到 CLAUDE.md/AGENTS.md 的章节。
  • audit.partial.sh — 由 tdd-session-audit.sh 加载。导出 check_<type>_evidence "$ROOT",返回文本格式的违规信息。设置 <TYPE>_MODE(大写),供框架决定采用阻止还是警告模式。
  • hooks/*.sh.tmpl — 该类型注册的可选额外钩子(例如 PostToolUse 证据记录器)。
  • README.md — 对该类型的说明文档。

框架会调用 templates/lib/audit-helpers.sh 中的辅助函数来解析 yml、匹配 glob、查找应用根目录以及检查时效性。添加新类型无需修改框架脚本。

安装类型

基础 agile-tdd 安装已遵循上述“手动安装”步骤。对于每个检测到的类型:

  1. 将 templates/project-types/<type>/guardrails.partial.yml 追加到 .tdd-guardrails.yml(如果配置块已存在,则进行合并)。
  2. 在标记对之间将 agents-block.partial.md 追加到 CLAUDE.md/AGENTS.md。
  3. 将 hooks/*.sh.tmpl 复制到 .claude/hooks/、.codex/hooks/ 和 .opencode/hooks/,去掉 .tmpl 后缀并执行 chmod +x。
  4. 将该类型的匹配器添加到每个 harness 配置中:
    • Claude Code(.claude/settings.json → PostToolUse):为该类型的 PostToolUse 钩子添加匹配器条目。对于 tauri: mcp__tauri__webview_screenshot|mcp__tauri__webview_execute_js|mcp__tauri__webview_dom_snapshot|mcp__tauri__manage_window 调用 $CLAUDE_PROJECT_DIR/.claude/hooks/tdd-record-mcp.sh。
    • Codex(.codex/hooks.json):使用相同的匹配器模式;命令使用 bash "$(git rev-parse --show-toplevel)/.codex/hooks/tdd-record-mcp.sh"。
    • OpenCode:扩展 .opencode/plugins/tdd-guardrails.js,使其订阅 tool.execute.after,并按工具名称筛选,通过 node:child_process.spawn 启动同一个 shell 脚本。
  5. 将类型标识(例如 tauri)追加到 .tdd-guardrails.yml 中的 project_types。会话审计会在运行时读取此列表。

Tauri MCP 验证(项目类型)

汇总自真实的 Tauri 调试/测试会话的经验。在已检测为 Tauri 的仓库中修改 src-tauri/src/** 或任何 src/{routes,components,hooks}/** 之前,请先阅读本文档。

工具箱(规范参考)
  • mcp__tauri__driver_session(start) — 始终先调用;后续的 webview 工具都假设会话处于活动状态。
  • mcp__tauri__webview_screenshot — 规范的“我已打开屏幕”信号。传入 windowId="main"(Tauri 应用通常有 main 和 tray-panel)。
  • mcp__tauri__webview_execute_js — 对于耗时超过 JS 执行器超时 (约几秒)的调用,通过 window.__TAURI_INTERNALS__.invoke(cmd, args).then(r => window.__last = r) 以即发即忘方式执行; 改为轮询 DB 或截屏,而不是使用 await 等待。
  • mcp__tauri__webview_interact / webview_find_element / webview_dom_snapshot 中的引用 — 这些依赖 window.__MCP__.resolveRef,该函数在开发服务器 HMR 重载后会变为 未定义。优先通过 webview_execute_js 使用 document.querySelector(...).click()。
重新构建流程
  • Rust 更改 → touch src-tauri/src/<file.rs>,强制 tauri-dev 重新 构建(cargo 的 mtime 监视器)。
  • 重新运行 MCP 调用前,监控开发进程输出,直到出现 Finished 和 MCP Bridge plugin initialized;HMR 只覆盖前端。
  • 在 Claude Code 中,优先使用 Monitor,并设置过滤器 tail -f tauri.log | grep --line-buffered -E "Finished|error\\[|MCP Bridge plugin initialized"。
验证模式
  • 直接读取 DB — 用于状态断言时比 invoke() 更省资源: sqlite3 <workspace>/<app>.db "SELECT ..."。
  • GPU 卸载检查 — ps -p $(pgrep -x <app-name>) -o pcpu,etime。 使用 Metal/CUDA 的应用在 GPU 执行工作时 CPU 占用率较低(5–15%);仅使用 CPU 的回退模式则为 200–400%。
  • 视觉检查 — 通过 webview_execute_js 执行 location.assign('/route/...'),等待约 500 ms,然后调用 webview_screenshot。
已知注意事项(跨项目模式)

每个项目都有自己的代码库内修复项列表(例如,遵循 LLM wiki 模式的项目会将其放在 wiki/technical/tauri-gotchas.md 中)。以下内容描述的是模式,实际 文件路径因项目而异。

  • whisper-rs 0.14.x 的 set_abort_callback_safe 类型混淆 — 在 v0.14.4 中,trampoline 使用原始闭包 类型实例化,而 user_data 实际写入的是 Box<dyn FnMut() -> bool>。回调解引用了错误的 内存布局并返回无意义的布尔值,导致 whisper 在 0–5% 处以错误 -6 中止。解决方法:使用 unsafe 变体 set_abort_callback + set_abort_callback_user_data,并手写一个与存储类型匹配的 trampoline:

    unsafe extern "C" fn abort_trampoline(ud: *mut std::ffi::c_void) -> bool {
        let f = &mut *(ud as *mut Box<dyn FnMut() -> bool>);
        f()
    }
    let closure: Box<dyn FnMut() -> bool> = Box::new({
        let cancel = cancel.clone();
        move || cancel.load(Ordering::Relaxed)
    });
    let ud = Box::into_raw(Box::new(closure)) as *mut std::ffi::c_void;
    unsafe {
        params.set_abort_callback(Some(abort_trampoline));
        params.set_abort_callback_user_data(ud);
    }
    
  • 二进制被终止后,后台任务卡在 running 状态 — 一个 tokio 任务 若在执行过程中途退出(cargo 重启、应用崩溃),永远不会将其 DB 行更新为终态。在打开连接池时添加一次协调检查:

    // db::open_pool, after schema migration
    sqlx::query(
        "UPDATE jobs SET status='cancelled',
             error_message=COALESCE(error_message,'interrupted by app restart'),
             finished_at=?
         WHERE status IN ('running','pending')"
    ).bind(now_iso()).execute(&pool).await?;
    
  • 将 open 与数据状态耦合的模态框库(例如 Base UI Dialog、某些 Radix 模式)— 当数据 prop 在同一次渲染中变为 null, 且 open 切换为 false 时,模态框会在关闭动画结束前卸载;document.body 上的指针事件会一直被拦截, 导致页面无法点击。将 open(布尔值)与数据解耦,然后用 setTimeout(..., 200) 延迟清除数据(或者在库提供 onCloseComplete 回调时使用该回调)。

  • CREATE TABLE IF NOT EXISTS 对已有表不起作用 — 复用的工作区 / DB 不会获取架构文件中新增的列。症状:升级后运行时提示 no such column。修复选项:针对每项架构偏差,显式执行 ALTER TABLE … ADD COLUMN IF NOT EXISTS;或者,如果 DB 中没有生产数据,则删除并重新初始化。

  • hound::WavReader 只能解码 WAV — 对于 .mp3/.mp4/.m4a/ .webm,先通过 ffmpeg 转为 f32le @ 16 kHz mono,再 传给 Whisper:

    // ffmpeg -hide_banner -loglevel error -nostdin -i <input>
    //   -ac 1 -ar 16000 -f f32le -
    let mut child = Command::new(ffmpeg)
        .args(["-hide_banner","-loglevel","error","-nostdin","-i"])
        .arg(input)
        .args(["-ac","1","-ar","16000","-f","f32le","-"])
        .stdout(Stdio::piped()).spawn()?;
    // read stdout, reinterpret bytes as &[f32]
    
Definition of Done(Tauri)

对于每项涉及每个受影响应用中 affected_paths 的更改(单体仓库:按应用分别处理):

  1. cargo check --manifest-path <app>/src-tauri/Cargo.toml --lib 检查通过。
  2. bun run typecheck(或 tsc --noEmit)检查通过。
  3. 在 <app>/src-tauri/src/** 中最后一次 touch 后,tauri-dev 显示 Finished。
  4. 存在配套测试(适用时遵循基本 TDD 规则)。
  5. 在 <app>/{src-tauri,src}/** 下最后一次编辑后,至少调用 1 次 mcp__tauri__webview_screenshot。
  6. 确认操作后的状态:通过数据库查询、DOM 快照或截图中可见的证据进行确认。

tdd-session-audit.sh Stop hook 通过 tauri 模板自动检查 (1)、(2) 和 (5)。第 (3)、(4) 和 (6) 步由 Agent 负责。

与工作流的关系

flowchart LR
    A["/agile-story"] --> B[TDD cycle]
    B --> C[Red: failing test]
    C --> D[Green: minimum code]
    D --> E[Refactor]
    E --> F{More?}
    F -->|Yes| C
    F -->|No| G["/agile-refinement"]

此技能在执行期间发挥作用。它与 /agile-story(定义要构建的内容)配合,并为 /agile-refinement(验证结果)提供输入。安装可选强制机制后,该规则也会在每次调用 Write/Edit/MultiEdit 工具时自动应用。

评论

支持 Markdown