# 0021. Documentation set and workflow

- **Status:** Accepted
- **Date:** 2026-08-08

## Context

The project had 147 lines of documentation across five Hungarian files, against 457 PHP files and ~46 000
lines of code. `docs/ADMIN.md` was six lines for a 13 871-line subsystem. `db/ActiveRecord.php` — 805 lines
carrying schema declaration, slugs, translations, search indexing and translation queueing — was documented
by `/** Basic active record. */`.

Two claims in those files were **false**: a `./yii feed/sitemap` console command that has never existed and
was listed as a required deployment step, and a third web entry point (`web/index-test.php`) that does not
exist. `CLAUDE.md` stated that database columns are `snakeCase`; they are camelCase and always have been.

The sibling **Molino** project — same foundation, same client — had adopted a documentation
system that was working. The developer asked for it here.

## Decision

Adopt the sibling project's structure, adapted to this codebase.

**Five kinds of document, each with one audience and one lifetime:**

| Kind | Where | Audience | Lifetime |
|------|-------|----------|----------|
| Human docs | `docs/*.md` | the developer | permanent |
| LLM wiki | `docs/wiki/` | Claude only | permanent, continuously refreshed |
| ADR | `docs/adr/` | both | immutable once accepted |
| Plans | `docs/plans/` | both | deleted when the task closes |
| Private context | `CLAUDE.local.md` | Claude only | gitignored, never committed |

**`CLAUDE.md` is a table of contents.** Content in it is a bug — it routes to the document that owns the
topic.

**Rule 0 — verify before you write.** No console command, route, path, class, method or config key goes into
a document before it has been confirmed to exist. When a document and the code disagree, the code wins.

**Everything is English** — code, schema, comments, commits and documentation. Only the conversation with the
developer and the user-facing message files are Hungarian.

**The workflow is master-based**: plan mode → implementation → stop after every phase → commit after the
review, never before → documentation in its own commit → production asset build → push → two closing texts
(deployment steps, and a summary the developer can forward to a non-technical client contact).

## Alternatives

- **Keep the Hungarian human docs and only add a wiki.** Rejected: the split language was already producing
  half-translated files, and the wiki has to cite English identifiers anyway.
- **Generated API documentation (phpDocumentor).** Documents what a class *is*, which the class already says.
  The valuable knowledge is cross-cutting: conventions, invariants and traps.
- **A single large `ARCHITECTURE.md`.** No audience separation — the developer would read Claude's working
  notes and Claude would read the deployment runbook.
- **Build the structure from scratch rather than copying the sibling.** The sibling's version had already
  been through a real review cycle; re-deriving it would have repeated the mistakes it had already corrected.

## Consequences

- **~4 200 lines of documentation** where there were 147.
- **Rule 0 caught real errors on the first pass** — the two false claims above, plus eight latent bugs, all
  since fixed. They are listed in [wiki/GOTCHAS.md](../wiki/GOTCHAS.md#latent-bugs) as a catalogue of the
  mistakes this codebase makes easily.
- **The wiki has to be maintained after every approved change**, or it becomes exactly the liability it is
  meant to prevent. A wiki that is 95% right is worse than none, because it is trusted on the 5%.
- **A weekly review is scheduled**, tracked by a date at the top of `docs/DOCUMENTATION.md`.
- The sibling project is a useful cross-check but **is not authoritative here** — the two have diverged
  (see [0002](0002-single-brand-deployment.md)), and copying a claim across without verifying it violates
  Rule 0.
- The Redmine `start-issue` skill remains outside this: it owns its own `f_<id>` branch and status handling.
  The repository's own process assumes `master`.
