diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..3262414 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,51 @@ +name: Bug Report +description: Report a bug in EmDash +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for reporting a bug. Please fill out the sections below so we can reproduce and fix it. + + - type: textarea + id: description + attributes: + label: Description + description: What happened? What did you expect to happen? + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to reproduce + description: Minimal steps to trigger the bug. Include code snippets, config, or a link to a reproduction repo if possible. + placeholder: | + 1. Create a collection with ... + 2. Navigate to ... + 3. Click ... + 4. See error + validations: + required: true + + - type: textarea + id: environment + attributes: + label: Environment + description: Relevant version info. + placeholder: | + - emdash version: x.x.x + - Node.js version: x.x.x + - Runtime: Node / Cloudflare Workers + - OS: macOS / Linux / Windows + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Logs / error output + description: Paste any relevant error messages or stack traces. + render: shell + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..872f508 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Feature request + url: https://github.com/emdash-cms/emdash/discussions/categories/ideas + about: Propose a feature in Discussions. Feature PRs without a prior approved Discussion will be closed. + - name: Question + url: https://github.com/emdash-cms/emdash/discussions/categories/q-a + about: Ask a question in Discussions. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..80e65f4 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,37 @@ +## What does this PR do? + + + +Closes # + +## Type of change + + + +- [ ] Bug fix +- [ ] Feature (requires [approved Discussion](https://github.com/emdash-cms/emdash/discussions/categories/ideas)) +- [ ] Refactor (no behavior change) +- [ ] Documentation +- [ ] Performance improvement +- [ ] Tests +- [ ] Chore (dependencies, CI, tooling) + +## Checklist + +- [ ] I have read [CONTRIBUTING.md](https://github.com/emdash-cms/emdash/blob/main/CONTRIBUTING.md) +- [ ] `pnpm typecheck` passes +- [ ] `pnpm --silent lint:json | jq '.diagnostics | length'` returns 0 +- [ ] `pnpm test` passes (or targeted tests for my change) +- [ ] `pnpm format` has been run +- [ ] I have added/updated tests for my changes (if applicable) +- [ ] New features link to an approved Discussion: https://github.com/emdash-cms/emdash/discussions/... + +## AI-generated code disclosure + + + +- [ ] This PR includes AI-generated code + +## Screenshots / test output + + diff --git a/.github/workflows/pr-compliance.yml b/.github/workflows/pr-compliance.yml new file mode 100644 index 0000000..f48bd9d --- /dev/null +++ b/.github/workflows/pr-compliance.yml @@ -0,0 +1,74 @@ +name: PR Compliance + +on: + pull_request: + branches: [main] + types: [opened, edited, synchronize] + +permissions: + contents: read + +jobs: + check-pr: + name: Validate PR + if: github.actor != 'dependabot[bot]' && github.actor != 'renovate[bot]' + runs-on: ubuntu-latest + steps: + - name: Check PR template + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const body = context.payload.pull_request.body || ''; + + const errors = []; + + // Must have a description (not just the raw template placeholder) + const descriptionSection = body.match(/## What does this PR do\?\s*\n([\s\S]*?)(?=\n## )/); + const description = descriptionSection?.[1]?.replace(//g, '').trim() || ''; + if (!description || description === 'Closes #') { + errors.push('Fill out the "What does this PR do?" section with a description of your change.'); + } + + // Must check at least one type + const typeChecks = [ + /- \[x\] Bug fix/i, + /- \[x\] Feature/i, + /- \[x\] Refactor/i, + /- \[x\] Documentation/i, + /- \[x\] Performance/i, + /- \[x\] Tests/i, + /- \[x\] Chore/i, + ]; + const hasType = typeChecks.some(re => re.test(body)); + if (!hasType) { + errors.push('Check at least one "Type of change" checkbox.'); + } + + // If Feature is checked, require a discussion link + const isFeature = /- \[x\] Feature/i.test(body); + if (isFeature) { + const hasDiscussionLink = /github\.com\/emdash-cms\/emdash\/discussions\/\d+/.test(body); + if (!hasDiscussionLink) { + errors.push('Feature PRs require a link to an approved Discussion (https://github.com/emdash-cms/emdash/discussions/categories/ideas). Open a Discussion first, get approval, then link it in the PR.'); + } + } + + // Must check the "I have read CONTRIBUTING.md" box + const hasReadContributing = /- \[x\] I have read \[CONTRIBUTING\.md\]/i.test(body); + if (!hasReadContributing) { + errors.push('Check the "I have read CONTRIBUTING.md" checkbox.'); + } + + if (errors.length > 0) { + const message = [ + '## PR template validation failed', + '', + 'Please fix the following issues by editing your PR description:', + '', + ...errors.map(e => `- ${e}`), + '', + 'See [CONTRIBUTING.md](https://github.com/emdash-cms/emdash/blob/main/CONTRIBUTING.md) for the full contribution policy.', + ].join('\n'); + + core.setFailed(message); + } diff --git a/AGENTS.md b/AGENTS.md index a0b3b56..b1ace99 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,6 +24,18 @@ This is a pre-release project. Do not add backwards compatibility or legacy patt **TDD for bugs.** Write a failing test -> fix the bug -> verify the test passes. A bug without a reproducing test is not fixed. +## Contribution Rules (for AI agents and human contributors) + +Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR. Key rules: + +- **Features require a prior approved Discussion.** Do not open a feature PR without one. It will be closed. Open a [Discussion](https://github.com/emdash-cms/emdash/discussions/categories/ideas) in the Ideas category first. +- **Bug fixes and docs** can be PRed directly. +- **Fill out the PR template completely.** Every section. Check every applicable checkbox. PRs with empty or skipped templates will be closed. +- **Check the AI disclosure box** in the PR template if any part of the code was AI-generated. +- **Do not make bulk/spray changes** (e.g., "fix all lint warnings", "add types everywhere", "improve error handling across codebase"). If you see a systemic issue, open a Discussion. +- **Do not touch code outside the scope of your change.** No drive-by refactors, no "while I'm here" improvements, no added comments or logging in unrelated files. +- **All CI checks must pass.** Typecheck, lint, format, and tests. No exceptions. + ## Workflow ### Before Starting @@ -47,7 +59,7 @@ You verified linting and types were clean before starting. If they're failing no 1. All tests pass: `pnpm test` 2. Full lint suite clean: `pnpm --silent lint:json | jq '.diagnostics | length'`. Returns JSON with stderr piped to /dev/null, so it won't break parsers. Fix any issues. 3. Format with `pnpm format` (oxfmt with tabs for indentation, configured in `.prettierrc`). -4. Open the PR with the `pr` skill +4. Open the PR with the `pr` skill. Fill out every section of the PR template. Check the AI disclosure box. ### Dev Servers diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6b5e790..a5278d2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -185,10 +185,41 @@ Your site will use `workspace:*` links to the local packages, so any changes you 4. Check authorization with `requirePerm()` on all state-changing routes. 5. Register the route in `packages/core/src/astro/integration/routes.ts`. +## Contribution Policy + +### What we accept + +| Type | Process | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| **Bug fixes** | Open a PR directly. Include a failing test that reproduces the bug. | +| **Docs / typos** | Open a PR directly. | +| **Features** | Open a [Discussion](https://github.com/emdash-cms/emdash/discussions/categories/ideas) first. Wait for approval before writing code. | +| **Refactors** | Open a Discussion first. Refactors are opinionated and need alignment. | +| **Performance** | Open a Discussion first with benchmarks showing the improvement. | + +**PRs that add features without a prior approved Discussion will be closed.** This isn't about gatekeeping — it's about not wasting your time on work that might not align with the project's direction. Talk to us first and we'll figure out the right approach together. + +### AI-generated PRs + +We welcome AI-assisted contributions. They are held to the same quality bar as any other PR: + +- The submitter is responsible for the code's correctness, not the AI tool. +- AI-generated PRs must pass all CI checks, follow the project's code patterns, and include tests. +- The PR template has an AI disclosure checkbox — please check it. This isn't punitive; it helps reviewers know to pay extra attention to edge cases that AI tools commonly miss. +- Bulk/spray PRs across the repo (e.g., "fix all lint warnings", "add types everywhere") will be closed. If you see a pattern worth fixing, open a Discussion first. + +### What we don't accept + +- **Drive-by feature additions.** If there's no Discussion, there's no PR. +- **Speculative refactors** that don't solve a concrete problem. +- **Dependency upgrades** outside of Renovate/Dependabot. We manage these centrally. +- **"Improvements"** to code you haven't been asked to change (added logging, extra error handling, style changes in unrelated files). + ## Commits and PRs - Branch from `main`. - Commit messages: describe _why_, not just _what_. +- Fill out the PR template completely. PRs with an empty template will be closed. - Ensure `pnpm typecheck` and `pnpm --silent lint:json` pass before pushing. - Run relevant tests.