# __APP_NAME__

<!-- >>> cmp:feature harness -->
<!-- cmp:generated evidence -->
[![No evidence receipt](https://img.shields.io/badge/evidence-none_yet-9E9E9E)](https://github.com/kvdm-co-pilot/create-cmp) — no verify receipt yet. Run `node qa/verify.mjs`.
<!-- /cmp:generated -->

A Kotlin / Compose Multiplatform app, generated by
[create-cmp](https://github.com/kvdm-co-pilot/create-cmp) with a **verification harness**:
the architecture, testing conventions, and definition of done are enforced mechanically, not
by convention. Start with [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md); AI collaborators
follow the contract in [`CLAUDE.md`](./CLAUDE.md).
<!-- <<< cmp:feature harness -->
<!-- >>> cmp:feature !harness -->
A Kotlin / Compose Multiplatform app, generated by
[create-cmp](https://github.com/kvdm-co-pilot/create-cmp) as a **minimal scaffold**: the
full app architecture with its tests, without the verification harness (one command adds
it — see "Full mode" below). Start with [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md);
AI collaborators follow the guide in [`CLAUDE.md`](./CLAUDE.md).
<!-- <<< cmp:feature !harness -->

## Quick start

```bash
# Android (device/emulator attached)
./gradlew :composeApp:installDebug

<!-- >>> cmp:feature dev-client -->
# Desktop dev-client with Compose Hot Reload — the daily dev loop
./gradlew :composeApp:hotRunDesktop --auto
<!-- <<< cmp:feature dev-client -->

<!-- >>> cmp:feature inspector -->
# Preview EVERY screen headlessly — no device, no emulator (agents: CLAUDE.md "UI feedback loop")
./gradlew :composeApp:renderScreens && node qa/preview-gallery.mjs
<!-- <<< cmp:feature inspector -->

# Unit tests (fast inner loop)
./gradlew :composeApp:desktopTest

<!-- >>> cmp:feature harness -->
# The verify lane — build + tests + every shipped gate, with an evidence receipt
node qa/verify.mjs
<!-- <<< cmp:feature harness -->
```

<!-- >>> cmp:feature inspector -->
**Watch and drive the app live from a browser:** with a debug build running on a
device/emulator, run `adb forward tcp:9500 tcp:9500` and open
`http://127.0.0.1:9500/inspect/remote` — a self-contained page that mirrors the running app
(~700ms refresh) with **click-to-tap driving the real device**. The human's window into the
same app the agent inspects structurally; also the way to watch an e2e run. Debug builds
only — release builds contain no inspector code.
<!-- <<< cmp:feature inspector -->

<!-- >>> cmp:feature ios -->
**iOS:** `cd iosApp && xcodegen generate && pod install`, then open
`iosApp.xcworkspace` in Xcode and run. (First time: `brew install xcodegen`.)
<!-- <<< cmp:feature ios -->

<!-- >>> cmp:feature firebase -->
**Firebase:** the scaffold ships a placeholder `google-services.json`. Wire your real project
before shipping — from Claude Code, the `cmp-firebase-connect` skill drives it end to end.
<!-- <<< cmp:feature firebase -->

## Project structure

```
<!-- >>> cmp:feature harness -->
specs/                       behavior specifications — new behavior starts here
<!-- <<< cmp:feature harness -->
composeApp/src/commonMain/   shared UI + logic (presentation / domain / data / di)
composeApp/src/commonTest/   unit tests — exemplar pattern in presentation/home
composeApp/src/desktopTest/  conformance gates + Compose UI tests + golden trees (JVM tier)
composeApp/src/androidMain/  Android entry point + platform actuals
<!-- >>> cmp:feature ios -->
composeApp/src/iosMain/      iOS actuals · iosApp/ is the Xcode shell
<!-- <<< cmp:feature ios -->
<!-- >>> cmp:feature dev-client -->
composeApp/src/desktopMain/  desktop dev-client (see docs/dev-client.md)
<!-- <<< cmp:feature dev-client -->
<!-- >>> cmp:feature harness -->
qa/verify.mjs                the verify lane — this repo's definition of done
qa/evidence/latest.json      the committed evidence receipt (see CONTRIBUTING.md)
<!-- <<< cmp:feature harness -->
<!-- >>> cmp:feature e2e -->
qa/e2e/                      Maestro E2E flows (device smoke)
<!-- <<< cmp:feature e2e -->
docs/                        architecture, testing, ADRs
```

## Documentation

| Doc | What |
|---|---|
| [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md) | Layers, data flow, how to add a feature |
| [`docs/TESTING.md`](./docs/TESTING.md) | The test pyramid, conventions, how to run everything |
| [`docs/adr/`](./docs/adr/) | Architecture decision records |
| [`CONTRIBUTING.md`](./CONTRIBUTING.md) | Workflow, definition of done, commit style |
<!-- >>> cmp:feature harness -->
| [`CLAUDE.md`](./CLAUDE.md) | The AI delivery contract |
<!-- <<< cmp:feature harness -->
<!-- >>> cmp:feature !harness -->
| [`CLAUDE.md`](./CLAUDE.md) | The AI working guide |
<!-- <<< cmp:feature !harness -->
| [`CHANGELOG.md`](./CHANGELOG.md) | Notable changes (Keep a Changelog) |

<!-- >>> cmp:feature !harness -->
## Full mode

This scaffold is deliberately light: no verify lane, evidence receipts, behavior specs,
approval gates, or generators. The full harness — a machine-checked definition of done,
with an audit trail — installs in place, idempotently, with one command:

```bash
npx create-cmp-cli harden
```
<!-- <<< cmp:feature !harness -->
<!-- >>> cmp:feature harness -->
## Verification

Every change must pass the verify lane (`node qa/verify.mjs`) and commit its updated receipt
(`qa/evidence/latest.json`). CI re-runs the same lane on every push — see
[`.github/workflows/verify.yml`](./.github/workflows/verify.yml).

## Verification enforcement

For AI sessions using Claude Code, a **Stop hook** (`.claude/settings.json`) makes
`CLAUDE.md`'s definition of done mechanical instead of honor-system.

**What it does:** when a session tries to end, the hook runs
`node "${CLAUDE_PROJECT_DIR:-.}/qa/receipt-check.mjs" --hook`. The path is anchored to the
project root because Claude Code runs a hook in the *session's* working directory, which is not
always this one — a session opened in a subdirectory would otherwise fail to find the script.
(`:-.` means an unset `CLAUDE_PROJECT_DIR` falls back to the current directory, so the hook is
never worse off than a plain relative path.) That script recomputes a sha256 hash over the project's
verified surface (`composeApp/`, `specs/`, `qa/`, and the Gradle build files — see
`qa/lib/inputs-hash.mjs`) and compares it to the `inputs.hash` in the committed
`qa/evidence/latest.json`. A `PASS` receipt whose hash matches the tree ends the session
silently. Source changed without a fresh `PASS` — or a missing, failed, or pre-mechanism
receipt — blocks with the specific reason and asks for `node qa/verify.mjs` plus a committed
receipt. It runs no build and no tests, only file hashing, so it costs milliseconds, and it
never fires twice in a row for the same stop.

Doc-only edits (`*.md`, `README`, `.github/`, `.claude/`) are deliberately outside the
verified surface: editing docs never invalidates a good receipt. The intent is transparent
enforcement, not a hostile one.

**Escape hatch:** this is your project. If you don't want the hook, delete the `Stop` block
in [`.claude/settings.json`](./.claude/settings.json) — nothing else depends on it locally.
CI independently enforces the same "receipt attests HEAD" check on every push
(`.github/workflows/verify.yml`), so disabling the local hook only trades an immediate
signal for a later one.
<!-- <<< cmp:feature harness -->

---

[![Built with create-cmp](https://img.shields.io/badge/Built%20with-create--cmp-7F52FF?logo=kotlin&logoColor=white)](https://github.com/kvdm-co-pilot/create-cmp) — the AI delivery harness for Compose Multiplatform. *(Just a static badge — delete this line if you prefer.)*
