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.
Files changed (55) hide show
  1. package/README.md +29 -247
  2. package/SKILL.md +173 -88
  3. package/package.json +22 -22
  4. package/references/log-note.md +3 -1
  5. package/references/state-model.md +29 -27
  6. package/references/troubleshooting.md +97 -32
  7. package/scripts/ledgerkit/__init__.py +0 -0
  8. package/scripts/ledgerkit/actions/__init__.py +0 -0
  9. package/scripts/ledgerkit/actions/atom.py +154 -0
  10. package/scripts/ledgerkit/actions/bootstrap.py +26 -0
  11. package/scripts/ledgerkit/actions/claim.py +82 -0
  12. package/scripts/ledgerkit/actions/close_task.py +180 -0
  13. package/scripts/ledgerkit/actions/guard.py +136 -0
  14. package/scripts/ledgerkit/actions/handoff.py +74 -0
  15. package/scripts/ledgerkit/actions/list_tasks.py +53 -0
  16. package/scripts/ledgerkit/actions/log_progress.py +60 -0
  17. package/scripts/ledgerkit/actions/new_task.py +120 -0
  18. package/scripts/ledgerkit/actions/query.py +33 -0
  19. package/scripts/ledgerkit/actions/query_history.py +172 -0
  20. package/scripts/ledgerkit/actions/registry.py +82 -0
  21. package/scripts/ledgerkit/actions/release.py +51 -0
  22. package/scripts/ledgerkit/actions/result.py +88 -0
  23. package/scripts/ledgerkit/actions/set_task.py +43 -0
  24. package/scripts/ledgerkit/actions/show_task.py +27 -0
  25. package/scripts/ledgerkit/actions/validate.py +224 -0
  26. package/scripts/ledgerkit/core/__init__.py +0 -0
  27. package/scripts/ledgerkit/core/history_md.py +350 -0
  28. package/scripts/ledgerkit/core/identity.py +27 -0
  29. package/scripts/ledgerkit/core/ids.py +58 -0
  30. package/scripts/ledgerkit/core/labels.py +79 -0
  31. package/scripts/ledgerkit/core/paths.py +93 -0
  32. package/scripts/ledgerkit/core/time.py +102 -0
  33. package/scripts/ledgerkit/core/worklog_md.py +232 -0
  34. package/scripts/ledgerkit/env.py +93 -0
  35. package/scripts/ledgerkit/errors.py +15 -0
  36. package/scripts/ledgerkit/notices.py +28 -0
  37. package/scripts/ledgerkit/shell/__init__.py +0 -0
  38. package/scripts/ledgerkit/shell/cli.py +259 -0
  39. package/scripts/ledgerkit/shell/gitops.py +655 -0
  40. package/scripts/ledgerkit/shell/merge.py +266 -0
  41. package/scripts/ledgerkit/shell/presync.py +23 -0
  42. package/scripts/ledgerkit/shell/render.py +165 -0
  43. package/scripts/ledgerkit/shell/runner.py +225 -0
  44. package/scripts/ledgerkit/store/__init__.py +0 -0
  45. package/scripts/ledgerkit/store/atomic.py +130 -0
  46. package/scripts/ledgerkit/store/dirty.py +108 -0
  47. package/scripts/ledgerkit/store/history_store.py +189 -0
  48. package/scripts/ledgerkit/store/json_store.py +166 -0
  49. package/scripts/ledgerkit/store/locks.py +64 -0
  50. package/scripts/ledgerkit/store/owners_index.py +114 -0
  51. package/scripts/ledgerkit/store/task_store.py +28 -0
  52. package/scripts/ledgerkit/store/worklog_store.py +168 -0
  53. package/scripts/progress.py +8 -3109
  54. package/references/taxonomy.md +0 -26
  55. package/references/worklog.md +0 -39
package/README.md CHANGED
@@ -1,267 +1,49 @@
1
1
  # task-ledger
2
2
 
3
- > 这份文档**给人看**:它是什么、为什么这么设计、一次调用背后发生什么。
4
- > 给 agent 的执行说明在 `SKILL.md`,两者不重复;`SKILL.md` 里**没有**引用本文件,所以它不会进 agent 上下文、不占 token。
3
+ > 给人看的概览与索引。给 agent 的执行说明在 `SKILL.md`(每次会话整份注入),两者不重复;本文件不进 agent 上下文、不占 token。
5
4
 
