diff options
| -rw-r--r-- | Makefile | 44 | ||||
| -rw-r--r-- | add-tests/SKILL.md | 57 | ||||
| -rw-r--r-- | claude-rules/testing.md | 140 | ||||
| -rw-r--r-- | claude-rules/verification.md | 42 | ||||
| -rw-r--r-- | debug/SKILL.md | 55 | ||||
| -rw-r--r-- | fix-issue/SKILL.md | 54 | ||||
| -rw-r--r-- | respond-to-review/SKILL.md | 50 | ||||
| -rw-r--r-- | review-pr/SKILL.md | 57 | ||||
| -rw-r--r-- | security-check/SKILL.md | 48 |
9 files changed, 545 insertions, 2 deletions
@@ -1,10 +1,13 @@ SKILLS_DIR := $(HOME)/.claude/skills -SKILLS := c4-analyze c4-diagram +RULES_DIR := $(HOME)/.claude/rules +SKILLS := c4-analyze c4-diagram debug add-tests respond-to-review review-pr fix-issue security-check +RULES := $(wildcard claude-rules/*.md) .PHONY: install uninstall list install: - @mkdir -p $(SKILLS_DIR) + @mkdir -p $(SKILLS_DIR) $(RULES_DIR) + @echo "Skills:" @for skill in $(SKILLS); do \ if [ -L "$(SKILLS_DIR)/$$skill" ]; then \ echo " skip $$skill (already linked)"; \ @@ -15,9 +18,24 @@ install: echo " link $$skill → $(SKILLS_DIR)/$$skill"; \ fi \ done + @echo "" + @echo "Rules:" + @for rule in $(RULES); do \ + name=$$(basename $$rule); \ + if [ -L "$(RULES_DIR)/$$name" ]; then \ + echo " skip $$name (already linked)"; \ + elif [ -e "$(RULES_DIR)/$$name" ]; then \ + echo " WARN $$name exists and is not a symlink — skipping"; \ + else \ + ln -s "$(CURDIR)/$$rule" "$(RULES_DIR)/$$name"; \ + echo " link $$name → $(RULES_DIR)/$$name"; \ + fi \ + done + @echo "" @echo "done" uninstall: + @echo "Skills:" @for skill in $(SKILLS); do \ if [ -L "$(SKILLS_DIR)/$$skill" ]; then \ rm "$(SKILLS_DIR)/$$skill"; \ @@ -26,6 +44,18 @@ uninstall: echo " skip $$skill (not a symlink)"; \ fi \ done + @echo "" + @echo "Rules:" + @for rule in $(RULES); do \ + name=$$(basename $$rule); \ + if [ -L "$(RULES_DIR)/$$name" ]; then \ + rm "$(RULES_DIR)/$$name"; \ + echo " rm $$name"; \ + else \ + echo " skip $$name (not a symlink)"; \ + fi \ + done + @echo "" @echo "done" list: @@ -37,3 +67,13 @@ list: echo " - $$skill"; \ fi \ done + @echo "" + @echo "Rules:" + @for rule in $(RULES); do \ + name=$$(basename $$rule); \ + if [ -L "$(RULES_DIR)/$$name" ]; then \ + echo " ✓ $$name (installed)"; \ + else \ + echo " - $$name"; \ + fi \ + done diff --git a/add-tests/SKILL.md b/add-tests/SKILL.md new file mode 100644 index 0000000..837810e --- /dev/null +++ b/add-tests/SKILL.md @@ -0,0 +1,57 @@ +# /add-tests + +Add test coverage to existing code by analyzing, proposing, writing, and reporting. + +## Usage + +`/add-tests [path]` — Analyze code at path (file, directory, or module) and add tests. + +`/add-tests` — Analyze the entire project. + +## Instructions + +Work through four phases in order. Do not skip phases. + +### Phase 1: Analyze + +1. **Explore the codebase thoroughly** before proposing any tests. Read the modules in scope, trace their data flows, and understand how components interact. Understand the code's intent — not just its structure — so tests target real behavior and real risks. +2. Discover the test infrastructure: runner, config files, existing test directories, fixtures, helpers, and shared utilities. Check for `pytest.ini`, `pyproject.toml [tool.pytest]`, `jest.config.*`, `vitest.config.*`, or equivalent. +3. Inventory source files in scope. For each file, determine: public function/method count, whether tests exist (full, partial, or none), and what external dependencies would need mocking. +4. Identify external boundaries that need mocks: API clients, database calls, file I/O, time/date, third-party services. Follow the mocking rules in `testing.md` — mock at external boundaries only, never mock code under test. +5. Prioritize files by risk using the coverage targets from `testing.md`: + - Business logic / domain: 90%+ + - API endpoints: 80%+ + - UI components: 70%+ + - Untested files with high public function counts rank highest. + +### Phase 2: Propose + +6. Present a test plan as a markdown table with columns: File, Functions, Current Coverage, Proposed Tests, Priority (P0/P1/P2). +7. For each proposed test, specify: target function, category (Normal / Boundary / Error), one-line description, and any mocking required. All three categories are required per function — see `testing.md` for category definitions. +8. For large codebases, group the plan into batches (e.g., "Batch 1: core domain models, Batch 2: API endpoints"). +9. **Stop and ask the user for confirmation.** The user may add, remove, or reprioritize tests before you proceed. Do not write any test files until the user approves. + +### Phase 3: Write + +10. Create test files following the organization from `testing.md`: + ``` + tests/ + unit/ # One test file per source file + integration/ # Multi-component workflows + ``` +11. Follow the naming convention: `test_<module>_<function>_<scenario>_<expected>`. Example: `test_satellite_calculate_position_null_input_raises_error`. +12. Write all three test categories (normal, boundary, error) for every function in the approved plan. Be thorough with edge cases — cover boundary conditions, error states, and interactions that could realistically fail. +13. Use language-specific standards: + - **Python:** Follow `python-testing.md` — use `pytest` (never `unittest`), fixtures for setup, `@pytest.mark.parametrize` for category coverage, `@pytest.mark.django_db` for DB tests, `freezegun`/`time-machine` for time mocking. + - **TypeScript/JavaScript:** Follow `typescript-testing.md` — use Jest + React Testing Library, query priority (`getByRole` > `getByLabelText` > `getByText` > `getByTestId`), `waitFor` for async, type-safe test helpers in `tests/helpers/`. +14. Mock only at external boundaries. Never mock the code under test, domain logic, or framework behavior. +15. Run the tests after writing each batch. Confirm they pass. If a test fails against the current code, that is a discovered bug — do not delete the test or make it pass artificially. Note it for the report. + +### Phase 4: Report + +16. Summarize what was created: + - Test files created (with paths) + - Test count by category (normal / boundary / error) + - Coverage change (if a coverage tool is configured and measurable) + - Bugs discovered (tests that correctly fail against current code) + - Suggested follow-up: integration tests needed, areas that need refactoring before they are testable, additional mocking infrastructure to build diff --git a/claude-rules/testing.md b/claude-rules/testing.md new file mode 100644 index 0000000..37ba412 --- /dev/null +++ b/claude-rules/testing.md @@ -0,0 +1,140 @@ +# Testing Standards + +Applies to: `**/*.py`, `**/*.ts`, `**/*.tsx`, `**/*.js`, `**/*.jsx` + +## Test-Driven Development (Default) + +TDD is the default workflow for all code, including demos and prototypes. **Write tests first, before any implementation code.** Tests are how you prove you understand the problem — if you can't write a failing test, you don't yet understand what needs to change. + +1. **Red**: Write a failing test that defines the desired behavior +2. **Green**: Write the minimal code to make the test pass +3. **Refactor**: Clean up while keeping tests green + +Do not skip TDD for demo code. Demos build muscle memory — the habit carries into production. + +### Understand Before You Test + +Before writing tests, invest time in understanding the code: + +1. **Explore the codebase** — Read the module under test, its callers, and its dependencies. Understand the data flow end to end. +2. **Identify the root cause** — If fixing a bug, trace the problem to its origin. Don't test (or fix) surface symptoms when the real issue is deeper in the call chain. +3. **Reason through edge cases** — Consider boundary conditions, error states, concurrent access, and interactions with adjacent modules. Your tests should cover what could actually go wrong, not just the obvious happy path. + +### Adding Tests to Existing Untested Code + +When working in a codebase without tests: + +1. Write a **characterization test** that captures current behavior before making changes +2. Use the characterization test as a safety net while refactoring +3. Then follow normal TDD for the new change + +## Test Categories (Required for All Code) + +Every unit under test requires coverage across three categories: + +### 1. Normal Cases (Happy Path) +- Standard inputs and expected use cases +- Common workflows and default configurations +- Typical data volumes + +### 2. Boundary Cases +- Minimum/maximum values (0, 1, -1, MAX_INT) +- Empty vs null vs undefined (language-appropriate) +- Single-element collections +- Unicode and internationalization (emoji, RTL text, combining characters) +- Very long strings, deeply nested structures +- Timezone boundaries (midnight, DST transitions) +- Date edge cases (leap years, month boundaries) + +### 3. Error Cases +- Invalid inputs and type mismatches +- Network failures and timeouts +- Missing required parameters +- Permission denied scenarios +- Resource exhaustion +- Malformed data + +## Test Organization + +``` +tests/ + unit/ # One test file per source file + integration/ # Multi-component workflows + e2e/ # Full system tests +``` + +## Naming Convention + +- Unit: `test_<module>_<function>_<scenario>_<expected>` +- Integration: `test_integration_<workflow>_<scenario>_<outcome>` + +Examples: +- `test_satellite_calculate_position_null_input_raises_error` +- `test_integration_telemetry_sync_network_timeout_retries_three_times` + +## Test Quality + +### Independence +- No shared mutable state between tests +- Each test runs successfully in isolation +- Explicit setup and teardown + +### Determinism +- Never hardcode dates or times — generate them relative to `now()` +- No reliance on test execution order +- No flaky network calls in unit tests + +### Performance +- Unit tests: <100ms each +- Integration tests: <1s each +- E2E tests: <10s each +- Mark slow tests with appropriate decorators/tags + +### Mocking Boundaries +Mock external dependencies at the system boundary: +- Network calls (HTTP, gRPC, WebSocket) +- File I/O and cloud storage +- Time and dates +- Third-party service clients + +Never mock: +- The code under test +- Internal domain logic +- Framework behavior (ORM queries, middleware, hooks) + +## Coverage Targets + +- Business logic and domain services: **90%+** +- API endpoints and views: **80%+** +- UI components: **70%+** +- Utilities and helpers: **90%+** +- Overall project minimum: **80%+** + +New code must not decrease coverage. PRs that lower coverage require justification. + +## TDD Discipline + +TDD is non-negotiable. These are the rationalizations agents use to skip it — don't fall for them: + +| Excuse | Why It's Wrong | +|--------|----------------| +| "This is too simple to need a test" | Simple code breaks too. The test takes 30 seconds. Write it. | +| "I'll add tests after the implementation" | You won't, and even if you do, they'll test what you wrote rather than what was needed. Test-after validates implementation, not behavior. | +| "Let me just get it working first" | That's not TDD. If you can't write a failing test, you don't understand the requirement yet. | +| "This is just a refactor" | Refactors without tests are guesses. Write a characterization test first, then refactor while it stays green. | +| "I'm only changing one line" | One-line changes cause production outages. Write a test that covers the line you're changing. | +| "The existing code has no tests" | Start with a characterization test. Don't make the problem worse. | +| "This is demo/prototype code" | Demos build habits. Untested demo code becomes untested production code. | +| "I need to spike first" | Spikes are fine — then throw away the spike, write the test, and implement properly. | + +If you catch yourself thinking any of these, stop and write the test. + +## Anti-Patterns (Do Not Do) + +- Hardcoded dates or timestamps (they rot) +- Testing implementation details instead of behavior +- Mocking the thing you're testing +- Shared mutable state between tests +- Non-deterministic tests (random without seed, network in unit tests) +- Testing framework behavior instead of your code +- Ignoring or skipping failing tests without a tracking issue diff --git a/claude-rules/verification.md b/claude-rules/verification.md new file mode 100644 index 0000000..8993736 --- /dev/null +++ b/claude-rules/verification.md @@ -0,0 +1,42 @@ +# Verification Before Completion + +Applies to: `**/*` + +## The Rule + +Do not claim work is done without fresh verification evidence. Run the command, read the output, confirm it matches the claim, then — and only then — declare success. + +This applies to every completion claim: +- "Tests pass" → Run the test suite. Read the output. Confirm all green. +- "Linter is clean" → Run the linter. Read the output. Confirm no warnings. +- "Build succeeds" → Run the build. Read the output. Confirm no errors. +- "Bug is fixed" → Run the reproduction steps. Confirm the bug is gone. +- "No regressions" → Run the full test suite, not just the tests you added. + +## What Fresh Means + +- Run the verification command **now**, in the current session +- Do not rely on a previous run from before your changes +- Do not assume your changes didn't break something unrelated +- Do not extrapolate from partial output — read the whole result + +## Red Flags + +If you find yourself using these words, you haven't verified: + +- "should" ("tests should pass") +- "probably" ("this probably works") +- "I believe" ("I believe the build is clean") +- "based on the changes" ("based on the changes, nothing should break") + +Replace beliefs with evidence. Run the command. + +## Before Committing + +Before any commit: +1. Run the test suite — confirm all tests pass +2. Run the linter — confirm no new warnings +3. Run the type checker — confirm no new errors +4. Review the diff — confirm only intended changes are staged + +Do not commit based on the assumption that nothing broke. Verify. diff --git a/debug/SKILL.md b/debug/SKILL.md new file mode 100644 index 0000000..e4e1041 --- /dev/null +++ b/debug/SKILL.md @@ -0,0 +1,55 @@ +# /debug — Systematic Debugging + +Investigate a bug or test failure methodically. No guessing, no shotgun fixes. + +## Usage + +``` +/debug [description of the problem] +``` + +If no description is given, prompt the user to describe the symptom. + +## Instructions + +Work through four phases in order. Do not skip to a fix. + +### Phase 1: Understand the Symptom + +1. **Reproduce the failure** — run the failing test or trigger the bug. Capture the exact error message, stack trace, or incorrect output. If you can't reproduce it, say so — don't guess. +2. **Check logs and observability** — review application logs, error tracking, and metrics around the time of failure. For deployed services, check structured logs, APM traces, and alerting dashboards. Logs often reveal context that code reading alone cannot. +3. **Locate the failure point** — identify the exact file and line where the error occurs. Read the surrounding code. Understand what the code is trying to do, not just where it fails. +4. **Trace the data flow** — follow the inputs from their origin to the failure point. Read callers, callees, models, serializers, and middleware in the path. Understand how the data got into the state that caused the failure. + +Do not propose any fix during this phase. You are gathering evidence. + +### Phase 2: Identify the Root Cause + +5. **Ask "why?" at least three times** — if a value is wrong in a view, why? Because the service returned bad data. Why? Because the model query missed a filter. Why? Because the migration didn't add the index. That's the root cause. +6. **Check for related symptoms** — search for similar patterns elsewhere in the codebase. If the bug is in one endpoint, check sibling endpoints for the same mistake. Bugs often travel in packs. +7. **Form a hypothesis** — state the root cause clearly: "The bug is caused by [X] in [file:line] because [reason]." If you have multiple hypotheses, rank them by likelihood. + +### Phase 3: Verify the Hypothesis + +8. **Write a failing test** that proves your hypothesis — the test should fail for the reason you identified, not just any reason. If the test passes, your hypothesis is wrong. Go back to Phase 2. +9. **Confirm the test fails for the right reason** — read the failure output. Does it match your hypothesis? A test that fails for a different reason than expected is not evidence. + +### Phase 4: Fix and Verify + +10. **Write the minimal fix** — change only what is necessary to address the root cause. Do not refactor, clean up, or improve adjacent code. +11. **Run the failing test** — confirm it passes. +12. **Add boundary and error case tests** — cover edge cases around the fix. +13. **Run the full test suite** — confirm no regressions. +14. **Commit** following conventional commit format. + +## Escalation Rule + +If you've attempted 3 fixes and the bug persists, stop. The problem is likely architectural, not local. Report what you've learned and recommend a broader investigation rather than attempting fix #4. + +## What Not to Do + +- Don't propose fixes before completing Phase 2 +- Don't change multiple things at once — isolate variables +- Don't suppress errors or add try/catch to hide symptoms +- Don't add logging as a fix (logging is a diagnostic, not a solution) +- Don't delete or skip a failing test to "fix" the suite diff --git a/fix-issue/SKILL.md b/fix-issue/SKILL.md new file mode 100644 index 0000000..adfed14 --- /dev/null +++ b/fix-issue/SKILL.md @@ -0,0 +1,54 @@ +# /fix-issue — Pick Up and Implement an Issue + +Create a branch, implement the fix, test, and commit. + +## Usage + +``` +/fix-issue [ISSUE_ID] +``` + +If no issue ID is given, prompt the user to provide one or describe the issue. + +## Instructions + +1. **Fetch the issue** from the project's issue tracker (Linear, GitHub Issues, Jira, etc.) or ask the user for the issue details (title, description, acceptance criteria). + +2. **Create a branch** following the naming convention: + - Bug: `fix/ISSUE_ID-short-description` + - Feature: `feature/ISSUE_ID-short-description` + - Chore: `chore/ISSUE_ID-short-description` + +3. **Explore the codebase and find the root cause**: + - Do NOT jump to a fix. Read the relevant modules, trace the data flow, and understand how the system works around the issue. + - Identify the **root cause**, not just the surface symptom. If a value is wrong in a handler, trace it back through the service, model, schema, or migration — wherever the real problem lives. + - Read callers, callees, and related tests to understand the full context of the change. + - Follow the project's coding standards and conventions + - Keep changes focused — only what the issue requires + - If the change involves data flow, confirm API contracts (schemas, typed clients) exist or create them first + - No drive-by refactoring or scope creep + +4. **Write failing test first (TDD)** — before any implementation code: + - Create a test file if one doesn't exist for the module + - Write a test that demonstrates the bug or defines the desired behavior — this proves you understand the root cause + - Run the test — confirm it **fails** + - Commit: `test: Add failing test for [issue]` + +5. **Implement the fix**: + - Write the minimal code to make the failing test pass + - Run the test — confirm it **passes** + - Commit: `fix: [description]` + +6. **Add edge case tests — be thorough**: + - Add boundary and error case tests (normal, boundary, and error categories) + - Think through all edge cases: empty inputs, nulls, concurrent access, large data, permission boundaries, and interactions with adjacent modules + - Run the full test suite to confirm nothing is broken + - Commit: `test: Add edge cases for [issue]` + +7. **Refactor if needed**: + - Clean up the implementation while all tests stay green + - Commit: `refactor: [description]` + +All commits must use conventional messages (`feat:`, `fix:`, `chore:`, `test:`, `refactor:`), reference the issue ID in the body, and contain no AI attribution. + +8. **Report** what was done: files changed, tests added, and any open questions. diff --git a/respond-to-review/SKILL.md b/respond-to-review/SKILL.md new file mode 100644 index 0000000..c1cc996 --- /dev/null +++ b/respond-to-review/SKILL.md @@ -0,0 +1,50 @@ +# /respond-to-review — Evaluate and Implement Code Review Feedback + +Evaluate code review feedback technically before implementing. Verify suggestions against the actual codebase — don't implement blindly. + +## Usage + +``` +/respond-to-review [PR_NUMBER] +``` + +If no PR number is given, check the current branch's open PR for pending review comments. + +## Instructions + +### 1. Gather the Feedback + +- Fetch review comments using `gh api repos/{owner}/{repo}/pulls/{number}/comments` (for inline review comments) and `gh api repos/{owner}/{repo}/issues/{number}/comments` (for top-level PR conversation comments) +- Read each comment in full. Group related comments — reviewers often raise connected issues across multiple comments. + +### 2. Evaluate Each Item + +For each review comment, before implementing anything: + +1. **Restate the suggestion in your own words** — make sure you understand what's being asked. If you can't restate it clearly, ask for clarification before touching code. +2. **Verify against the codebase** — check whether the reviewer's premise is correct. Reviewers sometimes misread code, miss context, or reference outdated patterns. Read the actual code they're commenting on. +3. **Check YAGNI** — if the reviewer suggests a "more proper" or "more robust" implementation, grep the codebase for actual usage. If nothing uses the suggested pattern today, flag it: "This would add complexity without current consumers. Should we defer until there's a concrete need?" +4. **Assess the suggestion** — categorize as: + - **Correct and actionable** — implement it + - **Correct but out of scope** — acknowledge and create a follow-up issue + - **Debatable** — present your reasoning and ask for the reviewer's perspective + - **Incorrect** — explain why with evidence (file paths, test results, documentation) + +### 3. Respond + +- Lead with technical substance, not agreement +- If you disagree, explain why with code references — not opinion +- If you're unsure, say so and ask a specific question +- Never implement a suggestion you don't understand + +### 4. Implement + +- Address simple fixes first, complex ones after +- Test each change individually — don't batch unrelated fixes into one commit +- Run the full test suite after all changes +- Commit with conventional messages referencing the review: `fix: Address review — [description]` + +### 5. Report + +- Summarize what was implemented, what was deferred, and what needs discussion +- Link any follow-up issues created for out-of-scope suggestions diff --git a/review-pr/SKILL.md b/review-pr/SKILL.md new file mode 100644 index 0000000..c7ebd75 --- /dev/null +++ b/review-pr/SKILL.md @@ -0,0 +1,57 @@ +# /review-pr — Review a Pull Request + +Review a PR against engineering standards. + +## Usage + +``` +/review-pr [PR_NUMBER] +``` + +If no PR number is given, review the current branch's open PR. + +## Instructions + +1. Fetch the PR diff and description using `gh pr view` and `gh pr diff`. +2. Review against these criteria, reporting each as PASS / WARN / FAIL: + +### Security +- No hardcoded secrets, tokens, API keys, or credentials +- All user input validated at system boundary +- Parameterized queries only (no SQL string concatenation) +- No sensitive data logged (PII, tokens, passwords) +- Dependencies pinned and auditable + +### Testing (TDD Evidence) +- Tests exist for all new code — check for test commits **before** implementation commits (TDD workflow) +- All three categories covered: normal (happy path), boundary, and error cases — edge cases must be thorough, not token +- Tests are independent — no shared mutable state between tests +- Mocking is at external boundaries only (network, file I/O, time) — domain logic tested directly +- Test naming follows project convention +- Coverage does not decrease — flag PRs that lower coverage without justification + +### Conventions +- Type annotations on all functions (including return types) +- Conventional commit messages (`feat:`, `fix:`, `chore:`, etc.) +- No AI attribution anywhere (code, comments, commits, PR descriptions) +- One logical change per commit +- Docstrings on public functions/classes + +### Root Cause & Thoroughness +- Bug fixes address the root cause, not surface symptoms — if the fix is a band-aid, flag it +- Changes demonstrate understanding of the surrounding code (not just the changed lines) +- Edge cases are covered comprehensively, not just the obvious happy path + +### Architecture +- Request handlers deal with request/response only — business logic in services or domain layer +- No unnecessary abstractions or over-engineering +- Changes scoped to what was asked (no drive-by refactoring) + +### API Contracts +- New endpoints have typed contracts or schemas defined +- No raw dict/object responses bypassing the contract layer +- Client-side types match server-side output +- Data flows through the API layer, not direct data access from handlers + +3. Summarize findings with a clear verdict: **Approve**, **Request Changes**, or **Needs Discussion**. +4. For each WARN or FAIL, include the file and line number with a brief explanation. diff --git a/security-check/SKILL.md b/security-check/SKILL.md new file mode 100644 index 0000000..ca431e0 --- /dev/null +++ b/security-check/SKILL.md @@ -0,0 +1,48 @@ +# /security-check — Audit Changes for Security Issues + +Scan staged or recent changes for secrets, OWASP vulnerabilities, and dependency risks. + +## Usage + +``` +/security-check [FILE_OR_DIRECTORY] +``` + +If no argument is given, audit all staged changes (`git diff --cached`). If there are no staged changes, audit the diff from the last commit. + +## Instructions + +1. **Gather the changes** to audit: + - Staged changes: `git diff --cached` + - Or last commit: `git diff HEAD~1` + - Or specific path if provided + +2. **Check for hardcoded secrets** — scan for patterns: + - AWS access keys (`AKIA...`) + - Generic secret patterns (`sk-`, `sk_live_`, `sk_test_`) + - Password assignments (`password=`, `passwd=`, `secret=`) + - Private keys (`-----BEGIN.*PRIVATE KEY-----`) + - `.env` file contents committed by mistake + - API tokens, JWTs, or bearer tokens in source code + +3. **OWASP Top 10 review**: + - SQL injection: string concatenation in queries + - XSS: unsanitized user input rendered in HTML/JSX + - Broken authentication: missing permission checks on endpoints + - Insecure deserialization: unsafe deserialization of untrusted data (e.g., eval, exec) + - Security misconfiguration: debug mode enabled in production settings + - Sensitive data exposure: PII or tokens in log statements + +4. **Dependency audit**: + - Run `pip-audit` if Python files changed + - Run `npm audit` if JavaScript/TypeScript files changed + - Flag any new dependencies added without version pinning + +5. **Report findings** in a table: + + | Severity | File:Line | Finding | Recommendation | + |----------|-----------|---------|----------------| + + Severity levels: CRITICAL, HIGH, MEDIUM, LOW, INFO + +6. If no issues found, report "No security issues detected" with a summary of what was checked. |
