Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 11 additions & 126 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,134 +1,19 @@
# CLAUDE.md
# hacker-rank-queue agent instructions

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

A Slack bot for managing a queue of reviewers for HackerRank coding assessments. The bot connects reviewers with candidates by maintaining a queue of available reviewers, matching them by language preference, and managing the request/acceptance workflow through Slack interactions and direct messages.
Slack bot that queues reviewers for HackerRank assessments. Uses Google Sheets as its database (see `src/database/`).

## Commands

### Development

```bash
pnpm install # Install dependencies
pnpm verify # Run all checks: lint, format, compile, build, and test
pnpm test # Run tests
pnpm test:watch # Run tests in watch mode
pnpm lint # Lint and fix
pnpm format # Format code
pnpm compile # Type check without emitting files
pnpm build # Build for production
```

### Deployment

```bash
dev # Sign into AWS dev (requires sai-aws-auth setup)
pnpm deploy # Deploy to dev (can run from any directory)
```

## Architecture

### Data Storage

The application uses **Google Spreadsheets as its database**. The `database` module (`src/database/database.ts`) manages connections to Google Sheets using service account authentication. Each "table" is a separate sheet within the spreadsheet:

- **users sheet**: Stores reviewers in the queue with their language preferences and last review date
- **activeReviews sheet**: Tracks ongoing review requests and their state
- **languages sheet**: Defines available programming languages

Repositories (`src/database/repos/`) provide CRUD operations on these sheets, mapping rows to TypeScript models.

### Core Models

- **User** (`src/database/models/User.ts`): Queue members with `id`, `name`, `languages[]`, and `lastReviewedDate`
- **ActiveReview** (`src/database/models/ActiveReview.ts`): Ongoing reviews with thread info, requestor, candidate identifier, and arrays tracking `acceptedReviewers`, `pendingReviewers`, and `declinedReviewers`

### Request Lifecycle

1. Someone requests a review via Slack shortcut (`requestReview`)
2. `QueueService` finds best reviewers by language match and last review time
3. `RequestService` sends DMs to selected reviewers with accept/decline buttons
4. Reviewers respond, transitioning from `pendingReviewers` to `acceptedReviewers` or `declinedReviewers`
5. Requests expire after `REQUEST_EXPIRATION_MIN` if not accepted (handled by `expireRequests` cron)
6. Once enough reviewers accept, the review is complete and closed via `ReviewCloser`

### Services

Services (`src/services/`) contain business logic:

- **QueueService**: Finds and ranks available reviewers
- **RequestService**: Manages sending review requests to users
- **ChatService**: Slack messaging utilities
- **ReviewActionService**: Processes accept/decline actions

### Bot Commands

Bot commands (`src/bot/`) handle Slack shortcuts and interactions:

- `joinQueue`: Add/update user in reviewer queue
- `leaveQueue`: Remove user from queue
- `requestReview`: Initiate a new review request
- `acceptReviewRequest`: Handle reviewer acceptance
- `declineReviewRequest`: Handle reviewer decline
- `requestPosition`: Show user their position in queue
- `triggerCron`: Dev-only manual cron trigger

Each bot command exports a `setup(app)` function that registers Slack event handlers.

### Cron Jobs

Scheduled jobs (`src/cron/index.ts`) run on node-cron in America/Chicago timezone:

- **healthCheck**: Daily at midnight
- **checkAllUsersActive**: Daily at 12:05 AM (verifies users still exist in Slack)
- **expireRequests**: Every 15 minutes during work hours

Work hours are configured via `WORKDAY_START_HOUR` and `WORKDAY_END_HOUR` environment variables.

### TypeScript Path Aliases

The project uses path aliases (configured in `tsconfig.json`):

- `@/*` → `src/*`
- `@bot/*` → `src/bot/*`
- `@cron` / `@cron/*` → `src/cron`
- `@database` → `src/database/database`
- `@models/*` → `src/database/models/*`
- `@repos/*` → `src/database/repos/*`
- `@services` → `src/services`
- `@utils/*` → `src/utils/*`

### Testing

- Jest with ts-jest preset
- Tests colocated in `__tests__` directories next to source
- Coverage thresholds enforced: 80% lines, 75% functions/statements, 55% branches
- `@utils/log` is mocked globally via `moduleNameMapper`
- Timezone set to `America/Chicago` for tests

## Development Workflow

**IMPORTANT**: Before considering any task complete, ALWAYS run `pnpm verify` to ensure:

- Linting passes
- Code formatting is correct
- TypeScript compilation succeeds
- Build completes successfully
- All tests pass

This helps catch issues early and maintains code quality.
- Verify (run before considering any task done): `pnpm verify` — lint, format check, type-check, build, test
- All tests: `pnpm test`
- Single test: `pnpm test -- <pattern>` — **do not** run `jest`/`npx jest` directly; the suite is timezone-sensitive and only passes under `TZ=America/Chicago`, which the `test` script sets.
- Type-check only: `pnpm compile`

## Commit Conventions
## Rules

This repo uses [Conventional Commits](https://www.conventionalcommits.org/):
- `pnpm verify` must pass before a task is complete. Don't claim done without it.
- Squash-merge only. Don't worry about conventional commits on feature-branch commits — name the **PR** per the Conventional Commits types (see README.md "Workflow"). The squash commit title comes from the PR title.

- `feat:` - New feature
- `fix:` - Bug fix
- `chore:` - Refactor, lint fixes, formatting
- `ci:` - CI updates
- `docs:` - Documentation changes
- `BREAKING CHANGE:` - Breaking changes
## Do not touch

PRs are squash-merged, so commit messages on feature branches don't need to follow the convention—just name the PR correctly.
- `dist/` — build output from tsup.
Loading