diff --git a/.github/workflows/issue-gate.yml b/.github/workflows/issue-gate.yml index 70bab864..8ca8c401 100644 --- a/.github/workflows/issue-gate.yml +++ b/.github/workflows/issue-gate.yml @@ -1,4 +1,4 @@ -name: Contribution gate - issues +name: Contribution intake - issues on: issues: @@ -8,16 +8,11 @@ permissions: contents: read issues: write -env: - # Keep new gates observable first. Switch to "enforce" only after maintainers - # have seeded active contributors and reviewed the dry-run signal. - CONTRIBUTION_GATE_MODE: dry-run - jobs: gate: runs-on: ubuntu-latest steps: - - name: Gate unapproved external issues + - name: Welcome new external issue reporters uses: actions/github-script@v7 with: script: | @@ -25,12 +20,6 @@ jobs: const owner = context.repo.owner; const repo = context.repo.repo; const privileged = new Set(['OWNER', 'MEMBER', 'COLLABORATOR']); - const gateMode = (process.env.CONTRIBUTION_GATE_MODE || 'dry-run').trim().toLowerCase(); - const enforceGate = gateMode === 'enforce'; - - if (!['dry-run', 'enforce'].includes(gateMode)) { - core.warning(`Unknown CONTRIBUTION_GATE_MODE "${gateMode}"; defaulting to dry-run.`); - } if (privileged.has(issue.author_association)) return; if (issue.user.login === 'github-actions[bot]') return; @@ -71,29 +60,25 @@ jobs: return; } - const gateMessage = enforceGate - ? 'This repository currently uses a maintainer-managed contribution gate, so issues from contributors who are not listed in `.github/APPROVED_CONTRIBUTORS` are closed automatically.' - : 'This repository is currently observing a maintainer-managed contribution gate in dry-run mode, so this issue is staying open. When enforcement is enabled, issues from contributors who are not listed in `.github/APPROVED_CONTRIBUTORS` will be closed automatically.'; + const marker = ''; + const { data: comments } = await github.rest.issues.listComments({ + owner, + repo, + issue_number: issue.number, + per_page: 100, + }); + if (comments.some(comment => (comment.body || '').includes(marker))) return; await github.rest.issues.createComment({ owner, repo, issue_number: issue.number, body: [ + marker, `Thanks @${issue.user.login} for the report.`, '', - gateMessage, + 'This issue is staying open for maintainer triage. CodeWhale gets better because people bring us real edge cases from real machines, providers, regions, and workflows.', '', - 'Please read `CONTRIBUTING.md` for the expected issue shape. A maintainer can grant issue access by commenting `/lgtmi` on an issue.', + 'If you can add a reproduction, logs, version output, screenshots, or the provider/model involved, that makes it much easier for us to verify and harvest the fix. Maintainers may comment `/lgtmi` to mark recurring issue reporters as approved so this intake note is skipped next time.', ].join('\n'), }); - - if (!enforceGate) return; - - await github.rest.issues.update({ - owner, - repo, - issue_number: issue.number, - state: 'closed', - state_reason: 'not_planned', - }); diff --git a/.github/workflows/pr-gate.yml b/.github/workflows/pr-gate.yml index 3e4052db..40afe8c1 100644 --- a/.github/workflows/pr-gate.yml +++ b/.github/workflows/pr-gate.yml @@ -73,8 +73,8 @@ jobs: } const gateMessage = enforceGate - ? 'This repository currently uses a maintainer-managed contribution gate, so pull requests from contributors who are not listed in `.github/APPROVED_CONTRIBUTORS` are closed automatically.' - : 'This repository is currently observing a maintainer-managed contribution gate in dry-run mode, so this pull request is staying open. When enforcement is enabled, pull requests from contributors who are not listed in `.github/APPROVED_CONTRIBUTORS` will be closed automatically.'; + ? 'This repository currently limits automated PR intake to contributors listed in `.github/APPROVED_CONTRIBUTORS`. This is a maintainer-safety control for code review and CI load, not a judgment on the contribution. A maintainer can reopen or grant access with `/lgtm` after review.' + : 'This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered.'; await github.rest.issues.createComment({ owner, @@ -85,7 +85,7 @@ jobs: '', gateMessage, '', - 'Please read `CONTRIBUTING.md` for the expected contribution shape. A maintainer can grant PR access by commenting `/lgtm` on a pull request.', + 'Please read `CONTRIBUTING.md` for the expected contribution shape. A maintainer can grant recurring PR access by commenting `/lgtm` on a pull request.', ].join('\n'), }); diff --git a/CHANGELOG.md b/CHANGELOG.md index c250464e..08c058c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Appended volatile `` blocks after user text in outgoing user message content arrays so provider prefix caches can keep matching the stable user-input prefix across date, route, and working-set changes. +- Softened contribution intake automation: external issues now receive a warm + triage note and are never auto-closed by the contribution gate, while the PR + gate copy makes clear that dry-run observations are about maintainer safety, + not contributor quality. +- Documented the agent and sub-agent stewardship ethos so future automation + preserves human issue intake, careful PR review, and contributor credit. ### Community diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7ed555b9..66328675 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -172,16 +172,24 @@ Validation: CodeWhale uses a maintainer-managed contribution gate for the community front door. Maintainers and collaborators bypass this gate automatically. The gate workflows default to dry-run / comment-only mode so maintainers can observe the -signal before closing contributor work. In dry-run mode, unapproved external -issues and pull requests receive a short thank-you / CONTRIBUTING pointer and -remain open. +signal before changing contributor flow. -When maintainers are ready to enforce the gate, set -`CONTRIBUTION_GATE_MODE: enforce` in the PR and issue gate workflows. In enforce -mode, external contributors must be listed in -`.github/APPROVED_CONTRIBUTORS` before their issues or pull requests remain -open. Before enabling enforcement, seed the allowlist broadly enough for active -external contributors who should not be interrupted by the rollout. +The maintainer posture is documented in +[docs/AGENT_ETHOS.md](docs/AGENT_ETHOS.md): automation should reduce load while +keeping good-faith contributors seen, credited, and able to keep helping. + +Issues are never auto-closed by the contribution gate. Unapproved external +issues receive a short welcome note that asks for reproduction details and then +remain open for maintainer triage. CodeWhale depends on real edge cases from +real users, so issue intake should stay warm and open. + +Pull requests are different because they can touch code, CI, release plumbing, +auth, sandboxing, provider policy, and other trust-boundary surfaces. The PR +gate can be switched from dry-run to enforcement when maintainers decide they +need that safety control, but it should be treated as a review-load control, +not a judgment on contributor quality. Before enabling PR enforcement, seed the +allowlist broadly enough for active external contributors who should not be +interrupted by the rollout. The allowlist is scoped: @@ -198,11 +206,10 @@ discussion. Approvals do not edit `main` directly. The approval workflow opens a small allowlist update PR so the new entry is reviewable before it takes effect. -If the gate fires on a good contributor incorrectly, use the same approval flow -to restore them: comment `/lgtm` or `/lgtmi`, merge the generated allowlist PR, -then reopen the affected issue or pull request. If GitHub will not allow the -closed item to be reopened, ask the contributor to resubmit after the allowlist -PR is merged. +If the PR gate fires on a good contributor incorrectly, use the same approval +flow to restore them: comment `/lgtm`, merge the generated allowlist PR, then +reopen the affected pull request. If GitHub will not allow the closed PR to be +reopened, ask the contributor to resubmit after the allowlist PR is merged. ## Agent-Assisted Improvements @@ -213,6 +220,11 @@ from a fresh fork or branch, let the agent find exactly one small friction point and stop after one patch. DeepSeek V4 Pro is the first-class path for this loop today, but the review shape matters more than the provider. +Agents and maintainers should follow the stewardship posture in +[docs/AGENT_ETHOS.md](docs/AGENT_ETHOS.md): use automation for evidence, +verification, and narrow patches while keeping the final community decision +human-reviewed. + The useful output is not "ideas for improvement." The useful output is a specific reproduction, a minimal diff, focused checks, and a PR description that explains the trade-off. Do not use an agent to touch auth, credentials, sandbox diff --git a/README.md b/README.md index c36be8e1..b22d3ffc 100644 --- a/README.md +++ b/README.md @@ -545,6 +545,7 @@ without recreating skills the user deliberately deleted. | [TENCENT_CLOUD_REMOTE_FIRST.md](docs/TENCENT_CLOUD_REMOTE_FIRST.md) | Tencent/CNB/Lighthouse/Feishu remote-first path | | [TENCENT_LIGHTHOUSE_HK.md](docs/TENCENT_LIGHTHOUSE_HK.md) | Lighthouse Hong Kong server setup | | [MEMORY.md](docs/MEMORY.md) | User memory feature guide | +| [AGENT_ETHOS.md](docs/AGENT_ETHOS.md) | Maintainer and agent stewardship posture | | [SUBAGENTS.md](docs/SUBAGENTS.md) | Sub-agent role taxonomy and lifecycle | | [KEYBINDINGS.md](docs/KEYBINDINGS.md) | Full shortcut catalog | | [RELEASE_RUNBOOK.md](docs/RELEASE_RUNBOOK.md) | Release process | diff --git a/docs/AGENT_ETHOS.md b/docs/AGENT_ETHOS.md new file mode 100644 index 00000000..156b95da --- /dev/null +++ b/docs/AGENT_ETHOS.md @@ -0,0 +1,50 @@ +# Agent Ethos + +CodeWhale is maintained with agents, but it is not maintained by automation +alone. Treat community reports and patches as real collaboration: people are +bringing us machines, providers, regions, shells, packages, and edge cases we +could not cover by ourselves. + +## Stewardship + +- Verify live truth before acting. Check the current branch, release state, + registry state, CI, and linked issues instead of trusting a handoff. +- Issues are intake, not a privilege boundary. Do not auto-close good-faith + issues because the reporter is not allowlisted. Ask for missing reproduction + detail and leave room for maintainer triage. +- PR gates exist for code review, CI load, and trust-boundary safety. They are + not a quality judgment on the contributor. Keep dry-run mode unless a + maintainer deliberately enables enforcement, and use warm copy when the gate + comments. +- Be generous with recurring contributors. When someone repeatedly brings + useful reports or patches, use `/lgtmi` for issue access or `/lgtm` for PR + access so the automation gets out of their way. +- Preserve contributor credit. When harvesting work, inspect the PR and linked + issues, keep author/co-author attribution where possible, add + `Harvested from PR #N by @handle`, and credit the contributor in the + changelog or release notes. +- Deferral is a maintainer action, not a dismissal. If a PR or issue is not + ready, say what is blocked, what evidence would change the decision, and + which part of the work remains valuable. + +## Agent Workflow + +- Use sub-agents for exploration, review, and verification, but keep a human + maintainer posture in the parent session. Sub-agent output is evidence; the + parent is responsible for the final decision. +- Personally review community PRs before merging, harvesting, closing, or + deferring them. Do not close work based only on title, labels, or an agent's + summary. +- Prefer narrow, reversible changes that match the existing codebase. Avoid + drive-by refactors while harvesting community work. +- Run the smallest meaningful validation first, then broaden tests when a + change touches shared behavior, release plumbing, auth, sandboxing, + providers, or UI workflows. +- Do not tag, publish, push release artifacts, or create GitHub releases + without explicit maintainer approval. + +## Product Tone + +CodeWhale should feel like a capable coding harness with a public community, +not a closed queue. Automation should reduce maintainer load while making +contributors feel seen, credited, and able to keep helping. diff --git a/docs/SUBAGENTS.md b/docs/SUBAGENTS.md index 5c61f4b2..71aba596 100644 --- a/docs/SUBAGENTS.md +++ b/docs/SUBAGENTS.md @@ -18,6 +18,19 @@ The `type` field on `agent_open` selects a system-prompt posture for the child (`agent_type` is accepted as a compatibility alias). Each role is a distinct stance toward the work — not just a different label. +## Maintainer posture + +Sub-agents help CodeWhale move faster, but the parent agent still owns the +maintainer decision. Use children to gather evidence, review patches, and run +verification while keeping the community posture in +[`AGENT_ETHOS.md`](AGENT_ETHOS.md): issues are open intake, PR gates are +review-load controls, and harvested work needs clear contributor credit. + +When a child reviews community work, the parent should still inspect the PR +diff, linked issues, tests, and CI before merging, harvesting, closing, or +deferring it. A sub-agent's result is a working set, not a substitute for +stewardship. + | Role | Stance | Writes? | Shell posture | Typical use | |---------------|----------------------------------------|---------|---------------|----------------------------------------------| | `general` | flexible; do whatever the parent says | yes | yes | the default; multi-step tasks |