# Coder Subagent Guide

The **coder** subagent is your primary tool for writing and modifying production Node.js/TypeScript code in the Flyer Crawler project. This guide explains how to work effectively with the coder subagent.

## Quick Reference

| Aspect           | Details                                                                  |
| ---------------- | ------------------------------------------------------------------------ |
| **Primary Use**  | Write/modify production TypeScript code                                  |
| **Key Files**    | `src/routes/*.routes.ts`, `src/services/**/*.ts`, `src/components/*.tsx` |
| **Key ADRs**     | ADR-034 (Repository), ADR-035 (Services), ADR-028 (API Response)         |
| **Test Command** | `podman exec -it flyer-crawler-dev npm run test:unit`                    |
| **Type Check**   | `podman exec -it flyer-crawler-dev npm run type-check`                   |
| **Delegate To**  | `db-dev` (database), `frontend-specialist` (UI), `testwriter` (tests)    |

## When to Use the Coder Subagent

Use the coder subagent when you need to:

- Implement new features or functionality
- Fix bugs in existing code
- Refactor existing code
- Add new API endpoints
- Create new React components
- Write service layer logic
- Implement business rules

## What the Coder Subagent Knows

The coder subagent has deep knowledge of:

### Project Architecture

```
Routes -> Services -> Repositories -> Database
            |
       External APIs (*.server.ts)
```

- **Routes Layer**: Request/response handling, validation, authentication
- **Services Layer**: Business logic, transaction coordination, external APIs
- **Repositories Layer**: Database access, query construction, error translation

### Key Patterns

| Pattern            | ADR     | Implementation                                             |
| ------------------ | ------- | ---------------------------------------------------------- |
| Error Handling     | ADR-001 | `handleDbError()`, throw `NotFoundError`                   |
| Repository Methods | ADR-034 | `get*` throws, `find*` returns null, `list*` returns array |
| API Responses      | ADR-028 | `sendSuccess()`, `sendPaginated()`, `sendError()`          |
| Transactions       | ADR-002 | `withTransaction(async (client) => {...})`                 |

### File Naming Conventions

| Pattern       | Location           | Purpose                          |
| ------------- | ------------------ | -------------------------------- |
| `*.db.ts`     | `src/services/db/` | Database repositories            |
| `*.server.ts` | `src/services/`    | Server-only code (external APIs) |
| `*.routes.ts` | `src/routes/`      | Express route handlers           |
| `*.test.ts`   | Colocated          | Unit tests                       |

## How to Request Code Changes

### Good Request Examples

**Specific and contextual:**

```
"Use the coder subagent to add a new endpoint GET /api/stores/:id/locations
that returns all locations for a store, following the existing patterns
in stores.routes.ts"
```

**With acceptance criteria:**

```
"Use the coder subagent to implement the shopping list sharing feature:
- Add a share_token column to shopping_lists table
- Create POST /api/shopping-lists/:id/share endpoint
- Return a shareable link with the token
- Allow anonymous users to view shared lists"
```

**Bug fix with reproduction steps:**

```
"Use the coder subagent to fix the issue where flyer items are not
sorted by price on the deals page. The expected behavior is lowest
price first, but currently they appear in insertion order."
```

### Less Effective Request Examples

**Too vague:**

```
"Make the code better"
```

**Missing context:**

```
"Add a feature to search things"
```

**Multiple unrelated tasks:**

```
"Fix the login bug, add a new table, and update the homepage"
```

## Common Workflows

### Adding a New API Endpoint

The coder subagent will follow this workflow:

1. **Add route** in `src/routes/{domain}.routes.ts`
2. **Use `validateRequest(schema)`** middleware for input validation
3. **Call service layer** (never access DB directly from routes)
4. **Return via** `sendSuccess()` or `sendPaginated()`
5. **Add tests** in `*.routes.test.ts`

**Example Code Pattern:**

```typescript
// src/routes/stores.routes.ts
router.get('/:id/locations', validateRequest(getStoreLocationsSchema), async (req, res, next) => {
  try {
    const { id } = req.params;
    const locations = await storeService.getLocationsForStore(parseInt(id, 10), req.log);
    sendSuccess(res, { locations });
  } catch (error) {
    next(error);
  }
});
```

### Adding a New Database Operation

The coder subagent will:

1. **Add method** to `src/services/db/{domain}.db.ts`
2. **Follow naming**: `get*` (throws), `find*` (returns null), `list*` (array)
3. **Use `handleDbError()`** for error handling
4. **Accept optional `PoolClient`** for transaction support
5. **Add unit test**

**Example Code Pattern:**

