From bd2e34f3bd3160a351b26b38daae6a662629ca53 Mon Sep 17 00:00:00 2001 From: Ryan Vogel Date: Sat, 28 Mar 2026 19:03:13 -0400 Subject: [PATCH] update --- AGENTS.md | 252 ++++++++++++++---------- packages/apn-relay/AGENTS.md | 106 ++++++++++ packages/mobile-voice/AGENTS.md | 103 ++++++++++ packages/mobile-voice/src/app/index.tsx | 2 +- packages/mobile-voice/tsconfig.json | 15 +- 5 files changed, 356 insertions(+), 122 deletions(-) create mode 100644 packages/apn-relay/AGENTS.md create mode 100644 packages/mobile-voice/AGENTS.md diff --git a/AGENTS.md b/AGENTS.md index 0b080ac4e2..a116df4331 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,128 +1,162 @@ -- To regenerate the JavaScript SDK, run `./packages/sdk/js/script/build.ts`. -- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE. -- The default branch in this repo is `dev`. -- Local `main` ref may not exist; use `dev` or `origin/dev` for diffs. -- Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility. +# OpenCode Monorepo Agent Guide -## Style Guide +This file is for coding agents working in `/Users/ryanvogel/dev/opencode`. -### General Principles +## Scope And Precedence -- Keep things in one function unless composable or reusable -- Avoid `try`/`catch` where possible -- Avoid using the `any` type -- Prefer single word variable names where possible -- Use Bun APIs when possible, like `Bun.file()` -- Rely on type inference when possible; avoid explicit type annotations or interfaces unless necessary for exports or clarity -- Prefer functional array methods (flatMap, filter, map) over for loops; use type guards on filter to maintain type inference downstream +- Start with this file for repo-wide defaults. +- Then check package-local `AGENTS.md` files for stricter rules. +- Existing local guides include `packages/opencode/AGENTS.md` and `packages/app/AGENTS.md`. +- Package-specific guides override this file when they conflict. + +## Repo Facts + +- Package manager: `bun` (`bun@1.3.11`). +- Monorepo tool: `turbo`. +- Default branch: `dev`. +- Root test script intentionally fails; do not run tests from root. + +## Cursor / Copilot Rules + +- No `.cursor/rules/` directory found. +- No `.cursorrules` file found. +- No `.github/copilot-instructions.md` file found. +- If these files are added later, treat them as mandatory project policy. + +## High-Value Commands + +Run commands from the correct package directory unless noted. + +### Root + +- Install deps: `bun install` +- Run all typechecks via turbo: `bun run typecheck` +- OpenCode dev CLI entry: `bun run dev` +- OpenCode serve (common): `bun run dev serve --hostname 0.0.0.0 --port 4096` + +### `packages/opencode` + +- Dev CLI: `bun run dev` +- Typecheck: `bun run typecheck` +- Tests (all): `bun test --timeout 30000` +- Tests (single file): `bun test test/path/to/file.test.ts --timeout 30000` +- Tests (single test name): `bun test test/path/to/file.test.ts -t "name fragment" --timeout 30000` +- Build: `bun run build` +- Drizzle helper: `bun run db` + +### `packages/app` + +- Dev server: `bun dev` +- Build: `bun run build` +- Typecheck: `bun run typecheck` +- Unit tests (all): `bun run test:unit` +- Unit tests (single file): `bun test --preload ./happydom.ts ./src/path/to/file.test.ts` +- Unit tests (single test name): `bun test --preload ./happydom.ts ./src/path/to/file.test.ts -t "name fragment"` +- E2E tests: `bun run test:e2e` + +### `packages/mobile-voice` + +- Start Expo: `bun run start` +- Start Expo dev client: `bunx expo start --dev-client --clear --host lan` +- iOS native run: `bun run ios` +- Android native run: `bun run android` +- Lint: `bun run lint` +- Expo doctor: `bunx expo-doctor` +- Dependency compatibility check: `bunx expo install --check` + +### `packages/apn-relay` + +- Start relay: `bun run dev` +- Typecheck: `bun run typecheck` +- DB connectivity check: `bun run db:check` + +## Build / Lint / Test Expectations + +- Always run the narrowest checks that prove your change. +- For backend changes: run package typecheck + relevant tests. +- For mobile changes: run `expo lint` and at least one `expo` compile-style command if possible. +- Never claim tests passed unless you ran them in this workspace. + +## Single-Test Guidance + +- Prefer running one file first, then broaden scope. +- For Bun tests, pass the file path directly. +- For name filtering, use `-t "..."`. +- Keep original timeouts when scripts define them. + +## Code Style Guidelines + +These conventions are already used heavily in this repo and should be preserved. + +### Formatting + +- Use Prettier defaults configured in root: `semi: false`, `printWidth: 120`. +- Keep imports grouped and stable; avoid noisy reorder-only edits. +- Avoid unrelated formatting churn in touched files. + +### Imports + +- Prefer explicit imports over dynamic imports unless runtime gating is required. +- Prefer existing alias patterns (for example `@/...`) where already configured. +- Do not introduce new dependency layers when a local util already exists. + +### Types + +- Avoid `any`. +- Prefer inference for local variables. +- Add explicit annotations for exported APIs and complex boundaries. +- Prefer `zod` schemas for request/response validation and parsing. ### Naming -Prefer single word names for variables and functions. Only use multiple words if necessary. - -### Naming Enforcement (Read This) - -THIS RULE IS MANDATORY FOR AGENT WRITTEN CODE. - -- Use single word names by default for new locals, params, and helper functions. -- Multi-word names are allowed only when a single word would be unclear or ambiguous. -- Do not introduce new camelCase compounds when a short single-word alternative is clear. -- Before finishing edits, review touched lines and shorten newly introduced identifiers where possible. -- Good short names to prefer: `pid`, `cfg`, `err`, `opts`, `dir`, `root`, `child`, `state`, `timeout`. -- Examples to avoid unless truly required: `inputPID`, `existingClient`, `connectTimeout`, `workerPath`. - -```ts -// Good -const foo = 1 -function journal(dir: string) {} - -// Bad -const fooBar = 1 -function prepareJournal(dir: string) {} -``` - -Reduce total variable count by inlining when a value is only used once. - -```ts -// Good -const journal = await Bun.file(path.join(dir, "journal.json")).json() - -// Bad -const journalPath = path.join(dir, "journal.json") -const journal = await Bun.file(journalPath).json() -``` - -### Destructuring - -Avoid unnecessary destructuring. Use dot notation to preserve context. - -```ts -// Good -obj.a -obj.b - -// Bad -const { a, b } = obj -``` - -### Variables - -Prefer `const` over `let`. Use ternaries or early returns instead of reassignment. - -```ts -// Good -const foo = condition ? 1 : 2 - -// Bad -let foo -if (condition) foo = 1 -else foo = 2 -``` +- Follow existing repo preference for short, clear names. +- Use single-word names when readable; use multi-word only for clarity. +- Keep naming consistent with nearby code. ### Control Flow -Avoid `else` statements. Prefer early returns. +- Prefer early returns over nested `else` blocks. +- Keep functions focused; split only when it improves reuse or readability. -```ts -// Good -function foo() { - if (condition) return 1 - return 2 -} +### Error Handling -// Bad -function foo() { - if (condition) return 1 - else return 2 -} -``` +- Fail with actionable messages. +- Avoid swallowing errors silently. +- Log enough context to debug production issues (IDs, env, status), but never secrets. +- In UI code, degrade gracefully for missing capabilities. -### Schema Definitions (Drizzle) +### Data / DB -Use snake_case for field names so column names don't need to be redefined as strings. +- For Drizzle schema, use snake_case fields and columns. +- Keep migration and schema changes minimal and explicit. +- Follow package-specific DB guidance in `packages/opencode/AGENTS.md`. -```ts -// Good -const table = sqliteTable("session", { - id: text().primaryKey(), - project_id: text().notNull(), - created_at: integer().notNull(), -}) +### Testing Philosophy -// Bad -const table = sqliteTable("session", { - id: text("id").primaryKey(), - projectID: text("project_id").notNull(), - createdAt: integer("created_at").notNull(), -}) -``` +- Prefer testing real behavior over mocks. +- Add regression tests for bug fixes where practical. +- Keep fixtures small and focused. -## Testing +## Agent Workflow Tips -- Avoid mocks as much as possible -- Test actual implementation, do not duplicate logic into tests -- Tests cannot run from repo root (guard: `do-not-run-tests-from-root`); run from package dirs like `packages/opencode`. +- Read existing code paths before introducing new abstractions. +- Match local patterns first; do not impose a new style per file. +- If a package has its own `AGENTS.md`, review it before editing. +- For OpenCode Effect services, follow `packages/opencode/AGENTS.md` strictly. -## Type Checking +## Known Operational Notes -- Always run `bun typecheck` from package directories (e.g., `packages/opencode`), never `tsc` directly. +- `packages/app/AGENTS.md` says: never restart app/server processes during that package's debugging workflow. +- `packages/app/AGENTS.md` also documents local backend+web split for UI work. +- `packages/opencode/AGENTS.md` contains mandatory Effect and database conventions. + +## Regeneration / Special Scripts + +- Regenerate JS SDK with: `./packages/sdk/js/script/build.ts` + +## Quick Checklist Before Finishing + +- Ran relevant package checks. +- Updated docs/config when behavior changed. +- Avoided committing unrelated files. +- Kept edits minimal and aligned with local conventions. diff --git a/packages/apn-relay/AGENTS.md b/packages/apn-relay/AGENTS.md new file mode 100644 index 0000000000..a3de217188 --- /dev/null +++ b/packages/apn-relay/AGENTS.md @@ -0,0 +1,106 @@ +# apn-relay Agent Guide + +This file defines package-specific guidance for agents working in `packages/apn-relay`. + +## Scope And Precedence + +- Follow root `AGENTS.md` first. +- This file provides stricter package-level conventions for relay service work. +- If future local guides are added, closest guide wins. + +## Project Overview + +- Minimal APNs relay service (Hono + Bun + PlanetScale via Drizzle). +- Core routes: + - `GET /health` + - `GET /` + - `POST /v1/device/register` + - `POST /v1/device/unregister` + - `POST /v1/event` + +## Commands + +Run all commands from `packages/apn-relay`. + +- Install deps: `bun install` +- Start relay locally: `bun run dev` +- Typecheck: `bun run typecheck` +- DB connectivity check: `bun run db:check` + +## Build / Test Expectations + +- There is no dedicated package test script currently. +- Required validation for behavior changes: + - `bun run typecheck` + - `bun run db:check` when DB/env changes are involved + - manual endpoint verification against `/health`, `/v1/device/register`, `/v1/event` + +## Single-Test Guidance + +- No single-test command exists for this package today. +- For focused checks, run endpoint-level manual tests against a local dev server. + +## Code Style Guidelines + +### Formatting / Structure + +- Keep handlers compact and explicit. +- Prefer small local helpers for repeated route logic. +- Avoid broad refactors when a targeted fix is enough. + +### Types / Validation + +- Validate request bodies with `zod` at route boundaries. +- Keep payload and DB row shapes explicit and close to usage. +- Avoid `any`; narrow unknown input immediately after parsing. + +### Naming + +- Follow existing concise naming in this package (`reg`, `unreg`, `evt`, `row`, `key`). +- For DB columns, keep snake_case alignment with schema. + +### Error Handling + +- Return clear JSON errors for invalid input. +- Keep handler failures observable via `app.onError` and structured logs. +- Do not leak secrets in responses or logs. + +### Logging + +- Log delivery lifecycle at key checkpoints: + - registration/unregistration attempts + - event fanout start/end + - APNs send failures and retries +- Mask sensitive values; prefer token suffixes and metadata. + +### APNs Environment Rules + +- Keep APNs env explicit per registration (`sandbox` / `production`). +- For `BadEnvironmentKeyInToken`, retry once with flipped env and persist correction. +- Avoid infinite retry loops; one retry max per delivery attempt. + +## Database Conventions + +- Schema is in `src/schema.sql.ts`. +- Keep table/column names snake_case. +- Maintain index naming consistency with existing schema. +- For upserts, update only fields required by current behavior. + +## API Behavior Expectations + +- `register`/`unregister` must be idempotent. +- `event` should return success envelope even when no devices are registered. +- Delivery logs should capture per-attempt result and error payload. + +## Operational Notes + +- Ensure `APNS_PRIVATE_KEY` supports escaped newline format (`\n`) and raw multiline. +- Validate that `APNS_DEFAULT_BUNDLE_ID` matches mobile app bundle identifier. +- Avoid coupling route behavior to deployment platform specifics. + +## Before Finishing + +- Run `bun run typecheck`. +- If DB/env behavior changed, run `bun run db:check`. +- Manually exercise affected endpoints. +- Confirm logs are useful and secret-safe. diff --git a/packages/mobile-voice/AGENTS.md b/packages/mobile-voice/AGENTS.md new file mode 100644 index 0000000000..ea3a5a1fb8 --- /dev/null +++ b/packages/mobile-voice/AGENTS.md @@ -0,0 +1,103 @@ +# mobile-voice Agent Guide + +This file defines package-specific guidance for agents working in `packages/mobile-voice`. + +## Scope And Precedence + +- Follow root `AGENTS.md` first. +- This file overrides root guidance for this package when rules conflict. +- If additional local guides are added later, treat the closest guide as highest priority. + +## Project Overview + +- Expo + React Native app for voice dictation and OpenCode session monitoring. +- Uses native modules (`react-native-executorch`, `react-native-audio-api`, `expo-notifications`, `expo-camera`). +- Development builds are required for native module changes. + +## Commands + +Run all commands from `packages/mobile-voice`. + +- Install deps: `bun install` +- Start Metro: `bun run start` +- Start dev client server (recommended): `bunx expo start --dev-client --clear --host lan` +- iOS run: `bun run ios` +- Android run: `bun run android` +- Lint: `bun run lint` +- Expo doctor: `bunx expo-doctor` +- Dependency compatibility check: `bunx expo install --check` +- Export bundle smoke test: `bunx expo export --platform ios --clear` + +## Build / Verification Expectations + +- For JS-only changes: run `bun run lint` and verify app behavior via dev client. +- For native dependency/config/plugin changes: rebuild dev client via EAS before validation. +- If notifications/camera/audio behavior changes, verify on a physical iOS device. +- Do not claim a fix unless you validated in Metro logs and app runtime behavior. + +## Single-Test Guidance + +- This package currently has no dedicated unit test script. +- Use targeted validation commands instead: + - `bun run lint` + - `bunx expo export --platform ios --clear` + - manual runtime test in dev client + +## Code Style And Patterns + +### Formatting / Structure + +- Preserve existing style (`semi: false`, concise JSX, stable import grouping). +- Keep UI changes localized; avoid large architectural rewrites. +- Avoid unrelated formatting churn. + +### Types + +- Avoid `any`; prefer local type aliases for component state and network payloads. +- Keep exported/shared boundaries typed explicitly. +- Use discriminated unions for UI modes/status where practical. + +### Naming + +- Prefer short, readable names consistent with nearby code. +- Keep naming aligned with existing app state keys (`serverDraftURL`, `monitorStatus`, etc.). + +### Error Handling / Logging + +- Fail gracefully in UI (alerts, disabled actions, fallback text). +- Log actionable diagnostics for runtime workflows: + - server health checks + - relay registration attempts + - notification token lifecycle +- Never log secrets or full APNs tokens. + +### Network / Relay Integration + +- Normalize and validate URLs before storing server configs. +- Keep relay registration idempotent. +- Guard duplicate scan/add flows to avoid repeated server entries. + +### Notifications / APNs + +- Distinguish sandbox vs production token environments correctly. +- On registration changes, ensure old token unregister flow remains intact. +- Treat permission failures as non-fatal and degrade to foreground monitoring when needed. + +## Native-Module Safety + +- If adding a native module, ensure it is in `package.json` with SDK-compatible version. +- Rebuild dev client after native module additions/changes. +- For optional native capability usage, prefer runtime fallback paths instead of hard crashes. + +## Common Pitfalls + +- Black screen + "No script URL provided" often means stale dev client binary. +- `expo-doctor` duplicate module warnings may appear in Bun workspaces; prioritize runtime verification. +- `expo lint` may auto-generate `eslint.config.js`; do not commit accidental generated config unless requested. + +## Before Finishing + +- Run `bun run lint`. +- If behavior could break startup, run `bunx expo export --platform ios --clear`. +- Confirm no accidental config side effects were introduced. +- Summarize what was verified on-device vs only in tooling. diff --git a/packages/mobile-voice/src/app/index.tsx b/packages/mobile-voice/src/app/index.tsx index 3b2dd415f9..88c50ceeaf 100644 --- a/packages/mobile-voice/src/app/index.tsx +++ b/packages/mobile-voice/src/app/index.tsx @@ -557,7 +557,7 @@ export default function DictationScreen() { lastWaveformCommitRef.current = now } - // Always use the latest model ref to avoid stale closure + // Always use the latest model ref to avoid stale closure. modelRef.current.streamInsert(samples) }, ) diff --git a/packages/mobile-voice/tsconfig.json b/packages/mobile-voice/tsconfig.json index 2e9a6695e2..a90e9858ad 100644 --- a/packages/mobile-voice/tsconfig.json +++ b/packages/mobile-voice/tsconfig.json @@ -3,18 +3,9 @@ "compilerOptions": { "strict": true, "paths": { - "@/*": [ - "./src/*" - ], - "@/assets/*": [ - "./assets/*" - ] + "@/*": ["./src/*"], + "@/assets/*": ["./assets/*"] } }, - "include": [ - "**/*.ts", - "**/*.tsx", - ".expo/types/**/*.ts", - "expo-env.d.ts" - ] + "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"] }