Contribution guide¶
Thank you for your interest in contributing to data-director, a reference implementation of the
Research Data Alliance's Data Director Agentic AI Blueprint.
The organisation-wide contribution guide
applies here: when to open an RFC, the Developer Certificate of Origin sign-off (git commit -s)
and the pull request workflow. Governance
and the code of conduct
are also organisation-wide. This file covers what is specific to this repository.
Contributing without writing code¶
Much of what the project needs is judgement rather than code: whether advice is right for a discipline, whether a decision suits an institution, whether a requirement is met. Each has an issue form, chosen when you open an issue:
- Conformance review: you examined a Blueprint requirement, such as accessibility (C6) or the appropriateness of standards advice (R3), and found it met or not met. A maintainer records it in the review record on your instruction (the conformance report).
- Spec feedback: a question about, or objection to, how one of the specifications says Data Director is built.
- Blueprint reading: the project reads a Blueprint requirement differently from you, or misses one.
- Feedback on advice: an agent's advice was wrong, incomplete or unhelpful, and you can say what good advice would have been.
Repository structure¶
This repository is organised as follow:
docs/contains what governs every package: the Blueprint, the specifications (docs/specs/), the contract, the glossary, the requirements register and the review record. A package's own documents are in its owndocs/(harness/docs/,workbench/docs/)app/contains the Data Director app that people use (alpha); its browser shell inapp/webneeds Node 22 or later and npm (app/README.md)sdk/contains what agents and the harness share: the contract, evidence and the agent serverharness/contains the governance every agent invocation goes through (System and boundaries)workbench/contains the development environment for building and testing sub-agentsagents/contains one package per agent, including alpha-versioned experimental ones (agents/README.md)
Each package keeps to its own directory, so that it can later move to a repository of its own. Agent Skills, MCP servers and other resources that do not use the contract belong in their own repositories in the organisation. System and boundaries sets out both.
Changing the design¶
A specification states how one part is meant to work today, so a change to
the design changes its spec in the same pull request, edited to say what is now true rather than
amended. A change to a fixed format (the schema, the dd.* trace attributes, evidence
canonicalisation or the outcome vocabulary) always changes a spec. An issue that proposes one
carries the needs spec label. The history of the repository, its pull requests and its RFC
issues are the record of how the design got here; the spec is the result.
Code style and testing¶
The Python packages use Python 3.14 and uv; app/web uses Node 22
and npm. uv run scripts/dev.py setup installs both sides and uv run scripts/dev.py doctor
says what is wrong with a setup (README, "Quick start"). Follow the conventions of the surrounding
code, and describe how you tested your change in the pull request description.
Every pull request runs .github/workflows/ci.yml, which ends in one check, CI passed, that
passes only when every other job has. Each job can be run locally from the repository root:
| Job | Locally |
|---|---|
| Ruff (lint + format) | uv run ruff check . && uv run ruff format --check . |
| mypy | uv run mypy |
| pytest | uv run pytest --json-report --json-report-file=.report.json |
| CONFORMANCE.md is current | uv run python scripts/conformance_report.py --check (after pytest, which writes .report.json) |
| Generated schemas up to date | uv run dd-gen-schema && git diff --exit-code -- sdk/src/dd_sdk/schema/generated/ |
| Packages build and install alone | uv build --all-packages -o dist && uv run python scripts/check_wheels.py dist |
| Agents as services (smoke) | uv run python scripts/smoke_agents.py |
| Workbench viewer in a browser | uv run playwright install chromium && uv run pytest workbench/browser_tests |
| App shell | in app/web: npm ci && npm run lint && npm run typecheck && npm test && npm run build && npm run e2e |
| Links and citation file | lychee --offline --include-fragments '**/*.md', uvx cffconvert --validate, uv run scripts/check_citation.py, scripts/check_todos.py and scripts/check_boundaries.py |
| Workflows | uvx zizmor .github and actionlint |
| Developer Certificate of Origin | every commit signed off by its author: git commit -s |
| Dependency review | a new dependency with a known advisory of moderate severity or worse is refused |
.github/workflows/accessibility.yml checks what people read and use against WCAG 2.2 AA, with
axe-core and reflow at 320 CSS pixels, and ends in its own check, Accessibility passed:
| Job | Locally |
|---|---|
| Documentation site | uv run --only-group docs mkdocs build --strict && uv run --only-group docs --only-group accessibility scripts/check_site_accessibility.py site |
| Workbench viewer | uv run pytest workbench/browser_tests/test_viewer_accessibility.py |
The app shell's accessibility checks run in the App shell job of ci.yml.
The pytest suite blocks the network and needs no credentials. CONFORMANCE.md is generated;
regenerate it with the same two commands without --check. CodeQL (codeql.yml) analyses the
Python, JavaScript and TypeScript code and the workflows, and audit.yml checks every locked
dependency against the advisory databases each day. Dependabot proposes updates weekly.
Pull request titles and branch names¶
A pull request is squash-merged, so its title becomes the commit subject on main, and
release-please reads that subject as a Conventional Commit
to decide each package's next version and its changelog. names.yml checks every pull request
and runs again when the title is edited:
- the title is
type(scope)!: summary.typeis one ofbuild,chore,ci,docs,feat,fix,perf,refactor,revert,styleortest;(scope), usually the package (app,harness,sdk), and!, for a breaking change, are optional. The summary starts in lower case unless its first word is a name or acronym, has no closing full stop, and the whole title is at most 90 characters:feat(app): register every in-tree agent - the branch is lower-case words joined by hyphens, optionally grouped with slashes, in at most
60 characters:
ci-faster,harness/run-store
Dependabot's and release-please's pull requests are exempt. Check a title and branch locally:
python3 scripts/check_names.py --title "feat(app): history tab" --branch "$(git branch --show-current)"
Keeping uv.lock current¶
uv.lock records every workspace package's version and dependencies, so any branch that changes
a pyproject.toml changes it too, and two such branches conflict. The uv-lock pre-commit hook
re-locks whenever a pyproject.toml changes, so the lock never lags behind and CI's locked check
never fails for that reason. Install it once:
uv tool install pre-commit && pre-commit install
Never resolve a uv.lock conflict by hand. Take the base branch's file and lock again:
git checkout origin/main -- uv.lock && uv lock && git add uv.lock
then continue the rebase or merge. Release pull requests are re-locked by release-please.yml.
Releases¶
RELEASING.md describes the versioning policy, how release-please makes a release and what to do when it goes wrong. A pull request needs nothing more than a Conventional Commit title; release-please reads it.
Credit¶
Everyone who authors or co-authors a commit is cited as an author of the software. In your first
pull request, add yourself to authors in the citation file, with your ORCID
and affiliation if you have them:
- given-names: Ada
family-names: Lovelace
email: ada@example.org
affiliation: University of Example
orcid: 'https://orcid.org/0000-0000-0000-0000'
scripts/check_citation.py runs in the "Links and citation file" job and lists anyone missing.
It matches the email address of each commit's author, and of each Co-authored-by: trailer,
against email, or the name against given-names and family-names. If you commit under
several names or addresses, add a line to .mailmap that maps them to the one in
the citation file. Bots and AI assistants are not cited; the project's AI usage statement discloses their use instead. Run it locally in a full clone:
uv run scripts/check_citation.py