Git Worklog
產生專案工作日誌(非個人報告),透過讀取指定時間範圍內每一天的真實 Git diff 和相關程式碼,然後在 .git-worklog/ 目錄下每天寫入一個 Markdown 檔案,並重新整理 .git-worklog/index.md,同時保留人工筆記。
確定性工作(日期計算、Git 收集、Markdown 檔案處理、預覽完整性)由 git-worklog CLI 和 scripts/ 目錄下的指令碼處理。判斷性工作(閱讀程式碼、判斷實際變更內容、撰寫摘要)則由你和每日子代理負責。永遠不要讓提交訊息取代閱讀 diff 的過程。
需要已安裝 python3 和 git,無需安裝其他套件。請從此目錄執行 CLI:python3 -m git_worklog <command>,執行指令碼則使用 python3 scripts/<name>.py。每個指令會向標準輸出列印一個 JSON 物件。退出碼 0 表示成功,1 表示執行時發現問題,2 表示無法執行。
0. 黃金規則
- 無參數則顯示選單並停止。 在使用者選定範圍之前,不要掃描 Git、啟動子代理或產生任何內容。
- 閱讀程式碼,而不只是訊息。 必須閱讀每個相關提交的實際修補程式碼和週遭程式碼脈絡。請參閱
references/code-analysis-rules.md。這也適用於報告模式:當某一天沒有工作日誌時,其提交訊息不能作為替代——應指出缺口並詢問。 - 整個專案,所有作者。 工作日誌始終儲存所有作者;切勿根據
git config user.name/email來過濾。報告模式可能根據作者過濾,但僅限於使用者明確指定人名時——切勿推測「我」是誰。 - 產生和補填的最大日曆天數為 30 天。 此上限可控制每日子代理的成本。報告模式僅讀取現有的每日檔案,不會啟動任何子代理,因此最多可讀取 90 天(
--max-days 90)。無論哪種情況,超過限制則應拒絕、顯示請求的天數,並要求使用者縮小範圍。切勿在未告知的情況下截斷。 - 務必先進行乾執行。 任何有效的請求都只會產生預覽。僅在使用者明確確認後才進行寫入。
- 每天一個檔案;索引用於導航。 每一天的檔案為
.git-worklog/days/<date>.md;重新分析某一天不會影響其他天的檔案。index.md會根據每日檔案重新建構。 - 永遠保留每一天檔案中的 MANUAL 區域和索引的 MANUAL 區域。
- 切勿執行
git add/commit/push/fetch/pull/checkout/switch/merge/rebase。
1. 觸發與無參數選單
由 /git-worklog 或自然語言的工作日誌請求觸發。
當以無有效參數呼叫時,請逐字列印此選單並等待——不要執行任何其他操作:
請選擇要整理的專案工作日誌範圍:
1. 今天
2. 指定日期
3. 最近 7 天
4. 最近 30 天
5. 自訂日期範圍
6. 今天,並包含尚未提交的異動
7. 自訂日期或範圍,並包含尚未提交的異動
日期範圍最多為 30 天。
所有操作都會先顯示 dry-run 預覽,不會直接修改專案檔案。
你可以直接輸入選項編號,或用自然語言回答,例如:
- 整理今天
- 整理 2026-07-01
- 整理最近 7 天
- 整理 2026-07-01 到 2026-07-10
- 整理今天並包含未提交異動
- 整理近 30 天
選項編號對應:1→今天,2→詢問日期,3→days=7,4→days=30,5→詢問起迄範圍,6→今天 + include_uncommitted,7→詢問日期/範圍 + include_uncommitted。
完整的選單、選項和確認處理:references/interaction-flow.md。
1a. 路由:產生或報告
兩種模式。在執行任何其他操作之前決定。
| 使用者想要 | 模式 | 前往位置 |
|---|---|---|
| 建構或填寫工作日誌本身——「整理今天」「整理最近 7 天」「補 7/1 的日誌」 | 產生(寫入) | 前往 §2 及後續章節 |
| 從歷史記錄中獲得答案——「整理上一週工作摘要」「整理 v1.0.1 CHANGELOG」「Daniel 上個月做了什麼」「目前有哪些技術債」 | 報告(唯讀) | 前往 references/report-mode.md |
區分方式:產生模式的產物是檔案;報告模式的產物是對話中的散文。「整理今天」想要一個每日檔案。「整理上一週的工作摘要」想要可以貼到狀態更新中的內容。當確實模稜兩可時,請詢問——不要憑猜測寫入檔案。
報告模式讀取現有的每日檔案加上 Git,不寫入任何內容,因此沒有乾執行或確認閘門。其唯一的寫入路徑是填補缺口,這將交回給 §§2–8 處理,僅針對那些日期,並包含乾執行和確認流程。
選單僅限於產生模式。 報告模式是透過自然語言或明確參數觸發的,永遠不會透過選項編號觸發——選單詢問的是「要建構哪個範圍」,這並非報告模式所要回答的問題。
2. 標準化輸入 → 標準參數
你(模型)需將自然語言轉換為標準參數;指令碼永遠不會解讀自由文字。標準參數:
date · days · from · to · include_uncommitted,以及捷徑 7d、30d 和單純的 YYYY-MM-DD。
- 「整理今天」→
date=<本地今天> - 「最近一週」→
days=7;「近一個月」→days=30(永遠是 30,不是該月的天數) - 「7 月 1 日到 7 月 10 日」→
from=2026-07-01 to=2026-07-10 - 「包含未提交 / 連 working tree 一起」→
include_uncommitted=true
模式 date / days / from+to 互斥。標準化案例:references/date-parameter-contract.md。
2a. 解析輸出語言(路線圖 §6.2)
這是你的職責,不是指令碼的。 優先順序最高的項目僅存在於此對話中——使用者要求了什麼、你正在使用什麼語言交談、主機設定了什麼。指令碼無法看到這些資訊,而 --language 就是你告訴它的方式。每次執行解析一次,並將相同的標籤用於各處。
優先順序,最高優先:
- 使用者在本次請求中要求的語言——「用英文整理」→
en。永遠勝出。 .git-worklog/config.json中專案的language,如果它不是auto的話。指令碼會自行讀取這個設定;請傳入--language auto並讓它們處理。- 你與此使用者交談所使用的語言,即主機的語言。 這是正常情況,也是一個實際的答案——請傳入它,並加上
--language-source agent-host。
然後也傳入 --language-source 說明是以上哪種情況,以便清單記錄原因,而不僅僅是內容:
| 你從何處解析出來 | --language-source |
|---|---|
| 使用者在本次請求中要求一種語言 | user-request |
| 此對話/主機的語言 | agent-host |
| 無需特別說明——讓設定和環境決定 | 省略,搭配 --language auto |
不要讓儲存庫來決定。 英文的提交訊息、英文的識別名稱、英文的註解和英文的 README 都不能決定任何事。一個完全使用英文的儲存庫,搭配一個 zh-TW 的對話,應產生 zh-TW 的工作日誌。不要「與程式碼庫匹配」,也不要將這份英文的 SKILL.md 解讀為提示。
不要從作業系統的地區設定推斷。 你是在一個代理主機上執行,而 --language 正是讓一個固定在 en_US 的容器不會覆蓋使用中文的發言的機制。指令碼不會為你查詢區域設定(§6.2.5);這是刻意的設計,不是需要填補的缺口。
如果某次執行的清單回傳 source: "fallback" 和一個 LANGUAGE_NOT_RESOLVED 警告,代表你未能傳入語言,而該次執行將以英文寫入。請以明確的 --language 重新執行,而不是接受這個結果(§6.2.14)——除非英文確實正確。
報告可能與工作日誌不同。 每日檔案是以產生它們的那次執行的語言寫入的;報告則是以提出請求時所使用的語言寫入的(§6.2.11)。讀取 zh-TW 的每日檔案並產生英文的發行說明是正確的,無需轉換磁碟上的任何內容。
切勿翻譯:檔案路徑、程式碼符號、提交雜湊值、API/類別/套件名稱、分支和問題參照,或 evidence[] 中的任何內容。歡迎在輸出語言中解釋某個術語,但不要重新命名它。
3. 驗證日期範圍(永遠優先)
python3 scripts/resolve_date_range.py <args> [--timezone <IANA>] [--today <YYYY-MM-DD>]
傳入標準參數,例如 --days 7、--date 2026-07-01、--from 2026-07-01 --to 2026-07-10,或捷徑如 7d。當請求包含未提交變更時,加上 --include-uncommitted。
- 若
ok:false,向使用者報告錯誤並停止。常見的錯誤碼:TOO_MANY_DAYS(顯示requested_days,要求縮小範圍)、ARG_CONFLICT、DAYS_OUT_OF_RANGE、INVALID_DATE、FROM_AFTER_TO、TO_WITHOUT_FROM。 - 若
ok:true,保留dates[](每個都有date、start、end半開放邊界)、timezone和timezone_source。如果timezone_source是system-offset(沒有 IANA 名稱),請告知使用者假設的偏移量,並提供設定選項。
時區優先順序和半開放 [00:00, next 00:00) 每日規則:references/date-parameter-contract.md。
4. 偵測儲存庫狀態
python3 scripts/collect_git_history.py --repo <root> --info-only
NOT_A_GIT_REPO→ 告訴使用者此目錄不是 Git 儲存庫並停止。- 記錄
root、branch(若為detached_head則為 null)、head/short_head、has_commits、dirty_worktree。這些資訊會顯示在乾執行摘要中。 - 空儲存庫(
has_commits:false):若include_uncommitted=false,則無可記錄的內容——請告知。若include_uncommitted=true,則僅分析工作目錄樹。
5. 每日分析——每個日期一個每日子代理
此部分由兩個指令界定。analyze prepare 決定必須分析什麼以及使用哪種語言;analyze collect 決定是否相信回傳的結果。介於兩者之間的所有事情——閱讀修補程式、理解程式碼、撰寫散文——都是你和子代理的責任。CLI 永遠不會執行這些操作,也不需要模型 API 金鑰。
5a. 準備執行(確定性,對整個範圍執行一次):
python3 -m git_worklog analyze prepare --repo <root> \
--from <first date> --to <last date> --timezone <tz> \
--language <tag|auto> --language-source <source> \
--provider <provider> --model-json '<model object>' \
[--include-uncommitted]
回傳 run_id、run_dir 和 tasks[]——每個日曆日一個項目,每個項目都有 manifest_path(要分析的內容)和 result_path(其分析結果必須寫入的位置)。請保留所有資訊。
--language 和 --language-source 來自 §2a。它們在此處解析一次,並標記在執行過程中的每個清單上:一個清單中的 language.resolved 是每個日期結果的檢查依據,不一致的日期會阻止整個執行流程。
使用 scripts/resolve_provider_model.py --host <anthropic|openai|google>(請參閱下方的模型表格)為整個執行流程解析一次<provider> 和 <model object>。model 是一個物件——{display_name, model_id},以及僅適用於 openai 的 reasoning_effort。
每個清單包含 file_groups(按實際工作區域分組)、required_context、analysis_rules、一個 large_day 標記(當該天工作量很大時,建議使用程式碼分析子代理)、parts_dir(分支部分的存放位置——絕不能放在每日結果的旁邊,請參閱下文)、required_commit_file_pairs(§5b)以及該日的作者資訊——authors[](不同的名稱,按首次出現順序)加上 commits[].author_name。你直接從這些資訊中呈現 參與者 行和每個 相關 commits 項目的作者;子代理永遠不會回傳歸屬資訊。
大型日的分支會將其每組部分寫入 parts_dir,而不是放在該日 result_path 旁邊。results/ 目錄存放執行流程的答案,而 collect 會因為任何它沒有要求但存在的檔案(unknown)而判定該次執行失敗——因此,一個分支產生了 result_path 的同級檔案,會阻礙它本來旨在使其易於處理的那一天。
修補程式不包含在清單中——子代理使用 git show 來讀取它們。
5b. 每個日期必須遵守的規定。 每個清單都列出 required_commit_file_pairs:該日觸及的每個(提交,檔案)配對,並標記為 required 或非 required。Required 意味著該日的分析必須說明該檔案的變更——在工作項目的 files[] 中提及它即可;evidence[] 的引用更強烈但非強制。只有原始碼檔案是 required 的;文件、設定檔、CI 設定檔、測試檔案、二進位檔案和已刪除的檔案會被列出但可豁免(已刪除的檔案已不在該提交的目錄樹中,因此無法被引用)。
如果分析從未提及某個 required 的檔案,該日期將在 §5d 判定為失敗。這並非吹毛求疵:一個曾被變更但從未被描述的檔案,可能從未被讀取過,而這在一個看起來很有信心的結果中是無法察覺的。
5c. 為每個日期啟動一個每日子代理,傳入其 manifest_path 及其 result_path。子代理必須讀取真實的 diff 和足夠的程式碼脈絡,確定當天結束時的狀態(一個當天新增但當天又還原的功能不是有效的變更),並將結構化 JSON 寫入該路徑(契約請見 references/subagent-contract.md),僅回覆 DONE——結果絕不作為回覆文字傳回,因為那會導致資料遺失或截斷(references/subagent-contract.md §6a)。它不得寫入工作日誌。沒有提交的日期仍需寫入 has_changes:false。
5d. 收集每日結果(確定性),在所有子代理完成後執行一次:
python3 -m git_worklog analyze collect --run-id <run_id> --repo <root>
此處不指定任何日期或語言:collect 會讀取該次執行自己的清單,因此不會因為指令行上漏掉某個日期而跳過檢查。它會報告:
complete/degraded/missing/invalid/unknown/failed_dates、results(日期 → 物件)、partial_run、escalation_suggested_dates。- 出現在
missing或invalid中的日期是失敗的日期,不是空的日期——切勿將其視為「沒發生任何事」,也切勿回退到其提交訊息。 unknown是該次執行從未要求過但存在的結果檔案。請勿合併它。partial_run:true預設會阻止應用程式修改(§9)。退出碼為1。
每個結果都會檢查以下三件事,任何一項不符合都會導致該日期失敗:
- 語言——標籤必須與其清單要求的語言一致。
- 證據準確性——每個條目都會根據它所引用的提交的目錄樹進行檢查:提交存在、檔案在該提交時存在、
symbol出現在檔案中、lines範圍在檔案內。一個子代理引用了一個名為migrate_directory的函數,但實際函數名是parse_legacy,這等於沒有提供任何可以遵循的資訊(#15)。在淺層克隆中,無法到達的提交會報告EVIDENCE_UNVERIFIABLE。
6. 乾執行:產生預覽
在 §5 完成後,在寫入任何內容之前,必須向使用者呈現乾執行摘要。
python3 scripts/build_preview.py --run-id <run_id> --repo <root>
這會建構一個包含以下內容的 Markdown 預覽區塊:
- 摘要行:日期範圍、時區、作者數量、總提交數、總變更檔案數、語言。
- 受影響的檔案:
收集到的 git 歷史記錄中的變更檔案列表(新增/修改/刪除),按群組或目錄排序。 - 每日摘要:對於每一天,顯示:
- 日期和作者
- 提交數量
- 高層級摘要(來自每日子代理的結果)
- 每個工作項目的簡短描述,包括關聯的檔案
- 任何警告或注意事項(例如,
large_day、EVIDENCE_UNVERIFIABLE)
- 最終摘要行:將要寫入的檔案、將要重新整理的索引、保留的 MANUAL 區域。
在呈現乾執行摘要後,等待使用者明確確認。使用者的回覆可能是:
- 「確認」或「寫入」→ 繼續前往 §7。
- 「修改範圍」或「調整參數」→ 返回 §2。
- 「取消」或「放棄」→ 停止。不要在未經明確同意的情況下寫入任何內容。
7. 寫入工作日誌
python3 scripts/write_worklog.py --run-id <run_id> --repo <root>
此指令會:
- 將每日結果寫入
.git-worklog/days/<date>.md。 - 重新整理
.git-worklog/index.md。 - 保留任何現有的 MANUAL 區域。
如果 --dry-run 被設定,它只會列印它將要執行的操作而不實際執行。實際執行時,它會報告:
written_days:已寫入的檔案數量。errors:任何寫入錯誤。
8. 錯誤處理與降級
- 部分執行(
partial_run:true):寫入只能在使用者明確允許的情況下發生。如果使用者允許,則僅寫入成功日期的檔案。失敗的日期將被記錄並跳過。 - 遺失的結果:當某個日期的結果遺失時,該日期將被記錄為失敗。不要使用提交訊息作為替代。
- 無效的結果:當結果的結構或內容無效時,該日期將被記錄為失敗。不要使用提交訊息作為替代。
- 未知的結果:當存在執行流程未要求的結果檔案時,它將被記錄為未知。不要合併它。
- 證據無法驗證:當由於淺層克隆或無法到達的提交而無法驗證證據時,該日期將被標記為可疑。向使用者報告此資訊。
9. 應用程式修改(僅限於完全成功的執行)
python3 scripts/apply_worklog.py --run-id <run_id> --repo <root>
此指令僅在執行流程完全成功(無 partial_run、無 missing、無 invalid)時才應被呼叫。它會:
- 將產生的工作日誌檔案放入
.git-worklog/目錄。 - 更新索引。
- 保留任何 MANUAL 區域。
如果 partial_run:true,則不應直接呼叫此指令。
10. 附加說明
- 語言解析:輸出語言始終根據 §2a 中定義的優先順序決定。永遠不要從程式碼庫或 OS 區域設定推斷。
- 時區處理:時區始終根據
resolve_date_range.py中定義的優先順序決定。如果無法取得 IANA 時區名稱,則假設系統偏移量。 - 證據驗證:所有證據都會根據實際的 Git 物件進行驗證。如果無法驗證,則會發出警告。
- MANUAL 區域:現有的 MANUAL 區域在每次寫入操作中都會被保留。
- 檔案結構:
.git-worklog/days/<date>.md:每日工作日誌。.git-worklog/index.md:工作日誌索引。.git-worklog/config.json:專案設定檔(可選)。