|
1 | 1 | # Development Rules |
2 | 2 |
|
| 3 | +## Build & Test |
| 4 | +- `npm run build` - Build (wireit + tsup, ESM) |
| 5 | +- `npm run test` - Unit/integration tests (Vitest) |
| 6 | +- `npm run test:smoke` - Smoke tests (builds first, serial execution) |
| 7 | +- `npm run lint` / `npm run lint:fix` - ESLint |
| 8 | +- `npm run format` / `npm run format:check` - Prettier |
| 9 | +- `npm run typecheck` - TypeScript type checking (src + test config) |
| 10 | +- `npm run docs:check` - Validate docs match CLI surface |
| 11 | + |
| 12 | +## Architecture |
| 13 | +ESM TypeScript project (`type: module`). Key layers: |
| 14 | + |
| 15 | +- `src/cli/` - CLI entrypoint, yargs wiring, daemon routing |
| 16 | +- `src/server/` - MCP stdio server, lifecycle, workflow/resource registration |
| 17 | +- `src/runtime/` - Config bootstrap, session state, tool catalog assembly |
| 18 | +- `src/core/manifest/` - YAML manifest loading, validation, tool module imports |
| 19 | +- `src/mcp/tools/` - Tool implementations grouped by workflow (mirrors `manifests/workflows/`) |
| 20 | +- `src/mcp/resources/` - MCP resource implementations |
| 21 | +- `src/integrations/` - External integrations (Xcode tools bridge) |
| 22 | +- `src/utils/` - Shared helpers (execution, logging, validation, responses) |
| 23 | +- `src/visibility/` - Tool/workflow exposure predicates |
| 24 | +- `src/daemon/` - Background daemon for persistent sessions |
| 25 | +- `src/rendering/` - Output rendering and formatting |
| 26 | +- `src/types/` - Shared type definitions |
| 27 | + |
| 28 | +## Contributing Workflow |
| 29 | +1. Create a branch from `main` |
| 30 | +2. Make changes following the conventions in this file |
| 31 | +3. Run the pre-commit checklist before committing: |
| 32 | + ```bash |
| 33 | + npm run lint:fix |
| 34 | + npm run typecheck |
| 35 | + npm run format |
| 36 | + npm run build |
| 37 | + npm run docs:check |
| 38 | + npm test |
| 39 | + ``` |
| 40 | +4. Update `CHANGELOG.md` under `## [Unreleased]` |
| 41 | +5. Update documentation if adding or modifying features |
| 42 | +6. Clone and test against example projects (e.g., `XcodeBuildMCP-iOS-Template`) when changes affect runtime behavior |
| 43 | +7. Push and create a pull request with a clear description |
| 44 | +8. Link any related issues |
| 45 | + |
3 | 46 | ## Code Quality |
4 | 47 | - No `any` types unless absolutely necessary |
5 | 48 | - Check node_modules for external API type definitions instead of guessing |
|
8 | 51 | - Always ask before removing functionality or code that appears to be intentional |
9 | 52 | - Follow TypeScript best practices |
10 | 53 |
|
| 54 | +## Import Conventions |
| 55 | +- ESM with explicit `.ts` extensions in `src/` (tsup rewrites to `.js` at build) |
| 56 | +- No `.js` imports in `src/` (enforced by ESLint) |
| 57 | +- No barrel imports from `utils/index` - import from specific submodules (e.g., `src/utils/execution/index.ts`, `src/utils/logging/index.ts`) |
| 58 | + |
| 59 | +## Test Conventions |
| 60 | +- Vitest with colocated `__tests__/` directories using `*.test.ts` |
| 61 | +- Smoke tests in `src/smoke-tests/__tests__/` (separate Vitest config, serial execution) |
| 62 | +- Use `vi.mock`/`vi.hoisted` for isolation; inject executors and mock file systems |
| 63 | +- MCP integration tests use `McpServer`, `InMemoryTransport`, and `Client` |
| 64 | +- External dependencies (command execution, file system) must use dependency injection via `createMockExecutor()` / `createMockFileSystemExecutor()` from `src/test-utils/` |
| 65 | + |
| 66 | +## Tool Development |
| 67 | +- Tool manifests in `manifests/tools/*.yaml` define `id`, `module`, `names.mcp` (snake_case), optional `names.cli` (kebab-case), predicates, and annotations |
| 68 | +- Workflow manifests in `manifests/workflows/*.yaml` group tools and define exposure rules |
| 69 | +- Tool modules export a Zod `schema`, a pure `*Logic` function, and a `handler` built with `createTypedTool` or `createSessionAwareTool` |
| 70 | +- Resource modules export a `handler` (and a pure `*Logic` function); `uri`, `name`, `description`, and `mimeType` are declared in `manifests/resources/*.yaml` |
| 71 | + |
11 | 72 | ## Commands |
12 | 73 | - NEVER commit unless user asks |
13 | 74 |
|
@@ -48,8 +109,8 @@ Use these sections under `## [Unreleased]`: |
48 | 109 | - NEVER update snapshot fixtures unless asked to do so, these are integration tests, on failure assume code is wrong before questioning the fixture |
49 | 110 | - |
50 | 111 | #### Attribution |
51 | | -- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/cameroncook/XcodeBuildMCP/issues/123))` |
52 | | -- **External contributions**: `Added feature X ([#456](https://github.com/cameroncook/XcodeBuildMCP/pull/456) by [@username](https://github.com/username))` |
| 112 | +- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/getsentry/XcodeBuildMCP/issues/123))` |
| 113 | +- **External contributions**: `Added feature X ([#456](https://github.com/getsentry/XcodeBuildMCP/pull/456) by [@username](https://github.com/username))` |
53 | 114 |
|
54 | 115 | ## Test Execution Rules |
55 | 116 | - When running long test suites (snapshot tests, smoke tests), ALWAYS write full output to a log file and read it afterwards. NEVER pipe through `tail` or `grep` directly — that loses output you may need to debug failures. |
|
0 commit comments