task-ledger 1.3.9 → 1.3.11

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/SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: task-ledger
3
3
  description: 本地任务台账,跨会话记录在办任务的归属、进度与起止。当用户要登记一件新的事(新建任务 / 建个坑 / 这活我领了)、记录已有任务的进展(接着做 / 记一条进展 / 这轮先记下)、查看任务状态或历史(现在该做什么 / 这活谁在做 / 上周做过什么)、给任务结案或退回(做完了 / 验收通过 / 不做了 / 退回待认领)、整理标签或检查台账一致性时加载;只是改代码、讨论方案时不要用。
4
- version: 1.3.9
4
+ version: 1.3.11
5
5
  allowed-tools: Read,Edit,Bash,Grep
6
6
  ---
7
7
 
@@ -45,7 +45,7 @@ allowed-tools: Read,Edit,Bash,Grep
45
45
  | `--claim <uuid>` | 认领名册里已有的 uuid(名字一起复制) |
46
46
  | `--new --name "…"` | 新建身份:生成 uuid + 名字 |
47
47
 
48
- 干什么:写本机身份文件(`~/.taskledger/identity.json`),**一台机器只一次**,与台账无关。在终端里**裸跑 `init` 即交互式选择框**:读当前仓库名册,用**上下箭头**移动、**Enter** 认领某个身份,末尾「+ 新建身份」可输入新用户名自建;名册为空则直接让你输入用户名;全程要真终端。`--claim <uuid>` / `--new --name "<名字>"` 也只接受真终端,agent 的无终端调用会被脚本拒绝。
48
+ 干什么:写本机身份文件(`~/.taskledger/identity.json`),**一台机器只一次**,与台账无关。在终端里**裸跑 `init` 即交互式选择框**:读当前仓库名册,用**上下箭头**移动、**Enter** 认领某个身份,末尾「+ 新建身份」可输入新用户名自建;名册为空则直接让你输入用户名;全程要真终端。`--claim <uuid>` / `--new --name "<名字>"` 也只接受真终端,agent 的无终端调用会被脚本拒绝。
49
49
 
50
50
  ### new — 建任务
51
51
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-ledger",
3
- "version": "1.3.9",
3
+ "version": "1.3.11",
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",
@@ -304,21 +304,23 @@ def _select_identity(opts: list[dict], *, title: str) -> tuple[str, int | None]:
304
304
  sel = 0
305
305
  try:
306
306
  tty.setraw(fd)
307
+ sys.stdout.write("\x1b[?25l") # 隐藏光标
307
308
  while True:
308
- sys.stdout.write("\x1b[H\x1b[J")
309
+ # 每帧整屏重绘(2J 清屏 + H 回家),位置无关,避免折行/行数错位
310
+ sys.stdout.write("\x1b[2J\x1b[H")
309
311
  sys.stdout.write("\x1b[1;36m" + title + "\x1b[0m\n\n")
310
312
  for i, e in enumerate(entries):
311
313
  label = (
312
- "+ 新建身份(自己输入名字)"
314
+ "+ 新建身份(自己输入名字)"
313
315
  if e.get("new")
314
316
  else f"@{e['name']} {e['uuid']}"
315
317
  )
316
318
  if i == sel:
317
- sys.stdout.write(" \x1b[7m ❯ " + label + " \x1b[0m\n")
319
+ sys.stdout.write("\x1b[7m ❯ " + label + " \x1b[0m\n")
318
320
  else:
319
321
  sys.stdout.write(" " + label + "\n")
320
322
  sys.stdout.write(
321
- "\n \x1b[2m↑/↓ 移动 · Enter 确认 · Ctrl-C 退出\x1b[0m\n"
323
+ "\n\x1b[2m ↑/↓ 移动 Enter 确认 Ctrl-C 退出\x1b[0m"
322
324
  )
323
325
  sys.stdout.flush()
324
326
  ch = sys.stdin.read(1)
@@ -335,14 +337,15 @@ def _select_identity(opts: list[dict], *, title: str) -> tuple[str, int | None]:
335
337
  elif ch == "\x03": # Ctrl-C
336
338
  return ("cancel", None)
337
339
  finally:
340
+ sys.stdout.write("\x1b[?25h") # 显示光标
341
+ sys.stdout.write("\x1b[2J\x1b[H") # 退出时清掉选择框,结果从顶部打印
338
342
  termios.tcsetattr(fd, termios.TCSADRAIN, old)
339
- sys.stdout.write("\x1b[2J\x1b[H")
340
343
  sys.stdout.flush()
341
344
  except (OSError, ImportError):
342
345
  print(title)
343
346
  for i, o in enumerate(opts, 1):
344
347
  print(f" {i}. @{o['name']} {o['uuid']}")
345
- print(f" {n}. + 新建身份")
348
+ print(f" {n}. + 新建身份")
346
349
  while True:
347
350
  try:
348
351
  c = input(f"选编号(1-{n}):").strip()
@@ -409,13 +412,13 @@ def _run_init(args: argparse.Namespace) -> int:
409
412
  opts, title="这台机器还没初始化。选择你的身份,或新建一个:"
410
413
  )
411
414
  if kind == "cancel":
412
- print("已取消初始化。")
413
- return BUSINESS
415
+ print("\x1b[2m✕ 已取消初始化。随时可重跑 init 重新开始。\x1b[0m")
416
+ return 0
414
417
  if kind == "new":
415
418
  prompt_name = input("输入用户名:").strip()
416
419
  if not prompt_name:
417
- print("未输入用户名,已取消。")
418
- return BUSINESS
420
+ print("\x1b[2m✕ 未输入用户名,已取消。\x1b[0m")
421
+ return 0
419
422
  res = init_identity(repo, claim=None, new=True, name=prompt_name)
420
423
  else:
421
424
  res = init_identity(
@@ -431,6 +434,10 @@ def _run_init(args: argparse.Namespace) -> int:
431
434
  except (ValueError, IndexError):
432
435
  render.fail_message(Fail("输入无效,初始化已取消。"))
433
436
  return BUSINESS
437
+ except (KeyboardInterrupt, EOFError):
438
+ # 中途 Ctrl-C / Ctrl-D:平静取消,不抛栈、干净退出
439
+ print("\x1b[2m✕ 已取消初始化。随时可重跑 init 重新开始。\x1b[0m")
440
+ return 0
434
441
  _print_init_result(res)
435
442
  return 0
436
443