time-report

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Time report

工时报告

Estimate active work time per ticket from conversation history. These estimates describe gaps between recorded messages, not continuous observation of the user. The default range is yesterday.
根据对话历史估算每个 ticket 的活跃工作时长。这些估算值描述的是已记录消息之间的间隔,并非对用户活动的连续观察。默认范围是昨天。

1. Scan the conversations

1. 扫描对话

First locate the user's transcript files. Check the agent's configuration, environment, and any paths the user supplied. Verify that the directories contain session JSONL files; do not assume the defaults exist or contain the history the user wants. If locations remain unknown, report which paths you checked and ask only for the missing location. Complete the report for sources you can read.
Run the scanner with Bun 1.4 or newer:
bash
bun <skill-dir>/scripts/scan-sessions.ts --since YYYY-MM-DD --until YYYY-MM-DD
Both dates are local midnights and
--until
is exclusive. With no flags it scans yesterday. Use the requested range, or yesterday even on weekends. State the dates in the report. Ask about the working calendar only when the requested range depends on it.
Likely locations, also used as the scanner defaults:
  • Claude Code:
    ~/.claude/projects/*/*.jsonl
  • Cursor:
    ~/.cursor/projects/*/agent-transcripts/**/*.jsonl
  • Codex:
    ~/.codex/sessions/**/*.jsonl
    and
    ~/.codex/archived_sessions/**/*.jsonl
  • Pi:
    ~/.pi/agent/sessions/**/*.jsonl
For files stored elsewhere, pass the verified directory with
--transcripts SOURCE=DIR
. This replaces the defaults for that source and searches the directory recursively. Repeat the option to include multiple directories, including any separate archive:
bash
bun <skill-dir>/scripts/scan-sessions.ts --since YYYY-MM-DD --until YYYY-MM-DD \
  --transcripts "codex=/path/to/sessions" --transcripts "pi=/another/path/sessions"
An empty result does not prove there was no activity. Confirm the locations and requested dates before drawing that conclusion.
Codex and Pi use the working directory in the session header as the project. It prints UTC timestamps in one JSON line per conversation with
source
,
project
,
file
,
start
,
end
,
active_seconds
,
first_prompt
,
tickets
with each key and its first mention time, and
pull_requests
.
Conversations with less than one minute of estimated activity are omitted. Use
--home PATH
to scan these paths under another home directory and
--gap-minutes N
to change the idle threshold. Bun downloads the pinned Zod dependency on first run. Later runs use its local cache.
Active time is the sum of the gaps between messages that are shorter than 15 minutes. Longer gaps count as time away. Cursor timestamps user messages to the minute. The scanner uses the last write time as the final edge when it follows those messages. It does not use filesystem creation times.
首先定位用户的对话记录文件。检查 agent 的配置、环境以及用户提供的所有路径。验证目录中是否包含 session JSONL 文件;不要默认默认路径存在,或默认路径中包含用户所需的历史记录。如果仍无法确定文件位置,请报告已检查的路径,并且只询问缺失的位置信息。对于能够读取的来源,完成相应报告。
使用 Bun 1.4 或更高版本运行扫描器:
bash
bun <skill-dir>/scripts/scan-sessions.ts --since YYYY-MM-DD --until YYYY-MM-DD
两个日期均为本地时间的午夜,且
--until
不包含在扫描范围内。不带参数运行时会扫描昨天的记录。使用用户要求的范围;如果未指定范围,即使在周末也使用昨天。应在报告中注明日期。仅当所请求的范围取决于工作日历时,才询问工作日历。
可能的位置如下,同时也是扫描器的默认路径:
  • Claude Code:
    ~/.claude/projects/*/*.jsonl
  • Cursor:
    ~/.cursor/projects/*/agent-transcripts/**/*.jsonl
  • Codex:
    ~/.codex/sessions/**/*.jsonl
    和
    ~/.codex/archived_sessions/**/*.jsonl
  • Pi:
    ~/.pi/agent/sessions/**/*.jsonl
对于存储在其他位置的文件,使用
--transcripts SOURCE=DIR
传入已验证的目录。该参数会替换对应来源的默认路径,并递归搜索该目录。可以重复使用此参数,以包含多个目录以及任何单独归档目录:
bash
bun <skill-dir>/scripts/scan-sessions.ts --since YYYY-MM-DD --until YYYY-MM-DD \
  --transcripts "codex=/path/to/sessions" --transcripts "pi=/another/path/sessions"
空结果并不能证明没有活动。在得出这一结论前,请确认文件位置和请求的日期。
Codex 和 Pi 使用 session 标头中的工作目录作为项目。扫描器会以每段对话一行 JSON 的形式输出 UTC 时间戳,其中包含
source
、
project
、
file
、
start
、
end
、
active_seconds
、
first_prompt
、
tickets
(包含每个 key 及其首次提及时间)以及
pull_requests
。
估算活动时间不足一分钟的对话会被省略。使用
--home PATH
可在另一个 home 目录下扫描这些路径,使用
--gap-minutes N
可更改空闲阈值。Bun 首次运行时会下载固定版本的 Zod 依赖项,后续运行则使用本地缓存。
活跃工作时长是所有短于 15 分钟的消息间隔之和。较长的间隔视为离开工作时间。Cursor 对用户消息的时间戳精确到分钟。扫描器在跟踪这些消息时,会将最后写入时间作为结束边界。它不会使用文件系统创建时间。

