Files
OpenShell/CONTRIBUTING.md
T
Evan LezarandJim Meyer d3bb26606f docs(triage): add triage duty tooling (#3082)
* Add triage duty tooling

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* docs(triage): surface dependabot prs early

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* docs(triage): keep local state untracked

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* docs(triage): clarify queue continuation order

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* docs(triage): remove playbook whitespace

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* docs(triage): address duty tooling review feedback

Signed-off-by: Jim Meyer <jimeyer@nvidia.com>

* docs(triage): minimize changes to original duty skills

Signed-off-by: Jim Meyer <jimeyer@nvidia.com>

---------

Signed-off-by: Evan Lezar <elezar@nvidia.com>
Signed-off-by: Jim Meyer <jimeyer@nvidia.com>
Co-authored-by: Jim Meyer <jimeyer@nvidia.com>
2026-10-14 15:18:46 +00:00

519 lines
31 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Contributing to OpenShell
OpenShell is built agent-first. We use agents to design and implement systems, while humans manage product decisions and the project roadmap.
## The Critical Rule
**You must understand your code.** Using AI agents to write code is not just acceptable, it's how this project works. But you must be able to explain what your changes do and how they interact with the rest of the system. If you can't, don't submit it.
Submitting agent-generated code without understanding it — regardless of how clean it looks — wastes maintainer time and will result in your PR being closed. Repeat offenders will be blocked from the project.
## AI Usage
OpenShell is agent-first, not agent-only. The distinction matters:
- **Do** use agents to explore the codebase, run diagnostics, generate code, and iterate on implementations.
- **Do** use the skills in `.agents/skills/` — they exist to make your agent effective.
- **Do** interrogate your agent until you understand every edge case and interaction in your changes.
- **Don't** submit code you can't explain without your agent open.
- **Don't** use agents as a substitute for understanding the system. Read the RFCs, crate READMEs, and published docs.
## First-Time Contributors
We use a vouch system. This exists because AI makes it trivial to generate plausible-looking but low-quality contributions, and we can no longer trust by default.
1. Open a [Vouch Request](https://github.com/NVIDIA/OpenShell/discussions/new?category=vouch-request) discussion.
2. Describe what you want to change and why.
3. Write in your own words. AI-generated vouch requests will be denied.
4. A maintainer will comment `/vouch` if approved, and the request discussion
will close automatically.
5. **Get vouched before opening a PR.** Once vouched, you can submit pull requests.
**If you are not vouched, any pull request you open will be automatically closed.** The PR and its discussion are preserved. Once vouched, open a new PR (preferred) or reopen the closed one. It cannot be held open or converted to a draft to bypass the check. Org members and collaborators with push access bypass this check.
### Finding Work
Issues labeled [`good first issue`](https://github.com/NVIDIA/OpenShell/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) are scoped, well-documented, and friendly to new contributors. Start there. If you need guidance, comment on the issue.
An open issue is not necessarily accepted or ready for implementation. Inspect the repository’s current `state:*` labels and ask a maintainer when its status is unclear. A direct user request authorizes an agent to perform the requested phase without changing the issue’s disposition.
## Before You Open an Issue
Search open and closed issues for the same need. Bug reports and feature requests must include:
1. **User Story:** attest that you personally use OpenShell and describe the specific use case and behavior you directly encountered or need. Agents must ask the human operator for this first-hand context before filing if it is missing.
2. **Problem Statement:** a concise summary of what is broken or missing in the current behavior.
3. **Impact / Why This Matters:** the consequences of the current behavior, the current workaround, and why that workaround is insufficient.
4. **Acceptance Criteria:** specific, observable outcomes that define success.
Feature requests must also propose a user-facing workflow and describe alternatives considered, including relevant OpenShell extension points. When an existing middleware, interceptor, provider, or other extension can satisfy the use case, prefer that path. Running another service alone is not grounds to dismiss it. For changes to configuration, CLI, SDK, or other user experience, include notional examples for human review. Bug reports must include reproduction steps using only an OpenShell deployment, the OpenShell version and relevant environment, and a small, redacted log excerpt when it materially clarifies the behavior. Do not install third-party tools solely to demonstrate reproducibility. Frame every issue entirely in terms of OpenShell.
The project includes optional [agent skills](#agent-skills) for using OpenShell and contributing to the repository. Use them when they help you, but summarize any useful result in your own words rather than pasting a diagnostic transcript.
### When to Open an Issue
- A workflow behaves differently from what you need or reasonably expect.
- OpenShell does not support an outcome that matters to your workflow.
- The available documentation or configuration does not explain how to complete a supported workflow.
- Security vulnerabilities must follow [SECURITY.md](SECURITY.md) — **not** GitHub issues.
### When NOT to Open an Issue
- General questions or open-ended discussion — use [GitHub Discussions](https://github.com/NVIDIA/OpenShell/discussions).
- Security vulnerabilities — follow [SECURITY.md](SECURITY.md) instead.
## Before You Submit a Change
Do not start substantial issue-backed work until a maintainer has accepted the issue, unless a maintainer directly asks you to investigate or implement it. Once the work is authorized, use your agent to investigate the current code and behavior. If the issue contains earlier diagnostics, verify them rather than relying on them.
Use agents and the repository skills as needed to understand the affected code, evaluate tradeoffs, implement the smallest coherent change, and verify it. The pull request should explain what changed and how it was tested; it should not substitute an agent transcript for the contributor's understanding.
Every pull request must be approved by someone listed in [MAINTAINERS.md](MAINTAINERS.md) before it can merge. This is enforced by the `OpenShell / Maintainer Approval` status check, which turns green once one of those reviewers approves. Reviews from other contributors are welcome and count toward the general approval requirement, but they do not satisfy this check.
Pull requests that touch the enforcement machinery itself — anything under `.github/workflows/`, `.github/actions/`, `MAINTAINERS.md`, `.github/CODEOWNERS`, or the enforcement scripts in `tasks/scripts/` — additionally require a code owner's approval, listed in [.github/CODEOWNERS](.github/CODEOWNERS). The status check reads its inputs from `main`, but a workflow triggered by a review runs the pull request's own copy of the workflow file, so GitHub's native code owner requirement is what keeps a change from disabling the gate that would have blocked it.
Maintainers are not requested automatically. If your pull request has been idle, ask for a reviewer in the pull request or in the CNCF Slack channel rather than waiting.
## Agent Skills
OpenShell keeps skills for using the product separate from skills for developing the repository.
### Skills for Using OpenShell
Public skills live in `skills/` and work without an OpenShell source checkout. Install them with `npx skills add NVIDIA/OpenShell`.
| Skill | Purpose |
| --- | --- |
| `openshell-cli` | CLI usage, sandbox lifecycle, provider management, and BYOC workflows |
| `debug-openshell-cluster` | Diagnose gateway deployment and health issues |
| `debug-inference` | Diagnose attached-provider inference, native endpoints, and migration from the retired managed endpoint |
| `generate-sandbox-policy` | Generate YAML sandbox policies from requirements or API documentation |
Public skills use `openshell --help` for installed command syntax and published OpenShell documentation for product concepts and configuration. They must not depend on repository-relative source or documentation files.
### Agent Skills for Contributors
Contributor and maintainer skills live in `.agents/skills/`. They are marked internal so the Agent Skills CLI excludes them from ordinary public discovery, but repository-aware agent harnesses can discover and load them natively. Internal metadata is a discovery filter, not an access-control boundary.
| Category | Skill | Purpose |
| --------------- | ------------------------- | --------------------------------------------------------------------------------------------------- |
| Contributing | `create-spike` | Investigate a problem, produce a structured GitHub issue |
| Contributing | `create-rfc` | Create RFC proposals from the repository template |
| Contributing | `build-from-issue` | Plan and implement work from a GitHub issue (maintainer workflow) |
| Contributing | `create-github-issue` | Create well-structured GitHub issues |
| Contributing | `create-github-pr` | Create pull requests with proper conventions |
| Reviewing | `review-github-pr` | Summarize PR diffs and key design decisions |
| Reviewing | `review-security-issue` | Assess security issues for severity and remediation |
| Reviewing | `fix-security-issue` | Implement an approved security remediation plan |
| Reviewing | `watch-github-actions` | Monitor CI pipeline status and logs |
| Reviewing | `launch-openshell-gator` | Launch and supervise OpenShell gator agents for issue and PR monitoring |
| Reviewing | `test-release-canary` | Dispatch and iterate on the Release Canary workflow that smoke-tests published artifacts |
| Maintenance | `release-openshell` | Pick the latest qualified prerelease and tag its commit as stable |
| Triage | `triage-issue` | Assess, classify, and route community-filed issues |
| Triage | `review-triage-queue` | Create a local, read-only queue report from GitHub intake |
| Triage | `apply-triage-action` | Apply, reject, or defer one explicitly selected triage recommendation |
| Platform | `helm-dev-environment` | Start and manage the local Kubernetes development environment |
| Platform | `tui-development` | Development guide for the ratatui-based terminal UI |
| Platform | `build-openshell-mxc-windows` | Maintain and validate the build-only x64 and ARM64 Windows MSVC lane |
| Documentation | `update-docs-from-commits` | Scan recent commits and draft doc updates for user-facing changes |
| Maintenance | `sync-agent-infra` | Detect and fix drift across agent-first infrastructure files |
| Reference | `sbom` | Generate SBOMs and resolve dependency licenses |
### Issue Workflow
Community issues move through triage, technical validation, and human acceptance. The repository's `state:*` labels record these stages. Follow [Label Discovery](#label-discovery) before applying or interpreting them; do not assume a fixed label list. An agent may assess evidence and request missing information. A maintainer decides whether to accept valid work and where it belongs on the roadmap.
A direct request to an agent authorizes the requested planning or implementation. A request to plan alone does not authorize implementation. For unattended work, inspect current state descriptions, maintainer assignments, and comments to determine the authorized phase. Technical validation alone does not authorize implementation. Check for an existing owner, branch, or PR before starting.
Do not file suspected vulnerabilities as public issues. Follow [SECURITY.md](SECURITY.md). Use the specialized security skills for authorized review or remediation.
### Label Discovery
Retrieve every page of repository labels and their descriptions:
```shell
gh api --paginate 'repos/{owner}/{repo}/labels?per_page=100' --jq '.[] | {name, description}'
```
The default `gh label list` output is limited to 30 labels. Do not treat that first page as the complete workflow definition. If a description is missing or ambiguous, check maintainer instructions and issue comments for the intended meaning. If it remains unclear, ask a maintainer to define it before changing the state or starting unattended work. Do not infer authorization from a label name alone.
When recording a triage outcome, replace the previous assessment state rather than accumulating assessment labels. Preserve maintainer acceptance, execution state, roadmap decisions, and unrelated labels.
## Prerequisites
Install [mise](https://mise.jdx.dev/). This is used to set up the development environment.
```bash
# Install mise (macOS/Linux)
curl https://mise.run | sh
```
After installing `mise`, activate it with `mise activate` or [add it to your shell](https://mise.jdx.dev/getting-started.html).
Shell setup examples:
```bash
# Bash
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
# Fish
echo '~/.local/bin/mise activate fish | source' >> ~/.config/fish/config.fish
# Zsh
echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc
```
Project requirements:
- Rust 1.94+
- Python 3.11+
- Docker (running)
### Z3 installation
The `openshell-prover` crate and standalone `openshell-prover-cli` binary link
directly against Z3. The `openshell-server` crate depends on the prover, and
the `openshell-gateway` binary crate depends on `openshell-server` in turn.
The `openshell-cli` crate does not depend on Z3. The Nix development shell
supplies Z3. For builds outside that shell on macOS and Linux, install the
system Z3 development package; `z3-sys` discovers it through `pkg-config`.
The linker uses the installed static or shared library. The Nix development
shell provides a static Z3 library.
```bash
# macOS
brew install z3
# Ubuntu / Debian
sudo apt install libz3-dev
# Fedora
sudo dnf install z3-devel
```
To build Z3 from source instead, enable `vendored-z3` (requires CMake and a C++
compiler):
```bash
cargo build -p openshell-prover --features vendored-z3
cargo build -p openshell-prover-cli --features vendored-z3
```
Local gateway image and E2E builds enable `vendored-z3` so their
copied gateway binaries do not need a shared Z3 library in the runtime image.
For x86-64 and ARM64 Windows MSVC builds, use one of these Z3 paths:
- Prebuilt Z3 (the default for `windows:*` tasks): `z3-sys` downloads the
pinned Z3 5.1.0 GitHub release for the target architecture on the first
build. Cargo reuses the extracted archive from its target directory. Windows
CI authenticates the GitHub API request with `READ_ONLY_GITHUB_TOKEN` and
preserves the archive in the architecture-specific Cargo target cache. For
cold local builds, you may set `READ_ONLY_GITHUB_TOKEN` to avoid anonymous
GitHub API rate limits.
- System Z3: point `Z3_LIBRARY_PATH_OVERRIDE` at the directory containing the
target-compatible MSVC Z3 library and `Z3_SYS_Z3_HEADER` at the full path to `z3.h`.
The `windows:*` tasks use this path automatically when `Z3_LIBRARY_PATH_OVERRIDE`
is set.
`openshell-prover` itself has no `bindgen`/`libclang` dependency, so building
just this crate does not require `LIBCLANG_PATH`:
```powershell
cargo build -p openshell-prover --target x86_64-pc-windows-msvc --features prebuilt-z3
```
### Windows full build
To build the full set of Windows binaries, including `openshell-gateway.exe`
and `openshell.exe`, use the `windows:build:x64` mise task instead of a
single-crate `cargo build`. It downloads the pinned prebuilt Z3 release by default. A
full build also compiles crates that use `bindgen` (e.g. the MXC driver on
Windows), so it requires `libclang.dll`; if LLVM is not on the default search
path, set `LIBCLANG_PATH` to the directory containing `libclang.dll`:
```powershell
$env:LIBCLANG_PATH='C:\Program Files\Microsoft Visual Studio\2022\<Edition>\VC\Tools\Llvm\x64\bin'
mise run --skip-tools windows:build:x64
```
To use a local x64 Z3 release instead of the prebuilt download, set
`Z3_LIBRARY_PATH_OVERRIDE` and `Z3_SYS_Z3_HEADER` before running the task:
```powershell
$env:Z3_LIBRARY_PATH_OVERRIDE='C:\path\to\z3-5.1.0-x64-win\bin'
$env:Z3_SYS_Z3_HEADER='C:\path\to\z3-5.1.0-x64-win\include\z3.h'
mise run --skip-tools windows:build:x64
```
### macOS build tools
Install Apple Command Line Tools before building locally:
```bash
xcode-select --install
```
## Getting Started
```bash
# One-time trust
mise trust
# Run a standalone gateway for local development
mise run gateway
```
## Building the `openshell` CLI
Inside this repository, `openshell` is a local shortcut script at `scripts/bin/openshell`. The script will
1. Build `openshell-cli` if needed.
2. Run the local debug CLI binary under `target/debug/openshell`.
Because `mise` adds `scripts/bin` to `PATH` for this project, you can run `openshell` directly from the repo.
```bash
openshell --help
openshell sandbox create -- codex
```
### Rust build cache
Mise preserves an existing `SCCACHE_DIR` so each environment can choose where
to store compiler cache entries. When `SCCACHE_DIR` is unset, OpenShell uses
the worktree-local `.cache/sccache` directory. To make cache entries available
to multiple worktrees on a workstation, set the variable to a user-level
directory before activating mise. For example:
```shell
export SCCACHE_DIR="$HOME/.cache/openshell/sccache"
```
CI can select a different directory or configure a remote sccache backend
without changing the workstation setting. Cargo output remains in each
worktree's `target/` directory.
OpenShell does not set `SCCACHE_BASEDIRS`. Sccache loads base directories when
its machine-local daemon starts, but the correct workspace root differs for
each worktree. Cache reuse therefore depends on the compiler inputs: outputs
that embed absolute paths, including Rust dependencies in some builds, can
still miss across worktrees.
## Container Image Base Overrides
The gateway and supervisor Dockerfiles accept `GATEWAY_BASE_IMAGE` and
`SUPERVISOR_BASE_IMAGE` build arguments. Omitting them keeps the pinned
distroless defaults. To build with your own bases, pass the argument through
the corresponding task:
```shell
mise run build:docker:gateway -- --build-arg GATEWAY_BASE_IMAGE=registry.example.com/gateway-base:tag
mise run build:docker:supervisor -- --build-arg SUPERVISOR_BASE_IMAGE=registry.example.com/supervisor-base:tag
```
Choose bases that provide the GNU runtime libraries required by the binaries
and CA certificates for the target architecture. Validate the resulting images
with your deployment. The sandbox image uses `scratch` and has no base override.
## Main Tasks
These are the primary `mise` tasks for day-to-day development:
| Task | Purpose |
| -------------------- | ------------------------------------------------------- |
| `mise run gateway` | Run a standalone gateway for local development |
| `mise run sandbox` | Create or reconnect to the dev sandbox |
| `mise run test` | Default test suite |
| `mise run e2e` | Default end-to-end test lane |
| `mise run ci` | Full local CI checks (lint, compile/type checks, tests) |
| `mise run docs` | Validate Fern docs locally |
| `mise run helm:docs` | Regenerate the Helm chart README |
| `mise run clean` | Clean build artifacts |
## Project Structure
| Path | Purpose |
| --------------- | --------------------------------------------- |
| `crates/` | Rust crates |
| `crates/openshell-policy-schema/` | Canonical authored policy DTOs and bounded YAML/JSON parser |
| `crates/openshell-prover-cli/` | Standalone local policy boundary checker |
| `python/` | Python SDK and bindings |
| `sdk/go/` | Go SDK (types, gRPC clients, converters) |
| `sdk/typescript/` | TypeScript SDK (Connect client and generated protobuf bindings) |
| `proto/` | Protocol buffer definitions and [public API conventions](proto/README.md) |
| `tasks/` | `mise` task definitions and build scripts |
| `deploy/` | Dockerfiles, Helm chart, Kubernetes manifests |
| `docs/` | Published Fern docs source, navigation, and content assets |
| `fern/` | Fern site config, components, and theme assets |
| `plans/` | Local plans (git-ignored) |
| `rfc/` | Request for Comments proposals |
| `skills/` | Public skills for using and operating OpenShell |
| `.agents/` | Contributor skills and persona definitions |
## RFCs
New features always start as GitHub issues using the feature request template. For cross-cutting architectural decisions, API contract changes, or process proposals that need broad consensus, maintainers may ask for an RFC from the issue and assign an RFC number there. RFCs live in `rfc/`. See [rfc/README.md](rfc/README.md) for the full lifecycle and guidelines.
## Public API conventions
Follow [the protobuf API conventions](proto/README.md) when adding or changing
gRPC contracts. The guide defines entity-reference naming, workspace selectors,
field design, and schema-evolution rules.
## Documentation
If your change affects user-facing behavior (new flags, changed defaults, new features, bug fixes that contradict existing docs), update the relevant pages under `docs/` in the same PR and adjust `docs/index.yml` if navigation changes. For explicit navigation entries, keep `page:` aligned with `sidebar-title` when present and put relative `slug:` values in `docs/index.yml`. Reserve frontmatter `slug` for folder-discovered pages or absolute URL overrides. Keep every page URL equal to its file path under `docs/`; `mise run docs` checks this with `docs:nav`.
To ensure your doc changes follow NVIDIA documentation style, use the `update-docs-from-commits` skill.
It scans commits, identifies doc pages that need updates, and drafts content that follows the style guide in `docs/CONTRIBUTING.mdx`.
To preview Fern docs locally:
```bash
mise run docs:serve
```
To run non-interactive validation:
```bash
mise run docs
```
PRs that touch `docs/**` or `fern/**` are validated by `.github/workflows/branch-docs.yml`, and they get a preview when `FERN_TOKEN` is available to the workflow.
Release Dev publishes the `dev` docs version from `main`. Release Tag publishes an immutable stable version and updates `latest`. See [fern/README.md](fern/README.md) for the source layout, version model, and publishing workflows.
`docs/` is the source-of-truth docs tree. `fern/` contains the site configuration, components, theme assets, and its README.
See [docs/CONTRIBUTING.mdx](docs/CONTRIBUTING.mdx) for the current docs authoring guide.
## Stale Issues and Pull Requests
Issues and pull requests receive `state:stale` after 14 days without activity. Only `lifecycle:frozen` or `state:frozen` exempts an issue from stale handling. Both labels are supported while the naming convention is being decided. Issues close after another 14 days without activity; pull requests are not automatically closed. Comment on an item to reset the inactivity timer and remove its stale label.
## Pull Requests
1. Create a branch from `main`, or from the parent PR branch for dependent work, following [Branch Names](#branch-names).
2. Make your changes with tests.
3. Run the checks appropriate to the affected code and behavior, as described below.
4. Open a PR using the `create-github-pr` skill or manually following the [PR template](.github/PULL_REQUEST_TEMPLATE.md).
Every PR except an automated dependency update must close an existing issue. In the PR's **Related Issue** section, use `Closes #NNN` for the issue covering that PR's scope. Split multi-PR work into a closable issue for each PR; a tracking issue can link them. Security fixes follow the private disclosure process in [SECURITY.md](SECURITY.md).
Authors without write access to the target repository must link at least one issue with `state:accepted`, and every linked issue must be accepted. This applies to drafts and direct requests to agents. Authors with verified `WRITE`, `MAINTAIN`, or `ADMIN` access may create a PR without the acceptance label; they must still follow the issue-linking requirement above. PR body text, roadmap placement, other labels, and vouch status do not bypass acceptance.
The `PR Issue Acceptance` workflow reports the native `OpenShell / PR Issue Acceptance` job result for the triggering PR when it is opened, edited, reopened, or updated with new commits. It does not publish a shared commit status; lookup and execution errors fail the job. Link accepted issues in this repository using `Fixes #NNN` or `Closes #NNN`; GitHub recognizes closing references when a PR targets the default branch. Rerun the workflow after issue labels change. Making the job required for merging and configuring any required Actions event policy are separate repository settings; merge-queue support is not included.
Automated dependency update PRs, including Dependabot PRs, are exempt from the separate issue and closing-reference requirement. Human-authored dependency updates follow the normal issue requirement. The exception does not bypass `PR Issue Acceptance` for authors without repository write access or change applicable verification, review, or private vulnerability disclosure requirements.
### Branch Names
Use `<type>/<issue-id>-<short-description>/<github-username>` for contributor branches. Choose the Conventional Commit type that describes the work, such as `feat`, `fix`, `refactor`, `chore`, `perf`, `docs`, `test`, or `ci`. The description is a short lowercase slug separated by hyphens; the final component is your GitHub login, not initials.
For example, issue 1234 with contributor `octocat` uses `feat/1234-add-pagination/octocat`. Dependent PRs follow the same naming rule and branch from their parent PR's branch.
Branches created by automation, such as Dependabot and CI mirror branches, keep their generated names. For private security work, follow the authorized disclosure workflow and use a neutral description that does not expose vulnerability details.
### Choose Verification for the Change
Choose checks based on the files changed and the behavior they can affect. Run the relevant formatter, linter, type or compile checks, and tests for those areas. Include dependent components when a shared API, schema, dependency, or build change can affect them.
For contributor guidance, skills, Markdown, and issue or PR templates, validate formatting, links, YAML, and cross references as applicable. Run docs validation when published docs or navigation change. These changes do not require full Rust or SDK suites when they cannot affect those components.
For code changes, run tests for the affected crates or SDKs and their dependent behavior. For sandbox, policy, or deployment infrastructure changes, run the relevant E2E lane. Broaden verification when the change spans components, focused checks fail, or a concrete regression risk remains.
`mise run ci` runs the full repository checks, and `mise run pre-commit` runs broad formatting and lint checks. Use them when that scope is warranted; they are not blanket prerequisites for every change. Report what actually ran and any relevant limitation in the PR. Stop once the checks needed for the change have passed.
### Commit Messages
This project uses [Conventional Commits](https://www.conventionalcommits.org/). All commit messages must follow the format:
```text
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
```
**Types:**
- `feat` - New feature
- `fix` - Bug fix
- `docs` - Documentation only
- `chore` - Maintenance tasks (dependencies, build config)
- `refactor` - Code change that neither fixes a bug nor adds a feature
- `test` - Adding or updating tests
- `ci` - CI/CD changes
- `perf` - Performance improvements
**Examples:**
```text
feat(cli): add --verbose flag to openshell run
fix(sandbox): handle timeout errors gracefully
docs: update installation instructions
chore(deps): bump tokio to 1.40
```
### DCO
All human contributions must include a `Signed-off-by` line in each commit message. This certifies you have the right to submit the work under the project license. Dependabot-authored dependency update PRs are allowlisted because the bot cannot sign commits.
The project uses version 1.1 of the [Developer Certificate of Origin](https://developercertificate.org/):
```text
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
```bash
git commit --signoff --message "feat(sandbox): add new capability"
```
DCO sign-off is separate from cryptographic commit signing, and the two have different requirements:
- **DCO sign-off** (`--signoff`) adds the `Signed-off-by` trailer to each commit. It applies to every contributor. The DCO Assistant bot also asks you to sign the DCO once, by commenting on your PR.
- **Cryptographic commit signing** applies to org members and collaborators only. CI requires it so that copy-pr-bot can mirror your PR automatically; see [CI.md](CI.md#commit-signing) for setup.
### PR testing checklist
Only mark a checklist item as complete after you have run and verified it, not as a plan for what you intend to test. Unchecked boxes at submission are fine; they show what still needs verification before merge.
## CI
How PR CI runs, the `test:e2e`, `test:e2e-gpu`, and `test:e2e-kubernetes` labels, copy-pr-bot, and commit-signing setup are documented in [CI.md](CI.md).