Usage guide (complete)
Synced verbatim from the repo on every site build. Edit the source file on GitHub (link in the page footer); do not edit the rendered copy here.
Prerequisites
- Claude Code installed and running
- A workspace folder that will contain all your project’s services
Setup (once per workspace)
1. Clone this repo into your workspace:
workspace/└── ai-standards/ ← clone here2. Copy the commands and skills folders to your workspace root:
cp -r ai-standards/.claude/commands .claude/commandscp -r ai-standards/.claude/skills .claude/skillscommands/makes all slash commands available in Claude Code (e.g./init-project,/create-specs).skills/gives agents on-demand access to narrow playbooks (CORS setup, safe migrations, JWT lifecycle, Vitest patterns, etc.). Claude auto-loads each skill only when it matches the file or task at hand — zero cost when not needed. See skills reference below.
Re-run the cp commands when ai-standards updates its skills or commands. For a live link (edits in ai-standards instantly reflected), replace cp -r with a symlink: ln -s ../ai-standards/.claude/skills .claude/skills.
3. Initialize your project:
/init-projectThe agent will ask for your project name and list of services, then create the project-docs folder and install the Agent model-tier enforcement hook into .claude/settings.json (source: templates/agent-model-hook.json; rationale in CLAUDE.md → “Agent model tiering”). Result:
workspace/├── ai-standards/│ └── workspace.md ← local config (gitignored) — all agents read this├── {project-name}-docs/│ ├── services.md ← your project catalog│ ├── decisions.md ← architecture decisions (populated by Spec Analyzer)│ ├── design-decisions.md ← frontend design decisions (populated by Frontend Developer)│ ├── workspace.md ← local workspace config — all agents read this│ ├── workspace.mk ← Makefile variables (service lists)│ └── lessons-learned/ ← per-project agent mistakes, split by back.md / front.md / infra.md / general.md└── (your services...){project-name}-docs/workspace.md is the single source of truth for project paths. Every agent discovers it via the pointer file ai-standards/.workspace-config-path (gitignored, one line — created by /init-project). That pointer is the only project-specific file inside ai-standards/; everything else lives in the docs repo.
Every service you create must have a CLAUDE.md pointing to ai-standards. Use this as the template:
## StandardsRead `ai-standards/CLAUDE.md` and the relevant `ai-standards/standards/*.md` before doing anything.4. Install Playwright MCP (enables live browser verification by the Tester):
The Tester agent drives a real browser — via the Playwright MCP server — to verify visual and interactive DoD items (full-viewport gradients, rendered error copy, light/dark parity, viewport-size checks). Without it, those items fall back to “requires human verification” and slow down every /build-plan loop.
Create .mcp.json at your workspace root (the folder that contains ai-standards/ and your services — not inside any repo):
{ "mcpServers": { "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest"] } }}Then reload Claude Code (close and reopen the session). On first use, npx downloads @playwright/mcp and Chromium (~150 MB, one-time). Verify with /mcp inside Claude Code — playwright should appear as connected.
The workspace root is intentionally outside version control in this layout, so this step is per-machine. If you set up a second machine (or a teammate joins), re-run step 4 there. The Tester agent definition (agents/tester-agent.md) and build-plan command already assume Playwright MCP is available and will instruct the subagent accordingly.
Upgrading ai-standards in an existing workspace
If you pulled a new version of ai-standards into a workspace that was already initialized (so /init-project will not run again), refresh the Agent model-tier enforcement hook by running this from the workspace root. The merge is idempotent — existing permissions and hooks for other matchers are preserved:
TARGET=".claude/settings.json"TEMPLATE="ai-standards/templates/agent-model-hook.json"if [ -f "$TARGET" ]; then jq -s ' .[0] as $existing | .[1].hooks.PreToolUse[0] as $new_hook | $existing | .hooks //= {} | .hooks.PreToolUse //= [] | .hooks.PreToolUse = (.hooks.PreToolUse | map(select(.matcher != "Agent")) + [$new_hook]) ' "$TARGET" "$TEMPLATE" > "$TARGET.tmp" && mv "$TARGET.tmp" "$TARGET"else mkdir -p .claude && cp "$TEMPLATE" "$TARGET"fiAfter the merge, open the /hooks menu in Claude Code once (or restart the session) so the harness picks up the change. Verify with jq '.hooks.PreToolUse[] | select(.matcher == "Agent")' .claude/settings.json.
Building a feature
Every feature follows the same four-step flow:
1. /create-specs
Describe the feature in plain business language. No technical details needed.
“I want users to invite others to a board by email”
The agent asks clarifying questions, warns about incompatibilities, and creates:
{project-name}-docs/specs/{Aggregate}/{feature-name}-specs.md2. /refine-specs
Point to the spec file created in step 1. The agent reads the codebase, fills in technical details, and produces:
{feature-name}-specs.md ← updated with architecture decisions{feature-name}-plan.md ← execution plan with agent phases{feature-name}-task.md ← Definition of Done checklist3. /build-plan
Point to the plan file. The agent orchestrates the full implementation:
- Spawns isolated subagents per phase
- Runs Backend + Frontend in parallel
- Runs reviewers in parallel, loops until approved
- Runs tests, loops until they pass
- Calls
/update-specsautomatically as the last step — syncs the spec with the code, distills the plan + task into an## As-built notessection, and retires the plan/task files (deleted onsimple/standardcomplexity; archived underspecs/_archive/{feature}/oncomplex). After a successful/build-plan, you should not need to call/update-specs.
4. /update-specs (rarely invoked manually)
/build-plan runs this for you on every successful feature. Call it manually only when:
- You edited the implementation directly (outside
/build-plan) and the spec is now stale. /build-planaborted mid-run and the spec was never closed — re-run/update-specspointing at the same spec so the plan and task are properly distilled and retired.- A later bugfix changed something documented in a previous
## As-built notes(rare — usually better to create a new-fix-specs.mdfeature instead).
The agent compares spec vs actual implementation, updates the spec to match, appends the
## As-built notes section, and deletes or archives the plan/task files.
Spec file lifecycle
Each feature produces a triplet under {project-name}-docs/specs/{Aggregate}/:
| File | Lifespan |
|---|---|
{feature}-specs.md | Permanent — durable contract, read by future features and agents. |
{feature}-plan.md | Ephemeral — deleted by /update-specs after simple/standard features; moved to specs/_archive/{feature}/ after complex features. |
{feature}-task.md | Same as the plan. |
The non-obvious rationale from plan + task (complexity choice, files explicitly excluded from
scope, deviations from the plan, test deltas) is distilled into an ## As-built notes section
appended to {feature}-specs.md before the plan/task are retired. That keeps the specs folder
lean while preserving what would otherwise be lost. INDEX.md marks archived features with 📦.
If you want to keep plan/task for a specific feature (e.g. to review before deletion), tell the
orchestrator during /update-specs — it will skip retirement but still update the spec and INDEX.
Commands reference
| Command | When to use | Invokes |
|---|---|---|
/init-project | Once, when starting a new project | — |
/create-specs | When you have a new feature to build | — |
/refine-specs | After create-specs, to produce the technical spec and plan | — |
/build-plan | After refine-specs, to implement the full feature | /update-specs (automatic, last step) |
/update-specs | Rarely by hand — see “When to run this manually” in commands/update-specs-command.md | — |
/check-web <url> | Manual on-demand audit of a deployed UI — find symptoms (5xx, 4xx, console errors, axe violations, deprecations), group them by inferred root cause, emit paste-ready /create-specs prompts. Read-only navigation, never submits forms or triggers destructive actions. Requires npm install once in scripts/check-web/. | Web Auditor agent |
Make commands (workspace-level)
The root Makefile in ai-standards/ orchestrates every service in the workspace using the BACKEND_SERVICES and FRONTEND_SERVICES lists from {project-name}-docs/workspace.mk (generated by /init-project; located via the .workspace-config-path pointer file). Run these from the ai-standards/ directory.
Lifecycle
| Command | What it does |
|---|---|
make infra-up | Starts shared infrastructure only (PostgreSQL, RabbitMQ, Mailpit) |
make infra-down | Stops shared infrastructure |
make up | Starts infrastructure first, then every service (docker compose up -d) |
make down | Stops every service, then the infrastructure |
make build | Rebuilds all service images |
make update | make build + make up (use after changing composer.json, Dockerfile, or any file in the Docker build context) |
Observability
| Command | What it does |
|---|---|
make ps | Shows container status for infrastructure + all services |
make logs | Tails infrastructure logs |
Tests
| Command | What it does |
|---|---|
make test | Unit + integration on every service |
make test-unit | Unit tests only |
make test-integration | Backend integration tests only (frontends don’t have integration tier) |
Quality gates
| Command | What it does |
|---|---|
make lint | PHP-CS-Fixer dry-run (backends) + ESLint + Prettier check (frontends) |
make static | PHPStan level 9 (backends) + vue-tsc --noEmit (frontends) |
make quality | lint + static + test — the full gate bar across the workspace |
Run make quality before a push. See standards/quality-gates.md for the full rules and templates/ for the installable CI / hook / Makefile assets per service.
Framework self-checks
| Command | What it does |
|---|---|
make smoke | Static checks over the ai-standards/ repo (agent model tier, command→agent wiring, skill folder/name drift, docs path refs, CLAUDE.md index coverage, reviewer checklist rule IDs). 0 tokens. Runs on every CI push. |
make smoke-dynamic | Local only. Runs /build-plan against a minimal fixture (tests/fixtures/standard/), intercepts the first Agent spawn, asserts the model tier + context-bundle invariants. Real API tokens. Run before cutting a release, or after changing commands/build-plan-command.md, any file under agents/, or standards/agent-reading-protocol.md. See tests/README.md. |
What’s NOT in the root Makefile
Per-service commands — make lint, make static, make quality — also exist inside each service directory after you install the quality snippets. The root targets iterate over services; the per-service targets run directly via docker compose exec.
Workspace structure (after setup)
workspace/├── .claude/│ ├── commands/ ← slash commands (copied from ai-standards/.claude/commands/)│ └── skills/ ← on-demand playbooks (copied from ai-standards/.claude/skills/)├── ai-standards/ ← this repo (standards, agents, commands, skills) + `.workspace-config-path` pointer├── {project-name}-docs/│ ├── services.md ← project service catalog│ ├── decisions.md ← architecture decisions (Spec Analyzer)│ ├── design-decisions.md ← frontend design decisions (Frontend Developer)│ ├── workspace.md ← workspace config — path source of truth for agents│ ├── workspace.mk ← Makefile variables (BACKEND_SERVICES, FRONTEND_SERVICES)│ ├── lessons-learned/ ← per-project agent mistakes (back / front / infra / general)│ │ ├── README.md│ │ ├── general.md│ │ ├── back.md│ │ ├── front.md│ │ └── infra.md│ └── specs/│ ├── INDEX.md│ ├── _archive/ ← complex features: plan + task preserved here after /update-specs│ │ └── {feature-name}/│ │ ├── {feature}-plan.md│ │ └── {feature}-task.md│ └── {Aggregate}/│ ├── {feature}-specs.md ← durable contract (with ## As-built notes after /update-specs)│ ├── {feature}-plan.md ← ephemeral — retired on /update-specs│ └── {feature}-task.md ← ephemeral — retired on /update-specs├── {service-1}/ ← your backend/frontend services├── {service-2}/└── ...Multi-developer use
The framework is designed for one developer per workspace at a time. The orchestrator, lessons-learned files, Phinx migration timestamping, and the model-tier hook all assume a single concurrent operator. Some scenarios still work in practice; others are untested. Be explicit about which one you are in.
No friction
- Two developers each running
/build-planagainst different services on different branches. - Reading specs, standards, and reference files in parallel — nothing in the framework writes to those during a feature.
Expected merge conflicts (normal git, not a bug)
When two developers complete features in parallel and merge to master, plain text-diff conflicts can appear in any append-only or shared file the project keeps under {project-docs}/:
- Per-domain notes the project chooses to maintain (e.g. lessons-learned files split by
back/front/general/infra, or whatever layout the project adopted) — append-only by convention; conflicts resolve cleanly by keeping both entries. {project-docs}/specs/INDEX.md— same append-only pattern.{project-docs}/services.md,{project-docs}/decisions.md,{project-docs}/workspace.md— touched only when the framework or services list changes; rarer.
These are normal git conflicts. Resolve them in the second-merger’s PR.
Concurrent state to be aware of
/check-webappends findings to{project-docs}/web-flows.md(the auditor’s append-only memo). Two parallel runs against the same checkout will produce a normal git merge conflict on that file — resolve like any append-only conflict by keeping both blocks. Two parallel runs against the same uncommitted working copy would collide in-memory (last writer wins on disk before either commits). Serialise the runs in that case, or each developer should work on their own branch.
Not supported / untested
- Two
/build-planruns on the same service at the same time. The model-tier hook is global per workspace, dev/test containers are per-service (so they share state when both runs hit the same service), and Phinx migrations following the project’sM_NNNN_*sequence-numbered convention will collide on the next free integer if both runs create one. Don’t rely on it. - Two
/update-specsruns on the same feature concurrently. The spec file is the single source of truth; last writer wins silently. - Concurrent edits to
ai-standards/itself (the framework repo). Treat upgrades as a single-operator event coordinated through release-please, not parallel work. - Branch naming collisions: two developers picking the same
feature/{aggregate}/{description}will conflict at push time. Coordinate branch names beforehand or include a dev identifier (feature/board/add-archived-flag-mario).
If a multi-dev scenario you care about is not listed here, treat it as “untested” — open an issue with the exact workflow before relying on it.
Standards reference
Standards are split into rules (concise, always loaded by agents) and reference (full examples, loaded conditionally).
| File | What it governs |
|---|---|
standards/invariants.md | Non-negotiable rules — read first by all agents |
standards/agent-reading-protocol.md | Canonical reading order for every agent (build-plan + standalone modes) |
standards/tech-stack.md | Authoritative versions (minimums, open to update) + upgrade procedure |
standards/backend.md | PHP/Symfony: architecture rules (concise) |
standards/backend-reference.md | Full code examples, configs, scaffold usage |
standards/backend-review-checklist.md | Closed list of verifiable rules consumed by the Backend Reviewer agent |
standards/frontend.md | Vue 3/TS: rules (concise) |
standards/frontend-reference.md | Full code examples, test patterns |
standards/frontend-review-checklist.md | Closed list of verifiable rules consumed by the Frontend Reviewer agent |
standards/security.md | Headers, CORS, JWT, rate limiting, input validation, XSS, redirect allowlist |
standards/secrets.md | Secret classification, project manifest, injection matrix, rotation, redaction |
standards/performance.md | Database indexing, pagination, N+1, response envelope, frontend perf budget |
standards/caching.md | HTTP cache headers, Redis keys/TTLs, invalidation, stampede protection |
standards/observability.md | OpenTelemetry tracing, RED metrics, health endpoints, SLO shape |
standards/logging.md | Structured JSON logs, Monolog config, sensitive-field redaction |
standards/api-contracts.md | URL versioning, OpenAPI as contract, breaking-change protocol, deprecation headers |
standards/data-migrations.md | Schema evolution strategy, expand-contract, backfills, zero-downtime deploy matrix |
standards/authorization.md | Voter pattern, Subject VO, tenant scoping, RBAC + ABAC hybrid model |
standards/i18n.md | Locale negotiation, UI strings vs content translations, fallback chain, plurals/dates/currency formatting, vue-i18n |
standards/gdpr-pii.md | Four-tier PII classification, encryption, DSAR + RTBF workflow, consent ledger, sub-processors, DPIA |
standards/attack-surface-hardening.md | OWASP Top 10 coverage, CSP/HSTS, CSRF, SSRF (SafeHttpClient), XXE/SSTI, lockout, bot, SBOM, container scan, gitleaks, DAST |
standards/llm-integration.md | LlmGatewayInterface Domain seam, prompt versioning, JSON schema, retries/circuit breaker, cost spans, PiiPromptGuard, tool-use loop |
standards/payments-and-money.md | Money VO (integer minor units + ISO 4217), append-only ledger, deterministic webhook idempotency, state machines, multi-party splits, reconciliation |
standards/file-and-media-storage.md | Bucket layout, presigned PUT/GET, magic-byte verification, antivirus state machine, video transcode pipeline, retention, observability |
standards/geo-search.md | geography(Point, 4326) storage, GiST indexes, Postgres FTS before any dedicated search engine, MatchScoreCalculator, score → label translation |
standards/audit-log.md | Append-only audit_log table, AuditLogProjector wiring, same-tx-or-outbox synchrony, mandatory entries on success AND denial, retention |
standards/feature-flags.md | Flag taxonomy (release / operational / experiment / permission), registry, FlagGatewayInterface Domain seam, sticky bucketing, removal procedure |
standards/analytics-readonly-projection.md | Four-tier projection model (T1 read-on-operational / T2 materialized / T3 replica / T4 warehouse), schema isolation, replica lag, mandatory Voter |
standards/pwa-offline.md | Four progressive levels (L0 SPA → L3 offline writes + push), Workbox-generated SW, manifest, IndexedDB never holding Sensitive-PII, push consent per category |
standards/digital-signature-integration.md | SignatureGatewayInterface Domain seam, modality (simple / advanced / qualified), versioned templates, SigningRequest state machine, signed-document document_sha256, signature-verify-before-parse webhooks |
standards/adr.md | Architecture Decision Record format — ID convention, status lifecycle, structure, when to write one |
standards/critical-paths/ | Curated rule subsets per feature kind (CRUD, auth, PII, payment, LLM, file upload, signature, geo-search, PWA, async handler, public-facing deploy) |
standards/new-service-checklist.md | Pre-commit checklist for new services |
standards/quality-gates.md | CI + pre-commit + Makefile quality rules (PHPStan L9, vue-tsc, tests) |
scaffolds/ | Copy-verbatim PHP classes (AppController, ApiExceptionSubscriber, LoggingMiddleware, SecurityHeadersSubscriber, Subject + Voter, Money + Currency + CurrencyMismatchException, SafeHttpClient + SsrfBlockedException, LlmGatewayInterface + LlmRequest + LlmResponse, AuditLogProjector, AssertMaxQueriesTrait + QueryCountMiddleware) |
templates/ci/ | GitHub Actions workflow templates (backend + frontend) |
templates/hooks/ | Git pre-commit hooks (backend + frontend) |
templates/makefile/ | Makefile quality snippets to drop into a service Makefile |
templates/agent-model-hook.json | PreToolUse hook that rejects Agent invocations without a model argument — installed by /init-project into .claude/settings.json |
.claude/skills/ | On-demand playbooks (see below) |
Skills reference
Skills are narrow, auto-loading playbooks. Claude reads only each skill’s description at session start (cheap) and loads the full body only when the active task matches. This replaces reading big reference files end-to-end.
| Skill | Activates when |
|---|---|
cors-nelmio-configuration | Configuring NelmioCorsBundle, adding a new frontend origin, debugging CORS preflight failures |
docker-env-reload | Editing .env / env_file; when env-var changes aren’t taking effect in a running container |
docker-frontend-deps-sync | Running npm install, adding/removing packages in a Dockerized Vue/Vite frontend |
shadcn-vue-component-add | Before/after npx shadcn-vue add <component> — to catch silent overwrites of unrelated files |
new-service-bootstrap | Scaffolding a new PHP/Symfony service (Kernel, bundles, routes, Flex cleanup, composer.lock sync) |
doctrine-migration-safe | Writing a Phinx migration — tables, columns, indexes, safe ALTER patterns |
symfony-messenger-async | Configuring buses, RabbitMQ transports, cross-service message contracts, consumer workers |
messenger-logging-middleware | Wiring LoggingMiddleware, configuring Monolog JSON-to-stdout, sensitive field redaction |
jwt-security | Implementing JWT auth, refresh-token rotation, httpOnly cookie storage, Lexik config |
rate-limiting-auth | Adding Symfony RateLimiter to login/register/password-reset/token-refresh endpoints |
vue-composable-mutation | Writing a Vue 3 composable with TanStack Query useMutation for write operations |
pinia-store-pattern | Creating/modifying a Pinia store — canonical setup-store shape, destructuring rules, reactive() in tests |
empty-loading-error-states | Writing a Vue page that renders server data — canonical loading / error / filtered-empty / initial-empty branches |
openapi-controller-docs | Adding #[OA\...] attributes on a Symfony controller — request body, response schemas, error envelope, security |
vitest-composable-test | Writing Vitest tests for composables, stores, pages (mocks, captured callbacks, jsdom shims) |
quality-gates-setup | Installing CI workflow, pre-commit hook, and Makefile quality targets in a new or existing service |
backend-finder-service-throw-on-miss | Writing or reviewing a service that locates an aggregate by id/email/slug — repository nullable, FinderService throws, one variant per class |
backend-service-placement-decision | Creating a new service class — Domain vs Application placement, one-public-method rule, naming convention |
backend-controller-handler-shape | Writing a new controller + command/query handler pair — thin controller, one-per-message handler, OpenAPI + ApiExceptionSubscriber wiring |
backend-voter-pattern | Adding an authorization-protected endpoint — Subject VO, tenant-scoping-first, isGranted-before-side-effect, audit log on grant AND deny |
backend-pii-write-flow | Implementing or reviewing an endpoint that stores personal data — single-commit checklist (migration + inventory + redaction + projector + tests) |
backend-async-failure-subscriber | Wiring a Symfony Messenger consumer’s failure path — WorkerMessageFailedEvent subscriber, idempotency time-bucket, exception unwrapping (BE-070..072) |
backend-cache-headers | Adding HTTP cache headers to a new GET endpoint — decision tree for Cache-Control / Vary / ETag, public vs per-user vs per-tenant |
frontend-perf-vite-budget | Configuring or reviewing the bundler’s chunk budget — initial JS / per-route / LCP image / virtualization / font-display |
All skills can also be invoked manually with /skill-name. See each skill’s SKILL.md for the full content.