


Make a Coding Agent Follow a Large Full-Stack Repo's Contribution Rules
Use when an AI agent works in a large repo with typed frontend and backend code. It runs pre-commit checks before pushing, follows the patterns the repo is moving to, judges security issues by what each role may do, and keeps tests, docs, and pull requests in the project's format.
To use this AI rule
## Run the Pre-commit Checks Before Every Push
Always run the repository's pre-commit suite across all files before pushing commits. Continuous integration fails when pre-commit checks fail, so this is a non-negotiable gate, not a preference.
How to run it efficiently:
- Stage changes first. Pre-commit inspects staged files only, so an unstaged edit is silently skipped.
- For a fast inner loop, run the suite on staged files, or run a single named hook (type checker, formatter, linter). Run the full-file pass before the push that opens or updates a pull request.
- Activate the project's virtual environment or toolchain shell before running. Common locations differ per developer; if the command is not found, ask the user which environment to activate instead of guessing a path.
- Some hooks auto-fix (formatters, trailing whitespace). Re-stage the fixed files and re-run, because the first run reports failures it has already repaired.
Expect three failure classes: formatting issues that auto-fix, type-checker errors that need manual fixes, and lint errors that need manual fixes.
## Write New Code in the Patterns the Repo Is Moving To, Not the Old Ones
Several migrations are actively in flight. Code that matches the old pattern still exists, so its presence is not permission to write more of it. New and modified code follows the target pattern.
- Typed frontend: no escape-hatch `any` types, and no new untyped script files — write in the typed dialect and reuse existing type definitions.
- Shared component layer: import UI components from the project's own design-system package rather than the third-party library directly, prefer the design-system's theming tokens over legacy ones, and avoid bespoke CSS in favor of the component library's supported styling.
- Test pyramid: prefer unit tests over integration tests, and integration tests over end-to-end tests. Write new end-to-end tests in the adopted framework; the superseded end-to-end framework is deprecated and will be removed once the migration completes.
- Backend typing: all new code carries type hints, models use proper annotations, and the type checker must pass.
- Identifier migration: new models use opaque unique identifiers as primary keys, public APIs expose those identifiers instead of internal sequential integers, and existing models gain the new identifier alongside the integer one for a gradual cutover.
## Judge Security Issues by What Each Role Is Allowed to Do
Before evaluating any code path for security issues, read the repository's canonical security policy document. It is the authoritative source for the security model and is what both human reporters and automated scanners are measured against.
The single test for whether a finding is in scope: does it let a principal perform an action that the role and capability matrix in the security policy does not entitle them to? If yes, it is in scope. If no, it is not.
Three trust boundaries frame that test:
1. The administrator role is a fully trusted operational principal. Anything an administrator can do through documented configuration, API, or UI is an intended capability, not a vulnerability.
2. The operator owns deployment-time decisions: secrets, network exposure, feature-flag selection, connector and codec choices, notification destinations, and third-party plugins. Misconfiguration at this layer is a deployment defect, not a product vulnerability.
3. The codebase is responsible for enforcing the role and capability matrix everywhere it exposes functionality to a principal — API routes, command and data-access layers, UI handlers, background jobs, and every other entry point. A missing or incorrect enforcement check is in scope no matter where it lives.
The model assumes operator-controlled infrastructure — metadata database, caches, message brokers, secret stores, deployment environment — stays inside the operator's trust boundary. A valid finding must demonstrate a boundary violation by an attacker who does not already control those systems.
## Use the Right Permission Check for Each Route and Kind of Data
Route-level authorization uses one decorator per route class, and the correct one depends on the kind of route: one for the modern REST API surface, one for legacy JSON view routes, and one for legacy HTML view routes. Mixing them up is an enforcement bug even when a check appears to be present.
Object-level authorization is a second, separate gate. It applies to data-bearing resources — dashboards, charts, datasets and data sources, queries, database and table access, and query contexts — and is invoked per object through the security manager's access check. Code that omits the per-object gate on a route that returns or mutates a specific data-bearing object is in scope.
Other resources — annotations, tags, style templates, reports, row-level-security rules, and similar — deliberately rely on the route-level decorator plus ownership scoping in the data-access layer's base filters. The absence of a per-object check on these resources is by design and is not a finding.
Following the correct authorization pattern for a resource class does not clear the code of other issues. Injection, server-side request forgery, cross-site scripting, and similar classes are unrelated to authorization and are evaluated separately.
## Make Automated Scanners Name the Broken Rule and the Attacker's Role
Automated scanners — model-based code scanners, static analyzers, and dependency tools — must, in every finding they file against this codebase, name two things explicitly:
1. The specific row of the role and capability matrix in the security policy that the finding believes is violated.
2. The principal the finding assumes the attacker holds: an anonymous or public principal, a low-privilege authenticated role, a query-tool role, an elevated authoring role, the administrator role, an embedded guest token, or a named custom role with explicit capability grants.
A finding that cannot identify both must be filed as a question, not as a vulnerability. This requirement exists so that every reported issue is testable against the published security model, and so that speculative or pattern-match-only reports stay out of the triage queue.
## Follow the Repo's Frontend and Backend Code Standards
Frontend: avoid `any` and reuse existing types; write functional components with hooks; take UI components from the shared design-system package rather than importing the third-party library directly; use the project's standard test runner and testing library, not the removed legacy renderer; use the global store where it already exists and local hook state otherwise.
Backend: type hints are required for all new code, the static type checker must pass, data models carry proper typing, and the project's standard test framework is used for tests. When building queries, use the ORM's negation operator on a boolean column rather than comparing it to a false literal, which the linter flags.
License headers: new source files require the project's standard license header. Agent instruction files (this file and its per-vendor siblings) are deliberately excluded from that requirement to avoid spending tokens on the header.
Comments: avoid time-specific language such as "now", "currently", or "today", because it goes stale. Write comments that stay accurate whenever they are read.
## Update the Docs and Breaking-Change Notes Along with the Code
Documentation is part of the change, not a follow-up task:
- Update the documentation tree for any user-facing change.
- Record breaking changes in the dedicated upgrade-notes file so operators can find them in one place.
- Write docstrings for every new function and class.
When a change touches behavior an operator or end user can observe, a pull request without the matching documentation edit is incomplete.
## Fix Generated Component Docs in the Story Files, Not the Generator
The developer portal auto-generates component documentation from component-catalog stories. Stories are the single source of truth, which drives two rules: when something renders incorrectly, fix the story file first rather than the generator, and keep the generator lightweight — it extracts and passes through story data, so resist adding per-component special cases to it.
For a component's docs to generate correctly, its story file must:
- Export the metadata object inline as the default export rather than assigning it to a variable and exporting that variable.
- Name interactive stories with a consistent prefix plus the component name.
- Define default prop values in the story's arguments.
- Define argument types at the story level, not the metadata level, including control types and descriptions.
- Use the documented parameter keys for variant grids, sample children for components that need them, custom live code blocks, and complex object props that cannot be parsed inline.
Keep the generator script, its wrapper component, and the generated output directory in mind as the three moving parts when diagnosing a docs problem.
## Use the Repo's Test Helpers Instead of Writing Your Own Setup
The repository ships helpers; use them instead of hand-rolling setup. On the backend that means the shared test base class, decorators for mocking configuration and toggling feature flags, authentication helpers for logging in as a given role, and factory helpers for creating the fixtures a test needs. On the frontend that means the custom render helper that installs the standard providers, the wrapper factory for store, router, and theme, and the select-interaction helper.
Mocking rules: use a plain mock for configuration objects, and do not reach for an async mock when the code under test is synchronous. When a model gains a new field, update the expected-column lists in the API tests.
Know how to run each suite: the whole frontend suite, a single frontend test file, all backend tests, a single backend test file, a directory of backend tests, and the end-to-end suite in headless, interactive, headed, and debug modes.
If the backend tests fail because of database or environment setup rather than the code under test, ask the user to run the test environment setup instead of improvising fixes to their environment.
## Check the App's Health Endpoint Before Debugging
Run the quick setup check first: hit the application's health endpoint and confirm it responds before spending time on a bug report. A failed health check usually means the workspace was never set up, not that the code is broken.
If the health check fails, tell the user the environment does not look set up and point them to the project's documented setup instructions for working with agents, rather than attempting to repair their environment yourself.
Know the key project files when orienting: the frontend package manifest for build, test, and lint scripts and the development server port; the Python project file for linter and type-checker configuration; and the dependency requirements folder split into base and development sets.
## Fill In the Pull Request Template and Use Conventional-Commit Titles
When opening a pull request:
1. Read the current pull request template file in the repository before drafting. Always read the actual file rather than reusing cached content, because the template changes over time.
2. Fill in every section the template defines — summary, before and after evidence, testing instructions, and additional information.
3. Title the pull request using the conventional-commits format `type(scope): description`, for example `fix(dashboard): load charts correctly`. Valid types are `fix`, `feat`, `docs`, `style`, `refactor`, `perf`, `test`, and `chore`.
## Learn the Folder Layout and File Patterns Before Editing Unfamiliar Code
Two habits keep changes in the right place in a large repository. First, learn the directory map before editing: which tree holds the backend application, its API endpoints, data models, and connectors; which tree holds the frontend source and its component, chart-builder, dashboard, and query-editor areas; where the shared design-system package lives; and where tests, documentation, and the breaking-change log sit.
Second, know the recurring file patterns so a new feature lands in the conventional files: the API module for endpoints with their decorators and schema-generating docstrings, the schemas module for request and response validation feeding the generated API spec, the commands layer for business logic wrapped in transactions, and the models layer for persistence. Generated API documentation is derived from those docstrings and schemas, so an endpoint change without a docstring update silently degrades it.
Database migrations follow their own convention: they live in the migrations versions directory, are named with a timestamp, revision hash, and description, and should call the shared migration utility helpers rather than raw ORM operations so that they stay compatible across database engines.
Finally, note that this repository keeps parallel instruction files for different agent vendors. Keep them consistent when you change a rule that applies to all of them.
