Git Worklog
Produisez un journal de travail projet (pas un rapport personnel) en lisant les diffs Git réels
et le code environnant pour chaque jour d'une plage demandée, puis écrivez un
fichier Markdown par jour sous .git-worklog/ et rafraîchissez .git-worklog/index.md,
tout en préservant les notes humaines.
Le travail déterministe (calculs de dates, collecte Git, édition Markdown, intégrité
des aperçus) est effectué par la CLI git-worklog et les scripts dans scripts/. Le
travail de jugement (lecture du code, décision de ce qui a réellement changé, rédaction
du résumé) est effectué par vous et les sous-agents par jour. Ne laissez jamais les messages de commit
remplacer la lecture du diff.
python3 et git doivent être disponibles ; rien n'a besoin d'être installé. Exécutez la CLI comme
python3 -m git_worklog <commande> et tout script comme python3 scripts/<nom>.py,
depuis ce répertoire. Chacun imprime un objet JSON sur stdout. Une sortie 0 signifie
ok, 1 signifie qu'il s'est exécuté et a trouvé un problème, 2 signifie qu'il n'a pas pu s'exécuter.
0. Règles d'or
- Aucun paramètre → afficher le menu et s'arrêter. Ne parcourez pas Git, ne lancez pas de sous-agents, et ne générez rien tant que l'utilisateur n'a pas choisi une plage.
- Lisez le code, pas seulement les messages. Le correctif réel de chaque commit pertinent et le
contexte de code environnant doivent être lus. Voir
references/code-analysis-rules.md. Cela s'applique également en mode rapport : là où un jour n'a pas de journal, ses messages de commit ne sont pas un substitut — signalez l'écart et demandez. - Projet entier, chaque auteur. Le journal stocke toujours tous les auteurs ;
ne filtrez jamais par
git config user.name/email. Le mode rapport peut filtrer par auteur uniquement lorsque l'utilisateur nomme la personne explicitement — n'inférez jamais qui "je" est. - Maximum 30 jours calendaires pour la génération et le remplissage. Le plafond limite le coût
des sous-agents par jour. Le mode rapport lit uniquement les fichiers jour existants et ne lance
aucun sous-agent, donc il lit jusqu'à 90 jours (
--max-days 90). Dans les deux cas, au-delà de la limite → refusez, affichez le nombre de jours demandé, demandez à l'utilisateur de réduire. Ne tronquez jamais silencieusement. - D'abord l'aperçu, toujours. Toute demande valide ne produit qu'un aperçu. Écrivez uniquement après confirmation explicite de l'utilisateur.
- Un fichier par jour ; l'index est un outil de navigation. Chaque jour est
.git-worklog/days/<date>.md; la réanalyse d'un jour ne touche jamais au fichier d'un autre jour.index.mdest reconstruit à partir des fichiers jour. - Préservez la région MANUAL de chaque jour et la région MANUAL de l'index, pour toujours.
- N'exécutez jamais
git add/commit/push/fetch/pull/checkout/switch/merge/rebase.
1. Déclencheur et menu sans argument
Déclenché par /git-worklog ou des demandes de journal en langage naturel.
Lorsqu'il est invoqué sans argument utilisable, imprimez ce menu textuellement et attendez — ne faites rien d'autre :
請選擇要整理的專案工作日誌範圍:
1. 今天
2. 指定日期
3. 最近 7 天
4. 最近 30 天
5. 自訂日期範圍
6. 今天,並包含尚未提交的異動
7. 自訂日期或範圍,並包含尚未提交的異動
日期範圍最多為 30 天。
所有操作都會先顯示 dry-run 預覽,不會直接修改專案檔案。
你可以直接輸入選項編號,或用自然語言回答,例如:
- 整理今天
- 整理 2026-07-01
- 整理最近 7 天
- 整理 2026-07-01 到 2026-07-10
- 整理今天並包含未提交異動
- 整理近 30 天
Les numéros d'options correspondent à : 1 → aujourd'hui, 2 → demander une date,
3 → days=7, 4 → days=30, 5 → demander une plage de dates,
6 → aujourd'hui + include_uncommitted, 7 → demander une date/plage + include_uncommitted.
Menu complet, options et gestion de la confirmation : references/interaction-flow.md.
1a. Acheminement : générer ou rapporter
Deux modes. Décidez avant de faire quoi que ce soit d'autre.
| L'utilisateur veut | Mode | Va vers |
|---|---|---|
| Le journal lui-même construit ou rempli — 「整理今天」「整理最近 7 天」「補 7/1 的日誌」 | Générer (écrit) | §2 et suivants |
| Une réponse tirée de l'historique — 「整理上一週工作摘要」「整理 v1.0.1 CHANGELOG」「Daniel 上個月做了什麼」「目前有哪些技術債」 | Rapport (lecture seule) | references/report-mode.md |
L'indicateur : le produit du mode génération est des fichiers ; le produit du mode rapport est du texte dans la conversation. "整理今天" veut un fichier jour. "整理上一週的工作摘要" veut quelque chose à coller dans une mise à jour de statut. Lorsque c'est vraiment ambigu, demandez — n'écrivez pas de fichiers en devinant.
Le mode rapport lit les fichiers jour existants plus Git, n'écrit rien, et donc n'a pas de porte d'aperçu ou de confirmation. Son seul chemin d'écriture est le remplissage d'un écart, qui repasse aux §§2–8 pour ces seules dates, aperçu et confirmation inclus.
Le menu est réservé à la génération. Le mode rapport est atteint par langage naturel ou paramètres explicites, jamais par un numéro d'option — le menu demande "quelle plage construire", ce qui n'est pas la question à laquelle le mode rapport répond.
2. Normaliser l'entrée → paramètres canoniques
Vous (le modèle) convertissez le langage naturel en paramètres canoniques ; les scripts n'interprètent jamais le texte libre. Paramètres canoniques :
date · days · from · to · include_uncommitted, plus les raccourcis
7d, 30d, et un simple YYYY-MM-DD.
- "整理今天" →
date=<aujourd'hui local> - "最近一週" →
days=7; "近一個月" →days=30(toujours 30, jamais la longueur du mois) - "7 月 1 日到 7 月 10 日" →
from=2026-07-01 to=2026-07-10 - "包含未提交 / 連 working tree 一起" →
include_uncommitted=true
Les modes date / days / from+to sont mutuellement exclusifs. Cas de
normalisation : references/date-parameter-contract.md.
2a. Résoudre la langue de sortie (feuille de route §6.2)
C'est votre travail, pas celui des scripts. Le sommet de l'ordre de priorité
n'existe que dans cette conversation — ce que l'utilisateur a demandé, dans quelle
langue vous parlez, ce dans quoi l'hôte est configuré. Un script ne peut rien voir
de tout cela, et --language est la façon dont vous le lui dites. Résolvez une
fois par exécution et transmettez la même balise partout.
Priorité, la plus haute d'abord :
- Ce que l'utilisateur a demandé dans cette requête — "用英文整理" →
en. Gagne toujours. languagedu projet dans.git-worklog/config.json, si ce n'est pasauto. Les scripts le lisent eux-mêmes ; passez--language autoet laissez-les faire.- La langue dans laquelle vous converse
ez avec cet utilisateur, c'est-à-dire la langue de l'hôte.
C'est le cas normal et c'est une vraie réponse — passez-la, avec
--language-source agent-host.
Puis passez aussi --language-source en disant laquelle de ces sources a été utilisée,
pour que le manifeste enregistre pourquoi et pas seulement quoi :
| Vous l'avez résolue depuis | --language-source |
|---|---|
| L'utilisateur demandant une langue dans cette requête | user-request |
| La langue de cette conversation / votre hôte | agent-host |
| Rien à dire — laissez le config et l'env décider | omettre, avec --language auto |
Ne laissez pas le dépôt choisir. Les messages de commit en anglais, les identifiants anglais, les commentaires anglais et un README anglais ne décident rien. Un dépôt entièrement anglais avec une conversation zh-TW produit un journal zh-TW. Ne "faites pas correspondre la base de code", et ne lisez pas ce SKILL.md anglais comme un indice.
N'inférez pas à partir des paramètres régionaux du système d'exploitation.
Vous êtes une exécution hébergée par un agent, et --language est exactement le
mécanisme qui empêche un conteneur réglé sur en_US de remplacer un utilisateur
parlant chinois. Les scripts ne consulteront pas les paramètres régionaux pour vous
(§6.2.5) ; c'est délibéré, pas une lacune à combler.
Si le manifeste d'une exécution revient avec source: "fallback" et un
LANGUAGE_NOT_RESOLVED d'avertissement, vous n'avez pas réussi à passer une langue
et l'exécution est sur le point d'être écrite en anglais. Réexécutez avec un
--language explicite plutôt que de l'accepter (§6.2.14) — sauf si l'anglais est
vraiment correct.
Les rapports peuvent différer du journal. Les fichiers jour sont écrits dans la langue de l'exécution qui les a produits ; un rapport est écrit dans la langue de la requête qui le demande (§6.2.11). Lire des fichiers jour zh-TW et produire une note de version en anglais est correct et ne nécessite aucune conversion de quoi que ce soit sur le disque.
Ne traduisez jamais : les chemins de fichiers, les symboles de code, les hashes
de commit, les noms d'API/classe/paquet, les références de branche et de problème,
ou quoi que ce soit dans evidence[]. Expliquer un terme dans la langue de sortie
est bienvenu ; le renommer ne l'est pas.
3. Valider la plage de dates (toujours en premier)
python3 scripts/resolve_date_range.py <args> [--timezone <IANA>] [--today <YYYY-MM-DD>]
Passez les paramètres canoniques, par ex. --days 7, --date 2026-07-01,
--from 2026-07-01 --to 2026-07-10, ou un raccourci comme 7d. Ajoutez
--include-uncommitted lorsque demandé.
- Sur
ok:false, rapportez l'erreur à l'utilisateur et arrêtez-vous. Codes courants :TOO_MANY_DAYS(affichezrequested_days, demandez de réduire),ARG_CONFLICT,DAYS_OUT_OF_RANGE,INVALID_DATE,FROM_AFTER_TO,TO_WITHOUT_FROM. - Sur
ok:true, conservezdates[](chacun adate,start,endbornes demi-ouvertes),timezone, ettimezone_source. Sitimezone_sourceestsystem-offset(pas de nom IANA), dites à l'utilisateur quel décalage est supposé et proposez d'en définir un.
Priorité du fuseau horaire et règle du jour demi-ouvert [00:00, 00:00 suivant) :
references/date-parameter-contract.md.
4. Détecter l'état du dépôt
python3 scripts/collect_git_history.py --repo <racine> --info-only
NOT_A_GIT_REPO→ dites à l'utilisateur que ce répertoire n'est pas un dépôt Git et arrêtez-vous.- Enregistrez
root,branch(null sidetached_head),head/short_head,has_commits,dirty_worktree. Ceux-ci apparaissent dans le résumé d'aperçu. - Dépôt vide (
has_commits:false) : avecinclude_uncommitted=false, il n'y a rien à journaliser — dites-le. Avecinclude_uncommitted=true, analysez uniquement l'arbre de travail.
5. Analyse par jour — un sous-agent par jour
Deux commandes encadrent cette section. analyze prepare décide quoi doit être
analysé et dans quelle langue ; analyze collect décide s'il faut croire
ce qui est revenu. Tout ce qui se trouve entre les deux — lire les correctifs,
comprendre le code, écrire le texte — est votre travail et celui des sous-agents.
La CLI ne le fait jamais et n'a besoin d'aucune clé API de modèle.
5a. Préparer l'exécution (déterministe, une fois pour toute la plage) :
python3 -m git_worklog analyze prepare --repo <racine> \
--from <première date> --to <dernière date> --timezone <tz> \
--language <balise|auto> --language-source <source> \
--provider <fournisseur> --model-json '<objet modèle>' \
[--include-uncommitted]
Retourne run_id, run_dir, et tasks[] — une entrée par jour calendaire, chacune
avec un manifest_path (quoi analyser) et un result_path (où son analyse doit
être écrite). Conservez tout cela.
--language et --language-source viennent du §2a. Ils sont résolus une fois
ic i et tamponnés sur chaque manifeste dans l'exécution : le language.resolved
d'un manifeste est ce à quoi le résultat de chaque jour est vérifié, et les jours
en désaccord bloquent toute l'exécution.
Résolvez <fournisseur> et <objet modèle> une fois pour toute l'exécution
avec scripts/resolve_provider_model.py --host <anthropic|openai|google> (voir le
tableau de modèles ci-dessous). model est un objet — {display_name, model_id}
plus reasoning_effort pour openai seulement.
Chaque manifeste donne file_groups (groupés par domaine de travail réel),
required_context, analysis_rules, un drapeau large_day recommandant les
sous-agents d'analyse de code lorsque le jour est grand, parts_dir (où vont
les parties d'un fan-out — jamais à côté du résultat du jour, voir ci-dessous),
required_commit_file_pairs (§5b), et la paternité du jour — authors[]
(noms distincts, ordre de première apparition) plus commits[].author_name.
Vous rendez la ligne 參與者 et chaque entrée 相關 commits de l'auteur à
partir de ceux-ci directement ; le sous-agent ne renvoie jamais d'attribution.
Le fan-out d'un grand jour écrit ses parties par groupe dans parts_dir,
pas à côté du result_path du jour. results/ contient les réponses de
l'exécution et collect fait échouer l'exécution pour tout fichier là qu'il
n'a pas demandé (unknown) — donc un fan-out qui dérive un frère de
result_path bloque le jour même qu'il était censé rendre traitable.
Les correctifs ne sont pas dans le manifeste — les sous-agents les lisent avec
git show.
5b. À quoi chaque jour est tenu. Chaque manifeste liste
required_commit_file_pairs : chaque (commit, fichier) que le jour a touché,
marqué required ou non. Requis signifie que l'analyse du jour doit tenir
compte de ce fichier — le nommer dans le files[] d'un élément de travail
suffit ; une citation dans evidence[] est plus forte mais pas exigée. Seuls
les fichiers source sont requis ; les docs, config, CI, tests, binaires et
fichiers supprimés sont listés mais excusés (un fichier supprimé a disparu de
l'arbre de ce commit, donc il ne peut pas être cité).
Un fichier requis que l'analyse ne mentionne jamais fait échouer le jour au §5d. Ce n'est pas de la pédanterie : un fichier qui a été modifié mais jamais décrit n'a peut-être jamais été lu, et c'est invisible dans un résultat qui a sinon l'air confiant.
5c. Lancez un sous-agent par jour, en passant son manifest_path et son
result_path. Le sous-agent doit lire les diffs réels et assez de contexte de
code, déterminer l'état de fin de journée (une fonctionnalité ajoutée puis
annulée le même jour n'est pas une modification en direct), et écrire le JSON
structuré dans references/subagent-contract.md à ce chemin, en répondant
seulement DONE — les résultats ne sont jamais repassés comme texte de réponse,
ce qui les fait chuter et les tronque (references/subagent-contract.md §6a). Il
ne doit pas écrire dans le journal. Les jours sans commits écrivent toujours
has_changes:false.
5d. Collectez le résultat de chaque jour (déterministe), une fois que tous les sous-agents ont terminé :
python3 -m git_worklog analyze collect --run-id <run_id> --repo <racine>
Rien ici ne nomme une date ou une langue : collect lit les manifestes de sa
propre exécution, donc un jour ne peut pas être omis de la vérification en étant
laissé de côté d'une ligne de commande. Il signale :
complete/degraded/missing/invalid/unknown/failed_dates,results(date → objet),partial_run,escalation_suggested_dates.- Une date dans
missingouinvalidest un jour échoué, pas un jour vide — ne la traitez jamais comme "rien ne s'est passé" et ne retombez jamais sur ses messages de commit. unknownest un fichier de résultat que l'exécution n'a jamais demandé. Ne le fusionnez pas.partial_run:truebloque l'application par défaut (§9). Le code de sortie est1.
Trois choses auxquelles chaque résultat est vérifié, et chacune fait échouer le jour :
- Langue — la balise doit être celle que son manifeste a demandée.
- Précision des preuves — chaque entrée est vérifiée par rapport à l'arbre du
commit qu'elle cite : le commit existe, le fichier existait à ce commit, le
symbolapparaît dans celui-ci, la plagelinesest à l'intérieur. Un sous-agent qui citemigrate_directorypour une fonction appeléeparse_legacyne vous a rien dit que vous puissiez suivre (#15). Sur un clone superficiel, les commits inaccessibles signalentEVIDENCE_UNVERIFIABLEplutôt que de faire échouer. - Fichiers requis — voir §5b. Si un fichier requis n'est nommé dans aucune
citation ni aucun
files[], le jour échoue.
6. Générer l'aperçu
6a. Résumé d'aperçu :
python3 -m git_worklog preview --repo <racine> --run-id <run_id>
Produit un résumé de ce qui sera écrit : nombre de jours, plages, jours nouveaux/modifiés, et auteurs. L'utilisateur voit ceci et confirme ou annule.
6b. Aperçu de chaque jour :
python3 -m git_worklog preview --repo <racine> --run-id <run_id> --day <date>
Affiche une vue en Markdown du résultat qui sera écrit, sans l'écrire. L'utilisateur peut demander des aperçus individuels de cette façon.
7. Appliquer les écrire (après confirmation)
python3 -m git_worklog apply --repo <racine> --run-id <run_id>
Écrit les fichiers jour dans .git-worklog/days/, reconstruit index.md,
et signale ce qui a été écrit et ce qui a été ignoré. Utilisez --force pour
remplacer les jours existants.
8. Appliquer partiel (si permis)
python3 -m git_worklog apply --repo <racine> --run-id <run_id> --partial
Applique uniquement les jours terminés (complete). Les jours degraded,
missing, invalid sont ignorés. L'utilisateur doit explicitement demander
l'application partielle ; ne le faites pas automatiquement.
9. Nettoyer les exécutions
python3 -m git_worklog clean --repo <racine> --run-id <run_id>
Supprime les fichiers temporaires de l'exécution (manifestes, résultats, parties).
Ne touche pas aux fichiers jour ni à index.md.
10. Scripts de support
collect_git_history.py — récupère l'état du dépôt, les commits, les fichiers modifiés.
resolve_date_range.py — valide les paramètres de date, retourne les dates canoniques.
resolve_provider_model.py — retourne le fournisseur et le modèle à utiliser.
Voir scripts/README.md pour la documentation complète.
11. Fichiers de référence
references/code-analysis-rules.md — comment lire le code et écrire les résumés.
references/date-parameter-contract.md — contrat de paramètres de date.
references/interaction-flow.md — flux complet de l'interaction utilisateur.
references/report-mode.md — mode rapport (lecture seule).
references/subagent-contract.md — contrat de résultat JSON pour les sous-agents.
12. Tableau des modèles
| Fournisseur | Modèle | reasoning_effort |
|---|---|---|
anthropic | claude-sonnet-4-20250514 | n/a |
anthropic | claude-3-5-sonnet-20241022 | n/a |
openai | gpt-4o-2024-08-06 | medium |
google | gemini-2.0-flash-001 | n/a |
La détermination du modèle est effectuée par resolve_provider_model.py ; voir
scripts/resolve_provider_model.py --help pour les options.
13. Variables d'environnement
GIT_WORKLOG_MODEL_PROVIDER — fournisseur par défaut (anthropic, openai, ou google).
GIT_WORKLOG_MODEL_NAME — nom du modèle par défaut (ex. claude-sonnet-4-20250514).
GIT_WORKLOG_TIMEZONE — fuseau horaire IANA par défaut (ex. Asia/Taipei).
GIT_WORKLOG_LANGUAGE — langue par défaut pour les journaux (ex. zh-TW, en).