Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions .claude/rules/frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,32 @@ globs: ["**/*.{js,jsx,ts,tsx,vue,svelte}"]

# Frontend Rules

> Loaded automatically when Claude opens any frontend source file. Each rule has a "why" so you can override it intentionally.

## Components
- Functional components only (no class components)
- One component per file
- Reusable components in `components/` directory
- Page components in `pages/` or `views/` directory
- Props interface/type defined at top of file
- Functional components only (no class components) — *hooks API is the supported path since React 16.8 (2019); class lifecycle methods are not first-class with Suspense / concurrent rendering*
- One component per file — *grep-by-filename works; circular-import risk drops*
- Reusable components in `components/`, page components in `pages/` or `views/` — *next.js / nuxt convention; routing tools depend on it*
- Props interface/type defined at top of file (TS) or `propTypes` defined at bottom (JS) — *contract is visible without scrolling; LSP autocomplete works for consumers*

## State Management
- Local state for component-specific data
- Global store for shared application state
- API calls through dedicated service layer (not inside components)
- Loading and error states for all async operations
- Local state for component-specific data (`useState`, `useReducer`) — *keep blast radius small; don't pollute global store with form input state*
- Global store (Zustand / Redux / Pinia) for shared application state only — *anything passed through more than 2 prop layers is a candidate; below that, prop drilling is fine*
- API calls through a dedicated service layer (`services/` or `api/`), not inside components — *one place to swap fetch for axios, add retries, mock in tests*
- Loading and error states for all async operations — *the "spinner-then-blank" UX is a regression magnet; always render `if (error) ... if (loading) ... return data`*

## Styling
- Follow existing project conventions (CSS modules / Tailwind / styled-components)
- Responsive design — mobile-first approach
- No inline styles beyond trivial cases
- Follow the project's existing convention (CSS modules / Tailwind / styled-components / vanilla-extract) — *do not introduce a second styling system; the bundle size and cognitive cost is real*
- Responsive design — mobile-first (`min-width` queries, not `max-width`) — *progressive enhancement; default styles work on the smallest target*
- No inline styles beyond trivial cases (one-off `style={{ width: dynamicPx }}`) — *inline styles bypass the design system, can't be themed, and hurt CSP*

## Error Handling
- Error boundaries for user-facing components
- User-friendly error messages (no raw error objects)
- Graceful degradation when API is unavailable
- Error boundaries for user-facing component trees — *uncaught render errors otherwise unmount the entire React tree (white screen)*
- User-friendly error messages, no raw `error.toString()` — *expose stack traces only in dev; production users see a sentence and a retry button*
- Graceful degradation when API is unavailable — *show cached data + "offline" indicator rather than a hard error*

## Testing
- Unit tests for utility functions
- Component tests for user interactions
- Mock API responses in tests
- Test accessibility (semantic HTML, ARIA labels)
- Unit tests for utility functions (Vitest / Jest) — *fastest feedback loop; pure functions deserve 100% coverage*
- Component tests for user interactions (Testing Library: `getByRole`, `userEvent.click`) — *test the user contract, not implementation details; avoid `getByTestId` unless nothing semantic exists*
- Mock API responses in tests (MSW preferred over `jest.mock`) — *MSW intercepts at the network layer, so the same mocks work in Storybook and Playwright*
- Test accessibility (semantic HTML, ARIA labels, `getByRole` queries) — *if Testing Library can find your button, so can a screen reader*
42 changes: 22 additions & 20 deletions .claude/rules/python-backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,32 @@ globs: ["**/*.py"]

# Python Backend Rules

> Loaded automatically when Claude opens any `*.py` file. Each rule has a "why" so you can override it intentionally rather than blindly.

## Code Style
- Type hints on ALL function signatures (parameters and return types)
- Docstrings on all public functions and classes (Google style)
- Use `pathlib.Path` instead of `os.path`
- Prefer f-strings over `.format()` or `%`
- Use `logging` module, never `print()` for non-debug output
- Constants in UPPER_SNAKE_CASE at module level
- Type hints on ALL function signatures (parameters and return types) — *enables `mypy --strict` and IDE autocomplete; required by FastAPI/Pydantic v2 for response_model inference*
- Docstrings on all public functions and classes (Google style) — *parsed by Sphinx/mkdocstrings; downstream callers see hover hints*
- Use `pathlib.Path` instead of `os.path` — *cross-platform paths, chainable API, `.exists()`/`.read_text()` without import gymnastics*
- Prefer f-strings over `.format()` or `%` — *fastest path on CPython 3.12+; lower cognitive load*
- Use `logging` module, never `print()` for non-debug output — *level filtering, structured handlers, captured by pytest's `caplog` fixture*
- Constants in UPPER_SNAKE_CASE at module level — *grep-friendly, distinguishable from runtime values*

