- Update `VibeCard` to support custom `children` content and ensure text readability with a gradient overlay.
- Refactor Outfit list in `Equipments.tsx` to use a grid of `VibeCard` components.
- Implement a 3x3 equipment preview grid inside Outfit cards, with overflow (+N) handling.
- Center the preview grid to 80% height as per design requirements.
- Update `CreateOutfitDialog` to support editing existing outfits (PUT request).
- Change category selection in `CreateOutfitDialog` to single-select.
- Update equipment selection grid in `CreateOutfitDialog` to fixed 3 columns.
- Add "Edit" action to Outfit cards.
- Fitting Room:
- Constrain page height to viewport.
- Use `ScrollArea` for "Generated Looks".
- Ensure character image uses `object-contain` and empty state is centered.
- Extractor:
- Add "Save as Outfit" checkbox and name input to `RefineStage`.
- Implement API call to create outfit upon completion.
- Dockerfile:
- Copy `example-data` directory to final image.
- Fixed Fitting Room page overflow by constraining height and using ScrollArea for the Generated Looks section.
- Added "Save as Outfit" checkbox and input to the Refine stage of the Extractor dialog.
- Installed @radix-ui/react-checkbox and added Shadcn Checkbox component.
- Updated Dockerfile to include example-data directory in the final image.
- Removed hardcoded `BUILTIN_POSES` and `BUILTIN_EXPRESSIONS` constants.
- Updated `PoseService` and `ExpressionService` to only list and delete items from the database.
- Removed the `type` field ('builtin' | 'custom') from `PoseItem` and `ExpressionItem`.
- Updated `GenerationService` to resolve pose and expression assets strictly from the database (`data/files`) instead of falling back to `public/`.
- Updated `Poses.tsx` and `Expressions.tsx` to remove "SYSTEM" vs "CUSTOM" UI distinction and enable deletion for all items.
- Updated `pose.test.ts` and created `expression.test.ts` to verify the new behavior.
- Fixed `generation.test.ts` to mock database calls correctly for pose/expression lookups and avoid polluting other tests.
- Removed hardcoded `BUILTIN_POSES` and `BUILTIN_EXPRESSIONS` constants.
- Updated `PoseService` and `ExpressionService` to only list and delete items from the database.
- Removed the `type` field ('builtin' | 'custom') from `PoseItem` and `ExpressionItem`.
- Updated `GenerationService` to resolve pose and expression assets strictly from the database (`data/files`) instead of falling back to `public/`.
- Updated `Poses.tsx` and `Expressions.tsx` to remove "SYSTEM" vs "CUSTOM" UI distinction and enable deletion for all items.
- Updated `pose.test.ts` and created `expression.test.ts` to verify the new behavior.
- Added `POST /api/equipments` endpoint to create equipment from an existing asset.
- Created `UploadEquipmentDialog` component with drag-and-drop and clipboard paste support.
- Added "Upload" button to the Equipments page header.
- Verified new equipment creation flow via frontend verification script.
- Added `POST /api/equipments` endpoint to create equipment from an existing asset.
- Created `UploadEquipmentDialog` component with drag-and-drop and clipboard paste support.
- Added "Upload" button to the Equipments page header.
- Verified new equipment creation flow via frontend verification script.
- Update prisma/schema.prisma to use @default(ulid()) for all relevant models
- Remove manual ulid() calls from all service files
- Update list APIs to order by id descending
- Update AssetService tests to match new behavior
- Update AGENTS.md with new conventions
- Remove empty migration file (20260217022222_add_ulid_default)
* I added `DialogFooter` to `ExtractorDialog`.
* I moved the action buttons (Start, Cancel, and the finish button) from `AnalyzeStage`, `SelectionStage`, and `RefineStage` to the `ExtractorDialog` footer.
* I lifted the `selectedIndices` state from `SelectionStage` to `ExtractorDialog`.
* I updated `AnalyzeStage` to show the status in the primary action button.
* I enabled cancellation during analysis.
* I ensured that `onSuccess` is called only when the user clicks the finish button in the Refine stage.
- Refactor `ExtractorDialog.tsx` into modular stages: `UploadStage`, `AnalyzeStage`, `SelectionStage`, `RefineStage`.
- Implement new UI flow: Upload -> Analyze -> Select -> Refine.
- Adapt "vibe" reference visuals to application's Light Mode theme (Slate/Cyan/Amber).
- Implement real-time status updates for analysis and refinement steps using backend streams.
- Add drag-and-drop and paste support for image upload.
- Visualize candidate selection grid and refinement progress.
- Implement manual confirmation for analysis start.
- Increase dialog size to `max-w-[98vw]` and `h-[95vh]`.
- Simplify title bar and adjust candidate grid cell size to 140px.
Updates the test expectations in `src/service/extraction.test.ts` to match the actual prompt content used in `src/service/extraction.ts`. The previous test was asserting the presence of specific instructions regarding cropping artifacts that are no longer present in the codebase. The updated test now verifies the presence of the task name and the instruction to return only the image.
- Restored the centered logo `<div>` block at the top as requested.
- Replaced generic intro with "Why Forgery?", "Highlights", and "Core Concepts" sections derived from marketing copy.
- Corrected tech stack information (Bun, Hono, React, SQLite) to match the codebase.
- Replaced incorrect `curl` demos with a UI-focused "How It Works" workflow.
- Updated installation instructions to use `bun` commands.
- Added "Architecture Overview" to explain the modular pipeline.
- Replaced generic intro with "Why Forgery?", "Highlights", and "Core Concepts" sections derived from marketing copy.
- Corrected tech stack information (Bun, Hono, React, SQLite) to match the codebase.
- Replaced incorrect `curl` demos with a UI-focused "How It Works" workflow.
- Updated installation instructions to use `bun` commands.
- Added "Architecture Overview" to explain the modular pipeline.
- Add semi-transparent dark background to delete button for better visibility on light images.
- Remove equipment labels from generation cards in Fitting Room.
- Implement `ExampleDataService` to export/import Characters, Equipments, Poses, Expressions, and Generations.
- Add `generate-example` script to `package.json` to generate example data from current DB.
- Add startup logic in `src/index.ts` to seed example data if system is uninitialized and no data exists.
- Store system initialization state in `Setting` table.
- Add comprehensive tests for `ExampleDataService` in `src/service/example-data.test.ts` mocking `Bun` file API and `node:fs`.
- Refactor `src/service/example-data.ts` to use `Bun.file` and `Bun.write` for file I/O, ensuring better compatibility with Bun's test runner.
- Implement `ExampleDataService` to export/import Characters, Equipments, Poses, Expressions, and Generations.
- Add `generate-example` script to `package.json` to generate example data from current DB.
- Add startup logic in `src/index.ts` to seed example data if system is uninitialized and no data exists.
- Store system initialization state in `Setting` table.
- Add comprehensive tests for `ExampleDataService` in `src/service/example-data.test.ts` mocking filesystem and database operations.
- Refactor `src/service/example-data.ts` to use default `node:fs` import for better test compatibility.
- Implement `ExampleDataService` to export/import Characters, Equipments, Poses, Expressions, and Generations.
- Add `generate-example` script to `package.json` to generate example data from current DB.
- Add startup logic in `src/index.ts` to seed example data if system is uninitialized and no data exists.
- Store system initialization state in `Setting` table.
- Add comprehensive tests for `ExampleDataService` in `src/service/example-data.test.ts` mocking filesystem and database operations.
- Implement `ExampleDataService` to export/import Characters, Equipments, Poses, Expressions, and Generations.
- Add `generate-example` script to `package.json` to generate example data from current DB.
- Add startup logic in `src/index.ts` to seed example data if system is uninitialized and no data exists.
- Store system initialization state in `Setting` table.
- Add comprehensive tests for `ExampleDataService` in `src/service/example-data.test.ts` mocking filesystem and database operations.
- Implement `ExampleDataService` to export/import Characters, Equipments, Poses, Expressions, and Generations.
- Add `generate-example` script to `package.json` to generate example data from current DB.
- Add startup logic in `src/index.ts` to seed example data if system is uninitialized and no data exists.
- Store system initialization state in `Setting` table.
- Add comprehensive tests for `ExampleDataService` in `src/service/example-data.test.ts` mocking filesystem and database operations.
- Add `DELETE /api/equipments/:id` endpoint.
- Add `deleteEquipment` method to `EquipmentService` which also cleans up associated assets and generation references.
- Implement delete action in `Equipments` page UI.
- Pass `actions` prop to `VibeCard` to enable context menu.
Split the equipment extraction process into two phases:
1. Analyze & Split: Generates texture sheet and crops assets.
2. Refine & Save: Allows user to select which assets to keep before refining and saving.
- Refactored `src/api/extract.ts` to expose `/analyze` and `/refine` endpoints.
- Updated `src/ui/components/ExtractorDialog.tsx` to handle the multi-step flow and selection UI.
- Added `CandidateAsset` type and updated `ExtractionStatus` in `src/ui/types.ts`.
- Added `deleteFile` to `FileService` and `deleteAsset` to `AssetService` to support file deletion.
- Implemented cascading deletion in `CharacterService` (delete looks -> delete character image -> delete character).
- Updated `GenerationService`, `PoseService`, and `ExpressionService` to delete associated image assets upon deletion.
- Added `DELETE /api/generations/:id` endpoint.
- Created `DropdownMenu` and `DeleteConfirmDialog` UI components.
- Updated `VibeCard` to include an internal `DropdownMenu` driven by a new `actions` prop.
- Updated `Characters`, `Poses`, and `Expressions` pages to use the new `VibeCard` `actions` prop for deletion.
- Updated `FittingRoom` page to use the `DropdownMenu` and `DeleteConfirmDialog` for deleting looks.
- Updated `CreateLookDialog` to enforce single selection for equipment categories.
- Added necessary tests adjustments.
- Added `deleteFile` to `FileService` and `deleteAsset` to `AssetService` to support file deletion.
- Implemented cascading deletion in `CharacterService` (delete looks -> delete character image -> delete character).
- Updated `GenerationService`, `PoseService`, and `ExpressionService` to delete associated image assets upon deletion.
- Added `DELETE /api/generations/:id` endpoint.
- Created `DropdownMenu` and `DeleteConfirmDialog` UI components.
- Updated `Characters`, `Poses`, `Expressions`, and `FittingRoom` pages to use the new delete UI (3-dot menu + confirmation).
- Updated `CreateLookDialog` to enforce single selection for equipment categories.
- Added necessary tests adjustments.
- Update `src/service/backup.test.ts` to fully mock `node:fs` methods (`existsSync`, `renameSync`, `mkdirSync`, `rmSync`).
- This prevents the test from interacting with the real file system, eliminating the `ENOENT` race condition error observed in CI pipelines.
- Ensures the test is idempotent and safely verifies the service logic without side effects.
- Verified all 49 tests pass locally.
- Create `BackupService` in `src/service/backup.ts` to encapsulate tar stream creation and restore logic (db connection, fs operations).
- Refactor `src/api/backup.ts` and `src/api/restore.ts` to use `BackupService`.
- Add unit tests for `BackupService` in `src/service/backup.test.ts`.
- Add API tests for backup and restore endpoints in `src/api/backup.test.ts` and `src/api/restore.test.ts`.
- Maintain existing functionality: uncompressed tar streaming, safe restore with rollback.
- Implement `GET /api/backup` to stream `data` directory as a tarball using `node-tar`.
- Implement `POST /api/restore` to accept and extract tarballs to the `data` directory.
- Update `BackupRestoreDialog` to accept `.tar` files and remove gzip references.
- Ensure safe restore with database connection management and rollback.
- Disabled Gzip compression as requested since assets are already compressed WebP files.
- Implement `GET /api/backup` to stream `data` directory as a gzipped tarball using `node-tar`.
- Implement `POST /api/restore` to accept and extract gzipped tarballs to the `data` directory, handling database disconnection/reconnection and rollbacks.
- Add `BackupRestoreDialog` UI component for downloading backups and uploading restore files.
- Integrate backup dialog trigger into the AppSidebar logo.
- Ensure type safety and add temporary integration tests for verification.
- Add `GET /api/backup` endpoint to stream `data` directory as a tar file.
- Add `POST /api/restore` endpoint to handle tar file upload and restore.
- Implement `BackupRestoreDialog` in the UI for user interaction.
- Integrate backup/restore dialog into the sidebar via the logo.
- Ensure safe restore with rollback on failure and database connection management.
- Consolidate SQLite database and file storage into `data/` directory.
- Update `src/index.ts` to ensure `data` and `data/files` directories exist on startup.
- Update `src/db.ts` to use hardcoded `file:./data/data.db` path.
- Update `prisma.config.ts` to use absolute path to `data/data.db` for CLI compatibility.
- Update `.gitignore` to ignore `data/` directory entirely.
- Remove `.env.example` and `.env.test` as they are no longer needed.
- Fix TS2307 typecheck error by adding `*.webp` declaration to `src/env.d.ts`.
- Consolidate SQLite database and file storage into `data/` directory.
- Update `src/index.ts` to ensure `data` and `data/files` directories exist on startup.
- Update `src/db.ts` to use hardcoded `file:./data/data.db` path.
- Update `prisma.config.ts` to use absolute path to `data/data.db` for CLI compatibility.
- Update `.gitignore` to ignore `data/` directory entirely.
- Remove `.env.example` and `.env.test` as they are no longer needed.
- Added `useInfiniteScroll` hook using `react-intersection-observer`.
- Updated `PoseService` and `ExpressionService` to support pagination with mixed built-in and DB items.
- Updated `OutfitService` to support pagination.
- Updated `src/api/pose.ts`, `src/api/expression.ts`, `src/api/outfit.ts`, `src/api/character.ts` to accept `page`/`limit` (default limit 20).
- Refactored `Equipments`, `Characters`, `Poses`, `Expressions` pages to use infinite scroll.
- Refactored `CreateLookDialog` and `LoadOutfitDialog` to use infinite scroll.
- Updated `AGENTS.md` with new guidelines.
This change refines the `CreateLookDialog` layout to be more compact and user-friendly.
Key changes:
- Replaced the sidebar with a text-only vertical navigation bar (`w-32`) to maximize content space.
- Adjusted the equipment, pose, and expression grids to a fixed 2-column layout (`grid-cols-2`) for better item visibility and reduced density.
- Removed icons from sidebar buttons to streamline the interface.
- Updated `ScrollArea` components to correctly fill available height (`h-full`) to enable proper scrolling.
- Maintained the tabbed structure (Equipment, Pose, Expression, Instructions) and footer layout from the previous iteration.
This change refines the `CreateLookDialog` layout to be more compact and user-friendly.
Key changes:
- Replaced the sidebar with a text-only vertical navigation bar (`w-32`) to maximize content space.
- Adjusted the equipment grid to a fixed 2-column layout (`grid-cols-2`) for better item visibility and reduced density.
- Removed icons from sidebar buttons to streamline the interface.
- Maintained the tabbed structure (Equipment, Pose, Expression, Instructions) and footer layout from the previous iteration.
- Rename public/expressions files to expression_*.webp
- Add Expression model to Prisma schema
- Add expression field to Generation model
- Implement ExpressionService and API
- Update GenerationService to support expressions in AI prompt
- Add Expressions page and dialogs
- Update CreateLookDialog to include expression selector
- Add Expressions to sidebar and routing
- Moved builtin poses to `public/poses`
- Added `Pose` model to schema and updated `Generation` model
- Created Pose Service and API
- Added Poses page to Frontend
- Updated CreateLookDialog to allow pose selection
- Updated Generation Service to handle pose instructions
- Added tests for Pose Service and Generation Service update
- Refactored `Equipments` page to use single category selection.
- Updated `FittingRoom` page to use `PageHeader` component.
- Added `backButton` prop to `PageHeader` component to support navigation controls.
- Removed "Manage looks for" hint text from Fitting Room header.
- Updated texture generation and refinement prompts to emphasize capturing and maintaining all details, materials, and patterns.
- Reverted analyze prompt to original state to avoid over-constraint.
- Removed AI-based bounding box detection
- Implemented deterministic grid calculation (1x3, 2x2, 2x3, 3x3)
- Updated extraction prompts to request specific grid layouts and white background
- Removed color assignment logic
- Updated ExtractedAsset interface
- Updated API to stream grid splitting status instead of detection status
- Updated tests to verify new logic and mock removal of color fields
- Removed "Detect Bounding Boxes" step from ExtractionFlowDesigner UI
- Removed AI-based bounding box detection
- Implemented deterministic grid calculation (1x3, 2x2, 2x3, 3x3)
- Updated extraction prompts to request specific grid layouts and white background
- Removed color assignment logic
- Updated ExtractedAsset interface
- Updated API to stream grid splitting status instead of detection status
- Updated tests to verify new logic and mock removal of color fields
- Updated `LookDetailsDialog` to use a top-down layout (image top, details bottom).
- Updated `EquipmentDetailsDialog` to use a top-down layout (image top, form bottom).
- Ensured images are contained and details are scrollable.
- Added `LookDetailsDialog` to display full look image, prompt, and used equipment thumbnails.
- Updated `FittingRoom` page to open `LookDetailsDialog` on look click.
- Added `EquipmentDetailsDialog` to display full equipment image and allow editing name/description.
- Updated `Equipments` page to open `EquipmentDetailsDialog` on equipment click.
- Updated `GenerationService` to include equipment images in look details.
- Added `updateEquipment` to `EquipmentService` and `PATCH /equipments/:id` API endpoint.
- Added unit tests for equipment update functionality.
- Added `Outfit` model and migration.
- Implemented backend service and API for outfits.
- Added frontend support for outfits management (create, list, delete, load, save).
- Updated `AGENTS.md` with Prisma migration guidelines.
- Create `src/ui/components/VibeCard.tsx` as a reusable component for the "vibe coded" card UI.
- Refactor `src/ui/pages/Characters.tsx` to use `VibeCard`.
- Refactor `src/ui/pages/Equipments.tsx` to use `VibeCard`.
- Update `CharacterService` to include generation counts (`_count.generations`) in the list response.
- Update `CharacterAPI` to map `_count.generations` to a flat `looksCount` field.
- Add new CSS classes (`clip-path-slant`, `clip-path-hex`, `scanline`, `font-display`) to `src/ui/index.css`.
- Revamp `src/ui/pages/Characters.tsx` to use the new card design with color bars, looks count, and improved visuals.
- Replaced "System // Operator_Select" with "System // Character_Select", "Select Operator" with "Characters", and "UNITS" with "COUNT".
- Remove `src/ui/CharacterListDemo.tsx`.
- Update `CharacterService` to include generation counts (`_count.generations`) in the list response.
- Update `CharacterAPI` to map `_count.generations` to a flat `looksCount` field.
- Add new CSS classes (`clip-path-slant`, `clip-path-hex`, `scanline`, `font-display`) to `src/ui/index.css`.
- Revamp `src/ui/pages/Characters.tsx` to use the new card design with color bars, looks count, and improved visuals.
- Remove `src/ui/CharacterListDemo.tsx`.
- Update `Generation` model to include `userPrompt`.
- Update `GenerationService` to accept and use `userPrompt` in AI prompt.
- Update `Generation` API to accept `userPrompt`.
- Update `CreateLookDialog` to include an input for `userPrompt`.
- Add tests for `userPrompt` functionality.
- Install `dotenv` for prisma migrations.
Renames the terminology in the Fitting Room feature from "Outfit" to "Look" to better align with future feature plans (where "Outfit" will refer to equipment combinations).
Changes include:
- Renaming `CreateOutfitDialog.tsx` to `CreateLookDialog.tsx`.
- Updating the route from `/characters/:id/outfits` to `/characters/:id/looks`.
- Updating all UI text and internal variable names in the affected components.
- Updating navigation in `Characters.tsx`.
- Add `Setting` model to Prisma schema for storing API keys and model configs.
- Implement `SettingService` and API for managing application settings.
- Refactor `src/service/ai.ts` to `UnifiedAIService` supporting dynamic OpenAI and Google provider selection.
- Add Settings page (`src/ui/pages/Settings.tsx`) to configure providers and default models.
- Update `AppSidebar` to include Settings, use text-under-icon style, and decrease sidebar width to 4.5rem.
- Update `Layout` to move "Forgery" title to header and add GitHub link.
- Add unit tests for `SettingService` and `UnifiedAIService`, mocking database interactions to resolve test environment issues.
- Fix API URL path for settings in frontend client.
- Add `Setting` model to Prisma schema for storing API keys and model configs.
- Implement `SettingService` and API for managing application settings.
- Refactor `src/service/ai.ts` to `UnifiedAIService` supporting dynamic OpenAI and Google provider selection.
- Add Settings page (`src/ui/pages/Settings.tsx`) to configure providers and default models.
- Update `AppSidebar` to include Settings, use text-under-icon style, and increase icon size.
- Update `Layout` to move "Forgery" title to header and add GitHub link.
- Add unit tests for `SettingService` and `UnifiedAIService`.
- Implemented `Character Creation` flow with dialog and image upload.
- Implemented `Fitting Room` page with split view (Character Preview / Generations).
- Implemented `Create Outfit` dialog with equipment filtering and selection.
- Added `POST /api/generations` to handle outfit generation.
- Updated `AIService` to support complex prompt structure with interleaved text and images.
- Updated `CharacterService` to support fetching single character.
- Added frontend routes and components.
- Added relevant tests.
- Fixed lint issues and updated UI sizing to 150px.
- Implemented `Character Creation` flow with dialog and image upload.
- Implemented `Fitting Room` page with split view (Character Preview / Generations).
- Implemented `Create Outfit` dialog with equipment filtering and selection.
- Added `POST /api/generations` to handle outfit generation.
- Updated `AIService` to support complex prompt structure with interleaved text and images.
- Updated `CharacterService` to support fetching single character.
- Added frontend routes and components.
- Added relevant tests.
- Add `react-router-dom` for client-side routing.
- Add `shadcn` components: `Sidebar`, `Dialog`, `Button`, `ScrollArea`, `Avatar`, `Badge`, `Card`, `Sheet`, `Tooltip`, `Separator`, `Input`, `Label`.
- Implement `AppSidebar` with navigation to Characters and Equipments.
- Implement `Characters` page displaying character avatars.
- Implement `Equipments` page with:
- Horizontal scrollable category filter (multi-select).
- Equipment grid layout.
- "Extract Equipment" button opening a `Dialog` (refactored from `Extractor` component, maintaining original UI design).
- Added support for pasting images directly into the Extractor Dialog.
- Update `Equipment` API and Service to support filtering by multiple categories.
- Add database index to `Equipment` table on `[category, subCategory]`.
- Refactor `App.tsx` and `Layout.tsx` to use the new routing and sidebar structure.
- Remove legacy `Stash` and `Extractor` components.
- Add `react-router-dom` for client-side routing.
- Add `shadcn` components: `Sidebar`, `Dialog`, `Button`, `ScrollArea`, `Avatar`, `Badge`, `Card`, `Sheet`, `Tooltip`, `Separator`, `Input`, `Label`.
- Implement `AppSidebar` with navigation to Characters and Equipments.
- Implement `Characters` page displaying character avatars.
- Implement `Equipments` page with:
- Horizontal scrollable category filter (multi-select).
- Equipment grid layout.
- "Extract Equipment" button opening a `Dialog` (refactored from `Extractor` component but maintaining original UI design).
- Update `Equipment` API and Service to support filtering by multiple categories.
- Add database index to `Equipment` table on `[category, subCategory]`.
- Refactor `App.tsx` and `Layout.tsx` to use the new routing and sidebar structure.
- Remove legacy `Stash` and `Extractor` components.
- Add `react-router-dom` for client-side routing.
- Add `shadcn` components: `Sidebar`, `Dialog`, `Button`, `ScrollArea`, `Avatar`, `Badge`, `Card`, `Sheet`, `Tooltip`, `Separator`, `Input`, `Label`.
- Implement `AppSidebar` with navigation to Characters and Equipments.
- Implement `Characters` page displaying character avatars.
- Implement `Equipments` page with:
- Horizontal scrollable category filter (multi-select).
- Equipment grid layout.
- "Extract Equipment" button opening a `Dialog` (refactored from `Extractor` component).
- Update `Equipment` API and Service to support filtering by multiple categories.
- Add database index to `Equipment` table on `[category, subCategory]`.
- Refactor `App.tsx` and `Layout.tsx` to use the new routing and sidebar structure.
- Remove legacy `Stash` and `Extractor` components.
- Removed Category table from schema.prisma
- Updated Equipment table to use string `category` and `subCategory`
- Created `src/lib/categories.ts` with hardcoded categories
- Updated `ExtractionService` to use hardcoded categories and "Others" fallback
- Updated `Extract` API to stream `asset_refined` events
- Updated Frontend to handle new data structure and SSE events
- Updated tests to reflect changes
- Removed unused `mock.module` calls for `file`, `category`, `asset`, and `equipment` services in `src/service/extraction.test.ts`.
- These mocks were causing global pollution and interfering with `src/service/file.test.ts`, causing it to fail.
- Verified that `extraction.test.ts` and `file.test.ts` now pass independently and together.
- Refactored `AssetService`, `CategoryService`, `CharacterService`, `EquipmentService`, `FileService`, `ExtractionService`, `GenerationService` to use instance methods.
- Exported singleton instances for each service.
- Updated all API routes to use the exported service instances.
- Updated all tests to use and mock service instances.
- Updated `AGENTS.md` to reflect the new service layer pattern.
- Verified changes with lint, format, typecheck, and test.
- Add `.env` to `.gitignore` and create `.env.example`.
- Install `@modelcontextprotocol/sdk` to fix type errors.
- Fix linting issues (unused vars, error handling) in `src/api/extract.ts` and `src/service/ai.ts`.
- Fix typecheck errors in `src/service/file.ts` (Buffer types) and `src/service/ai.ts` (GenAI types).
- Update `tsconfig.json` to use React JSX and skip lib checks.
- Fix tests in `src/service/asset.test.ts` (mocking `Bun.write`) and `src/api/equipment.test.ts`.
- Refactor `src/ui/components/Stash.tsx` and `src/ui/components/Extractor.tsx` to infer types from Hono client.
- Simplify `src/ui/types.ts` by removing redundant types.
- Migrated frontend demo to `src/ui` as a Bun-native React app.
- Implemented `ExtractionService` with 5-step AI extraction flow (Analyze, Generate, Detect, Crop, Refine).
- Implemented `FileService` for image processing and storage using `sharp`.
- Implemented `EquipmentService` and `CategoryService` for managing game assets.
- Set up Hono RPC (`hc`) for type-safe frontend-backend communication.
- Configured `Bun.serve` to handle both API routes and frontend static files/SPA routing.
- Added `zod` validation for API endpoints.
- Updated `AGENTS.md` with new architecture details.
- Added Prisma schema with Asset, Character, Equipment, Generation, Category models
- Configured SQLite with LibSQL adapter
- Implemented Service layer (src/service) with unit tests
- Implemented API layer (src/api) with Hono and integration tests
- Added static file serving for assets
- Configured CI/CD with GitHub Actions
- Added Developer Guide (AGENTS.md)
- Removed Format Check from CI