diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..1690e17 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,45 @@ +name: Bug report +description: Something does not work as described in the documentation +labels: [bug] +body: + - type: markdown + attributes: + value: | + Thanks for reporting! Remove camera addresses and passwords from anything you paste. + - type: input + id: version + attributes: + label: VisionState version + description: Settings → Apps → VisionState (or VisionState (beta)) + placeholder: "0.8.0" + validations: + required: true + - type: dropdown + id: kind + attributes: + label: Sensor kind + options: + - State sensor + - Object sensor + - Reading sensor + - Not about one sensor + validations: + required: true + - type: input + id: system + attributes: + label: Home Assistant version and hardware + placeholder: "2026.10.0, Raspberry Pi 4 / Intel NUC / Proxmox VM" + - type: textarea + id: what + attributes: + label: What happened, and what did you expect? + description: Steps to see it again help a lot. A screenshot is welcome. + validations: + required: true + - type: textarea + id: log + attributes: + label: Log + description: The app's Log tab, around the time it happened. + render: text diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3f91377 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Questions, ideas and shared meter readings + url: https://github.com/oleost/VisionState/discussions + about: Ask, suggest a feature, or share an export of readings (Quality tab → Export readings) to help improve reading. + - name: Security vulnerability + url: https://github.com/oleost/VisionState/security/advisories/new + about: Report it privately, not as an issue. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa68409..9c8ae1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,12 +25,12 @@ jobs: cache: pip cache-dependency-path: visionstate/backend/requirements*.txt - run: pip install -r requirements-dev.txt - - name: Cache AI model + - name: Cache AI models (all of them, for tests/test_models.py) uses: actions/cache@v6 with: path: visionstate/backend/models - key: models-${{ hashFiles('visionstate/backend/visionstate/backbones.json', 'visionstate/backend/visionstate/detectors.json', 'visionstate/backend/visionstate/readers.json') }} - - run: python -m visionstate.backbones models + key: models-all-${{ hashFiles('visionstate/backend/visionstate/backbones.json', 'visionstate/backend/visionstate/detectors.json', 'visionstate/backend/visionstate/readers.json') }} + - run: python -m visionstate.backbones models --all - run: ruff check visionstate tests - run: ruff format --check visionstate tests - name: Types (pyright) diff --git a/CLAUDE.md b/CLAUDE.md index 66ca9fe..2b599ce 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3,13 +3,41 @@ VisionState — a Home Assistant app that turns camera images into sensors, all locally: **states** the user teaches it (garage door open/closed; embedding model + small per-sensor classifier), **objects** found by a pretrained detector (people, cars, animals) and **readings** -(a number on a display, OCR). This file is the contributor guide for people and AI assistants. +(a number on a display or the wheels of a meter). This file is the contributor guide for people +and AI assistants. -- **Source of truth for scope and design decisions:** [`docs/SCOPE.md`](docs/SCOPE.md). - Update it when a decision changes. -- **Language:** everything in the repository (code, comments, UI text, docs, commit - messages, this file) is written in English. -- Public repository `github.com/oleost/VisionState`, Apache-2.0. Pull requests go to `beta`. +- **Language:** everything in the repository (code, comments, UI text, docs, commit messages) is + written in English. +- Public repository `github.com/oleost/VisionState`, Apache-2.0, owned by its maintainer (oleost). + The maintainer (and Claude working for them) commits straight to `beta`; everyone else opens a + pull request against `beta`. Branches and releases: [`docs/RELEASING.md`](docs/RELEASING.md). + +## Where things are written down + +Every fact has **one** home; other files link to it instead of repeating it. + +| What | Home | +|---|---| +| What the app does for a user, how to use it, the defaults a user sees | [`visionstate/DOCS.md`](visionstate/DOCS.md) (the app's *Documentation* tab) | +| The pitch, install, screenshots | [`README.md`](README.md) (and the short store text `visionstate/README.md`) | +| Design decisions and why, non-goals, roadmap, open ideas | [`docs/SCOPE.md`](docs/SCOPE.md) | +| Where the code is, how a check flows, data on disk, recipes for common changes | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | +| Values of defaults, limits and tunables | `settings.py` and the model registries — docs name the setting, not its value (DOCS.md may state what the user sees) | +| Branches, channels, CI, release steps | [`docs/RELEASING.md`](docs/RELEASING.md) | +| How to work: principles, checks, testing, pitfalls | this file | +| The wheel reader model: data, licences, results, how to train it | [`tools/wheelreader/README.md`](tools/wheelreader/README.md) | +| The plan for better counter readings, and its status | [`docs/WHEEL_READER_PLAN.md`](docs/WHEEL_READER_PLAN.md) | +| Face recognition: models, licences, privacy, the plan and the decisions made building it | [`docs/FACE_RECOGNITION_PLAN.md`](docs/FACE_RECOGNITION_PLAN.md) | +| What changed in a version | `visionstate/CHANGELOG.md` (written at release, never edited afterwards) | +| Test image sources | `visionstate/backend/tests/assets/README.md` | + +- Update the home of a fact **in the same change** as the code; a change that makes a doc wrong is + not finished. +- No "as of version X" or "currently vN" status lines outside the CHANGELOG and the roadmap: they go + stale. Say what is, and let git say when. +- `tests/test_docs.py` (backend, runs in CI) checks every Markdown link, every repository path and + every `module.name` / `settings.X["key"]` in backticks against the code — a rename that leaves a + doc behind fails the tests. ## Principles (do not break these) @@ -19,205 +47,130 @@ classifier), **objects** found by a pretrained detector (people, cars, animals) - **Camera credentials never leak:** `redact.py` masks them in logs, errors and exports. - **No hard-coded defaults** outside `settings.py` / the registries; the UI reads them from `GET /api/v1/config`. -- Home Assistant state values stay lower-case keys (`open`, `car_parked`). +- Home Assistant state values stay lower-case keys (`open`, `car_parked`); unique IDs and topics + never change once released. - Marketing text (README, release notes) promotes VisionState on its own merits — no comparisons with other products. -## Layout and conventions - -- `visionstate/` is the Home Assistant app (build context of the Dockerfile). - - `backend/visionstate/settings.py` holds every backend default/tunable; import from there. - - **Map of the code: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)** — what runs where, how a - check flows, which files a common change touches. Keep it current when the structure changes. - - `backend/visionstate/engine/` is the runtime: `Runtime` (`runtime.py`) is put together from one - mixin per part (`models`, `checks`, `objects`, `reading`, `teaching`, `training`, `publishing`, - `history`, `reminders`) on `RuntimeBase` (`base.py`, the shared state); a part inherits the parts it uses. - `state.py` holds `SensorConfig`/`LiveState`, `logic.py` the pure decisions. New engine code goes - into the part it belongs to; a long-running loop must survive any exception (log it once, try - again) — only `CancelledError` may end it. - - `backend/visionstate/backbones.json` (state sensors), `detectors.json` (object sensors) and - `readers.json` (reading sensors; also the wheel readers for mechanical counters, trained with - `tools/wheelreader` — see its README) are the model registries. Entries are never changed or - removed once released (a new model gets a new id); `python -m visionstate.backbones