2. Attribute time to tickets

2. 将时长归因到 ticket

  • A conversation lists every ticket key it mentions, including keys it only read about. Open the transcript near each key's first mention and keep only the tickets the user actually worked on in that conversation (planned, implemented, opened or fixed a PR).
  • When one conversation covers several tickets, split its active time by the stretch spent on each ticket if the transcript makes that clear. If the split is unclear, keep the time unattributed and explain why. Do not turn a guess into billable hours.
  • Check for overlapping parent and subagent conversations. Count overlapping intervals once; a separate file or worktree does not establish separate human work time.
  • If a ticket has no conversation, say so. Don't invent time.
  • 一段对话会列出其中提到的每个 ticket key,包括仅被读取或讨论过的 key。打开每个 key 首次出现位置附近的对话记录,并且只保留用户在该对话中实际处理过的 ticket,包括规划、实现、创建 PR 或修复 PR。
  • 当一段对话涉及多个 ticket 时,如果对话记录能够清楚体现,可以按处理每个 ticket 所花费的时间段拆分活跃工作时长。如果无法清楚拆分,则将时长保留为未归因,并解释原因。不要将猜测转化为可计费工时。
  • 检查父对话与 subagent 对话之间是否存在重叠。重叠的时间区间只计算一次;单独的文件或 worktree 并不能证明存在独立的人工工作时长。
  • 如果某个 ticket 没有相关对话,请明确说明。不要虚构工作时长。

3. Look up PR state and waiting time

3. 查询 PR 状态和等待时间

For each ticket with a PR, get the open and merge times:
bash
gh pr view <number> --repo <owner/repo> --json createdAt,mergedAt,state
If GitHub access is unavailable, report the conversation estimates and say that PR state was not checked.
PR waiting time runs from open to merge. It is elapsed time, not work performed. Show it separately when useful. Do not add it to active work time or log it to Jira. Keep conversation activity after PR creation, since review fixes are work too.
对于每个关联了 PR 的 ticket,获取 PR 的创建时间和合并时间:
bash
gh pr view <number> --repo <owner/repo> --json createdAt,mergedAt,state
如果无法访问 GitHub,请报告对话估算结果,并说明未检查 PR 状态。
PR 等待时间从 PR 开放到合并。它是经过时间,并不代表实际完成的工作。必要时单独显示该时间,不要将其加入活跃工作时长,也不要记录到 Jira。PR 创建后产生的对话活动仍应保留,因为评审修复也属于工作。

4. Show the report

4. 展示报告

Show a table with the ticket, PR state, estimated active work time, and optional PR waiting time. Round displayed work estimates to minutes. Do not imply second-level accuracy from Cursor's minute-level timestamps.
Include unmatched conversations with their first prompts and estimated activity. Deliver the useful report without waiting for the user to classify every row. State any assumptions about overlapping sessions or ticket attribution.
Stop here unless the user asked to log the hours.
显示一个表格,包含 ticket、PR 状态、估算活跃工作时长,以及可选的 PR 等待时间。将展示的工作时长估算值四舍五入到分钟。不要根据 Cursor 精确到分钟的时间戳暗示秒级准确性。
包含未匹配到 ticket 的对话,并列出其首个 prompt 和估算活动时间。直接提供有用的报告,不要等待用户对每一行进行分类。说明有关重叠会话或 ticket 归因情况的任何假设。
除非用户要求记录工时,否则到此停止。

5. Log to Jira when asked

5. 按要求记录到 Jira

Use allocations and hours the user already approved. If the report introduced unapproved estimates or uncertain allocations, show the proposed entries and ask for those details before writing. Do not request the same approval twice. Jira access is required; if it is unavailable, return the report and identify what remains unlogged.
  • Log only the approved active work estimate, rounded to the nearest whole minute. Set
    started
    to the first activity.
  • Include a concise source and rounding note in the worklog description. Keep local transcript contents private. Do not add a separate ticket comment unless asked.
  • Move a ticket to Done only if its PR is merged and the user asked for that transition.
  • Check existing worklogs before writing. Skip entries that already match; update only entries covered by the request. After a failed write, read the remote state before retrying to avoid duplicates.
  • Verify the saved entries and report what was logged, skipped, or blocked. A successful tool call alone is not proof of the saved hours.
使用用户已经批准的工作分配和工时。如果报告中出现了未经批准的新估算值或不确定的工作分配,请先展示拟记录的条目,并就相关细节征求确认,然后再写入。不要重复请求同一次批准。需要具备 Jira 访问权限;如果无法访问,请返回报告,并明确指出哪些工时尚未记录。
  • 只记录已批准的活跃工作时长估算值,并四舍五入到最接近的整分钟。将
    started
    设置为首次活动时间。
  • 在 worklog 描述中加入简明的来源说明和舍入说明。保持本地对话记录的隐私。除非用户要求,否则不要单独添加 ticket 评论。
  • 仅当 PR 已合并且用户要求进行状态转换时,才将 ticket 移动到 Done。
  • 写入前检查已有的 worklog。跳过已经匹配的条目;只更新本次请求涵盖的条目。写入失败后,应先读取远程状态再重试,以避免产生重复记录。
  • 验证已保存的条目,并报告哪些内容已记录、已跳过或被阻止。工具调用成功本身并不能证明工时已经保存。