Files
houseplan-card/docs/DEVELOPMENT.md
T
Matysh 70d3453f78
Validate / hacs (push) Has been cancelled
Validate / hassfest (push) Has been cancelled
Validate / frontend (push) Has been cancelled
Validate / backend (push) Has been cancelled
docs: catch all documentation up to v1.23.1
- READMEs (en+ru): doors/windows/locks section (openings tool, live rendering, drag,
  double-click properties), presence ripples + per-device icon size/rotation in the
  manual-marker section.
- ARCHITECTURE: room geometry rules (derived walls, no-overlap, merge/split via
  polyclip-ts and why not polygon-clipping), doors & windows model (space.openings,
  snapToWall, absolute coords, security), per-marker display fields + cell_cm ruler.
- DEVELOPMENT: gotchas — polygon-clipping ESM/types mismatch; same-version redeploys
  keep ?v so browsers cache the old bundle.
- STATUS: snapshot refreshed (releases to v1.23.1, dacha deployed v1.23.1), milestones
  v1.17–v1.23.1 incl. the lost-sources lesson (push right after building).
- ROADMAP: 8 shipped Quality-Scale items ticked (done since v1.12.0).
- TESTING: restored the v1.22.0 ripple checklist lost in the sandbox reset.
2026-07-17 07:53:16 +03:00

99 lines
6.0 KiB
Markdown
Raw 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.
# Development and deployment
## Environment (cowork sessions)
- The source of truth is **GitHub `main`** (https://github.com/Matysh/houseplan-card).
In a sandbox session restore from it or from `houseplan-card.git.bundle`
(`git clone houseplan-card.git.bundle hpcN` into a **fresh** /tmp directory).
- The user's folder `houseplan/houseplan-card/` is a file mirror (synced after every commit)
+ an up-to-date `houseplan-card.git.bundle`. The mount cannot delete files — stale
artifacts linger there; git is authoritative.
- `/tmp` persists between sessions, **but files created in previous sessions belong to
`nobody` and are unreadable** (this hit `/tmp/hpc`, `/tmp/ha_jb`, `/tmp/shots/srv`).
Always clone into a new directory and re-run `npm ci`; ask the user to re-upload `ha_jb`.
- Headless Chromium for smoke tests: `PLAYWRIGHT_BROWSERS_PATH=/tmp/pw npx playwright
install chromium-headless-shell`, then run with `LD_LIBRARY_PATH` pointing to the
extracted lib dirs (`libs/lib/x86_64-linux-gnu:libs/usr/lib/x86_64-linux-gnu:.../nss`).
- Restart HA over SSH with `nohup ha core restart >/dev/null 2>&1 </dev/null &` —
a plain `ha core restart` holds the SSH session until the sandbox call times out.
- GitHub pushes: classic PAT (repo+workflow scopes), created via the user's Chrome;
stored in `~/.git-credentials` for the session.
### ⚠️ File-sync pitfalls (critical)
1. The network mount sometimes serves files **truncated/scrambled** — edits via the Edit tool
from the Windows side are unreliable. Rule: **apply python patches against a clean copy in /tmp,
write via bash**, with an assert that count(old)==1.
2. **Run the rollup build ONLY in /tmp/hpc** (`npm ci` is already done). A build on the mount once
produced a syntactically valid but broken bundle ("wi is not defined") that crashed the rendering
of ALL HA dashboards (the card is loaded as an extra_module on every page!).
3. `.git` cannot be created on the mount ("Operation not permitted" on dot-directories) — hence the bundle.
## Tests
- Frontend: `npm test` — compiles src/logic.ts+rules.ts (tsconfig.test.json) and runs node:test
(test/*.test.mjs). Strict typing: `npm run typecheck` (tsc --noEmit, part of `npm run build`).
- Backend: `python -m pytest tests_backend/` — pure validation of custom_components/houseplan/validation.py
(loaded by path, without importing the HA package).
- IMPORTANT (audit lesson): the rollup typescript plugin reports a syntax error as a WARNING and still
builds the bundle — a truncated file can "pass". That is why the build starts with `tsc --noEmit`,
which fails on such errors. Always build with `npm run build`, never bare `rollup -c`.
## Build
```bash
cd /tmp/hpc && npm ci # once
npx rollup -c # → dist/houseplan-card.js
node --check dist/houseplan-card.js
cp dist/houseplan-card.js custom_components/houseplan/frontend/
```
## Deployment to the dacha (ha.jbstudio.pro)
- SSH: port **323**, root, key `ha_jb` (the user uploads it to the chat; in the sandbox /tmp/ha_jb, chmod 600).
- JS: `scp -P 323 -i /tmp/ha_jb dist/houseplan-card.js root@ha.jbstudio.pro:/config/custom_components/houseplan/frontend/`
- The whole integration: tar c custom_components/houseplan (--exclude __pycache__) → tar x on the server.
- **Verification is mandatory**: `md5sum` locally == on the server == `curl http://homeassistant:8123/houseplan_files/houseplan-card.js | md5sum`
(inside the SSH add-on `localhost` is NOT HA, use the host `homeassistant`).
- Python changes require an HA restart (`ha core restart`, holds the connection until it finishes, HTTP
comes back up in 13 min). JS changes — just a page refresh (the static path is served
with no-cache).
- After deploying JS — check in the browser (Ctrl+F5) and the console (there must be no errors from
houseplan-card.js; a broken bundle takes down all dashboards).
## Frontend cache and the "empty view"
- The card module URL contains `?v=<VERSION from const.py>`. Browsers keep the ES module in
memory cache: after deploying new JS **bump VERSION in const.py and restart HA**,
otherwise a plain F5 will keep the old version.
- After a page reload the HA frontend (with kiosk-mode) sometimes leaves the view empty
("InvalidStateError: Transition was aborted", hui-view is not created for 12 min).
Cured by repeating the SPA navigation: pushState + a location-changed event, or just waiting.
## Dependency and cache gotchas
- **polygon-clipping is a trap**: its `.d.ts` declares named exports but the ESM build has only
a default export — tsc or the runtime breaks, whichever you appease. Use **polyclip-ts**
(proper ESM + native types; same results, +~50 KB bundle via bignumber.js).
- **Redeploying the same version keeps the resource URL** (`/houseplan_files/houseplan-card.js?v=X`),
so browsers may serve the previous bundle from cache. Bump the version for anything users must
pick up, or hard-refresh (Ctrl+Shift+R) when testing a hotfix redeploy.
## Release
Tag `vX.Y.Z` + GitHub Release → the workflow `.github/workflows/release.yml` builds and attaches
`houseplan-card.js`. Bump the version everywhere in sync: `src/houseplan-card.ts` (CARD_VERSION),
`package.json`, `custom_components/houseplan/manifest.json`, `custom_components/houseplan/const.py`.
## Reproducible scripts (data)
- Extracting the geometry/backgrounds from the prototype and generating `src/data/*` — see the commit
history and docs/ARCHITECTURE.md (SVG→base-space transforms: f1 0.647/(490,27), f2 0.896/(351,21)).
- Room fitting: render the plan with rectangles overlaid (cv2) → snap to walls → manual fine-tuning.
## Production objects in HA (the dacha)
- Dashboard `plan-doma`, panel view, card `custom:houseplan-card` (icon_size 2.5).
- The houseplan integration: entry loaded, `.storage/houseplan.layout` — the layout (server-side).
- The old prototype `/config/www/houseplan/` (iframe) is kept as a fallback, do not touch.
- configuration.yaml backups: `.bak-avgtemp` (before the average-temperature sensor edit).