diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..5dea88b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,7 @@ +# Project context + +Read these on every session. Rules in them override defaults. + +@ai/shared.md +@ai/backend-context.md +@ai/frontend-context.md diff --git a/ai/backend-context.md b/ai/backend-context.md new file mode 100644 index 0000000..fca41f0 --- /dev/null +++ b/ai/backend-context.md @@ -0,0 +1,45 @@ +# Backend context + +> Read `ai/shared.md` first. This file only covers backend-specific rules. + +## Project Context + +**Stack:** PHP 8.5, Slim 4, PHP-DI/Slim-Bridge, PHPUnit 13, Composer. +Persistence is JSON-file based (see `Json*Repository` classes); no ORM. +**Architecture:** Domain-Driven Design. Code is organized by domain entity +under `app/` (Auth, Node, Plan, ScheduledNode, Text, User, View, +ValueObjects) into Entities, DTOs, Repositories, Use Cases, and Fakes +(in-memory repos for tests). + +## Code patterns + +- Look at similar entities (e.g. `Node`, `Text`) for reference +- Entities: constructor with properties, getters +- DTOs: simple data containers for creation (e.g. `CreateTextDto`) +- Repositories: interfaces that define data access + - Do not write unit tests for concrete repository implementations + (e.g. `JsonNodeRepository`). They are exercised by e2e tests. Use + cases are tested with fake repositories. +- Use cases: business logic with Request objects + - When throwing exceptions, add `@throws` docblock +- Fakes: in-memory implementations for testing + - Look at `tests/Fakes/` for examples + - Find/lookup methods must return a new instance of the entity, not the + stored reference +- Tests: follow existing patterns in `tests/Unit/[Entity]/UseCases/` + - In `setUp`, only use fake repositories for entities under test - construct + dependency objects directly with `new` (e.g. + `new Text(...)`) instead of creating them through their fake + repositories + +## PHP rules + +- Imports: always put `use` statements at the top of the file, never use inline + imports (e.g. `\App\Foo\Bar::class`) +- Closures: never use arrow functions (`fn () =>`) - always use regular + anonymous functions (`function () { return ...; }`) + +## Pre-commit + +Run `php-cs-fixer fix` on worked-on directories before committing (uses the +existing `.php-cs-fixer.dist.php` config). diff --git a/ai/backend_prompt_template.md b/ai/backend_prompt_template.md deleted file mode 100644 index c16ef26..0000000 --- a/ai/backend_prompt_template.md +++ /dev/null @@ -1,68 +0,0 @@ -# Entity Creation Prompt Template - -Follow the existing patterns in this codebase to: -- create a new entity called [EntityName]. - -Requirements: -- The entity encapsulates [one or more Entities] -- Include [any other fields] - -Process (TDD - Test Driven Development): -1. Write a test first -2. Run the test to confirm it fails -3. Implement the code to make the test pass -4. Run the test to confirm it passes -5. Repeat for each new behavior - -Code patterns to follow: -- First, explore the codebase to understand existing entity patterns -- Look at similar entities (e.g. Node, Text, etc.) for reference -- Entities: constructor with properties, getters -- DTOs: simple data containers for creation -- Repositories: interfaces that define data access - - Do not write unit tests for concrete repository implementations - (e.g., Doctrine/persistence-backed). They are exercised by e2e - tests. Use cases are tested with fake repositories. -- Use cases: business logic with Request objects - - When throwing exceptions, add @throws docblock -- Fakes: in-memory implementations for testing - - Look at tests/Fakes/ for examples - - Find/lookup methods must return a new instance of the entity, not the stored reference -- Tests: follow existing patterns in tests/Unit/[Entity]/UseCases/ - - In setUp, only use fake repositories for entities under test - construct dependency objects directly with `new` (e.g., `new Text(....)`) instead of creating them through their fake repositories -- Lines should not exceed 80 columns, but should use up to 80 columns when possible - do not split lines unnecessarily -- Imports: always put use statements at the top of the file, never use inline imports (e.g., \App\Foo\Bar::class) -- Variable names: use explicit, descriptive names - never single-letter or abbreviated variables (e.g., use $sponsorship not $s, $event not $e) -- Never use em-dashes (—) in code, comments, commit messages, or any - written output. Use a regular hyphen (-), a colon, or rephrase - with parentheses instead. - -Git commit style: -- Subject: present tense, imperative mood (add, create, test, fix) -- Subject: lowercase, short (3-6 words) -- Match subject patterns found in git history -- Add a body when the change needs explanation beyond the subject - - e.g., why the change was made, non-obvious tradeoffs, or notable - implementation details. Skip the body for trivial/self-evident commits. -- Separate subject and body with a blank line; wrap body at ~72 columns - -Git commits: -- Tests should be committed first, before implementation -- Group related changes together in a single commit (e.g., a new class - plus its registration, or a getter plus the property it exposes). - Avoid mixing unrelated concerns in one commit. -- Keep commits small and focused - prefer many small commits over few - large ones, but don't artificially split a single logical change - across multiple commits -- Commits are for reviewing and documenting the development of code -- Don't wait to commit - commit as you go -- Run `php-cs-fixer fix` on worked on directories before committing - -Branch naming: -- Use kebab-case (e.g., presenting-track, agenda-slots) -- Use descriptive feature names -- Examples: "presenting-track", "agenda-slots", "confirm-application" -- Or use type/description: "feature/presenting-track", "fix/bug-name" -- NEVER work directly on master/main - always create and work on a branch - -Do not push anything. Make commits as you go. diff --git a/ai/frontend-context.md b/ai/frontend-context.md new file mode 100644 index 0000000..8757e1f --- /dev/null +++ b/ai/frontend-context.md @@ -0,0 +1,33 @@ +# Frontend context + +> Read `ai/shared.md` first. This file only covers frontend-specific rules. + +## Project Context + +**Stack:** vanilla PHP templates in `views/templates/`, plain ES JavaScript in +`public/js/`, no framework, no build step. Cypress 15 for E2E. +**Entry point:** `public/index.php` (Slim app); page templates are rendered +via the existing templating layer. + +## Code patterns + +- Look at existing pages (`home.php`/`home.js`, `text.php`/`text.js`, + `today.php`/`today.js`) for reference before writing anything +- **Templates:** `views/templates/.php`, one file per page +- **Page JS:** `public/js/.js`, one file per page, paired with the + matching template +- **Testing:** Cypress E2E only, mirror existing `cypress/e2e/*.cy.js` style + (note: this project uses `.cy.js`, not `.cy.ts`) +- **Imports / script tags:** keep at the top of the file +- **Variable names:** explicit, descriptive (e.g. `text` not `t`) + +## Pre-commit + +No JS formatter or linter is configured yet; format manually for consistency +with surrounding files. (TODO: wire up format/lint when added.) + +## Note on commit granularity + +Frontend changes are often a template plus its page-level JS counterpart - +commit them together as a single logical unit, per the "one logical change +per commit" rule in `shared.md`. diff --git a/ai/frontend_prompt_template.md b/ai/frontend_prompt_template.md deleted file mode 100644 index a865577..0000000 --- a/ai/frontend_prompt_template.md +++ /dev/null @@ -1,52 +0,0 @@ -# Frontend Prompt Template - -Follow the existing patterns in this codebase to: -- xxxxxxxx - -Requirements: -- xxxxx - -Process (TDD - Test Driven Development): -1. Write a test first -2. Run the test to confirm it fails -3. Implement the code to make the test pass -4. Run the test to confirm it passes -5. Repeat for each new behavior - -Code patterns to follow: -- First, explore the codebase to understand existing entity patterns -- Look at similar pages for reference -- Tests: follow existing patterns in cypress/e2e/ -- Lines should not exceed 80 columns, but should use up to 80 columns when possible - do not split lines unnecessarily -- Imports: always put imports at the top of the file -- Variable names: use explicit, descriptive names - never single-letter or abbreviated variables (e.g., use sponsorship not s, event not e) -- Never use em-dashes (—) in code, comments, commit messages, or any - written output. Use a regular hyphen (-), a colon, or rephrase - with parentheses instead. - -Git commit style: -- Subject: present tense, imperative mood (add, create, test, fix) -- Subject: lowercase, short (3-6 words) -- Match subject patterns found in git history -- Add a body when the change needs explanation beyond the subject - - e.g., why the change was made, non-obvious tradeoffs, or notable - implementation details. Skip the body for trivial/self-evident commits. -- Separate subject and body with a blank line; wrap body at ~72 columns - -Git commits: -- Tests should be committed first, before implementation -- Group related changes together in a single commit (e.g., a new class - plus its registration, or a getter plus the property it exposes). - Avoid mixing unrelated concerns in one commit. -- Keep commits small and focused - prefer many small commits over few - large ones, but don't artificially split a single logical change - across multiple commits -- Commits are for reviewing and documenting the development of code -- Don't wait to commit - commit as you go - -Branch naming: -- Use kebab-case (e.g., node-page text-page) -- Use descriptive feature names -- NEVER work directly on master - always create and work on a branch - -Do not push anything. Make commits as you go. diff --git a/ai/shared.md b/ai/shared.md new file mode 100644 index 0000000..71256ea --- /dev/null +++ b/ai/shared.md @@ -0,0 +1,69 @@ +# Shared rules + +Rules that apply to both backend and frontend work in this repo. Stack-specific +guides (`backend-context.md`, `frontend-context.md`) extend these. + +## Process (TDD) + +0. Before editing any file, ensure you are on a feature branch + (`git status` to confirm). If on master/main, create a branch + first. +1. Write the test first +2. Run the test to confirm it fails +3. Commit the failing test (the "tests committed first" rule in + action - the test commit precedes the implementation commit, not + merely the implementation lines) +4. Implement the code to make the test pass +5. Run the test to confirm it passes +6. Commit the implementation +7. Repeat for each new behavior + +## Code style + +- Lines should not exceed 80 columns, but should use up to 80 columns when + possible - do not split lines unnecessarily +- Variable names: use explicit, descriptive names - never single-letter or + abbreviated variables (e.g. `$text` not `$t`, `$node` not `$n`) +- First, explore the codebase to understand existing patterns - look at similar + files for reference before writing anything +- Never use em dashes (—) in code, comments, or docblocks - use hyphens (-) + instead + +## Git commit style + +- Present tense, imperative mood (add, create, wire, fix, test) +- Lowercase +- Short (3-6 words) +- Match patterns found in git history +- Do not add any section mentioning claude as a coauthor +- Add a commit body when the subject alone cannot convey the change - e.g. + non-obvious motivation, multi-file coordination, or notable complexity +- Body: wrap at ~72 columns, separated from subject by a blank line, explain + the why and any non-obvious what +- Skip the body for trivial or self-explanatory commits + +## Git commits + +- Tests should be committed first, before implementation +- One logical change per commit - a commit may span multiple files when they + form a single logical unit (e.g. a use case with its request and exception, + or a template with its page-level JS) +- Keep commits focused: not one file per commit, not unrelated work batched +- Make commits frequent - commit each meaningful logical step as you go +- Commits are for reviewing and documenting the development of code +- When the formatter or linter modifies files outside your intended + change, either `git restore` them or land them as a separate + `format ` / `lint ` commit - never bundle drive-by + formatter churn into a feature commit +- If pre-commit lint fails on code you did not touch, do not bundle + the fix - either land the unrelated fix as its own commit first, or + note the pre-existing failure and proceed + +## Branching + +- Use kebab-case (e.g. `text-page`, `scheduled-node`, `auth-flow`) +- Use descriptive feature names +- Or use type/description: `feature/text-page`, `fix/bug-name` +- NEVER work directly on master/main - always create and work on a branch + +Do not push anything. Make commits as you go.