Community编程与开发github.com

taiga-stories

将用户故事以标准格式编写为 Markdown 文件并上传到 Taiga,每个故事包含“## Tasks”下列出的任务。在用户要求编写、创建、标准化或审核故事 .md,或要求将故事和任务上传、注册或推送到 Taiga、某个 Sprint 或待办事项列表时使用。

taiga-stories 是什么?

这是一个专门用于 Taiga 项目管理平台的 AI 助手技能,核心功能是将用户故事以标准 Markdown 格式编写并上传至 Taiga。技能通过 Taiga REST API 实现上传,仅依赖 Python 标准库,无需浏览器控制。它支持英语和葡萄牙语两种语言的故事编写,并能自动处理标题、元数据(如项目、分支、版本、日期和故事点)以及任务分组(后端、前端、测试、文档)。上传前需要用户确认目标 Sprint 或待办事项、提供会话令牌,并通过 `--dry-run` 模式检查缺失的故事点。脚本具有防重复、断点续传和防火墙友好文本重写等特性,能有效处理 Cloudflare WAF 拦截等问题。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/czarist/md2taiga/tree/HEAD/.claude/skills/taiga-stories

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Taiga stories

无需浏览器控制。上传通过 Taiga REST API 进行,使用 scripts/taiga_stories.py 脚本,该脚本仅依赖 Python 标准库。同一套工具适用于任何 Taiga 项目,项目配置位于 .env 中。

设置(每个仓库只需一次)

  1. 将仓库根目录下的 .env.example 复制为 .env,并将 TAIGA_PROJECT_URL 设置为项目链接,例如 https://taiga.example.com/project/my-project。
  2. 可选设置 STORIES_DIR(默认为 stories)。

.env 不包含任何机密信息,且被 git 忽略。令牌 绝不能 放入其中。

编写故事

每个故事是 stories/ 目录下的一个 .md 文件,遵循 story-template.md 模板。

  • 文件名: 小写、无重音符号、单词之间使用连字符(automatic-slug.md)。

  • 第一行: # Story: <标题>。“Story:” 之后的文本将成为 Taiga 中的标题。对于错误修复,使用 Fix — <问题描述>。

  • 页眉: **Project:**、**Branch:**、**Version:**、**Date:** 和 **Points:**,每行一个。

  • 故事点: 没有默认值。在将新故事保存到 stories/ 之前,使用 story-points skill 估算其故事点(查看 CODE_REPO_PATH 的提交历史),并让用户确认。将值写入 **Points:**(葡萄牙语为 **Pontos:**)。它必须是项目点标度中的名称(1, 2, 3, 5, 8, 13, 21)。

  • 章节,按此顺序: ## User story(As / I want / so that,每个加粗显示在自己的行上)、## Description(面向产品负责人的散文,无代码术语)、## Acceptance criteria(- [ ] 清单,[x] 表示已完成并测试)、## Tasks 和 ## Deployment notes(若非部署相关则用 ## Notes)。

  • 任务: 按顺序分组到 ### Backend、### Frontend、### Tests 和 ### Documentation 下,空组可省略。每个任务格式为 N. **标题**,描述缩进在下一行。编号在所有组中连续。

  • 语言: 整个故事(包括标题)使用用户请求的语言编写。葡萄牙语的请求会得到葡萄牙语的故事。以下两套标题均被解析:

    英语葡萄牙语
    # Story:# História:
    **Project:** / **Branch:** / **Version:** / **Date:** / **Points:****Projeto:** / **Branch:** / **Versão:** / **Período:** / **Pontos:**
    ## User story (As / I want / so that)## História de usuário (Como / quero / para)
    ## Description## Descrição
    ## Acceptance criteria## Critérios de aceite
    ## Tasks (### Backend, ### Frontend, ### Tests, ### Documentation)## Tarefas (### Backend, ### Frontend, ### Testes, ### Documentação)
    ## Deployment notes / ## Notes## Observações para implantação / ## Observações
    Fix — ...Correção — ...
  • 防火墙友好文本: 在描述中,避免在 code 前使用 ;(使用句号)、字面标签如 <script>(写成“script 标签”),以及路由旁连续的 Class::method。脚本会绕过这些问题,但文本质量会下降。

检查格式(无需网络,无需令牌):

python -X utf8 .claude/skills/taiga-stories/scripts/taiga_stories.py validate [file.md ...]

修复错误。没有描述的任务只是警告。缺少 **Points:** 此处也仅作为警告,但会阻止上传。

上传到 Taiga

每次务必先在聊天中询问

使用 AskUserQuestion 或(若不可用)直接提问。不要重复使用之前的答案:

  1. 目标: 哪个 sprint(精确名称,例如 Sprint 34)或 backlog。
  2. 会话令牌: 在打开的 Taiga 标签页中,按 F12 > 控制台 > localStorage.getItem("token")。仅将其作为命令的内联环境变量使用。绝不要将其写入 .env 或任何文件。
  3. 缺失的故事点: 如果要上传的任何故事没有 **Points:**(--dry-run 会显示 MISSING),使用 story-points skill 估算并让用户确认,按标题列出。将每个值写入故事的 **Points:** 行(葡萄牙语为 **Pontos:**),紧随 **Date:** / **Período:** 之后。已有故事点的故事不会再次估算。 在上传前,只要任何一个故事缺少有效值,上传就会停止,不会创建任何内容。

如果缺少 .env,还需询问 Taiga 项目链接,并根据 .env.example 创建 .env。

步骤

S=.claude/skills/taiga-stories/scripts/taiga_stories.py
python -X utf8 $S validate
python -X utf8 $S upload --sprint "Sprint 34" --dry-run        # 或 --backlog
TAIGA_TOKEN='<token>' python -X utf8 $S upload --sprint "Sprint 34"

在末尾传递文件名可仅上传部分故事。然后向用户汇报创建了多少故事和任务,以及脚本重写了哪些文本(以及哪些任务的描述被丢弃)。

默认行为:令牌所有者是故事和任务的负责人,状态使用项目默认值,故事点来自每个故事的 **Points:** 字段,基于项目的可计算角色。

脚本:

  • 跳过 标题已经在项目中存在 的故事。仅在用户要求时使用 --force;
  • 中断后可恢复运行而不重复(状态保存在 stories/.taiga_state.json 中)。如果中断,只需再次运行;
  • 重写被防火墙阻止的文本,并在结束时列出。

不要在可能失败的步骤之后用 ; 链接其他创建命令。中途失败可能导致重复。

经验教训

  • Cloudflare 403 带 HTML 正文(“Just a moment...”)表示 WAF 阻止了文本,而非权限问题。脚本会使用更简单的变体重试。如果某个任务最终没有描述,将其重写为纯散文(无反引号、无 ::),并通过 PATCH 发送当前 version。
  • 403 带 JSON PermissionDenied 是真正的权限错误。普通成员可能无法 删除用户故事(任务可以),因此避免重复。如果发生重复,使用 PATCH(主题、描述、故事点、里程碑、assigned_to、version)复用该故事,而不是删除。
  • 故事点通过 points: {"<可计算角色 ID>": <故事点 ID>} 设置,故事点 ID 根据名称在项目标度中查找。
  • 在 Windows 上,Python 无法识别 Git Bash 的 /tmp。请使用 Windows 路径,并运行带参数 -X utf8 的 Python,以便正确打印重音字符。

相关技能