Contributing to openadapt-flow

August 26, 2026 · View on GitHub

Thanks for your interest in improving openadapt-flow. This project compiles a recorded GUI demonstration into a deterministic, self-healing, locally-run script — so correctness, determinism, and honest measurement matter more here than raw feature count.

Development setup

git clone https://github.com/OpenAdaptAI/openadapt-flow && cd openadapt-flow
python -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'
playwright install chromium
pytest -q

Python 3.10–3.12 are supported and exercised in CI.

The checks CI runs (run them locally first)

ruff check openadapt_flow          # lint
ruff format --check openadapt_flow # format (drop --check to auto-apply)
mypy                               # type-check (config in pyproject.toml)
pytest -q                          # tests
  • Lint/format: ruff. Config lives in [tool.ruff] in pyproject.toml.
  • Types: mypy runs on the core package (not tests). It is deliberately lenient today; a set of modules with known type debt is listed under [[tool.mypy.overrides]]. Improving a module's annotations and removing it from that list is a very welcome PR.
  • Coverage: CI reports coverage for visibility. There is no hard floor yet, but new code should come with tests.
  • Repository tree: a test must never write into the checkout. The session hooks in tests/conftest.py snapshot the tracked-file status before the first test and after the last one, and fail the run when a new entry appears, because a regenerated golden can be committed by accident and scripts/check_release_consistency.py pins a reviewed SHA-256 inventory of the public files. Write to tmp_path (copy a fixture bundle there first) instead. The check reports any tracked file that changed during the run, so editing files yourself while a long suite runs also trips it — set OPENADAPT_FLOW_ALLOW_DIRTY_TREE=1 for that case.

CI execution lanes

Every pull request and push to main runs the required safety, unit, browser E2E, native-platform contract, type, PHI, documentation, interoperability, and package checks. The complete Python 3.10–3.12 Linux matrix plus macOS suite is intentionally a second lane: it runs nightly and as an explicit release qualification, avoiding four redundant full-suite jobs on every routine merge without reducing the required merge or exact-main gates.

Prepare each release in a reviewed pull request. Update the version in pyproject.toml, openadapt_flow/__init__.py, and the editable root entry in uv.lock. Add the matching CHANGELOG.md section, then run the package and claims checks:

python scripts/check_release_consistency.py
python scripts/validate_claims.py --check --structure-only
uv build --wheel --sdist
python scripts/check_release_consistency.py --require-dist

After that pull request merges, dispatch the full matrix on the exact candidate ref:

gh workflow run ci.yml --ref <candidate-ref>

Wait for all four test-matrix jobs and the unchanged required jobs to pass. Then create the reviewed version tag from protected main:

gh workflow run release.yml --ref main -f version=<reviewed-version>

The release App can push that annotated tag. It can't push a version commit to main. The tag run rebuilds the package, repeats the source, license, and claims checks, publishes through PyPI Trusted Publishing, and compares the public artifact digests with the local build. If a publication step fails, rerun the same tag run. Don't create a recovery tag.

Pull request guidelines

  • Conventional Commits for titles and commits: feat:, fix:, perf:, docs:, ci:, chore:, refactor:, test:. Releases are automated from these — feat: → minor, fix:/perf: → patch, BREAKING CHANGE → major.
  • Keep PRs focused. Separate mechanical changes (formatting, renames) from behavior changes so review stays legible.
  • Add or update tests for any behavior change. The suite mocks browsers/servers where it can, so most of it runs with no live VM.
  • Update docs (README.md, DESIGN.md, docs/) when behavior or contracts change. Bind capability claims to exact evidence and qualification boundaries. Product state comes only from active release admissions. Do not add a static lifecycle label for a product target.

Licensing and vendored files

openadapt-flow package artifacts are MIT-licensed. Do not copy, adapt, vendor, embed, or redistribute GPL, AGPL, LGPL, SSPL, source-available, or field-of-use-restricted material in the wheel or source distribution without explicit reviewed approval from qualified licensing counsel.

OpenAdapt-specific non-negotiable: do not ship AGPL benchmark files in a PyPI wheel or sdist. The openIMIS reference environment and any other copied or adapted AGPL benchmark material must remain repository-only or be obtained through a pinned, hash-verified, opt-in upstream fetch.

Running or automating an external copyleft application is not the same as redistributing its source. For reference environments, prefer an opt-in fetch of the exact pinned, hash-verified upstream project. If repository-only benchmark material has a different file-local license, preserve its full license, provenance, modification notice, and source hashes, and exclude the entire surface from permissively licensed package artifacts.

The release-consistency gate inspects the actual wheel and sdist. A source-tree notice alone is not sufficient.

Safety-sensitive areas

The identity gate, the resolution ladder, and the postcondition/halt logic are the safety core: the whole value proposition is that the tool halts instead of acting on the wrong target. Changes there deserve extra tests (see the test_identity_*, test_resolver*, and *_fuzz suites) and a clear explanation of why the never-false-accept invariant still holds.

Reporting security issues

See SECURITY.md — do not file security problems as public issues.

Code of Conduct

This project follows the Contributor Covenant.