diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..cde47ba --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,12 @@ +# Plain-language categories for native GitHub release notes. +changelog: + exclude: + labels: + - "autorelease: pending" + - "autorelease: tagged" + - "autorelease: failed" + categories: + - title: Breaking changes + labels: [breaking] + - title: Changes + labels: ["*"] diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 5c86934..e658101 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -52,6 +52,7 @@ jobs: - name: PR title is a Conventional Commit header env: PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} run: | # The title becomes the squash commit subject on main (K22-REPO-22), so it # must be a valid Conventional Commits 1.0 header of at most 100 characters. @@ -65,6 +66,15 @@ jobs: printf 'Title was: %s\n' "$PR_TITLE" exit 1 fi + node - <<'NODE' + const emoji = /\p{Emoji_Presentation}|[\u2600-\u27BF]|\p{Extended_Pictographic}\uFE0F|[#*0-9]\uFE0F?\u20E3/u; + for (const [field, text] of [['title', process.env.PR_TITLE], ['description', process.env.PR_BODY || '']]) { + if (emoji.test(text)) { + console.error(`::error title=Unprofessional pull request::The ${field} contains an emoji; use professional text.`); + process.exit(1); + } + } + NODE echo "PR title OK" dco: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c49bf19..6d472fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,6 +22,8 @@ themselves: everything below comes from the [SDLC policy](policies/sdlc.md). ## What a good change looks like +- Use professional wording in code comments, documentation, commit/PR messages, + release notes and automation output. No emojis, joke copy or bot sound effects. - A new or changed requirement follows the format in [policies/README.md](policies/README.md#requirement-ids): an ID that has never been used, a level, the rule, *Why*, and *Verified by*. A requirement nobody can verify is not diff --git a/configs/intellij/README.md b/configs/intellij/README.md index 8ec103e..bda9b8d 100644 --- a/configs/intellij/README.md +++ b/configs/intellij/README.md @@ -22,7 +22,7 @@ picks them up on open: *Settings → Editor → Code Style* shows **Project** se ## Per IDE (all projects) -1. **Code style:** *Settings → Editor → Code Style → ⚙ (Show Scheme Actions) → Import +1. **Code style:** *Settings → Editor → Code Style → Show Scheme Actions → Import Scheme → IntelliJ IDEA code style XML* → choose `Kingsrook_Code_Style.xml`. 2. **Reformat on save:** *Settings → Tools → Actions on Save* → enable **Reformat code** and **Optimize imports**. diff --git a/docs/releases.md b/docs/releases.md index e573b03..301c6bb 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -24,10 +24,17 @@ against it before packaging. Use `feat` for new guidance and `!` for new obligations or removed allowances as defined in [the versioning policy](../policies/README.md#versioning-of-the-standards). -Infrastructure changes appear in release notes and can produce PATCH releases; -`test`, `style`, and `chore` alone do not produce release notes. Review the proposed +Infrastructure changes can produce PATCH releases; +`test`, `style`, and `chore` alone do not trigger a version proposal. Review the proposed version and notes before merging. A `breaking` label alone does not change the version. +PR headers and footers are explicitly configured in `release-please-config.json`. +Native GitHub release notes use the plain-language categories in `.github/release.yml`, +keeping breaking changes visible without decorative symbols. Versions still come +from Conventional Commits; note entries link to reviewed PRs. Maintainers review +breaking-change descriptions before publication. Repository text and automation +output use professional wording, without emojis, joke copy or bot sound effects. + ## One-time maintainer setup 1. Keep **Settings → General → Releases → Enable release immutability** enabled. diff --git a/release-please-config.json b/release-please-config.json index 64b644a..e5020c0 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -3,18 +3,10 @@ "release-type": "simple", "include-component-in-tag": false, "bump-minor-pre-major": false, + "changelog-type": "github", + "pull-request-header": "Release proposal generated from reviewed changes on main. Review the version, changes, and validation before merging.", + "pull-request-footer": "Generated by [Release Please](https://github.com/googleapis/release-please) using this repository's release configuration.", "initial-version": "0.1.0", - "changelog-sections": [ - { "type": "security", "section": "Security", "hidden": false }, - { "type": "feat", "section": "Features", "hidden": false }, - { "type": "fix", "section": "Bug Fixes", "hidden": false }, - { "type": "docs", "section": "Documentation", "hidden": false }, - { "type": "perf", "section": "Performance", "hidden": false }, - { "type": "refactor", "section": "Refactoring", "hidden": false }, - { "type": "build", "section": "Build", "hidden": false }, - { "type": "ci", "section": "Automation", "hidden": false }, - { "type": "revert", "section": "Reverts", "hidden": false } - ], "packages": { ".": { "version-file": "version.txt" } } diff --git a/standards/ai-agents.md b/standards/ai-agents.md index 5c13f6f..9cb277c 100644 --- a/standards/ai-agents.md +++ b/standards/ai-agents.md @@ -117,7 +117,10 @@ the pull request description discloses it, per **K22-AGENT-41 (SHOULD)** An agent reports in concise plain language: what changed, why, what was verified, and what limitations remain. Document length scales with the -task; decoration (emojis, filler praise) is omitted unless asked for. +task. Repository text, including code comments, documentation, commits, PRs, release +notes and generated automation messages, uses professional wording. Omit emojis, +joke copy, filler praise and bot sound effects. Configure third-party automation to +follow the same rule; its default templates are not an exception. *Why:* the report is the maintainer's primary review input. *Verified by:* review. ## Context economy diff --git a/templates/repo/CONTRIBUTING.md b/templates/repo/CONTRIBUTING.md index 0a6c85c..b37679c 100644 --- a/templates/repo/CONTRIBUTING.md +++ b/templates/repo/CONTRIBUTING.md @@ -1,5 +1,8 @@ # Contributing to {{PROJECT_NAME}} +Use professional wording in code comments, documentation, commit/PR messages, +release notes and automation output. No emojis, joke copy or bot sound effects. + Thanks for helping. This project follows the [KofTwentyTwo standards](https://github.com/KofTwentyTwo/standards); this page is the short version of what they ask of a contribution. diff --git a/tools/Build-StandardsPackage.ps1 b/tools/Build-StandardsPackage.ps1 index 8660577..ec7e60a 100644 --- a/tools/Build-StandardsPackage.ps1 +++ b/tools/Build-StandardsPackage.ps1 @@ -44,7 +44,9 @@ if($committedVersion -ne $Version -or $releaseManifest['.'] -ne $Version) $changelog = (git -C $repository show "${commit}:CHANGELOG.md") -join "`n" $escapedVersion = [regex]::Escape($Version) -$section = [regex]::Match($changelog, "(?ms)^## (?:\[$escapedVersion\](?:\([^\r\n]*\))?|$escapedVersion)(?=\s|$)[^\r\n]*\r?\n.*?(?=^## |\z)") +# Native release-note categories also use H2; only a version heading ends a release. +$releaseHeading = '^## (?:\[\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?\](?:\([^\r\n]*\))?|\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)(?=\s|$)' +$section = [regex]::Match($changelog, "(?ms)^## (?:\[$escapedVersion\](?:\([^\r\n]*\))?|$escapedVersion)(?=\s|$)[^\r\n]*\r?\n.*?(?=$releaseHeading|\z)") if(-not $section.Success) { throw "CHANGELOG.md has no release notes for $Version at $commit." diff --git a/tools/Test-StandardsPackage.ps1 b/tools/Test-StandardsPackage.ps1 index 0b9334b..4468097 100644 --- a/tools/Test-StandardsPackage.ps1 +++ b/tools/Test-StandardsPackage.ps1 @@ -63,6 +63,14 @@ Future notes. Current notes. +## Changes + +Native category notes. + +## Breaking changes + +Current breaking details. + ## 1.2.2 Older notes. @@ -100,6 +108,7 @@ $manifest = Get-Content -LiteralPath (Join-Path $first "$prefix.manifest.json") Test-Condition ($manifest.version -eq '1.2.3' -and $manifest.commit -eq (git -C $source rev-parse HEAD)) 'manifest identifies version and exact source commit' $notes = Get-Content -LiteralPath (Join-Path $first "$prefix.notes.md") -Raw Test-Condition ($notes -match 'Current notes' -and $notes -notmatch 'Older notes|Future notes' -and $notes.Contains($checklist)) 'notes contain only this release and its checklist' +Test-Condition ($notes -match 'Native category notes' -and $notes -match 'Current breaking details') 'notes preserve native H2 categories within a release' foreach($file in (Get-ChildItem -LiteralPath $first -File)) { Test-Condition ((Get-FileHash -LiteralPath $file.FullName).Hash -eq (Get-FileHash -LiteralPath (Join-Path $second $file.Name)).Hash) "$($file.Name) is reproducible" @@ -115,6 +124,14 @@ Test-Exception { & $builder -Version '1.2.4' -RepositoryPath $source -OutputPath Test-Exception { & $builder -Version '01.2.3' -RepositoryPath $source } 'ValidatePattern|validation|pattern' Test-Exception { & $builder -Version '1.2.3' -RepositoryPath $source -OutputPath $first } 'already exists' Test-Exception { & $builder -Version '1.2.3' -RepositoryPath $source -OutputPath (Join-Path $fixtureRoot 'invalid-url') -ChecklistUrl 'http://example.com/123' } 'GitHub issue URL' +$nativeChangelog = (Get-Content -LiteralPath (Join-Path $source 'CHANGELOG.md') -Raw).Replace('## [1.2.3](https://example.com/current)', '## 1.2.3') +Set-Content -LiteralPath (Join-Path $source 'CHANGELOG.md') -Value $nativeChangelog +git -C $source add -- CHANGELOG.md +git -C $source -c user.name=Fixture -c user.email=fixture@example.invalid -c commit.gpgsign=false commit --quiet -m 'test: native release heading fixture' +$nativeOutput = Join-Path $fixtureRoot 'native-headings' +& $builder -Version '1.2.3' -RepositoryPath $source -OutputPath $nativeOutput +$nativeNotes = Get-Content -LiteralPath (Join-Path $nativeOutput "$prefix.notes.md") -Raw +Test-Condition ($nativeNotes -match 'Native category notes' -and $nativeNotes -match 'Current breaking details' -and $nativeNotes -notmatch 'Older notes|Future notes') 'native unlinked version heading retains only its release categories' Set-Content -LiteralPath (Join-Path $source 'CHANGELOG.md') -Value '# Changelog without release notes' git -C $source add -- CHANGELOG.md git -C $source -c user.name=Fixture -c user.email=fixture@example.invalid -c commit.gpgsign=false commit --quiet -m 'test: missing release notes fixture'