Ryan Vogel 3 hete
szülő
commit
bd2e34f3bd

+ 128 - 94
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.
 
-### Naming
+## Repo Facts
+
+- Package manager: `bun` (`[email protected]`).
+- 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`
 
-Prefer single word names for variables and functions. Only use multiple words if necessary.
+- 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`
 
-### Naming Enforcement (Read This)
+### `packages/app`
 
-THIS RULE IS MANDATORY FOR AGENT WRITTEN CODE.
+- 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`
 
-- 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`.
+### `packages/mobile-voice`
 
-```ts
-// Good
-const foo = 1
-function journal(dir: string) {}
+- 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`
 
-// Bad
-const fooBar = 1
-function prepareJournal(dir: string) {}
-```
+### `packages/apn-relay`
 
-Reduce total variable count by inlining when a value is only used once.
+- Start relay: `bun run dev`
+- Typecheck: `bun run typecheck`
+- DB connectivity check: `bun run db:check`
 
-```ts
-// Good
-const journal = await Bun.file(path.join(dir, "journal.json")).json()
+## Build / Lint / Test Expectations
 
-// Bad
-const journalPath = path.join(dir, "journal.json")
-const journal = await Bun.file(journalPath).json()
-```
+- 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.
 
-### Destructuring
+## Single-Test Guidance
 
-Avoid unnecessary destructuring. Use dot notation to preserve context.
+- 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.
 
-```ts
-// Good
-obj.a
-obj.b
+## Code Style Guidelines
 
-// Bad
-const { a, b } = obj
-```
+These conventions are already used heavily in this repo and should be preserved.
 
-### Variables
+### Formatting
 
-Prefer `const` over `let`. Use ternaries or early returns instead of reassignment.
+- 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.
 
-```ts
-// Good
-const foo = condition ? 1 : 2
+### Imports
 
-// Bad
-let foo
-if (condition) foo = 1
-else foo = 2
-```
+- 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
+
+- 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.
+
+### Error Handling
+
+- 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.
+
+### Data / DB
+
+- 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
-function foo() {
-  if (condition) return 1
-  return 2
-}
+### Testing Philosophy
 
-// Bad
-function foo() {
-  if (condition) return 1
-  else return 2
-}
-```
+- Prefer testing real behavior over mocks.
+- Add regression tests for bug fixes where practical.
+- Keep fixtures small and focused.
 
-### Schema Definitions (Drizzle)
+## Agent Workflow Tips
 
-Use snake_case for field names so column names don't need to be redefined as strings.
+- 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.
 
-```ts
-// Good
-const table = sqliteTable("session", {
-  id: text().primaryKey(),
-  project_id: text().notNull(),
-  created_at: integer().notNull(),
-})
+## Known Operational Notes
 
-// Bad
-const table = sqliteTable("session", {
-  id: text("id").primaryKey(),
-  projectID: text("project_id").notNull(),
-  createdAt: integer("created_at").notNull(),
-})
-```
+- `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.
 
-## Testing
+## Regeneration / Special Scripts
 
-- 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`.
+- Regenerate JS SDK with: `./packages/sdk/js/script/build.ts`
 
-## Type Checking
+## Quick Checklist Before Finishing
 
-- Always run `bun typecheck` from package directories (e.g., `packages/opencode`), never `tsc` directly.
+- Ran relevant package checks.
+- Updated docs/config when behavior changed.
+- Avoided committing unrelated files.
+- Kept edits minimal and aligned with local conventions.

+ 106 - 0
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.

+ 103 - 0
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.

+ 1 - 1
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)
       },
     )

+ 3 - 12
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"]
 }