```typescript
// src/services/db/store.db.ts
export async function listLocationsByStoreId(
  storeId: number,
  client?: PoolClient,
): Promise<StoreLocation[]> {
  const queryable = client || getPool();
  try {
    const result = await queryable.query<StoreLocation>(
      `SELECT * FROM store_locations WHERE store_id = $1 ORDER BY created_at`,
      [storeId],
    );
    return result.rows;
  } catch (error) {
    handleDbError(
      error,
      log,
      'Database error in listLocationsByStoreId',
      { storeId },
      {
        entityName: 'StoreLocation',
        defaultMessage: 'Failed to list store locations.',
      },
    );
  }
}
```

### Adding a New React Component

The coder subagent will:

1. **Create component** in `src/components/` or feature-specific folder
2. **Follow Neo-Brutalism design** patterns (ADR-012)
3. **Use existing design tokens** from `src/styles/`
4. **Add unit tests** using Testing Library

**Example Code Pattern:**

```typescript
// src/components/StoreCard.tsx
import { Store } from '@/types';

interface StoreCardProps {
  store: Store;
  onSelect?: (store: Store) => void;
}

export function StoreCard({ store, onSelect }: StoreCardProps) {
  return (
    <div
      className="brutal-card p-4 cursor-pointer hover:translate-x-1 hover:-translate-y-1 transition-transform"
      onClick={() => onSelect?.(store)}
    >
      <h3 className="text-lg font-bold">{store.name}</h3>
      <p className="text-sm text-gray-600">{store.location_count} locations</p>
    </div>
  );
}
```

## Code Quality Standards

The coder subagent adheres to these standards:

### TypeScript

- Strict TypeScript mode enabled
- No `any` types unless absolutely necessary
- Explicit return types for functions
- Proper interface/type definitions

### Error Handling

- Use custom error classes from `src/services/db/errors.db.ts`
- Never swallow errors silently
- Log errors with appropriate context
- Return meaningful error messages to API consumers

### Logging

- Use Pino logger (`src/services/logger.server.ts`)
- Include module context in log child
- Log at appropriate levels (info, warn, error)
- Include relevant data in structured format

### Testing

- All new code should have corresponding tests
- Follow testing patterns in ADR-010
- Use mock factories from `src/tests/utils/mockFactories.ts`
- Run tests in the dev container

## Platform Considerations

### Linux-Only Development

The coder subagent knows that this application runs exclusively on Linux:

- Uses POSIX-style paths (`/`)
- Assumes Linux shell commands
- References dev container environment

**Important**: Any code changes should be tested in the dev container:

```bash
podman exec -it flyer-crawler-dev npm run test:unit
```

### Database Schema Synchronization

When the coder subagent modifies database-related code, it will remind you:

> **Schema files must stay synchronized:**
>
> - `sql/master_schema_rollup.sql` - Test DB setup
> - `sql/initial_schema.sql` - Fresh install schema
> - `sql/migrations/*.sql` - Production changes

## Working with the Coder Subagent

### Before Starting

1. **Identify the scope** - What exactly needs to change?
2. **Check existing patterns** - Is there similar code to follow?
3. **Consider tests** - Will you need the testwriter subagent too?

### During Development

1. **Review changes incrementally** - Don't wait until the end
2. **Ask for explanations** - Understand why certain approaches are chosen
3. **Provide feedback** - Tell the coder if something doesn't look right

### After Completion

1. **Run tests** in the dev container
2. **Run type-check**: `npm run type-check`
3. **Review the changes** before committing
4. **Consider code review** with the code-reviewer subagent

## Common Issues and Solutions

### Issue: Code Doesn't Follow Project Patterns

**Solution**: Provide examples of existing code that follows the desired pattern. The coder will align with it.

### Issue: Missing Error Handling

**Solution**: Explicitly request comprehensive error handling:

```
"Include proper error handling using handleDbError and the project's
error classes for all database operations"
```

### Issue: Tests Not Included

**Solution**: Either:

1. Ask the coder to include tests: "Include unit tests for all new code"
2. Use the testwriter subagent separately for comprehensive test coverage

### Issue: Code Works on Windows but Fails on Linux

**Solution**: Always test in the dev container. The coder subagent writes Linux-compatible code, but IDE tooling might behave differently.

## Related Documentation

- [OVERVIEW.md](./OVERVIEW.md) - Subagent system overview
- [TESTER-GUIDE.md](./TESTER-GUIDE.md) - Testing strategies
- [DATABASE-GUIDE.md](./DATABASE-GUIDE.md) - Database development workflows
- [../adr/0034-repository-pattern-standards.md](../adr/0034-repository-pattern-standards.md) - Repository patterns
- [../adr/0035-service-layer-architecture.md](../adr/0035-service-layer-architecture.md) - Service layer architecture
- [../adr/0028-api-response-standardization.md](../adr/0028-api-response-standardization.md) - API response patterns
- [../development/CODE-PATTERNS.md](../development/CODE-PATTERNS.md) - Code patterns reference
