workshop/packages/spike/CLAUDE.md
Corey Johnson 238df92888 Untangle Spike architecture with bridge pattern
Split the monolithic gitea/helpers.ts (which had Discord imports and created circular dependencies) into three focused libs:

1. **gitea/** — Pure API client: fetchPR, fetchReviewComments, convertUsername, threadName. No side effects or external deps.

2. **discord/** — Discord client setup: bot login, event listeners, slash commands. Now isolated from Gitea internals.

3. **bridge/** — New integration layer: webhook handler, DB mappings (Gitea PR ↔ Discord thread), Discord helpers, and createPRComment.

Dependencies now flow one direction: bridge → gitea and bridge → discord. No circular imports.

Added:
- Barrel exports (index.ts) for each lib with public API
- README.md for each lib documenting the barrel exports
- Comprehensive spike README.md with setup guide and architecture explanation
- Integration tests for webhooks (callback-based, no race conditions)
- Unit tests for pure API functions
- CLAUDE.md with links to each lib's README

This architecture makes it possible for AI to understand a lib by reading just its README, keeping context focused and small.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-09 15:23:11 -07:00

2.1 KiB

Spike

Discord-Gitea bridge bot. Syncs PRs, comments, and code reviews between a Gitea server (git.nose.space) and Discord.

Architecture

src/
├── server.tsx     — HTTP server (webhook endpoint, health check, error log)
├── config.ts      — Dev/prod environment config (DB paths, channel IDs, username mappings)
├── discord/       — Discord bot client, event listeners, slash commands
├── gitea/         — Gitea API calls, types, username conversion
└── bridge/        — Wiring between Gitea and Discord (webhook handler, DB, Discord helpers)

Dependencies flow one way: bridge/ → gitea/, bridge/ → discord/. Neither gitea/ nor discord/ imports from the other.

Libs

Each directory with an index.ts barrel is a standalone lib. Read the lib's README for its public API — you don't need to read internals to use it.

  • gitea/ — Pure Gitea API client and types. No side effects, no Discord, no DB.
  • discord/ — Discord bot client, events, slash commands. Hands off to bridge for Gitea integration.
  • bridge/ — The glue. Webhook handler, Discord helpers, SQLite DB for ID mappings.

Import rules:

  • External code imports from the barrel only: import { handleGiteaWebhook } from "./bridge"
  • Never reach into internal files: import { handleGiteaWebhook } from "./bridge/webhook-handler"
  • Internal files within a lib can import from each other freely

This keeps AI context small. When working on code that uses a lib, only read the lib's README — not every internal file.

Running

  • bun run subdomain:dev — Start with hot reload
  • bun run subdomain:start — Start for production
  • bun test — Run integration tests (requires Tailscale funnel + test env vars)

Environment Variables

  • DISCORD_TOKEN — Discord bot token
  • DISCORD_CLIENT_ID — Discord application client ID
  • GITEA_API_TOKEN — Gitea API token
  • DATA_DIR — Data directory (prod only)
  • NODE_ENVproduction or omit for dev
  • PORT — Server port (default 3000)