## Error Handling
- Handle exceptions explicitly — never use bare `except:`
- Use custom exception classes for domain errors
- Always log exceptions with traceback: `logger.exception("message")`
- Return meaningful error messages to API callers
- Handle exceptions explicitly — never use bare `except:` — *bare except swallows `KeyboardInterrupt` and `SystemExit`, hides real bugs*
- Use custom exception classes for domain errors — *callers can `except DomainError` without coupling to library-specific exception types*
- Always log exceptions with traceback: `logger.exception("message")` — *not `logger.error(str(e))` which loses the stack*
- Return meaningful error messages to API callers — *FastAPI: prefer `HTTPException(status_code, detail)` over generic 500*

## Architecture
- Use Pydantic models for request/response validation
- Async endpoints where I/O is involved
- Dependency injection for testability
- Repository pattern for database access
- Service layer between routes and repositories
- Use Pydantic v2 models for request/response validation — *catches malformed input at the boundary; auto-generates OpenAPI*
- Async endpoints where I/O is involved (`await db.execute(...)`, `await http.get(...)`) — *sync handlers block the event loop and serialise the entire app*
- Dependency injection (FastAPI `Depends`) for testability — *swap real DB session for in-memory in tests without monkey-patching*
- Repository pattern for database access — *isolates SQL/ORM details from business logic; one place to add caching*
- Service layer between routes and repositories — *route handlers stay thin (parse → call service → serialise); business logic is unit-testable without HTTP*

## Testing
- Use pytest with fixtures
- Mock external services (API calls, database) in unit tests
- Use factories for test data (not hardcoded dictionaries)
- Async tests with `pytest-asyncio`
- Each test function tests ONE thing
- Use pytest with fixtures (not `unittest.TestCase`) — *first-class parametrize, smaller boilerplate, plugin ecosystem (`pytest-asyncio`, `pytest-mock`, `pytest-cov`)*
- Mock external services (API calls, database) in unit tests — *unit tests must run in <1 s each; integration tests live in a separate folder*
- Use factories for test data (`factory_boy`, `polyfactory`), not hardcoded dictionaries — *changes to a model don't break 50 unrelated tests*
- Async tests with `pytest-asyncio` and `@pytest.mark.asyncio` — *required for `async def` tests; otherwise pytest treats them as coroutines and skips silently*
- Each test function tests ONE thing — *failure message names exactly what regressed; no shotgun debugging*
73 changes: 73 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Validate

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Validate settings.json is well-formed JSON
run: |
python -c "import json,sys; json.load(open('.claude/settings.json'))"
echo "settings.json: OK"