6
- ## 一、它做什么
5
+ ## 它做什么
7
6
 
8
- 管一个项目 / 工作区的任务进度(开发活、琐事、调研、备忘都算),一共三件东西:
7
+ 管一个工作区 / 项目的任务进度(开发活、琐事、调研、备忘都算),一共三件东西:
9
8
 
10
- | 管什么 | 落在哪 | 谁写 |
11
- |---|---|---|
12
- | 在办任务的状态 | `ledger/progress.json` | **只由脚本写** |
13
- | 每个任务的过程正文 | `ledger/worklog/<年月>/<日>-<时分>-<说明>-<随机码>.md` | **建档只由脚本按模板做**,之后正文 **agent 直接编辑** |
14
- | 已结案任务,一行一条(9 列:结案时间 / 创建时间 / 工作包 / 分类 / 标签 / owner / creator / 摘要 / 过程文档) | `ledger/history/<年月>.md`(按**结案时间**分月;存量 `ledger/PROGRESS-HISTORY.md` 只读兼容、永不重写) | **只由脚本写**;查询走 `history` 子命令 |
9
+ - **谁在做、做到哪**:状态只在台账 JSON —— `ledger/pool.json`(公共池)+ 每人一份 `ledger/owners/<hash>.json` 分片,索引 `ledger/owners.json`。
10
+ - **过程正文**:全在 `ledger/worklog/<年月>/<月日>-<时分>-<说明>-<码>.md`(六节),agent 直接编辑前五节,末节「执行记录」只由脚本写。
11
+ - **已结案**:一行一条在 `ledger/history/<年月>.md`(9 列),只由脚本写。
15
12
 
16
- 覆盖的动作:建任务、认领、交接、改状态、结案、查在办、查历史、体检。
13
+ 状态改动与正文重写分开、全部经脚本改 —— 不另建副本、不手改状态表和历史。覆盖动作:建任务、认领、释放、结案、查在办、查历史、标签归并、体检。
17
14
 
18
- 典型场景:
15
+ ## 文件布局(脚本只写这些)
19
16
 
