diff --git a/.babelrc.js b/.babelrc.js new file mode 100644 index 0000000..0545a12 --- /dev/null +++ b/.babelrc.js @@ -0,0 +1,26 @@ +/** + * Babel Configuration Pointer File + * + * This file serves as the entry point for Babel configuration and MUST remain + * in the project root directory. Here's why: + * + * What Babel does: + * - Transpiles modern JavaScript (ES6+) to backwards-compatible code + * - Enables use of latest JS features while maintaining browser/Node compatibility + * - Currently configured for Node.js environment via @babel/preset-env + * + * Why this file is in the root: + * - Babel's file discovery mechanism looks for config files starting from the + * current directory and moving upward through parent directories + * - Tools like Jest, bundlers, and other build tools expect to find Babel + * config following this standard discovery pattern + * - Moving this file would break automatic detection by these tools + * + * Project organization: + * - This file acts as a lightweight pointer to the actual configuration + * - Real config is in ./config/babel.config.js for better organization + * - This approach keeps tooling compatibility while organizing configs centrally + * + * Used by: Jest (via babel-jest), and potentially other build tools + */ +module.exports = require('./config/babel.config.js'); diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100644 index 0000000..664a3ec --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,12 @@ +#!/usr/bin/env sh +# Block pushes unless the full test suite passes. + +set -eu + +echo "🧪 Running npm test before push..." +npm test --silent || { + echo "❌ npm test failed; push aborted." + exit 1 +} + +echo "✅ npm test passed; proceeding with push." diff --git a/.github/ISSUE_TEMPLATE/agent_task.md b/.github/ISSUE_TEMPLATE/agent_task.md new file mode 100644 index 0000000..c694317 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/agent_task.md @@ -0,0 +1,86 @@ +--- +name: Agent Task +about: Task specifically designed for autonomous AI agents +title: '[AGENT] ' +labels: ['agent-task', 'automation'] +assignees: '' +--- + +## Task Overview +**Objective:** + + +**Priority:** + +## Detailed Requirements + +### Primary Goals +- [ ] Goal 1 +- [ ] Goal 2 +- [ ] Goal 3 + +### Technical Constraints +- [ ] Must maintain 100% test coverage +- [ ] Must pass all quality gates (`npm run check:all`) +- [ ] Must follow existing code patterns +- [ ] Must not introduce breaking changes + +### Success Criteria + +- [ ] All tests pass: `npm test` +- [ ] Quality checks pass: `npm run check:all` +- [ ] Mutation testing >50%: `npm run mutation` +- [ ] Specific functionality works as described +- [ ] Documentation is updated if needed + +## Implementation Guidance + +### Suggested Approach + +1. Analyze existing code structure +2. Write tests first (TDD approach) +3. Implement incrementally +4. Validate continuously + +### Files to Consider + +``` +src/ +├── components/ +├── utils/ +├── index.js +index.html +package.json +``` + +### Testing Strategy +- **Unit tests:** Test individual functions/components +- **Property tests:** Use fast-check for complex logic +- **Integration tests:** Test component interactions +- **Manual verification:** Test in browser if UI changes + +## Quality Gates +Before opening PR, ensure: +```bash +npm test # All tests pass +npm run check:all # All quality checks pass +npm run validate:all # Complete validation +``` + +## Agent Instructions +**Branch naming:** `agent/[issue-number]-[short-description]` + +**Commit strategy:** +- Small, focused commits +- Clear commit messages +- Reference this issue number + +**Error handling:** +- If tests fail, analyze each failure individually +- Fix simplest issues first +- Make minimal changes +- Verify fixes immediately + +--- + +**Ready for agent assignment:** Comment `@claude` or `/cursor start` to assign this task to an autonomous agent. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..874755f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,69 @@ +--- +name: Bug Report +about: Report a bug or issue with the template +title: '[BUG] ' +labels: ['bug', 'needs-triage'] +assignees: '' +--- + +## Bug Description +**Current behavior:** + + +**Expected behavior:** + + +**Steps to reproduce:** +1. +2. +3. + +## Environment +- Browser: +- Node version: +- NPM version: +- Operating System: + +## Code/Error Details +**Error messages:** +``` + +``` + +**Relevant code:** +```javascript +// Paste relevant code here +``` + +**Test failures:** +``` + +``` + +## Investigation Notes +**Files involved:** + + +**Potential causes:** + + +## Fix Requirements +- [ ] Must fix the reported behavior +- [ ] Must not break existing functionality +- [ ] Must include test coverage for the fix +- [ ] Must pass all quality gates + +## Acceptance Criteria +- [ ] Bug is resolved +- [ ] Tests pass: `npm test` +- [ ] Quality checks pass: `npm run check:all` +- [ ] No regression in existing features + +--- + +**For AI Agents:** +To fix this bug, create a branch named `agent/[issue-number]-fix-[bug-description]` and: +1. Write a failing test that reproduces the bug +2. Implement the minimal fix +3. Ensure all tests pass +4. Run complete validation with `npm run validate:all` diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..ccfa236 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,64 @@ +--- +name: Feature Request +about: Suggest a new feature for the template +title: '[FEATURE] ' +labels: ['enhancement', 'needs-specification'] +assignees: '' +--- + +## Feature Description +**Brief description of the feature:** + + +**Problem it solves:** + + +## Requirements + +### Functional Requirements + +- [ ] Requirement 1 +- [ ] Requirement 2 +- [ ] Requirement 3 + +### Technical Requirements + +- [ ] Must maintain 100% test coverage +- [ ] Must follow existing code structure +- [ ] Must not break existing functionality + +### Acceptance Criteria + +- [ ] Criteria 1 +- [ ] Criteria 2 +- [ ] Criteria 3 + +## Implementation Notes +**Suggested approach:** + + +**Files likely to be affected:** + +- `src/` +- `index.html` +- `package.json` + +## Testing Strategy + +- [ ] Unit tests for core functionality +- [ ] Property-based tests for complex logic +- [ ] Integration tests if needed +- [ ] Manual testing scenarios + +## Additional Context + + +--- + +**For AI Agents:** +To implement this feature, create a branch named `agent/[issue-number]-[short-description]` and ensure all quality gates pass before opening a PR. + +Test commands: +- `npm test` - Run all tests +- `npm run check:all` - Run quality checks +- `npm run validate:all` - Complete validation diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cb21f8a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,99 @@ +name: CI +on: [push, pull_request] + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: { node-version: '20' } + - run: npm ci + - name: Core test suite + run: npm run test:core + - name: Upload coverage reports + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: coverage/ + + quality: + runs-on: ubuntu-latest + needs: test + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: { node-version: '20' } + - run: npm ci + - name: Lint check + run: npm run lint + - name: Duplication guard (jscpd) + run: npm run check:dup + - name: Cycle guard (madge) + run: npm run check:cycles + - name: Boundaries (dependency-cruiser) + run: npm run check:boundaries + - name: Mutation Test + run: npm run mutation + - name: Upload mutation report + uses: actions/upload-artifact@v4 + with: + name: mutation-report + path: mutation-testing/reports/ + + # Agent-created PR validation + agent-pr-check: + if: github.event_name == 'pull_request' && contains(github.head_ref, 'agent/') + runs-on: ubuntu-latest + needs: [test, quality] + steps: + - uses: actions/checkout@v4 + - name: Validate agent PR + uses: actions/github-script@v7 + with: + script: | + const prTitle = context.payload.pull_request?.title || ''; + const prBody = context.payload.pull_request?.body || ''; + const branch = context.payload.pull_request?.head?.ref || ''; + + let validationPassed = true; + let issues = []; + + // Validate PR has issue reference + if (!prBody.match(/#\d+/) && !prTitle.match(/#\d+/)) { + issues.push('❌ PR must reference an issue number'); + validationPassed = false; + } + + // Check if PR template was used + if (!prBody.includes('## Description') || !prBody.includes('## Testing')) { + issues.push('❌ PR template should be used'); + validationPassed = false; + } + + // Post validation results + const status = validationPassed ? '✅ Agent PR Validation Passed' : '❌ Agent PR Validation Failed'; + let comment = `## ${status}\n\n`; + + if (validationPassed) { + comment += 'This agent-created PR meets all validation criteria:\n' + + '- ✅ References an issue\n' + + '- ✅ Uses PR template\n' + + '- ✅ All CI checks pass\n\n' + + '**Ready for human review!**'; + } else { + comment += 'Issues found:\n' + issues.map(issue => `- ${issue}`).join('\n') + '\n\n' + + 'Please address these issues before merging.'; + } + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); diff --git a/.github/workflows/claude-agent.yml b/.github/workflows/claude-agent.yml new file mode 100644 index 0000000..2ab70a5 --- /dev/null +++ b/.github/workflows/claude-agent.yml @@ -0,0 +1,96 @@ +name: Claude Agent - Issue to PR +on: + issue_comment: + types: [created] + issues: + types: [opened, assigned] + +permissions: + contents: write + pull-requests: write + issues: write + +concurrency: + group: claude-agent-${{ github.event.issue.number || github.ref }} + cancel-in-progress: true + +jobs: + claude-agent: + if: | + (github.event_name == 'issue_comment' && + contains(github.event.comment.body, '@claude')) || + (github.event_name == 'issues' && + contains(github.event.issue.body, '@claude')) + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Configure git + run: | + git config user.name "claude-agent[bot]" + git config user.email "claude-agent[bot]@users.noreply.github.com" + + - name: Run Claude Code Agent + uses: anthropics/claude-code-action@v1 + with: + trigger_phrase: "@claude" + timeout_minutes: "25" + max_turns: "15" + model: "claude-3-5-sonnet-20240620" + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Post completion status + if: always() + uses: actions/github-script@v7 + with: + script: | + const status = '${{ job.status }}'; + const issueNumber = context.issue.number; + + let message; + if (status === 'success') { + message = '🤖 **Claude Agent Task Completed**\n\n' + + 'The agent has successfully processed this issue. ' + + 'Please check for a new pull request or updates to existing PRs.\n\n' + + '**Next Steps:**\n' + + '- Review the created/updated PR\n' + + '- Verify all tests pass\n' + + '- Check code quality metrics\n' + + '- Merge when ready'; + } else if (status === 'failure') { + message = '❌ **Claude Agent Task Failed**\n\n' + + 'The agent encountered an error while processing this issue. ' + + 'Please check the workflow logs for details.\n\n' + + '**Possible next steps:**\n' + + '- Review the error logs\n' + + '- Clarify requirements if needed\n' + + '- Try again with `@claude` comment'; + } else { + message = '⏰ **Claude Agent Task Cancelled**\n\n' + + 'The agent task was cancelled (likely due to timeout or cancellation).\n\n' + + 'You can retry by commenting `@claude` again.'; + } + + await github.rest.issues.createComment({ + issue_number: issueNumber, + owner: context.repo.owner, + repo: context.repo.repo, + body: message + }); diff --git a/.github/workflows/cursor-agent.yml b/.github/workflows/cursor-agent.yml new file mode 100644 index 0000000..3dbecd5 --- /dev/null +++ b/.github/workflows/cursor-agent.yml @@ -0,0 +1,136 @@ +name: Cursor Agent - Manual Trigger +on: + issue_comment: + types: [created] + +permissions: + contents: write + pull-requests: write + issues: write + +concurrency: + group: cursor-agent-${{ github.event.issue.number }} + cancel-in-progress: true + +jobs: + cursor-agent: + if: contains(github.event.comment.body, '/cursor start') + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Install Cursor CLI + run: | + curl https://cursor.com/install -fsS | bash + echo "$HOME/.cursor/bin" >> $GITHUB_PATH + + - name: Configure git + run: | + git config user.name "cursor-agent[bot]" + git config user.email "cursor-agent[bot]@users.noreply.github.com" + + - name: Extract issue details + id: issue-details + uses: actions/github-script@v7 + with: + script: | + const issue = context.payload.issue; + const issueBody = issue.body || ''; + const issueTitle = issue.title || ''; + const issueNumber = issue.number; + + core.setOutput('title', issueTitle); + core.setOutput('body', issueBody); + core.setOutput('number', issueNumber); + + return { + title: issueTitle, + body: issueBody, + number: issueNumber + }; + + - name: Run Cursor Agent + env: + CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} + run: | + # Create branch name + BRANCH_NAME="agent/${{ steps.issue-details.outputs.number }}-$(echo '${{ steps.issue-details.outputs.title }}' | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]' | sed 's/--*/-/g' | sed 's/^-\|-$//g' | cut -c1-50)" + + # Run cursor agent in non-interactive mode + cursor-agent -p " + I need to implement the requirements described in issue #${{ steps.issue-details.outputs.number }}. + + Issue Title: ${{ steps.issue-details.outputs.title }} + + Issue Description: + ${{ steps.issue-details.outputs.body }} + + Please: + 1. Create a new branch named: ${BRANCH_NAME} + 2. Analyze the existing codebase structure in CLAUDE.md + 3. Implement the requirements following the coding standards + 4. Write comprehensive tests (aim for 100% coverage) + 5. Run all quality checks (npm run check:all) + 6. Ensure tests pass (npm test) + 7. Commit changes with clear messages + 8. Push the branch + 9. Open a pull request referencing issue #${{ steps.issue-details.outputs.number }} + + Important constraints: + - Must maintain 100% test coverage + - Must pass all quality gates + - Follow existing code patterns + - Use the project structure defined in CLAUDE.md + - Make incremental commits with descriptive messages + + Test commands to run: + - npm test (unit tests) + - npm run check:all (quality checks) + - npm run validate:all (complete validation) + " --output-format json + + - name: Post completion status + if: always() + uses: actions/github-script@v7 + with: + script: | + const status = '${{ job.status }}'; + const issueNumber = context.issue.number; + + let message; + if (status === 'success') { + message = '🎯 **Cursor Agent Task Completed**\n\n' + + 'The Cursor agent has processed this issue. ' + + 'Check for a new pull request or branch updates.\n\n' + + '**Validation checklist:**\n' + + '- [ ] Tests pass (`npm test`)\n' + + '- [ ] Quality checks pass (`npm run check:all`)\n' + + '- [ ] Code follows project standards\n' + + '- [ ] PR has clear description and references this issue'; + } else { + message = '❌ **Cursor Agent Task Failed**\n\n' + + 'The Cursor agent encountered an error. Check the workflow logs.\n\n' + + '**To retry:** Comment `/cursor start` again.'; + } + + await github.rest.issues.createComment({ + issue_number: issueNumber, + owner: context.repo.owner, + repo: context.repo.repo, + body: message + }); diff --git a/.github/workflows/qa-agent.yml b/.github/workflows/qa-agent.yml new file mode 100644 index 0000000..a7b4e18 --- /dev/null +++ b/.github/workflows/qa-agent.yml @@ -0,0 +1,180 @@ +name: Quality Assurance Agent +on: + schedule: + - cron: "0 2 * * *" # Daily at 2 AM UTC + workflow_dispatch: # Manual trigger + inputs: + scope: + description: 'Scope of QA check' + required: true + default: 'full' + type: choice + options: + - full + - tests-only + - security-only + +permissions: + contents: write + pull-requests: write + issues: write + security-events: write + +jobs: + quality-assurance: + runs-on: ubuntu-latest + timeout-minutes: 45 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Configure git + run: | + git config user.name "qa-agent[bot]" + git config user.email "qa-agent[bot]@users.noreply.github.com" + + - name: Run comprehensive quality checks + id: quality-check + run: | + echo "## Quality Assurance Report" > qa-report.md + echo "Generated: $(date)" >> qa-report.md + echo "" >> qa-report.md + + # Test coverage + echo "### Test Coverage" >> qa-report.md + if npm test 2>&1 | tee test-output.log; then + echo "✅ All tests pass" >> qa-report.md + echo "TESTS_PASS=true" >> $GITHUB_OUTPUT + else + echo "❌ Test failures detected" >> qa-report.md + echo "TESTS_PASS=false" >> $GITHUB_OUTPUT + echo "\`\`\`" >> qa-report.md + tail -20 test-output.log >> qa-report.md + echo "\`\`\`" >> qa-report.md + fi + echo "" >> qa-report.md + + # Quality checks + echo "### Code Quality" >> qa-report.md + if npm run check:all 2>&1 | tee check-output.log; then + echo "✅ All quality checks pass" >> qa-report.md + echo "QUALITY_PASS=true" >> $GITHUB_OUTPUT + else + echo "❌ Quality issues detected" >> qa-report.md + echo "QUALITY_PASS=false" >> $GITHUB_OUTPUT + echo "\`\`\`" >> qa-report.md + tail -20 check-output.log >> qa-report.md + echo "\`\`\`" >> qa-report.md + fi + echo "" >> qa-report.md + + # Mutation testing (if requested) + if [ "${{ github.event.inputs.scope }}" = "full" ] || [ "${{ github.event_name }}" = "schedule" ]; then + echo "### Mutation Testing" >> qa-report.md + if npm run mutation 2>&1 | tee mutation-output.log; then + echo "✅ Mutation testing passes" >> qa-report.md + echo "MUTATION_PASS=true" >> $GITHUB_OUTPUT + else + echo "❌ Mutation testing issues" >> qa-report.md + echo "MUTATION_PASS=false" >> $GITHUB_OUTPUT + echo "\`\`\`" >> qa-report.md + tail -20 mutation-output.log >> qa-report.md + echo "\`\`\`" >> qa-report.md + fi + echo "" >> qa-report.md + fi + + # Security audit + echo "### Security Audit" >> qa-report.md + if npm audit --audit-level moderate 2>&1 | tee audit-output.log; then + echo "✅ No security vulnerabilities found" >> qa-report.md + echo "SECURITY_PASS=true" >> $GITHUB_OUTPUT + else + echo "❌ Security vulnerabilities detected" >> qa-report.md + echo "SECURITY_PASS=false" >> $GITHUB_OUTPUT + echo "\`\`\`" >> qa-report.md + cat audit-output.log >> qa-report.md + echo "\`\`\`" >> qa-report.md + fi + + - name: Create issue for failures + if: steps.quality-check.outputs.TESTS_PASS == 'false' || steps.quality-check.outputs.QUALITY_PASS == 'false' || steps.quality-check.outputs.SECURITY_PASS == 'false' || steps.quality-check.outputs.MUTATION_PASS == 'false' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const report = fs.readFileSync('qa-report.md', 'utf8'); + + const title = '🚨 Automated QA Issues Detected'; + const body = `${report} + +## Recommended Actions + +**For test failures:** +- Review failing tests and fix implementation +- Ensure 100% test coverage is maintained +- Run \`npm run test:watch\` for continuous feedback + +**For quality issues:** +- Fix linting errors: \`npm run lint\` +- Remove code duplication: \`npm run check:dup\` +- Resolve circular dependencies: \`npm run check:cycles\` +- Fix architectural boundaries: \`npm run check:boundaries\` + +**For security issues:** +- Update vulnerable dependencies: \`npm update\` +- Review \`npm audit\` output for manual fixes +- Consider using \`npm audit fix\` + +## Agent Assignment +Comment \`@claude\` to assign this task to an autonomous agent for automated resolution. + +--- +*Generated by QA Agent on ${new Date().toISOString()}*`; + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + body: body, + labels: ['qa-issue', 'automation', 'priority:high'] + }); + + - name: Post success summary + if: steps.quality-check.outputs.TESTS_PASS == 'true' && steps.quality-check.outputs.QUALITY_PASS == 'true' && steps.quality-check.outputs.SECURITY_PASS == 'true' && (steps.quality-check.outputs.MUTATION_PASS == 'true' || steps.quality-check.outputs.MUTATION_PASS == '') + uses: actions/github-script@v7 + with: + script: | + // Create a comment on the latest commit + const { data: commits } = await github.rest.repos.listCommits({ + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 1 + }); + + if (commits.length > 0) { + await github.rest.repos.createCommitComment({ + owner: context.repo.owner, + repo: context.repo.repo, + commit_sha: commits[0].sha, + body: '✅ **QA Agent Report**: All quality checks pass!\n\n' + + '- Tests: ✅ Passing\n' + + '- Code Quality: ✅ Passing\n' + + '- Security: ✅ No vulnerabilities\n' + + '- Mutation Testing: ✅ Passing\n\n' + + '*Automated quality assurance completed successfully.*' + }); + } diff --git a/.gitignore b/.gitignore index 1170717..5bdf59a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ +# Stryker Mutation testing +.stryker-tmp/ +mutation-testing/reports/mutation-report.json +mutation-testing/reports/html/ + # Logs logs *.log @@ -22,6 +27,8 @@ lib-cov # Coverage directory used by tools like istanbul coverage *.lcov +playwright-report/ +test-results/ # nyc test coverage .nyc_output diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..a0627b1 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "singleQuote": true, + "trailingComma": "es5", + "semi": true +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..fb757e5 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "ms-vscode.js-debug-nightly", + "mhutchie.git-graph", + "GitHub.copilot", + "ritwickdey.liveserver", + "esbenp.prettier-vscode" + ] +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..503fa93 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,58 @@ +# General + +- The `README.md` contains the full spec of the application. Read it end-to-end to understand the full context. It should be kept up to date whenever the code is ready for a PR +- You must follow the instructions in the `AGENTS.md` file while working on your task and regularly review if you are still aligned with these instructions and the spec. +- Do not stop until every acceptance criterion is implemented, verified locally and prepared for review. +- **Co-locate docs**: every code file must have a matching `*.md` sidecar next to it, that explains the component in detail. The goal of the sidecar is to make purpose, API, invariants, examples and test strategy of the component obvious to agents and humans. +- This is a minimal local first web app (static HTML + modular JS). Prefer tailwind over custom CSS. +- Entrypoint: `index.html` (+ static pages in `pages/` if any needed) +- The code is composed of small, focused modules in `src/` (`components/`, `utils/`, ..) with colocated tests +- Do exactly one prioritized task per iteration and work in a TDD approach where possible. +- Before and after any change, run `npm test` +- Run `npm outdated` weekly at minimum; keep dependencies healthy. Prefer bumping to the `Wanted` version unless blocked by incompatibilities (document any exceptions). Also run `npm audit` to catch security issues even when versions are current. +- Only change code directly related to the current task; keep diffs small! +- Preserve existing comments & docs; add concise, long-lived comments where useful and avoid narrating changes via comments +- When external documentation could be consulted, do so to validate your plan makes sense. If you lack a browsing/online search tool, ask the user to run an online search for you (e.g., "Please search for \"x\" and paste back the findings") +- Before adding functionality, search the codebase (e.g., ripgrep) to confirm it's truly absent. If present, prefer refactor over re-implementation. +- After each iteration add a concise update at the end of docs/implementation-progress.md to use it as the memory between iterations for learnings, decisions, planning etc. + +## Dependencies & no-build approach to use + +This project follows a no-build, static workflow: + +- Use native ES modules and ` @@ -89,7 +89,8 @@ flex-direction: column; } - #editor-wrapper > div:not(#drag-handle) { /* Target panes, not handle */ + #editor-wrapper > div:not(#drag-handle) { + /* Target panes, not handle */ width: 100% !important; height: auto !important; /* Let flex-basis control height */ flex-basis: 50%; /* Reset basis for vertical */ @@ -99,7 +100,7 @@ overflow: hidden; /* Hide overflow from the pane itself */ } html.dark #editor-wrapper > div:not(#drag-handle) { - border-bottom-color: #4b5563; /* Dark mode border */ + border-bottom-color: #4b5563; /* Dark mode border */ } #drag-handle { @@ -120,7 +121,7 @@