The project SHALL use Vite 7 as the build tool with dev server at port 1420 and HMR support. Documentation lives in `packages/docs/` as `@open-pencil/docs` workspace package with its own dev/build/preview scripts.
The project SHALL configure a `@/` → `src/` path alias in both `vite.config.ts` (resolve.alias) and `tsconfig.json` (paths). All cross-directory imports SHALL use `@/` instead of relative `../` paths. Same-directory `./` imports are kept as-is.
#### Scenario: Import with alias
- **WHEN** a component in `src/components/` imports from `src/engine/`
- **THEN** the import uses `@/engine/` instead of `../../engine/`
### Requirement: Shared types module
Shared primitive types (Vector, Matrix, Rect) SHALL be defined in `src/types.ts` and imported across the codebase. Window API declarations (File System Access, queryLocalFonts) SHALL be in `src/global.d.ts`. Inline type duplicates SHALL be eliminated.
#### Scenario: Shared Vector type
- **WHEN** multiple files need a 2D point type
- **THEN** they import `Vector` from `@/types` instead of defining their own
### Requirement: Zero lint and type errors
The codebase SHALL maintain 0 oxlint warnings and 0 tsgo type errors. `bun run check` SHALL pass cleanly.
#### Scenario: Clean check
- **WHEN** `bun run check` is executed
- **THEN** both lint and typecheck pass with zero issues
The project SHALL use Bun workspaces with packages: root (app), packages/core (@open-pencil/core), packages/cli (@open-pencil/cli), packages/docs (@open-pencil/docs). The workspace is configured in the root package.json. CLI is runnable via `bun open-pencil` in the workspace.
The project SHALL use jscpd for copy-paste detection. The `bun run jscpd` command SHALL scan for duplicated code blocks.
#### Scenario: Detect duplicates
- **WHEN** `bun run jscpd` is run
- **THEN** duplicated code blocks are reported with locations and percentages
### Requirement: Kiwi serialization consolidation
Shared kiwi serialization logic (sceneNodeToKiwi, buildFigKiwi, parseFigKiwiChunks, decompressFigKiwiDataAsync) SHALL be extracted to packages/core/src/kiwi-serialize.ts. The app's src/kiwi/ SHALL re-export from core, eliminating the vendored kiwi-schema copy.
#### Scenario: Clipboard and fig-export share serialization
- **WHEN** clipboard.ts and fig-export.ts serialize nodes to kiwi
- **THEN** both use the shared kiwi-serialize.ts functions
### Requirement: Test coverage script
The project SHALL include a `test:coverage` script for measuring code coverage.
- **THEN** MCP protocol adapter converts tool schema to MCP format
### Requirement: Tool schema structure
Tool schemas SHALL be defined in `packages/core/src/tools/schema.ts` with name, description, parameters (with types and descriptions), and handler function.
#### Scenario: Tool definition format
- **WHEN** defining a tool in schema.ts
- **THEN** structure includes `{ name, description, parameters: { <param>: { type, description } }, handler: (params) => result }`
#### Scenario: Type-safe parameters
- **WHEN** tool is invoked
- **THEN** parameters are validated against schema types
### Requirement: Deduplication of AI tools
The project SHALL eliminate duplication in `src/ai/tools.ts` by using `FigmaAPI.toJSON()` for node serialization and shared color parsing from `packages/core/src`.
#### Scenario: Node serialization
- **WHEN** AI tool returns node data
- **THEN** it uses `figmaAPI.toJSON(node)` instead of custom JSON builders
#### Scenario: Color parsing
- **WHEN** AI tool parses color input
- **THEN** it uses `parseColor()` from core instead of inline regex
#### Scenario: Code reduction
- **WHEN** AI tools are refactored
- **THEN** 311 lines are removed from `src/ai/tools.ts` via deduplication
### Requirement: Shared tool testing
The project SHALL provide test suites for tools in `tests/engine/tools.test.ts`, `tests/engine/tools-ai-adapter.test.ts`, and `tests/engine/tools-cli.test.ts`.
#### Scenario: Tool schema tests
- **WHEN** `tests/engine/tools.test.ts` runs
- **THEN** each tool schema is validated for structure and handler execution