Immutable. This exact content is served forever at /api/v1/blob/e61a98399d65488a.
--- description: Record a change that reshaped the repository — what moved, why it was worth doing, and which areas it touched. Use after a migration, a rewrite, or a decision that changed how part of the system works. --- # Record a milestone A git log says what changed. It rarely says **why the change was worth making**, and never says which areas moved together. Six months later that is what somebody needs — usually while deciding whether they are allowed to undo it. ## When to write one For a change big enough that a newcomer would ask "why is this part like that?" - a migration — a database, an auth model, a framework - a rewrite of a module, or a service split in two - a design reversal: something was done one way, then deliberately undone Roughly a handful a year on an active repository. If you are writing one a week, they are commits, not milestones, and the file stops being readable. ## When not to - **A task, or something in progress.** That is `STATE.md`, or a session record. - **A single decision with no structural change.** That is `/chamnan:remember` → `.chamnan/memory/decisions/`. - **A repeated procedure.** That is `/chamnan:capture`. - **Anything with a status, an owner, or a due date.** This is not project management, and adding those fields would quietly turn it into a worse version of a tool you already have. ## Where it goes ``` .chamnan/milestones.md ``` One file, and entries are **appended at the end**. Newest last is deliberate: appending keeps every diff to added lines, where prepending would rewrite the context of the whole file each time. ## The format ```markdown ## 2026-08-20 — Authentication migration **Why:** sessions dropped under load; the old design held state per node. **Affected:** auth module, API layer **Decisions:** short-lived tokens; the old endpoint stays for one release ``` Four parts, and the middle two carry the value: | | | |---|---| | Date and title | ISO date, then a short name for the change | | **Why** | The problem that made it worth doing. Not "we migrated auth" — *what was going wrong*. | | **Affected** | Which areas moved together. This is what nobody can reconstruct later. | | **Decisions** | Choices made along the way, especially anything ruled out. | Leave out a field rather than filling it with a dash. Write the *why* as the problem, not the activity. "Migrated to short-lived tokens" is the diff restated; "sessions dropped under load because the old design held state per node" is the reason, and it is the half that stops somebody re-treading it. ## What reaches a session Only the **two most recent titles**, with their dates. The bodies stay in the file, and the agent reads it when a title looks relevant. So a repository with forty milestones costs the same per session as one with two. ## What not to put in it - **No credentials, hostnames or connection strings.** This file is committed. The session-start hook redacts what it injects; that does not clean the file on disk. - No incident write-ups. Name the failure in one clause; a post-mortem belongs in `docs/`. ## Housekeeping Not pruned by age, on purpose — the oldest entry is usually the one nobody can reconstruct. Because only titles are injected, length costs nothing per session. Edit an entry if it turns out to be wrong; a false milestone is worse than a missing one. Set `"milestones": false` in `.chamnan/config.json` to switch it off.