@kairyou/agent-tools 0.18.0 → 0.19.0

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 CHANGED
@@ -56,7 +56,7 @@ Usage:
56
56
 
57
57
  ### at-zentao
58
58
 
59
- Work ZenTao (禅道) bugs/tasks end to end, read linked story context, or log task hours; asks before committing and before writing back.
59
+ Work ZenTao (禅道) bugs/tasks end to end, manage task status and hours, or read linked story context; asks before committing and before writing back.
60
60
 
61
61
  ```bash
62
62
  npx -y skills@latest add kairyou/agent-tools --skill at-zentao -g -y
@@ -67,7 +67,7 @@ Usage:
67
67
  - `/at-zentao bugs` — list bugs assigned to you (the configured account); pick one or several (several = batch mode)
68
68
  - `/at-zentao tasks` — same, for tasks
69
69
  - `/at-zentao bug <id>` — work a specific bug
70
- - `/at-zentao task <id> [request]` — work a specific task or log hours with a natural-language request
70
+ - `/at-zentao task <id> [request]` — work a task, start/pause/resume it, or log hours with a natural-language request
71
71
  - `/at-zentao story <id>` — read requirement scope and acceptance context without writing back
72
72
 
73
73
  Config: `~/.agent-tools/config.jsonc` → `"zentao": { "url", "account", "password" }`. The password can be entered directly or referenced with `"password": { "env": "ZENTAO_PASSWORD" }`; never paste credentials or tokens into chat.
package/README.zh-CN.md CHANGED
@@ -56,7 +56,7 @@ npx -y skills@latest add kairyou/agent-tools --skill at-simplify -g -y
56
56
 
57
57
  ### at-zentao
58
58
 
59
- 读取禅道 bug/task 并端到端处理, 补充关联 story 上下文, 或记录任务工时; 提交和回写前均需确认.
59
+ 读取禅道 bug/task 并端到端处理, 管理任务状态和工时, 或补充关联 story 上下文; 提交和回写前均需确认.
60
60
 
61
61
  ```bash
62
62
  npx -y skills@latest add kairyou/agent-tools --skill at-zentao -g -y
@@ -67,7 +67,7 @@ npx -y skills@latest add kairyou/agent-tools --skill at-zentao -g -y
67
67
  - `/at-zentao bugs` — 列出指派给你(配置的账号)的 bug, 挑一个或多个(多个 = 批量模式)
68
68
  - `/at-zentao tasks` — 同上, 任务清单
69
69
  - `/at-zentao bug <id>` — 直接处理指定 bug
70
- - `/at-zentao task <id> [请求]` — 处理指定 task, 或用自然语言记录工时
70
+ - `/at-zentao task <id> [请求]` — 处理指定 task, 用自然语言开始/暂停/继续或记录工时
71
71
  - `/at-zentao story <id>` — 只读查看研发需求范围和验收信息
72
72
 
73
73
  配置: `~/.agent-tools/config.jsonc` → `"zentao": { "url", "account", "password" }`. 密码可以直接填写, 也可以使用 `"password": { "env": "ZENTAO_PASSWORD" }` 引用环境变量; 不要在对话中粘贴凭据或 token.
@@ -14,7 +14,7 @@ agent-tools/
14
14
  │ │ ├── at-review/ # Review local or hosted changes for bugs and regressions.
15
15
  │ │ └── at-simplify/ # Reduce complexity and duplication in changes.
16
16
  │ └── systems/ # Self-contained Skills for external systems.
17
- │ └── at-zentao/ # Self-contained ZenTao development and time-entry workflow.
17
+ │ └── at-zentao/ # Self-contained ZenTao development and task-lifecycle workflow.
18
18
  ├── docs/ # Advanced guides and contributor reference.
19
19
  ├── tools/ # Maintainer-only upstream sync and repository tooling.
20
20
  └── scripts/ # Install, sync, validation, and maintenance scripts.
@@ -14,7 +14,7 @@ agent-tools/
14
14
  │ │ ├── at-review/ # 审查本地或托管改动中的 bug 与回归风险.
15
15
  │ │ └── at-simplify/ # 减少改动中的冗余和复杂度.
16
16
  │ └── systems/ # 面向外部系统的自包含 Skills.
17
- │ └── at-zentao/ # 自包含的禅道研发事项与工时工作流.
17
+ │ └── at-zentao/ # 自包含的禅道研发事项与任务生命周期工作流.
18
18
  ├── docs/ # 高级指南和贡献者参考.
19
19
  ├── tools/ # 仅供维护者使用的上游同步和仓库工具.
