Skip to content

Latest commit

 

History

History
224 lines (169 loc) · 7.3 KB

File metadata and controls

224 lines (169 loc) · 7.3 KB
description General development guidelines for ado - code style, testing, quality checks, and commit standards

General Development Guidelines for ado

These guidelines apply to all code development in the ado codebase.

Code Structure

  • orchestrator: main Python package
    • schema: pydantic models for properties, entities, experiments, and measurement results
    • core: pydantic models and associated code for the core resource types managed by ado:
      • discoveryspace
      • operation
      • samplestore
      • datacontainer
      • actuatorconfiguration
    • modules/actuators: defines actuators, custom experiments, and their associated management code (plugins, registry)
    • modules/operators: defines operators and their associated management code (plugins, collections, orchestration)
    • utilities: common utilities
    • cli: ado CLI
    • metastore: code defining and interacting with the metastore, which stores core resource types
  • tests: unit and integration tests (pytest)
  • plugins: actuator, operator, and custom_experiment plugins
  • website: mkdocs website and documentation
  • examples: examples of using ado

Structure Guidelines

  • Place new code in the most specific existing subpackage.
  • Do not create new top-level packages unless explicitly instructed.

Code Style

  • Use PEP8 naming conventions for new code.
  • Exception: use camelCase for fields of pydantic models.
  • Do not modify existing names unless explicitly asked, even if they do not follow PEP8.
  • Use type annotations on all functions and methods, including return types.
  • Add docstrings to all functions and methods.
  • Use the pydantic annotated form for pydantic fields (see orchestrator/schema/entity.py). Assign the default value to the Annotated variable, not inside pydantic.Field. For any mutable default values such as dictionaries, lists, tuples, or sets, use default_factory inside pydantic.Field and do not assign a default to the Annotation.
  • Use discriminated unions when a type is a union (see ExperimentType in orchestrator/schema/experiment.py).
  • Use the Defaultable type from orchestrator/utilities/pydantic for pydantic fields that:
    • accept None, but
    • are always defaulted to a different type.
  • Use absolute imports within the repository unless the file already uses relative imports.
  • Use orchestrator.utilities.output.pydantic_model_as_yaml for serializing pydantic models to YAML.
  • Use Google style for docstrings.

Developer Tools

  • All development tools (ruff, black, pytest, etc.) are available in the project's uv-managed virtual environment.

  • Do not install tools globally.

  • Use the following pattern to execute tools:

    uv run TOOLNAME


Code Development

Use Test Driven Development

  • For changes to existing code: First search for tests that call this code and update them so the new behaviour is tested
  • For new functionality: Write tests first
  • Run pytest: confirm tests fail
  • Implement the code to be tested
  • Run pytest: check tests
  • Iterate until tests pass

Writing Tests

  • Check for existing fixtures before creating new ones:
    • tests/fixtures/
  • Do not mock by default; prefer integration tests.
    • Search for existing fixtures that provide same functionality
    • If you really feel a mock is correct, confirm with the user before implementing
  • Test the full lifecycle for pydantic models: create → dump → create from dump

Code Linting

  • Linting must be run after any code changes and must pass before running tests.

  • Run black after changes:

    uv run black $DIR

  • Run ruff after changes:

    uv run ruff check --fix $DIR

  • Fix any issues reported by ruff that it could not fix automatically.

  • Run black and ruff at directory level for efficiency (e.g. orchestrator/, plugins/, tests/).

  • Run the mkdocs linter on markdown files (*.md) that have added or modified:

    uv run markdownlint-cli2 NEW_OR_CHANGED_MARKDOWN_FILE --fix

  • Run if YAML changed or added

    pre-commit run yamlfmt

  • Run if TOML changed or added

    uv run tombi fmt


Code Installation & Execution

The project has a top-level virtual environment managed by uv. Plugins and examples within the repo are also uv managed and may have venvs.

When installing packages, install into the top-level virtual environment. When executing code with uv, including pip, execute from the top level of this repo. This is to avoid accidentally using the local uv environments of plugins and examples within the repo.


Testing

Code Testing

  • Each subpackage has a corresponding test directory under tests/, for example:

    • tests/schema/
    • tests/core/
    • tests/actuators/
    • tests/operators/
    • tests/metastore/
    • tests/cli/
  • Test files are often named after the class or concept being tested. For example, MeasurementResult (defined in result.py) is tested in test_measurement_result.py. When changing a class, look for a test file whose name matches the class name before grepping.

  • To find all tests relevant to a change, search by the name of each modified function, method, or field

  • As a final validation step after a change, run tests for all impacted subpackages.

  • All tests must pass before submitting changes.

  • Ensure the virtual environment is correctly set up before running tests:

    uv sync --reinstall --group test --group dev

  • Run tests in parallel (pytest-xdist) for quicker execution e.g.

    uv run pytest -n auto tests/

YAML Testing

  • Test any new or modified ado resource YAML using:

    uv run ado create RESOURCETYPE -f FILE --dry-run

ado CLI command-line construction and testing

  • Confirm all ado CLI commands and options written in documentation are correct

    uv run ado [COMMAND] --help uv run ado [COMMAND] [SUBCOMMAND1] ... --help

  • Leverage the --use-latest ado CLI command arg when writing documentation if an "ado create" or "ado show" command requires the identifier of a previously created resource


Agent Skills

When writing agent skills:

  • Be brief and to the point
  • Avoid ambiguous statements
  • Skills should be instructions on how to perform a specific task
  • Avoid duplication - before writing check the following sources and link existing relevant data
    • all skills under .cursor/skills/
    • the examples under examples/
    • the documentation under website/docs/
  • After writing a new skill:
    • review if any information is more appropriate in an existing skill, rules or AGENTS.md, if so move it there
    • verify all file and directory paths referenced, exist in the repo
    • check each section is within the scope declared in the skill's description field
  • When creating YAML or code examples, prefer:
    • using an external file
    • linking it or including its contents in SKILL.md
    • write tests for such files
  • Ensure the metadata of the skill is sufficient so it triggers when likely to be required

Links