task-ledger 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -4
- package/SKILL.md +86 -135
- package/assets/worklog.md +8 -16
- package/package.json +3 -2
- package/references/log-note.md +47 -0
- package/references/state-model.md +43 -0
- package/references/taxonomy.md +26 -0
- package/references/troubleshooting.md +26 -0
- package/references/worklog.md +39 -0
- package/scripts/progress.py +23 -13
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|---|---|---|
|
|
12
12
|
| 在办任务的状态 | `ledger/progress.json` | **只由脚本写** |
|
|
13
13
|
| 每个任务的过程正文 | `ledger/worklog/<年月>/<日>-<时分>-<说明>-<随机码>.md` | **建档只由脚本按模板做**,之后正文 **agent 直接编辑** |
|
|
14
|
-
| 已结案任务,一行一条(
|
|
14
|
+
| 已结案任务,一行一条(9 列:结案时间 / 创建时间 / 工作包 / 分类 / 标签 / owner / creator / 摘要 / 过程文档) | `ledger/history/<年月>.md`(按**结案时间**分月;存量 `ledger/PROGRESS-HISTORY.md` 只读兼容、永不重写) | **只由脚本写**;查询走 `history` 子命令 |
|
|
15
15
|
|
|
16
16
|
覆盖的动作:建任务、认领、交接、改状态、结案、查在办、查历史、体检。
|
|
17
17
|
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
|
|
103
103
|
### 只能改自己的任务
|
|
104
104
|
|
|
105
|
-
`set` 和 `
|
|
105
|
+
`set`、`close` 和 `log` 都先取身份,再校验「这个任务的 owner 是不是你」:**不是就拒绝**;任务还没人认领(`open`)也拒绝,提示先 `claim`。要接手就走 `set --owner` 交接 —— 一次显式动作。
|
|
106
106
|
|
|
107
107
|
理由有两层:一是别人替你结案,你会失去对进度的掌控;二是如果只取了身份却不校验归属,`owner` 这个字段就只是个装饰品。
|
|
108
108
|
|
|
@@ -199,7 +199,7 @@ stateDiagram-v2
|
|
|
199
199
|
|
|
200
200
|
- `done` **只能由 `close` 产生**;`set --status done` 会被拒绝
|
|
201
201
|
- **退回未认领**:owner 用 `set --status open` 把任务退回去,owner 清空、之后别人可以重新 `claim`;这条不能与 `--owner` 同时给
|
|
202
|
-
- `set --owner <某人>` 是**交接**,由当前 owner 执行,执行后 owner
|
|
202
|
+
- `set --owner <某人>` 是**交接**,由当前 owner 执行,执行后 owner 换成那个人。**该能力只为将来的 UI 保留**:SKILL.md 不向 agent 暴露它,换人一律走「释放 → 认领」,避免随便编一个名字挂上去
|
|
203
203
|
- 状态表里不允许残留 `done`(`validate` 会报)
|
|
204
204
|
|
|
205
205
|
### 命令一览
|
|
@@ -209,11 +209,13 @@ stateDiagram-v2
|
|
|
209
209
|
| `init` | 建状态表 | 否 | 否 |
|
|
210
210
|
| `new` | 建任务并建档 | **是**(记 creator) | 是 |
|
|
211
211
|
| `claim` | 认领待认领任务 | **是** | 是 |
|
|
212
|
-
| `set` | 改状态 / 交接 | **是**(且必须是该任务的 owner) | 是 |
|
|
212
|
+
| `set` | 改状态 / 交接 / 释放认领(`--status open`) | **是**(且必须是该任务的 owner) | 是 |
|
|
213
|
+
| `log` | 往 worklog「执行记录」补一条 | **是**(且必须是该任务的 owner) | 否(只回一行确认) |
|
|
213
214
|
| `close` | 结案归档 | **是**(且必须是该任务的 owner) | 否 |
|
|
214
215
|
| `list` | 查在办任务 | 仅 `--mine` | 否 |
|
|
215
216
|
| `history` | 查已结案任务(只读) | 仅 `--mine` | 否(只给过程文档链接) |
|
|
216
217
|
| `show` | 单任务详情 | 否 | 是 |
|
|
218
|
+
| `tags` | 分类/标签巡检(`--all` 只读)/ 归并(`--rename` 批量写) | 否 | 否 |
|
|
217
219
|
| `validate` | 校验一致性 | 否 | 否 |
|
|
218
220
|
|
|
219
221
|
参数细节看 `SKILL.md`,或直接跑 `<子命令> --help`。
|
|
@@ -223,6 +225,7 @@ stateDiagram-v2
|
|
|
223
225
|
| 命令 | 返回 |
|
|
224
226
|
|---|---|
|
|
225
227
|
| `new` / `claim` / `set` / `show` | 状态行 + 该任务过程文档的**路径与全文** |
|
|
228
|
+
| `log` | 一行确认(记了什么) |
|
|
226
229
|
| `close` | 结案结果与摘要 |
|
|
227
230
|
| `list` | 在办任务列表(不含正文,避免撑爆上下文) |
|
|
228
231
|
| `history` | 已结案紧凑列表(默认不含摘要,避免撑爆上下文) |
|
|
@@ -247,3 +250,9 @@ stateDiagram-v2
|
|
|
247
250
|
|
|
248
251
|
1. 本 skill 位于工作区 `_Skills/task-ledger/`;是否安装到全局 skill 目录由使用者决定 —— 未安装时其它项目不会自动触发。
|
|
249
252
|
2. `scripts/progress.py` 里的 `FALLBACK_TEMPLATE` 是**无注释的最小骨架**,只在 `assets/worklog.md` 读不到时启用 —— 两处注释多寡不同不是缺陷,**正例只放模板文件**。
|
|
253
|
+
|
|
254
|
+
## 五、维护者须知
|
|
255
|
+
|
|
256
|
+
- `SKILL.md` 的 frontmatter `version` 与 `package.json` 的 `version` 保持同值;发版时一起改,打 `skill-v<version>` tag。
|
|
257
|
+
- **`SKILL.md` 是每次会话整份注入的**:只放「不做就会写错数据」的规则与路由,细节进 `references/`(按需读,索引在 SKILL.md 末尾)。加体积前先自问「脚本或 `--help` 能不能兜住」。
|
|
258
|
+
- 改完跑 `cd packages/plugin && npm run verify`(build + typecheck + smoke);`copy-skill` 会把 `scripts/` `assets/` `references/` 一并拷进插件内嵌副本,不要直接改那份拷贝。
|
package/SKILL.md
CHANGED
|
@@ -1,179 +1,130 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-ledger
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
description_en: "Manage task progress: create, claim, hand over, update, close, query in-progress and closed history"
|
|
6
|
-
version: 1.0.0
|
|
3
|
+
description: 本地任务台账,跨会话记录在办任务的归属、进度与起止。当用户要登记一件新的事(新建任务 / 建个坑 / 这活我领了)、记录已有任务的进展(接着做 / 记一条进展 / 这轮先记下)、查看任务状态或历史(现在该做什么 / 这活谁在做 / 上周做过什么)时加载;对某个具体任务要求结案或退回时,只认用户的明确指令;只是改代码、讨论方案时不要用。
|
|
4
|
+
version: 1.2.2
|
|
7
5
|
allowed-tools: Read,Write,Bash,Grep
|
|
8
6
|
---
|
|
9
7
|
|
|
10
8
|
# task-ledger
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
台账只管三件事:**谁在做、做到哪、什么时候建 / 结**。状态只在 `progress.json`,叙事只在 worklog,**全部经脚本改**。
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|---|---|---|
|
|
16
|
-
| `ledger/progress.json` | 在办任务的状态:任务号 / 标题 / 创建人 / owner / 状态 / 时间 / **分类(`category`)与标签(`tags`)** / 过程文档路径(`worklog` 字段) | **只由脚本写** |
|
|
17
|
-
| `ledger/worklog/<年月>/<日>-<时分>-<说明>-<随机码>.md` | 该任务的过程正文,固定六节:背景 / 待办 / 下一步 / 过程 / 结论 + **执行记录**(末节,脚本维护、禁手改) | **建档只由脚本按模板做**,之后正文(前五节)由 agent 直接编辑 |
|
|
18
|
-
| `ledger/history/<年月>.md` | 已结案任务,一行一条(8 列:结案时间 / 创建时间 / 工作包 / 分类 / 标签 / **owner** / 摘要 / 过程文档);按**结案时间**分月。存量 `ledger/PROGRESS-HISTORY.md` 只读兼容、永不重写 | **只由脚本写**;查询走 `history` 子命令 |
|
|
12
|
+
## 三个文件
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
| 文件 | 装什么 |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `ledger/progress.json` | 在办任务:标题 / owner / 状态 / 时间(`created` `started` `updated` `finished`)/ 分类标签 / 过程文档路径。**只由脚本写** |
|
|
17
|
+
| `ledger/worklog/…md` | 任务正文,六节:背景 / 待办 / 下一步 / 过程 / 结论 / **执行记录**(末节) |
|
|
18
|
+
| `ledger/history/<年月>.md` | 已结案,一行一条。**只由脚本写** |
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
前五节你直接编辑;**末节「执行记录」只由脚本追加,一个字都不许手写**。
|
|
21
|
+
不另建副本、不手改状态表和历史、不自己拼 worklog 文件名(`new` 会建好并给路径)。
|
|
22
|
+
**台账 ≠ 产出物**:成果按所在项目自己的约定落盘,台账只放「建/做/结」和指向成果的链接。
|
|
27
23
|
|
|
28
24
|
## 什么时候用
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- 「现在该做什么」「我还有什么没做完」「谁在做这个」
|
|
33
|
-
- 「新建一个任务」「我要做 X」
|
|
34
|
-
- 「这活我领了」「这个我来做」
|
|
35
|
-
- 「卡住了」「先放一放」「转给某人来做」
|
|
36
|
-
- 「这活做完了」「结案」
|
|
37
|
-
- 「某件老活是什么时候做的」
|
|
38
|
-
- 「谁改过什么」「拉某人的工作日志」
|
|
39
|
-
- 在已有 `ledger/progress.json` 的项目里开工之前,先查一眼在办任务
|
|
40
|
-
|
|
41
|
-
❌ 不该用:
|
|
26
|
+
❌ 项目没有 `ledger/` 且只是临时一次性的事 → 不要自动 `init`,先问。
|
|
27
|
+
❌ 只想改某任务正文 → 用 `show` 拿路径与全文直接改,不要另建 md;已结案的用 `history` 找链接。
|
|
42
28
|
|
|
43
|
-
|
|
44
|
-
- 只想改某个任务的过程正文 → 那是编辑 Markdown:`show` 会把该文档**全文和路径一起**给你,直接在它上面改(文档已由脚本建好,不要另建一个)。**已结案**任务的过程文档别用 `show` 找(它可能已不在状态表)—— 用 `history` 拿到文档链接再读
|
|
29
|
+
## 意图 → 命令
|
|
45
30
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
|
49
|
-
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
| 「卡住了」「先放一放」 |
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
31
|
+
| 用户说 | 动作 |
|
|
32
|
+
|---|---|
|
|
33
|
+
| 「现在该做什么」「我还有啥没做完」 | `list --mine` |
|
|
34
|
+
| 「谁在做 X」「有哪些在办」 | `list`;在等认领的加 `--status open` |
|
|
35
|
+
| 「这个任务到哪一步了」「这轮做了什么」 | `show --id`(任务 JSON + worklog 全文) |
|
|
36
|
+
| 「某件老活什么时候做的」「谁做过哪些活」 | `history`(可按 `--owner` / `--since` 筛) |
|
|
37
|
+
| 「哪些任务停太久」 | `list --json`:`updated` 满 3 天=停滞、`started` 满 7 天=阻塞(看板算,别改状态) |
|
|
38
|
+
| 「新建一个任务」 | `new`(`--self` = 建完即认领) |
|
|
39
|
+
| 「这活我领了」 | `claim`(只对 `open` 有效) |
|
|
40
|
+
| 「开始做 / 接着做 X」 | 还是 `open` 就先 `claim`;已是 `doing` 就直接改正文 + `log` |
|
|
41
|
+
| 「继续做」「推进一下」 | 改「下一步 / 过程」,再 `log --note "本轮做了 X,下一步 Y"` |
|
|
42
|
+
| 「记一下这轮」「这段做完了」 | `log --id <任务号> --note "…"`(agent 可主动做) |
|
|
43
|
+
| 「卡住了」「先放一放」 | 写清卡在哪(不改状态),再 `log` |
|
|
44
|
+
| 「退回待认领」「让别人接」 | `set --status open`(记 `release`),回待认领 |
|
|
45
|
+
| 「转给某人」 | **skill 不换人**:你先释放,对方自己 `claim`;不许替用户写别人的名字 |
|
|
46
|
+
| 「彻底不做了」「取消这个任务」 | `close --summary "放弃:原因"`(需用户明说) |
|
|
47
|
+
| 「做完了」「验收通过」「结案」 | `close`(需用户明说,见红线) |
|
|
48
|
+
| 「把某任务过程补一下」 | `show --id` → 改前五节 → `log` |
|
|
49
|
+
| 项目还没有台账 / 状态表可疑 | `init`(先问)/ `validate` |
|
|
50
|
+
| 「标签太乱」「两个标签一个意思」 | `tags --all` 看频次 → `tags --rename 旧 新` |
|
|
64
51
|
|
|
65
52
|
## 命令怎么调
|
|
66
53
|
|
|
67
54
|
```bash
|
|
68
|
-
python3 <本 SKILL.md 所在目录>/scripts/progress.py <子命令> --repo <当前工作区>
|
|
55
|
+
python3 <本 SKILL.md 所在目录>/scripts/progress.py <子命令> --repo <当前工作区>
|
|
69
56
|
```
|
|
70
57
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
- **`--repo` 传当前工作区(项目根)**:脚本只知道自己在哪,不可能知道你在哪个项目里干活,这一步必须由调用方给出
|
|
75
|
-
- 参数细节用 `<子命令> --help` 查
|
|
58
|
+
子命令:`init` `new` `claim` `set` `log` `close` `list` `history` `show` `tags` `validate`。
|
|
59
|
+
参数细节一律看 `<子命令> --help`(不要凭记忆编参数)。
|
|
60
|
+
写类命令返回 worklog 路径 + 全文;`list` / `history` 只返回摘要,不吐正文。
|
|
76
61
|
|
|
77
|
-
|
|
78
|
-
|---|---|---|
|
|
79
|
-
| `init` | 建 `ledger/progress.json` | — |
|
|
80
|
-
| `new` | 新建任务,并自动建过程文档 | `--title`(必填)、`--id`(可选)、`--self`、`--created`(可选,补录创建时间)、`--category` / `--tags`(可选,分类 / 标签,见下节口径) |
|
|
81
|
-
| `claim` | 认领一个待认领任务 | `--id`(必填) |
|
|
82
|
-
| `set` | 改状态 / 换负责人 | `--id`(必填)、`--status`、`--owner` |
|
|
83
|
-
| `log` | 往 worklog 的「执行记录」节补一条 | `--id`(必填)、`--note`(必填,一句话) |
|
|
84
|
-
| `close` | 结案:移出状态 + 追加历史 + 封卷过程文档 | `--id`、`--summary`(都必填)、`--finished`(可选,结案时间)、`--category` / `--tags`(可选,结案时覆盖修正一次) |
|
|
85
|
-
| `list` | 查询在办任务 | `--mine`、`--owner`、`--status`、`--since`、`--until`、`--category`(精确)、`--tag`(包含)、`--json` |
|
|
86
|
-
| `history` | 查已结案任务(只读) | `--owner`、`--mine`、`--since`、`--until`、`--limit`、`--category`(精确)、`--tag`(包含)、`--json`;另:`--count-only`(只数行数、封顶 1 万输出 `{count, capped}`,显示级统计)、`--months N`(只读最近 N 个月文件,不含存量平铺文件) |
|
|
87
|
-
| `show` | 单任务详情 | `--id`(必填) |
|
|
88
|
-
| `tags` | 分类/标签巡检与归并 | `--all`(全量频次表)、`--rename 旧 新`(归并在办任务的同值) |
|
|
89
|
-
| `validate` | 校验状态表与过程文档是否一致 | — |
|
|
90
|
-
|
|
91
|
-
### 命令返回什么
|
|
92
|
-
|
|
93
|
-
| 命令 | 返回 |
|
|
94
|
-
|---|---|
|
|
95
|
-
| `new` / `claim` / `set` / `show` | 状态行 + **该任务过程文档的路径与全文** —— 拿到就能直接编辑,不用再去找文件、拼路径(`history` 是例外:只给链接不给全文) |
|
|
96
|
-
| `log` | 一行确认(记了什么) |
|
|
97
|
-
| `close` | 结案结果与摘要 |
|
|
98
|
-
| `list` | 在办任务列表(**不含**文档正文,避免撑爆上下文) |
|
|
99
|
-
| `history` | 已结案紧凑列表(结案时间 / 创建时间 / owner / 工作包 / 过程文档链接,行尾附所在历史文件),**默认不含摘要**;要摘要走 `--json` |
|
|
62
|
+
## 铁律
|
|
100
63
|
|
|
101
|
-
|
|
64
|
+
- **状态只有 `open` / `doing`**;`done` 只能由 `close` 产生。**没有 `blocked` 状态**:阻塞 = `started` 满 7 天、停滞 = `updated` 满 3 天,都由看板按时间算,`progress.json` 里不存、不手改;卡在哪写进正文。
|
|
65
|
+
- **`log` 就是刷新 `updated` 的动作**:该记不记,任务会被看板标成停滞。
|
|
66
|
+
- **owner = 当前 `git config user.name`**,不能由外部传入;读不到就报错(先让用户配 git)。**只能动自己名下**的任务(`open` 的先 `claim`),不是你的直接拒绝 —— 不要绕过脚本改 JSON。
|
|
67
|
+
- **换人只能「释放 → 认领」**:skill 不提供交接,随便写的名字都是假的。
|
|
68
|
+
- **「执行记录」禁手改**:只由脚本按 `new / claim / set / release / log / close` 追加,只增不改;手写=伪造时间线,且不刷新 `updated`。
|
|
69
|
+
- **改正文必配一条日志**:只要动了 worklog 的正文(改一句、补一节、改标题、修错字都算),**必须立刻跑一次 `log`**。没有对应日志的正文改动 = 这轮没做完 —— 时间线上会留下你改过、但没人知道为什么改的空洞。
|
|
70
|
+
- **升级前建的老 worklog 没有这一节**:不用你补,脚本第一次记时自动在文末补一节;文档丢失时 `log` 报错(`updated` 已刷新),用 `show` 查路径,**不要手写**。
|
|
71
|
+
- **旧数据里的 `blocked`**:读侧当进行中;`list --status blocked` 可捞出,用 `set --status doing` 归位。
|
|
102
72
|
|
|
103
|
-
|
|
104
|
-
**没有 `blocked` 状态**:阻塞由时间判定(接任务满 7 天仍未结案),看板自己算,不用也不能手动改;卡在哪里写进 worklog。旧数据里残留的 `blocked` 读侧当进行中处理(`list --status blocked` 可捞出来,用 `set --status doing` 归位)。
|
|
105
|
-
- **`new --self`** = 建完即认领(直接 `doing`);**不带 `--self`** = 空开,等别人 `claim`。
|
|
106
|
-
- **任务号自动生成**:创建时间(`年月日-时分`)+ 标题里的字母、数字、汉字 + 4 位随机码(如 `20261015-1430-登录接入-sso-7f3a`)。想指定就传 `--id`。
|
|
107
|
-
- **owner 取 `git config user.name`**:认领人**只能是当前 git 身份,不能由外部传入**;读不到就直接报错退出(提示「需要用户名才能执行」),不做任何兜底 —— 先让用户配好 git 身份。(`history` 只有 `--mine` 会取这个身份;`--owner <别人>` 是只读查询,不校验身份)
|
|
108
|
-
- **只能动自己名下的任务**:`set` 与 `close` 同样先取身份,再校验 `owner` 是不是你。**不是你的直接拒绝**;任务还是 `open`(没人认领)时也拒绝,提示先 `claim`。别人要动你的任务,必须你先交接(`set --owner`)。**`history` 是只读查询,不在此列** —— 查别人的已结案不需要对方交接。
|
|
73
|
+
细节见 `references/state-model.md`。
|
|
109
74
|
|
|
110
|
-
##
|
|
75
|
+
## 过程文档
|
|
111
76
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
- **怎么写**:格式随意、只要对 —— `2026-10-06`、`2026-10-06 14:30`、`2026-10-06 14:30:05` 都行,脚本补全到秒(没传秒补 `:00`,没传分秒补 `00:00`);传了但不对(如 `2026-13-40`)会被拒。
|
|
117
|
-
- **结案时间必须存在**:`close` 一定写(不传=当前)。
|
|
118
|
-
- **按时间筛**:`list` / `history` 都有 `--since`(起)/ `--until`(止),都按**创建时间**,可只给其一;只给日期时,起=当天 `00:00:00`、止=当天 `23:59:59`(含整天)。`history` 输出里**第一列是结案时间、第二列才是创建时间**,排序也按创建时间。
|
|
77
|
+
1. **建档**:`new` 按模板建六节骨架并把路径写进状态表。
|
|
78
|
+
2. **推进**:你直接编辑前五节,标题不许改名;**每改一轮正文就配一条日志**——同一次编辑动作里连改多处只记一条,改完立刻 `log --note "这轮做了什么"`。
|
|
79
|
+
3. **交付(待验收)**:任务仍留 `doing`,「待办」写「待用户验收」,「下一步」写清验收该看什么;这轮**照样要走收工三步**。结论只写可验证事实,评价等用户验收。
|
|
80
|
+
4. **封卷**:`close` 打封卷标记,此后不再改;文档靠 `history` 给的回链找回。
|
|
119
81
|
|
|
120
|
-
|
|
82
|
+
细节见 `references/worklog.md`。
|
|
121
83
|
|
|
122
|
-
|
|
123
|
-
2. **推进** —— 这个 md 由 **agent 直接编辑**(它是正文,不是状态数据,不走脚本)。六节(背景 / 待办 / 下一步 / 过程 / 结论 / 执行记录)**标题结构不能动**,且**末节「执行记录」由脚本维护、不许手改**:改完前五节内容后跑一次 `log --id <任务号> --note "这轮做了什么"`,脚本会按时间追加一行(`new` / `claim` / `set` / `close` 也会各自自动记一条)。记录格式固定 `- 时间 · 类型 · @谁 · 说明`,类型取 `new` / `claim` / `set` / `release`(`set --status open` 释放认领,单列)/ `log` / `close`;**只追加不改旧行**,移交后旧记录仍记在原负责人名下。**各写什么、写成什么样算对,模板注释里给了正例**,照它填即可。
|
|
124
|
-
3. **交付(待验收)** —— 活干完了但**用户还没验收**时,任务仍留在 `doing`:worklog 的「待办」写「待用户验收」,「下一步」写清验收该看什么(哪条命令、哪个文件)。**这一段不产出状态变化,只写正文。**
|
|
125
|
-
4. **封卷** —— 执行 `close` 时,脚本自动打封卷标记并把头部状态改为完成,此后不再修改。历史行按**结案时间**落 `ledger/history/<年月>.md`(存量 `ledger/PROGRESS-HISTORY.md` 只读、不再写入);封卷后要找回这篇文档:`history` 会给出它的链接与所在历史文件(只读、无需确认)。
|
|
84
|
+
## 每次收工必做(「收工」= 这一轮对用户有可见产出)
|
|
126
85
|
|
|
127
|
-
|
|
86
|
+
1. 改正文:这轮变化的事实都落笔,「下一步」写具体动作,不写「继续推进」。
|
|
87
|
+
2. 跑 `log`:**这一轮只要改过正文就必须记**(一轮至少一条);正文没变也能记一条推进,但要同时重写「下一步」。
|
|
88
|
+
3. 回读末行(`tail -n 3 <路径>` 或 `show --id`):时间 = 现在、说明 = 这轮的事。
|
|
128
89
|
|
|
129
|
-
|
|
90
|
+
交付前必须走完这三步;不走,这轮等于没发生,看板还会标停滞。
|
|
130
91
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
| `--tags`(1~5 个) | 这事**涉及什么**(对象 / 领域 / 模块,如 `镜像拉取`、`Hindsight`) | 至多 5 个;宁缺毋滥,**不凑数** | 下钻查询(包含匹配,容忍变体) |
|
|
92
|
+
**什么算一个节点**:明天你自己想不起来、或换个人接手会看不出的事,就记一条;一次状态/结论变化对应一条,不对应一次工具调用。
|
|
93
|
+
`--note` 一句一条、约 60 字、含命令 / `文件:行号` / 符号名 / 结论之一。
|
|
94
|
+
不记:读文件、跑 `list`、改错别字、依赖锁文件变更。
|
|
135
95
|
|
|
136
|
-
|
|
96
|
+
细节与正反例见 `references/log-note.md`。
|
|
137
97
|
|
|
138
|
-
|
|
139
|
-
2. **数量软约束**:3~5 个是目标不是硬指标 —— 设下限会逼出凑数标签,凑的正是噪声;脚本只卡上限
|
|
140
|
-
3. **统计与查询分工**:统计只认 category(精确匹配,同值才能比较);tags 只做查询(包含匹配,「bug」命中「bug修复」正是要的效果)
|
|
98
|
+
## 分类与标签
|
|
141
99
|
|
|
142
|
-
|
|
100
|
+
`new` 时自行总结:`--category` 答「是什么类型」(单值,≤4 字,吃不准写「其他」);`--tags` 答「涉及什么」(0~5 个,写不出就留空)。
|
|
101
|
+
口径错开:tags 不许写 category 的同义词。统计只认 category,查询用 tags(包含匹配)。
|
|
143
102
|
|
|
144
|
-
|
|
145
|
-
- 中文优先,不中英混排;纯英文 ≤3 个单词(`fix a bug` 可以,`fix a login bug` 超了)
|
|
146
|
-
- 标签之间用**逗号**分隔 —— 空格是英文多词标签自身的,不当分隔符(`--tags "fix a bug,docker"`)
|
|
147
|
-
- 正例:`--category 缺陷修复 --tags "镜像拉取,超时重试"`;反例:`--category 已完成登录修复`、`--tags 修 bug`
|
|
148
|
-
|
|
149
|
-
时机与修正:`new` 建档时一并总结(标题 + 背景语义最全);`close` 可用 `--category` / `--tags` 覆盖修正一次;日常漂移用 `tags --rename 旧 新` 归并(只改在办任务,已封卷文档不动)。看板侧先跑 `tags --all` 看全量频次与低频变体,再决定查什么、归并什么。已结案记录的分类/标签落在 history 行的「分类/标签」列(8 列结构,close 时从 task 终值写入)。
|
|
103
|
+
细节见 `references/taxonomy.md`。
|
|
150
104
|
|
|
151
105
|
## 写操作红线
|
|
152
106
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
107
|
+
| 命令 | 档位 | 要求 |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `init` / `new` / `claim` / `set` | 动手类 | 执行前把完整参数复述给用户并取得确认 |
|
|
110
|
+
| `log` | 免确认 | 本任务的推进 / 卡点 / 交付记录直接跑,跑完一句话交代「已记执行记录:…」;要替用户下结论、或替别人记,先问 |
|
|
111
|
+
| `close` | 独立授权 | 只认用户明确的验收 / 结案 / 放弃指令;**agent 自判「干完了」不算** —— 那是交付,停在 `doing` 等用户回话 |
|
|
112
|
+
| `tags --rename` | 批量写 | 先 `tags --all`,把影响条数与任务号报给用户,确认后再改 |
|
|
113
|
+
| `list` / `show` / `history` / `validate` / `tags --all` | 只读 | 直接跑 |
|
|
158
114
|
|
|
159
|
-
|
|
160
|
-
- **agent 自己判断「我干完了」不算触发条件** —— 那是交付,不是结案。交付后停在 `doing`,把做了什么、`--summary` 打算怎么写交给用户,**等用户回话**(这段时间 worklog 怎么记见下节)。
|
|
161
|
-
- 用户没点头就不许先斩后奏,也不许替用户下验收结论。**宁可任务停在 `doing`,也不要悄悄进历史。**
|
|
115
|
+
## 出错即停
|
|
162
116
|
|
|
163
|
-
|
|
117
|
+
非 0 退出就停手、原样报告,**不要绕过脚本手改 `progress.json` 或历史层**。
|
|
118
|
+
并发冲突(文件被改动)重跑一次即可,不要用 `git pull` / `rebase` 去「解决」。
|
|
164
119
|
|
|
165
|
-
|
|
120
|
+
细节见 `references/troubleshooting.md`。
|
|
166
121
|
|
|
167
|
-
|
|
122
|
+
## references(按需读,别全读)
|
|
168
123
|
|
|
169
|
-
|
|
|
124
|
+
| 何时读 | 文件 |
|
|
170
125
|
|---|---|
|
|
171
|
-
|
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
|
|
|
175
|
-
|
|
|
176
|
-
|
|
177
|
-
**报错就停下并原样报告,不要绕过脚本直接改 `ledger/progress.json` 或历史层(`ledger/history/<年月>.md`)。**
|
|
178
|
-
|
|
179
|
-
并发冲突(文件在操作期间被改动)会报错并中止 —— 重新执行一次即可,**不要用 `git pull` / `rebase` 去「解决」**。
|
|
126
|
+
| 要传 `--created` / `--finished` 补录时间、看到旧 `blocked`、答「停太久」要解释口径 | `references/state-model.md` |
|
|
127
|
+
| 填正文前、补老任务文档、`log` 报错找不到文档 | `references/worklog.md` |
|
|
128
|
+
| 拿不准一条记录够不够格、`--note` 怎么写 | `references/log-note.md` |
|
|
129
|
+
| 写分类/标签、用户说标签太乱要归并 | `references/taxonomy.md` |
|
|
130
|
+
| 任何非 0 退出、并发冲突、`validate` 报错 | `references/troubleshooting.md` |
|
package/assets/worklog.md
CHANGED
|
@@ -2,37 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
> **创建**:<created>(@<creator>)
|
|
4
4
|
|
|
5
|
-
<!-- 「> **分类**:… | **标签**:…」行由脚本按 new --category / --tags
|
|
6
|
-
两者皆空则不写此行。close 时可用 --category / --tags 覆盖修正。 -->
|
|
5
|
+
<!-- 「> **分类**:… | **标签**:…」行由脚本按 new --category / --tags 插入;两者皆空则不写。 -->
|
|
7
6
|
|
|
8
7
|
## 背景
|
|
9
8
|
|
|
10
|
-
<!--
|
|
11
|
-
例:用户说「导出的 Excel 中文列名乱码」(附原话 / 截图 / 报错) -->
|
|
9
|
+
<!-- 为什么做:触发它的原话 / 现象 / 链接 -->
|
|
12
10
|
|
|
13
11
|
## 待办
|
|
14
12
|
|
|
15
|
-
<!--
|
|
16
|
-
例:等宿主 1.2 才能复测流式接口;错误分支尚未测 -->
|
|
13
|
+
<!-- 还没做的、没验证的、等别人给东西的 -->
|
|
17
14
|
|
|
18
15
|
## 下一步
|
|
19
16
|
|
|
20
|
-
<!--
|
|
21
|
-
例:改 src/export.ts:88 的编码参数,然后跑一次冒烟 -->
|
|
17
|
+
<!-- 下一个具体动作(文件:行号 级别),不要写「继续推进」 -->
|
|
22
18
|
|
|
23
19
|
## 过程
|
|
24
20
|
|
|
25
|
-
<!--
|
|
26
|
-
例:rc4f2a1 的 src/host.ts:112 返回 null,是因为没等 ready 事件就发了请求 -->
|
|
21
|
+
<!-- 踩坑与证据:带 revision + 文件:行号 或符号名 -->
|
|
27
22
|
|
|
28
23
|
## 结论
|
|
29
24
|
|
|
30
|
-
<!--
|
|
31
|
-
例:已修复,但只覆盖 UTF-8;GBK 另开任务 -->
|
|
25
|
+
<!-- 做成了什么、留了什么坑 -->
|
|
32
26
|
|
|
33
27
|
## 执行记录
|
|
34
28
|
|
|
35
|
-
<!-- 本节由脚本维护:new / claim / set /
|
|
36
|
-
|
|
37
|
-
每条一行:时间 · 类型 · @谁 · 说明(类型取 new / claim / set / release / log / close);
|
|
38
|
-
只追加、不改旧行 —— 移交后旧记录仍留在原负责人名下。 -->
|
|
29
|
+
<!-- 本节由脚本维护:new / claim / set / release / log / close 自动追加,请勿手改。
|
|
30
|
+
补记用 progress.py log --id <任务号> --note "一句话"。 -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "task-ledger",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Task-ledger skill for coding agents: per-workspace progress tracking (ledger/progress.json, history, worklog) driven by a CLI script. Standalone install for CodeBuddy and other agents; also bundled inside the dsh-task-ledger DSH plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"skill",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"SKILL.md",
|
|
19
19
|
"README.md",
|
|
20
20
|
"scripts/",
|
|
21
|
-
"assets/"
|
|
21
|
+
"assets/",
|
|
22
|
+
"references/"
|
|
22
23
|
]
|
|
23
24
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# 执行记录:什么算一个节点
|
|
2
|
+
|
|
3
|
+
> TL;DR:一件事「明天你想不起来、换个人接手看不出」就记一条;一次状态/结论变化对应一条,不对应一次工具调用。`--note` 一句 60 字内,必须含具体对象。
|
|
4
|
+
|
|
5
|
+
## 判据
|
|
6
|
+
|
|
7
|
+
**明天你自己想不起来、或换个人接手会看不出** —— 就是一个节点,记一条。
|
|
8
|
+
一条 `log` 对应**一次状态变化或一次结论变化**,不对应一次工具调用。
|
|
9
|
+
|
|
10
|
+
## 该记
|
|
11
|
+
|
|
12
|
+
| 触发 | `--note` 写成什么 |
|
|
13
|
+
|---|---|
|
|
14
|
+
| 用户提了新要求 / 改了目标 | 新要求是什么,覆盖了哪条旧做法 |
|
|
15
|
+
| 方案变更 / 方案被排除 | 新方案(或排除了哪个)+ 为什么 |
|
|
16
|
+
| 改完一批文件 | 动了哪几个模块、验证没有 |
|
|
17
|
+
| 跑完验证(**通过或失败都算**) | 跑了什么、结果、下一步是否因此变 |
|
|
18
|
+
| 被卡住 / 停下 / 等外部 | 卡在哪一环、缺什么、等谁 |
|
|
19
|
+
| 拿到关键外部事实(版本 / 接口形状 / 已核实结论) | 结论 + 来源标识,免得下次重新查 |
|
|
20
|
+
| 交付(待验收) | 交付了什么、验收该看哪 |
|
|
21
|
+
| 释放 / 重新认领 | 脚本已自动记,别重复记 |
|
|
22
|
+
|
|
23
|
+
## 不该记
|
|
24
|
+
|
|
25
|
+
读文件、查命令、跑 `list`、想了一下;纯格式化 / 改错别字 / 依赖锁文件自动变更 —— 这些留在会话或 git 里。
|
|
26
|
+
|
|
27
|
+
## 写法
|
|
28
|
+
|
|
29
|
+
- 一句一条,`--note` 会被压成单行;**第一句说明白做了什么**,约 60 字以内,细节写正文对应小节。
|
|
30
|
+
- 一轮做了明显不相关的两件事 → 记两条,别拼成一条。
|
|
31
|
+
- 自检:一条记录至少能回答「动了什么」—— 含命令 / `文件:行号` / 符号名 / 结论之一。
|
|
32
|
+
|
|
33
|
+
正例:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
--note "把 home.service 的停滞口径改成 updated 满 3 天(home.service.ts:41-52)"
|
|
37
|
+
--note "验证通过:verify 25 项;下一步补 UI 的 overdue 标记"
|
|
38
|
+
--note "卡在远端鉴权,缺 deploy key,等用户给"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
反例:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
--note "继续推进" # 零信息量
|
|
45
|
+
--note "我改了代码,应该没问题了" # 无具体对象 + 替用户下结论
|
|
46
|
+
--note "改了 a.ts,又跑了测试,还回了消息" # 三件事挤一条
|
|
47
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# 状态与时间模型
|
|
2
|
+
|
|
3
|
+
> TL;DR:状态只有 `open` / `doing`;`done` 由 `close` 产生。阻塞 = `started` 满 7 天、停滞 = `updated` 满 3 天,看板算、不存字段。`updated` 由 `new/claim/set/log` 刷新。owner 只取当前 git 身份。
|
|
4
|
+
|
|
5
|
+
## 状态机
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
open ──claim──> doing ──close──> ledger/history(移出状态表)
|
|
9
|
+
doing ──set --status open──> open # 释放认领,执行记录类型 release
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
- `open`:已建、等认领。`doing`:已认领、在做。`done` 只由 `close` 产生。
|
|
13
|
+
- **没有 `blocked` 状态**(2026-10-19 取消)。旧数据里残留的 `blocked` 读侧当进行中:`list --status blocked` 可捞出,用 `set --status doing` 归位;新写入一律拒绝。
|
|
14
|
+
|
|
15
|
+
## 两个标记(看板计算,不是状态)
|
|
16
|
+
|
|
17
|
+
| 标记 | 依据 | 阈值 |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| 阻塞 | `started`(接任务)至今,中途更新不影响 | 满 7 天 |
|
|
20
|
+
| 停滞 | `updated`(最后推进)至今 | 满 3 天 |
|
|
21
|
+
|
|
22
|
+
- 真源:`packages/plugin/src/host/services/home.service.ts` 的 `OVERDUE_DAYS = 7` / `STALE_DAYS = 3`;看板随响应下发 `staleDays`,界面文案不硬编码。
|
|
23
|
+
- 脚本不算这两个值,`progress.json` 里也不存;agent 要回答「哪些停太久」时用 `list --json` 的 `updated` / `started` 与当前时间比。
|
|
24
|
+
- 老数据没有 `updated` 时,读侧回退到 `started`,再到 `created`。
|
|
25
|
+
|
|
26
|
+
## 时间
|
|
27
|
+
|
|
28
|
+
- **精度**:任务号、worklog 目录与文件名到分(`年月日-时分`);其余记录到秒(`YYYY-MM-DD HH:MM:SS`)。
|
|
29
|
+
- **默认不传**:`new` 创建、`claim` / `set` 推进、`log` 刷新 `updated`、`close` 结案,脚本都取当前时刻。
|
|
30
|
+
- **只在补录过去时间时传**:`new --created`、`close --finished`。格式 `YYYY-MM-DD[ HH:MM[:SS]]`,脚本补全到秒;非法值拒绝。
|
|
31
|
+
**`new --created` 补录时 `updated` 会一并等于该时间**,之后记得补一条 `log`,否则看板算它停滞。
|
|
32
|
+
- **筛选语义**:`list` / `history` 的 `--since` / `--until` 按**创建时间**;只给日期时,起 = 当天 `00:00:00`、止 = 当天 `23:59:59`(含整天)。
|
|
33
|
+
- **history 列序**:第一列结案时间、第二列创建时间;排序按创建时间。
|
|
34
|
+
|
|
35
|
+
## 任务号
|
|
36
|
+
|
|
37
|
+
`年月日-时分` + 标题里的字母/数字/汉字 + 4 位随机码(如 `20261015-1430-登录接入-sso-7f3a`)。要指定就传 `--id`(小写字母、数字、汉字、连字符)。
|
|
38
|
+
|
|
39
|
+
## 身份
|
|
40
|
+
|
|
41
|
+
- owner 恒取 `git config user.name`;读不到直接报错,**不做兜底**(先让用户配好 git)。
|
|
42
|
+
- 取身份的命令:`new`(记 creator)、`claim`、`set`、`close`、`log`、`list --mine`、`history --mine`。`history --owner <别人>` 是只读查询,不校验身份。
|
|
43
|
+
- `set` / `close` / `log` 都校验「owner 是不是你」;不是你的、或任务还没人认领,直接拒绝。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 分类与标签
|
|
2
|
+
|
|
3
|
+
> TL;DR:`category` 答「是什么类型」(单值,≤4 字,吃不准写「其他」);`tags` 答「涉及什么」(0~5 个,写不出就留空)。两者口径错开;统计只认 category,查询用 tags。
|
|
4
|
+
|
|
5
|
+
为什么不设枚举:本 skill 跨所有工作区(开发 / 运维 / 个人事务 / 调研备忘),固定分类覆盖不全。分类与标签由 agent 在 `new` 时按本节口径自行总结;脚本只校验形态(≤4 字 / 纯英文 ≤3 词 / ≤5 个),不校验语义。
|
|
6
|
+
|
|
7
|
+
## 两条边界
|
|
8
|
+
|
|
9
|
+
1. **口径错开**:tags 不许写 category 的同义词 —— `category=缺陷修复` 时,tags 别再写「bug修复」。
|
|
10
|
+
2. **统计与查询分工**:统计只认 category(精确匹配,同值才能比较);tags 只做查询(包含匹配,「bug」命中「bug修复」正是要的效果)。
|
|
11
|
+
3. **数量不设下限**:3~5 个是目标不是硬指标;设下限会逼出凑数标签。
|
|
12
|
+
|
|
13
|
+
## 写法口径
|
|
14
|
+
|
|
15
|
+
- 名词性短语,不带时态、不用动词收尾:写「缺陷修复」,不写「修复了」「修 bug」。
|
|
16
|
+
- 中文优先,不中英混排;纯英文 ≤3 个单词(`fix a bug` 可以,`fix a login bug` 超了)。
|
|
17
|
+
- 标签之间用**逗号**分隔;空格属于英文多词标签自身(`--tags "fix a bug,docker"`)。
|
|
18
|
+
|
|
19
|
+
正例:`--category 缺陷修复 --tags "镜像拉取,超时重试"`
|
|
20
|
+
反例:`--category 已完成登录修复`、`--tags 修 bug`
|
|
21
|
+
|
|
22
|
+
## 时机与修正
|
|
23
|
+
|
|
24
|
+
- `new` 建档时一并总结(标题 + 背景语义最全)。
|
|
25
|
+
- `close` 可用 `--category` / `--tags` 覆盖修正一次;终值写进 history 行的「分类 / 标签」列。
|
|
26
|
+
- 日常漂移:先 `tags --all` 看全量频次与低频变体,再 `tags --rename 旧 新` 归并(只改在办任务,已封卷文档不动;批量写,见写操作红线)。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 排错
|
|
2
|
+
|
|
3
|
+
> TL;DR:非 0 退出就停手、原样报告,别绕过脚本改 JSON。并发冲突重跑一次,不要用 `git pull` / `rebase` 去「解决」。
|
|
4
|
+
|
|
5
|
+
## 退出码
|
|
6
|
+
|
|
7
|
+
| 码 | 含义 | 处置 |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| 0 | 成功 | — |
|
|
10
|
+
| 1 | 业务错误(参数值 / 状态 / 权限不对) | 按提示纠正后重试;改不了的报告用户 |
|
|
11
|
+
| 2 | 命令行参数错误 | 看 `<子命令> --help` 重新拼参数 |
|
|
12
|
+
| 3 | 未预期的内部失败 | 上报,不要重试 |
|
|
13
|
+
| 130 | 被中断 | 重跑一次 |
|
|
14
|
+
|
|
15
|
+
## 常见错误
|
|
16
|
+
|
|
17
|
+
- **「需要用户名才能执行」**:`git config user.name` 没配。让用户配好,不要自拟名字。
|
|
18
|
+
- **「不是你的任务 / 先 claim」**:任务 owner 不是你或是 `open`。让别人接手只能走「你释放 → 对方 `claim`」;不要用别的名字绕过。
|
|
19
|
+
- **「状态不一致」**:对已在 `doing` 的任务又跑了 `claim`。直接改正文 + `log` 即可。
|
|
20
|
+
- **`log` 报「没写进过程文档」**:worklog 路径丢失 / 不可读。用 `show --id` 查路径;`progress.json` 的 `updated` 已刷新,不要手写「执行记录」。
|
|
21
|
+
- **「文件在操作期间被改动」**(并发指纹冲突):重新执行一次即可。
|
|
22
|
+
- **`validate` 报问题**:按行号读原文,先核对 `progress.json` 与 worklog 是否一致;能通过脚本修的走 `set` / `log`,**不要手改 JSON**。
|
|
23
|
+
|
|
24
|
+
## 硬约束
|
|
25
|
+
|
|
26
|
+
不要直接编辑 `ledger/progress.json`、`ledger/history/*.md`;不要另建 worklog;不要手写「执行记录」节。
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# 过程文档(worklog)
|
|
2
|
+
|
|
3
|
+
> TL;DR:六节固定;前五节 agent 改,末节「执行记录」只由脚本写。改完正文必须 `log`,交付也要 `log`。老文档缺末节时脚本自动补。
|
|
4
|
+
|
|
5
|
+
## 六节结构
|
|
6
|
+
|
|
7
|
+
| 节 | 写什么 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| 背景 | 为什么做:触发它的原话 / 现象 / 链接 |
|
|
10
|
+
| 待办 | 还没做的、没验证的、等别人给东西的 |
|
|
11
|
+
| 下一步 | 下一个**具体动作**(文件:行号 级别),不要写「继续推进」 |
|
|
12
|
+
| 过程 | 踩坑与证据:带 revision + `文件:行号` 或符号名 |
|
|
13
|
+
| 结论 | 做成了什么、留了什么坑;只写可验证事实,评价留给用户验收 |
|
|
14
|
+
| 执行记录 | 脚本维护,**禁手改** |
|
|
15
|
+
|
|
16
|
+
标题结构不能改名。建档只由 `new` 做(按 `assets/worklog.md` 模板生成骨架并写入状态表 `worklog` 字段)。
|
|
17
|
+
|
|
18
|
+
## 执行记录
|
|
19
|
+
|
|
20
|
+
- 一行一事件:`- 2026-10-19 12:08:33 · log · @GuoJia-Agent · 说明`。
|
|
21
|
+
- 类型:`new`(建)/ `claim`(认领)/ `set`(改状态、owner 变更)/ `release`(`set --status open` 释放)/ `log`(手记)/ `close`(结案)。
|
|
22
|
+
- **只追加、不改旧行**:`@谁` 记的是这次动手的人,不是任务现 owner —— 释放/重新认领后旧记录仍留在原负责人名下。
|
|
23
|
+
- 老 worklog 没有这一节:脚本第一次记时在文末自动补一节(正文不迁移),agent 不用也不许手动加。
|
|
24
|
+
- 过程文档丢失:`log` 报错退出(`updated` 已刷新),用 `show --id` 查路径,**不要手写这一节**。
|
|
25
|
+
|
|
26
|
+
## 编辑既有任务
|
|
27
|
+
|
|
28
|
+
1. `show --id` 拿任务 JSON + worklog 全文与路径;
|
|
29
|
+
2. 直接改前五节;
|
|
30
|
+
3. **立刻** `log --id <任务号> --note "补了…/改了…"`。
|
|
31
|
+
|
|
32
|
+
**改正文必配一条日志**:只要动过正文(哪怕一处错字、一个标题),就必须跟一条 `log`;没有日志的正文改动等于没发生过。同一次编辑动作里连改多处,只记一条。
|
|
33
|
+
|
|
34
|
+
已结案任务:worklog 已封卷、不在状态表,用 `history` 给出的回链找回,只读不改。
|
|
35
|
+
|
|
36
|
+
## 交付与封卷
|
|
37
|
+
|
|
38
|
+
- **交付(待验收)**:任务仍留 `doing`;「待办」写「待用户验收」,「下一步」写清验收看什么(哪条命令 / 哪个文件);按收工三步记一条 `log --note "已交付待验收:…"`。
|
|
39
|
+
- **封卷**:`close` 打封卷标记,此后不再修改;历史行按结案时间写入 `ledger/history/<年月>.md`(存量 `ledger/PROGRESS-HISTORY.md` 只读兼容,不再写入)。
|
package/scripts/progress.py
CHANGED
|
@@ -55,7 +55,7 @@ HISTORY_TITLE = "# 进度历史(已结案)"
|
|
|
55
55
|
# 但「谁建的」不变)。看板「新增(我的)= 我创建的」要它;旧 8 列无此列,
|
|
56
56
|
# upgrade_history / cmd_history 回链 worklog 头部「创建」行补(与 created 同一来源,不丢)。
|
|
57
57
|
HISTORY_HEADER = "| 结案时间 | 创建时间 | 工作包 | 分类 | 标签 | owner | creator | 完成了什么 | 过程文档 |"
|
|
58
|
-
HISTORY_SEP = "
|
|
58
|
+
HISTORY_SEP = "|---|---|---|---|---|---|---|---|---|"
|
|
59
59
|
FROZEN_MARK = "✅ 完成封卷"
|
|
60
60
|
ID_RE = re.compile(r"[a-z0-9\u4e00-\u9fff][a-z0-9\u4e00-\u9fff-]*\Z")
|
|
61
61
|
# 读侧兼容:秒可有可无(旧数据只到分)。写侧一律到秒,见 normalize_time。
|
|
@@ -1158,11 +1158,14 @@ def exec_line(when: str, who: str | None, kind: str, note: str) -> str:
|
|
|
1158
1158
|
|
|
1159
1159
|
|
|
1160
1160
|
def append_exec_log(text: str, line: str) -> str:
|
|
1161
|
-
"""
|
|
1161
|
+
"""把一条记录追加到「执行记录」节末尾。
|
|
1162
|
+
|
|
1163
|
+
升级前建的老 worklog 没有这一节:在文末补一节再写(不迁移正文,也不让记录静默丢掉)。
|
|
1164
|
+
"""
|
|
1162
1165
|
lines = text.splitlines()
|
|
1163
1166
|
at = next((i for i, ln in enumerate(lines) if ln.strip() == EXEC_HEAD), None)
|
|
1164
1167
|
if at is None:
|
|
1165
|
-
return text
|
|
1168
|
+
return text.rstrip() + f"\n\n{EXEC_HEAD}\n\n{EXEC_HINT}\n\n{line}\n"
|
|
1166
1169
|
end = next(
|
|
1167
1170
|
(i for i in range(at + 1, len(lines)) if lines[i].startswith("## ")), len(lines)
|
|
1168
1171
|
)
|
|
@@ -1175,23 +1178,25 @@ def append_exec_log(text: str, line: str) -> str:
|
|
|
1175
1178
|
|
|
1176
1179
|
def record_exec(
|
|
1177
1180
|
repo: Path, tid: str, task: dict[str, Any], who: str | None, kind: str, note: str
|
|
1178
|
-
) ->
|
|
1181
|
+
) -> bool:
|
|
1179
1182
|
"""给任务的过程文档补一条执行记录(`who` = 这次动手的人,不是任务现 owner)。
|
|
1180
1183
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1184
|
+
返回是否真的落盘;`log` 用它判断要不要报错。调用方必须已经持有 progress_lock ——
|
|
1185
|
+
与 close 的封卷(读全文→改写→落盘)互斥,否则两条记录并发追加会互相覆盖。
|
|
1183
1186
|
"""
|
|
1184
1187
|
log = find_worklog(repo, tid, task)
|
|
1185
1188
|
if log is None:
|
|
1186
|
-
return
|
|
1189
|
+
return False
|
|
1187
1190
|
try:
|
|
1188
1191
|
text = log.read_text(encoding="utf-8")
|
|
1189
1192
|
except (OSError, UnicodeDecodeError):
|
|
1190
|
-
return
|
|
1193
|
+
return False
|
|
1191
1194
|
line = exec_line(now(), who, kind, note)
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
+
try:
|
|
1196
|
+
write_text_atomic(log, append_exec_log(text, line))
|
|
1197
|
+
except OSError:
|
|
1198
|
+
return False
|
|
1199
|
+
return True
|
|
1195
1200
|
|
|
1196
1201
|
|
|
1197
1202
|
def write_worklog(repo: Path, tid: str, task: dict[str, Any]) -> Path:
|
|
@@ -1423,7 +1428,12 @@ def cmd_log(args: argparse.Namespace) -> None:
|
|
|
1423
1428
|
require_owner(task, tid, me)
|
|
1424
1429
|
task["updated"] = now()
|
|
1425
1430
|
commit_guarded(path, before, data)
|
|
1426
|
-
record_exec(repo, tid, task, me, "log", note)
|
|
1431
|
+
written = record_exec(repo, tid, task, me, "log", note)
|
|
1432
|
+
if not written:
|
|
1433
|
+
raise Fail(
|
|
1434
|
+
f"没写进 {tid} 的过程文档(文件不存在或不可读);progress.json 的 updated 已刷新。"
|
|
1435
|
+
"先用 show --id 确认 worklog 路径,不要手写「执行记录」。"
|
|
1436
|
+
)
|
|
1427
1437
|
print(f"已记入 {tid} 的执行记录:{note}")
|
|
1428
1438
|
|
|
1429
1439
|
|
|
@@ -2099,7 +2109,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
2099
2109
|
p = sub.add_parser("set", help="改状态 / 交接(结案请用 close)")
|
|
2100
2110
|
p.add_argument("--id", required=True)
|
|
2101
2111
|
p.add_argument("--status", help=f"{' / '.join(STATUSES)}(done 请走 close)")
|
|
2102
|
-
p.add_argument("--owner", help="
|
|
2112
|
+
p.add_argument("--owner", help="交接给谁(仅供 UI / 维护者;agent 提示词不暴露)")
|
|
2103
2113
|
add_repo(p)
|
|
2104
2114
|
p.set_defaults(func=cmd_set)
|
|
2105
2115
|
|