Taiga stories
无需浏览器控制。上传通过 Taiga REST API 进行,使用 scripts/taiga_stories.py 脚本,该脚本仅依赖 Python 标准库。同一套工具适用于任何 Taiga 项目,项目配置位于 .env 中。
设置(每个仓库只需一次)
- 将仓库根目录下的
.env.example复制为.env,并将TAIGA_PROJECT_URL设置为项目链接,例如https://taiga.example.com/project/my-project。 - 可选设置
STORIES_DIR(默认为stories)。
.env 不包含任何机密信息,且被 git 忽略。令牌 绝不能 放入其中。
编写故事
每个故事是 stories/ 目录下的一个 .md 文件,遵循 story-template.md 模板。
-
文件名: 小写、无重音符号、单词之间使用连字符(
automatic-slug.md)。 -
第一行:
# Story: <标题>。“Story:” 之后的文本将成为 Taiga 中的标题。对于错误修复,使用Fix — <问题描述>。 -
页眉:
**Project:**、**Branch:**、**Version:**、**Date:**和**Points:**,每行一个。 -
故事点: 没有默认值。在将新故事保存到
stories/之前,使用story-pointsskill 估算其故事点(查看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çõesFix — ...Correção — ... -
防火墙友好文本: 在描述中,避免在
code前使用;(使用句号)、字面标签如<script>(写成“script 标签”),以及路由旁连续的Class::method。脚本会绕过这些问题,但文本质量会下降。
检查格式(无需网络,无需令牌):
python -X utf8 .claude/skills/taiga-stories/scripts/taiga_stories.py validate [file.md ...]
修复错误。没有描述的任务只是警告。缺少 **Points:** 此处也仅作为警告,但会阻止上传。
上传到 Taiga
每次务必先在聊天中询问
使用 AskUserQuestion 或(若不可用)直接提问。不要重复使用之前的答案:
- 目标: 哪个 sprint(精确名称,例如
Sprint 34)或 backlog。 - 会话令牌: 在打开的 Taiga 标签页中,按 F12 > 控制台 >
localStorage.getItem("token")。仅将其作为命令的内联环境变量使用。绝不要将其写入.env或任何文件。 - 缺失的故事点: 如果要上传的任何故事没有
**Points:**(--dry-run会显示MISSING),使用story-pointsskill 估算并让用户确认,按标题列出。将每个值写入故事的**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,以便正确打印重音字符。