AI-AGENTS.md
Project-specific instructions for AI agents. MUST be loaded at conversation start.
Discourse is large with long history. Understand context before changes.
pnpm for JavaScript, bundle for Rubyfrontend/discourse/app/form-kit)frontend/discourse/app/lib/load-*.js wrapper that does the import() (see load-morphlex.js)..skills/discourse-writing-rspec-tests when writing RSpec tests# JavaScript tests - bin/qunit
bin/qunit --help # detailed help
bin/qunit path/to/test-file.js # Run all tests in file
bin/qunit path/to/tests/directory # Run all tests in directory
bin/qunit --filter "Some text" # Case-insensitive substring match on "module: test name"
bin/qunit --filter "/Foo|Bar/i" # Slash-wrapped value is a regex (include the "i" flag); use for alternation
# Linting
bin/lint --fix path/to/file path/to/another/file
bin/lint --fix --recent # Lint all recently changed files
Run bin/lint --fix once after implementation is complete and before handing
off completed changes, committing, or pushing. During iterative edits, only run
lint when it helps diagnose an issue. Prefer passing the specific changed files;
use bin/lint --fix --recent only when appropriate.
config/site_settings.yml or config/settings.yml for pluginslib/site_setting_extension.rbSiteSetting.setting_name (Ruby), siteSettings.setting_name (JS with @service siteSettings)app/services (only classes with Service::Base)includes()/preload() (N+1), find_each()/in_batches() (large sets), update_all/delete_all (bulk), exists? over present?explain, specify columns, strategic indexing, counter_cache for counts.skills/discourse-migration before writing or reviewing any migrationhead :no_content for successful operations that don't return data
render json: success_json when returning confirmation data or when clients expect a response body{{}} (escaped) not {{{ }}}, sanitize with sanitize/cook, no innerHTML, careful with @htmllib/guardian.rb), POST/PUT/DELETE for state changes, CSRF tokens, protect_from_forgerycan_see?/can_edit? patterns. Use user.guardian shorthand not Guardian.new(user)