From f4649e0dacbaa39937184c6bc5852092be645d07 Mon Sep 17 00:00:00 2001 From: hypercross Date: Thu, 2 Apr 2026 15:36:38 +0800 Subject: [PATCH] chore: AGENTS.md --- AGENTS.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..91dd5a0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,70 @@ +# AGENTS.md - boardgame-core + +## Commands + +Prefer `bash.exe`(C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps\bash.exe) over Powershell. + +```bash +npm run build # Build ESM bundle + declarations to dist/ +npm run test # Run vitest in watch mode +npm run test:run # Run vitest once (no watch) +npm run typecheck # Type-check without emitting (tsc --noEmit) +``` + +### Running a single test file +```bash +npx vitest run tests/samples/tic-tac-toe.test.ts +``` + +### Running a single test by name +```bash +npx vitest run -t "should detect horizontal win for X" +``` + +## Code Style + +### Imports +- Use **double quotes** for local imports, **single quotes** for npm packages +- No path aliases — use relative `../` and `./` paths + +### Formatting +- **4-space indentation** +- **Semicolons** at statement ends +- **Arrow functions** for callbacks; `function` keyword for methods needing `this` (e.g. command handlers) +- No trailing whitespace + +### Naming Conventions +- **Types/Interfaces**: `PascalCase` — `Part`, `Region`, `Command`, `IGameContext` +- **Classes**: `PascalCase` — `Entity`, `AsyncQueue`, `Mulberry32RNG` +- **Functions**: `camelCase`, verb-first — `createGameContext`, `parseCommand`, `isValidMove` +- **Variables**: `camelCase` +- **Constants**: `UPPER_SNAKE_CASE` — `BOARD_SIZE`, `WINNING_LINES` +- **Test files**: `*.test.ts` mirroring `src/` structure under `tests/` + +### Types +- **Strict TypeScript** is enabled — no `any` +- Use **generics** heavily: `Entity`, `CommandRunner` +- Use **type aliases** for object shapes (not interfaces) +- Use **discriminated unions** for results: `{ success: true; result: T } | { success: false; error: string }` +- Use `unknown` for untyped values, narrow with type guards or `as` + +### Error Handling +- Prefer **result objects** over throwing: return `{ success, result/error }` +- When catching: `const error = e as Error;` then use `error.message` +- Use `throw new Error(...)` only for truly exceptional cases +- Validation error messages are in Chinese (e.g. `"参数不足"`) + +### Testing +- **Vitest** with globals enabled (`describe`, `it`, `expect` available without import) +- Use `async/await` for async tests +- Narrow result types with `if (result.success)` before accessing `result.result` +- Define inline helper functions in test files when needed +- No mocking — use real implementations +- Test helpers: `createTestContext()`, `createTestRegion()` + +## Architecture Notes + +- **Reactivity**: `Entity` extends Preact Signal — access state via `.value`, mutate via `.produce(draft => ...)` +- **Command system**: CLI-style parsing with schema validation via `inline-schema` +- **Prompt system**: Commands prompt for input via `PromptEvent` with `resolve`/`reject` +- **Barrel exports**: `src/index.ts` is the single public API surface