# Court Pilot Agent Instructions ## Project purpose Court Pilot is a badminton umpire rotation and court-assignment application. It manages court officials, waiting queues, active court assignments, and optional service judges. ## Technology - Angular 22 with standalone components and strict TypeScript - Ionic Angular 9 UI components - Angular signals and RxJS - Dexie 4 / IndexedDB for local persistence - Angular CDK drag and drop - Tauri 2 for desktop packaging and updates - Capacitor configuration is present, but native mobile targets are not currently committed - Jasmine and Karma for unit tests - SCSS for styling ## Important paths - `src/app/` — Angular application - `src/app/tab1/` — court rotation and assignments (`/tabs/pilot`) - `src/app/tab2/` — court-official management (`/tabs/umpires`) - `src/app/tab3/` — settings (`/tabs/settings`) - `src/app/services/` — persistence and domain services - `src/app/i18n/` — typed English and Hungarian translations - `db.ts` — Dexie entities, database declaration, and schema version - `src/theme/` — Ionic theme variables - `src-tauri/` — Tauri/Rust desktop wrapper - `.github/workflows/release.yml` — tagged desktop release workflow - `snap/` — Linux Snap packaging - `docs/` — architecture and domain documentation ## Generated and dependency directories Do not manually edit generated output or installed dependencies: - `node_modules/` - `.angular/` - `www/` - `src-tauri/target/` - `src-tauri/gen/` - `snap-root/` when generated by release tooling ## Implementation conventions - Preserve strict TypeScript and strict Angular template checks. - Use standalone Angular components and import Ionic components from `@ionic/angular`. - Prefer `inject()` for dependency injection, matching current components and services. - Keep persistent-data access in services rather than directly in page components. - Expose reactive Dexie queries through signals when following an existing service pattern. - Use `readonly` for injected dependencies, signals, and derived state when reassignment is unnecessary. - Use `computed()` for state derived from signals. - Keep page-specific templates and SCSS beside their page component. - Component selectors use the `app-` prefix and kebab-case. - Component classes end in `Page` or `Component`. - Directive selectors use the `app` prefix and camelCase. - Format touched source and documentation files with Prettier. The root `.prettierrc` is the shared configuration; do not override it with personal formatting preferences. - Avoid formatting unrelated files or lines as part of a focused change. - Do not add dependencies unless the task clearly requires one. ## Domain and persistence rules - Treat changes to `db.ts` as database migrations, not ordinary interface edits. - Never change an existing Dexie schema version in place after release. Add a new `db.version(...)` declaration and document migration behavior. - “Court official” is the umbrella term; “umpire” and “service judge” are roles. - Every official must be in exactly one state: not on duty, waiting as umpire, waiting as service judge, assigned as umpire, or assigned as service judge. - Preserve FIFO queue ordering by numeric `order`; the lowest order is assigned next. - After a court rotation with service judges enabled, the former umpire joins the service-judge queue and the former service judge joins the umpire queue. - When the court count is reduced, remove assignments on eliminated court numbers so those officials become not on duty. - Confirm any other uncertain rotation rule with the maintainer; do not infer business rules solely from UI behavior. ## Localization - Do not hardcode new user-facing text when it should be translated. - Write both the English and Hungarian copy for every new user-facing string. - Add every translation key to both `en` and `hu` in `src/app/i18n/translations.ts`. - Use `TranslatePipe` in templates and `TranslationService` in TypeScript. - Keep placeholders consistent between languages. ## Platform-specific behavior - Guard Tauri APIs with `isTauri()` when code may execute in a browser. - Linux updates are delivered through Snap; the in-app Tauri updater is intentionally skipped on Linux. - Desktop updater changes must account for Windows and macOS release artifacts and the CrabNebula endpoint. - Browser, Windows, macOS, and Linux Snap are supported targets. - Android and iOS are not supported or planned at this stage; Capacitor configuration is retained only for possible future use. ## Commands - Node.js must use the `lts/jod` NVM alias, as declared in `.nvmrc`. - Documented commands target Bash on Linux, macOS, or Windows WSL. Use Bash explicitly for agent commands; fish's `nvm.fish` is unavailable in Bash. - Initialize Bash NVM once at the start of each shell session: `export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"; . "$NVM_DIR/nvm.sh" && nvm use` from the project root. `nvm use` reads `lts/jod` from `.nvmrc`. Reuse that initialized shell for subsequent npm commands. If a tool starts a fresh shell for each execution, initialize each new shell or use a persistent shell; environment changes do not carry between independent shells. Stop if initialization fails. Do not rely on `.bashrc` loading in noninteractive shells or fall back to system Node. - If `${NVM_DIR:-$HOME/.nvm}/nvm.sh` is missing, ask the user for permission before installing Bash NVM. Follow `docs/development.md#shell-and-nvm-setup` after approval. Keep existing fish NVM separate. - Install exact dependencies: `npm ci` - Start the Ionic development server: `npm start` - Build the web application: `npm run build` - Run unit tests: `npm test` - Run linting: `npm run lint` - Run Tauri CLI commands: `npm run tauri -- ` Tauri development intentionally uses port `8103`. `src-tauri/tauri.conf.json` expects that port, so its `beforeDevCommand` starts the project's Angular CLI with `serve --host=0.0.0.0 --port=8103`. Keep the command aligned with `devUrl`. Verify the full `npm run tauri dev` flow before claiming it works. ## Release versioning For every release, keep the same semantic version in: - `package.json` (and the generated root package entry in `package-lock.json`) - `src-tauri/tauri.conf.json` - `src-tauri/Cargo.toml` (and the generated root package entry in `src-tauri/Cargo.lock`) - `snap/snapcraft.yaml` The version displayed in the Settings UI must match these values. Before editing them, inspect Conventional Commits since the latest release tag and recommend the appropriate SemVer bump. If messages are ambiguous, inspect the code/configuration diff since that tag. Present the recommendation and reasoning, allow the developer to enter a different version, and wait for confirmation before changing files. Follow the manual checklist in `docs/development.md`; do not introduce release automation unless requested. During release version confirmation, ask whether to run the test suite or skip it. Running tests is the default; skip them only when the developer explicitly chooses to skip. Record any skipped tests in the release validation report. Lint, build, and Cargo checks still apply. After the confirmed version is synchronized, committed, and validated, create the matching lightweight local tag with `GIT_EDITOR=true git tag v`. Never tag uncommitted version changes. Do not push the tag without explicit permission because pushing it triggers the release workflow. ## Validation expectations Choose checks based on the affected area: 1. Run focused or related unit tests for behavior changes where practical. 2. Run `npm run lint` for TypeScript/template changes. 3. Run `npm run build` for application or build-configuration changes. 4. For Rust changes, run `cargo check` from `src-tauri/`. 5. For Tauri configuration or release changes, explain which platform-specific builds were not available locally. 6. Report commands actually run and any pre-existing failures; never claim unrun checks passed. ## Working practices - Read the relevant page, service, and tests before changing behavior. - Make focused changes and preserve unrelated user work. - Update tests and documentation when changing behavior, data models, workflows, or commands. - Prefer root-cause fixes over UI-only workarounds. - Ask for clarification when a change depends on an undocumented tournament or rotation rule.