Files
Toju/agents-docs/ENGINEERING.md
brogeby c48b6e9c94 docs: scaffold agent instruction tree
Add AGENTS.md, CLAUDE.md, and the agents-docs/ tree (workflow, lessons,
engineering standards, context map, ADR seed, feature template) plus a
domain-bearing CONTEXT.md for each of the six subdomains: toju-app,
electron, server, e2e, website, docs-site.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 00:02:02 +02:00

223 lines
11 KiB
Markdown
Raw Permalink 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.
# Engineering Standards & Workflows
This document defines shared engineering practices for **MetoYou / Toju**.
---
## Root README.md policy
`README.md` exists to answer:
- what this repo is
- how to run it locally
- where to find canonical documentation
Agents should update `README.md` when dev commands change, ports or startup steps change, or links to docs move.
Agents should **not** describe feature behavior, list API endpoints, or include request/response schemas. Canonical documentation lives under `agents-docs/` and (for product-client bounded contexts) under `toju-app/src/app/domains/<name>/README.md`.
---
## Testing standards
This repo runs two test stacks. Choose by what you're verifying.
### Unit / component tests — Vitest
- **Framework:** Vitest 4.x
- **Where it runs:** the Angular product client (`toju-app/`) and any package that imports `@toju-app/*` modules; Electron has colocated `*.spec.ts` files that are wired through the same root Vitest config.
- **Test suffix:** `*.spec.ts`
- **Location:** colocated with source (`message-rules.ts``message-rules.spec.ts`)
- **Run all:** `npm run test` (from repo root — runs `cd toju-app && vitest run`)
- **Watch:** `cd toju-app && npx vitest`
- **Single file:** `cd toju-app && npx vitest run <relative-path>`
- **Setup file:** `toju-app/src/test-setup.ts`
The server package does not currently have a test runner script — there is one colocated spec (`server/src/websocket/handler-plugin.spec.ts`) but no `test` script in `server/package.json`. If you add server-side tests, wire a `test` script and update this section.
### End-to-end — Playwright
- **Framework:** Playwright 1.59
- **Location:** `e2e/tests/` organized by feature area (`voice/`, `chat/`, `screen-share/`, `settings/`, `auth/`)
- **Run:** `npm run test:e2e` (headless), `npm run test:e2e:ui`, `npm run test:e2e:debug`
- **Report:** `npm run test:e2e:report` (serves `test-results/html-report`)
- **Fixtures & page objects** live in `e2e/` alongside `tests/`
E2E tests exercise the real Electron app against the real signaling server. The `.agents/skills/playwright-e2e/SKILL.md` describes the convention this repo uses for E2E test design — read it before adding new tests.
### TDD discipline
Write the failing test first. Run it, watch it fail, then write the smallest code that makes it pass. This rule is non-negotiable (see `/AGENTS.md` § CRITICAL).
Integration / cross-package work that needs a real database can rely on Electron's TypeORM + sql.js setup (in-memory by default) — no Testcontainers required.
---
## TypeScript standards
- Strict mode is enabled across all packages
- Avoid `any` unless absolutely necessary; document why if used
- Prettier (`.prettierrc.json`: `printWidth: 150`, single quotes, no trailing commas) handles formatting of Angular HTML templates only — ESLint stylistic rules handle TypeScript/JavaScript formatting
- Angular CLI / `tsc -p tsconfig.electron.json` / `cd server && tsc` perform the actual type checks; there is no single repo-wide `typecheck` script
- The repository uses npm workspaces (`npm@10.9.2`); cross-package imports go through workspace package names, not relative `../../` paths
---
## Naming conventions
Files and folders are predominantly **kebab-case**, with a few well-established suffixes:
- Angular components: `chat-messages.component.ts`, `user-list.component.html`, `*.component.scss`
- Angular services: `link-metadata.service.ts`
- Angular directives: `chat-image-proxy-fallback.directive.ts`
- Domain rules (pure functions): `message.rules.ts`, `link-embed.rules.ts`
- Domain models: `chat-messages.model.ts`
- NgRx slices: `chat.actions.ts`, `chat.reducer.ts`, `chat.effects.ts`, `chat.selectors.ts`
- CQRS handlers (server and electron): `registerUser.ts`, `deleteServer.ts`, `upsertServer.ts`**camelCase** for handler files (mirrors the command/query name)
- Test files: `<name>.spec.ts` (Vitest), `<feature>.spec.ts` (Playwright)
- Migrations (TypeORM): `<timestamp>-<name>.ts` in `electron/migrations/` and `server/migrations/`
Types, interfaces, classes, and Angular component classes: `PascalCase`. Functions, variables, NgRx action props: `camelCase`. Constants: `SCREAMING_SNAKE_CASE`.
When in doubt, mimic the closest existing file in the same folder.
---
## Error handling
- Use typed errors. Never `throw 'string literal'`
- Never swallow errors silently — at minimum, log with enough context to find the call site
- Centralize cross-cutting error handling: Express error middleware on the server, NgRx effect `catchError` in the product client, and IPC error envelopes in Electron handlers
- Surfacing errors to the user is a UX concern — degrade gracefully (toast, retry button, offline banner) rather than crashing the renderer
---
## Database guidelines
Persistence uses **TypeORM 0.3** with **sql.js / SQLite** in both the Electron desktop shell and the signaling server.
- **Electron data source:** `electron/data-source.ts` — entities in `electron/entities/`, migrations in `electron/migrations/`
- **Server data source:** wired up under `server/src/db/` — entities in `server/src/entities/`, migrations in `server/src/migrations/`
- Always write a migration for schema changes. Generate with `npm run migration:generate` (Electron) or the equivalent inside `server/`
- Run pending migrations: `npm run migration:run` (Electron)
- Never edit a migration after it has shipped — write a new one
- Entity classes use TypeORM decorators; keep persistence concerns out of domain `*.rules.ts` files
- Schema changes are usually **hard to reverse** and **surprising without context** — see `agents-docs/AGENTS_ADRS.md` for when to also write an ADR
---
## Realtime, IPC, and plugins
These are the three cross-context contracts that change most often. Treat each as a public contract that requires `agents-docs/features/` updates when it changes:
- **WebSocket messages** between client and server — schemas live under `server/src/websocket/` and `toju-app/src/app/infrastructure/realtime/`
- **IPC channels** between Electron preload and renderer — surface defined in `electron/preload.ts` and the `api/` directory
- **Plugin manifests** consumed by `electron/plugin-library.ts` — the runtime contract that third-party plugins depend on
Behavioral changes to any of these qualify as a feature-doc update under the rule in `/AGENTS.md`.
---
## CI/CD
- CI runs on **Gitea Workflows** (a GitHub Actionscompatible runner) — workflow files in `.gitea/workflows/`:
- `release-draft.yml` — queues release builds on push to `main` / `master`
- `publish-draft-release.yml` — publishes draft releases
- `deploy-web-apps.yml` — deploys the marketing site and Docusaurus docs
- All checks must pass before merging a PR
- Workflow status is visible in the Gitea PR view; use the web UI or `tea` CLI to inspect runs
There is **no pre-commit hook** configured (no Husky, no pre-commit, no lefthook). Lint/build are enforced by CI, not by local hooks.
---
## Commit message conventions
Use **Conventional Commits** with no scope. The recent history is consistent on this:
```
feat: Update how messages load and sync, allow plugins to import messages
fix: Mobile style fixes and other small ui fixes
perf: server navigation
refactor: Remove hardcoded values
test: Ensure tests work after latest changes
```
Allowed prefixes (observed across the last 100 commits): `feat`, `fix`, `chore`, `docs`, `perf`, `refactor`, `test`. Subject is sentence case with no trailing period.
If your change resolves a Gitea issue, add `Fixes #<n>` (or `Relates to #<n>`) in the PR body — Gitea supports the same auto-close keywords as GitHub.
---
## Issue linking
- Issues live in the Gitea instance at `git.azaaxin.com/myxelium/Toju`
- Reference them in PR bodies with `Fixes #<n>` (auto-closes on merge) or `Relates to #<n>` (cross-reference only)
- Commits themselves do not need issue numbers — keep subjects clean and Conventional
---
## Commands reference
Run these from the repository root unless otherwise noted.
```bash
# --- setup ---
npm install # install root + workspaces
cd server && npm install # server has its own lockfile
cd website && npm install # only if working on the marketing site
cd docs-site && npm install # only if working on app/plugin docs
# --- common dev flows ---
npm run dev # full stack: server + Angular client + Electron (via dev.sh)
npm run start # Angular product client only (ng serve on :4200)
npm run electron:dev # Angular client + Electron, no signaling server
npm run server:dev # signaling server only (ts-node-dev)
# --- testing ---
npm run test # toju-app Vitest suite
npm run test:e2e # Playwright (headless)
npm run test:e2e:ui # Playwright UI mode
npm run test:e2e:debug # Playwright debug
npm run test:e2e:report # serve last Playwright HTML report
# --- type / build (also serves as typecheck) ---
npm run build # Angular product client → dist/client
npm run build:electron # tsc -p tsconfig.electron.json → dist/electron
npm run build:docs # Docusaurus → docs-site/build
cd server && npm run build # server tsc
npm run build:all # all of the above
# --- lint / format ---
npm run lint # eslint .
npm run lint:fix # format + sort:props + eslint --fix
npm run format # prettier on Angular HTML templates only
npm run format:check # prettier --check on HTML templates
# --- database migrations (Electron) ---
npm run migration:generate # autogenerate from entity diff
npm run migration:create # empty migration scaffold
npm run migration:run # apply pending
npm run migration:revert # roll back last
```
---
## Completion checklist
Before marking work complete:
- [ ] Tests written before implementation
- [ ] All tests passing (`npm run test`, plus `npm run test:e2e` if behavior is user-visible)
- [ ] `npm run lint` passes
- [ ] Affected package builds: `npm run build` / `npm run build:electron` / `cd server && npm run build`
- [ ] Naming conventions followed
- [ ] Errors handled
- [ ] Security considered (no secrets in code, no plaintext token logging, no IPC handler accepting arbitrary file paths)
- [ ] Feature docs updated if contract/schema/invariant changed (see `agents-docs/AGENTS_FEATURES.md`)
- [ ] `CONTEXT.md` updated if a domain term was resolved or introduced (see `agents-docs/AGENTS_CONTEXT.md`)
- [ ] ADR written if a hard-to-reverse decision was made (see `agents-docs/AGENTS_ADRS.md`)
- [ ] Lesson recorded in `agents-docs/LESSONS.md` if this session produced a correction, revert, or hidden constraint (see triggers in `agents-docs/AGENT_WORKFLOW.md`)
- [ ] PR opened with summary and linked issues
- [ ] Gitea Workflows checks passing