This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a high-performance JavaScript/TypeScript implementation of Knuth's Dancing Links algorithm (DLX) for solving exact cover problems. The library provides the fastest JS implementation of the algorithm and includes examples for n-queens, pentomino tiling, and sudoku problems.
npm run build- Build TypeScript to JavaScript (cleans first)npm run test- Run unit tests (alias for test-unit)npm run test-watch- Run tests in watch modenpm run test-unit- Run unit tests with Mocha and ts-nodenpm run lint- Run ESLint checksnpm run lint:fix- Run ESLint with auto-fixnpm run format- Format code with Prettiernpm run format:check- Check code formattingnpm run coverage- Generate test coverage report with nycnpm run benchmark- Run internal solver benchmarks for regression testingnpm run benchmark:competitive- Run competitive benchmarks comparing our best solver vs external librariesnpm run benchmark:comprehensive- Run comprehensive analysis across all solver-case combinationsnpm run profile- Generate CPU profile for performance analysis
index.ts- Public API exports (DancingLinks factory, ProblemSolver, SolverTemplate)lib/index.ts- Main library re-exports from organized moduleslib/core/algorithm.ts- Core Dancing Links algorithm implementation using state machinelib/types/interfaces.ts- TypeScript type definitions and constraint interfaceslib/solvers/factory.ts- DancingLinks factory class for creating solvers and templateslib/constraints/handlers/- Constraint handlers for simple and complex modes
The core algorithm (lib/core/algorithm.ts) uses a state machine pattern to avoid recursion and implement Knuth's Dancing Links algorithm. The states are:
- FORWARD: Select next column to cover
- ADVANCE: Try next option for selected column
- BACKUP: Backtrack when no options remain
- RECOVER: Restore previous state when backtracking
- DONE: Solution found or search complete
NodeStore<T>class: Struct-of-Arrays implementation with typed arrays for navigation fieldsColumnStoreclass: Column headers with length tracking and circular linking- Constraint types:
SimpleConstraint(single row) andComplexConstraint(primary + secondary rows)
- State machine logic in
search()function inlib/core/algorithm.ts - Matrix operations:
cover()anduncover()for constraint satisfaction - Data structures in
lib/core/data-structures.tswith NodeStore and ColumnStore classes - Constraint handlers in
lib/constraints/handlers/for simple and complex solver modes
Performance is critical - always run benchmarks before and after changes using npm run benchmark. The library maintains its position as the fastest Dancing Links implementation in JavaScript through systematic optimization.
See PERFORMANCE.md for detailed analysis of optimization work completed.
All new features require comprehensive unit tests. Use npm run test for standard testing, npm run test-watch for development. Coverage reports available via npm run coverage.
Must follow Conventional Commits specification:
feat:- New features (minor version bump)fix:- Bug fixes (patch version bump)perf:- Performance improvementstest:- Test additions/changesdocs:- Documentation changesci:- CI/build changes (no release)build:- Build system changes (no release)
lib/- Core library implementation with organized nested modulescore/- Core algorithm and data structuresconstraints/handlers/- Constraint handlers for different solver modessolvers/- Factory, solver, and template classestypes/- TypeScript interfaces and type definitions
benchmark/- Performance testing and example problems (n-queens, pentomino, sudoku)test/unit/- Unit test suitebuilt/- Compiled JavaScript output- TypeScript configuration supports both development (
tsconfig.dev.json) and production builds
Make sure to leave relevant and detailed comments on complex parts of the codebase.
DO write detailed comments for:
- Complex algorithms with multiple steps
- Non-obvious business logic or domain-specific rules
- Areas where refactoring considerations are documented
- Code that cannot be easily simplified due to technical constraints
DON'T write comments for:
- Self-evident code (obvious function names, simple operations)
- Historical changes or what code "used to do"
- Anything that can be understood from reading the code itself
When you write complex code, you MUST write documentation explaining the why, not the what.
DO use for performance-critical code:
for...ofloops over.forEach()- Manual loops over
.map()and.reduce()for data transformation - Low-level iteration patterns in hot paths
DON'T use for performance-critical code:
- Array utility methods (
.map,.reduce,.forEach) - provably slower than loops - Functional programming patterns that create intermediate arrays
- Method chaining that allocates temporary objects
DO in tests:
- Test functionality and behavior
- Focus on input/output verification
- Test edge cases and error conditions
DON'T in tests:
- Test method existence with
.to.have.property- TypeScript ensures this - Test implementation details
- Duplicate type checking that TypeScript already provides
ALWAYS plan together first for complex problems before implementing.
When to PLAN TOGETHER (not implement immediately):
- Questions like "Can we think of a better way..."
- "Maybe we can build something better..."
- "Is it a good interface to..."
- Architecture or design discussions
- Performance optimization strategies
- API design questions
- Complex problem exploration
When to IMPLEMENT DIRECTLY:
- "Can you fix the type issue"
- "Add this specific feature"
- "Run the tests"
- Clear, specific implementation requests
- Bug fixes with known solutions
Always use judgment: If unsure whether to plan or implement, err on the side of planning and discussion first. Implementation can always come after we've explored the problem space together.
BREAK APIs PROPERLY - No Legacy Compatibility Unless Explicitly Requested
When refactoring or renaming:
- DO make clean breaks and update everything consistently
- DO rename options, functions, and variables everywhere they're used
- DO update all documentation, scripts, and references in one go
- DON'T keep legacy compatibility layers or deprecated options
- DON'T maintain backward compatibility unless explicitly asked
The codebase should be internally consistent. If you rename something, rename it everywhere. If you break an API, break it completely and update all consumers. Half-measures create technical debt and confusion.
- ALWAYS run
npm run formatbefore committing - Code must be properly formatted - Commit frequently, ensure tests pass before committing, always ensure that ALL TS types pass
- Always do work in branches and create one if we're not in a branch already. Commit frequently.
Before every commit, ALWAYS run:
npm run format- Format code with Prettiernpm run lint- Check for linting issuesnpm run test- Ensure all tests passnpm run build- Verify TypeScript compilation