diff --git a/AGENTS.md b/AGENTS.md index 3f35aed..722a2be 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,36 +1,54 @@ # AGENTS.md -## Project Overview +Rules and principles for agents working on **this** project. -`tiny-lru` is a high-performance, lightweight LRU (Least Recently Used) cache library for JavaScript with O(1) operations and optional TTL support. +--- -## Setup Commands +## 1. Core Rules -```bash -npm install # Install dependencies -npm run build # Lint and build (runs lint then rollup) -npm run rollup # Build with rollup -npm run test # Run lint and tests -npm run coverage # Run tests with coverage reporting -npm run fix # Fix linting and formatting issues -npm run lint # Lint code with oxlint -``` +### 1.0 Document Conventions -## Development Workflow +When updating this document, append new information or sections. Do NOT delete or overwrite existing content unless explicitly directed. Always ask before making structural changes. When in doubt, keep it. -Source code is in `src/`. +### 1.1 Forbidden Patterns + +The following are **strictly prohibited**: + +- Hardcoded secrets, API keys, or credentials. +- `eval()`, `exec()` at any level. +- Star imports (`import * as foo from 'bar'`). +- Mutating a list while iterating over it. +- `new Array()` — use `Array()` or `Array.from()` instead (oxlint will warn). + +### 1.2 Security Rules + +Follow the [OWASP Top 10](https://owasp.org/www-project-top-10/) for every piece of code written: -- **lint**: Check and fix linting issues with oxlint -- **fix**: Fix linting and formatting issues -- **build**: Lint + rollup build -- **coverage**: Run test suite with coverage reporting +- Avoid unsafe operations, validate inputs, prevent injection risks. -## Project Structure +### 1.3 Git Operations + +- **Never rebase under any circumstance without explicit agreement from the user.** Never assume your decision is correct. +- Never force push. + +### 1.4 Core Principles + +- **DRY (Don't Repeat Yourself)**: Extract common logic into reusable functions; avoid duplication. +- **YAGNI (You Ain't Gonna Need It)**: Implement only what's needed; avoid over-engineering. +- **SOLID**: Follow single responsibility, open/closed, and interface segregation principles. + +--- + +## 2. Project Context + +### 2.0 Expected Project Layout + +`tiny-lru` is a high-performance, lightweight LRU (Least Recently Used) cache library for JavaScript with O(1) operations and optional TTL support. ``` ├── src/lru.js # Main LRU cache implementation ├── tests/ # Test files -├── benchmarks/ # Performance benchmarks +├── benchmarks/ # Performance benchmarks ├── dist/ # Built distribution files │ ├── tiny-lru.js # ES Modules │ ├── tiny-lru.cjs # CommonJS @@ -38,24 +56,58 @@ Source code is in `src/`. ├── types/ # TypeScript definitions ├── docs/ # Documentation ├── rollup.config.js # Build configuration -└── package.json # Project configuration +└── package.json # Project configuration ``` -## Code Style +### 2.1 Quick Commands + +| Command | Purpose | +|-------------------|---------------------------------------------------| +| `npm install` | Install dependencies | +| `npm run build` | Lint and build (runs lint then rollup) | +| `npm run rollup` | Build with rollup | +| `npm run test` | Run lint and tests | +| `npm run coverage`| Run tests with coverage reporting | +| `npm run fix` | Fix linting and formatting issues | +| `npm run lint` | Lint code with oxlint | + +--- + +## 3. Code Conventions + +### 3.1 Language & Tooling + +- **JavaScript/TypeScript**: CommonJS, ESM, and minified ESM outputs via Rollup +- **Package manager**: `npm` +- **Linting**: `oxlint` +- **Formatting**: (via `npm run fix`) +- **Testing**: Node.js built-in test runner (`node --test`) + +### 3.2 Style - Indentation: Tabs - Quotes: Double quotes - Semicolons: Required - Array constructor: Avoid `new Array()` (oxlint will warn) -## Development Principles +### 3.3 Error Handling + +Not applicable — internal LRU operations should not surface errors; handle gracefully. + +### 3.4 Testing + +- Framework: Node.js built-in test runner (`node --test`) +- Tests: 149 tests across 26 suites +- Coverage: 100% lines, 99.28% branches, 100% functions +- Test pattern: `tests/**/*.js` +- All tests must pass with 100% line coverage before merging +- Run: `npm test` (lint + tests) or `npm run coverage` for coverage report + +--- -- **DRY (Don't Repeat Yourself)**: Extract common logic into reusable functions; avoid duplication -- **YAGNI (You Ain't Gonna Need It)**: Implement only what's needed; avoid over-engineering -- **SOLID**: Follow single responsibility, open/closed, and interface segregation principles -- **OWASP**: Prioritize security; avoid unsafe operations, validate inputs, prevent injection risks +## 4. API Conventions -## API Reference +### 4.1 API Reference - `lru(max, ttl, resetTtl)` - Factory function to create cache - `LRU` class - Direct instantiation with `new LRU(max, ttl, resetTtl)` @@ -65,26 +117,83 @@ Source code is in `src/`. - Properties: `first`, `last`, `max`, `size`, `ttl`, `resetTtl` - `peek(key)` - Retrieve value without moving it (no LRU update, no TTL check) -## Testing +--- -- Framework: Node.js built-in test runner (`node --test`) -- Tests: 149 tests across 26 suites -- Coverage: 100% lines, 99.28% branches, 100% functions -- Test pattern: `tests/**/*.js` -- All tests must pass with 100% line coverage before merging -- Run: `npm test` (lint + tests) or `npm run coverage` for coverage report +## 5. Git Conventions + +### 5.1 Commit Messages + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat: add TTL support to LRU cache +fix: correct LRU eviction order for edge case +docs: update AGENTS.md with new conventions +test: add coverage for keysByTTL method +chore: update rollup configuration +``` + +### 5.2 Branching + +- Main branch is `main`. +- Feature branches: `feat/` or `fix/`. +- Never commit directly to `main`. Always create a feature branch first, then open a PR targeting `main`. + +### 5.3 Code Review + +- All changes require tests to pass and maintain coverage requirements. +- 100% line coverage is required before merging. + +--- -## Common Issues to Avoid +## 6. Operational Rules -- **Memory leaks**: When removing items from the linked list, always clear `prev`/`next` pointers to allow garbage collection -- **LRU order pollution**: Methods like `entries()` and `values()` should access items directly rather than calling `get()`, which moves items and can delete expired items mid-iteration -- **TTL edge cases**: Direct property access (`this.items[key]`) should be used instead of `has()` when you need to inspect expired-but-not-yet-deleted items -- **Dead code**: Always verify edge case code is actually reachable before adding special handling -- **Constructor assignment**: Use `let` not `const` for variables that may be reassigned (e.g., in `setWithEvicted`) +### 6.1 Coverage -## Implementation Notes +Tests must maintain **100% line coverage**. Every new function or class needs test coverage. No exceptions. + +```bash +npm run coverage +``` + +### 6.2 Common Issues to Avoid + +- **Memory leaks**: When removing items from the linked list, always clear `prev`/`next` pointers to allow garbage collection. +- **LRU order pollution**: Methods like `entries()` and `values()` should access items directly rather than calling `get()`, which moves items and can delete expired items mid-iteration. +- **TTL edge cases**: Direct property access (`this.items[key]`) should be used instead of `has()` when you need to inspect expired-but-not-yet-deleted items. +- **Dead code**: Always verify edge case code is actually reachable before adding special handling. +- **Constructor assignment**: Use `let` not `const` for variables that may be reassigned (e.g., in `setWithEvicted`). + +### 6.3 Development Workflow + +Source code is in `src/`. + +- **install**: `npm install` — Install dependencies +- **lint**: `npm run lint` — Check and fix linting issues with oxlint +- **fix**: `npm run fix` — Fix linting and formatting issues +- **build**: `npm run build` — Lint + rollup build +- **rollup**: `npm run rollup` — Build with rollup +- **test**: `npm run test` — Run lint and tests +- **coverage**: `npm run coverage` — Run test suite with coverage reporting + +--- + +## 7. Session Learnings + +### 7.1 Implementation Notes - The LRU uses a doubly-linked list with `first` and `last` pointers for O(1) operations - TTL is stored per-item as an `expiry` timestamp; `0` means no expiration - `moveToEnd()` is the core method for maintaining LRU order - item is always moved to the `last` position - `setWithEvicted()` optimizes updates by avoiding the full `set()` path for existing keys + +--- + +## 8. Checklist Before Marking a TODO Complete + +- [ ] All code follows style conventions (tabs, double quotes, semicolons). +- [ ] No forbidden patterns used (`new Array()`, etc.). +- [ ] Unit tests written and passing. +- [ ] 100% line coverage maintained (`npm run coverage`). +- [ ] `npm run lint` passes with no errors. +- [ ] No hardcoded secrets or credentials introduced. diff --git a/docs/CODE_STYLE_GUIDE.md b/docs/CODE_STYLE_GUIDE.md index 85530c4..b0a203c 100644 --- a/docs/CODE_STYLE_GUIDE.md +++ b/docs/CODE_STYLE_GUIDE.md @@ -2,10 +2,22 @@ Coding conventions for tiny-lru source code. +--- + ## Editor Configuration Set your editor to use **tabs** for indentation. +## Forbidden Patterns + +The following are **strictly prohibited**: + +- Hardcoded secrets, API keys, or credentials. +- `eval()`, `exec()`, `__import__()` at any level. +- `*` imports (`from x import *`). +- Mutating a list while iterating over it. +- `new Array()` — use `Array()` or `Array.from()` instead (oxlint will warn). + ## JavaScript Style ### Formatting @@ -53,6 +65,9 @@ this.items = Object.create(null); // Use Array.from() for pre-allocated arrays const result = Array.from({ length: this.size }); + +// Never use new Array() - use Array() or Array.from() instead +const items = Array(10); // NOT new Array(10) ``` ## JSDoc Comments @@ -101,9 +116,6 @@ setWithEvicted() { } // Variables: camelCase const maxSize = 1000; let currentItem = null; - -// Constants: camelCase (not UPPER_SNAKE) -const defaultMax = 1000; ``` ## Method Patterns @@ -177,20 +189,32 @@ export class LRU { ## Error Handling -Use TypeError with clear messages: +Not applicable — internal LRU operations should not surface errors; handle gracefully. -```javascript -if (isNaN(max) || max < 0) { - throw new TypeError("Invalid max value"); -} +## Testing and Coverage + +- Framework: Node.js built-in test runner (`node --test`) +- Tests: 149 tests across 26 suites +- Coverage: 100% lines, 99.28% branches, 100% functions +- Test pattern: `tests/**/*.js` +- All tests must pass with 100% line coverage before merging +- Run: `npm test` (lint + tests) or `npm run coverage` for coverage report + +### Coverage + +Tests must maintain **100% line coverage**. Every new function or class needs test coverage. No exceptions. + +```bash +npm run coverage ``` -## Testing and Coverage +## Common Issues to Avoid -- All tests must pass before merging -- 100% line coverage required -- Run tests with `npm test` (includes linting) -- Generate coverage report with `npm run coverage` +- **Memory leaks**: When removing items from the linked list, always clear `prev`/`next` pointers to allow garbage collection. +- **LRU order pollution**: Methods like `entries()` and `values()` should access items directly rather than calling `get()`, which moves items and can delete expired items mid-iteration. +- **TTL edge cases**: Direct property access (`this.items[key]`) should be used instead of `has()` when you need to inspect expired-but-not-yet-deleted items. +- **Dead code**: Always verify edge case code is actually reachable before adding special handling. +- **Constructor assignment**: Use `let` not `const` for variables that may be reassigned (e.g., in `setWithEvicted`). ## Lint Configuration