From e6fafd4132a821ac041c20f44de0b4399abbfddc Mon Sep 17 00:00:00 2001 From: Jeffery Date: Wed, 26 Aug 2026 10:47:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(report):=20=E6=96=B0=E5=A2=9E=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=97=A5=E8=AA=8C=E7=B8=BD=E7=B5=90=E6=8A=80=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What: 新增 jsc-log:report,把工作日誌總結成年報、月報、週報或日報,寫進 wiki REPORT_{HASH}。另加 tools/report-range.sh 算期間、tools/report-template.sh 解析範本,以及四份報表範本與報表目錄範本。 Why: worklog 只記單筆工作,累積起來沒有工具看得出一週或一個月做了什麼、什麼在卡。要總結只能自己翻頁面加總。 How: 期間換算交給系統的 date,不自己算閏年與週界;週次採 ISO-8601。範本解析採工作目錄優先,.jsc/templates/report-{period}.md 蓋過技能自帶的那份,專案要換格式不必改技能。資料讀 LOG_CONTENTS 列出的所有日誌頁,取工作日期落在期間內的條目,只加總條目真的寫了的數字。 Who: 工作日誌的期間總結。 --- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- README.md | 15 +++++++- plugin.json | 2 +- skills/report/SKILL.md | 59 ++++++++++++++++++++++++++++ templates/report-contents.md | 7 ++++ templates/report-daily.md | 27 +++++++++++++ templates/report-monthly.md | 48 +++++++++++++++++++++++ templates/report-weekly.md | 39 +++++++++++++++++++ templates/report-yearly.md | 54 ++++++++++++++++++++++++++ tools/report-range.sh | 75 ++++++++++++++++++++++++++++++++++++ tools/report-template.sh | 62 +++++++++++++++++++++++++++++ 12 files changed, 388 insertions(+), 4 deletions(-) create mode 100644 skills/report/SKILL.md create mode 100644 templates/report-contents.md create mode 100644 templates/report-daily.md create mode 100644 templates/report-monthly.md create mode 100644 templates/report-weekly.md create mode 100644 templates/report-yearly.md create mode 100755 tools/report-range.sh create mode 100755 tools/report-template.sh diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index a23d9eb..8e9831c 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-log", - "version": "0.0.9", + "version": "0.1.0", "description": "工作日誌(LOG_{HASH} wiki 頁)、技能使用統計與教訓紀錄(LEARN_{HASH} wiki 頁)", "skills": "./skills", "author": { diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 4e99326..6fe7423 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-log", - "version": "0.0.9", + "version": "0.1.0", "description": "工作日誌(LOG_{HASH} wiki 頁)、技能使用統計與教訓紀錄(LEARN_{HASH} wiki 頁)", "skills": "./skills" } diff --git a/README.md b/README.md index 86439b0..aa6b9da 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安 | `tools/usage-stats.sh` | 聚合 `$JSC_HOME/usage/*.jsonl`:`skills` 列技能使用次數、`chains` 列呼叫鏈次數(皆降冪),`--cli ` 過濾 | | `tools/worklog-target.sh` | 接收已由 `jsc-gitea/tools/hash-id` 算好的 `HASH`,組出 `LOG_{HASH}`、`LOG_CONTENTS`(本身不再計算 SHA-1) | | `tools/worklog-pending.sh` | 待寫入日誌的暫存區,存放於 `$JSC_HOME/worklog-pending/{HASH}/`。`add {HASH} {檔案}` 存一段內容(`jsc-sdlc` 的階段回報發現沒寫日誌時會呼叫),`cat {HASH}` 依時間印出全部、`list` 列路徑、`clear` 清除。結束碼 `3` 代表沒有暫存內容。**寫進 wiki 成功之後才 clear**,先清再寫會兩邊都沒有 | +| `tools/report-range.sh` | 算報表期間:`report-range.sh {daily\|weekly\|monthly\|yearly} [yyyy-MM-dd]` 印出「起訖標籤期間」,含頭含尾。週採 ISO-8601(週一起算),標籤如 `2026-W35`。日期運算交給系統的 `date`,不自己算閏年 | +| `tools/report-template.sh` | 解析報表範本位置:`resolve {period}` 印出「路徑project\|skill」,`list` 一次列四種期間。工作目錄的 `.jsc/templates/report-{period}.md` 優先於技能自帶的 `templates/` | | `tools/token-usage.sh` | 讀單一 CLI 這次工作的 token 用量,印出「input(tab)output」;來源讀不到就印「N/A(tab)N/A」並正常結束。第二個參數傳 session id,就只讀該階段的 transcript,數字才會跟花費時間對得上。各 CLI 的取得方式寫在腳本開頭註解 | ## Skills 目錄 @@ -45,6 +47,10 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安 技能執行後把教訓(日期、技能、CLI、情境、教訓、下次做法)附加到 `LEARN_{HASH}` 並更新 `LEARN_CONTENTS`;技能執行前查閱同兩頁,套用相符的「下次做法」。 +### `report` + +把工作日誌總結成年報、月報、週報或日報。期間由 `tools/report-range.sh` 算出(週次採 ISO-8601),範本由 `tools/report-template.sh` 解析——工作目錄的 `.jsc/templates/report-{period}.md` 優先,沒有才用技能自帶的那份。讀 `LOG_CONTENTS` 列出的所有日誌頁,取工作日期落在期間內的條目,統計條目數、涵蓋存取庫、花費時間、token 用量、困難與未結項目,填進範本後寫入 wiki `REPORT_{HASH}`(`HASH` 取 `{owner}/{repo}/{期間}`),同一期間重跑只換掉那一節。單筆工作紀錄請用 `worklog`。 + ## 範本 @@ -55,10 +61,17 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安 | `templates/log-contents.md` | 日誌目錄 `LOG_CONTENTS` | | `templates/learn-page.md` | 教訓紀錄頁 `LEARN_{HASH}`(六欄表格,逐列附加) | | `templates/learn-contents.md` | 教訓目錄 `LEARN_CONTENTS` | +| `templates/report-daily.md` | 日報:當天產出、卡住的地方、明天接著做 | +| `templates/report-weekly.md` | 週報:本週產出、用時分布、困難與解法、滾到下週的項目 | +| `templates/report-monthly.md` | 月報:本月成果、逐週推進、重複出現的困難、月底未結 | +| `templates/report-yearly.md` | 年報:全年總覽、逐月推進、里程碑、全年教訓、年底未結 | +| `templates/report-contents.md` | 報表目錄 `REPORT_CONTENTS` | + +工作目錄放一份同名的 `.jsc/templates/report-{period}.md`,就會蓋過技能自帶的範本,不必改技能。 ## 環境變數 -Wiki 位置:日誌頁用 `JSC_WIKI_REPO_LOG`、教訓頁用 `JSC_WIKI_REPO_LEARN`,未設定退回 `JSC_WIKI_REPO`,再未設定就詢問(見 `jsc-gitea`)。先讀目前 shell 繼承的環境變數,缺值才詢問。 +Wiki 位置:日誌頁用 `JSC_WIKI_REPO_LOG`、教訓頁用 `JSC_WIKI_REPO_LEARN`、報表頁用 `JSC_WIKI_REPO_REPORT`,未設定退回 `JSC_WIKI_REPO`,再未設定就詢問(見 `jsc-gitea`)。先讀目前 shell 繼承的環境變數,缺值才詢問。 ## 相關 domain diff --git a/plugin.json b/plugin.json index 1c557aa..23bced9 100644 --- a/plugin.json +++ b/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-log", - "version": "0.0.9", + "version": "0.1.0", "description": "工作日誌(LOG_{HASH} wiki 頁)、技能使用統計與教訓紀錄(LEARN_{HASH} wiki 頁)", "skills": "./skills/" } diff --git a/skills/report/SKILL.md b/skills/report/SKILL.md new file mode 100644 index 0000000..48839cd --- /dev/null +++ b/skills/report/SKILL.md @@ -0,0 +1,59 @@ +--- +name: report +description: Summarise work logs into a yearly, monthly, weekly or daily report. Resolve the period with tools/report-range.sh, resolve the template with tools/report-template.sh - a project's .jsc/templates/report-{period}.md wins over the skill's own copy - then read every log page listed in LOG_CONTENTS and keep the entries dated inside the range. Fill the template with real aggregates (entry count, repositories, elapsed time, token usage, blockers, carry-overs) and write it to wiki REPORT_{HASH}, hashed from {owner}/{repo}/{period}, appending the period as a new section. Use when someone asks for a work summary over a period; not for recording a single work package, which is jsc-log:worklog. +--- + +# report — summarise work logs by period + +Reading and aggregating the log pages **MUST run as a sub agent**: it reads every page in `LOG_CONTENTS` and only a handful of entries survive the date filter. Report content is written in Traditional Chinese (STE100). + +## 1. Period + +Ask for the period per the `jsc-ask:ask` rules when the caller did not name one: `daily`, `weekly`, `monthly`, `yearly`. Each option states what it covers. + +Run `tools/report-range.sh {period} [yyyy-MM-dd]` — it prints `{start}{end}{label}{period}`, both dates inclusive. The base date defaults to today; pass one to re-run an earlier period. + +Never work the dates out by hand. Week boundaries and month lengths are exactly where a hand-rolled range quietly loses a day. + +Done when start, end and label are known. + +## 2. Template + +Run `tools/report-template.sh resolve {period}` from the working directory. It prints `{path}{project|skill}`. + +`project` means the working directory holds `.jsc/templates/report-{period}.md` and that file wins. Say which source was used in the final report — the same period rendered from two different templates has to be traceable to the file that shaped it. + +Follow the template's headings and tables exactly, including ones with no data: an empty section stated as 無 is information, a silently dropped section is not. + +Done when the template path and its source are known. + +## 3. Collect + +Read `LOG_CONTENTS` through `jsc-gitea:wiki` (repo from `jsc-gitea/tools/gitea.sh wiki-repo LOG`), then read every log page it lists. Entries start with `## {yyyy-MM-dd HH:mm}`; keep those whose date falls within start and end. + +Aggregate from the entry tables: entry count, distinct repositories, elapsed time, token usage per CLI, task status counts, blockers, unfinished work packages. Sum only what the entries state — an entry with no 花費時間 stays out of the total and is reported as 無資料 rather than estimated. + +A yearly report also reads `LEARN_CONTENTS` for its 全年教訓 section; other periods skip it. + +Zero entries in range → produce the report anyway, with counts of 0 and a line saying which range came back empty. A silent "no report" cannot be told apart from a failure. + +Done when every log page in the directory has been read and the aggregates are computed. + +## 4. Write + +Write through `jsc-gitea:wiki`: + +- Repo: `gitea.sh wiki-repo REPORT`. +- Page: `REPORT_` plus `gitea.sh hash-id "{owner}/{repo}/{period}"`, where `{owner}/{repo}` is the REPORT wiki repo. Year, month, week and day each get their own page. +- Append this period as a new section, newest first. Rerunning the same period replaces that period's section only, leaving the other periods untouched. +- Refresh the page's row in `REPORT_CONTENTS` from `templates/report-contents.md`. + +`wiki-repo` exit 3 → print the finished report and say the write was skipped because no wiki repo is configured for REPORT. The report itself is still the deliverable. + +Done when the page URL is reported, or the skipped write is reported with its reason. + +## 5. Close + +State the period label, entry count, repositories covered, template source, and the page URL. Name every unfinished work package that carried over — that list is what the next period starts from. + +Done when those five facts and the carry-over list are stated. diff --git a/templates/report-contents.md b/templates/report-contents.md new file mode 100644 index 0000000..1322a73 --- /dev/null +++ b/templates/report-contents.md @@ -0,0 +1,7 @@ +# 報表目錄 + +> 由 `jsc-log:report` 維護。年、月、週、日各一頁;`HASH` 取 `{owner}/{repo}/{期間}`,算法與其他頁面共用。 + +| 報表頁 | 期間 | 最新一期 | 期數 | 最後更新 | +| --- | --- | --- | --- | --- | +| [[REPORT_{HASH}]] | {daily、weekly、monthly、yearly 四選一} | {最新一期的標籤} | {n} | {yyyy-MM-dd HH:mm} | diff --git a/templates/report-daily.md b/templates/report-daily.md new file mode 100644 index 0000000..d5f958c --- /dev/null +++ b/templates/report-daily.md @@ -0,0 +1,27 @@ +# 日報 {yyyy-MM-dd} + +> 由 `jsc-log:report` 產生。資料來源:`LOG_CONTENTS` 列出的所有工作日誌頁,取工作日期落在 {yyyy-MM-dd} 當天的條目。 +> 專案要自訂格式,在工作目錄放一份 `.jsc/templates/report-daily.md` 就會蓋過這一份。 + +- 期間:{yyyy-MM-dd}(含) +- 條目數:{n} +- 涵蓋存取庫:{n} +- 花費時間合計:{h} 小時 {m} 分 + +## 今天做完什麼 + +| 存取庫 | 工作包 | 摘要 | 狀態 | 花費時間 | +| --- | --- | --- | --- | --- | +| {owner}/{repo} | [WP-{編號}]({ANALYZE 頁絕對網址}#wp-{編號}) | {一句話} | {完成、部分完成、阻塞} | {h}h{m}m | + +## 卡住的地方 + +| 存取庫 | 困難 | 目前處置 | 還缺什麼 | +| --- | --- | --- | --- | +| {owner}/{repo} | {困難} | {已做的處置} | {待解} | + +> 沒有阻塞項目時,整張表寫一列「無」。 + +## 明天接著做 + +- {下一步,取自未完成條目的剩餘 todo} diff --git a/templates/report-monthly.md b/templates/report-monthly.md new file mode 100644 index 0000000..d91668c --- /dev/null +++ b/templates/report-monthly.md @@ -0,0 +1,48 @@ +# 月報 {yyyy-MM} + +> 由 `jsc-log:report` 產生。資料來源:`LOG_CONTENTS` 列出的所有工作日誌頁,取工作日期落在 {start} 到 {end} 之間的條目。 +> 專案要自訂格式,在工作目錄放一份 `.jsc/templates/report-monthly.md` 就會蓋過這一份。 + +- 期間:{start} 到 {end} +- 條目數:{n} +- 涵蓋存取庫:{n} +- 花費時間合計:{h} 小時 {m} 分 +- token 用量合計:{CLI}: {input}/{output} + +## 本月成果 + +| 存取庫 | 完成工作包 | 部分完成 | 阻塞 | 花費時間 | +| --- | --- | --- | --- | --- | +| {owner}/{repo} | {n} | {n} | {n} | {h}h{m}m | + +## 逐週推進 + +```mermaid +xychart-beta + title "每週花費時間(小時)" + x-axis [{yyyy}-W{ww}, {yyyy}-W{ww}, {yyyy}-W{ww}, {yyyy}-W{ww}] + y-axis "小時" 0 --> {上限} + bar [{h}, {h}, {h}, {h}] +``` + +| 週次 | 條目數 | 完成 | 花費時間 | 主要進展 | +| --- | --- | --- | --- | --- | +| {yyyy}-W{ww} | {n} | {n} | {h}h{m}m | {一句話} | + +## 重複出現的困難 + +> 同一類困難出現兩次以上才列進來。只出現一次的留在週報,不往上滾。 + +| 困難 | 出現次數 | 影響存取庫 | 根因 | 對策 | +| --- | --- | --- | --- | --- | +| {困難} | {n} | {owner}/{repo} | {根因} | {對策} | + +## 月底未結 + +| 存取庫 | 工作包 | 狀態 | 卡多久 | 下一步 | +| --- | --- | --- | --- | --- | +| {owner}/{repo} | WP-{編號} | {部分完成、阻塞} | {n} 天 | {下一步} | + +## 下月重點 + +- {下一批工作包或維護項目} diff --git a/templates/report-weekly.md b/templates/report-weekly.md new file mode 100644 index 0000000..bde0301 --- /dev/null +++ b/templates/report-weekly.md @@ -0,0 +1,39 @@ +# 週報 {yyyy}-W{ww} + +> 由 `jsc-log:report` 產生。資料來源:`LOG_CONTENTS` 列出的所有工作日誌頁,取工作日期落在 {start} 到 {end} 之間的條目。 +> 週次採 ISO-8601,週一起算、週日結束。專案要自訂格式,在工作目錄放一份 `.jsc/templates/report-weekly.md` 就會蓋過這一份。 + +- 期間:{start} 到 {end} +- 條目數:{n} +- 涵蓋存取庫:{n} +- 花費時間合計:{h} 小時 {m} 分 +- token 用量合計:{CLI}: {input}/{output} + +## 本週產出 + +| 存取庫 | 工作包 | 摘要 | 狀態 | 花費時間 | PR | +| --- | --- | --- | --- | --- | --- | +| {owner}/{repo} | [WP-{編號}]({ANALYZE 頁絕對網址}#wp-{編號}) | {一句話} | {完成、部分完成、阻塞} | {h}h{m}m | [{base 分支}]({PR URL}) | + +## 各存取庫用時分布 + +```mermaid +pie title 本週花費時間(分鐘) + "{owner}/{repo}" : {分鐘} +``` + +## 困難與解法 + +| 困難 | 解決方式 | 是否已解 | +| --- | --- | --- | +| {困難} | {解法} | {是、否} | + +## 未完成,滾到下週 + +| 存取庫 | 工作包 | 剩下什麼 | 阻塞原因 | +| --- | --- | --- | --- | +| {owner}/{repo} | WP-{編號} | {剩餘 todo} | {原因,無阻塞寫「無」} | + +## 下週重點 + +- {取自未完成條目與計畫頁的下一批工作包} diff --git a/templates/report-yearly.md b/templates/report-yearly.md new file mode 100644 index 0000000..38bcee6 --- /dev/null +++ b/templates/report-yearly.md @@ -0,0 +1,54 @@ +# 年報 {yyyy} + +> 由 `jsc-log:report` 產生。資料來源:`LOG_CONTENTS` 列出的所有工作日誌頁,取工作日期落在 {start} 到 {end} 之間的條目。 +> 專案要自訂格式,在工作目錄放一份 `.jsc/templates/report-yearly.md` 就會蓋過這一份。 + +- 期間:{start} 到 {end} +- 條目數:{n} +- 涵蓋存取庫:{n} +- 花費時間合計:{h} 小時 +- token 用量合計:{CLI}: {input}/{output} + +## 全年總覽 + +| 存取庫 | 完成工作包 | 花費時間 | 佔比 | 最後一次動工 | +| --- | --- | --- | --- | --- | +| {owner}/{repo} | {n} | {h}h | {n}% | {yyyy-MM-dd} | + +## 逐月推進 + +```mermaid +xychart-beta + title "每月完成工作包數" + x-axis [01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12] + y-axis "工作包" 0 --> {上限} + bar [{n}, {n}, {n}, {n}, {n}, {n}, {n}, {n}, {n}, {n}, {n}, {n}] +``` + +| 月份 | 條目數 | 完成 | 花費時間 | 主要里程碑 | +| --- | --- | --- | --- | --- | +| {yyyy-MM} | {n} | {n} | {h}h | {一句話} | + +## 全年里程碑 + +| 日期 | 存取庫 | 里程碑 | 交付文件 | +| --- | --- | --- | --- | +| {yyyy-MM-dd} | {owner}/{repo} | {里程碑} | [{DELIVER 頁名}]({絕對網址}) | + +## 全年教訓 + +> 取自 `LEARN_CONTENTS` 的教訓頁,只列同類重複三次以上、或造成整批工作停擺的那幾條。 + +| 教訓 | 出現次數 | 已改成什麼做法 | +| --- | --- | --- | +| {教訓} | {n} | {現行做法} | + +## 年底未結 + +| 存取庫 | 工作包 | 狀態 | 卡多久 | 打算怎麼處理 | +| --- | --- | --- | --- | --- | +| {owner}/{repo} | WP-{編號} | {部分完成、阻塞} | {n} 天 | {處理方式} | + +## 明年方向 + +- {取自計畫頁尚未動工的使用者故事} diff --git a/tools/report-range.sh b/tools/report-range.sh new file mode 100755 index 0000000..ae87c44 --- /dev/null +++ b/tools/report-range.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env sh +# report-range.sh — 算出報表期間的起訖日期與標籤(供 jsc-log:report 呼叫)。 +# 用法: +# report-range.sh {daily|weekly|monthly|yearly} [基準日期 yyyy-MM-dd] +# 基準日期省略時用今天。輸出一行 TSV: +# {start}{end}{label}{period} +# start、end 皆為 yyyy-MM-dd,含頭含尾。 +# label:daily=2026-08-26、weekly=2026-W35、monthly=2026-08、yearly=2026 +# +# 週的定義採 ISO-8601:週一起算、週日結束,標籤用 ISO 週次。worklog 頁內以工作週的 +# 週五整理內容,週次與那個週五落在同一週,兩邊對得起來。 +# +# 日期運算優先用 GNU date -d,退回 BSD date -v。兩者都不支援就 exit 4,不自己算閏年: +# 手刻日期運算出錯的方式很安靜,報表會少算一天而沒有人發現。 +# +# 結束碼: 0=成功 2=用法錯誤 4=系統的 date 不支援日期運算 +set -eu + +usage() { + echo "用法:report-range.sh {daily|weekly|monthly|yearly} [yyyy-MM-dd]" >&2 + exit 2 +} + +period="${1:-}" +case "$period" in daily|weekly|monthly|yearly) ;; *) usage ;; esac + +base="${2:-}" +if [ -z "$base" ]; then + base=$(date +%Y-%m-%d) +else + case "$base" in + [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]) ;; + *) echo "基準日期格式要是 yyyy-MM-dd:$base" >&2; exit 2 ;; + esac +fi + +# $1=基準日 $2=偏移(例 -3 days、+1 month)$3=輸出格式 +shift_date() { + if date -d "$1 $2" "+$3" >/dev/null 2>&1; then + date -d "$1 $2" "+$3" + return 0 + fi + # BSD:偏移寫法不同(-v-3d),只轉換這裡真的用到的幾種 + _bsd=$(printf '%s' "$2" | sed 's/ days\{0,1\}/d/; s/ months\{0,1\}/m/; s/ years\{0,1\}/y/; s/^+/+/') + if date -j -f %Y-%m-%d -v"$_bsd" "$1" "+$3" >/dev/null 2>&1; then + date -j -f %Y-%m-%d -v"$_bsd" "$1" "+$3" + return 0 + fi + echo "系統的 date 不支援日期運算,算不出報表期間" >&2 + exit 4 +} + +fmt() { shift_date "$1" "+0 days" "$2"; } + +case "$period" in + daily) + start="$base"; end="$base" + label=$(fmt "$base" %Y-%m-%d) ;; + weekly) + # ISO 週:週一為第 1 天。%u 給 1(週一)到 7(週日)。 + dow=$(fmt "$base" %u) + start=$(shift_date "$base" "-$((dow - 1)) days" %Y-%m-%d) + end=$(shift_date "$start" "+6 days" %Y-%m-%d) + label=$(fmt "$base" %G-W%V) ;; + monthly) + start=$(fmt "$base" %Y-%m-01) + end=$(shift_date "$(shift_date "$start" "+1 month" %Y-%m-%d)" "-1 day" %Y-%m-%d) + label=$(fmt "$base" %Y-%m) ;; + yearly) + start=$(fmt "$base" %Y-01-01) + end=$(fmt "$base" %Y-12-31) + label=$(fmt "$base" %Y) ;; +esac + +printf '%s\t%s\t%s\t%s\n' "$start" "$end" "$label" "$period" diff --git a/tools/report-template.sh b/tools/report-template.sh new file mode 100755 index 0000000..10a70b9 --- /dev/null +++ b/tools/report-template.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env sh +# report-template.sh — 解析報表範本的位置(供 jsc-log:report 呼叫)。 +# 用法: +# report-template.sh resolve {daily|weekly|monthly|yearly} [起始目錄] +# report-template.sh list [起始目錄] +# +# 解析順序:工作目錄的 .jsc/templates/report-{period}.md 優先,沒有才用技能自帶的 +# templates/report-{period}.md。專案要自訂報表格式時,放一份同名檔案就換掉範本, +# 不必改技能。起始目錄省略時用目前工作目錄。 +# +# 輸出(resolve):{絕對路徑}{project|skill} +# 輸出(list):每種期間一行 {period}{絕對路徑}{project|skill} +# +# 結束碼: 0=找到 2=用法錯誤 3=兩處都找不到範本(技能自帶的那份被刪了) +set -eu + +HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +SKILL_TPL=$(CDPATH= cd -- "$HERE/.." && pwd)/templates +TAB=$(printf '\t') + +usage() { + echo "用法:report-template.sh {resolve {daily|weekly|monthly|yearly} [起始目錄]|list [起始目錄]}" >&2 + exit 2 +} + +resolve_one() { # $1=period $2=起始目錄 + _p="$1"; _d="$2" + _proj="$_d/.jsc/templates/report-$_p.md" + if [ -f "$_proj" ]; then + printf '%s%s%s\n' "$_proj" "$TAB" project + return 0 + fi + _skill="$SKILL_TPL/report-$_p.md" + if [ -f "$_skill" ]; then + printf '%s%s%s\n' "$_skill" "$TAB" skill + return 0 + fi + return 3 +} + +cmd="${1:-}" +case "$cmd" in + resolve) + period="${2:-}" + case "$period" in daily|weekly|monthly|yearly) ;; *) usage ;; esac + dir="${3:-$PWD}" + dir=$(CDPATH= cd -- "$dir" 2>/dev/null && pwd) || { echo "找不到目錄:${3:-$PWD}" >&2; exit 2; } + resolve_one "$period" "$dir" || { + echo "找不到 report-$period.md:$dir/.jsc/templates/ 與 $SKILL_TPL 都沒有" >&2 + exit 3 + } ;; + list) + dir="${2:-$PWD}" + dir=$(CDPATH= cd -- "$dir" 2>/dev/null && pwd) || { echo "找不到目錄:${2:-$PWD}" >&2; exit 2; } + rc=0 + for p in daily weekly monthly yearly; do + out=$(resolve_one "$p" "$dir") || { printf '%s\t-\tmissing\n' "$p"; rc=3; continue; } + printf '%s\t%s\n' "$p" "$out" + done + exit "$rc" ;; + *) usage ;; +esac