From 250c9eb5e35cc5e4bba60d12f797e31353bd4d45 Mon Sep 17 00:00:00 2001 From: morgmart <98432065+morgmart@users.noreply.github.com> Date: Thu, 13 Aug 2026 18:16:19 -0500 Subject: [PATCH 1/4] docs: establish the OSS contribution front door MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Berd is public, but its front door was still template text: CONTRIBUTING.md was a single link to Block's generic guidelines, and the README pointed at it. Nothing told an outside reader what we accept. We accept issues, not outside pull requests. This makes that explicit and raises the bar on what an issue has to contain. - CONTRIBUTING.md is now the source of truth for participating: the no-outside-PR policy and why, what a bug report and a feature request each require, how triage works. It doubles as the agent-followable spec — one file, browsable on github.com and fetchable raw, so a reporter's agent can read the same rules a human does. - Issue templates converted from markdown to YAML forms. Markdown headings are deletable suggestions; forms have genuinely required fields. Bug reports now require repro steps, expected vs. actual, frequency, version, platform, and log output. Feature requests require the problem, the current workaround, why it belongs in core rather than a skill or extension, and non-goals. - blank_issues_enabled: false, so the forms can't be bypassed. - Restore CODEOWNERS. main already requires code-owner review, so without this file that protection matched nobody and passed trivially. - Add close-external-prs workflow. Anyone can open a PR on a public repo, so outside PRs get a polite comment and an immediate close. Checks real collaborator permission rather than author_association, which reads as CONTRIBUTOR for maintainers with private org membership. - PR template leads with the policy so it's seen before submitting. --- .github/ISSUE_TEMPLATE/bug-report.md | 24 --- .github/ISSUE_TEMPLATE/bug-report.yml | 147 ++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 15 +- .github/ISSUE_TEMPLATE/feature-request.md | 21 -- .github/ISSUE_TEMPLATE/feature-request.yml | 117 +++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 6 + .github/workflows/close-external-prs.yml | 77 ++++++++ CODEOWNERS | 9 + CONTRIBUTING.md | 219 ++++++++++++++++++++- README.md | 25 ++- 10 files changed, 610 insertions(+), 50 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature-request.md create mode 100644 .github/ISSUE_TEMPLATE/feature-request.yml create mode 100644 .github/workflows/close-external-prs.yml create mode 100644 CODEOWNERS diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md deleted file mode 100644 index 3d97a3ac6..000000000 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Bug report -about: Report a reproducible bug in Berd -labels: bug ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**Steps to reproduce** -1. Go to '...' -2. Click on '...' -3. See error - -**Expected behavior** -What did you expect to happen? - -**Version and platform** -Find your version in Settings. Write "unknown" if you cannot determine it. -- Berd version: -- OS: - -**Logs / additional context** -Paste any relevant logs, error messages, or screenshots here. diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 000000000..1bb90d9dd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,147 @@ +name: Bug report +description: Berd does something other than what it says it does +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time. A report we can reproduce without asking you + anything is worth a great deal to us. + + Before you start, please read + [the bug report section of CONTRIBUTING.md](https://github.com/block/berd/blob/main/CONTRIBUTING.md#bug-reports). + You're welcome to have an agent help you fill this in — see + [Using an agent](https://github.com/block/berd/blob/main/CONTRIBUTING.md#using-an-agent). + + **Do not report security vulnerabilities here.** Use + [SECURITY.md](https://github.com/block/berd/blob/main/SECURITY.md). + + - type: checkboxes + id: preflight + attributes: + label: Before filing + description: All three are required. Please actually do them. + options: + - label: I searched [open and closed issues](https://github.com/block/berd/issues?q=is%3Aissue) for duplicates. + required: true + - label: I reproduced this on the [latest release](https://github.com/block/berd/releases). + required: true + - label: This is one bug, not several bundled together. + required: true + + - type: input + id: duplicate-search + attributes: + label: Closest existing issue + description: Link the nearest thing you found, or write "none found". + placeholder: "#123, or none found" + validations: + required: true + + - type: textarea + id: summary + attributes: + label: What's broken + description: One or two sentences. Save the detail for the fields below. + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: | + Numbered, starting from a freshly launched Berd. Include the model and + provider, whether the chat had prior history, and anything about your + setup that might matter. + value: | + 1. Launch Berd + 2. + 3. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: What you expected to happen + validations: + required: true + + - type: textarea + id: actual + attributes: + label: What actually happened + validations: + required: true + + - type: dropdown + id: frequency + attributes: + label: How often does it happen? + description: This changes how we chase it more than almost anything else. + options: + - Every time — reliably reproducible + - Intermittently — happens often but not always + - Once — I have not been able to reproduce it + validations: + required: true + + - type: input + id: version + attributes: + label: Berd version + description: 'Settings → About. If Berd will not launch, write "cannot launch".' + placeholder: "0.6.0" + validations: + required: true + + - type: dropdown + id: os + attributes: + label: Operating system + options: + - macOS (Apple Silicon) + - macOS (Intel) + - Linux + - Windows + validations: + required: true + + - type: input + id: model + attributes: + label: Model and provider + description: If the bug involves a chat or an agent turn. Otherwise "n/a". + placeholder: "Claude Sonnet 4.5 via Anthropic" + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Relevant log output + description: | + The lines around when the problem happened — not the whole file, not a + screenshot of text. **Scrub anything private first**: logs can contain + file paths, prompt text, and project names. + + macOS `~/Library/Logs/xyz.block.berd/` · Linux + `~/.local/share/xyz.block.berd/logs/` · Windows + `%LOCALAPPDATA%\xyz.block.berd\logs\` + + If there is genuinely nothing relevant, write "no relevant log output" + so we know you looked. + render: text + validations: + required: true + + - type: textarea + id: context + attributes: + label: Screenshots, recordings, or other context + description: | + Required for anything visual — a few seconds of capture saves an hour of + back-and-forth. Drag files in to attach them. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 0086358db..715dbacd6 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1 +1,14 @@ -blank_issues_enabled: true +# Free-form issues are disabled on purpose: a well-formed issue is the one way +# to participate in Berd, so the forms ask for what we need to act on it. +# See CONTRIBUTING.md. +blank_issues_enabled: false +contact_links: + - name: Questions about using Berd + url: https://github.com/block/berd/blob/main/README.md + about: The README covers setup, building, and how Berd is put together. The issue tracker is not a support channel. + - name: Security vulnerabilities + url: https://github.com/block/berd/blob/main/SECURITY.md + about: Please report privately — never as a public issue. + - name: How to participate + url: https://github.com/block/berd/blob/main/CONTRIBUTING.md + about: What we accept, what makes a good issue, and why we don't take outside pull requests. diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md deleted file mode 100644 index 98284e0e2..000000000 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: Feature request -about: Propose a new feature or improvement -labels: enhancement ---- - -**Motivation** -What problem does this solve? Who runs into it and when? - -**Proposed solution** -Describe what you'd like to see. - -**Alternatives considered** -What other approaches did you consider? - -**Additional context** -Anything else that helps — links, screenshots, prior art. - ---- - -Before opening: please [search open issues and PRs](https://github.com/block/berd/issues?q=is%3Aopen) for duplicates — link the closest one, or say "none found". diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 000000000..3f65ea74b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,117 @@ +name: Feature request +description: You want Berd to do something it doesn't, or to do something existing noticeably better +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + We want to understand the **problem**, not just the solution you have in + mind — the problem often has a better answer than the one you'd have + asked for. + + Before you start, please read + [the feature request section of CONTRIBUTING.md](https://github.com/block/berd/blob/main/CONTRIBUTING.md#feature-requests). + You're welcome to have an agent help you fill this in — see + [Using an agent](https://github.com/block/berd/blob/main/CONTRIBUTING.md#using-an-agent). + + - type: checkboxes + id: preflight + attributes: + label: Before filing + description: All three are required. Please actually do them. + options: + - label: I searched [open and closed issues](https://github.com/block/berd/issues?q=is%3Aissue) for duplicates. + required: true + - label: I am using a recent [release](https://github.com/block/berd/releases) and this doesn't already exist. + required: true + - label: This is one request, not several bundled together. + required: true + + - type: input + id: duplicate-search + attributes: + label: Closest existing issue + description: Link the nearest thing you found, or write "none found". + placeholder: "#123, or none found" + validations: + required: true + + - type: dropdown + id: kind + attributes: + label: Is this new, or an improvement? + options: + - New capability — Berd can't do this at all today + - Improvement — Berd does this, but badly + validations: + required: true + + - type: textarea + id: problem + attributes: + label: The problem, in your terms + description: | + What were you trying to get done, and what made it hard? Describe the + situation, not the feature. Lead with this. + validations: + required: true + + - type: textarea + id: today + attributes: + label: What you do today + description: | + Your current workaround, however ugly — or "nothing, I gave up". This + tells us how much the gap actually costs you. + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: What you'd like to see + description: Your proposed change. Rough is fine. + validations: + required: true + + - type: textarea + id: why-core + attributes: + label: Why this belongs in Berd itself + description: | + Berd is extensible on purpose. Could this be a + [skill](https://github.com/block/berd/tree/main/.agents/skills), an + agent, an extension, or an automation instead? If it could and you still + think it should be built in, say why. If it genuinely can't be done from + outside, say that — it's a strong argument. + validations: + required: true + + - type: textarea + id: non-goals + attributes: + label: Non-goals + description: | + What are you explicitly **not** asking for? This is the most useful line + in a feature request and almost nobody writes it — it tells us where the + edges of your idea are. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives you considered + description: Including the ones you rejected, and why. + validations: + required: false + + - type: textarea + id: context + attributes: + label: Mockups, prior art, or other context + description: | + Screenshots, sketches, or examples of other tools that get this right. + Drag files in to attach them. + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 238878c74..0bf9b22be 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,9 @@ + + ## Summary diff --git a/.github/workflows/close-external-prs.yml b/.github/workflows/close-external-prs.yml new file mode 100644 index 000000000..cfdd0a8cb --- /dev/null +++ b/.github/workflows/close-external-prs.yml @@ -0,0 +1,77 @@ +# Berd does not accept pull requests from outside the maintainer team. +# +# GitHub offers no way to stop anyone from opening a PR against a public repo, +# so we close them politely and point back at CONTRIBUTING.md. Branch protection +# already makes an outside merge impossible; this exists so nobody sinks time +# into a patch we can't take, and so the PR queue stays readable. +# +# Uses pull_request_target so the token has write access even for fork PRs. +# It never checks out or runs any PR code — only the GitHub API calls below. +name: Close external pull requests + +on: + pull_request_target: + types: [opened, reopened] + +permissions: + pull-requests: write + +jobs: + close: + runs-on: ubuntu-latest + # Cheap pre-filter: OWNER/MEMBER/COLLABORATOR never need the API check. + if: >- + github.event.pull_request.author_association != 'OWNER' && + github.event.pull_request.author_association != 'MEMBER' && + github.event.pull_request.author_association != 'COLLABORATOR' && + github.event.pull_request.user.type != 'Bot' + steps: + - uses: actions/github-script@v7 + with: + script: | + const author = context.payload.pull_request.user.login; + const pull_number = context.payload.pull_request.number; + const { owner, repo } = context.repo; + + // author_association can read as CONTRIBUTOR for maintainers whose + // org membership is private, so confirm against real permissions. + // Anything at write or above is on the team. + let permission = 'none'; + try { + const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ + owner, repo, username: author, + }); + permission = data.permission; + } catch (error) { + // 404 means "not a collaborator" — treat as external. + if (error.status !== 404) throw error; + } + + if (['admin', 'maintain', 'write'].includes(permission)) { + core.info(`${author} has ${permission} permission — leaving PR open.`); + return; + } + + core.info(`${author} has ${permission} permission — closing PR #${pull_number}.`); + + await github.rest.issues.createComment({ + owner, repo, issue_number: pull_number, + body: [ + `Thanks for the interest, @${author} — and sorry for the automated reply.`, + '', + "**Berd doesn't accept pull requests from outside the maintainer team**, so this one is being closed automatically. It's a policy, not a judgment on your code, and we'd rather tell you now than let it sit.", + '', + "Berd is early and its architecture is still moving week to week. Reviewing outside patches against a design that keeps shifting costs us more than it saves, and it isn't fair to you either.", + '', + '**What we do want:** a well-formed issue. A bug report with clean reproduction steps is worth more to us right now than a patch, because it\'s the part we genuinely can\'t do ourselves.', + '', + '- [How to participate](https://github.com/block/berd/blob/main/CONTRIBUTING.md)', + '- [Open an issue](https://github.com/block/berd/issues/new/choose)', + '', + "You're also free to fork and build on Berd however you like — it's Apache 2.0.", + ].join('\n'), + }); + + await github.rest.pulls.update({ + owner, repo, pull_number, state: 'closed', + }); diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000..7cf525ab4 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,9 @@ +# Berd code owners. +# +# `main` requires code-owner review, so this file is what makes that protection +# real — without it, the rule matches nobody and passes trivially. +# +# Format: https://docs.github.com/articles/about-code-owners + +# Default owners for everything in the repo. +* @block/berd-oss-team diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01575f2b5..c491e98cc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1 +1,218 @@ -## [Block General Contribution Guidelines](https://github.com/block/.github/blob/main/CONTRIBUTING.md) +# Contributing to Berd + +Berd is developed by a small team at Block, in the open. You can read every line +of the source, build it yourself, fork it, and tell us when it breaks. + +**We do not accept pull requests from outside the maintainer team.** Please do +not spend your time on one — see [Why we don't take outside PRs](#why-we-dont-take-outside-prs) +below. + +**The way to participate is to open a well-formed issue.** A good issue is +genuinely valuable to us and takes real effort to write. This document tells you +exactly what "well-formed" means. + +- [Filing an issue](#filing-an-issue) + - [Using an agent](#using-an-agent) + - [Before you file](#before-you-file) + - [Bug reports](#bug-reports) + - [Feature requests](#feature-requests) +- [What happens next](#what-happens-next) +- [Why we don't take outside PRs](#why-we-dont-take-outside-prs) +- [Security issues](#security-issues) +- [Building Berd yourself](#building-berd-yourself) +- [For maintainers](#for-maintainers) + +--- + +## Filing an issue + +Open issues at **https://github.com/block/berd/issues/new/choose**. + +There are two kinds, and the forms enforce the required fields: + +| Kind | Use it when | +| --- | --- | +| **Bug report** | Berd does something other than what it says it does. | +| **Feature request** | You want Berd to do something it doesn't, or to do something existing noticeably better. | + +Free-form issues are disabled. Pick a form. + +### Using an agent + +You're welcome — encouraged, really — to have a coding agent help you write the +issue. It's good at gathering version numbers, trimming logs, and writing crisp +repro steps. Paste this to your agent of choice: + +``` +Read https://raw.githubusercontent.com/block/berd/main/CONTRIBUTING.md +and help me file a Berd issue. Interview me for anything the guide +requires that I haven't given you, and tell me if what I'm reporting +is actually two separate issues. +``` + +Two rules if you do: + +- **You are the author, not the agent.** Read what it wrote before you post it. + If you can't answer a question about your own issue, it isn't ready. +- **Do not let it invent details.** An agent guessing at a version number or + paraphrasing an error it never saw is worse than a blank field. Write + "unknown" instead. + +We can tell the difference between an agent that helped you investigate and an +agent that padded a thin report into something that looks thorough. The second +kind gets closed. + +### Before you file + +Every issue must clear these three bars. The forms ask you to confirm each one. + +**1. Search first.** Look through +[open and closed issues](https://github.com/block/berd/issues?q=is%3Aissue). +Link the closest thing you found, or say "none found". If someone already +reported it, add your details to that thread — a second data point on an +existing bug is more useful than a duplicate. + +**2. Reproduce on the current version.** Update to the +[latest release](https://github.com/block/berd/releases) and confirm the problem +is still there. We can't act on reports against builds we've already moved past. + +**3. One issue per issue.** If your report has an "and also", split it. Bundled +issues can't be triaged, assigned, or closed cleanly. + +### Bug reports + +A bug report earns its keep by letting a maintainer reproduce the problem +without asking you anything. That means: + +**Steps to reproduce** — numbered, starting from a freshly launched Berd. +Include what you clicked, what you typed, which model and provider you were +using, and whether the chat had prior history. "Send a message and it hangs" is +not reproducible. "New chat, Claude Sonnet via Anthropic, ask it to read a file +over 2MB, hangs at ~10s" is. + +**Expected vs. actual** — two separate statements. Skipping "expected" seems +obvious to you and frequently isn't to us; sometimes the answer is that Berd is +working as designed and the design is wrong, which is a different fix. + +**Frequency** — every time, intermittently, or once. This changes how we chase +it more than almost anything else you can tell us. + +**Version and platform** — exact version and OS. In Berd: +**Settings → About**. If Berd won't launch, say so and give us your OS. + +**Logs** — the relevant excerpt, not the whole file, and not a screenshot of +text. The app log is `berd.log`, alongside rotated `berd_.log` +archives: + +| Platform | Path | +| --- | --- | +| macOS | `~/Library/Logs/xyz.block.berd/` | +| Linux | `~/.local/share/xyz.block.berd/logs/` | +| Windows | `%LOCALAPPDATA%\xyz.block.berd\logs\` | + +If the problem involves the agent backend rather than the app shell — a hung +turn, a tool that never returns, a model error — the backend keeps its own logs +under the Goose state directory (`~/Library/Application Support/Block/goose/state/logs/` +on macOS, `~/.local/state/Block/goose/logs/` on Linux). The `server/` subtree is +usually the interesting one. + +Find the lines around when the problem happened and paste those, in a fenced +code block. **Scrub them first** — logs can contain file paths, prompts, and +project names you may not want public. If there's genuinely nothing relevant, +say "no relevant log output" so we know you looked. + +**Screenshots or a recording** for anything visual. A five-second capture of a +layout glitch saves an hour of back-and-forth. + +### Feature requests + +The bar here is different: we need to understand the *problem*, not just your +proposed solution. + +**The problem, in your terms** — what were you trying to get done, and what +made it hard? Lead with this. A request framed only as a solution ("add a +setting for X") hides the problem behind it, and the problem often has a better +answer than the one you'd have asked for. + +**What you do today** — your current workaround, however ugly, or "nothing, I +gave up". This tells us how much the gap actually costs you. + +**Why it belongs in Berd** — Berd is extensible on purpose. Before asking for +core surface area, consider whether it could be a +[skill](https://github.com/block/berd/tree/main/.agents/skills), an agent, an +extension, or an automation. If it could and you still think it should be +built in, say why. If it genuinely can't be done from outside, say that — it's +a strong argument. + +**Non-goals** — what you're explicitly *not* asking for. This is the single most +useful line in a feature request and almost nobody writes it. It tells us where +the edges of your idea are. + +**Alternatives you considered** — including the ones you rejected, and why. + +--- + +## What happens next + +We triage on a best-effort basis. Berd is built by a small team with its own +roadmap, and no timeline is promised. + +Your issue will get one of: + +- **A label and a place in the queue** — we understand it and it's real. +- **`needs-info`** — we can't act yet. Answer the questions and it comes back to + the queue. If a `needs-info` issue goes quiet for 30 days, we close it; comment + any time to reopen. +- **Closed as duplicate** — with a link to the original. Follow that thread. +- **Closed as out of scope** — with a reason. This isn't a judgment on the idea; + Berd just isn't going to be the thing that does it. + +Closed doesn't mean unwelcome. A clearly-written out-of-scope request still tells +us something about what people want. + +--- + +## Why we don't take outside PRs + +Berd is early, and its architecture is still moving underneath us. Reviewing +external patches against a design that's changing weekly costs us more than it +saves, and it isn't fair to you — we'd be sitting on your work while the ground +shifts under it. + +Anyone can open a PR against a public repo; GitHub offers no way to prevent it. +So PRs from outside the maintainer team are **closed automatically** with a +pointer back to this document. That's a policy, not a comment on your code. + +What we want from you instead is the issue. A well-researched bug report with +clean repro steps is worth more to us right now than a patch, because it's the +part we can't do ourselves. + +If this changes, it'll change here first. + +--- + +## Security issues + +**Do not open a public issue for a security vulnerability.** See +[SECURITY.md](SECURITY.md) for private disclosure. + +--- + +## Building Berd yourself + +You don't need our permission to build, run, fork, or modify Berd — it's Apache +2.0 licensed. See the [README](README.md) for `just setup` and `just dev`, and +[AGENTS.md](AGENTS.md) for how the codebase is organized. + +Building it locally is also the best way to write a great bug report. + +--- + +## For maintainers + +Contribution setup, review expectations, and the Block-wide baseline: + +- [Block General Contribution Guidelines](https://github.com/block/.github/blob/main/CONTRIBUTING.md) +- [Code of Conduct](CODE_OF_CONDUCT.md) — applies to everyone, in issues and PRs alike +- [AGENTS.md](AGENTS.md) and [LAWS](LAWS) — architecture rules the codebase is held to +- [DESIGN.md](DESIGN.md) — design system and token usage diff --git a/README.md b/README.md index 87ff86005..b07c345cb 100644 --- a/README.md +++ b/README.md @@ -68,11 +68,30 @@ in dev builds and off in production builds. Use `.agents/skills/experimental-features/SKILL.md` for the current workflow, registry contract, storage rules, Tauri guardrails, and test coverage. -## Contributing +## Participating + +Berd is built by a small team at Block, in the open. You can read the source, +build it, and fork it freely — but **we don't accept pull requests from outside +the maintainer team**, and outside PRs are closed automatically. + +The way to participate is to **open a well-formed issue**. A bug report we can +reproduce is worth more to us than a patch, because it's the part we can't do +ourselves. [CONTRIBUTING.md](CONTRIBUTING.md) spells out exactly what each kind +of issue needs; the [issue forms](https://github.com/block/berd/issues/new/choose) +require it. + +Filing one? Hand this to your coding agent: + +``` +Read https://raw.githubusercontent.com/block/berd/main/CONTRIBUTING.md +and help me file a Berd issue. Interview me for anything the guide +requires that I haven't given you, and tell me if what I'm reporting +is actually two separate issues. +``` -See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution setup and expectations. Please also review the [Code of Conduct](CODE_OF_CONDUCT.md) and -[Security Policy](SECURITY.md). +[Security Policy](SECURITY.md). Never report a security vulnerability as a +public issue. ## Useful commands From 605431ddf35a9ea5410aaf4a56d52c29befef7ff Mon Sep 17 00:00:00 2001 From: morgmart <98432065+morgmart@users.noreply.github.com> Date: Thu, 13 Aug 2026 18:29:18 -0500 Subject: [PATCH 2/4] chore: close inactive needs-info issues Warn after 23 inactive days and close after 30, but only for issues a maintainer has explicitly labeled needs-info. Any new activity cancels the close countdown. PRs and all other issue types are exempt. --- .github/workflows/close-needs-info.yml | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/close-needs-info.yml diff --git a/.github/workflows/close-needs-info.yml b/.github/workflows/close-needs-info.yml new file mode 100644 index 000000000..03d730f50 --- /dev/null +++ b/.github/workflows/close-needs-info.yml @@ -0,0 +1,49 @@ +# Keep the issue queue honest: once a maintainer marks an issue `needs-info`, +# the reporter has 30 days of inactivity to answer. We warn after 23 days and +# close 7 days later. Any new comment or edit resets the clock and removes the +# `closing-soon` label; maintainers remove `needs-info` once the answer is enough +# to resume triage. +name: Close inactive needs-info issues + +on: + schedule: + - cron: "17 14 * * *" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + # Only issues deliberately blocked on the reporter. Never touch PRs or + # any other kind of issue. + only-issue-labels: needs-info + days-before-issue-stale: 23 + days-before-issue-close: 7 + days-before-pr-stale: -1 + days-before-pr-close: -1 + + stale-issue-label: closing-soon + stale-issue-message: >- + We still need the information requested above to act on this issue. + It has been inactive for 23 days, so it will close automatically in + 7 days if there is no reply. Add the missing details in a comment + and the countdown will reset. + close-issue-message: >- + Closing because the information we need has not arrived after 30 + days. If you can provide it later, leave a comment with the missing + details and a maintainer can reopen the issue. + close-issue-reason: not_planned + + # A reply means the reporter is engaged. Keep `needs-info` until a + # maintainer confirms the answer is sufficient, but cancel the active + # close countdown immediately. + remove-issue-stale-when-updated: true From 693dd91191092af4a0fd11aa85b9edca510a45ec Mon Sep 17 00:00:00 2001 From: morgmart <98432065+morgmart@users.noreply.github.com> Date: Thu, 13 Aug 2026 18:36:23 -0500 Subject: [PATCH 3/4] fix: align participation automation with policy Define eligible PR authors consistently as authorized write collaborators, pin github-script by SHA, apply the rule to bots as well as people, and describe issue forms as the supported UI path rather than an API-level enforcement mechanism. Clarify that needs-info remains maintainer-owned after a reply. --- .github/ISSUE_TEMPLATE/config.yml | 6 +++--- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- .github/workflows/close-external-prs.yml | 9 ++++----- .github/workflows/close-needs-info.yml | 5 +++-- CONTRIBUTING.md | 25 ++++++++++++++---------- README.md | 2 +- 6 files changed, 28 insertions(+), 23 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 715dbacd6..81ec85125 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,6 +1,6 @@ -# Free-form issues are disabled on purpose: a well-formed issue is the one way -# to participate in Berd, so the forms ask for what we need to act on it. -# See CONTRIBUTING.md. +# The normal GitHub UI does not offer a blank issue: a well-formed issue is the +# supported way to participate in Berd, so the forms ask for what we need to act +# on it. API-created issues remain subject to the same policy. See CONTRIBUTING.md. blank_issues_enabled: false contact_links: - name: Questions about using Berd diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0bf9b22be..f79052629 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ diff --git a/.github/workflows/close-external-prs.yml b/.github/workflows/close-external-prs.yml index cfdd0a8cb..b733d7e34 100644 --- a/.github/workflows/close-external-prs.yml +++ b/.github/workflows/close-external-prs.yml @@ -1,4 +1,4 @@ -# Berd does not accept pull requests from outside the maintainer team. +# Berd does not accept pull requests from outside authorized repository collaborators. # # GitHub offers no way to stop anyone from opening a PR against a public repo, # so we close them politely and point back at CONTRIBUTING.md. Branch protection @@ -23,10 +23,9 @@ jobs: if: >- github.event.pull_request.author_association != 'OWNER' && github.event.pull_request.author_association != 'MEMBER' && - github.event.pull_request.author_association != 'COLLABORATOR' && - github.event.pull_request.user.type != 'Bot' + github.event.pull_request.author_association != 'COLLABORATOR' steps: - - uses: actions/github-script@v7 + - uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 with: script: | const author = context.payload.pull_request.user.login; @@ -59,7 +58,7 @@ jobs: body: [ `Thanks for the interest, @${author} — and sorry for the automated reply.`, '', - "**Berd doesn't accept pull requests from outside the maintainer team**, so this one is being closed automatically. It's a policy, not a judgment on your code, and we'd rather tell you now than let it sit.", + "**Berd doesn't accept pull requests from outside authorized repository collaborators**, so this one is being closed automatically. It's a policy, not a judgment on your code, and we'd rather tell you now than let it sit.", '', "Berd is early and its architecture is still moving week to week. Reviewing outside patches against a design that keeps shifting costs us more than it saves, and it isn't fair to you either.", '', diff --git a/.github/workflows/close-needs-info.yml b/.github/workflows/close-needs-info.yml index 03d730f50..832c20e27 100644 --- a/.github/workflows/close-needs-info.yml +++ b/.github/workflows/close-needs-info.yml @@ -13,10 +13,10 @@ on: permissions: contents: read issues: write - pull-requests: write jobs: stale: + if: github.repository == 'block/berd' runs-on: ubuntu-latest steps: - uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0 @@ -36,7 +36,8 @@ jobs: We still need the information requested above to act on this issue. It has been inactive for 23 days, so it will close automatically in 7 days if there is no reply. Add the missing details in a comment - and the countdown will reset. + and the countdown will reset. A maintainer will review the answer + and remove `needs-info` once the issue is actionable. close-issue-message: >- Closing because the information we need has not arrived after 30 days. If you can provide it later, leave a comment with the missing diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c491e98cc..5c034f4dd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,9 +3,9 @@ Berd is developed by a small team at Block, in the open. You can read every line of the source, build it yourself, fork it, and tell us when it breaks. -**We do not accept pull requests from outside the maintainer team.** Please do -not spend your time on one — see [Why we don't take outside PRs](#why-we-dont-take-outside-prs) -below. +**We do not accept pull requests from outside authorized repository +collaborators.** Please do not spend your time on one — see +[Why we don't take outside PRs](#why-we-dont-take-outside-prs) below. **The way to participate is to open a well-formed issue.** A good issue is genuinely valuable to us and takes real effort to write. This document tells you @@ -28,14 +28,17 @@ exactly what "well-formed" means. Open issues at **https://github.com/block/berd/issues/new/choose**. -There are two kinds, and the forms enforce the required fields: +There are two supported submission paths, and their forms require the fields +we need to triage: | Kind | Use it when | | --- | --- | | **Bug report** | Berd does something other than what it says it does. | | **Feature request** | You want Berd to do something it doesn't, or to do something existing noticeably better. | -Free-form issues are disabled. Pick a form. +The normal GitHub UI does not offer a blank issue. Pick a form. Issues that +bypass the forms through the API or other tooling are still held to the same +requirements and may be closed or sent back for missing information. ### Using an agent @@ -160,9 +163,10 @@ roadmap, and no timeline is promised. Your issue will get one of: - **A label and a place in the queue** — we understand it and it's real. -- **`needs-info`** — we can't act yet. Answer the questions and it comes back to - the queue. If a `needs-info` issue goes quiet for 30 days, we close it; comment - any time to reopen. +- **`needs-info`** — we can't act yet. Answer the questions and a maintainer + will review the reply, then remove the label once the issue is actionable. If + a `needs-info` issue stays quiet for around 30 days, automation closes it; + comment with the missing details any time to request reopening. - **Closed as duplicate** — with a link to the original. Follow that thread. - **Closed as out of scope** — with a reason. This isn't a judgment on the idea; Berd just isn't going to be the thing that does it. @@ -180,8 +184,9 @@ saves, and it isn't fair to you — we'd be sitting on your work while the groun shifts under it. Anyone can open a PR against a public repo; GitHub offers no way to prevent it. -So PRs from outside the maintainer team are **closed automatically** with a -pointer back to this document. That's a policy, not a comment on your code. +So PRs from outside authorized repository collaborators are **closed +automatically** with a pointer back to this document. That's a policy, not a +comment on your code. What we want from you instead is the issue. A well-researched bug report with clean repro steps is worth more to us right now than a patch, because it's the diff --git a/README.md b/README.md index b07c345cb..8b45cdbce 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ registry contract, storage rules, Tauri guardrails, and test coverage. Berd is built by a small team at Block, in the open. You can read the source, build it, and fork it freely — but **we don't accept pull requests from outside -the maintainer team**, and outside PRs are closed automatically. +authorized repository collaborators**, and outside PRs are closed automatically. The way to participate is to **open a well-formed issue**. A bug report we can reproduce is worth more to us than a patch, because it's the part we can't do From 46f1699b5e8f79a07e6f37c712638530ecde95db Mon Sep 17 00:00:00 2001 From: morgmart <98432065+morgmart@users.noreply.github.com> Date: Thu, 13 Aug 2026 18:37:22 -0500 Subject: [PATCH 4/4] chore: identify automated repository comments --- .github/workflows/close-external-prs.yml | 2 +- .github/workflows/close-needs-info.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/close-external-prs.yml b/.github/workflows/close-external-prs.yml index b733d7e34..185dea88d 100644 --- a/.github/workflows/close-external-prs.yml +++ b/.github/workflows/close-external-prs.yml @@ -56,7 +56,7 @@ jobs: await github.rest.issues.createComment({ owner, repo, issue_number: pull_number, body: [ - `Thanks for the interest, @${author} — and sorry for the automated reply.`, + `🤖 Thanks for the interest, @${author} — and sorry for the automated reply.`, '', "**Berd doesn't accept pull requests from outside authorized repository collaborators**, so this one is being closed automatically. It's a policy, not a judgment on your code, and we'd rather tell you now than let it sit.", '', diff --git a/.github/workflows/close-needs-info.yml b/.github/workflows/close-needs-info.yml index 832c20e27..0c8bc816c 100644 --- a/.github/workflows/close-needs-info.yml +++ b/.github/workflows/close-needs-info.yml @@ -33,13 +33,13 @@ jobs: stale-issue-label: closing-soon stale-issue-message: >- - We still need the information requested above to act on this issue. + 🤖 We still need the information requested above to act on this issue. It has been inactive for 23 days, so it will close automatically in 7 days if there is no reply. Add the missing details in a comment and the countdown will reset. A maintainer will review the answer and remove `needs-info` once the issue is actionable. close-issue-message: >- - Closing because the information we need has not arrived after 30 + 🤖 Closing because the information we need has not arrived after 30 days. If you can provide it later, leave a comment with the missing details and a maintainer can reopen the issue. close-issue-reason: not_planned