task-ledger 1.0.1 → 1.0.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/SKILL.md +1 -1
- package/package.json +1 -1
- package/scripts/progress.py +89 -13
package/SKILL.md
CHANGED
|
@@ -82,7 +82,7 @@ python3 <本 SKILL.md 所在目录>/scripts/progress.py <子命令> --repo <当
|
|
|
82
82
|
| `set` | 改状态 / 换负责人 | `--id`(必填)、`--status`、`--owner` |
|
|
83
83
|
| `close` | 结案:移出状态 + 追加历史 + 封卷过程文档 | `--id`、`--summary`(都必填)、`--finished`(可选,结案时间)、`--category` / `--tags`(可选,结案时覆盖修正一次) |
|
|
84
84
|
| `list` | 查询在办任务 | `--mine`、`--owner`、`--status`、`--since`、`--until`、`--category`(精确)、`--tag`(包含)、`--json` |
|
|
85
|
-
| `history` | 查已结案任务(只读) | `--owner`、`--mine`、`--since`、`--until`、`--limit`、`--category`(精确)、`--tag`(包含)、`--json` |
|
|
85
|
+
| `history` | 查已结案任务(只读) | `--owner`、`--mine`、`--since`、`--until`、`--limit`、`--category`(精确)、`--tag`(包含)、`--json`;另:`--count-only`(只数行数、封顶 1 万输出 `{count, capped}`,显示级统计)、`--months N`(只读最近 N 个月文件,不含存量平铺文件) |
|
|
86
86
|
| `show` | 单任务详情 | `--id`(必填) |
|
|
87
87
|
| `tags` | 分类/标签巡检与归并 | `--all`(全量频次表)、`--rename 旧 新`(归并在办任务的同值) |
|
|
88
88
|
| `validate` | 校验状态表与过程文档是否一致 | — |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "task-ledger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.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",
|
package/scripts/progress.py
CHANGED
|
@@ -736,6 +736,47 @@ def history_sources(repo: Path) -> list[Path]:
|
|
|
736
736
|
return paths
|
|
737
737
|
|
|
738
738
|
|
|
739
|
+
# 数行计数的封顶值(2026-10-17 为 dsh-task-ledger 看板统计卡新增):显示级统计封顶,
|
|
740
|
+
# 超出即 capped,精确值走 history --json / 列表。
|
|
741
|
+
COUNT_CAP = 10000
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
def history_row_count(
|
|
745
|
+
sources: list[Path], since: str | None, until: str | None, cap: int = COUNT_CAP
|
|
746
|
+
) -> dict[str, Any]:
|
|
747
|
+
"""数行计数(只读;2026-10-17 新增,服务看板「本周 / 近一年完成」统计卡)。
|
|
748
|
+
|
|
749
|
+
只数数据行(`| 2` 开头 = 结案时间以年份开头),到 cap 封顶返回 capped=True。
|
|
750
|
+
给了 since/until 时按创建时间列(第 2 列)粗筛——取日期部分做字符串比较
|
|
751
|
+
(ISO 日期字典序即时间序),不建对象、不判格式,比 parse_history 便宜一个量级。
|
|
752
|
+
⚠️ 显示级统计:坏行 / 旧格式行可能多数少数,精确数以 history --json 为准。
|
|
753
|
+
"""
|
|
754
|
+
since_d = (since or "")[:10]
|
|
755
|
+
until_d = (until or "")[:10]
|
|
756
|
+
total = 0
|
|
757
|
+
for hp in sources:
|
|
758
|
+
try:
|
|
759
|
+
text = hp.read_text(encoding="utf-8-sig")
|
|
760
|
+
except (OSError, UnicodeDecodeError):
|
|
761
|
+
continue
|
|
762
|
+
for line in text.splitlines():
|
|
763
|
+
if not line.startswith("| 2"):
|
|
764
|
+
continue
|
|
765
|
+
if since_d or until_d:
|
|
766
|
+
cells = line.split("|")
|
|
767
|
+
if len(cells) < 4:
|
|
768
|
+
continue
|
|
769
|
+
created = cells[2].strip()[:10]
|
|
770
|
+
if since_d and created < since_d:
|
|
771
|
+
continue
|
|
772
|
+
if until_d and created > until_d:
|
|
773
|
+
continue
|
|
774
|
+
total += 1
|
|
775
|
+
if total >= cap:
|
|
776
|
+
return {"count": total, "capped": True}
|
|
777
|
+
return {"count": total, "capped": False}
|
|
778
|
+
|
|
779
|
+
|
|
739
780
|
def worklog_link(log_path: Path, history_path: Path) -> str:
|
|
740
781
|
"""worklog 相对历史文件所在目录的 posix 链接。
|
|
741
782
|
|
|
@@ -1691,11 +1732,48 @@ def cmd_history(args: argparse.Namespace) -> None:
|
|
|
1691
1732
|
|
|
1692
1733
|
repo = find_repo(args.repo)
|
|
1693
1734
|
sources = history_sources(repo)
|
|
1735
|
+
want_owner = (
|
|
1736
|
+
args.owner.strip().lstrip("@") if args.owner else None
|
|
1737
|
+
) # 容忍「@名字」写法
|
|
1738
|
+
me = git_user() if args.mine else None
|
|
1739
|
+
filter_echo = {
|
|
1740
|
+
"owner": want_owner,
|
|
1741
|
+
"mine": args.mine,
|
|
1742
|
+
"since": since,
|
|
1743
|
+
"until": until,
|
|
1744
|
+
"limit": args.limit,
|
|
1745
|
+
"category": args.category.strip() if args.category else None,
|
|
1746
|
+
"tag": args.tag.strip() if args.tag else None,
|
|
1747
|
+
}
|
|
1694
1748
|
if not sources:
|
|
1749
|
+
# JSON / 计数模式必须**始终**机器可读:空台账也给 JSON,人话只走 stderr。
|
|
1750
|
+
# (2026-10-17 真机教训:这里原先直接 print 人话后 return,--json 调用方
|
|
1751
|
+
# 拿到非 JSON 输出 ⇒ dsh-task-ledger 看板 /board 整条 500。)
|
|
1752
|
+
if args.count_only:
|
|
1753
|
+
print(json.dumps({"count": 0, "capped": False}, ensure_ascii=False))
|
|
1754
|
+
return
|
|
1755
|
+
if args.json:
|
|
1756
|
+
print(
|
|
1757
|
+
json.dumps(
|
|
1758
|
+
{"count": 0, "filters": filter_echo, "records": []},
|
|
1759
|
+
ensure_ascii=False,
|
|
1760
|
+
indent=2,
|
|
1761
|
+
)
|
|
1762
|
+
)
|
|
1763
|
+
return
|
|
1695
1764
|
print(
|
|
1696
1765
|
f"没有已结案记录:ledger/history/ 还没有文件(存量 {HISTORY_REL} 也没有)。"
|
|
1697
1766
|
)
|
|
1698
1767
|
return
|
|
1768
|
+
if args.months is not None:
|
|
1769
|
+
if args.months < 1:
|
|
1770
|
+
raise Fail("--months 必须是正整数")
|
|
1771
|
+
# 只取按月归档的文件(存量平铺文件不进了——它是改造前的历史,窗口模式用不到)
|
|
1772
|
+
monthly = [p for p in sources if p.parent.name == HISTORY_DIR.name]
|
|
1773
|
+
sources = monthly[-args.months :]
|
|
1774
|
+
if args.count_only:
|
|
1775
|
+
print(json.dumps(history_row_count(sources, since, until), ensure_ascii=False))
|
|
1776
|
+
return
|
|
1699
1777
|
records: list[dict[str, Any]] = []
|
|
1700
1778
|
warnings: list[str] = []
|
|
1701
1779
|
for hp in sources:
|
|
@@ -1713,10 +1791,6 @@ def cmd_history(args: argparse.Namespace) -> None:
|
|
|
1713
1791
|
records.extend(recs)
|
|
1714
1792
|
warnings.extend(f"{rel} {w}" for w in warns)
|
|
1715
1793
|
|
|
1716
|
-
me = git_user() if args.mine else None
|
|
1717
|
-
want_owner = (
|
|
1718
|
-
args.owner.strip().lstrip("@") if args.owner else None
|
|
1719
|
-
) # 容忍「@名字」写法
|
|
1720
1794
|
rows = []
|
|
1721
1795
|
undated = 0
|
|
1722
1796
|
for r in records:
|
|
@@ -1757,15 +1831,7 @@ def cmd_history(args: argparse.Namespace) -> None:
|
|
|
1757
1831
|
json.dumps(
|
|
1758
1832
|
{
|
|
1759
1833
|
"count": len(rows),
|
|
1760
|
-
"filters":
|
|
1761
|
-
"owner": want_owner,
|
|
1762
|
-
"mine": args.mine,
|
|
1763
|
-
"since": since,
|
|
1764
|
-
"until": until,
|
|
1765
|
-
"limit": args.limit,
|
|
1766
|
-
"category": args.category.strip() if args.category else None,
|
|
1767
|
-
"tag": args.tag.strip() if args.tag else None,
|
|
1768
|
-
},
|
|
1834
|
+
"filters": filter_echo,
|
|
1769
1835
|
"records": rows,
|
|
1770
1836
|
},
|
|
1771
1837
|
ensure_ascii=False,
|
|
@@ -1914,6 +1980,16 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1914
1980
|
)
|
|
1915
1981
|
p.add_argument("--limit", type=int, help="过滤 + 倒序后取前 N 条(最近 N 条)")
|
|
1916
1982
|
p.add_argument("--json", action="store_true", help="输出结构化 JSON(含摘要)")
|
|
1983
|
+
p.add_argument(
|
|
1984
|
+
"--count-only",
|
|
1985
|
+
action="store_true",
|
|
1986
|
+
help="只数行数(封顶 1 万,输出 {count, capped});显示级统计,精确数以 --json 为准",
|
|
1987
|
+
)
|
|
1988
|
+
p.add_argument(
|
|
1989
|
+
"--months",
|
|
1990
|
+
type=int,
|
|
1991
|
+
help="只读最近 N 个月的历史文件(ledger/history/*.md 按文件名取末 N 个;不含存量平铺文件)",
|
|
1992
|
+
)
|
|
1917
1993
|
add_repo(p)
|
|
1918
1994
|
p.set_defaults(func=cmd_history)
|
|
1919
1995
|
|