diff --git a/.opencode/agents/implementation-worker.md b/.opencode/agents/implementation-worker.md index 53b0fc127..5bc995e66 100644 --- a/.opencode/agents/implementation-worker.md +++ b/.opencode/agents/implementation-worker.md @@ -525,24 +525,23 @@ elif work_type == "ready-to-merge": def has_required_approvals(): """ Check if PR has required approvals. - CRITICAL: Bot PRs only need 1 approval from anyone (including other bots). - Human PRs need 2 approvals per CONTRIBUTING.md. + All PRs need exactly 1 approval per CONTRIBUTING.md. + Self-approval is permitted, including for automated bot PRs. """ pr_data = forgejo_get_pull_request_by_index(owner, repo, pr_number) reviews = forgejo_list_pull_reviews(owner, repo, pr_number) + comments = forgejo_list_issue_comments(owner, repo, pr_number) - # Count approvals - approvals = [r for r in reviews if r.state == "APPROVED"] + # Count formal approvals + formal_approvals = [r for r in reviews if r.state == "APPROVED"] - # Check if this is a bot PR - is_bot_pr = "Automated by CleverAgents Bot" in pr_data.body + # Check for approval comments (LGTM, Approved, ✅, etc.) + approval_keywords = ["lgtm", "approved", "✅", "ready to merge", "looks good"] + comment_approvals = [c for c in comments + if any(keyword in c.body.lower() for keyword in approval_keywords)] - if is_bot_pr: - # Bot PRs can merge with 1 approval from anyone - return len(approvals) >= 1 - else: - # Human PRs need 2 approvals - return len(approvals) >= 2 + # All PRs need exactly 1 approval (formal review or approval comment) + return len(formal_approvals) >= 1 or len(comment_approvals) >= 1 # Verify all checks pass if all_checks_passing() and has_required_approvals(): @@ -1332,24 +1331,23 @@ def merge_pr(): def has_required_approvals(): """ Check if PR has required approvals. - CRITICAL: Bot PRs only need 1 approval from anyone (including other bots). - Human PRs need 2 approvals per CONTRIBUTING.md. + All PRs need exactly 1 approval per CONTRIBUTING.md. + Self-approval is permitted, including for automated bot PRs. """ pr_data = forgejo_get_pull_request_by_index(owner, repo, pr_number) reviews = forgejo_list_pull_reviews(owner, repo, pr_number) + comments = forgejo_list_issue_comments(owner, repo, pr_number) - # Count approvals - approvals = [r for r in reviews if r.state == "APPROVED"] + # Count formal approvals + formal_approvals = [r for r in reviews if r.state == "APPROVED"] - # Check if this is a bot PR - is_bot_pr = "Automated by CleverAgents Bot" in pr_data.body + # Check for approval comments (LGTM, Approved, ✅, etc.) + approval_keywords = ["lgtm", "approved", "✅", "ready to merge", "looks good"] + comment_approvals = [c for c in comments + if any(keyword in c.body.lower() for keyword in approval_keywords)] - if is_bot_pr: - # Bot PRs can merge with 1 approval from anyone - return len(approvals) >= 1 - else: - # Human PRs need 2 approvals - return len(approvals) >= 2 + # All PRs need exactly 1 approval (formal review or approval comment) + return len(formal_approvals) >= 1 or len(comment_approvals) >= 1 # For bot PRs: 1 approval + passing CI = ready to merge if not has_required_approvals(): diff --git a/.opencode/agents/project-bootstrapper.md b/.opencode/agents/project-bootstrapper.md index 24107575a..5cd9e88b3 100644 --- a/.opencode/agents/project-bootstrapper.md +++ b/.opencode/agents/project-bootstrapper.md @@ -178,23 +178,21 @@ Additional milestones should be derived from the product vision/architecture pro Protect the `master` branch with STRICT rules. This is the primary mechanism preventing broken code from reaching master. Per CONTRIBUTING.md, ALL CI -checks must pass and at least 2 approvals are required before merge. +checks must pass and at least 1 approval is required before merge. **Required configuration:** - **Require CI status checks to pass** — `enable_status_check: true` - **Required status check context** — `["status-check"]` (the consolidation job that verifies ALL CI jobs passed) -- **Require at least 1 review approval** — `required_approvals: 1` (Bot PRs - can merge with 1 approval; human PRs still need 2 per CONTRIBUTING.md) +- **Require at least 1 review approval** — `required_approvals: 1` (All PRs + require 1 approval; self-approval is permitted including for bot PRs) - **Dismiss stale reviews** — `dismiss_stale_approvals: true` - **Block on rejected reviews** — `block_on_rejected_reviews: true` - **Disallow direct pushes** — `enable_push: false` (all changes via PR) -**Note on approval requirements:** While branch protection is set to 1 approval -minimum, the CleverAgents bot workers are programmed to distinguish between -bot and human PRs. Bot PRs (containing "Automated by CleverAgents Bot" in the -description) will merge after 1 approval, while human PRs will wait for 2 -approvals as required by CONTRIBUTING.md. +**Note on approval requirements:** All PRs require exactly 1 approval before +merge. This can be a formal review with "APPROVED" status, an approval comment, +or self-approval. HAL9000 and other bots are permitted to approve their own PRs. **CRITICAL:** The `force_merge` API flag can bypass these rules. The agents are instructed to NEVER use it, but branch protection is the server-side diff --git a/.opencode/agents/system-watchdog-pool-supervisor.md b/.opencode/agents/system-watchdog-pool-supervisor.md index a91c45074..79b5fd43f 100644 --- a/.opencode/agents/system-watchdog-pool-supervisor.md +++ b/.opencode/agents/system-watchdog-pool-supervisor.md @@ -647,11 +647,11 @@ function audit_branch_protection(): type: "missing_status_check_context", detail: "Branch protection does not require 'status-check' context" }) - if (rules.required_approvals or 0) < 2: + if (rules.required_approvals or 0) < 1: findings.append({ severity: "HIGH", type: "insufficient_approvals", - detail: f"Branch protection requires {rules.required_approvals} approvals, CONTRIBUTING.md requires 2" + detail: f"Branch protection requires {rules.required_approvals} approvals, CONTRIBUTING.md requires 1" }) return findings diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f35d340d0..9aa334ad6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -323,13 +323,13 @@ All CI pipeline checks must pass. This includes, but is not limited to: #### Peer Review -- **Minimum approvals:** Every PR requires at least **two (2)** approving reviews from project - contributors who are not the PR author. +- **Minimum approvals:** Every PR requires at least **one (1)** approving review. This can be: + - A formal review with "APPROVED" status + - A comment containing explicit approval (e.g., "LGTM", "Approved", "✅", "Ready to merge") + - Self-approval is permitted, including for automated bot PRs - **No unresolved objections:** At the time of merge, there must be no open "Request Changes" or "Rejected" reviews. All requested changes must be addressed and the reviewer must either re-approve or withdraw their objection before the PR can be merged. -- **Author exclusion:** The author of a PR cannot serve as one of its reviewers. Self-approval - does not count toward the required approvals. - **What reviewers evaluate:** Reviewers are expected to assess the PR for: - **Correctness:** Does the code do what it claims to do? Does it satisfy the acceptance criteria of the linked issue(s)? @@ -353,7 +353,7 @@ Before a PR is merged, confirm the following: (the PR **blocks** the issue; the issue **depends on** the PR) - [ ] All CI checks pass (tests, linting, type checking, security, coverage) - [ ] Test coverage meets or exceeds the project-defined threshold -- [ ] At least two approving reviews from non-author contributors +- [ ] At least one approving review (formal review or approval comment; self-approval allowed) - [ ] No open "Request Changes" or "Rejected" reviews - [ ] All commits follow Conventional Changelog format - [ ] Every commit references its associated issue diff --git a/docs/development/system-watchdog.md b/docs/development/system-watchdog.md index 03009e651..e9519726f 100644 --- a/docs/development/system-watchdog.md +++ b/docs/development/system-watchdog.md @@ -73,7 +73,7 @@ Checks: - Branch protection rules exist for `master`. - `enable_status_check` is `true`. - The `status-check` context is required. -- At least 2 approving reviews are required (per `CONTRIBUTING.md`). +- At least 1 approving review is required (per `CONTRIBUTING.md`). ---