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

11 KiB
Raw Permalink Blame History

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.tsmessage-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.tscamelCase 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.

# --- 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