dsh-task-ledger 0.0.89 → 0.0.90

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-task-ledger",
3
- "version": "0.0.89",
3
+ "version": "0.0.90",
4
4
  "description": "Task ledger board for dsh (DeepSeek Harness): read-only board over task-ledger skill workspaces. The task-ledger skill is bundled — install the plugin, get the skill globally.",
5
5
  "keywords": [
6
6
  "deepseek",
package/skill/SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: task-ledger
3
3
  description: 本地任务台账,跨会话记录在办任务的归属、进度与起止。当用户要登记一件新的事(新建任务 / 建个坑 / 这活我领了)、记录已有任务的进展(接着做 / 记一条进展 / 这轮先记下)、查看任务状态或历史(现在该做什么 / 这活谁在做 / 上周做过什么)、给任务结案或退回(做完了 / 验收通过 / 不做了 / 退回待认领)、整理标签或检查台账一致性时加载;只是改代码、讨论方案时不要用。
4
- version: 1.3.15
4
+ version: 1.3.16
5
5
  allowed-tools: Read,Edit,Bash,Grep
6
6
  ---
7
7
 
@@ -15,17 +15,7 @@ allowed-tools: Read,Edit,Bash,Grep
15
15
 
16
16
  ## 身份闸门(未初始化时怎么走)
17
17
 
18
- **任何命令返回「这台机器还没有初始化身份」⇒ 一律停下,不许绕。** 身份是用户自己的,不是你的决定。
19
-
20
- - **查询类**(`list` / `show` / `history` / `validate`):什么都不做。把 init 命令交给用户,等 ta 跑完再重试原命令。
21
- - **写入类**(`new` / `claim` / `set` / `log` / `close`):不建、不改、不推送。先裸跑一次 `init`(只读,只把名册里已有的身份报出来):
22
- - **有名单** ⇒ 「名册里已有这些身份:<uuid 名字>。确定哪个是你的,就自己在终端跑 `init --claim <uuid>` 选它;都不是就 `init --new --name <名字>` 新建。」**报给用户,让 ta 选。**
23
- - **没名单** ⇒ 「名册为空,请在终端 `init --new --name <名字>` 新建。」
24
- - **禁止(硬规则)**:
25
- - **不替用户执行** `init --claim` / `init --new` / `init --name` —— 挑哪个身份是用户的事;
26
- - **不读** `ledger/*.json`、worklog 去"自己看";
27
- - 未初始化时**不做任何写**。
28
- - `init` 的写操作只能由用户在终端交互执行(脚本对无终端调用直接报错);agent **唯一**可跑的 `init` 是不带参数、只报名单的只读形式。
18
+ **任何命令返回「这台机器还没有初始化身份」⇒ 停下,不许绕。** 身份是用户自己的,不是你的决定:不替用户选、不读 `ledger/*.json` 兜底、未初始化时不写任何东西。**具体走法(用户自跑 / 你代跑的分步流程、Y/N 与回退)见 `references/init-identity.md`,按那里一步步做。**
29
19
 
30
20
  ## 手写边界
31
21
 
@@ -45,7 +35,7 @@ allowed-tools: Read,Edit,Bash,Grep
45
35
  | `--claim <uuid>` | 认领名册里已有的 uuid(名字一起复制) |
46
36
  | `--new --name "…"` | 新建身份:生成 uuid + 名字 |
47
37
 
48
- 干什么:写本机身份文件(`~/.taskledger/identity.json`),**一台机器只一次**,与台账无关。在终端里**裸跑 `init` 即交互式选择框**:读当前仓库名册,用**上下箭头**移动、**Enter** 认领某个身份,末尾「+ 新建身份」可输入新用户名自建;名册为空则直接让你输入用户名;选定或输入名字后需 **Y/N 确认**才写入(选 **N** 会返回选择菜单重新选,不会直接退出);**ESC 或 Ctrl-C** 可随时取消。全程要真终端。`--claim <uuid>` / `--new --name "<名字>"` 也只接受真终端,agent 的无终端调用会被脚本拒绝。
38
+ 干什么:写本机身份文件(`~/.taskledger/identity.json`),**一台机器只一次**,与台账无关。真终端里裸跑 `init` 是交互式选择框(↑/↓ 选、Enter 认领、末尾「+ 新建身份」输名字、Y/N 确认、ESC/Ctrl-C 取消);非终端(agent)下裸跑 `init` 只报名单,写操作须带 `--yes`。完整流程见 `references/init-identity.md`。
49
39
 
50
40
  ### new — 建任务
51
41
 
@@ -244,3 +234,4 @@ python3 <本 SKILL.md 所在目录>/scripts/progress.py <子命令> --repo <工
244
234
  | 任何非 0 退出、退出码 0 但有 `提示:` / `错误:` / `警告:`、并发冲突、`validate` 报错 | `references/troubleshooting.md` |
245
235
  | 传 `--created` / `--finished` 补录时间、看 `--json` 里的时间字段、查别人时 owner 匹配异常、看 history 列义 / 时间窗口口径 | `references/state-model.md` |
246
236
  | 拿不准一条记录够不够格、`--note` 不会写 | `references/log-note.md` |
237
+ | 任何命令报「这台机器还没有初始化身份」、或要初始化身份 | `references/init-identity.md` |
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-ledger",
3
- "version": "1.3.15",
3
+ "version": "1.3.16",
4
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
5
  "keywords": [
6
6
  "skill",
@@ -0,0 +1,50 @@
1
+ # 未初始化身份时怎么走
2
+
3
+ 触发:任何命令返回「这台机器还没有初始化身份」。身份是用户自己的,**不是你的决定**。
4
+
5
+ 先问用户走哪条:
6
+
7
+ 1. 用户自己在终端执行(推荐)
8
+ 2. 你一步步代跑
9
+
10
+ ## 路径 1:用户自跑
11
+
12
+ 给用户这条命令,让 ta 在自己的终端里跑:
13
+
14
+ ```
15
+ python3 <本 SKILL.md 所在目录>/scripts/progress.py init --repo <工作区根>
16
+ ```
17
+
18
+ 交互式:↑/↓ 选、Enter 认领、末尾「+ 新建身份」输名字、Y/N 确认、ESC/Ctrl-C 取消。
19
+ 用户说「好了」后,重跑原来那条命令。
20
+
21
+ ## 路径 2:你代跑(分步,每步停下等用户回答)
22
+
23
+ 1. 只读报名单(非终端下裸跑 `init` 就是只读,不写):
24
+
25
+ ```
26
+ python3 <本 SKILL.md 所在目录>/scripts/progress.py init --repo <工作区根>
27
+ ```
28
+
29
+ 2. 把名单原样给用户:
30
+ - 有名单 ⇒「名册现有:@A(uuid)、@B(uuid)。请告诉我要用哪一个;或回「新建」并给出用户名。」
31
+ - 没名单 ⇒「名册为空,请给一个用户名。」
32
+ 3. 复述并要确认:
33
+ - 选现有 ⇒「您确认是要使用「@X」这个身份吗?回复 Y 或 N。」
34
+ - 新建 ⇒「您确认要用「X」这个名称新建账户吗?回复 Y 或 N。」
35
+ 4. 仅当用户这一轮明确回 Y,才执行(注意 `--yes`):
36
+ - 认领:`... init --claim <uuid> --yes --repo <工作区根>`
37
+ - 新建:`... init --new --name "X" --yes --repo <工作区根>`
38
+ - 回 N ⇒ 回到第 2 步重选。
39
+ - 用户取消 / 不回 ⇒ 停,什么都不写。
40
+ 5. 成功后重跑原命令;失败照实报告并停。
41
+
42
+ ## 硬规则
43
+
44
+ - 不自己编 uuid 或名字;不猜身份。
45
+ - 没有用户这一轮的明确 Y,**不得**加 `--yes`。
46
+ - 用户没回,不要自己继续。
47
+ - 不读 `ledger/*.json`、worklog 去"自己看"。
48
+ - 未初始化时不做任何写。
49
+
50
+ `--yes` 只表示「用户已在此对话中明确同意」,不是安全沙箱:Agent 无视规则时脚本拦不住,靠的是这份流程约束。
@@ -69,7 +69,7 @@ def current(repo: Path | None = None) -> Identity:
69
69
  if identity is None:
70
70
  raise Fail(
71
71
  "这台机器还没有初始化身份。\n"
72
- " 处理:先运行 `progress.py init --repo <工作区根>`,输入一个名字,再执行本命令。"
72
+ " 处理:先运行 `progress.py init --repo <工作区根>`(交互式选择或新建身份),再执行本命令。"
73
73
  )
74
74
  name = identity.name
75
75
  if repo is not None:
@@ -108,6 +108,11 @@ def build_parser() -> argparse.ArgumentParser:
108
108
  initp.add_argument("--claim", help="认领名册里已有的 uuid")
109
109
  initp.add_argument("--new", action="store_true", dest="new_id", help="新建身份")
110
110
  initp.add_argument("--name", help="新建身份时的显示名字(必填)")
111
+ initp.add_argument(
112
+ "--yes",
113
+ action="store_true",
114
+ help="非交互写入确认(由 Agent 在用户明确同意后使用)",
115
+ )
111
116
 
112
117
  # 宿主(插件 / SKILL.md)的调用写法是 `progress.py list --repo <仓库>`:
113
118
  # `--repo` 挂在**子命令后面**,所以每个子命令都要认;子命令给的值覆盖顶层那个。
@@ -417,6 +422,7 @@ def _run_init(args: argparse.Namespace) -> int:
417
422
  claim = getattr(args, "claim", None)
418
423
  new = bool(getattr(args, "new_id", False))
419
424
  name = (getattr(args, "name", "") or "").strip()
425
+ yes = bool(getattr(args, "yes", False))
420
426
  tty = sys.stdin.isatty()
421
427
 
422
428
  try:
@@ -425,12 +431,12 @@ def _run_init(args: argparse.Namespace) -> int:
425
431
  # 已初始化:幂等空转(带不带 flag 都一样,零写)
426
432
  res = init_identity(repo, claim=claim, new=new, name=name)
427
433
  elif claim or new or name:
428
- # flag 写操作:只接受真终端;agent 无终端调不动(2026-10-26 事故)
429
- if not tty:
434
+ # 非终端写入必须带 --yes:Agent 只能在用户明确同意后代跑(2026-10-26 事故)
435
+ if not tty and not yes:
430
436
  raise Fail(
431
- "写入身份必须由用户在终端里交互执行(当前没有终端)。\n"
432
- " 处理:请用户在终端运行 `python3 progress.py init --repo <工作区根>`,\n"
433
- " 它会列出已有身份供选择,或让 ta 输入一个新名字。"
437
+ "非交互写入身份需要用户明确同意。\n"
438
+ " 处理:先裸跑 init(只读)把名册报给用户,取得明确同意后再加 --yes 重跑;\n"
439
+ " 或请用户自己在终端运行 init(交互式选择/新建)。"
434
440
  )
435
441
  res = init_identity(repo, claim=claim, new=new, name=name)
436
442
  else: