diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..0d27337 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,50 @@ +# Agent instructions for CodesWhat/.github + +This repository is the organization's meta layer: community health defaults, +the repository onboarding checklist (`REPOSITORY_ONBOARDING.md`), reusable CI +workflows, the organization profile README and its generator, and the +contract tests that pin the shapes other repositories depend on. + +## What lives here + +- `.github/workflows/go-ci.yml`, `node-ci.yml`, `release-gate.yml`, + `greptile-summon.yml`, `quality-report-aggregate.yml` — reusable workflows + consumed by other CodesWhat repositories. +- `.github/tests/` — contract tests. These are the public API of the org's + shared configs (the `greptile.json` shape, the quality-report v1 contract, + the reusable CI inputs). Change a contract test and its consumers together, + never one side alone. +- `profile/` — the organization profile README plus generated SVG assets + from `scripts/generate_profile_svg.py`. The untracked + `profile/font_reference.svg` is user-owned; leave it alone. + +## Rules that are specific to this repository + +- Consumers pin the reusable workflows to frozen full commit SHAs. Treat + every workflow change as breaking for pinned consumers: add new inputs + with safe defaults, never repurpose an existing input, and let consumers + adopt by rolling their pin deliberately. +- PRs target `dev/repository-standards`. `main` advances only through + promotion PRs. Reconcile before promoting: + `git merge -s ours origin/main -m "chore(sync): reconcile main before promotion"`. + Verify promotions with tree equality + (`git diff --quiet origin/main origin/dev/repository-standards`), never + commit ancestry. +- CodeRabbit auto-reviews PRs against `dev/*` branches only (scoped in + `.coderabbit.yaml`); summon it explicitly anywhere else and read its + inline comments before merging. +- Commits are plain Conventional Commits, `(scope): `, + no emoji, no AI attribution trailers. +- Never weaken branch protection or rulesets to land a change. + +## Validation + +Run before pushing (the lefthook pre-push hook runs the same set): + +```bash +bash scripts/validate.sh +``` + +That script mirrors the Standards Validation CI job: contract tests, Python +compile, YAML/JSON parse, markdownlint (with the separate profile config for +`profile/README.md`), and actionlint/zizmor when installed locally. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..af599c9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 CodesWhat + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000..3872369 --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,12 @@ +# Local git hooks. Install once with: npx --yes lefthook install +# pre-push mirrors the Standards Validation CI job via scripts/validate.sh. + +commit-msg: + commands: + conventional-commits: + run: bash scripts/check-commit-msg.sh {1} + +pre-push: + commands: + validate: + run: bash scripts/validate.sh diff --git a/scripts/check-commit-msg.sh b/scripts/check-commit-msg.sh new file mode 100755 index 0000000..3b3320e --- /dev/null +++ b/scripts/check-commit-msg.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# commit-msg hook: enforce plain Conventional Commits on the subject line. +set -euo pipefail + +msg_file="$1" +subject="$(head -n 1 "$msg_file")" + +case "$subject" in + "Merge branch '"*|"Merge pull request #"*|"Merge remote-tracking branch '"*|fixup!\ *|squash!\ *) exit 0 ;; +esac + +if [[ "$subject" =~ ^Revert\ \".+\"$ ]]; then + exit 0 +fi + +pattern='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9./-]+\))?!?: [^[:space:]]' +if ! [[ "$subject" =~ $pattern ]]; then + { + echo "commit subject must be plain Conventional Commits:" + echo " (scope): " + echo "allowed types: feat fix docs style refactor perf test build ci chore revert" + echo "got: $subject" + } >&2 + exit 1 +fi diff --git a/scripts/validate.sh b/scripts/validate.sh new file mode 100755 index 0000000..5d02c10 --- /dev/null +++ b/scripts/validate.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Local mirror of the Standards Validation CI job. Run before pushing; +# lefthook pre-push runs this same script. +set -euo pipefail +cd "$(git rev-parse --show-toplevel)" + +echo "==> clean tree" +if ! git diff --quiet || ! git diff --cached --quiet; then + echo "commit or stash local changes before pushing" >&2 + exit 1 +fi + +echo "==> contract tests" +python3 .github/tests/community_health_contract_test.py +python3 .github/tests/greptile_summon_contract_test.py +python3 .github/tests/greptile_config_contract_test.py +python3 .github/tests/quality_report_contract_test.py +python3 .github/tests/reusable_ci_contract_test.py + +echo "==> compile python" +python3 -m compileall -q . + +echo "==> parse yaml and json" +ruby -e 'require "yaml"; Dir.glob("**/*.{yml,yaml}", File::FNM_DOTMATCH).sort.each { |path| YAML.parse_file(path) }' +python3 -c 'import json; from pathlib import Path; [json.load(path.open()) for path in Path(".").rglob("*.json")]' + +echo "==> markdownlint" +npx --yes markdownlint-cli2@0.23.2 "**/*.md" "#profile/README.md" +npx --yes markdownlint-cli2@0.23.2 "profile/README.md" --config .github/markdownlint-profile.yaml + +echo "==> actionlint" +if command -v actionlint >/dev/null 2>&1; then + actionlint -color +else + echo "actionlint not installed locally; CI will run it" +fi + +echo "==> zizmor" +if command -v zizmor >/dev/null 2>&1; then + zizmor --no-online-audits .github/workflows/ +else + echo "zizmor not installed locally; CI will run it" +fi + +echo "==> ok"