20
- - 问「现在该做什么 / 我还有什么没做完」→ 查在办
21
- - 说「新建一个任务 / 这活我领了 / 卡住了 / 转给某人 / 这活做完了」→ 改状态或结案
22
- - 问「某件老活是什么时候做的」「谁改过什么」「拉某人的工作日志」→ `history` 子命令(只读,可直接跑)
23
-
24
- ## 二、为什么这么设计
25
-
26
- ### 顶层目录为什么是 `ledger/`,不是 `docs/`
27
-
28
- `docs/` 是**项目自己的地盘** —— 项目的文档规范、设计、样例都住在那里,各有各的规矩。
29
- 把进度三件套塞进 `docs/`,等于让「进度管理」去占用别人已经安排好的空间;
30
- 换一个没有 `docs/` 的项目、或项目把 `docs/` 用作别的用途,就又得重新商量放在哪。
31
-
32
- 所以本 skill 统一用**独立的 `ledger/` 目录**:任何项目、任何工作区都用同一个名字,
33
- 既不依赖项目原有的 `docs/`,也不与它发生关系(项目原有 `docs/` 原样不动、不进本体系)。
34
- 进度是「跨项目长一个样」的东西,就该有一个跨项目固定的家。
35
-
36
- ### 状态用 JSON,不用 Markdown
37
-
38
- 状态要频繁改(`open` → `doing` → 结案),Markdown 里改一个词很容易顺手改到别处。JSON 结构化、字段固定、一次只动一个值,改动面最小。
39
-
40
- ### 状态与过程正文分离
41
-
42
- 状态改动频繁、正文频繁重写,混在一个文件里必然互相踩。所以拆成两个文件:**JSON 只放数据,正文全在 `worklog/`**。JSON 里一个字的过程描述都不放 —— 一旦开始写段落,改动面就不可控了。
43
-
44
- 唯一进 JSON 的「文档类」信息是过程文档的**路径**(`worklog` 字段,如 `worklog/202610/06-0000-doc-arch-review-7a3c.md`)。它不是描述而是索引:按月分目录之后文件名不再等于任务号,靠推算容易找错,记一笔最省事。
45
-
46
- ### 历史层的 owner 是独立列
47
-
48
- 「谁改过什么」「拉某人的工作日志」靠 `history --owner` **精确匹配**。owner 必须独立成列,不能缝在工作包标题里:缝进去就只能文本搜索,`a` 会命中 `a-11`;切分也只能靠「最后一个 ` @`」这种启发式,标题里出现 `@`(如 `rulemux@0.1.0`)就切错。独立列让按人查退化成列比较,与 `list --owner` 查在办是同一套精确语义。
49
-
50
- ### 记录时间精确到秒,任务号 / 文件名只到分
51
-
52
- 两者用途不同,精度也不同:**任务号、worklog 目录与文件名**只到分(`年月日-时分` / `YYYYMM`)—— 够排序、够肉眼定位,且短;**所有记录时间**(`progress.json` 的 `created` / `started` / `finished`、历史表的时间列、worklog 头部的创建 / 封卷行)到**秒** —— 按时间段检索、比对都靠它,分不够。
53
-
54
- 写入前一律经 `normalize_time` 归一化:`2026-10-06`、`2026-10-06 14:30`、`2026-10-06 14:30:05` 都接受,缺的补 `00:00:00`。读旧数据时又**兼容只到分**的写法(老历史行照读不误),只有新写入的才带秒。
55
-
56
- ### 历史表为什么带创建时间
57
-
58
- 历史层的过滤口径是**创建时间**(`list` / `history` 的 `--since` / `--until` 都按它),因为「这活是什么时候建的」比「什么时候被结案」更常用、也更稳。所以历史行同时存**结案时间**(第一列)与**创建时间**(第二列)。升级旧行时创建时间先读它链接的 worklog 头部「创建」行,读不到用升级时刻 —— 不留空。
59
-
60
- ### 历史层为什么按月归档
61
-
62
- `close` 每结案一行就往历史层追加,早期是单一文件 `ledger/PROGRESS-HISTORY.md`:项目一两年下来它无限增长,每次结案都要整文件读入、升级、重写 —— 结案成本随历史总量线性变差。
63
-
64
- 现在按**结案时间**分月落 `ledger/history/<年月>.md`,与 worklog 的 `ledger/worklog/<年月>/` 同构:
65
-
66
- - **写入时分月,不做定时外挪** —— 外挪需要一个「谁定时触发」的角色,必然漂移;写入时分月零新增动作,且结案只碰当月小文件
67
- - **存量文件原地只读** —— 改造前的 `ledger/PROGRESS-HISTORY.md` 永不重写、永不删除,读侧 glob 兼容;它里面的旧格式行也不会被自动升级(读侧三格式兼容 + `validate` 提示已覆盖)
68
- - **文档链接跟着所在文件走** —— 行里的 worklog 链接相对该行所在的历史文件目录解析:存量文件里是 `worklog/…`,月文件里是 `../worklog/…`,两边都可点击、可定位
69
- - **查询无感** —— `history` / `validate` 合并全部来源,过滤、排序、`--json` 行为不变;行尾附所在历史文件,`--json` 记录带 `src` 字段
70
-
71
- ### 状态文件只由脚本写
72
-
73
- 两个人(或两个 agent)同时编辑同一个文件会互相覆盖。脚本的写入靠两层保证:
74
-
75
- 1. **原子替换**:先写同目录的临时文件,再 `os.replace` —— 保证文件不会出现半截内容
76
- 2. **写前复查指纹**:读的时候记下文件的**内容哈希**(sha256),写之前再比一次;变了就报错中止、要求重跑。
77
- 刻意不用 mtime+size —— 并发写入可能落在同一时间精度内、字节数又恰好相同,那样指纹不变,复查就形同虚设
78
-
79
- 第 2 条是**发现并中止**,不是自动合并 —— 它把「静默覆盖别人」变成「明确报错让你重来一次」。所以并发下偶尔会遇到「被改动过,重跑」,这是设计如此,不是 bug。
80
-
81
- ### worklog 头部只写不会变的东西
82
-
83
- 原设计里 worklog 头部带 `状态:open · owner:(待认领)`,实测发现:**`claim` 之后头部还写着 `open`,成了过期副本**。删掉 —— 状态真源只有 `progress.json` 一个。
84
-
85
- 现在头部只写两样**写入后就不再变**的:**创建时间 + 创建人**(`new` 建档时写)、**封卷时间 + 封卷人**(`close` 结案时追加)。会变的东西(状态、当前 owner)一律不写。
86
-
87
- ### 任务号 = 创建时间 + 语义名 + 4 位随机码
88
-
89
- `登录接入 SSO`(2026-10-15 14:30 建的)→ `20261015-1430-登录接入-sso-1eed`。
90
-
91
- - 前置 `年月日-时分`:一眼看出这个任务是什么时候建的,也天然按时间排序
92
- - 中段语义名:一眼知道是什么任务(所以保留汉字,纯中文标题也能生成)
93
- - 后缀 4 位随机码:**必须保留** —— 任务号只在在办任务里去重,而 worklog 结案后仍留在磁盘上,去掉随机码会让新任务与已结案的过程文档同名、覆盖历史
94
- - 不用纯 UUID:文件名会变得完全不可读
95
- - 想自己指定就传 `--id`
96
-
97
- ### owner 只认 git 身份,不做兜底
98
-
99
- `owner` 一律取 `git config user.name`。取不到就**直接报错退出**(提示「需要用户名才能执行」),没有默认值、没有备选标识、没有降级路径。
100
-
101
- 理由:拿一个编造的身份去写"谁在做这个任务",比写不进去危险得多。
102
-
103
- ### 只能改自己的任务
104
-
105
- `set`、`close` 和 `log` 都先取身份,再校验「这个任务的 owner 是不是你」:**不是就拒绝**;任务还没人认领(`open`)也拒绝,提示先 `claim`。要接手就走 `set --owner` 交接 —— 一次显式动作。
106
-
107
- 理由有两层:一是别人替你结案,你会失去对进度的掌控;二是如果只取了身份却不校验归属,`owner` 这个字段就只是个装饰品。
108
-
109
- ### 不依赖任何框架注入的变量
110
-
111
- 早先写成 `{baseDir}/scripts/progress.py` —— 那是某一家的注入变量,换个 harness 就没有。现在写成「本 SKILL.md 所在目录」这种不依赖注入的表述。
112
-
113
- 同理,**项目位置必须由调用方用 `--repo` 传**:脚本只知道自己在哪,不可能知道你现在在哪个项目里干活。
114
-
115
- ### 并发策略
116
-
117
- - 所有写命令(`init` / `new` / `claim` / `set` / `log` / `close`)走同一套:**读 → 改内存 → 复查指纹 → 原子写**
118
- - 临时文件名唯一(`mkstemp`),写完 `fsync` 再 `os.replace`,无论成败都清理临时文件
119
- - key 按字母序落盘,减少两人同时新增时的文本冲突
120
- - 冲突时**报错要求重跑**,不静默覆盖
121
- - 写入成功后脚本会**自动同步**:把本次改动的台账文件 `git add <精确文件>` + `commit`(消息 `chore(ledger): <命令> <提交者>`,即 conventional commits 格式,多数仓库装了 commitlint 也认);当前分支有上游跟踪分支时再 `push`。全程确定性脚本,不依赖大模型
122
- - 仓库若装了自定义提交检查并拒了这条消息,脚本会**再用 `--no-verify` 提交一次**(台账是数据文件,不过 lint);仍失败则把 git 的报错打到 stderr 并要求手动提交 —— **同步失败绝不静默**,但退出码保持 0(台账本身已写成功)
123
- - 写前会**定向取最新**:只刷新 `ledger/progress.json` 与 `ledger/history/`(这两个只由脚本写);`ledger/worklog/` 里已有的正文一个字都不动,只在本地缺文件时补下远端的新文件(补下的文件随本次提交入库)。有未提交的台账改动、或未入库的同名文件时**中止**,不静默覆盖;命令随后失败时,写前刷下来的内容会回滚原样
124
- - 本地有未推送的台账提交时,写前会**先自动补推**(非快进就 `rebase` 一次再推),成功后照常写 —— 离线攒下的那几笔,联网后第一笔写就会自己推上去
125
- - 本地**没有未推送提交**时,写前先 fast-forward 到上游(只快进、不产生合并提交)
126
- - 同一个 clone 里的写命令**排队**执行(仓级文件锁,最多等 60 秒),避免两个 agent 同时写时,一个把另一个刚写完还没提交的改动静默覆盖
127
- - 写后推送被拒时,工作树干净才自动 `rebase` 一次再推(各自改各自的任务时按行自动合并);冲突立刻 `rebase --abort`,绝不 `--force`、绝不留 rebase 中间态。**本地有用户自己的(非台账)未推送提交时不做 rebase**(那会改写它们的提交号),只提示并让用户自己合并;推送前还会说明「这次会一并推走你本地几个提交」
128
- - 无 git 仓库 / 无上游跟踪 / 被 `.gitignore` 排除(含「台账先提交过、之后才加忽略规则」)/ 无实际变更 都会静默跳过;`--no-sync`(写在子命令前后都行)或环境变量 `TASK_LEDGER_NO_SYNC=1` 可同时关掉写前取最新与写后同步
129
- - **环境要求 git ≥ 2.27**(自动合并依赖 `rebase --autostash` 的冲突回滚)。没有 git 的目录自动跳过:台账照写,不提交、不推送
130
-
131
- ### 结案是原子操作
132
-
133
- `close` 一次完成三件事,**顺序是有意排的**:先写历史索引 → 再封卷过程文档 → **最后**才从状态表里移除。
134
-
135
- 为什么是这个顺序:万一中途崩溃,最坏结果是「历史多了一行、状态表里任务还在」,重跑一次就对上了;反过来先删状态、后写历史,崩溃会让任务**既不在状态表、也不在历史** —— 记录凭空消失。
136
-
137
- 落盘时任一步失败会**整体回滚**,并逐文件报告哪些恢复成功、哪些没成功(回滚本身失败时不会掩盖原始错误)。
138
-
139
- ### 分类与标签为什么不设枚举
140
-
141
- 本 skill 跨所有工作区使用(开发 / 运维 / 个人事务 / 调研备忘都算),任何固定枚举都覆盖不全、颗粒度难定;「让 Agent 判断会不准」也不能靠穷举分类消解。所以分两层、都自由:
142
-
143
- - **`category` 单值**:答「这事是什么类型」。一条一值,`count by` 干净,是人眼扫视和看板统计的轴
144
- - **`tags` 1~5 个**:答「这事涉及什么」(对象 / 领域 / 模块)。兜住长尾与新领域,写错了只影响一个切面
145
-
146
- 两层都只硬校验**形态**(≤4 字 / 纯英文 ≤3 词 / ≤5 个),不校验语义 —— 语义 correctness 交给口径(SKILL.md 的归一化规则 + 正反示例)和巡检归并机制,不交给枚举。
147
-
148
- ### category 精确匹配、tag 包含匹配
149
-
150
- 两种查询语义不同是有意的:category 是统计轴,同值才能比较,必须精确;tag 是容错下钻,「bug」命中「bug修复」正是包含匹配要的效果 —— 它天然吃掉一部分同义变体,剩下的漂移靠 `tags --all` 暴露、`tags --rename` 归并。
151
-
152
- ### 为什么只硬校验上限、不设标签数量下限
153
-
154
- 设下限(如必须 3 个标签)会逼 Agent 凑数 —— 凑出来的正是噪声,与「容忍错误」的初衷相反。上限(≤5)与字数(≤4 字 / 英文 ≤3 词)是形态红线,必须硬校验;数量只引导、不强制。
155
-
156
- ### 分类/标签进 history 列(2026-10-15 存量改造时加入)
157
-
158
- 初版设计是「不进列、回链读」:history 解析写死 6 列,加列要迁移存量。用户评审时要求反转——已结案记录也要能按分类/标签查,于是升为 **8 列**(结案时间 / 创建时间 / 工作包 / 分类 / 标签 / owner / 摘要 / 过程文档):
159
-
160
- - `close` 从 task 直写分类/标签终值(`--category`/`--tags` 覆盖过的用覆盖值)
161
- - 存量 4/5/6 列由 `upgrade_history` 升级为 8 列:分类/标签**回链该行 worklog 头部**读(`labels_for_log`,与 created 回填同一模式),读不到留空、不编造
162
- - 回链没有废弃:`history` 子命令对仍是 4/5/6 列的旧行(未升级文件)继续回链兜底,`cmd_history` 里「列空才回链」
163
-
164
- 代价说清:加列动了 parse/upgrade/close 全链路,靠「逐行按自己列数判别 + 不敢升级就按原列数追加」的老机制兜底;冒烟覆盖了 8 列写入、6 列升级(owner 剥 @ 防 `@@`)、4 列升级、坏行退回四条路径。
165
-
166
- ### rename 为什么不碰已封卷文档
167
-
168
- 与「封卷即不可变」同一哲学:rename 只改状态表与在办 worklog 头部;已结案记录的旧标签留在原文档里。这类残留在 `tags --all` 的频次表里可见,看板侧自行归并 —— 台账只做记录,不做历史改写。
169
-
170
- ### 「分类/标签」行为什么由 render 动态插入
171
-
172
- 不占模板占位符 ⇒ `assets/worklog.md` 与 `FALLBACK_TEMPLATE` 都不用改,两个模板永远一致;空值(存量任务、Agent 没总结)自动不写行,向后兼容零成本。生成、解析、覆盖三处共用 `label_line` 一个格式定义,防漂移。
17
+ | 文件 | 装什么 |
18
+ |---|---|
19
+ | `ledger/pool.json` | 公共池:未认领任务(owner 空) |
20
+ | `ledger/owners.json` | 索引:git 邮箱身份 → 分片文件 |
21
+ | `ledger/owners/<hash>.json` | 每人一份分片:自己认领的任务 |
22
+ | `ledger/worklog/<年月>/*.md` | 任务正文(六节) |
23
+ | `ledger/history/<年月>.md` | 已结案(一行一条,9 列) |
173
24
 
