Files
Claude 8dcc1cad4e docs(process): канон без противоречий, вход автора короче (#701)
Сверка PROCESS.md, ролевых выжимок, AGENTS.md, TESTING.md, CONTRIBUTING.md
и скриптов по 26 найденным расхождениям (D1–D26): трейлеры по классам
изменений, gate:small как единственный источник состава, пороги ревью,
путь реестра мутантов, golden по ci:golden, порядок чтения промпта ревью.

- scripts/change-classes.mjs: классы A/B/C/D — один модуль для
  process-gate и проверки трейлеров.
- commit-msg: коммит только с файлами класса C (документация) трейлеров
  не требует; указанные трейлеры по-прежнему проверяются.
- Маршрут автора без docs/STATUS.md: 5345 → 4703 слова.
- Промпт ревью читает SCOPE → AGENTS → REVIEWER, как ROUTES.reviewer.

Issue: #701
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-09-29 00:30:04 +03:00

149 lines
7.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Contributing to House Plan
Thanks for your interest! The project is one HACS package: a storage **integration**
(`custom_components/houseplan/`, Python) and a **Lovelace card** (`src/`, TypeScript + Lit).
## Changelog
User-visible changes go into **both** changelogs in the same commit:
`docs/CHANGELOG.md` (English) and `docs/CHANGELOG.ru.md` (Russian). Entries
older than v1.42.0 exist only in the English file — no need to backfill them.
## Translations
A shipped UI language has three matching parts:
1. `src/i18n/<code>.json` for the card;
2. `custom_components/houseplan/translations/<code>.json` for the Home Assistant
integration;
3. one registry entry (code, native label and eager dictionary or lazy loader)
in `src/i18n/registry.ts`.
Use the canonical Home Assistant/BCP 47 language tag as `<code>` (for example,
`fr` or `pt-BR`) and use that exact spelling for both JSON filenames. Lookup is
case-insensitive and also accepts `_` from legacy locale sources.
The registry drives language resolution, the visual-editor selector and parity
tests. The tests reject missing or extra locale files; frontend dictionaries
also fail on mismatched keys, empty values and changed placeholders.
Placeholders such as `{name}` and `{n}` are a contract: do not translate, add
or remove them.
English and Russian are synchronous fallback/legacy locales. German is the
reference lazy third-locale implementation: its module carries the same build
fingerprint as the entry bundle, has one content-hashed retry URL and is listed
under `lazyLocaleFiles` in `houseplan-assets.json`. New sizeable locales should
follow that path unless a measured initial-bundle budget explicitly justifies
an eager import. Extend the runtime, manifest, file/key/placeholder parity and
regional-locale tests together; never bypass the registry by importing a locale
directly in a component.
Administrator-only copy lives in three lazy namespace dictionaries —
`src/i18n/settings/`, `src/i18n/support/` and `src/i18n/topology/` (#627). Their
English file is static (the synchronous fallback); every other language is one
lazy chunk per namespace × language: a two-line loader module
`src/i18n/<namespace>/<namespace>-<code>.ts`, one `import()` with a
content-hashed retry token in `src/i18n/<namespace>.ts`, and one entry in
`NAMESPACE_LOCALE_CHUNKS` in `scripts/bundle-manifest.mjs`. The lazy surfaces
(onboarding, editor runtime, Zigbee overlay) wait for their dictionaries before
painting; never import a non-English namespace JSON statically — the budget
gate and `test/i18n-lazy-namespaces.test.mjs` refuse it.
The current `subst()` helper does not implement plural rules. Phrase strings so
their grammar does not depend on the numeric value (for example, use a neutral
label followed by `{n}` rather than an English singular/plural pair).
Adding a UI locale does not automatically create another full documentation
set; maintain the existing English and Russian documentation according to the
project's normal rules. Right-to-left layout is a separate product project,
because the plan canvas and editors cannot be mirrored by translations alone.
## Documentation screenshots
The images under `docs/images/` are produced only from synthetic data on the
pinned Chromium in CI. A task branch does not commit them, nor the golden
baselines: once per beta the `beta-derived.yml` workflow refreshes the
fingerprint, the frames and the golden baselines on `dev` in one bot commit,
accepting only the frames it was told to expect (`PROCESS.md` §8, #697). A task
that changes visuals on purpose sets the `ci:golden` label. The manual path —
the `Docs screenshots` workflow and `npm run docs:accept -- --reviewed
--from=<unpacked artifact>`, or `--identical` when no pixel can move — stays
for the release manager. Scenario version, source fingerprint and every image hash
are recorded in the [screenshot index](docs/images/screenshots.json), and
`node scripts/check-docs.mjs` reports a stale fingerprint: a warning on an
ordinary push, an error on a beta candidate (a commit with a `Release:`
trailer). The full rule is in `PROCESS.md` §8.
## Where to ask
Not sure whether something is a bug, or just want to discuss an idea before
writing code? The **[Telegram chat @ha_houseplan](https://t.me/ha_houseplan)**
is the quickest route to the author and other users. Bugs and concrete feature
requests still belong in [issues](https://github.com/Matysh/houseplan-card/issues).
## Backlog and work status
[GitHub Issues](https://github.com/Matysh/houseplan-card/issues) are the only
active backlog. An issue owns scope and acceptance criteria; its **labels** own
priority and workflow status — `PROCESS.md` §9 holds the vocabulary. Before
starting planned work, link it to an existing issue or create one, and keep it
current until the verified result is closed. Design specs and ADRs may support an
issue, but they do not replace it or maintain a separate checklist.
## Five-minute setup
```bash
git clone --filter=blob:none https://github.com/Matysh/houseplan-card && cd houseplan-card
npm ci # frontend toolchain; `prepare` installs .githooks
npm run typecheck # tsc --noEmit (strict)
npm test # node:test — pure logic, i18n parity, tap-action security
npm run build # tsc + rollup → dist/houseplan-card.js
pip install -r tests_backend/requirements.txt && python -m pytest tests_backend -q # CI pins, HA harness included
```
### Why `--filter=blob:none` (#345)
A blobless clone keeps every commit and tag, so ranges, `merge-base` and
`git diff` across history work exactly as in a full clone; only historical *file
contents* are fetched on demand. Most of the pack is exactly such content that
almost nobody reads again — documentation screenshots re-captured with the UI and
the committed bundle rewritten by every release candidate — so a blobless clone
is several times smaller. To see the numbers for your own clone, compare
`git count-objects -vH` in a blobless and in a full one.
Drop the flag if you work offline with history, or need `git log -p` over the whole
tree repeatedly. Do **not** replace it with `--depth=1`: a shallow clone is about
the same size but has no `merge-base`, so the process gate, `smoke-select` and
every `origin/dev..HEAD` range stop working.
The HA-harness backend tests (`tests_backend/test_ha_*.py`) need the
repository-pinned Python (`.python-version`) and
`pytest-homeassistant-custom-component home-assistant-frontend`; their canon is
Linux CI or WSL (`bash scripts/wsl-setup.sh --verify`). Without an importable
`homeassistant` they are not collected at all — not skipped — and pytest prints
`HA harness NOT collected: …` (#630).
## Ground rules
- **Docs in the same commit**: CHANGELOG entry for user-visible changes;
`docs/ARCHITECTURE.md` for changes to the data model, WS API or coordinate
system; `docs/STATUS.md` for state changes; `docs/DEVELOPMENT.md` for new
gotchas. A docs-only commit needs no trailers (`PROCESS.md` §3 п.10).
- Every UI string goes through `src/i18n/<lang>.json`; follow the
[Translations](#translations) flow for registry and backend parity.
- The committed bundle changes only in a release candidate: `npm run
bundle:release` in a commit with a `Release:` trailer (#657). An ordinary task
restores it with `npm run bundle:clean` before committing — the `commit-msg`
hook refuses a bundle change otherwise.
- Tap actions have a security model (locks/alarms never toggle from the plan) —
see `resolveToggleIntent` in `src/device-toggle.ts`; don't weaken it.
- Every commit follows the issue and trailer contract in `PROCESS.md`.
- Follow the Integration Quality Scale where applicable —
`custom_components/houseplan/quality_scale.yaml` tracks the self-assessment.
## Architecture
Start with `docs/ARCHITECTURE.md` (data model, WS API, coordinate system) and
`docs/STATUS.md` (current state). Release mechanics live in one place:
`docs/DEVELOPMENT.md` › Release.