20
20
  └── scripts/ # 安装, 同步, 校验和仓库维护脚本.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kairyou/agent-tools",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "Reusable Agent Skills, plus runtime capabilities (statusline, provider usage, vision) for Codex, Claude Code, and opencode.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: at-zentao
3
- description: "Work ZenTao bugs/tasks end to end, log task hours, or read a linked story as development context: fetch details, handle the user's request, verify changes, and ask before committing or writing back to ZenTao. Supports single items and sequential batches. Use when the user references ZenTao (禅道) bugs, tasks, stories, requirements, or task hours."
3
+ description: "Work ZenTao bugs/tasks end to end, manage task lifecycle and hours, or read a linked story as development context: fetch details, handle the user's request, verify changes, and ask before committing or writing back to ZenTao. Supports single items and sequential batches. Use when the user references ZenTao (禅道) bugs, tasks, stories, requirements, task status, or task hours."
4
4
  argument-hint: "bug <id> [request] | task <id> [request] | story <id> | bugs | tasks | export bug|task <id>"
5
5
  ---
6
6
 
@@ -85,6 +85,9 @@ confirmation steps below:
85
85
  node <skill-root>/scripts/zentao-cli.mjs comment bug <id>
86
86
  node <skill-root>/scripts/zentao-cli.mjs comment task <id>
87
87
  node <skill-root>/scripts/zentao-cli.mjs resolve bug <id>
88
+ node <skill-root>/scripts/zentao-cli.mjs start task <id>
89
+ node <skill-root>/scripts/zentao-cli.mjs pause task <id>
90
+ node <skill-root>/scripts/zentao-cli.mjs resume task <id>
88
91
  node <skill-root>/scripts/zentao-cli.mjs log-hours task <id>
89
92
  node <skill-root>/scripts/zentao-cli.mjs finish task <id>
90
93
  ```
@@ -94,6 +97,7 @@ Input shapes:
94
97
  ```json
95
98
  {"comment":"Root cause and result."}
96
99
  {"resolution":"fixed","resolvedBuild":"trunk","comment":"Root cause and result, commit abc1234."}
100
+ {"realStarted":"2026-08-11 09:00:00","comment":"Started implementation."}
97
101
  {"date":"2026-08-11","consumed":2,"left":14,"work":"Implemented the first part of the task."}
98
102
  {"currentConsumed":1.5,"realStarted":"2026-08-11 09:00:00","finishedDate":"2026-08-11 10:30:00"}
99
103
  ```
@@ -101,6 +105,9 @@ Input shapes:
101
105
  For `duplicate`, also pass `"duplicateBug": <id>`. Send JSON through stdin,
102
106
  not as a command-line argument. The CLI handles UTF-8 form encoding and
103
107
  computes a task's total consumed hours from its current ZenTao value.
108
+ `start`, `pause`, and `resume` accept an optional `comment`; `start` also
109
+ accepts `realStarted` and otherwise uses the current time. The CLI preserves
110
+ the task's current hours when starting or resuming it.
104
111
  `log-hours` defaults `date` to today, requires positive remaining hours,
105
112
  and keeps the task open. Use `finish` when the task is complete.
106
113
 
@@ -116,10 +123,11 @@ and keeps the task open. Use `finish` when the task is complete.
116
123
  - `/at-zentao export bug <id>` or `export task <id>` — create a read-only,
117
124
  self-contained handoff bundle.
118
125
 
119
- Treat text after an item id as a natural-language request. Phrases such as
120
- `填工时`, `记录工时`, `log hours`, and `worklog` enter task time-entry mode;
121
- users do not need to know the internal `log-hours` CLI command. Reuse any date,
122
- hours, or work description already supplied instead of asking twice.
126
+ Treat text after an item id as a natural-language request. Recognize task
127
+ lifecycle requests such as `开始`, `暂停`, `继续`, `start`, `pause`, and
128
+ `resume`, and time-entry requests such as `填工时`, `记录工时`, `log hours`,
129
+ and `worklog`. Users do not need to know the internal CLI commands. Reuse any
130
+ date, hours, or work description already supplied instead of asking twice.
123
131
 
124
132
  If a list response includes pager data showing more items than returned, tell
125
133
  the user the shown and total counts. Do not silently imply the list is complete.
@@ -131,6 +139,14 @@ planning the implementation. Use its `spec` and `verify` fields to identify
131
139
  scope, acceptance criteria, constraints, and non-goals. Keep the Bug or Task as
132
140
  the unit of work: never change, close, activate, or comment on the Story.
133
141
 
142
+ For a Task in `wait`, offer `start` when the user is about to work on it. For a
143
+ Task in `pause`, offer `resume`; the CLI maps this to ZenTao's `restart`
144
+ operation. Invoke `pause` only when the user explicitly asks or confirms that
145
+ the work itself is paused; the end of a session or workday is not enough. These
146
+ are status writes, so show the transition and optional comment and obtain
147
+ explicit confirmation before invoking the CLI. Starting or resuming preserves
148
+ the current hours and never implies new consumed time.
149
+
134
150
  ## Per-item workflow
135
151
 
136
152
  Follow these steps in order:
@@ -175,6 +191,10 @@ collect `currentConsumed` and draft a `finish` write. Never infer consumed
175
191
  hours. Show all submitted values and require the same explicit ZenTao
176
192
  confirmation before either write.
177
193
 
194
+ When the user wants to record hours and pause, show both exact writes in one
195
+ confirmation, then run `log-hours` before `pause`. Stop if the hour write fails.
196
+ Do not add lifecycle support for `activate`, `cancel`, or `close`.
197
+
178
198
  ## Export mode
179
199
 
180
200
  Export is read-only and never fixes code, commits, or writes back:
@@ -534,6 +534,9 @@ function help() {
534
534
  zentao-cli.mjs get <bug|task|story> <id> [--download-dir <path>]
535
535
  zentao-cli.mjs resolve bug <id> # JSON on stdin
536
536
  zentao-cli.mjs comment <bug|task> <id> # {"comment":"..."} on stdin
537
+ zentao-cli.mjs start task <id> # JSON on stdin
538
+ zentao-cli.mjs pause task <id> # JSON on stdin
539
+ zentao-cli.mjs resume task <id> # JSON on stdin
537
540
  zentao-cli.mjs log-hours task <id> # JSON on stdin
538
541
  zentao-cli.mjs finish task <id> # JSON on stdin`;
