task-ledger 1.3.0 → 1.3.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 +29 -247
- package/SKILL.md +173 -88
- package/package.json +22 -22
- package/references/log-note.md +3 -1
- package/references/state-model.md +29 -27
- package/references/troubleshooting.md +97 -32
- package/scripts/ledgerkit/__init__.py +0 -0
- package/scripts/ledgerkit/actions/__init__.py +0 -0
- package/scripts/ledgerkit/actions/atom.py +154 -0
- package/scripts/ledgerkit/actions/bootstrap.py +26 -0
- package/scripts/ledgerkit/actions/claim.py +82 -0
- package/scripts/ledgerkit/actions/close_task.py +180 -0
- package/scripts/ledgerkit/actions/guard.py +136 -0
- package/scripts/ledgerkit/actions/handoff.py +74 -0
- package/scripts/ledgerkit/actions/list_tasks.py +53 -0
- package/scripts/ledgerkit/actions/log_progress.py +60 -0
- package/scripts/ledgerkit/actions/new_task.py +120 -0
- package/scripts/ledgerkit/actions/query.py +33 -0
- package/scripts/ledgerkit/actions/query_history.py +172 -0
- package/scripts/ledgerkit/actions/registry.py +82 -0
- package/scripts/ledgerkit/actions/release.py +51 -0
- package/scripts/ledgerkit/actions/result.py +88 -0
- package/scripts/ledgerkit/actions/set_task.py +43 -0
- package/scripts/ledgerkit/actions/show_task.py +27 -0
- package/scripts/ledgerkit/actions/validate.py +224 -0
- package/scripts/ledgerkit/core/__init__.py +0 -0
- package/scripts/ledgerkit/core/history_md.py +350 -0
- package/scripts/ledgerkit/core/identity.py +27 -0
- package/scripts/ledgerkit/core/ids.py +58 -0
- package/scripts/ledgerkit/core/labels.py +79 -0
- package/scripts/ledgerkit/core/paths.py +93 -0
- package/scripts/ledgerkit/core/time.py +102 -0
- package/scripts/ledgerkit/core/worklog_md.py +232 -0
- package/scripts/ledgerkit/env.py +93 -0
- package/scripts/ledgerkit/errors.py +15 -0
- package/scripts/ledgerkit/notices.py +28 -0
- package/scripts/ledgerkit/shell/__init__.py +0 -0
- package/scripts/ledgerkit/shell/cli.py +259 -0
- package/scripts/ledgerkit/shell/gitops.py +655 -0
- package/scripts/ledgerkit/shell/merge.py +266 -0
- package/scripts/ledgerkit/shell/presync.py +23 -0
- package/scripts/ledgerkit/shell/render.py +165 -0
- package/scripts/ledgerkit/shell/runner.py +225 -0
- package/scripts/ledgerkit/store/__init__.py +0 -0
- package/scripts/ledgerkit/store/atomic.py +130 -0
- package/scripts/ledgerkit/store/dirty.py +108 -0
- package/scripts/ledgerkit/store/history_store.py +189 -0
- package/scripts/ledgerkit/store/json_store.py +166 -0
- package/scripts/ledgerkit/store/locks.py +64 -0
- package/scripts/ledgerkit/store/owners_index.py +114 -0
- package/scripts/ledgerkit/store/task_store.py +28 -0
- package/scripts/ledgerkit/store/worklog_store.py +168 -0
- package/scripts/progress.py +8 -3109
- package/references/taxonomy.md +0 -26
- package/references/worklog.md +0 -39
package/SKILL.md
CHANGED
|
@@ -1,134 +1,219 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-ledger
|
|
3
|
-
description: 本地任务台账,跨会话记录在办任务的归属、进度与起止。当用户要登记一件新的事(新建任务 / 建个坑 / 这活我领了)、记录已有任务的进展(接着做 / 记一条进展 / 这轮先记下)、查看任务状态或历史(现在该做什么 / 这活谁在做 /
|
|
4
|
-
version: 1.
|
|
5
|
-
allowed-tools: Read,
|
|
3
|
+
description: 本地任务台账,跨会话记录在办任务的归属、进度与起止。当用户要登记一件新的事(新建任务 / 建个坑 / 这活我领了)、记录已有任务的进展(接着做 / 记一条进展 / 这轮先记下)、查看任务状态或历史(现在该做什么 / 这活谁在做 / 上周做过什么)、给任务结案或退回(做完了 / 验收通过 / 不做了 / 退回待认领)、整理标签或检查台账一致性时加载;只是改代码、讨论方案时不要用。
|
|
4
|
+
version: 1.3.0
|
|
5
|
+
allowed-tools: Read,Edit,Bash,Grep
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# task-ledger
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
管一个工作区的任务进度:**谁在做、做到哪、什么时候建 / 结**。
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
- **数据落点与多人并行**:每个工作区下有一个 `ledger/` 目录,任务与进度以静态文件形式存放在里面。**多人协同必须有 git**;没有 git 只写本地,也能用。多人共用却没有 git,提醒用户。
|
|
13
|
+
- **任务状态**:`待认领(open)` = 建了还没人认领;`进行中(doing)` = 已认领、在做;`已结案` = 用户明确说结束后由 `close` 产生,此后只读。
|
|
14
|
+
- **操作方式**:台账的状态与归属只经命令改;唯一能手写的是过程文档前五节(见「手写边界」)。台账只记「建 / 做 / 结」和指向过程文档的链接;产出物本身按项目自己的约定落盘。
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
## 手写边界
|
|
17
|
+
|
|
18
|
+
- **唯一能手写的是任务的过程文档(worklog)前五节**(怎么写见「过程文档」节);末节「执行记录」由脚本维护,**禁止手写、禁止手工添加**。
|
|
19
|
+
- **其他所有文件一律不许手改**:修改 / 删除 / 任何操作都走命令;手改台账文件即数据损坏。
|
|
20
|
+
- 台账看着不对劲(任务凭空少了、状态怪、分片对不上)⇒ **不要动手修**:让用户跑 `validate`(要连老月份和正文一起看就跑 `validate --deep`),把清单交给用户。
|
|
21
|
+
|
|
22
|
+
## 命令参考
|
|
23
|
+
|
|
24
|
+
九个子命令,前五个是写命令(`new`/`claim`/`set`/`log`/`close`),后四个全是查询类(`list` / `show` / `history` / `validate`);何时用哪个见「任务生命周期」。参数语法看 `<子命令> --help`;下表说每个参数干什么、何时用。
|
|
25
|
+
|
|
26
|
+
### new — 建任务
|
|
27
|
+
|
|
28
|
+
| 参数 | 含义 |
|
|
15
29
|
|---|---|
|
|
16
|
-
| `
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
30
|
+
| `--title "…"` | 任务标题(必填)—— 写任务核心、一句话说清干啥;它用来生成任务号和过程文件名,建议 4~20 字 |
|
|
31
|
+
| `--id` | 自定义任务号(一般不传;只能用小写字母、数字、汉字和连字符) |
|
|
32
|
+
| `--created` | 给过去漏记的任务补建时,补录实际创建日期(`YYYY-MM-DD`) |
|
|
33
|
+
| `--self` | 建并认领:直接归自己名下、状态「进行中」。仅当用户明确说「并开始做 / 并执行」时才用(判定见生命周期第 2 条) |
|
|
34
|
+
| `--category` / `--tags` | 分类 / 标签,口径见本节末尾 |
|
|
19
35
|
|
|
20
|
-
|
|
21
|
-
不另建副本、不手改状态表和历史、不自己拼 worklog 文件名(`new` 会建好并给路径)。
|
|
22
|
-
**台账 ≠ 产出物**:成果按所在项目自己的约定落盘,台账只放「建/做/结」和指向成果的链接。
|
|
36
|
+
干什么:建任务、按模板建好过程文档。不加 `--self` = 只建,落公共池等认领;加 `--self` = 建并认领。
|
|
23
37
|
|
|
24
|
-
|
|
38
|
+
分类 / 标签口径(`new` 与 `close` 共用这组参数):`--category` 答「是什么类型」,单值,中文 ≤4 字 / 纯英文 ≤3 词,吃不准写「其他」;`--tags` 答「涉及什么」,0~5 个、逗号分隔,写不出就不传(传空串等于没传)。tags 不许写 category 的同义词;查询用 tags(包含匹配,见 `list --tag`)。名词性短语、中文优先。**在办任务的分类 / 标签一旦写下就改不了**,只有结案时用 `close --category` / `--tags` 写终值。正例:`--category 缺陷修复 --tags "镜像拉取,超时重试"`;反例:`--category 已完成登录修复`、`--tags 修 bug`。
|
|
25
39
|
|
|
26
|
-
|
|
27
|
-
❌ 只想改某任务正文 → 用 `show` 拿路径与全文直接改,不要另建 md;已结案的用 `history` 找链接。
|
|
40
|
+
举例:用户说「新建个任务:把发布流程走通」→ `new --title "把发布流程走通"`(只建,不认领);用户明确说「新建个任务并开始做」→ `new --title "把发布流程走通" --self`。
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
### claim — 认领
|
|
30
43
|
|
|
31
|
-
|
|
|
44
|
+
| 参数 | 含义 |
|
|
32
45
|
|---|---|
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
|
42
|
-
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
| `--id <任务号>` | 认领哪个(必填) |
|
|
47
|
+
|
|
48
|
+
干什么:把公共池里的任务认领到自己名下,状态变「进行中」。已经在别人名下的会拒绝;已在自己名下的会提示无需重复。
|
|
49
|
+
|
|
50
|
+
举例:用户说「这活我领了」→ `claim --id 20261023-1117-把发布流程走通-7f3a`。
|
|
51
|
+
|
|
52
|
+
### set — 释放任务(退回公共池)
|
|
53
|
+
|
|
54
|
+
| 参数 | 含义 |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `--id <任务号>` | 释放哪个(必填) |
|
|
57
|
+
| `--owner ""` | 固定传空串 —— 释放 |
|
|
58
|
+
| `--owner <别人>` | 把任务转交给对方(预留通道,**agent 不用**,见纪律) |
|
|
59
|
+
|
|
60
|
+
干什么:把任务放回公共池、状态回「待认领」,别人即可认领;没有单独的「改状态」入口。
|
|
61
|
+
|
|
62
|
+
举例:用户明确说「把这个任务退回去」→ `set --id <任务号> --owner ""`。
|
|
63
|
+
|
|
64
|
+
### log — 记一条进展
|
|
65
|
+
|
|
66
|
+
| 参数 | 含义 |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `--id <任务号>` | 哪条任务(必填)—— 只能给自己名下的任务记,不在名下会直接被拒 |
|
|
69
|
+
| `--note "…"` | 这条记录说什么(必填;一句话,含命令 / `文件:行号` / 符号名 / 结论之一) |
|
|
70
|
+
|
|
71
|
+
干什么:刷任务的最后进度时间 + 在过程文档「执行记录」节追加一行。改正文必配一条 log(见纪律)。
|
|
72
|
+
|
|
73
|
+
举例:一轮干完 → `log --id <任务号> --note "改了认领即 doing(claim.py:56);下一步同步文档"`。
|
|
74
|
+
|
|
75
|
+
### close — 结案
|
|
76
|
+
|
|
77
|
+
| 参数 | 含义 |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `--id <任务号>` | 结哪条(必填) |
|
|
80
|
+
| `--summary "…"` | 结案摘要(必填;放弃写「放弃:原因」) |
|
|
81
|
+
| `--finished` | 给漏记的旧任务补用时,补录实际结案时间(`YYYY-MM-DD[ HH:MM[:SS]]`) |
|
|
82
|
+
| `--category` / `--tags` | 覆盖分类 / 标签终值(写进历史行) |
|
|
83
|
+
|
|
84
|
+
干什么:结案并封卷过程文档、移出自己名下。**封卷后只读**(见生命周期第 8 条)。
|
|
85
|
+
|
|
86
|
+
举例:用户明确说「把这个任务结束掉」→ `close --id <任务号> --summary "发布流程走通,验证 25 项全过"`。
|
|
87
|
+
|
|
88
|
+
### list — 查在办
|
|
89
|
+
|
|
90
|
+
| 参数 | 含义 |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `--mine` | 只看自己名下的 |
|
|
93
|
+
| `--pool` | 只看公共池(没人认领的) |
|
|
94
|
+
| `--owner <邮箱>` | 看某个人的(精确匹配;邮箱在 `list --json` 里那个人名下的任务上能看到;没有 `me` 缩写) |
|
|
95
|
+
| `--status open\|doing` | 按状态筛(逗号分隔可多选;合法值只有 `open` / `doing`) |
|
|
96
|
+
| `--category` / `--tag` | 按分类(精确)/ 标签(包含)筛 |
|
|
97
|
+
| `--since` / `--until` | 按创建时间筛(只给日期含当天) |
|
|
98
|
+
| `--json` | 输出 JSON(`{任务号: 任务对象}`) |
|
|
99
|
+
|
|
100
|
+
干什么:合并公共池 + 各人名下的任务,列出在办。**默认就是全量**,没有 `--all` 参数;收窄用 `--mine` / `--pool`。
|
|
101
|
+
|
|
102
|
+
举例:「现在该做什么」→ `list --mine`;「有哪些没人认领的」→ `list --pool`。
|
|
103
|
+
|
|
104
|
+
### show — 看一条任务
|
|
105
|
+
|
|
106
|
+
| 参数 | 含义 |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `--id <任务号>` | 看哪条(必填;谁名下的都能看) |
|
|
109
|
+
| `--json` | 连过程文档全文一起给(人话模式只给路径) |
|
|
110
|
+
|
|
111
|
+
干什么:拿任务 JSON + 过程文档路径 / 全文。改既有任务正文前,先用它拿路径。
|
|
112
|
+
|
|
113
|
+
举例:「这个任务到哪一步了」→ `show --id <任务号> --json`。
|
|
114
|
+
|
|
115
|
+
### history — 查已结案
|
|
116
|
+
|
|
117
|
+
| 参数 | 含义 |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `--owner <邮箱>` / `--mine` | 按 owner 筛 |
|
|
120
|
+
| `--category` / `--tag` | 按分类 / 标签筛 |
|
|
121
|
+
| `--since` / `--until` | 按**结案时间**筛(只给日期含当天) |
|
|
122
|
+
| `--months N` | 最近 N 个自然月(与 `--since` / `--until` **互斥**,同传直接报错) |
|
|
123
|
+
| `--limit N` | 最近 N 条 |
|
|
124
|
+
| `--count-only` | 只输出 `{"count","capped"}`(与 `--json` 互斥) |
|
|
125
|
+
| `--json` | JSON 输出 |
|
|
126
|
+
|
|
127
|
+
干什么:按结案时间倒序排列,每条一行,只列结案时间、负责人、标题,其他都不在表格里;要摘要 / 分类 / 标签 / 完整时间加 `--json`。不给时间参数 = 最近 3 个自然月;最多 13 个月,超了直接报错。
|
|
128
|
+
|
|
129
|
+
举例:「上周做过什么」→ `history --since <上周一日期>`;「今年都结掉哪些」→ `history --months 12`(超过 13 个月要分段查)。
|
|
130
|
+
|
|
131
|
+
## 怎么调用
|
|
53
132
|
|
|
54
133
|
```bash
|
|
55
134
|
python3 <本 SKILL.md 所在目录>/scripts/progress.py <子命令> --repo <当前工作区>
|
|
56
135
|
```
|
|
57
136
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
137
|
+
- 定位项目:`--repo <目录>` 给了就用;不给就从当前目录逐级向上找第一个含 `ledger/` 的目录。
|
|
138
|
+
- `--no-sync`(放在子命令**前**):用户明确要求「先别同步」时才用;之后自己 `git add ledger && commit && push`。
|
|
139
|
+
- `--json` 只对只读命令(`list` / `show` / `history` / `validate`)有意义;写命令不接收 `--json`,传了是用法错。`--json` 里的时间字段是 UTC,人话输出是本地时间。
|
|
140
|
+
- 命令回执只用来确认生效;任务状态以 `show` / `list` 为准。
|
|
61
141
|
|
|
62
|
-
##
|
|
142
|
+
## 任务生命周期
|
|
63
143
|
|
|
64
|
-
|
|
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` 归位。
|
|
144
|
+
用户要「做某件事」时按这条线走。
|
|
72
145
|
|
|
73
|
-
|
|
146
|
+
1. **建(只建,不认领)—— 默认**:「新建一个任务」「新建个任务,我们来干 X」「新建个任务,我需要处理 Y」→ `new --title "…"`。落公共池、待认领。
|
|
147
|
+
2. **建并认领 —— 仅限明确说法**:用户明确说「新建一个任务**并开始做 / 并执行**」这类带着「现在就开始」的话 → `new --title "…" --self`。直接归自己名下、「进行中」。**除这种明确说法,其他一律按第 1 条只建** —— 别替用户决定他要开始做;拿不定,问一句。
|
|
148
|
+
3. **找已有的**:用户说「我们来做 X」→ 先 `list --mine` 找自己名下的,在做的直接接着做;没有 → `list --pool` 里找,找到先问用户:「X 还没认领,认领它吗?」→ 用户点头再 `claim`;哪儿都没有 → 按第 1/2 条的判定规则建。
|
|
149
|
+
4. **认领**:`claim --id <任务号>` —— 认到自己名下,状态即「进行中」。
|
|
150
|
+
5. **推进**:改 worklog 前五节 → 按「过程文档」节的收工三步记 `log`。卡住也 `log`(写清卡在哪,状态不动);「先放一放」同理 —— 是暂停,不是释放。
|
|
151
|
+
6. **交付待验收**:任务留「进行中」,「待办」写「待用户验收」,「下一步」写清验收看什么;照收工三步记一条 `log --note "已交付待验收:…"`。
|
|
152
|
+
7. **释放**:仅当用户明确说「退回去 / 释放掉」→ `set --id <任务号> --owner ""`。任务回公共池,别人可认领。
|
|
153
|
+
8. **结案**:仅当用户明确说「把这个任务结束掉 / close 掉」→ `close --id <任务号> --summary "…"`;说得含糊(「做完了」「验收通过」)先反问「是要结束这个任务吗?」。收尾顺序:**先补完正文 + 记 log,最后才 close** —— 关了就不能再写。
|
|
154
|
+
9. **查询**:在办 `list` / 单条 `show` / 已结案 `history`(默认只近 3 个自然月,更早的要 `--months` / `--since`)。
|
|
74
155
|
|
|
75
156
|
## 过程文档
|
|
76
157
|
|
|
77
|
-
|
|
78
|
-
2. **推进**:你直接编辑前五节,标题不许改名;**每改一轮正文就配一条日志**——同一次编辑动作里连改多处只记一条,改完立刻 `log --note "这轮做了什么"`。
|
|
79
|
-
3. **交付(待验收)**:任务仍留 `doing`,「待办」写「待用户验收」,「下一步」写清验收该看什么;这轮**照样要走收工三步**。结论只写可验证事实,评价等用户验收。
|
|
80
|
-
4. **封卷**:`close` 打封卷标记,此后不再改;文档靠 `history` 给的回链找回。
|
|
158
|
+
`new` 按模板建好六节骨架,路径由 `show` 给出;前五节是本 skill 唯一允许手写的内容。
|
|
81
159
|
|
|
82
|
-
|
|
160
|
+
| 节 | 写什么 |
|
|
161
|
+
|---|---|
|
|
162
|
+
| 背景 | 为什么做:触发它的原话 / 现象 / 链接 |
|
|
163
|
+
| 待办 | 还没做的、没验证的、等别人给东西的 |
|
|
164
|
+
| 下一步 | 下一个**具体动作**(文件:行号 级别),不写「继续推进」 |
|
|
165
|
+
| 过程 | 踩坑与证据:带 revision + `文件:行号` 或符号名 |
|
|
166
|
+
| 结论 | 做成了什么、留了什么坑;只写可验证事实,评价等用户验收 |
|
|
167
|
+
| 执行记录 | 脚本维护,**禁止手写**(见「手写边界」) |
|
|
83
168
|
|
|
84
|
-
|
|
169
|
+
规则:
|
|
85
170
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
171
|
+
- 「执行记录」节名一个字都别动;老文档缺这一节也不用补。
|
|
172
|
+
- 过程文档找不到时 `log` 只提示不失败;用 `show` 查路径,不要手写。
|
|
173
|
+
- 头部只有创建时间 / 创建人、封卷标记、分类 / 标签行 —— **状态与归属以台账数据为准,别从头部读**。
|
|
174
|
+
- 执行记录行格式 `- 本地时间 · 类型 · @谁 · 说明`,`@谁` 是这次动手的人、不是任务现归属;只追加、不改旧行。行首「类型」是脚本内部动作名(会见到 `release`,它就是 `set --owner ""`);认不出就别当成新命令,按 `--help` 查。
|
|
175
|
+
- 只改某条任务的正文:`show --id <任务号>` 拿路径直接改,不另建 md;已结案的用 `history --months 12`(或 `--since`)找回链接——默认只查近 3 个月,结案久了的要显式放大窗口;只读不改。
|
|
89
176
|
|
|
90
|
-
|
|
177
|
+
### 收工三步(「收工」= 这一轮对用户有可见产出)
|
|
91
178
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
179
|
+
1. 改正文:这轮变化的事实都落笔,「下一步」写具体动作。
|
|
180
|
+
2. 跑 `log`:这一轮只要改过正文就必须记(一轮至少一条;纪律见下文)。正文没变也能记一条推进,但要同时重写「下一步」。
|
|
181
|
+
3. 回读末行(`tail -n 3 <路径>`):说明 = 这轮的事。执行记录行的时间是本机本地时间,别以为没记上。
|
|
95
182
|
|
|
96
|
-
|
|
183
|
+
**什么算一个节点**:明天自己想不起来、或换个人接手会看不出的事,就记一条;一次状态 / 结论变化对应一条,不对应一次工具调用。拿不准够不够格、`--note` 不会写 → 见 `references/log-note.md`。
|
|
97
184
|
|
|
98
|
-
##
|
|
185
|
+
## 纪律
|
|
99
186
|
|
|
100
|
-
|
|
101
|
-
口径错开:tags 不许写 category 的同义词。统计只认 category,查询用 tags(包含匹配)。
|
|
187
|
+
### 数据完整性(脚本管不了的,违反了数据就脏)
|
|
102
188
|
|
|
103
|
-
|
|
189
|
+
- **执行记录禁手改**:只由脚本按 `new / claim / set / release / log / close` 追加,只增不改。
|
|
190
|
+
- **改正文必配一条日志**:动了 worklog 的正文(改一句、补一节、改标题、修错字都算)就必须立刻跑一次 `log`。
|
|
191
|
+
- **换人只能「释放 → 认领」**:`set --owner ""` 放回公共池,对方自己 `claim`;不许替别人挂名字。`set --owner <别人>`(预留转接通道,agent 一律不用)。
|
|
192
|
+
- **身份由脚本自取,agent 全程不传 owner**:查自己用 `--mine`,只有查别人才传对方邮箱(`list --owner <邮箱>`);释放传的是空串 `--owner ""`,不是身份。看到「读不到 git 身份」提示 ⇒ 让用户配 git,否则任务记到兜底身份名下。
|
|
104
193
|
|
|
105
|
-
|
|
194
|
+
### 人类授权(跑之前问不问)
|
|
195
|
+
|
|
196
|
+
项目没有 `ledger/` ⇒ 先问「要不要建个台账记这活?」,不许自建。用户同意 ⇒ 直接跑第一条写命令,且**必须带 `--repo <项目根>`**:不带时脚本只从当前目录逐级往上找第一个含 `ledger/` 的目录,一个都没有就退 1 报「找不到台账」,绝不就地建;台账由这条写命令顺带建出来,没有 `init` 命令。之后可以不带 `--repo`,但查找是**逐级往上**的 —— 在本项目的子目录里跑可能命中上层项目的台账,拿不准就一直带 `--repo <项目根>`。
|
|
106
197
|
|
|
107
198
|
| 命令 | 档位 | 要求 |
|
|
108
199
|
|---|---|---|
|
|
109
|
-
| `
|
|
110
|
-
| `log` | 免确认 | 本任务的推进 / 卡点 /
|
|
111
|
-
| `close` | 独立授权 |
|
|
112
|
-
| `
|
|
113
|
-
| `list` / `show` / `history` / `validate` / `tags --all` | 只读 | 直接跑 |
|
|
114
|
-
|
|
115
|
-
## 出错即停
|
|
200
|
+
| `new` / `claim` / `set` | 动手类 | 执行前把完整参数复述给用户并取得确认 |
|
|
201
|
+
| `log` | 免确认 | 本任务的推进 / 卡点 / 交付记录直接跑,跑完一句话交代「已记执行记录:…」;要替用户下结论,先问(任务不在自己名下会直接被拒) |
|
|
202
|
+
| `close` | 独立授权 | 仅认明确说「结束掉 / close 掉」(完整判定见生命周期第 8 条);说得含糊必须反问「是要结束这个任务吗?」;**agent 自判「干完了」不算** |
|
|
203
|
+
| `list` / `show` / `history` / `validate` | 只读 | 直接跑 |
|
|
116
204
|
|
|
117
|
-
|
|
118
|
-
**退出码 0 不等于没事**:写命令之后的同步(commit / push)失败仍返回 0,原因只写在输出里。写命令跑完必看输出,出现 `提示:` / `错误:` / `警告:` 就先用一句话说清「发生了什么 + 你要做什么」,再附原文关键行,按 `references/troubleshooting.md` 对应条目给步骤;纯告知类(如已用 `--no-verify` 提交)一句话带过。只读命令只有 `错误:` 才需要转述。
|
|
119
|
-
并发冲突(文件被改动)重跑一次即可,**台账同步一律交给脚本**,不要自己用 `git pull` / `rebase` 去「解决」;只有提示明确说脚本已回滚、或说它不替你 rebase 时,才让用户手动 `git pull --rebase` / `git merge` 后 `git push`,推完再重跑。
|
|
120
|
-
写前会**定向取最新**:只刷新 `ledger/progress.json` 与 `ledger/history/`,`worklog/` 里已有的正文一个字都不动;
|
|
121
|
-
有未推送的台账提交时**先自动补推再写**,不要让用户先去 push。只有补推失败、或本地有用户自己的非台账提交(脚本不替他推业务提交)时才中止;有未提交的台账改动、未入库的同名文件,同样中止 —— 按提示处理,或加 `--no-sync`(写在子命令前后都行)继续本地写。
|
|
122
|
-
同一仓库里写命令**排队**执行(最多等 60 秒),并发时不要重试轰炸,等前一个跑完再重跑。
|
|
205
|
+
### 故障处置(跑之后出事怎么办)
|
|
123
206
|
|
|
124
|
-
|
|
207
|
+
- **动作阶段失败(输出以 `错误:` 开头)= 该命令没生效**:不挡主任务 —— 继续手里的活,收尾时汇报「没记上,原因 …」;不绕过脚本手改文件。
|
|
208
|
+
- **退出码 0 也要看输出**:出现 `提示:` / `错误:` / `警告:` 就先用一句话说清「发生了什么 + 下一步做什么」,再按 `references/troubleshooting.md` 给步骤;纯告知类一句话带过。只读命令只有 `错误:` 才需要转述。
|
|
209
|
+
- **两类不是故障的退出码**:`validate` 查出问题时退出码 1,照实转述清单;提交阶段失败 ⇒ 文件已经写下去、只差进 git,让用户先提交再重跑,别说「没记上」。
|
|
210
|
+
- **并发冲突**(文件被改动、抢不到锁)重跑一次即可;台账同步一律交给脚本,不要自己 `git pull` / `rebase` 去「解决」(脚本明说不代劳的几种除外,见 troubleshooting)。
|
|
211
|
+
- 同一仓库里写命令排队执行,等前一个跑完再重跑。
|
|
125
212
|
|
|
126
213
|
## references(按需读,别全读)
|
|
127
214
|
|
|
128
215
|
| 何时读 | 文件 |
|
|
129
216
|
|---|---|
|
|
130
|
-
|
|
|
131
|
-
|
|
|
132
|
-
| 拿不准一条记录够不够格、`--note`
|
|
133
|
-
| 写分类/标签、用户说标签太乱要归并 | `references/taxonomy.md` |
|
|
134
|
-
| 任何非 0 退出、退出码 0 但有 `提示:` / `错误:`、并发冲突、`validate` 报错 | `references/troubleshooting.md` |
|
|
217
|
+
| 任何非 0 退出、退出码 0 但有 `提示:` / `错误:` / `警告:`、并发冲突、`validate` 报错 | `references/troubleshooting.md` |
|
|
218
|
+
| 传 `--created` / `--finished` 补录时间、看到旧 `blocked`、看 `--json` 里的时间字段、查别人时 owner 匹配异常、看 history 列义 / 时间窗口口径 / 旧格式行 | `references/state-model.md` |
|
|
219
|
+
| 拿不准一条记录够不够格、`--note` 不会写 | `references/log-note.md` |
|
package/package.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
2
|
+
"name": "task-ledger",
|
|
3
|
+
"version": "1.3.2",
|
|
4
|
+
"description": "Task-ledger skill for coding agents: per-workspace progress tracking (ledger/pool.json + owners/<hash>.json shards + owners.json index, history, worklog) driven by a CLI script. Standalone install for CodeBuddy and other agents; also bundled inside the dsh-task-ledger DSH plugin.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"skill",
|
|
7
|
+
"agent-skill",
|
|
8
|
+
"task-ledger",
|
|
9
|
+
"progress",
|
|
10
|
+
"todo"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/cq-guojia/dsh-task-ledger.git"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"SKILL.md",
|
|
19
|
+
"README.md",
|
|
20
|
+
"scripts/",
|
|
21
|
+
"assets/",
|
|
22
|
+
"references/"
|
|
23
|
+
]
|
|
24
24
|
}
|
package/references/log-note.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# 执行记录:什么算一个节点
|
|
2
2
|
|
|
3
3
|
> TL;DR:一件事「明天你想不起来、换个人接手看不出」就记一条;一次状态/结论变化对应一条,不对应一次工具调用。`--note` 一句 60 字内,必须含具体对象。
|
|
4
|
+
>
|
|
5
|
+
> 本节全部是 **agent 口径**:脚本只拒空值、折叠空白,**不校验长度、不校验内容** —— 别指望它帮你把关。
|
|
4
6
|
|
|
5
7
|
## 判据
|
|
6
8
|
|
|
@@ -33,7 +35,7 @@
|
|
|
33
35
|
正例:
|
|
34
36
|
|
|
35
37
|
```
|
|
36
|
-
--note "
|
|
38
|
+
--note "改了认领即 doing(claim.py:56)"
|
|
37
39
|
--note "验证通过:verify 25 项;下一步补 UI 的 overdue 标记"
|
|
38
40
|
--note "卡在远端鉴权,缺 deploy key,等用户给"
|
|
39
41
|
```
|
|
@@ -1,44 +1,46 @@
|
|
|
1
1
|
# 状态与时间模型
|
|
2
2
|
|
|
3
|
-
> TL;DR:状态只有 `open` / `doing`;`done` 由 `close`
|
|
3
|
+
> TL;DR:状态只有 `open` / `doing`;`done` 由 `close` 产生。认领即 `doing`(`claim` / `new --self` 都直接置)。`started` = 首次认领时间,释放不清、重新认领不刷新。`updated` 由 `new/claim/set/log` 刷新。身份由脚本自取,agent 不传 owner。
|
|
4
4
|
|
|
5
5
|
## 状态机
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
open
|
|
9
|
-
|
|
8
|
+
new → 公共池(open,没人认领)
|
|
9
|
+
new --self → 自己名下(doing,记 started)
|
|
10
|
+
公共池 ──claim──▶ 自己名下(doing;started 空则补 now)
|
|
11
|
+
set --owner "" → 公共池(open,没人认领;started 保留)
|
|
12
|
+
set --owner 别人 → 对方名下(预留转接通道,agent 不用)
|
|
13
|
+
close → 历史层 + 封卷 + 移出自己名下
|
|
10
14
|
```
|
|
11
15
|
|
|
12
|
-
- `
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
## 三个标记(看板计算,不是状态)
|
|
16
|
-
|
|
17
|
-
| 标记 | 依据 | 阈值 |
|
|
18
|
-
|---|---|---|
|
|
19
|
-
| 积压 | `created`(建了)至今仍 `open`(没人认领) | 满 30 天 |
|
|
20
|
-
| 逾期 | `started`(接任务)至今,中途更新不影响 | 满 14 天 |
|
|
21
|
-
| 停滞 | `updated`(最后推进)至今 | 满 3 天 |
|
|
22
|
-
|
|
23
|
-
- 真源:`packages/plugin/src/host/services/home.service.ts` 的 `BACKLOG_DAYS = 30` / `OVERDUE_DAYS = 14` / `STALE_DAYS = 3`;看板随响应下发三个天数,界面文案不硬编码。
|
|
24
|
-
- 脚本不算这三个值,`progress.json` 里也不存;agent 要回答「哪些停太久」时用 `list --json` 的 `created` / `updated` / `started` 与当前时间比。
|
|
25
|
-
- 老数据没有 `updated` 时,读侧回退到 `started`,再到 `created`。
|
|
16
|
+
- **`started` 是外卖计时器**:首次认领盖上之后,释放(`set --owner ""`)不清、重新认领不刷新 —— 逾期时钟从首次认领一口气跑到结案,转手不重置。防的是「眼看要超时,释放掉再认领回来洗时钟」;全链路没有重置 `started` 的命令(`claim` 的 `or now()` 只在它为空时才盖值;`set` 原样保留)。接手一个已超时的任务,一接单即逾期:单子已经迟了,谁端着谁负责;责任归属看执行记录流水(谁认领 / 谁释放逐笔有记录),计时器只回答「这单迟没迟」。
|
|
17
|
+
- 旧数据里的 `blocked`:读侧按 `doing` 算 —— `list --status doing` 能捞出,`--status blocked` 反而一条都匹配不到;没有归位命令,也不需要(只是读数)。
|
|
18
|
+
- 认领 / 释放 / 交接一律先写目标、再删原处,崩在中间会同一任务号短暂出现在两处 —— 重跑一次同一条命令即幂等收敛(`already_done`),或按 `validate` 的提示删掉多余那份。
|
|
26
19
|
|
|
27
20
|
## 时间
|
|
28
21
|
|
|
29
|
-
- **精度**:任务号、worklog
|
|
30
|
-
- **默认不传**:`new`
|
|
31
|
-
- **只在补录过去时间时传**:`new --created`、`close --finished`。格式 `YYYY-MM-DD[ HH:MM[:SS]]
|
|
32
|
-
|
|
33
|
-
- **筛选语义**:`list`
|
|
34
|
-
-
|
|
22
|
+
- **精度**:任务号、worklog 目录与文件名到分(`年月日-时分` / `YYYYMM`);其余记录到秒(`YYYY-MM-DD HH:MM:SS`)。
|
|
23
|
+
- **默认不传**:`new` / `claim` / `set` / `log` / `close` 都取当前时刻。
|
|
24
|
+
- **只在补录过去时间时传**:`new --created`、`close --finished`。格式 `YYYY-MM-DD[ HH:MM[:SS]]`,按本地墙钟给、脚本内部转 UTC。`new --created` 补录时 `updated` 一并等于该时间 —— 之后补一条 `log` 把 `updated` 刷回当前。
|
|
25
|
+
- 注意:任务号前缀与 worklog 月份目录按 **UTC** 推 —— UTC+8 下裸日期 `--created 2026-01-05` 存成 `2026-01-04 16:00:00`,任务号前缀变成 `20260104-1600`;临午夜补录要连时间一起传。
|
|
26
|
+
- **筛选语义**:`list` 的 `--since` / `--until` 按**创建时间**;`history` 的按**结案时间**(历史文件按结案月归档,按创建时间比较会漏「上月建、本月结」的记录)。只给日期时起 = 当天 `00:00:00`、止 = 当天 `23:59:59`(含当天)。
|
|
27
|
+
- **时区**:存盘为 UTC 的只有 —— 任务号、worklog 目录 / 文件名、台账 JSON 的 `created`/`started`/`updated`/`finished`、history 行、worklog 头部「创建」行。**执行记录行、封卷行、`list` / `history` 的人话输出都是本机本地时间**(给人看的日志行);`--json` 原样给 UTC,由消费方自己转。存量老数据(2026-10-22 前)写的是写入者本地时间、无标记,无法与 UTC 区分。
|
|
28
|
+
- **history 文件 9 列**:结案时间 / 创建时间 / 工作包(= `new --title` 的任务标题)/ 分类 / 标签 / owner / creator / 摘要 / 过程文档;排序与 `--since` / `--until` 按**结案时间**。(`history` 命令的人话输出只展示其中几列:结案时间、负责人、标题。)
|
|
35
29
|
|
|
36
30
|
## 任务号
|
|
37
31
|
|
|
38
|
-
`年月日-时分` +
|
|
32
|
+
`年月日-时分` + 标题里的字母 / 数字 / 汉字 + 4 位随机码(如 `20261015-1430-登录接入-sso-7f3a`)。随机码必须保留:任务号在**公共池、我自己的分片**两处查重(并发安全闸门),并直接判**过程文档路径** `worklog/<创建月>/<去前缀名>.md` 是否已存在 —— 在办、已结案任务的文档都留在磁盘上,命中即号被占过(复用会撞同一篇文档、日后让 `close` 误判 `already_done` 变僵尸)。O(1),不必扫历史。想自己指定就传 `--id`(小写字母、数字、汉字、连字符)。
|
|
39
33
|
|
|
40
34
|
## 身份
|
|
41
35
|
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
- `
|
|
36
|
+
- 主键 = **git 邮箱**(`git var GIT_COMMITTER_IDENT` 里的 email,退回 `git config user.email`),归一化(去空白 + 小写)后比对。
|
|
37
|
+
- 读不到邮箱**不报错**:走兜底链(`USER`/`LOGNAME` → `getpass` → 主机名 → 字面 `default`)并出一条提示,命令照常跑完。看到提示要告诉用户配好 git,否则任务记到兜底身份名下。
|
|
38
|
+
- 全站只认 git 邮箱这一个身份键;`list --owner` / `history --owner` 是归一化后的**精确匹配**,没有 `me` 缩写,「自己」用 `--mine`。
|
|
39
|
+
- `close` / `log` 只对自己名下的任务生效,不在名下直接拒绝;`set --owner ""` 对已在公共池里的任务是幂等空转(退 0);`set --owner <自己>` 会把公共池里的任务认领到自己名下。
|
|
40
|
+
|
|
41
|
+
## 历史层
|
|
42
|
+
|
|
43
|
+
- 按**结案时间**分月存放,9 列(creator 在 owner 之后);`close` 从任务直写分类 / 标签终值。
|
|
44
|
+
- 存量平铺历史文件只读兼容、永不重写;`history` 连同它在内、按下面的月份区间合并。
|
|
45
|
+
- **查询区间**:`history` 先由时间参数算出要读的月份文件,再逐个「存在才读、缺月跳过」,不扫磁盘。无时间参数默认最近 3 个自然月;`--months N`(近 N 月)与 `--since/--until`(结案时间闭区间)二选一;一次最多读 13 个历史文件(按月分文件,不区分连续/分散,只数总数),超出直接报错、不读任何文件。末列文档链接只按**文件名**消费(取 basename),链接里的 `../worklog/<年月>/` 前缀只为阅读器跳转服务,解析时忽略。
|
|
46
|
+
- `history --json` 直接按文件现状解析,旧行没有的列不编造;`close` 追加历史行时才会把旧行升级补上 creator。
|