All commit messages must be written in English.
Follow Conventional Commits specification:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
feat: A new featurefix: A bug fixdocs: Documentation only changesstyle: Changes that do not affect the meaning of the code (white-space, formatting, etc)refactor: A code change that neither fixes a bug nor adds a featureperf: A code change that improves performancetest: Adding missing tests or correcting existing testschore: Changes to the build process or auxiliary tools
feat: add task priority sorting to kanban board
fix: resolve CI build failure by switching from Taobao registry to npm official registry
docs: update README with installation instructions
refactor(storage): simplify task update logic
# Development
npm run dev # Start development mode with watch
# Building
npm run build # Full build (Node + Web)
npm run build:web # Build only web frontend
# Type checking
npm run typecheck # Run TypeScript type checking without emitting
# Testing
npm run test # Run tests in watch mode
npm run test:unit # Run unit tests once
npm run test:integration # Run integration tests once
# Run a single test file
npx vitest run tests/unit/storage.test.ts
# Run tests matching a pattern
npx vitest run --reporter=verbose --testNamePattern="createProject"- Target: ES2022 with NodeNext module resolution
- Strict mode: Enabled - all strict TypeScript options must pass
- Unused code: Not allowed (noUnusedLocals, noUnusedParameters)
- Implicit returns: Not allowed (noImplicitReturns)
- Use ES modules (
"type": "module"in package.json) - Include
.jsextension in imports:import { foo } from './bar.js' - Prefer named imports over default imports
- Group imports: built-ins → external → internal (separated by blank line)
Example:
import { readFile } from 'fs/promises';
import { join } from 'path';
import { z } from 'zod';
import { Project } from '../models/index.js';
import { readJsonFile } from '../utils/file-helpers.js';- Files: kebab-case (e.g.,
file-helpers.ts,project-tools.ts) - Classes: PascalCase (e.g.,
ProjectStorage,TaskManager) - Interfaces/Types: PascalCase (e.g.,
ProjectData,TaskStatus) - Functions/Variables: camelCase (e.g.,
createProject,getFilePath) - Constants: UPPER_SNAKE_CASE for true constants only
- Private class members: Use
privatemodifier (not#prefix)
- Always define explicit return types for public functions
- Use
interfacefor object shapes that may be extended - Use
typefor unions, intersections, and complex types - Prefer
nulloverundefinedfor optional values - All dates are stored as ISO 8601 strings
Example:
export interface Project {
id: string;
name: string;
dueDate: string | null; // ISO 8601 date string or null
}
export type ProjectStatus = 'active' | 'completed' | 'archived';- Use explicit error checking instead of try-catch when possible
- Always check for
ENOENTerrors when reading files - Log errors to
console.errorwith descriptive messages - Exit process with code 1 on fatal errors
Example:
async readProject(projectId: string): Promise<ProjectData | null> {
try {
const filePath = this.getFilePath(projectId);
return await readJsonFile<ProjectData>(filePath);
} catch (error) {
if (error instanceof Error && error.message.includes('ENOENT')) {
return null;
}
throw error;
}
}- Use JSDoc for public methods and functions
- Keep comments concise and up-to-date
- Explain "why" not "what" (code should be self-documenting)
Example:
/**
* Create a new project with generated ID and timestamps
* @param input - Project creation data (without ID/timestamps)
* @returns The complete project data including generated fields
*/
async createProject(input: CreateProjectInput): Promise<ProjectData> {
// Implementation...
}- Use Vitest with globals enabled
- Test file pattern:
tests/**/*.{test,spec}.{js,ts} - Use
describe/itblocks for organizing tests - Use
beforeEach/afterEachfor setup/teardown - Tests should be independent and not rely on execution order
Example:
describe('ProjectStorage', () => {
let storage: ProjectStorage;
beforeEach(() => {
storage = new ProjectStorage();
});
describe('createProject', () => {
it('should create a project with valid input', async () => {
// Test code...
});
});
});- Always use npm official registry (
https://registry.npmjs.org/) - Do not use Taobao mirror or other third-party registries
- The
.npmrcfile enforces this - do not override it - Node.js version requirement:
>=20.0.0
Before committing, ensure:
npm run typecheckpassesnpm run test:unitpasses- Code follows existing patterns in the codebase
- Commit message follows Conventional Commits format (in English)
This project uses GitHub Actions for automated npm publishing.
Follow Semantic Versioning:
MAJOR.MINOR.PATCH- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes
Before releasing a new version, ensure:
-
Update CHANGELOG
- View changes since last tag:
git log v0.2.8..HEAD --oneline - Add new version section at the TOP of CHANGELOG.md
- Categorize changes: Added / Changed / Fixed / Removed
- Format:
## [0.2.9] - 2026-02-26
- View changes since last tag:
-
Run tests
npm run typecheck npm run test:unit
-
Build verification
npm run build
-
Commit CHANGELOG update
git add CHANGELOG.md git commit -m "docs: update changelog for v0.2.9"
-
Bump version (creates git tag automatically):
npm version patch # or minor / major -
Push commits and tag:
git push git push origin v0.2.9
-
CI automatically publishes to npm registry
- On tag push (
v*), GitHub Actions automatically:- Runs tests on Node.js 20.x and 22.x
- Builds the project
- Publishes to npm with provenance
DO NOT run npm publish locally - let CI handle it via NPM_TOKEN secret.
# Development
npm run dev:web # Frontend dev server (port 7861, with HMR)
npm run dev:server # Backend server (port 7863)
npm run dev:full # Start both frontend and backend
# Debug
npm run inspector # Launch MCP Inspector for debugging
# Build & Test
npm run build # Full build
npm run typecheck # TypeScript check
npm run test:unit # Unit tests