# Git Worklog

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-g761007-git-worklog-git-worklog`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [g761007](https://agentstack.voostack.com/s/g761007)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [g761007](https://github.com/g761007)
- **Source:** https://github.com/g761007/git-worklog/tree/main/git-worklog
- **Website:** https://github.com/g761007/git-worklog/releases/latest

## Install

```sh
agentstack add skill-g761007-git-worklog-git-worklog
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Git Worklog

Produce a **project** worklog (not a personal report) by reading the real Git
diffs and surrounding code for each day in a requested range, then write one
Markdown file per day under `.git-worklog/` and refresh `.git-worklog/index.md`,
while preserving human notes.

The deterministic work (date math, Git collection, Markdown surgery, preview
integrity) is done by the `git-worklog` CLI. The judgement work (reading code,
deciding what actually changed, writing the summary) is done by you and per-day
subagents. **Never let commit messages stand in for reading the diff.**

`python3` and `git` must be available; nothing needs installing. Run every
command as `python3 -m git_worklog ` from this directory. Each prints
one JSON object to stdout. Exit `0` means ok, `1` means it ran and found a
problem, `2` means it could not run.

**Use the CLI, never `scripts/`.** The `scripts/` directory holds thin
command-line shells over the same engine, kept for anyone who scripted against
them; they are not part of your flow and calling them will not give you a run id,
a preview, or anything you can apply.

---

## 0. Golden rules

- **No parameters → show the menu and stop.** Do not scan Git, spawn subagents,
  or generate anything until the user picks a range.
- **Read code, not just messages.** Every relevant commit's actual patch and the
  surrounding code context must be read. See `references/code-analysis-rules.md`.
  This holds in report mode too: where a day has no worklog, its commit messages
  are **not** a substitute — surface the gap and ask.
- **Whole project, every author.** The worklog always *stores* every author;
  never filter by `git config user.name/email`. Report mode may filter by author
  **only when the user names the person explicitly** — never infer who "我" is.
- **Max 30 calendar days for generation and backfill.** The cap bounds per-day
  subagent cost. Report mode only *reads* existing day files and spawns no
  subagents, so it reads up to 90 days (`--max-days 90`). Either way, over the
  limit → refuse, show the requested day count, ask the user to narrow. Never
  silently truncate.
- **Dry-run first, always.** Any valid request produces a preview only. Write
  only after the user explicitly confirms.
- **One file per day; the index is navigation.** Each day is
  `.git-worklog/days/.md`; re-analysing one day never touches another day's
  file. `index.md` is rebuilt from the day files.
- **Preserve every day's MANUAL region and the index MANUAL region, forever.**
- **Never run** `git add/commit/push/fetch/pull/checkout/switch/merge/rebase`.

---

## 1. Trigger & no-argument menu

Triggered by `/git-worklog` or natural-language worklog requests.

When invoked with **no usable arguments**, print this menu verbatim and wait —
do nothing else:

```
請選擇要整理的專案工作日誌範圍：

1. 今天
2. 指定日期
3. 最近 7 天
4. 最近 30 天
5. 自訂日期範圍
6. 今天，並包含尚未提交的異動
7. 自訂日期或範圍，並包含尚未提交的異動

日期範圍最多為 30 天。
所有操作都會先顯示 dry-run 預覽，不會直接修改專案檔案。

你可以直接輸入選項編號，或用自然語言回答，例如：
- 整理今天
- 整理 2026-07-01
- 整理最近 7 天
- 整理 2026-07-01 到 2026-07-10
- 整理今天並包含未提交異動
- 整理近 30 天
```

Option numbers map to: `1`→today, `2`→ask for a date, `3`→`days=7`,
`4`→`days=30`, `5`→ask for a from/to range, `6`→today + `include_uncommitted`,
`7`→ask for a date/range + `include_uncommitted`.

Full menu, option, and confirmation handling: `references/interaction-flow.md`.

---

## 1a. Route: generate or report

