mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
Волна 3 эпика #674. AGENTS.md 650 → 187 строк: карта пакета, маршрут чтения, правило №1, классы и треки одной строкой со ссылками, трейлеры, рабочие деревья, хендофф и ожидание вердикта; пересказы PROCESS.md — ссылками на разделы. Неверный список «Gate jobs» снят (списки jobs не копируются в прозу, шапка PROCESS.md). Правила, жившие только в AGENTS, получили дом: жёлтый вердикт при выполненных AC — PROCESS §2.7; свежесть бандла, съёмка только в Linux (#455, HP_ALLOW_FOREIGN_CAPTURE) и смоки из AC до S7 (#151) — TESTING.md; причуда демо-стенда и среда-зависимый smoke_opening_measure — DEVELOPMENT › Smoke tests; отказ публикации без `Release:` и при несвежем отпечатке бандла, отмена Validate новым пушем, кандидат беты не promotion-only, fail-closed реестра Labs — DEVELOPMENT; предупреждение и ошибка свежести скриншотов — CONTRIBUTING. PROCESS.md: §13 (внедрение с открытым ⏳), §14 (блок со ссылкой на несуществующий docs/PROCESS.md) и §7.3 (история) удалены. Ссылки «§7.2» на правило полного разбора после ребейза ведут в §2.10, на сверку SHA перед выводом — в §2.7; то же в сообщениях scripts/branch-state.mjs, merge-candidate.mjs, review-doc-guard.mjs, pre-push-gate.mjs, в промпте _process.yml и TESTING.md. Число `any` в прозе → `node scripts/no-new-any.mjs --total` (новый режим, юнит-тест; было «1034 в 49 файлах», сейчас 862 в 52), дата-число замороженного списка якорей монолита снято. Устаревшая команда пересъёмки скриншотов в §8 заменена ссылкой на действующий путь. STATUS.md 113 → 61 строка: сгенерированный снимок, текущий цикл и девять строк решений; Workflow, CI, Toolchain, Tests, Scope, open items и политика документации — ссылками (PROCESS §2.6, DEVELOPMENT › Release, TESTING); локали en/ru/de/fr; закрытые «coverage, mypy strict» сняты. DEVELOPMENT.md: file-sync и «Reproducible scripts» (прототип) удалены; раздел Release — единственный дом релизной механики: введение, правила тела стабильного релиза (#328, release:notes), шаг continuity:screencast, источники версии по release-contract. CONTRIBUTING: ссылка на Release вместо пересказа, замеры клона без чисел. TESTING: any-гейт — ссылкой на PROCESS §8. entry-cost: автор 11 125 → 5 407 слов, ревьюер 8 464 → 4 285. Issue: #680 User-Visible: no Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
145 lines
7.5 KiB
Markdown
145 lines
7.5 KiB
Markdown
# 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 by the
|
||
`Docs screenshots` workflow (`demo/docs/capture.mjs` on the pinned Chromium)
|
||
and accepted locally with `npm run docs:accept -- --reviewed --from=<unpacked
|
||
artifact>`; when a change cannot move a pixel, `npm run docs:accept --
|
||
--identical` re-captures locally, compares decoded pixels and refreshes only the
|
||
source fingerprint. 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
|
||
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 pytest voluptuous && python -m pytest tests_backend -q # pure backend tests
|
||
npm install # also installs .githooks through the prepare script
|
||
```
|
||
|
||
### 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/STATUS.md` for state changes; `docs/DEVELOPMENT.md` for new gotchas.
|
||
- 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.
|