From 5acfc4a1222457dd9eb35f183293b90467694931 Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Tue, 25 Aug 2026 21:26:39 +0200 Subject: [PATCH] docs(llms): setup agents documentation --- .github/skills/code-review/SKILL.md | 46 ++++++++++++++ AGENTS.md | 22 +++++++ docs/agent-guides/architecture.md | 85 ++++++++++++++++++++++++++ docs/agent-guides/change-assessment.md | 30 +++++++++ docs/agent-guides/code-quality.md | 48 +++++++++++++++ docs/agent-guides/domain-invariants.md | 42 +++++++++++++ docs/agent-guides/routing-and-cloud.md | 49 +++++++++++++++ docs/agent-guides/security.md | 42 +++++++++++++ docs/agent-guides/testing.md | 52 ++++++++++++++++ docs/agent-guides/workflow.md | 69 +++++++++++++++++++++ 10 files changed, 485 insertions(+) create mode 100644 .github/skills/code-review/SKILL.md create mode 100644 AGENTS.md create mode 100644 docs/agent-guides/architecture.md create mode 100644 docs/agent-guides/change-assessment.md create mode 100644 docs/agent-guides/code-quality.md create mode 100644 docs/agent-guides/domain-invariants.md create mode 100644 docs/agent-guides/routing-and-cloud.md create mode 100644 docs/agent-guides/security.md create mode 100644 docs/agent-guides/testing.md create mode 100644 docs/agent-guides/workflow.md diff --git a/.github/skills/code-review/SKILL.md b/.github/skills/code-review/SKILL.md new file mode 100644 index 000000000..4c8619612 --- /dev/null +++ b/.github/skills/code-review/SKILL.md @@ -0,0 +1,46 @@ +--- +name: code-review +description: Review Ontime changes for concrete correctness, architecture, testing, routing, security, and maintenance issues. For GitHub Copilot review. +--- + +# Review Ontime changes + +Review as a maintainer. Find material defects, not speculative advice, style preferences, or generic checklists. Approve when no material issue remains. + +## Load relevant context + +Read the full diff, PR description, linked issue, tests, and nearby owning code. Then load only applicable guides: + +- Every non-trivial review: [change assessment](../../../docs/agent-guides/change-assessment.md) +- Module placement, server layers, client state, shared packages: [architecture](../../../docs/agent-guides/architecture.md) +- Tests or changed behaviour: [testing](../../../docs/agent-guides/testing.md) +- Comments, abstractions, naming, complexity: [code quality](../../../docs/agent-guides/code-quality.md) +- Authentication, external input, files, integrations, assets, secrets: [security](../../../docs/agent-guides/security.md) +- Routes, URLs, websockets, authentication, cookies, presets, assets: [routing and cloud](../../../docs/agent-guides/routing-and-cloud.md) +- Rundowns, timers, persistence, imports, cache, realtime: [domain invariants](../../../docs/agent-guides/domain-invariants.md) +- Commands, imports, dependencies, formatting, CI claims: [workflow](../../../docs/agent-guides/workflow.md) + +Check a guide and nearby canonical code before citing an Ontime convention. Skip unrelated guides. + +## Review order + +1. Establish intent and affected runtime surfaces. +2. Read tests first. Identify claimed behaviour and coverage. +3. Trace implementation, errors, and state transitions. +4. Check correctness/data integrity, security, architecture/testability, cloud routing, lifecycle/performance, maintainability. +5. Verify claimed checks. Never claim unobserved results. + +Passing tests do not prove architecture, routing, comments, or error paths. Review changed behaviour only; include existing problems only when the diff worsens or relies on them. + +## Findings + +Report only concrete, actionable issues. Each finding: tight line range, direct defect, impact and trigger, smallest viable remedy when unclear. + +- **P0 — Critical:** data loss, exploitable vulnerability, broadly broken production. Blocks merge. +- **P1 — High:** likely correctness failure or major supported-deployment regression. Blocks merge. +- **P2 — Medium:** real edge-case defect, architecture regression, missing business-rule test, stale comment, meaningful maintenance risk. Normally blocks merge. +- **P3 — Low:** local improvement with limited impact. No subjective style or tool-managed formatting. + +Order by priority. Prefer few high-confidence findings. No praise or checklist before findings. If none, say so and note verification gaps or residual risk. + +Then give one concise PR-level value/risk/complexity assessment. Never repeat it per finding. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..1de0eb5be --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,22 @@ +# Ontime agent guide + +Make the smallest maintainable change. Keep scope narrow. Inspect nearby code first. Reuse helpers and boundaries when semantics match. + +## Load only relevant guides + +- Commands, validation, formatting, imports, PRs: [workflow](docs/agent-guides/workflow.md). +- Non-trivial planning, implementation, review: [change assessment](docs/agent-guides/change-assessment.md). +- Module placement, server layers, client state, shared packages: [architecture](docs/agent-guides/architecture.md). +- Tests or changed behaviour: [testing](docs/agent-guides/testing.md). +- Comments, naming, abstractions, maintainability: [code quality](docs/agent-guides/code-quality.md). +- Authentication, external input, files, integrations, assets, secrets: [security](docs/agent-guides/security.md). +- Navigation, URLs, API paths, websockets, redirects, cookies, static assets: [routing and cloud](docs/agent-guides/routing-and-cloud.md). +- Rundowns, timers, imports, persistence, cache, websockets: [domain invariants](docs/agent-guides/domain-invariants.md). + +Load multiple guides when needed. Skip unrelated guides for mechanical work. + +## Before handoff + +- Check the final diff for scope, stale comments, temporary code, redundant tests, generated files. +- If work reveals a missing, stable, reusable system, domain, or product invariant, update its owning guide. Exclude guesses, one-off bugs, and implementation details. +- Follow [workflow verification](docs/agent-guides/workflow.md). Report only observed results. diff --git a/docs/agent-guides/architecture.md b/docs/agent-guides/architecture.md new file mode 100644 index 000000000..5531057ec --- /dev/null +++ b/docs/agent-guides/architecture.md @@ -0,0 +1,85 @@ +# Ontime architecture + +Use for module placement or cross-boundary changes. + +## Direction + +Dependencies point toward pure domain logic: + +```text +HTTP request + -> validation / router or controller + -> service orchestration + -> pure domain utilities + +service orchestration + -> DAO / stores / adapters / external clients +``` + +Keep a layer only for clearer ownership, isolated side effects, or direct business-rule tests. + +## Reuse and ownership + +Before adding a module, helper, service, or interface, find the concept owner and inspect callers. + +1. Reuse when the contract already matches. +2. Extend for the same concept when the contract stays coherent. +3. Keep local when reuse needs flags, broad optional inputs, unrelated modes, or leaky terms. +4. Generalise only after stable common behaviour appears across real callers. + +Do not duplicate canonical rules or distort an abstraction to force reuse. Small local duplication can beat coupling unrelated concepts. + +## Server + +### Routers and controllers + +Routers declare paths and middleware. Controllers map validated HTTP input to typed service arguments, then results/errors to responses. + +Keep reusable calculations, domain decisions, transformations, persistence workflows, and integration coordination out of handlers. Simple reads may stay direct when a service would only pass through. + +### Services + +Services orchestrate use cases and side-effect boundaries. Make ordering and effects visible. Move substantial branching, calculation, comparison, parsing, and transformation to pure utilities. + +### Pure utilities + +Pass required state, config, and time explicitly. No I/O, stores/globals, logging, websocket publication, browser inspection, or caller-owned mutation unless explicitly contracted. + +Use focused Vitest coverage. Colocate feature logic. Move to `ontime-utils` only for genuine cross-package use. + +### State and boundaries + +- DAOs/data providers: persistence. +- Stores: mutable runtime state. +- Adapters/clients: external protocols and integrations. +- Validators/parsers: protect boundaries before domain logic. +- Commit state before dependent notifications or invalidations. + +Old layering exceptions are context, not precedent. Improve touched boundaries only through focused, behaviour-preserving moves. + +## Client + +- `common/api`: HTTP transport. +- `common/hooks-query`: TanStack Query reads, mutations, keys, cache, invalidation. +- `features`: reusable product capabilities and domain behaviour. +- `views`: route-level composition. +- `common`: genuinely cross-feature code. + +Keep substantial rules out of JSX, effects, and handlers. Use tested, colocated pure utilities. TanStack Query owns server state; established Zustand/context owns local state. No parallel caches. + +Limit subscriptions with selectors. Keep effect dependencies stable. Clean up listeners, intervals, external resources. + +## Shared packages + +- `ontime-types`: shared contracts; type-focused. +- `ontime-utils`: environment-independent, side-effect-free shared logic. +- Never import application layers into shared packages. +- Keep feature-specific helpers with their owner, even when used by another file. + +## Review prompts + +- Business rule understandable/testable without app startup? +- Transport, orchestration, state, transformation separated? +- Existing owner reused without forcing unrelated behaviour? +- Abstraction removes concepts rather than relocating them? +- Smallest focused remedy clear? diff --git a/docs/agent-guides/change-assessment.md b/docs/agent-guides/change-assessment.md new file mode 100644 index 000000000..a3e2031b3 --- /dev/null +++ b/docs/agent-guides/change-assessment.md @@ -0,0 +1,30 @@ +# Change assessment + +Use before non-trivial planning/implementation and during non-trivial review. Let it shape scope and verification; avoid process theatre. + +## Rate three dimensions + +- **Value** — concrete user, product, operational, or maintenance benefit; include urgency. +- **Risk** — regression likelihood/impact: data loss, security, cloud incompatibility, disruption, hard rollback. +- **Complexity** — concepts, dependencies, layers, states, verification surfaces; not line count. + +Use `Low`, `Medium`, or `High`. Give one evidence-based sentence each. No pseudo-precise scores. + +```markdown +## Assessment + +- Value: High — +- Risk: Medium — +- Complexity: Low — +- Recommendation: Proceed | Reshape | Defer — +``` + +One assessment per overall change. + +- High value never excuses unmanaged risk/complexity. +- High risk needs earlier proof, narrower increments, rollback, or stronger checks. +- High complexity needs clearer boundaries and smaller steps, not automatic abstraction. +- Low value plus high risk/complexity suggests reshape or defer. +- Revise after material scope discovery. + +Plans: assessment before steps. Reviews: findings first, then assessment. Assessment informs; never replaces user intent or evidence. diff --git a/docs/agent-guides/code-quality.md b/docs/agent-guides/code-quality.md new file mode 100644 index 000000000..a4c85cbc9 --- /dev/null +++ b/docs/agent-guides/code-quality.md @@ -0,0 +1,48 @@ +# Simplicity and maintainability + +Use for abstractions, comments, helpers, naming, or structural complexity. + +## Simplicity + +Choose the smallest explicit, testable design. No extension points, generic engines, wrappers, or config for hypothetical needs. + +- Prefer direct flow over clever expressions or scattered conditions. +- Extract only to name a rule, enable pure tests, or remove meaningful duplication. +- Keep abstractions only when they reduce reader-held concepts. +- Reuse the concept owner when semantics match. +- Do not add flags, optional branches, generic names, or extension points to merge unlike cases. +- Prefer focused local helpers over generic APIs exposing unrelated modes. +- Keep scope narrow; note unrelated cleanup. +- Delete clearly obsolete branches, harnesses, and shims. Ask when ownership or compatibility is unclear. + +## Comments + +Keep comments for: + +- non-obvious intent or invariants; +- necessary ordering, timing, mutation, or side effects; +- browser, Electron, cloud, or protocol constraints; +- workaround reasons and removal conditions; +- public contracts names/types cannot express. + +Remove comments that: + +- narrate code or names; +- number obvious steps; +- explain mechanics better expressed by code; +- preserve removed history; +- claim untested behaviour; +- use banners to hide oversized modules. + +Update adjacent comments with code. Stale comments are defects. + +## Naming and types + +- Prefer Ontime terms over vague `data`, `result`, `item`. +- Prefer explicit/discriminated types over `any`, broad casts, optional fields, non-null assertions, silent fallbacks. +- Handle unions/enums exhaustively when future cases could be unsafe. +- Keep public functions focused enough to avoid long contract explanations. + +## Review standard + +Do not demand personal style. Report complexity only when it risks maintenance, hides rules, blocks focused tests, duplicates ownership, or makes changes unsafe. Suggest reuse only after verifying the existing contract fits without added genericity. diff --git a/docs/agent-guides/domain-invariants.md b/docs/agent-guides/domain-invariants.md new file mode 100644 index 000000000..01fe8df35 --- /dev/null +++ b/docs/agent-guides/domain-invariants.md @@ -0,0 +1,42 @@ +# Ontime domain invariants + +Load only for touched domains. Add only stable, recurring invariants; not one-off bugs. + +## Rundowns and entries + +- Keep `entries`, `order`, `flatOrder` normalised. +- Keep group membership, group entry lists, child `parent` references consistent. +- Preserve entry identity and supported types across patch, clone, group, ungroup, reorder. +- Distinguish loaded vs background rundown. Prefer explicit rundown ID over global current state. +- No caller-owned rundown mutation unless explicitly contracted. + +## Persistence, realtime, cache + +- No partial commit on failure. +- Preserve revision/transaction semantics for loaded and background rundowns. +- Persist before websocket refetches, runtime updates, integration notifications, or cache assumptions. +- Notify only invalidated consumers; never leave client cache stale. +- Avoid duplicate listeners, notifications, invalidations, lifecycle effects. +- Reconnect/refetch must converge on authoritative state. +- Align query keys and websocket refetch keys with the changed resource. + +## Timers + +When relevant, cover interactions among: + +- midnight/day offsets; +- linked events/gaps; +- delays/skipped entries; +- count-to-end; +- absolute/relative offsets; +- warning, danger, finish, roll, end-action transitions; +- loaded/next-event state. + +Pass time/state explicitly to keep rules deterministic and unit-testable. + +## Imports and migrations + +- Treat project files, spreadsheets, custom fields, migrated data as untrusted. +- Preserve fields the import/migration does not own. +- Validate/parse into the current model before runtime logic. +- Avoid source mutation; test round trips and non-mutation when preservation matters. diff --git a/docs/agent-guides/routing-and-cloud.md b/docs/agent-guides/routing-and-cloud.md new file mode 100644 index 000000000..9c26ea939 --- /dev/null +++ b/docs/agent-guides/routing-and-cloud.md @@ -0,0 +1,49 @@ +# Routing and Ontime Cloud + +Use for navigation, URLs, endpoints, websockets, auth, cookies, assets, redirects, presets, or local-storage scope. + +## Deployment invariant + +Support root and runtime-prefixed deployments: + +```text +local: http://localhost:4001/timer +cloud: https://cloud.example/client-hash/timer +``` + +Prefix is deployment data. Never assume `/`. + +## Client + +- `apps/client/src/externals.ts`: derives `baseURI`, `serverURL`, `websocketUrl` from document base/current origin. +- `BrowserRouter`: uses `baseURI` basename. +- APIs/assets: use `common/api/constants.ts` or base-aware helpers. +- App navigation: use React Router. Never strip/guess/re-add prefix from `window.location.pathname`. +- Persisted browser state: use existing base-aware scoping where prefixes need isolation. + +## Server + +- `updateRouterPrefix()` in `apps/server/src/externals.ts`: normalises `ROUTER_PREFIX`. +- `apps/server/src/app.ts`: mounts routes below that prefix. +- Domain routers: paths relative to mount; never derive prefix. +- Websockets, auth redirects, cookie paths, share URLs: preserve prefix. + +## URL rules + +Use `URL`, React Router, or existing helpers instead of string manipulation. Preserve: + +- leading/trailing slashes and runtime prefix; +- query params, auth tokens, navigation locks; +- preset aliases and canonical view paths; +- `https`/`wss` behind proxies; +- static/user asset paths. + +Never infer Ontime Cloud from hostname alone. Generated base markup marks cloud; runtime prefixes also serve non-cloud reverse proxies. + +## Cloud capabilities + +Gate unavailable local-network integrations in cloud, including OSC output. Keep server behaviour and UI availability aligned. + +## Verification + +Test both root and a prefix such as `/client-hash`. Include relevant queries, redirects, cookies, websocket paths, presets, assets. Root-only routing coverage is incomplete. diff --git a/docs/agent-guides/security.md b/docs/agent-guides/security.md new file mode 100644 index 000000000..77622818a --- /dev/null +++ b/docs/agent-guides/security.md @@ -0,0 +1,42 @@ +# Security boundaries + +Use for auth, external input, files, integrations, assets, URLs, or secrets. + +## Untrusted inputs + +Validate/parse before trust: + +- HTTP bodies, params, headers, cookies, websocket messages; +- project files, migrations, spreadsheets, imports; +- custom HTML/CSS/views, translations, served assets; +- automation payloads, third-party responses; +- externally supplied paths/filenames. + +Validate shape and domain constraints at the owning boundary. Keep existing parser/validation layers; avoid downstream defensive casts. + +## Authentication and authorisation + +- Keep protected routers behind auth middleware in `apps/server/src/app.ts`. +- Preserve auth across prefixed routes, redirects, websockets, generated links. +- Scope session cookies to runtime prefix; isolate hosted clients. +- Authentication never grants arbitrary file, path, project, or rundown access. + +## Files, URLs, integrations + +- Use established path/file helpers. Reject traversal and unexpected types. +- Build URLs with `URL` or existing helpers. Check open redirects, SSRF, protocol changes, token leaks. +- Encode/constrain untrusted HTML, CSS, filenames, headers, log values. +- Preserve cloud limits on local-network capabilities. + +## Secrets and diagnostics + +- Never commit/log passwords, hashes, tokens, credentials, cookies, private project content. +- Errors: useful, but no internal paths, stacks, credentials, sensitive payloads. +- Keep tokens in existing session/authenticated-share flows. Avoid new URL-token patterns. + +## Review prompts + +- Where does input become trusted? +- Validation once at owner, then useful type? +- Can one prefixed client cross another client's session/assets? +- Can logs, responses, redirects, URLs leak secrets? diff --git a/docs/agent-guides/testing.md b/docs/agent-guides/testing.md new file mode 100644 index 000000000..a6a1bf977 --- /dev/null +++ b/docs/agent-guides/testing.md @@ -0,0 +1,52 @@ +# Testing strategy + +Use for changed behaviour or tests. + +## Layers + +### Pure unit + +Put detailed business-rule coverage on pure functions. Test public inputs/outputs with Vitest: relevant boundaries, invalid input, ordering, rollover, errors. + +Every bug fix needs a regression test that fails before the fix. Prefer behaviour over mocks/implementation assertions. + +### Service and state + +Use service, DAO, store, or hook tests for orchestration: transitions, transactions, persistence, cache, notifications, external effects. + +Do not repeat all pure cases here. Prove delegation and sequencing. + +### End-to-end + +Reserve Playwright for key journeys and high-risk cross-layer integrations: edit/run rundown, playback, imports, rundown switching, cloud-prefixed navigation. + +No E2E for edges already proven in lower layers. Add E2E only when lower layers cannot prove the user-facing integration. + +## Compact before handoff + +Development harnesses may be broad, repetitive, diagnostic, temporary. Before handoff: + +1. Identify distinct required behaviours/regressions. +2. Keep the smallest readable set that catches them. +3. Parameterise repetition only when the table reads better. +4. Remove diagnostic assertions, redundant permutations, temporary fixtures, private-detail coupling. +5. Keep rare cases that encode real domain rules. + +Optimise for future readers, not minimum line count. + +## Quality + +- Name tests by observable behaviour. +- Keep setup local/explicit unless a fixture improves comprehension. +- Avoid arbitrary waits, wall-clock dependence, cross-test state, weak assertions. +- Prefer realistic typed fixtures over large snapshots or masking casts. +- Test non-mutation when promised. +- No tests for trivial type/format changes or framework behaviour Ontime does not own. + +## Review prompts + +- Business logic directly unit-testable? +- Test catches the reported bug/regression? +- Cases distinct, not repeated path? +- Temporary harness leaked? +- E2E justified by cross-layer risk? diff --git a/docs/agent-guides/workflow.md b/docs/agent-guides/workflow.md new file mode 100644 index 000000000..07245ed26 --- /dev/null +++ b/docs/agent-guides/workflow.md @@ -0,0 +1,69 @@ +# Workflow and repository conventions + +Use for commands, imports, formatting, CI, dependencies, PRs. + +## Workspaces + +Confirm names from `package.json`. + +| Package | Workspace name | +| ---------------- | --------------------- | +| Client | `ontime-ui` | +| Server | `ontime-server` | +| Electron | `ontime-electron` | +| Resolver | `@getontime/resolver` | +| CLI | `@getontime/cli` | +| Shared types | `ontime-types` | +| Shared utilities | `ontime-utils` | + +Run from repo root: `pnpm --filter