Two modes. Decide before doing anything else.

| The user wants | Mode | Goes to |
|---|---|---|
| The worklog itself built or filled in — 「整理今天」「整理最近 7 天」「補 7/1 的日誌」 | **Generate** (writes) | §2 onward |
| An **answer** drawn from the history — 「整理上一週工作摘要」「整理 v1.0.1 CHANGELOG」「Daniel 上個月做了什麼」「目前有哪些技術債」 | **Report** (read-only) | `references/report-mode.md` |

The tell: generate mode's product is **files**; report mode's product is **prose
in the conversation**. "整理今天" wants a day file. "整理上一週的工作摘要" wants
something to paste into a status update. When it is genuinely ambiguous, ask —
do not write files on a guess.

Report mode reads the existing day files plus Git, writes nothing, and therefore
has no dry-run or confirmation gate. Its one writing path is backfilling a gap,
which hands back to §§2–6 for just those dates, dry-run and confirmation
included.

**The menu is generate-only.** Report mode is reached by natural language or
explicit parameters, never by an option number — the menu asks "which range to
build", which is not the question report mode answers.

---

## 2. Normalise input → canonical parameters

You (the model) convert natural language into canonical parameters; the scripts
never interpret free text. Canonical parameters:

`date` · `days` · `from` · `to` · `include_uncommitted`, plus the shortcuts
`7d`, `30d`, and a bare `YYYY-MM-DD`.

- "整理今天" → `date=`
- "最近一週" → `days=7`; "近一個月" → `days=30` (always 30, never the month length)
- "7 月 1 日到 7 月 10 日" → `from=2026-07-01 to=2026-07-10`
- "包含未提交 / 連 working tree 一起" → `include_uncommitted=true`

Modes `date` / `days` / `from`+`to` are mutually exclusive. Normalisation cases:
`references/date-parameter-contract.md`.

---

## 2a. Resolve the output language (roadmap §6.2)

**This is your job, not the scripts'.** The top of the priority order lives only
in this conversation — what the user asked for, what language you are speaking,
what the host is set to. A script cannot see any of it, and `--language` is how
you tell it. Resolve **once per run** and thread the same tag everywhere.

Priority, highest first:

1. **What the user asked for in this request** — "用英文整理" → `en`. Always wins.
2. **The project's `language` in `.git-worklog/config.json`**, if it is not
   `auto`. The scripts read this themselves; pass `--language auto` and let them.
3. **The language you are conversing in with this user, i.e. the host's
   language.** This is the normal case and it is a real answer — pass it, with
   `--language-source agent-host`.

Then also pass `--language-source` saying which of those it was, so the manifest
records *why* and not merely what:

| You resolved it from | `--language-source` |
|---|---|
| The user asking for a language in this request | `user-request` |
| The language of this conversation / your host | `agent-host` |
| Nothing to say — let config and env decide | omit, with `--language auto` |

**Do not let the repository choose.** English commit messages, English
identifiers, English comments and an English README decide nothing. A fully
English repo with a zh-TW conversation produces a zh-TW worklog. Do not "match
the codebase", and do not read this English SKILL.md as a hint.

**Do not infer from the OS locale.** You are an agent-hosted run, and
`--language` is exactly the mechanism that keeps a container pinned to `en_US`
from overriding a user speaking Chinese. The scripts will not consult the locale
for you (§6.2.5); that is deliberate, not a gap to fill.

If a run's manifest comes back with `source: "fallback"` and a
`LANGUAGE_NOT_RESOLVED` warning, you failed to pass a language and the run is
about to be written in English. **Re-run with an explicit `--language` rather
than accepting it** (§6.2.14) — unless English is genuinely right.

**Reports may differ from the worklog.** Day files are written in the language
of the run that produced them; a report is written in the language of the
request that asks for it (§6.2.11) — pass it to `report --language`, resolved the
same way as §2a. Reading zh-TW day files and producing an English release note is
correct and needs no conversion of anything on disk.