539
542
  }
@@ -614,6 +617,59 @@ export async function run(argv, { env = process.env } = {}) {
614
617
  return legacyResult(response);
615
618
  }
616
619
 
620
+ if (["start", "pause", "resume"].includes(command)) {
621
+ if (args[0] !== "task") throw new CliError("usage_error", `${command} supports tasks only`);
622
+ const id = positiveId(args[1]);
623
+ const input = await readInput();
624
+ if (input.comment !== undefined && typeof input.comment !== "string") {
625
+ throw new CliError("usage_error", "comment must be a string when provided");
626
+ }
627
+ if (input.realStarted !== undefined && (
628
+ command !== "start" ||
629
+ typeof input.realStarted !== "string" ||
630
+ !input.realStarted.trim()
631
+ )) {
632
+ throw new CliError("usage_error", "realStarted is accepted only for start and must be a non-empty string");
633
+ }
634
+
635
+ const method = command === "resume" ? "restart" : command;
636
+ const route = `task-${method}-${id}.json`;
637
+ const form = decodeLegacy(await client.json(route));
638
+ const task = form?.task || form;
639
+ const fields = { comment: input.comment?.trim() };
640
+
641
+ if (command !== "pause") {
642
+ const consumed = Number(task?.consumed);
643
+ const left = Number(task?.left);
644
+ if (!Number.isFinite(consumed) || consumed < 0 || !Number.isFinite(left) || left <= 0) {
645
+ throw new CliError("response_error", "ZenTao task has no safe current consumed/left values for this transition");
646
+ }
647
+ const assignedTo = typeof task.assignedTo === "string" && task.assignedTo
648
+ ? task.assignedTo
649
+ : config.account;
650
+ const existingStarted = typeof task.realStarted === "string" &&
651
+ task.realStarted.trim() &&
652
+ !task.realStarted.startsWith("0000-00-00")
653
+ ? task.realStarted
654
+ : null;
655
+ Object.assign(fields, {
656
+ assignedTo,
657
+ consumed,
658
+ left,
659
+ realStarted: command === "start"
660
+ ? input.realStarted?.trim() || localDateTime()
661
+ : existingStarted || localDateTime(),
662
+ });
663
+ }
664
+
665
+ const response = await client.json(route, {
666
+ method: "POST",
667
+ headers: { "content-type": "application/x-www-form-urlencoded" },
668
+ body: formBody(fields),
669
+ });
670
+ return legacyResult(response);
671
+ }
672
+
617
673
  if (command === "log-hours") {
618
674
  if (args[0] !== "task") throw new CliError("usage_error", "log-hours supports tasks only");
619
675
  const id = positiveId(args[1]);