105 lines
7.9 KiB
Markdown
105 lines
7.9 KiB
Markdown
---
|
||
name: ticket-management
|
||
description: 用 Gitea 工单库做「人读 + 机读」双面管理 —— 标签零新增;标题用【问题域】前缀(闸门仅「不能动」时作第二段);正文**首行一行机读字段**(域/闸门/优先级/类型/模式/端/环境/证据);正文**自包含**(禁本地路径与内部分析编号,源码用仓库相对路径 + 该 ref 的 permalink);来源只能进**末尾机读引用块**(须写明 ref-owner)。含 bin/ticket.mjs 的 labels/milestones/list/verify/create/rename。适用于:建单、批量规范化既有工单标题、校验工单是否合规、用 API 读写 Gitea issue。
|
||
---
|
||
|
||
# ticket-management(Gitea 工单管理)
|
||
|
||
> **定位**:执行方法(怎么做),不含项目结论。
|
||
> **一句话**:**标签给人(少而稳)· 正文块给机器(全而准)· 标题给人扫(问题域 + 能否动)**。
|
||
|
||
## 0 什么时候用 / 不用
|
||
|
||
**用**:建单;批量规范化既有工单的标题 / 首行;校验工单是否符合本规范;用 API 读标签 / 里程碑 / 工单。
|
||
**不用**:拿工单做排期与资源计划(那是项目管理);把工作区内部知识库路径写进工单(见 §1 硬规则 3)。
|
||
|
||
## 1 三条硬规则(不合规就不建单)
|
||
|
||
1. **标签零新增** —— 只用仓库既有标签;**不得**为分类新建标签(标签是给人扫的稀缺资源,词表一膨胀人就不再用了)。
|
||
2. **标题 = `【问题域】` + 可选 `【闸门】`** —— 闸门**只在「当前不能开工」时**出现;能开工就不加(默认即常态,零打扰)。
|
||
3. **正文自包含** —— 人读部分**不得**出现工作区 / 本地路径(`codes/`、`分析/`、`C:\…`、`/home/…`)或内部分析编号;源码引用一律 **仓库相对路径 + 该 ref 的 permalink**。
|
||
|
||
## 2 标题规范
|
||
|
||
- **前缀(必填,单括号、`/` 分隔)**:`【订单】` `【库存】` `【结算】` `【商品】` `【报表】` `【平台】` `【其他】`;带闸门时**合并成一个括号**:`【域-闸门】`(例 `【报表-等口径】`)—— 分隔符用**半角连字符 `-`**;**不要写两个括号**(`【报表】【等口径】` 已废止)。
|
||
- 词表**可按项目替换**,但**改动须登记**;新域先用 `【其他】`,**同域攒够 3 条再立**新前缀。
|
||
- **闸门(可选)**:`-等口径` `-等取证` `-等部署` —— **仅当「不能开工」**;可开工 ⇒ 括号里只有域。
|
||
- **准入三问**(新增任何段都要过):① 列表页会按它筛 / 排吗?② 能否从正文推出(能推就别重复占位)?③ 生命周期里会变几次(反复变 = 每次都要改标题)?
|
||
- 按此三问:**问题域、闸门**通过;**优先级**(churn 大)· **端** · **环境** · **版本** · **客户 / 店铺**(敏感)· **批次**(用 milestone)全部不通过。
|
||
|
||
## 3 正文规范
|
||
|
||
### 3.1 首行 = 机读行(也是人读的第一行)
|
||
|
||
域=L1-L2-L3 | 闸门=… | 优先级=… | 类型=… | 模式=… | 端=… | 环境=… | 证据=…
|
||
|
||
- **字段顺序固定**;分隔符 = 空格 + 竖线 + 空格。
|
||
- **`域` 的 L1 必须等于标题主前缀**(机器可校验);`域` 三段逐级更细、**用半角连字符 `-` 分隔**(`域=L1-L2-L3`,如 `域=报表-统计-模式分列`):**L1 受控**(= 标题词表)· **L2 受控小词表** · **L3 自由**(表 / 文件 / 函数 / 接口)。
|
||
- 枚举建议:`闸门`=可开工|等口径|等取证|等部署 · `优先级`=立即|本迭代|排队 · `类型`=安全|数据|性能|可用|债务 · `端`=后端|前端|小程序|运维 · `环境`=正式服|测服 · `证据`=E1|E2|需生产取证。
|
||
- 若标题出现第二段,**必须与 `闸门=` 一致**。
|
||
|
||
### 3.2 正文其余(人读)
|
||
|
||
现象 → 证据锚点(仓库路径 + permalink)→ 复现(只读命令,仓库内执行)→ 影响面 → 反证条件
|
||
|
||
### 3.3 末尾 = 机读引用块(人读渲染不可见)
|
||
|
||
```html
|
||
<!-- 机器可读 · 引用登记(正文已自包含,本段不参与人读)
|
||
ref-owner: <引用对象的拥有者,例如:某分析工作区 / 某会议纪要库>
|
||
refs:
|
||
- <外部编号或文件>
|
||
-->
|
||
```
|
||
|
||
- **必须**写明 `ref-owner`(**引用对象的拥有者**)—— 读者据此知道该去哪儿找、以及**它不在这条工单所在的仓里**。
|
||
- **没有外部引用就整段不要**;也不要把内部编号写进人读部分。
|
||
|
||
## 4 路径口径
|
||
|
||
| | 写法 |
|
||
|---|---|
|
||
| ✅ 源码(本仓) | `path/to/file.go:105` + `https://<host>/<owner>/<repo>/src/commit/<sha>/<path>#L105` |
|
||
| ✅ 依赖 / 框架(**另一个仓**) | 另标仓:`https://<host>/<owner>/<repo>/src/tag/<tag>/<path>#L829` |
|
||
| ⛔ 禁用 | 本地物化前缀(`codes/` · `vendor/` 副本)、工作区路径(`分析/`)、内部分析编号 |
|
||
|
||
⚠ **行号必须按所引 ref 复核** —— 本地克隆常落后远端(实测:本地 `f5b74b2` 落后远端 `main` `c210c293`)。做法:用 API 取该 ref 的文件内容,再在内容里定位行号。
|
||
|
||
## 5 工具 `bin/ticket.mjs`
|
||
|
||
```bash
|
||
# 令牌:GITEA_TOKEN 环境变量,或 --token-file=<含 key=value 的文件>(不落盘、不回显)
|
||
node bin/ticket.mjs labels --repo xbc/xbc
|
||
node bin/ticket.mjs milestones --repo xbc/xbc
|
||
node bin/ticket.mjs list --repo xbc/xbc --state=open
|
||
node bin/ticket.mjs verify 142 --repo xbc/xbc
|
||
node bin/ticket.mjs create --repo xbc/xbc --title='【平台】…' --body-file=body.md --label=77 [--dry-run]
|
||
node bin/ticket.mjs rename 142 --repo xbc/xbc --domain=平台 [--gate=等口径] [--dry-run]
|
||
```
|
||
|
||
| 子命令 | 作用 | 需要 scope |
|
||
|---|---|---|
|
||
| `labels` / `milestones` / `list` | 读(标签 id 是创建时唯一可传的形式) | `read:issue` |
|
||
| `verify <n>` | **校验**(只读):见 §7 六项断言 | `read:issue` |
|
||
| `create` | 建单(**先按标题查重**) | `write:issue` |
|
||
| `rename <n>` | 规范化标题(重建前缀,描述不动) | `write:issue` |
|
||
|
||
## 6 常见坑(实测)
|
||
|
||
- **HTTP 分块解码**:`let d = ''; res.on('data', c => d += c)` 会把**跨块的多字节字符**打成 `U+FFFD`(中文标签名就被打坏过)⇒ 必须 `res.setEncoding('utf8')`,或用 `fetch` 的 `text()`。
|
||
- **建单前必须查重**:按标题查,否则会重复建单。
|
||
- **标签传 id**:`POST /issues` 的 `labels` 是**标签 id 数组**,不是名字。
|
||
- **批量改首行时必须保持 ` | ` 形态**(空格 + 竖线 + 空格):把 `域=…` 换成新值时若顺手吃掉它后面的空格,`闸门=` 会与 `域` 黏成一段 ⇒ **断言 4 全线 FAIL**(实测 14/14 中招,工具拦住了)。
|
||
- **改标题与正文**:都是 `PATCH /repos/{owner}/{repo}/issues/{n}`。
|
||
- **令牌 scope**:只读 `read:issue,read:repository` 建不了单(403,报错会写 required scope);建 / 改需 `write:issue`;`GET /user` 另需 `read:user`。
|
||
- **里程碑可能已被当「状态桶」用**(如「记录工单 / 领取工单 / 完结工单」)⇒ 不要再用它承载闸门,否则两套状态打架;用前先 `milestones` 看语义与 `due_on`。
|
||
- **没有看板时**(`/projects` 返回 404)不要设计「用看板列承载闸门」的流程。
|
||
|
||
## 7 `verify` 的六项断言(可交机器)
|
||
|
||
1. 标题以 `【…】` 开头,且内文 ∈ 问题域词表;
|
||
2. 正文第一行存在且含 `域=`;
|
||
3. **标题主域 = 首行 `域=` 的 L1**(`域` 内以 `-` 分层);
|
||
4. 标题 `-` 后的闸门 ∈ 词表 **且** 等于首行 `闸门=`;**可开工时标题不得带 `-闸门`**(多写即 FAIL);
|
||
5. 人读部分(第一个 `<!--` 之前)**不含**工作区路径与内部分析编号 —— 判据用**具体前缀**(`codes/` · `分析/数据/` · `分析/D-`…`分析/F-` · `分析/_tmp` · `分析/_archive` · `86 §` · `80 · V` · 盘符路径);⚠ **不要用裸 `分析/`**(会误伤中文词组,如「进货分析/商品维度」);
|
||
6. 正文若含 `<!--` ⇒ 该注释块必须含 `ref-owner:`。 |