**Never translate**: file paths, code symbols, commit hashes, API/class/package
names, branch and issue references, or anything in `evidence[]`. Explaining a
term in the output language is welcome; renaming it is not.

---

## 3. Per-day analysis — one Day Subagent per day

Two commands bracket this section. `analyze prepare` decides **what** must be
analysed and **in which language**; `analyze collect` decides whether to
**believe** what came back. Everything between them — reading the patches,
understanding the code, writing the prose — is yours and the subagents'. The CLI
never does it and needs no model API key.

The field-by-field detail of what these commands emit — every output key, the
manifest contents, the error codes, the check mechanics — is in
`references/analysis-pipeline.md`. What must reach you *inline* is here.

**3a. Prepare the run** (deterministic, once for the whole range):

```
python3 -m git_worklog analyze prepare  --repo  \
    --host  \
    --language  --language-source  \
    [--timezone ] [--include-uncommitted]
```

- **`` is what the user said, verbatim** — a shortcut like `7d`, or
  `--date` / `--days` / `--from`+`--to`. Do **not** resolve the dates yourself;
  prepare answers, and its `range` block is what you show in the dry-run.
- **Do not compute a model.** `--host` is the host you run under (Claude Code →
  `anthropic`, Codex → `openai`, Gemini → `google`); prepare resolves the model
  from the packaged config. Never guess the host; if you cannot tell, ask. If the
  model is unavailable it returns `MODEL_UNAVAILABLE` — **halt and ask**, never
  silently pick another. Details: `references/provider-models.md`.
- **`--language` / `--language-source` come from §2a**, resolved once and stamped
  on every manifest — a day whose result disagrees blocks the whole run.
- Keep `run_id`, `run_dir`, and every `tasks[]` entry (each carries a
  `manifest_path` and a `result_path`).
- On `ok:false`, report the error and stop (code table:
  `references/analysis-pipeline.md` §3).

**A `LARGE_DAY` warning means stop and ask before dispatching that day.** It
carries the commit, file and group counts and the resolved model, because one
subagent on the cheap model may not hold a big day. Offer to fan it out into the
recommended Code Analysis Subagents, to escalate the model (`--host … --escalate`,
redo `prepare`), or to proceed as-is — the same surface-and-ask you use for a gap
or an over-30-day range. Do not decide silently: a large day that ran anyway on
the cheap model is exactly the run that came back confidently wrong and nothing
noticed. The counts are there so a 60-file day and a 26-file one are not the same
question; proceeding is a legitimate answer, an unasked question is not.

**3b. Coverage.** Each manifest's `required_commit_file_pairs` marks the source
files the day's analysis **must account for** — naming one in a work item's
`files[]` is enough. A required file the result never mentions fails the day at
collect: a file changed but never described may never have been read, and that is
invisible in a result that otherwise looks confident. Which files are required,
and why deletions and non-source files are excused:
`references/analysis-pipeline.md` §5.

**3c. Spawn one Day Subagent** per day, passing its `manifest_path` **and its
`result_path`**. The subagent reads the real diffs and enough code context,
determines the **end-of-day state** (a feature added then reverted the same day
is *not* a live change), and **writes** the structured JSON from
`references/subagent-contract.md` to that path, replying only `DONE` — results
are never passed back as reply text, which drops and truncates them (§6a). It
must not write to the worklog. Days with no commits still write
`has_changes:false`. A large day may fan out into Code Analysis Subagents grouped
by work area, each writing to the manifest's `parts_dir` — never beside
`result_path`, where `collect` would fail the run over it
(`references/subagent-contract.md`).

**3d. Collect every day's result** (deterministic), once all subagents finish:

```
python3 -m git_worklog analyze collect --run-id  --repo 
```

It reads the run's own manifests, so no day can be dropped by being left off a
command line. Every result is checked three ways — **language**, **evidence and
prose symbols against the day's tree**, and **required-file coverage** — and each
failure fails the day. `partial_run:true` (any `missing`, `invalid`, `degraded`
or `unknown` date) blocks apply and exits `1`.

