92 lines
6.4 KiB
Markdown
92 lines
6.4 KiB
Markdown
# Repository Guidelines (Agent-Facing)
|
||
|
||
## What This Project Is
|
||
- Guided demo platform built on FastAPI + Playwright to showcase browser automations and GraphQL-backed data flows.
|
||
- Entry point: `src/guide/app/main.py`; CLI runner: `python -m guide` (respects `HOST`/`PORT`).
|
||
- Personas and host targets are data-driven via YAML, not hardcoded.
|
||
- App state wiring happens in `create_app()`: loads settings, builds `PersonaStore`, `ActionRegistry`, and `BrowserClient`, then stashes them on `app.state` for dependency injection.
|
||
|
||
## Code & Module Layout
|
||
- Source root: `src/guide/app/`
|
||
- `actions/` — FastAPI-triggered demo actions; keep them thin, declarative, and side-effect scoped.
|
||
- `auth/` — pluggable MFA/auth helpers; avoid coupling to specific IdPs.
|
||
- `browser/` — `BrowserClient` and Playwright wrappers; centralize navigation, timeouts, and tracing.
|
||
- `core/` — settings, logging, dependency wiring; `AppSettings` drives runtime config and reads YAML/env merges.
|
||
- `errors/` — `GuideError` hierarchy; routes standardize error responses.
|
||
- `raindrop/` — GraphQL client + operations; isolate schemas/operations from business logic.
|
||
- `strings/` — selectors, labels, copy, GraphQL strings; no inline literals in actions.
|
||
- `models/` — domain/persona models; prefer pydantic v2 models with explicit types.
|
||
- `utils/` — shared helpers; keep <300 LoC and avoid circular deps.
|
||
- Config files: `config/hosts.yaml`, `config/personas.yaml` describe targets/personas; never embed secrets. ENV overrides: `RAINDROP_DEMO_BROWSER_HOSTS_JSON` and `RAINDROP_DEMO_PERSONAS_JSON` accept JSON arrays of objects matching the YAML shape.
|
||
|
||
## Development Workflow
|
||
- Install deps: `pip install -e .`
|
||
- Type check: `basedpyright src`
|
||
- Sanity compile: `python -m compileall src/guide`
|
||
- Run API (dev): `python -m guide`
|
||
- Preferred loop: edit → `basedpyright` → `compileall` → manual smoke via CLI or hitting local `/docs`.
|
||
- API surface (2025-11-22):
|
||
- `GET /healthz` – liveness.
|
||
- `GET /actions` – list action metadata.
|
||
- `POST /actions/{id}/execute` – run an action; yields `ActionEnvelope` with correlation_id.
|
||
- `GET /config/browser-hosts` – current default + host map.
|
||
|
||
## Coding Conventions
|
||
- Python 3.12+, Pydantic v2, pydantic-settings.
|
||
- Use PEP 604 unions (`str | None`), built-in generics (`list[str]`, `dict[str, JSONValue]`).
|
||
- Ban `Any` and `# type: ignore`; add type guards instead.
|
||
- Actions/constants: use `ClassVar[str]` for IDs/descriptions.
|
||
- Keep modules small (<300 LoC); split by domain (e.g., `actions/intake/basic.py`).
|
||
- Strings/queries belong in `strings/`; selectors should be reusable and labeled.
|
||
- `strings.service` enforces domain names; missing keys raise immediately, so keep selectors/texts in sync with UI.
|
||
|
||
## Error Handling & Logging
|
||
- Raise `GuideError` subclasses; let routers translate to consistent HTTP responses.
|
||
- Log via `core/logging` (structured, levelled). Include persona/action ids and host targets in logs for traceability.
|
||
- For browser flows, prefer Playwright traces over ad-hoc prints; disable tracing only intentionally.
|
||
- `BrowserClient.open_page` resolves host by ID → CDP attach (reuses existing Raindrop page) or launches headless chromium/firefox/webkit; always close context/browser on exit.
|
||
- CDP mode requires `host` + `port` in `hosts.yaml`; errors surface as `BrowserConnectionError` with host_id detail.
|
||
|
||
## Browser Automation Notes
|
||
- Route all CDP calls through `BrowserClient`; configure timeouts/retries there, not per action.
|
||
- Keep selectors in `strings/`; avoid brittle text selectors—prefer data-testid / aria labels when available.
|
||
- When mocking Playwright in tests, isolate side effects and avoid real network/CDP hits.
|
||
- Current MFA flow uses `DummyMfaCodeProvider` which raises `NotImplementedError`; real runs need a provider implementation or override before executing login/ensure_persona.
|
||
|
||
## GraphQL & Data Layer
|
||
- `raindrop/graphql.py` houses the client; operations live in `raindrop/operations`. Keep queries/mutations versioned and colocated with types in `strings/`.
|
||
- Validate responses with pydantic models; surface schema mismatches as `GuideError`.
|
||
- Never bake URLs/tokens—pull from `AppSettings` and YAML/env overrides.
|
||
- HTTP transport via `httpx.AsyncClient` (10s timeout); GraphQL errors bubble as `GraphQLTransportError` or `GraphQLOperationError` with returned `errors` payload in `details`.
|
||
|
||
## Configuration & Secrets
|
||
- Runtime configuration flows: env vars → `config/*.yaml` → `AppSettings` defaults.
|
||
- Do not commit credentials; use env overrides for tokens/hosts.
|
||
- MFA providers are pluggable; keep provider-specific wiring behind interfaces.
|
||
- Default env prefix: `RAINDROP_DEMO_` (see `AppSettings.model_config`).
|
||
|
||
## Testing Expectations
|
||
- Minimum: `basedpyright src` and `python -m compileall src/guide` before publishing.
|
||
- Add unit tests under `tests/` alongside code; mock Playwright/GraphQL; avoid real external calls.
|
||
- Prefer deterministic fixtures; document any required env vars in test module docstrings.
|
||
- Action pipeline happy-path: request → resolve persona + browser host → `BrowserClient.open_page` → optional `ensure_persona` → action.run → `ActionEnvelope` with correlation_id from `ActionContext`.
|
||
|
||
## Git & PR Hygiene
|
||
- Commits: scoped and descriptive (e.g., `feat: add auth login action`, `chore: tighten typing`).
|
||
- PRs should state changes, commands run, and any config additions (`hosts.yaml`, `personas.yaml`).
|
||
- Link related issues; include screenshots/log snippets when UI or API behavior changes.
|
||
|
||
## Performance & Footprint
|
||
- Keep browser sessions short-lived; close contexts to avoid leaking handles.
|
||
- Cache expensive GraphQL lookups when safe; prefer per-request timeouts over global sleeps.
|
||
- Avoid widening dependencies; stick to project pins unless justified.
|
||
- Close Playwright contexts/browser handles promptly (client already wraps in contextmanager; keep action code lean to avoid dangling pages).
|
||
|
||
## Quick Start Checklist (new agents)
|
||
- [ ] Create/verify `config/hosts.yaml` and `config/personas.yaml` match your target env.
|
||
- [ ] Run `pip install -e .`
|
||
- [ ] Run `basedpyright src` and `python -m compileall src/guide`.
|
||
- [ ] Start API: `python -m guide` and open `/docs` to smoke basic actions.
|
||
- [ ] Review `strings/` for selectors relevant to your feature before writing new actions.
|
||
- [ ] If executing auth flows, supply a working `MfaCodeProvider` (current dummy raises) or stub the login call in demos/tests.
|