From 6e5d6b200b73f6e87caaadbad5f8492832543412 Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Wed, 1 Apr 2026 09:20:26 +0100 Subject: [PATCH 1/3] 2 humans Signed-off-by: Nicholas Gates --- .github/workflows/approvals.yml | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/approvals.yml diff --git a/.github/workflows/approvals.yml b/.github/workflows/approvals.yml new file mode 100644 index 00000000000..e99cce50470 --- /dev/null +++ b/.github/workflows/approvals.yml @@ -0,0 +1,48 @@ +name: PR Approval Check + +on: + pull_request_review: + types: [submitted, dismissed] + pull_request: + types: [opened, synchronize, reopened] + +jobs: + check-approvals: + runs-on: ubuntu-latest + steps: + - name: Check required approvals + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd + with: + script: | + const pr = context.payload.pull_request; + const reviews = await github.rest.pulls.listReviews({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + }); + + // Count unique human approvals (latest review per user) + const latestByUser = {}; + for (const review of reviews.data) { + if (review.user.type === 'Bot') continue; + latestByUser[review.user.login] = review.state; + } + const approvalCount = Object.values(latestByUser) + .filter(state => state === 'APPROVED').length; + + // Determine if PR author is a bot/GitHub Actions + const authorType = pr.user.type; // 'Bot' vs 'User' + const authorLogin = pr.user.login; // e.g. 'github-actions[bot]' + const isBot = authorType === 'Bot' || authorLogin.endsWith('[bot]'); + + const required = isBot ? 2 : 1; + + console.log(`PR author: ${authorLogin} (${authorType}), isBot: ${isBot}`); + console.log(`Approvals: ${approvalCount} / ${required} required`); + + if (approvalCount < required) { + core.setFailed( + `This PR needs ${required} human approval(s) but has ${approvalCount}. ` + + `(Author is ${isBot ? 'a bot' : 'human'})` + ); + } \ No newline at end of file From f5ae34486c114f03155ee2b18b41339c0e97e0ac Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Wed, 1 Apr 2026 09:30:27 +0100 Subject: [PATCH 2/3] 2 humans Signed-off-by: Nicholas Gates --- .github/workflows/approvals.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/approvals.yml b/.github/workflows/approvals.yml index e99cce50470..12e74a6534c 100644 --- a/.github/workflows/approvals.yml +++ b/.github/workflows/approvals.yml @@ -45,4 +45,4 @@ jobs: `This PR needs ${required} human approval(s) but has ${approvalCount}. ` + `(Author is ${isBot ? 'a bot' : 'human'})` ); - } \ No newline at end of file + } From bef78bf1ec824174a59bc3ba26ee3acb06025930 Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Wed, 1 Apr 2026 12:04:53 +0100 Subject: [PATCH 3/3] ArrayRef Signed-off-by: Nicholas Gates --- CONTRIBUTING.md | 18 ++++------ docs/project/contributing.md | 69 ++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eeaa13407b2..aef2e0c33ac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,19 +4,15 @@ Welcome, and thank you for your interest in contributing to Vortex! We are delig We ask that you read the guidelines below in order to make the process as streamlined as possible. -## AI Assistance Notice +## AI Assistance > [!IMPORTANT] -> The Vortex project allows AI-assisted contributions, which must be properly -> disclosed in the pull request. +> The Vortex project permits and embraces AI-assisted contributions. Contributors +> should disclose usage of conversational or agentic AI tools in the PR description. > -> If you are using any kind of AI assistance when contributing to Vortex, please -> disclose this in your pull request, along with the extent to which it was used -> (e.g. writing docs or code generation). -> -> Contributors are required to be able to understand the AI-assisted output and -> reason about it. Should a PR indicate no visible human accountability and -> involvement we reserve the right to close it. +> For the full AI policy — including disclosure requirements, review standards for +> AI-generated PRs, and rules for autonomous agents — see the +> [contributing guide](https://vortex.dev/project/contributing.html#ai-assistance). ## Code Contributions @@ -35,7 +31,7 @@ The contribution process is outlined below: 3. Open a PR to indicate that the change is ready for review. - Ensure that you sign your work via DCO (see below). - - Disclose LLM usage as described in [AI Assistance Notice](#ai-assistance-notice). + - Disclose LLM usage as described in [AI Assistance](#ai-assistance). - CI requires approval from external committers. ## Governance diff --git a/docs/project/contributing.md b/docs/project/contributing.md index 19ea1b0c528..fa6ea57d926 100644 --- a/docs/project/contributing.md +++ b/docs/project/contributing.md @@ -34,8 +34,73 @@ git commit -s ## AI Assistance -AI-assisted contributions are permitted but must be disclosed in the pull request, along with the -extent of use. Contributors must be able to understand and reason about AI-generated output. +The Vortex project permits and embraces AI-assisted contributions. Today, most PRs involve some +degree of AI assistance — whether through IDE autocomplete, conversational AI, or autonomous agents. +This section describes our expectations around disclosure, review, and accountability. + +### Repository Setup + +The repository has [Claude Code](https://docs.anthropic.com/en/docs/claude-code) configured as a +GitHub Action. Users with write access to the repository can mention `@claude` in PR comments or +issue comments to trigger AI-powered code reviews, request changes, or generate PRs. Configuration +for Claude's behavior lives in `CLAUDE.md` at the repository root. + +### Disclosure + +Contributors should disclose AI usage in the PR description when conversational or agentic AI tools +(e.g., Claude, ChatGPT, Claude Code) were used to produce code, documentation, or tests. Standard +IDE autocomplete (e.g., Copilot tab-completion) does not require disclosure. + +AI-translated content should note that it was translated with AI assistance. + +### Human vs. Agent PRs + +We distinguish between two kinds of AI-assisted PRs: + +- **Human PRs** — A human writes the PR, possibly with significant AI assistance. The human author + is accountable for the code quality and correctness, just as they would be for any handwritten + code. Standard review rules apply (one approving reviewer). + +- **Agent PRs** — An autonomous AI agent (e.g., triggered via `@claude` or a scheduled GitHub + Action) opens the PR with minimal human steering. Agent PRs require **two human reviewers** + before merge. + +The distinction is straightforward: if a human opened the PR, it's a human PR. If an automated +agent opened it, it's an agent PR. + +### Review Standards + +AI-assisted code should receive extra scrutiny during review. AI tools can produce code that is +superficially correct but subtly wrong — off-by-one errors, incorrect edge case handling, or tests +that pass without actually exercising the intended behavior. Reviewers should pay particular +attention to: + +- Correctness of logic, not just whether it compiles and passes CI. +- Tests that genuinely validate behavior rather than merely achieving coverage. +- Unnecessary complexity or over-abstraction. + +The project may use AI-powered review tools on PRs. Reviewers are free to use AI to assist their +reviews without disclosure. + +### AI Agents + +AI agents (bots, scheduled actions, etc.) are permitted to: + +- Open pull requests, with a human assigned as the responsible party. +- Post review comments on pull requests. + +AI agents must **not**: + +- Merge or approve pull requests. +- Push code to protected branches. + +A human is accountable for all actions taken by an agent operating under their authority. + +### AI-Generated Tests + +AI-generated tests are welcome, but contributors must verify that tests actually exercise the +intended behavior — not just pass. A green test suite produced by AI can give a false sense of +coverage if the assertions are trivial or the setup doesn't reflect real conditions. ## Coding Style