# Commit style

## Rules

- **English**, always.
- **Short and to the point.** One line is the norm.
- **Imperative mood, no closing period** — `Add future location events with reminders and dashboard alerts`.
  Older history uses noun phrases with a period (`Location types.`); that style is retired, do not extend it.
- Describe the change, not the process.
- **A body only for a non-obvious *why*, two or three lines at most**, after a blank line. The subject line
  still says *what*; the body exists for a cause that the diff cannot show and that does not warrant an ADR —
  daylight saving breaking a month count, a double slash appearing in absolute URLs. If the reason is visible
  in the diff, there is no body. A decision, rather than a surprise, is still an ADR.
- Use a semicolon to separate two unrelated changes in one commit.
- Prefix documentation-only commits with `Docs:`.
- **Never add a `Co-Authored-By` trailer.** No `Generated with` footers either.
- Commit per phase during implementation, **after the phase review, not before** — see
  [WORKFLOW.md](WORKFLOW.md#4-phase-commit). Documentation gets its own commit at the end of the task.
- **Never put `web/build/` in a phase commit.** The working tree carries a dev build while the task runs; the
  repository keeps the production build until the closing `Build assets (production)` commit.
- When the task came from a Redmine issue, append `#<id>` so Redmine links the commit to it.

## Examples

From the actual history:

```
Add TELL Gate Control PRO door-opening phone sync
Fix office/ad-space submodules and drop overview actions
Redesign header and mobile layout
Auto-translate multilingual records on save
Add callback request feature merged with offer tabs; make German copy informal
Docs: frontend copy uses informal address
Build assets (production)
```

With a body — `6d9a014` and `49e84e1` are the kind of fix that earns one:

```
Fix daylight saving, full month counting and daily price rounding in the item calculator

A day count taken from a timestamp difference is one hour short across the March DST
change, so an interval spanning it billed one day less.
```

## Anti-patterns

```
fix                                          # says nothing
Fixed the bug where the storage list would…  # too long, past tense
feat(storages): add pagination               # conventional commits are not used here
Add pagination

Co-Authored-By: …                            # forbidden
```

## Branch and push

- Work on `master` unless the developer asks for a branch. Tasks driven through the Redmine `start-issue`
  skill are the exception — that skill creates and owns an `f_<issue-id>` branch.
- Push only at the end of the task, after the documentation commit. `composer test` runs first, always — the
  `pre-push` hook enforces it where it is installed. Which gates a *commit* needs depends on what changed:
  [Which gates run](WORKFLOW.md#which-gates-run).
- **Run `npm run encore production` and commit `web/build/` before pushing** whenever `resources/` changed.
  The server has no Node, so whatever is in `web/build/` at push time is what goes live — a dev build
  shipped to production is a bug. See [DEVELOPMENT.md](DEVELOPMENT.md#assets).
