|
1 | 1 | # Repository Guidelines |
2 | 2 |
|
3 | | -## Project Structure & Module Organization |
4 | | -- `Backend/`: Rust + Tauri application code (`src/`), commands (`src/tauri_commands/`), and plugin runtime. |
5 | | -- `Backend/built-in-plugins/`: git submodules for bundled plugins; initialize/update with `git submodule update --init --recursive`. |
6 | | -- `Frontend/`: TypeScript + Vite UI (`src/scripts/`, `src/styles/`, `src/modals/`), with Vitest tests colocated as `*.test.ts`. |
7 | | -- `docs/`: architecture and plugin docs plus UI assets. |
8 | | -- `packaging/flatpak/`: Flatpak manifests and packaging notes. |
9 | | -- Root files: workspace `Cargo.toml`, `Justfile`, and project docs (`README.md`, `ARCHITECTURE.md`, `SECURITY.md`). |
10 | | - |
11 | | -## Build, Test, and Development Commands |
12 | | -- `just build` (or `just build client|plugins`): build frontend, backend, and plugin bundles. |
13 | | -- `git submodule update --init --recursive`: fetch submodule content (required before plugin builds/tests). |
14 | | -- `just test`: workspace Rust tests + frontend TypeScript check + Vitest run. |
15 | | -- `just fix`: run `cargo fmt`, `cargo clippy --fix`, and frontend typecheck. |
16 | | -- `cargo tauri dev`: run the desktop app in development mode. |
17 | | -- `npm --prefix Frontend run dev`: run frontend-only Vite dev server. |
18 | | -- `just tauri-build`: production Tauri build wrapper. |
19 | | - |
20 | | -## Coding Style & Naming Conventions |
21 | | -- Rust: format with `cargo fmt --all`; keep clippy-clean (`cargo clippy --all-targets -- -D warnings`). |
22 | | -- TypeScript: 2-space indentation, ES modules, and small feature-focused files under `Frontend/src/scripts/features/`. |
23 | | -- Tests: name frontend tests `*.test.ts` near the implementation (example: `Frontend/src/scripts/lib/dom.test.ts`). |
24 | | -- Naming: use `snake_case` for Rust modules/functions and `camelCase` for TypeScript variables/functions. |
25 | | - |
26 | | -# ExecPlans |
27 | | - |
28 | | -When writing complex features or significant refactors, use an ExecPlan (as described in .agent/PLANS.md) from design to implementation. |
29 | | - |
30 | | -## Testing Guidelines |
31 | | -- Run full checks before opening a PR: `just test`. |
32 | | -- For frontend-only work, run `cd Frontend && npm test` and `npm exec tsc -- -p tsconfig.json --noEmit`. |
33 | | -- Add or update tests for behavior changes; prefer focused unit tests over broad snapshots. |
34 | | - |
35 | | -## Commit & Pull Request Guidelines |
36 | | -- Follow existing commit style: short imperative subject, optional scope prefix (examples: `backend: fix tauri precommands`, `ci: add wasm32-wasip1 target`, `chore(deps): bump @types/node`). |
37 | | -- Keep commits logically scoped; avoid mixing frontend/backend refactors unless required. |
38 | | -- Do not directly modify plugin code under `Backend/built-in-plugins/`; only update submodule pointers in this repository when explicitly requested. |
39 | | -- PRs should include: summary of behavior changes, linked issue(s), test evidence (command output), and screenshots for UI changes. |
40 | | -- Target the `Dev` branch for normal development work. |
41 | | - |
42 | | -## Security & Configuration Tips |
43 | | -- Review `SECURITY.md` before changing update, plugin, or network-related code paths. |
44 | | -- Do not commit secrets; keep local overrides in files like `.env.tauri.local`. |
45 | | -- Do not directly edit code inside git submodules (including `Backend/built-in-plugins/*`) unless the task explicitly requires a submodule update; treat submodule changes as pointer-only updates in this repo. |
| 3 | +## Project structure & module organization |
| 4 | + |
| 5 | +- `Backend/`: Rust + Tauri backend (`src/`), commands (`src/tauri_commands/`), plugin runtime (`src/plugin_runtime/`), and bundled plugin support (`src/plugin_runtime`, `scripts/`). |
| 6 | +- `Backend/built-in-plugins/`: local copies of bundled plugins (do not edit their code unless explicitly requested; update submodule pointers instead). |
| 7 | +- `Frontend/`: TypeScript + Vite UI code (`src/scripts/`, `src/styles/`, `src/modals/`), with Vitest tests colocated as `*.test.ts` files. |
| 8 | +- `docs/`: UX docs, plugin architecture notes, and plugin/theme packaging guides referenced by contributors. |
| 9 | +- `packaging/flatpak/`: Flatpak manifests and Flatpak-specific build notes. |
| 10 | +- Supporting files at the repo root include the workspace `Cargo.toml`, `Justfile`, `README.md`, `ARCHITECTURE.md`, `SECURITY.md`, and installer scripts. |
| 11 | + |
| 12 | +## Build, test, and development commands |
| 13 | + |
| 14 | +### Full builds |
| 15 | +- `just build` (or `just build client|plugins`): builds the backend, frontend, and plugin bundles from the workspace Justfile. |
| 16 | +- `just tauri-build`: production Tauri build wrapper (AppImage/Flatpak). `git submodule update --init --recursive` is required before building bundled plugins. |
| 17 | + |
| 18 | +### Running tests |
| 19 | + |
| 20 | +**All tests:** |
| 21 | +- `just test`: runs workspace Rust tests plus frontend type-check + Vitest via the Justfile. |
| 22 | + |
| 23 | +**Frontend (Vitest):** |
| 24 | +- `npm --prefix Frontend test`: run all tests |
| 25 | +- `npm --prefix Frontend test run`: run tests once (non-watch mode) |
| 26 | +- `npm --prefix Frontend test -- --run`: explicit non-watch mode |
| 27 | +- `npm --prefix Frontend test -- src/scripts/lib/dom.test.ts`: run single test file |
| 28 | +- `npm --prefix Frontend test -- --run -t "qs and qsa"`: run single test by name pattern |
| 29 | +- `npm --prefix Frontend test -- --watch`: watch mode for development |
| 30 | + |
| 31 | +**Backend (Rust):** |
| 32 | +- `cargo test --workspace`: run all Rust tests |
| 33 | +- `cargo test`: run tests for current crate |
| 34 | +- `cargo test --package openvcs_lib`: test specific crate |
| 35 | +- `cargo test --lib`: run only library tests (not integration tests) |
| 36 | +- `cargo test --lib -- branch`: run tests matching "branch" in name |
| 37 | +- `cargo test --lib -- --test-threads=1`: run tests sequentially (for flaky tests) |
| 38 | + |
| 39 | +### Linting and formatting |
| 40 | + |
| 41 | +- `just fix`: formatter/lint quick fixes (runs `cargo fmt`, `cargo clippy --fix`, and frontend type-check). |
| 42 | +- `cargo fmt --all`: format Rust code |
| 43 | +- `cargo clippy --all-targets -- -D warnings`: check Rust for issues |
| 44 | +- `cargo clippy --fix --all-targets --allow-dirty`: auto-fix clippy issues |
| 45 | +- `npm --prefix Frontend exec tsc -- -p tsconfig.json --noEmit`: TypeScript type-check |
| 46 | + |
| 47 | +### Development servers |
| 48 | + |
| 49 | +- `cargo tauri dev`: run the desktop app in dev mode (`Backend/` directory). |
| 50 | +- `npm --prefix Frontend run dev`: run the frontend-only Vite dev server. |
| 51 | + |
| 52 | +## Plugin runtime & host expectations |
| 53 | + |
| 54 | +- Plugin components live under `Backend/built-in-plugins/` and follow the manifest format in `openvcs.plugin.json`. Built-in bundles ship with the AppImage/Flatpak and are also built by the SDK (`openvcs build` + `openvcs dist`). |
| 55 | +- The backend loads plugin modules as Node.js runtime scripts (`*.mjs|*.js|*.cjs`) via `Backend/src/plugin_runtime/node_instance.rs`. |
| 56 | +- The canonical host/plugin contract is JSON-RPC over stdio with method names in `Backend/src/plugin_runtime/protocol.rs`. |
| 57 | +- When changing host APIs or runtime behavior, update protocol constants and runtime logic in `Backend/src/plugin_runtime`. |
| 58 | + |
| 59 | +## Coding style & conventions |
| 60 | + |
| 61 | +### Rust |
| 62 | + |
| 63 | +**Formatting:** |
| 64 | +- Run `cargo fmt --all` before committing |
| 65 | +- Use default Rust formatting (4-space indentation, etc.) |
| 66 | +- Keep lines under ~100 characters when reasonable |
| 67 | + |
| 68 | +**Naming:** |
| 69 | +- `snake_case` for modules, functions, and variables |
| 70 | +- `PascalCase` for structs, enums, and trait names |
| 71 | +- Prefix private fields with underscore (e.g., `self._field`) |
| 72 | +- Use descriptive names; avoid single letters except in tight loops |
| 73 | + |
| 74 | +**Imports:** |
| 75 | +- Group imports: std library first, then external crates, then local modules |
| 76 | +- Use `use` statements for frequently used items |
| 77 | +- Prefer absolute paths from crate root (`crate::module::Item`) |
| 78 | + |
| 79 | +**Error handling:** |
| 80 | +- Use `Result<T, E>` for fallible operations; avoid `panic!` in library code |
| 81 | +- Use `?` operator for propagating errors |
| 82 | +- Include context in error messages: `some_func().context("failed to load config")?` |
| 83 | +- Log warnings for recoverable errors with `log::warn` |
| 84 | +- Use `anyhow` for application code (commands, main) when context is needed |
| 85 | + |
| 86 | +**Types & patterns:** |
| 87 | +- Prefer `Arc<T>` for shared ownership across threads |
| 88 | +- Use `tokio` async runtime for I/O-bound async operations |
| 89 | +- Use `parking_lot` mutexes (faster than std) |
| 90 | +- Derive `Clone`, `Debug`, `Serialize`, `Deserialize` as needed |
| 91 | + |
| 92 | +### Documentation |
| 93 | + |
| 94 | +- **ALL code must be documented**, not just public APIs. This includes: |
| 95 | + - Rust: Use doc comments (`///` for items, `//!` for modules) for all functions, structs, enums, traits, and fields. |
| 96 | + - TypeScript: Use JSDoc comments (`/** ... */`) for all functions, classes, interfaces, and types. |
| 97 | +- All functions must include documentation comments. |
| 98 | +- All code files MUST be no more than 1000 lines; split files before they exceed this limit. |
| 99 | +- When you change behavior, workflows, commands, paths, config, or plugin/runtime expectations, ALWAYS update the relevant documentation in the same change, even if the user does not explicitly ask. |
| 100 | +- Include usage examples for complex functions. |
| 101 | +- Keep README files in sync with code changes. |
| 102 | +- Document configuration options and environment variables. |
| 103 | +- All new files must include the following copyright header: |
| 104 | + |
| 105 | +```rust |
| 106 | +// Copyright © 2025-2026 OpenVCS Contributors |
| 107 | +// SPDX-License-Identifier: GPL-3.0-or-later |
| 108 | +``` |
| 109 | + |
| 110 | +```typescript |
| 111 | +// Copyright © 2025-2026 OpenVCS Contributors |
| 112 | +// SPDX-License-Identifier: GPL-3.0-or-later |
| 113 | +``` |
| 114 | + |
| 115 | +### TypeScript |
| 116 | + |
| 117 | +**Formatting:** |
| 118 | +- 2-space indentation (no tabs) |
| 119 | +- Use ES modules (`import`/`export`) |
| 120 | +- Keep lines under ~100 characters when reasonable |
| 121 | +- Use semicolons at statement ends |
| 122 | + |
| 123 | +**Naming:** |
| 124 | +- `camelCase` for variables, functions, and methods |
| 125 | +- `PascalCase` for classes, types, and interfaces |
| 126 | +- Prefix private class members with underscore (e.g., `this._field`) |
| 127 | +- Use descriptive names; avoid abbreviations except common ones (e.g., `btn`, `cfg`) |
| 128 | + |
| 129 | +**Imports:** |
| 130 | +- Use absolute imports from project root when possible |
| 131 | +- Group imports: external libs, then relative `./` paths, then `../` paths |
| 132 | +- Prefer named imports: `import { foo, bar } from './module'` |
| 133 | +- Use type-only imports (`import type { Foo }`) when only using types |
| 134 | + |
| 135 | +**Types:** |
| 136 | +- Use explicit types for function parameters and return values |
| 137 | +- Prefer interfaces for object shapes, types for unions/intersections |
| 138 | +- Use `null` for "intentionally empty", `undefined` for "not yet set" |
| 139 | +- Avoid `any`; use `unknown` when type is truly unknown |
| 140 | + |
| 141 | +**Error handling:** |
| 142 | +- Use try/catch for async operations; always handle or re-throw |
| 143 | +- Use `Promise.catch(() => {})` for fire-and-forget async calls |
| 144 | +- Show user-facing errors via `notify()` from `lib/notify` |
| 145 | +- Log internal errors with console for debugging |
| 146 | + |
| 147 | +**UI patterns:** |
| 148 | +- Use `qs<T>('#id')` for single element queries from `lib/dom` |
| 149 | +- Use `qsa('.class')` for multiple elements |
| 150 | +- Use event delegation for list items |
| 151 | +- Keep feature modules focused and small (<200 lines when possible) |
| 152 | +- Colocate tests as `*.test.ts` next to the source file |
| 153 | + |
| 154 | +### Testing |
| 155 | + |
| 156 | +- Run `just test` before PRs |
| 157 | +- Frontend-only work: run `npm --prefix Frontend exec tsc -- -p tsconfig.json --noEmit` and `npm --prefix Frontend test` |
| 158 | +- Use Vitest's `describe`/`it`/`expect` for frontend tests |
| 159 | +- Use descriptive test names: `it('finds elements by selector')` |
| 160 | +- Use `beforeEach` to reset DOM state in DOM tests |
| 161 | + |
| 162 | +## ExecPlans |
| 163 | + |
| 164 | +- For multi-component features or refactors, create/update an ExecPlan (`Client/PLANS.md`). Outline design, component impacts, and how the plugin runtime is exercised. |
| 165 | + |
| 166 | +## Testing guidelines |
| 167 | + |
| 168 | +- Run `just test` before PRs; frontend-only work should at least cover `npm --prefix Frontend exec tsc -- -p tsconfig.json --noEmit` and `npm --prefix Frontend test`. |
| 169 | +- Use `cargo tauri dev` to verify runtime plugin interactions (especially when touching `Backend/src/plugin_runtime/`), and make sure `docs/plugin architecture.md` stays aligned with behavior. |
| 170 | + |
| 171 | +## Commit & PR guidelines |
| 172 | + |
| 173 | +- Use short, imperative commit subjects (optionally scoped, e.g., `backend: refresh plugin runtime config`). Keep changelist focused; avoid mixing UI and backend refactors unless necessary. |
| 174 | +- PRs should target the `Dev` branch, include a summary, issue links, commands/tests run, and highlight architecture implications (host API/protocol changes and security decisions). |
| 175 | +- Do not modify plugin code inside submodules unless explicitly asked; treat submodule updates as pointer bumps after upstream changes. |
| 176 | +- Keep this AGENTS (and other module-level copies you rely on) current whenever workflows, tooling, or responsibilities change so future contributors can find accurate guidance. |
| 177 | + |
| 178 | +## Security & configuration notes |
| 179 | + |
| 180 | +- Review `SECURITY.md` before making plugin, plugin-install, or network-related changes. |
| 181 | +- Keep secrets out of the repo; use `.env.tauri.local` for local overrides and do not check them in. If new config flags are introduced, document them in `docs/` and update relevant settings screens/logs. |
0 commit comments