A failed or missing day is **not** an empty one: never treat it as "nothing
happened", never fall back to commit messages. Fix a failure by **re-running that
day's subagent** against the same manifest, then collecting again — never
hand-edit a result, never paper over a gap. Output fields and the check
mechanics: `references/analysis-pipeline.md` §6.

Model per host is resolved by `--host` (cost-first defaults, single source
`git_worklog/data/provider_models.json`); read `model` back off prepare's output.
Overrides, the per-host table, unavailable-model handling and opt-in escalation:
`references/provider-models.md`.

---

## 4. Uncommitted changes (only when include_uncommitted=true)

Pass `--include-uncommitted` to `analyze prepare` (§3a). It classifies
`staged` / `unstaged` / `untracked` (binary-aware), puts them on **today's**
manifest as `uncommitted_changes[]`, and returns a `worktree_fingerprint` on the
run.

Uncommitted content is attributed to **today only** — never spread across
historical days, because a file's mtime says when it was last written, not when
the work happened. In a multi-day range only today's task carries it; if today
is outside the range, prepare warns `UNCOMMITTED_NOT_IN_RANGE` rather than
silently dropping it. Present it in its own `### 尚未提交的異動` section, split
into staged / unstaged / untracked, and never describe it as committed.

---

## 5. Merge results, generate Markdown, dry-run

1. Merge the per-day results from `analyze collect` (§3d). If it reports any
   `missing`, `invalid`, `degraded` or `unknown` date — i.e. `partial_run` —
   mark the run **partial** and default to blocking apply (see error handling
   below).
2. Render each day's GENERATED Markdown from the day template in
   `references/worklog-format.md`, **in the run's resolved language** (§2a) —
   headings included. Omit empty sections — no walls of "無/N/A". Days with no
   changes get no file by default. Lead each day's summary with its single most
   useful sentence and **bracket it in SUMMARY markers**; that line becomes the
   index row, and without the markers a day written in anything but Traditional
   Chinese gets a blank one.
3. Hand the rendered days to `preview`, which freezes everything the apply will
   write. Pass only dates that actually have content:

```
git-worklog preview --run-id  --repo   --check` reports a stored preview's state; `--cancel ` retires
one the user decided against.

4. Show the dry-run summary (`references/interaction-flow.md` has the full
   layout). The load-bearing parts: the resolved range and timezone; the output
   **language** — and if it came from `fallback`, say so, because the user may
   want to correct it before anything is written; the subagent provider/model;
   each date's planned action (create / overwrite / no-change); the preserved
   MANUAL dates; every day file's full preview and the index preview; the
   `preview_id`; and the line **"No files have been modified."** If `not_written`
   is non-empty, say which dates and why — a day the user expected and does not
   get should not be discovered after the write.

---

## 6. Apply only after explicit confirmation

Natural-language confirmations ("寫入", "確認更新", "套用剛才的預覽", "把這份寫進去")
or `apply `.

1. Apply the preview. This is the whole step:

```
git-worklog apply --preview-id 
```

   **Do not pass the day content again — there is nowhere to pass it.** The
   record holds the exact bytes the user just approved, and apply writes those.
   Re-rendering, re-reading the results, or re-dispatching a subagent at this
   point would produce a worklog nobody previewed, which is precisely what the
   record exists to prevent.

   Apply re-checks the world first: repository identity, git dir, branch, HEAD,
   submodules, the working tree (when the run read it), every target day file,
   `index.md`, the day-file listing, the run's manifests and results, an

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [g761007](https://github.com/g761007)
- **Source:** [g761007/git-worklog](https://github.com/g761007/git-worklog)
- **License:** MIT
- **Homepage:** https://github.com/g761007/git-worklog/releases/latest

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-g761007-git-worklog-git-worklog
- Seller: https://agentstack.voostack.com/s/g761007
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