- name: Validate every agent has a YAML frontmatter name field
run: |
set -e
fail=0
for f in .claude/agents/*.md; do
if ! awk '/^---$/{f++; next} f==1' "$f" | grep -qE '^name:[[:space:]]*[A-Za-z0-9_-]+'; then
echo "::error file=$f::missing or invalid 'name:' field in YAML frontmatter"
fail=1
fi
if ! awk '/^---$/{f++; next} f==1' "$f" | grep -qE '^description:'; then
echo "::error file=$f::missing 'description:' field in YAML frontmatter"
fail=1
fi
if ! awk '/^---$/{f++; next} f==1' "$f" | grep -qE '^tools:'; then
echo "::error file=$f::missing 'tools:' field in YAML frontmatter"
fail=1
fi
done
exit $fail

- name: Validate every rule has a globs frontmatter
run: |
set -e
fail=0
for f in .claude/rules/*.md; do
if ! awk '/^---$/{f++; next} f==1' "$f" | grep -qE '^globs:'; then
echo "::error file=$f::missing 'globs:' field in YAML frontmatter"
fail=1
fi
done
exit $fail

- name: CHANGELOG.md exists and is non-empty
run: |
test -s CHANGELOG.md || (echo "CHANGELOG.md missing or empty" && exit 1)

- name: All Markdown internal links resolve
run: |
set -e
fail=0
while IFS= read -r line; do
file="${line%%:*}"
rest="${line#*:}"
target=$(echo "$rest" | grep -oE '\]\([^)#]+' | sed 's/](//' | head -1)
[ -z "$target" ] && continue
case "$target" in
http*|mailto:*|\#*) continue ;;
esac
base="$(dirname "$file")"
resolved="$base/$target"
if [ ! -e "$resolved" ] && [ ! -e "$target" ]; then
echo "::warning file=$file::broken internal link → $target"
fi
done < <(grep -rEn '\]\([^)]+\)' README.md CHANGELOG.md CONTRIBUTING.md docs/*.md 2>/dev/null || true)
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Changelog

All notable changes to this project will be documented in this file.
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) · [SemVer](https://semver.org/spec/v2.0.0.html).

## [0.2.0] — 2026-04-30

### Added
- Mermaid diagram of the four-layer defence model in `README.md`
- `Limitations & honest disclaimers` section covering compaction, subagent isolation, shell portability, slow suites, push-vs-commit gate, `/clear` behaviour, advisory nature of rules
- `Tech stack & component map` table mapping each file to a concrete role
- `Configuration notes` section explaining `permissions.allow` semantics and stack-specific test-command swap-ins
- `CHANGELOG.md` (this file)
- `CONTRIBUTING.md` with priority list for community submissions
- `.github/workflows/validate.yml` — validates `settings.json` is well-formed JSON and every agent file has a YAML frontmatter `name:` field
- "Featured on Habr / dev.to / Claude Code Opus 4.7" badges
- Inline `CRITICAL RULES` block in `README.md` so the value proposition is visible without opening the template
- "Why" rationale comments on rules in `.claude/rules/python-backend.md` and `.claude/rules/frontend.md`
- Author signature with full name and direct links to Habr / dev.to profiles

### Changed
- README hero rewritten: leads with social proof (Habr top-5, 20K reads, Технотекст 8) and Opus 4.7 / 1M context positioning
- "The Problem" section replaced with the post-1M-context narrative — regressions are a discipline problem, not a memory problem
- Project structure tree annotated with concrete responsibilities per file
- `Recommended stack` table extended with "Why" column

### Notes on `settings.json`
- `Bash(pip install*)` remains in `permissions.allow` for compatibility with the original community template, but is now flagged in README as a candidate for removal in security-sensitive projects
- The hook's `pytest` command is unchanged; README now documents the npm / cargo / go variants

## [0.1.0] — 2026-03-05

### Added
- Initial release accompanying the [Habr article](https://habr.com/ru/articles/1013330/) (top-5 day, 20K reads, Технотекст 8 entry) and the [dev.to article](https://dev.to/creatman/i-stopped-claude-code-from-breaking-my-projects-heres-the-exact-setup-1agi)
- `CLAUDE.md.template` with `CRITICAL RULES`, `Working Style`, `Agents`, `Known Patterns`, `Gotchas` sections
- `.claude/settings.json` with `PreToolUse` commit-blocking `pytest` hook and `PostToolUse` edit reminder
- Three subagents: `planner` (research-only, no `Write` tool), `tester` (full-suite runner with regression check), `code-reviewer` (severity-tagged review)
- Two glob-scoped rules: `python-backend.md` (`**/*.py`), `frontend.md` (`**/*.{js,jsx,ts,tsx,vue,svelte}`)
- `docs/WORKFLOW.md` daily playbook with emergency recovery and cheat sheet
- `docs/MCP-SETUP.md` for Playwright, GitHub, Postgres, Context7
- `LICENSE` (MIT)
39 changes: 39 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Contributing

Thanks for considering a contribution. This repo is intentionally small — its job is to be a clean, copy-paste starter for Claude Code anti-regression configs. PRs that add real, battle-tested artifacts are very welcome.

## Priorities (highest impact first)

1. **Sister rules for new languages** — `.claude/rules/go-backend.md`, `rust-backend.md`, `typescript-node.md`, `kotlin.md`, etc. Follow the existing `python-backend.md` shape (frontmatter `globs:` + sections + a one-line "why" per rule).
2. **Framework-specific subagents** — `django-tester.md`, `nextjs-reviewer.md`, `rails-planner.md`. Constrain `tools:` to the minimum set needed and document the output format.
3. **Additional `PreToolUse` hooks** — examples that would fit:
- **Lint gate** on `git commit*` (`ruff check` / `eslint` / `golangci-lint`)
- **Secret-scanning gate** on `git commit*` (`gitleaks detect --staged`)
- **Migration-safety gate** on writes to `migrations/` directory
4. **Stack-specific test-command swap-ins** for the README's `Configuration notes` section (Maven, Gradle, sbt, mix, etc.).
5. **Recording assets** — better demo GIF / asciinema cast than the placeholder.

## What we will not merge

- "Best practices" essays without code artifacts.
- Vendor-specific rules that lock the user into a single editor or shell beyond what the existing setup already does.
- Hooks that silently weaken the commit gate (e.g. `pytest --pass-with-no-tests` without a clear opt-in note).
- Generic linter configs that already have canonical homes elsewhere (just link to them in `docs/MCP-SETUP.md` style).

## Pull request checklist

- [ ] New rule file has frontmatter `globs:` and at least one "why" rationale per bullet
- [ ] New subagent has `name:`, `description:`, `tools:` frontmatter and an explicit output format
- [ ] New hook has a stated **timeout**, a stated **shell** (bash / pwsh / cross-platform), and a tested failure path
- [ ] `README.md` and `CHANGELOG.md` updated when surface area changes
- [ ] `validate.yml` workflow still passes (it checks `settings.json` is valid JSON and every `.claude/agents/*.md` has a `name:` frontmatter field)

## Style

- Prefer concrete commands and version numbers over abstract advice.
- One sentence per rule. If you need a paragraph, you are explaining the wrong thing.
- Cite the source of any "best practice" you import (Anthropic docs, SFEIR Institute, real incident).

## Author / maintainer

[@CreatmanCEO](https://github.com/CreatmanCEO) — Nick Podolyak. Open an issue first for anything larger than a single rule or subagent.
Loading
Loading