diff --git a/.gitignore b/.gitignore index f866521..1c01ac9 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ ecosystem.config.cjs /config.yml coverage/ +/data/lab.dev-backup-20260127.db diff --git a/QUICK_REFERENCE.md b/QUICK_REFERENCE.md new file mode 100644 index 0000000..30dd75b --- /dev/null +++ b/QUICK_REFERENCE.md @@ -0,0 +1,239 @@ +# 🦊 HPL CLI - Quick Reference Checklist + +> **TL;DR** of the full STYLE_GUIDE.md - print this and keep it handy! + +--- + +## Before You Start πŸš€ + +```bash +β–‘ npm install +β–‘ npm run build +β–‘ npm test +β–‘ Read STYLE_GUIDE.md (at least the Import Rules section!) +``` + +--- + +## The #1 Rule ⚠️ + +**ALL relative imports MUST end in `.js`** (even for `.ts` files) + +```typescript +βœ… import { foo } from "./bar.js" +❌ import { foo } from "./bar" +``` + +--- + +## Before Every Commit βœ… + +```bash +β–‘ npm run build # Succeeds? +β–‘ npm test # Passes? +β–‘ Check .js extensions # All imports have them? +β–‘ Commit message # Emoji prefix + format? +``` + +--- + +## Commit Format πŸ“ + +``` + : +``` + +Common prefixes: +- `βš™οΈ feat:` - New features +- `πŸ› fix:` - Bug fixes +- `πŸ“š docs:` - Documentation +- `πŸ”§ refactor:` - Code restructuring +- `βœ… test:` - Tests +- `πŸŒ‰ bridge:` - Relay system + +--- + +## Quick Commands πŸ’» + +```bash +# Development +npm run dev # Run with tsx (no build) +npm run build # Compile TypeScript +npm start # Run built version + +# Testing +npm test # All tests +npm test:watch # Watch mode + +# Local Install +npm install -g . # Install globally +hpl version # Test it works + +# Emergency Reset +rm -rf dist/ node_modules/ +npm install && npm run build +``` + +--- + +## Debugging Imports πŸ” + +```bash +# Find imports missing .js +grep -r "from ['\"]\.\.*/[^'\"]*[^s]['\"]" src/ --include="*.ts" | grep -v "\.js['\"]" + +# Or just look at the error: +# "Cannot find module '.../XXX' imported from YYY.js" +# ^^^ ^^^ +# Missing .js Check this source file +``` + +--- + +## Command Structure Pattern πŸ“‹ + +```typescript +import { Command } from "commander"; +import { writeHuman, writeJson } from "../io.js"; +import { EXIT } from "../contract/exitCodes.js"; +import { getAlphaIntent } from "../contract/intents.js"; +import { ok } from "../contract/envelope.js"; + +type GlobalOpts = { json?: boolean }; + +export function myCommand(): Command { + return new Command("mycommand") + .description("...") + .action((...args: any[]) => { + const cmd = args[args.length - 1] as Command; + const opts = (cmd.parent?.opts?.() ?? {}) as GlobalOpts; + + const result = runMyCommand(); + + if (opts.json) writeJson(result); + else writeHuman("..."); + + process.exitCode = EXIT.OK; + }); +} + +export function runMyCommand() { + const intent = getAlphaIntent("my_intent"); + return ok("mycommand", intent, { /* data */ }); +} +``` + +--- + +## Common Gotchas πŸ› + +| Problem | Cause | Fix | +|---------|-------|-----| +| `ERR_MODULE_NOT_FOUND` | Missing `.js` | Add `.js` to import | +| Type passes, runtime fails | No validation | Use Zod schemas | +| JSON has extra output | Logs to stdout | Use `console.error()` | +| Wrong exit code | Not set | Set `process.exitCode` | +| Old version runs | npm cache | `npm uninstall -g && npm cache clean --force` | + +--- + +## Contract Rules πŸ“œ + +**Breaking Changes** (DON'T DO in v0.x): +- ❌ Change envelope structure +- ❌ Remove JSON fields +- ❌ Change exit codes +- ❌ Rename commands +- ❌ Change intent IDs + +**Safe Changes**: +- βœ… Add new commands +- βœ… Add new JSON fields +- βœ… Add new intents +- βœ… Improve error messages +- βœ… Internal refactoring + +--- + +## VS Code Setup πŸ› οΈ + +Add to `.vscode/settings.json`: + +```json +{ + "typescript.preferences.importModuleSpecifierEnding": "js", + "typescript.preferences.importModuleSpecifier": "relative" +} +``` + +This auto-adds `.js` to imports! + +--- + +## Files to Know πŸ“ + +``` +src/ +β”œβ”€β”€ contract/ # Output contracts - STABLE +β”‚ β”œβ”€β”€ schema.ts # Zod schemas +β”‚ β”œβ”€β”€ envelope.ts # Success/error wrappers +β”‚ β”œβ”€β”€ intents.ts # Intent registry +β”‚ └── exitCodes.ts # Exit code constants +β”œβ”€β”€ commands/ # CLI commands +β”‚ └── notes/ # Domain commands +β”œβ”€β”€ lib/ # Shared utilities +└── io.ts # stdout/stderr helpers + +bin/ +└── hpl.ts # Entrypoint +``` + +--- + +## Need More Info? πŸ“– + +See **STYLE_GUIDE.md** for: +- Detailed explanations +- More code examples +- Architecture decisions +- Full gotcha list +- Contract details + +--- + +## Emergency Contact πŸ†˜ + +**Totally Stuck?** + +1. Check error message carefully (it tells you which file!) +2. Look at similar existing code +3. Run `npm test` to see examples +4. Full reset: `rm -rf dist/ node_modules/ && npm install && npm run build` +5. Ask for help (with error message + what you tried) + +--- + +## Status Checks βœ“ + +**Healthy Repo**: +```bash +$ npm run build +βœ“ Compiled successfully + +$ npm test +βœ“ All tests passing + +$ npm start version +βœ“ Shows version + +$ hpl version +βœ“ Shows version (global install works) +``` + +--- + +**Print this page and tape it to your monitor!** 🦊 + +--- + +*Quick ref for STYLE_GUIDE.md - Last updated: 2025-01-27* diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md new file mode 100644 index 0000000..4868bf2 --- /dev/null +++ b/STYLE_GUIDE.md @@ -0,0 +1,647 @@ +# 🦊 The Human Pattern Lab CLI - Style Guide + +> **Purpose**: This guide captures the conventions, patterns, and gotchas specific to this codebase. Read this before making changes to avoid common pitfalls! + +--- + +## πŸ“‹ Table of Contents + +1. [Quick Start](#quick-start) +2. [Import Rules (CRITICAL)](#import-rules-critical) +3. [File Structure & Naming](#file-structure--naming) +4. [Code Conventions](#code-conventions) +5. [Commit Message Format](#commit-message-format) +6. [Testing & Building](#testing--building) +7. [Common Gotchas](#common-gotchas) + +--- + +## Quick Start + +### For New Contributors + +```bash +# 1. Clone and install +git clone +cd the-human-pattern-lab-cli +npm install + +# 2. Build +npm run build + +# 3. Test locally +npm start version + +# 4. Install globally (optional) +npm install -g . +hpl version + +# 5. Run tests +npm test +``` + +### Key Things to Know Immediately + +- βœ… **ES Modules**: This project uses ES Modules (`"type": "module"`) +- βœ… **Import Extensions**: ALL relative imports MUST include `.js` (even for `.ts` files) +- βœ… **Lore-Coded Commits**: Use emoji prefixes (see [Commit Messages](#commit-message-format)) +- βœ… **Contract-First**: Output formats are contracts - changes are breaking +- βœ… **JSON Purity**: `--json` mode MUST only emit JSON to stdout + +--- + +## Import Rules (CRITICAL) + +### ⚠️ The #1 Source of Errors + +**Rule**: ALL relative imports MUST end in `.js`, even though the source files are `.ts`. + +### Why? + +Node.js ES Modules require explicit file extensions. TypeScript doesn't add them automatically, so you must write them yourself. + +### Examples + +```typescript +// ❌ WRONG - Will cause ERR_MODULE_NOT_FOUND at runtime +import { something } from "./utils" +import { other } from "../lib/config" +import { helper } from "./helpers/index" + +// βœ… CORRECT - Add .js to all relative imports +import { something } from "./utils.js" +import { other } from "../lib/config.js" +import { helper } from "./helpers/index.js" + +// βœ… ALSO CORRECT - npm packages don't need extensions +import { Command } from "commander" +import { z } from "zod" +import fs from "node:fs" +``` + +### Quick Check + +Before committing, search for potential missing extensions: + +```bash +# Find imports that might be missing .js +grep -r "from ['\"]\.\.*/[^'\"]*[^s]['\"]" src/ --include="*.ts" | grep -v "\.js['\"]" +``` + +### VS Code Auto-Import Setup + +Add to `.vscode/settings.json`: + +```json +{ + "typescript.preferences.importModuleSpecifierEnding": "js", + "typescript.preferences.importModuleSpecifier": "relative" +} +``` + +This makes VS Code auto-add `.js` when using auto-import! + +--- + +## File Structure & Naming + +### Directory Layout + +``` +src/ +β”œβ”€β”€ commands/ # CLI command implementations +β”‚ β”œβ”€β”€ version.ts +β”‚ β”œβ”€β”€ capabilities.ts +β”‚ └── notes/ # Domain-specific commands +β”‚ β”œβ”€β”€ notes.ts # Domain root (assembler) +β”‚ β”œβ”€β”€ list.ts +β”‚ β”œβ”€β”€ get.ts +β”‚ └── create.ts +β”œβ”€β”€ contract/ # Output contracts & schemas +β”‚ β”œβ”€β”€ envelope.ts # Success/error wrappers +β”‚ β”œβ”€β”€ intents.ts # Intent registry +β”‚ β”œβ”€β”€ schema.ts # Zod schemas +β”‚ └── exitCodes.ts +β”œβ”€β”€ lib/ # Shared utilities +β”œβ”€β”€ http/ # HTTP client +β”œβ”€β”€ sdk/ # SDK exports +└── io.ts # Input/output helpers +``` + +### Naming Conventions + +**Files**: `camelCase.ts` or `kebab-case.ts` (be consistent within a directory) +**Types**: `PascalCase` +**Functions**: `camelCase` +**Constants**: `SCREAMING_SNAKE_CASE` (for true constants) or `camelCase` (for config) +**Enums**: `PascalCase` (enum name) and `SCREAMING_SNAKE_CASE` (values) or `camelCase` (values) + +### File Naming Patterns + +```typescript +// Command files: .ts +src/commands/version.ts +src/commands/health.ts + +// Domain folders: /.ts is the assembler +src/commands/notes/notes.ts // Mounts subcommands +src/commands/notes/list.ts // Individual subcommand + +// Contract files: singular nouns +src/contract/envelope.ts +src/contract/schema.ts +``` + +--- + +## Code Conventions + +### File Headers + +All source files should have a lore-coded header: + +```typescript +/* =========================================================== + 🌌 HUMAN PATTERN LAB β€” + ----------------------------------------------------------- + Purpose: + Contract: + Notes: + - + - + =========================================================== */ +``` + +### Function Ordering + +Within a file, order from public β†’ private, top β†’ bottom: + +```typescript +// 1. Exports first (public API) +export function publicFunction() { ... } +export type PublicType = { ... } + +// 2. Internal helpers below +function helperFunction() { ... } + +// 3. Constants at top or bottom (be consistent) +const INTERNAL_CONSTANT = "value"; +``` + +### Command Pattern + +Commands follow this structure: + +```typescript +import { Command } from "commander"; +import { writeHuman, writeJson } from "../io.js"; +import { EXIT } from "../contract/exitCodes.js"; +import { getAlphaIntent } from "../contract/intents.js"; +import { ok, err } from "../contract/envelope.js"; + +type GlobalOpts = { json?: boolean }; + +export function myCommand(): Command { + return new Command("mycommand") + .description("What this command does (contract: intent_name)") + .action((...args: any[]) => { + const cmd = args[args.length - 1] as Command; + const rootOpts = (cmd.parent?.opts?.() ?? {}) as GlobalOpts; + + const result = runMyCommand(); + + if (rootOpts.json) { + writeJson(result); + } else { + writeHuman("Human-friendly output"); + } + + process.exitCode = EXIT.OK; + }); +} + +// Core logic separated from commander adapter +export function runMyCommand() { + const intent = getAlphaIntent("my_intent"); + return ok("mycommand", intent, { data: "here" }); +} +``` + +### Error Handling + +```typescript +// βœ… GOOD - Return error envelopes +try { + const data = await fetchData(); + return ok("command", intent, data); +} catch (error: any) { + return err("command", intent, { + code: "E_NETWORK", + message: "Failed to fetch data", + details: { originalError: error.message } + }); +} + +// ❌ BAD - Don't throw unhandled errors +const data = await fetchData(); // Could throw! +``` + +### Type Safety + +```typescript +// βœ… GOOD - Use Zod for runtime validation +const DataSchema = z.object({ + id: z.string(), + count: z.number() +}); + +type Data = z.infer; + +// Validate at runtime +const data = DataSchema.parse(unknownData); + +// ❌ BAD - Assuming types without validation +const data = unknownData as Data; // No runtime check! +``` + +--- + +## Commit Message Format + +### Lore-Coded Format (The Human Pattern Lab Style) + +This repo uses emoji-prefixed commit messages following the lab's department system: + +``` + : + + + + +``` + +### Common Prefixes + +**Engineering & Code (SCMS)** +- `βš™οΈ feat:` - New features +- `πŸ› fix:` - Bug fixes +- `πŸ”§ refactor:` - Code restructuring (no behavior change) +- `⚑ perf:` - Performance improvements +- `πŸ—οΈ build:` - Build system changes + +**Documentation & Knowledge (KROM)** +- `πŸ“š docs:` - Documentation changes +- `πŸ“ content:` - Content updates +- `🎨 style:` - Code style changes (formatting, no logic change) + +**Testing & Quality (QA)** +- `βœ… test:` - Adding or updating tests +- `πŸ§ͺ experiment:` - Experimental features + +**Infrastructure & Operations** +- `πŸš€ deploy:` - Deployment changes +- `πŸ”’ security:` - Security improvements +- `πŸŒ‰ bridge:` - Relay/bridge system changes (Liminal Bridge) + +### Examples + +```bash +# Good commit messages +βš™οΈ feat: Add relay generation command +πŸ› fix: Add missing .js extensions to contract imports +πŸ“š docs: Update README with relay examples +πŸ”§ refactor: Extract HTTP client to separate module +βœ… test: Add tests for envelope builders + +# Include body for complex changes +βš™οΈ feat: Implement notes sync command + +Add bidirectional sync between local markdown files and API. +Supports dry-run mode and conflict resolution. + +Closes #42 +``` + +### Commit Message Checklist + +- [ ] Starts with appropriate emoji +- [ ] Scope is relevant (feat/fix/docs/etc) +- [ ] Subject line ≀ 50 chars (aim for this) +- [ ] Subject is imperative mood ("Add" not "Added") +- [ ] Body explains WHY, not WHAT (code shows what) +- [ ] Breaking changes noted in footer + +--- + +## Testing & Building + +### Build Process + +```bash +# Clean build +rm -rf dist/ +npm run build + +# Watch mode (development) +npm run dev + +# Run without building (tsx) +npm run dev version +``` + +### Testing + +```bash +# Run all tests +npm test + +# Watch mode +npm test:watch + +# Single test file +npm test -- src/__tests__/config.test.ts +``` + +### Local Testing Before Publishing + +```bash +# 1. Build +npm run build + +# 2. Test built version +npm start version + +# 3. Install globally from local +npm install -g . + +# 4. Test global install +hpl version +hpl version --json + +# 5. Check actual output +hpl version --json | node -e "JSON.parse(require('fs').readFileSync(0,'utf8'))" +``` + +--- + +## Common Gotchas + +### 1. Missing .js Extensions + +**Symptom**: `Error [ERR_MODULE_NOT_FOUND]: Cannot find module` + +**Cause**: Relative import missing `.js` extension + +**Fix**: Add `.js` to the import in the SOURCE file (not compiled) + +```typescript +// ❌ Before +import { foo } from "./bar" + +// βœ… After +import { foo } from "./bar.js" +``` + +### 2. Type vs Runtime + +**Symptom**: Type checks pass but crashes at runtime + +**Cause**: TypeScript types don't validate data at runtime + +**Fix**: Use Zod schemas for runtime validation + +```typescript +// βœ… Do this +const UserSchema = z.object({ + name: z.string(), + age: z.number() +}); + +const user = UserSchema.parse(unknownData); // Runtime check! +``` + +### 3. JSON Purity + +**Symptom**: `--json` mode contains non-JSON output + +**Cause**: Console logs or errors going to stdout + +**Fix**: Use stderr for logs, stdout ONLY for JSON + +```typescript +// ❌ BAD +console.log("Fetching data..."); // Goes to stdout! +if (opts.json) writeJson(result); + +// βœ… GOOD +if (!opts.json) { + console.error("Fetching data..."); // stderr only +} +writeJson(result); // stdout +``` + +### 4. Exit Codes + +**Symptom**: Commands succeed but return non-zero exit code + +**Cause**: Not setting `process.exitCode` properly + +**Fix**: Always set explicit exit codes + +```typescript +import { EXIT } from "../contract/exitCodes.js"; + +// Success +process.exitCode = EXIT.OK; + +// Errors +process.exitCode = EXIT.ERROR; +process.exitCode = EXIT.INVALID_INPUT; +``` + +### 5. Global Install Issues + +**Symptom**: Old version runs after `npm install -g .` + +**Cause**: npm cache or permission issues + +**Fix**: Full reinstall + +```bash +# Uninstall +npm uninstall -g @thehumanpatternlab/hpl + +# Clear cache +npm cache clean --force + +# Reinstall +cd /path/to/the-human-pattern-lab-cli +npm run build +npm install -g . +``` + +### 6. Windows Path Issues + +**Symptom**: Tests fail on Windows but pass on Mac/Linux + +**Cause**: Hardcoded `/` separators instead of `path.join()` + +**Fix**: Use Node.js path module + +```typescript +import path from "node:path"; + +// ❌ BAD +const filePath = `${dir}/file.txt`; + +// βœ… GOOD +const filePath = path.join(dir, "file.txt"); +``` + +--- + +## Contract Guarantees + +### What is a Contract? + +The CLI's output format is a **contract** - a stable interface that scripts and agents depend on. Breaking the contract breaks automation. + +### Contract Rules + +1. **Schema versioning**: All JSON output includes `schemaVersion` +2. **Intent disclosure**: All commands declare their `intent` +3. **Envelope structure**: Success/error formats are stable +4. **Exit codes**: Deterministic exit codes for each scenario +5. **Additive only**: In v0.x, we can ADD but not CHANGE/REMOVE + +### What's Breaking? + +**Breaking Changes** (require major version bump): +- Changing envelope structure +- Removing fields from JSON output +- Changing exit code meanings +- Renaming commands or flags +- Changing intent IDs + +**Non-Breaking Changes** (safe in minor versions): +- Adding new commands +- Adding optional fields to output +- Adding new intents +- Improving error messages +- Internal refactoring + +--- + +## Development Workflow + +### Standard Workflow + +```bash +# 1. Create feature branch +git checkout -b feat/my-feature + +# 2. Make changes +# ... edit files ... + +# 3. Build and test +npm run build +npm test +npm start + +# 4. Commit with lore-coded message +git add . +git commit -m "βš™οΈ feat: Add my feature" + +# 5. Push and create PR +git push origin feat/my-feature +``` + +### Before Committing Checklist + +- [ ] Build succeeds: `npm run build` +- [ ] Tests pass: `npm test` +- [ ] Linter happy: `npm run lint` (when added) +- [ ] All imports have `.js` extensions +- [ ] Added tests for new features +- [ ] Updated docs if needed +- [ ] Commit message follows format + +--- + +## Quick Reference Card + +**Most Common Commands**: +```bash +npm run build # Compile TypeScript +npm start # Run built version +npm run dev # Run with tsx (no build) +npm test # Run tests +npm install -g . # Install globally from local +``` + +**Emergency Debugging**: +```bash +# Imports not working? +grep -r "from ['\"]\.\.*/[^'\"]*[^s]['\"]" src/ --include="*.ts" | grep -v "\.js['\"]" + +# Clean slate +rm -rf dist/ node_modules/ +npm install +npm run build + +# Global install issues +npm uninstall -g @thehumanpatternlab/hpl +npm cache clean --force +cd /path/to/repo && npm run build && npm install -g . +``` + +**Key Files**: +- `src/contract/schema.ts` - Output contract definitions +- `src/contract/intents.ts` - Intent registry +- `src/io.ts` - stdout/stderr helpers +- `bin/hpl.ts` - CLI entrypoint + +--- + +## Getting Help + +### Resources + +- **README.md**: High-level overview and usage +- **IMPLEMENTATION_NOTES.md**: Architecture decisions +- **docs/**: API documentation and guides + +### When in Doubt + +1. Look at existing commands for patterns +2. Check contract files for schema examples +3. Run `npm test` to see expected behavior +4. Ask in #engineering channel (if applicable) + +--- + +## Style Guide Itself + +### Updating This Guide + +This guide should evolve with the codebase. If you: + +- **Find a new gotcha**: Add it to [Common Gotchas](#common-gotchas) +- **Establish a pattern**: Document it in [Code Conventions](#code-conventions) +- **Change a rule**: Update relevant sections and note breaking changes + +Keep this guide: +- **Practical**: Focus on actionable advice +- **Concise**: Get to the point +- **Current**: Update when patterns change +- **Friendly**: Help future contributors (including future you!) + +--- + +**Last Updated**: 2025-01-27 +**Maintainer**: The Human Pattern Lab / SCMS +**Status**: Living Document 🦊 + +--- + +*"The hallwayβ€”er, bridgeβ€”exists, serves its purpose, and disappears."* πŸŒ‰ diff --git a/docs/RELAY_IMPLEMENTATION.md b/docs/RELAY_IMPLEMENTATION.md index 84012c9..a0f492b 100644 --- a/docs/RELAY_IMPLEMENTATION.md +++ b/docs/RELAY_IMPLEMENTATION.md @@ -2,7 +2,7 @@ ## What We Built -The **Hallway Architecture** relay service for The Human Pattern Lab. This enables AI agents with credential restrictions (like ChatGPT) to post Lab Notes using temporary, single-use URLs. +The **Liminal Bridge** relay service for The Human Pattern Lab. This enables AI agents with credential restrictions (like ChatGPT) to post Lab Notes using temporary, single-use URLs. ## Files Created @@ -239,4 +239,4 @@ When complete, you should be able to: --- -**The hallway exists, serves its purpose, and disappears.** πŸ›οΈ +**The bridge exists, serves its purpose, and disappears.** πŸŒ‰ diff --git a/src/db.ts b/src/db.ts index 11d96b5..c887995 100644 --- a/src/db.ts +++ b/src/db.ts @@ -9,6 +9,7 @@ import { migrateLabNotesSchema, LAB_NOTES_SCHEMA_VERSION } from "./db/migrateLab import {dedupeLabNotesSlugs} from "./db/migrations/2025-01-dedupe-lab-notes-slugs.js"; import { migrateApiTokensSchema } from "./db/migrateApiTokens.js"; import { createRelaySessions } from "./db/migrations/2025-01-add-relay-sessions.js"; +import { up as createBridgePosts } from "./db/migrations/2025-01-28-add-bridge-posts.js"; export function resolveDbPath(): string { const __filename = fileURLToPath(import.meta.url); @@ -81,6 +82,7 @@ export function bootstrapDb(db: Database.Database) { migrateLabNotesSchema(db, log); migrateApiTokensSchema(db, log); createRelaySessions(db, log); + createBridgePosts(db); // πŸŒ‰ Liminal Bridge posts table if (prevVersion < 3) { dedupeLabNotesSlugs(db, log); } diff --git a/src/db/migrations/2025-01-28-add-bridge-posts.ts b/src/db/migrations/2025-01-28-add-bridge-posts.ts new file mode 100644 index 0000000..c78ebb6 --- /dev/null +++ b/src/db/migrations/2025-01-28-add-bridge-posts.ts @@ -0,0 +1,34 @@ +import type { Database } from "better-sqlite3"; + +/** + * Migration: Add bridge_posts table + * + * This table stores posts that are relayed through the Liminal Bridge system, + * allowing AI collaborators with credential restrictions to post Lab Notes + * autonomously through a relay mechanism. + */ + +export const up = (db: Database) => { + db.exec(` + CREATE TABLE IF NOT EXISTS bridge_posts ( + id TEXT PRIMARY KEY, + content TEXT NOT NULL, + voice TEXT NOT NULL, + relay_session_id TEXT NOT NULL, + created_at TEXT NOT NULL, + posted_at TEXT, + status TEXT DEFAULT 'pending', + FOREIGN KEY (relay_session_id) REFERENCES relay_sessions(id) + ); + + CREATE INDEX IF NOT EXISTS idx_bridge_posts_voice ON bridge_posts(voice); + CREATE INDEX IF NOT EXISTS idx_bridge_posts_status ON bridge_posts(status); + CREATE INDEX IF NOT EXISTS idx_bridge_posts_relay_session ON bridge_posts(relay_session_id); + `); +}; + +export const down = (db: Database) => { + db.exec(` + DROP TABLE IF EXISTS bridge_posts; + `); +}; \ No newline at end of file