174
- ## 三、运行逻辑
25
+ ## 为什么这么设计
175
26
 
176
- ### 一次调用发生什么
27
+ 跨项目固定用 `ledger/`(不占项目的 `docs/`);状态用 JSON 而非 Markdown(改动面最小);状态与过程正文分离(互不踩);一人一份分片把并发冲突面从整份文件缩到公共池里几行;台账数据时间存 UTC、过程文档里的日志行显示本地时间。
177
28
 
178
- ```mermaid
179
- graph LR
180
- U[用户说一句话] --> A[agent 读 SKILL.md 判断意图]
181
- A -->|只读直接跑| R[list / show / validate / history]
182
- A -->|写操作| W[init / new / claim / set / log / close]
183
- W --> P[ledger/progress.json]
184
- W --> H[ledger/history/年月.md]
185
- W --> M[ledger/worklog/年月/日-时分-说明-码.md]
186
- A -->|直接编辑| M
187
- A -->|只读查询| H
188
- W -->|返回该任务文档全文| A
189
- ```
29
+ ## 怎么用(执行规则在 SKILL.md)
190
30
 
191
- ### 状态机
31
+ 直接跑:
192
32
 
193
- ```mermaid
194
- stateDiagram-v2
195
- [*] --> open: new(不带 --self)
196
- [*] --> doing: new --self
197
- open --> doing: claim(认领,写 owner)
198
- doing --> open: set --status open(释放认领,清空 owner)
199
- doing --> [*]: close(进历史)
200
- note right of doing
201
- set --owner 交接:owner 换成别人
202
- (只有当前 owner 能执行)
203
- 逾期 = 接任务满 14 天;停滞 = 最后更新满 3 天
204
- 积压 = 待认领满 30 天
205
- (都由看板按时间算,不是状态)
206
- end note
33
+ ```bash
34
+ python3 <SKILL.md 所在目录>/scripts/progress.py <子命令> --repo <当前工作区>
207
35
  ```
208
36
 
209
- - `done` **只能由 `close` 产生**;`set --status done` 会被拒绝
210
- - **退回未认领**:owner 用 `set --status open` 把任务退回去,owner 清空、之后别人可以重新 `claim`;这条不能与 `--owner` 同时给
211
- - `set --owner <某人>` 是**交接**,由当前 owner 执行,执行后 owner 换成那个人。**该能力只为将来的 UI 保留**:SKILL.md 不向 agent 暴露它,换人一律走「释放 → 认领」,避免随便编一个名字挂上去
212
- - 状态表里不允许残留 `done`(`validate` 会报)
213
-
214
- ### 命令一览
37
+ 子命令:`new` `claim` `set` `log` `close` `list` `history` `show` `tags` `validate`。命令参考(参数 / 一句话 / 举例)、任务生命周期、纪律(数据完整性 / 人类授权 / 故障处置)全在 `SKILL.md`;参数细节看 `<子命令> --help`(不要凭记忆编)。
215
38
 
216
- | 子命令 | 作用 | 需要 git 身份 | 会返回任务文档全文 |
217
- |---|---|---|---|
218
- | `init` | 建状态表 | 否 | 否 |
219
- | `new` | 建任务并建档 | **是**(记 creator) | 是 |
220
- | `claim` | 认领待认领任务 | **是** | 是 |
221
- | `set` | 改状态 / 交接 / 释放认领(`--status open`) | **是**(且必须是该任务的 owner) | 是 |
222
- | `log` | 往 worklog「执行记录」补一条 | **是**(且必须是该任务的 owner) | 否(只回一行确认) |
223
- | `close` | 结案归档 | **是**(且必须是该任务的 owner) | 否 |
224
- | `list` | 查在办任务 | 仅 `--mine` | 否 |
225
- | `history` | 查已结案任务(只读) | 仅 `--mine` | 否(只给过程文档链接) |
226
- | `show` | 单任务详情 | 否 | 是 |
227
- | `tags` | 分类/标签巡检(`--all` 只读)/ 归并(`--rename` 批量写) | 否 | 否 |
228
- | `validate` | 校验一致性 | 否 | 否 |
39
+ ## 深入参考(references/,按需读)
229
40
 
230
- 参数细节看 `SKILL.md`,或直接跑 `<子命令> --help`。
231
-
232
- ### 返回什么
233
-
234
- | 命令 | 返回 |
41
+ | 文件 | 看什么 |
235
42
  |---|---|
236
- | `new` / `claim` / `set` / `show` | 状态行 + 该任务过程文档的**路径与全文** |
237
- | `log` | 一行确认(记了什么) |
238
- | `close` | 结案结果与摘要 |
239
- | `list` | 在办任务列表(不含正文,避免撑爆上下文) |
240
- | `history` | 已结案紧凑列表(默认不含摘要,避免撑爆上下文) |
241
-
242
- 返回文档全文是有意的:agent 拿到就能直接编辑,不用再去找文件、拼路径。
243
- `history` 是唯一的例外:只回过程文档的**链接**,正文另读 —— 历史层摘要就是这套体系里唯一的「正文」,默认不吐。
244
-
245
- ### 失败约定
246
-
247
- | 情况 | 行为 |
248
- |---|---|
249
- | 成功 | 退出码 0 |
250
- | 业务错误(参数值 / 状态 / 权限不对) | 输出到 stderr,**退出码 1**,消息以「错误:」开头 |
251
- | 命令行参数错误(argparse) | 退出码 2 |
252
- | 未预期的内部失败 | 输出到 stderr,**退出码 3**(与可纠正的业务错误区分开) |
253
- | 用户中断 | 退出码 130 |
254
- | 输出被下游截断(如 `\| head`) | 静默退出,退出码 0,不打 traceback |
255
-
256
- **报错就停下并原样报告,不要绕过脚本直接改 `ledger/progress.json` 或历史层(`ledger/history/<年月>.md`)。**
257
-
258
- ## 四、已知边界与待办
259
-
260
- 1. 本 skill 位于工作区 `_Skills/task-ledger/`;是否安装到全局 skill 目录由使用者决定 —— 未安装时其它项目不会自动触发。
261
- 2. `scripts/progress.py` 里的 `FALLBACK_TEMPLATE` 是**无注释的最小骨架**,只在 `assets/worklog.md` 读不到时启用 —— 两处注释多寡不同不是缺陷,**正例只放模板文件**。
43
+ | [`references/state-model.md`](references/state-model.md) | 状态机、时间口径(UTC / 本地、补录、筛选)、任务号、身份 |
44
+ | [`references/log-note.md`](references/log-note.md) | 执行记录什么算一个节点、`--note` 怎么写(正 / 反例) |
45
+ | [`references/troubleshooting.md`](references/troubleshooting.md) | 退出码、常见错误、硬约束、环境要求(git ≥ 2.27) |
262
46
 
263
- ## 五、维护者须知
47
+ ## 本仓自己的台账
264
48
 
265
- - `SKILL.md` 的 frontmatter `version` 与 `package.json` 的 `version` 保持同值;发版时一起改,打 `skill-v<version>` tag。
266
- - **`SKILL.md` 是每次会话整份注入的**:只放「不做就会写错数据」的规则与路由,细节进 `references/`(按需读,索引在 SKILL.md 末尾)。加体积前先自问「脚本或 `--help` 能不能兜住」。
267
- - 改完跑 `cd packages/plugin && npm run verify`(build + typecheck + smoke);`copy-skill` 会把 `scripts/` `assets/` `references/` 一并拷进插件内嵌副本,不要直接改那份拷贝。
49
+ 本仓库(`dsh-task-ledger`)也用 ledgerkit 管自己的活,台账数据在 `ledger/`;它和本 skill 源码 `packages/skill/` 是两回事 —— **改 skill 请别动 `ledger/`**。