Skip to content

Latest commit

 

History

History
124 lines (97 loc) · 5.38 KB

File metadata and controls

124 lines (97 loc) · 5.38 KB

AI Coding Agent Guide

Project-specific instructions for AI agents. MUST be loaded at conversation start.

Default Mode

  • Architect mode enabled by default: detailed analysis, patterns, trade-offs, architectural guidance
  • Stop and ask for context if unable to write code meeting guidelines

Development Rules

Discourse is large with long history. Understand context before changes.

All Files

  • Always lint changed files
  • Create subagent to review changes against this file after completing tasks

Toolset

  • Use pnpm for JavaScript, bundle for Ruby
  • Use helpers in bin over bundle exec (bin/rspec, bin/rake, bin/lint)

JavaScript and UI

  • No empty backing classes for template-only components unless requested
  • Use FormKit for forms, see ./docs/developer-guides/docs/03-code-internals/21-form-kit.md (frontend/discourse/app/form-kit)
  • Use BEM for CSS, see ./docs/developer-guides/docs/03-code-internals/25-css-guidelines-bem.md
  • Make display strings translatable (use placeholders, not split strings)
  • Use "Sentence case" for strings, not "Proper Case" or "lower case"

JSDoc

  • Do not add JSDoc to any new code you write.
  • If JSDoc already exists, ensure any changes you make keep it accurate and up to date.

Testing

  • Do not write unnecessary comments in tests, every single assertion doesn't need a comment
  • Don't test functionality handled by other classes/components
  • Don't write obvious tests
  • Ruby: use fab! over let(), system tests for UI (spec/system), use page objects for system spec finders (spec/system/page_objects)

fab! Syntax

  • fab!(:user) - creates object using Fabricator defaults (name matches fabricator)
  • fab!(:user_1, :user) - preferred when variable name differs from fabricator, no custom attributes
  • fab!(:user) { Fabricate(:user, username: "some_username") } - with block for custom attributes

Page Objects (System Specs)

  • Located in spec/system/page_objects/pages/, inherit from PageObjects::Pages::Base
  • NEVER store find() results - causes stale element references after re-renders
  • Use has_x? / has_no_x? patterns for state checks (finds fresh each time)
  • Action methods find+interact atomically, return self for chaining
  • Don't assert immediate UI feedback after clicks (tests browser, not app logic)

Commands

Ruby RSpec tests

To run all RSpec examples in file use bin/rspec <path>. Example:

bin/rspec spec/path/file_spec.rb

To run one or more RSpec examples or groups, append the line number to the path. bin/rspec <path>:<line_number>. Example:

bin/rspec spec/path/file_spec.rb:123

JavaScript 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

Linting

# Linting
bin/lint path/to/file path/to/another/file
bin/lint --fix path/to/file path/to/another/file
bin/lint --fix --recent # Lint all recently changed files

ALWAYS lint any changes you make

Site Settings

  • Configured in config/site_settings.yml or config/settings.yml for plugins
  • Functionality in lib/site_setting_extension.rb
  • Access: SiteSetting.setting_name (Ruby), siteSettings.setting_name (JS with @service siteSettings)

Services

  • Extract business logic (validation, models, permissions) from controllers
  • docs/developer-guides/docs/03-code-internals/19-service-objects.md
  • Use the skill at .skills/discourse-service-authoring
  • Examples: app/services (only classes with Service::Base)

Database & Performance

  • ActiveRecord: use includes()/preload() (N+1), find_each()/in_batches() (large sets), update_all/delete_all (bulk), exists? over present?
  • Migrations: rollback logic, algorithm: :concurrently for large tables, deprecate before removing columns
  • Use bin/rails generate migration for new migrations
  • Queries: use explain, specify columns, strategic indexing, counter_cache for counts

HTTP Response Codes

  • 204 No Content: Use head :no_content for successful operations that don't return data
    • DELETE operations that successfully remove a resource
    • UPDATE/PUT operations that succeed but don't need to return modified data
    • POST operations that perform an action without creating/returning resources (mark as read, clear notifications)
  • 200 OK: Use render json: success_json when returning confirmation data or when clients expect a response body
  • 201 Created: Use when creating resources, include location header or resource data
  • Do NOT use 204 when:
    • Creating resources (use 201 with data)
    • Returning modified/useful data to the client
    • Clients expect confirmation data beyond success/failure

Security

  • XSS: use {{}} (escaped) not {{{ }}}, sanitize with sanitize/cook, no innerHTML, careful with @html
  • Auth: Guardian classes (lib/guardian.rb), POST/PUT/DELETE for state changes, CSRF tokens, protect_from_forgery
  • Input: validate client+server, strong parameters, length limits, don't trust client-only validation
  • Authorization: Guardian classes, route+action permissions, scope limiting, can_see?/can_edit? patterns

Knowledge Sharing

  • ALWAYS persist information for ALL developers (no conversational-only memory)
  • Follow project conventions, prevent knowledge silos
  • Recommend storage locations by info type
  • Inform when this file changes and reloads