feat: add .commit-guard.yml config with ai-attribution guard - #1
feat: add .commit-guard.yml config with ai-attribution guard#1codywilliamson wants to merge 6 commits into
Conversation
…, custom types, warn mode, and branch filters
drops the jq dependency and fallback-parser formatting constraints; pure bash parsing locally, yq validation in ci, comments in the starter config
There was a problem hiding this comment.
Pull request overview
This PR introduces a per-repository .commit-guard.yml configuration file shared by both local hooks and CI, enabling centralized policy control (notably AI attribution handling) while preserving existing behavior via workflow-input fallbacks.
Changes:
- Add
.commit-guard.ymlsupport (with file-over-env/input precedence) for both the nativecommit-msghook and the CI lint runner. - Implement new policies:
ai-attribution(allow/warn/strip/block), customtypes,ban-patterns,enforce: warn, and push-branch filtering. - Update installers, workflow, docs, and tests to support/validate the new configuration and behavior.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| test/install.t.sh | Asserts installer now creates a starter .commit-guard.yml with expected defaults. |
| test/config-features.t.sh | Adds coverage for config parsing and new policy behavior (local + CI). |
| scripts/validate-commit-message.sh | Adds bash YAML parsing and enforces new policies in the native hook (including strip mode). |
| scripts/run-commitlint-ci.sh | Adds config loading, failure aggregation, annotations, branch filters, and policy checks in CI. |
| README.md | Documents the new config file, schema, precedence, and policy behavior. |
| install.sh | Adds flags and writes a starter .commit-guard.yml on new installs. |
| install.ps1 | Adds flags and writes a starter .commit-guard.yml on new installs (PowerShell). |
| docs/superpowers/specs/2026-07-19-config-features-design.md | Records design + JSON→YAML amendment and rationale. |
| CHANGELOG.md | Announces v0.3.0 features and behavior changes. |
| caller-template.yml | Notes that .commit-guard.yml overrides workflow inputs; documents new inputs. |
| .github/workflows/commitlint.yml | Adds inputs, validates YAML with yq, resolves preset from file, injects types, and passes new env vars. |
Comments suppressed due to low confidence (2)
scripts/validate-commit-message.sh:148
- Same as above: this
while readloop can drop the last line if the file has no trailing newline, which can unintentionally remove/keep the final line duringstrip.
while IFS= read -r line; do
scripts/run-commitlint-ci.sh:266
- Invalid
ban-patternsregexes are silently ignored becausegrep -Eexits 2 and theifcondition treats it as “no match”. This can make CI pass unexpectedly. Detect exit code 2 and record a failure for invalid patterns.
if grep -Eiq -- "$pattern" <<< "$message"; then
record_failure "${label} matches banned pattern: ${pattern}"
ok=1
fi
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| cat >&2 <<EOF | ||
| error: commit message must follow Conventional Commits. | ||
| while IFS= read -r line; do |
| local pattern | ||
| local keep | ||
|
|
||
| temp_file="$(mktemp)" |
| if grep -Eiq -- "$pattern" <<< "$message"; then | ||
| add_violation "commit message matches banned pattern: ${pattern}" | ||
| fi |
| matches="$(find_ai_attribution_lines "$message")" | ||
| if [[ -z "$matches" ]]; then | ||
| return 0 | ||
| fi | ||
|
|
||
| if [[ "$AI_ATTRIBUTION" == "warn" ]]; then | ||
| echo "::warning::${label} contains AI attribution: ${matches}" | ||
| return 0 |
| echo "" | ||
| echo "done! installed:" | ||
| echo " - CI workflow: ${WORKFLOW_FILE}" | ||
| echo " - Config: .commit-guard.yml" | ||
|
|
| Write-Host "" | ||
| Write-Host "Done! Installed:" -ForegroundColor Green | ||
| Write-Host " - CI workflow: $WorkflowFile" | ||
| Write-Host " - Config: .commit-guard.yml" |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5028d28ba1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| cat >&2 <<EOF | ||
| error: commit message must follow Conventional Commits. | ||
| while IFS= read -r line; do | ||
| lowered="${line,,}" |
There was a problem hiding this comment.
Avoid Bash 4-only lowercasing in native hook
On systems where /usr/bin/env bash is Bash 3.x, such as the default macOS shell, ${line,,} is unsupported and the native commit-msg hook exits with bad substitution. Because the installer now writes ai-attribution: block by default, this path runs for every commit in a newly installed native-hook repo, so even valid commit messages are blocked before validation completes.
Useful? React with 👍 / 👎.
| \"*\") | ||
| value="${value#\"}" | ||
| value="${value%\"}" |
There was a problem hiding this comment.
Strip comments before unquoting config values
For valid YAML like ai-attribution: "block" # keep strict, this parser enters the quoted branch first and leaves the trailing comment attached, producing the value block" # keep strict; enum validation then rejects the config even though the workflow's YAML validation accepts it and the README says comments and quoted values are supported. This affects the local hook here and the duplicated CI parser when users add inline comments to quoted scalar settings.
Useful? React with 👍 / 👎.
Summary
.commit-guard.ymlread by both CI and local hooks, so config lives in one place instead of being split across workflow inputs and installer flags. File values override workflow inputs; inputs remain as fallbacks, and defaults preserve v0.2 behavior exactly.ai-attributionpolicy (allow/warn/strip/block) to keep AI co-author trailers and "generated with" bylines out of commit history when agents commit.striprewrites the message locally; in CI it acts asblocksince pushed commits can't be rewritten.types, case-insensitiveban-patterns,enforce: warnmode for gradual adoption, and abranchespush filter.yq(preinstalled on runners).Changes
scripts/validate-commit-message.sh: reads the config with an inlined pure-bash flat-YAML parser; enforces types, ban patterns, and the AI-attribution policy (including in-place strip)scripts/run-commitlint-ci.sh: same config precedence; collects all failures instead of stopping at the first, emits::error/::warningannotations, honors warn mode and branch filters.github/workflows/commitlint.yml: newenforceandai-attributioninputs; resolves the preset from the config file and injectstypesinto the generated commitlint config viayq(a repo-local commitlint config still wins)install.sh/install.ps1:--ai-attributionand--enforceflags; write a commented starter.commit-guard.yml(new installs default toai-attribution: block, existing configs never overwritten)test/config-features.t.sh: 12 new cases covering every policy, parser quoting/comments, file-beats-env precedence, and branch skipsdocs/superpowers/specs/with an amendment recording the JSON→YAML changeTest plan
bash test/test.sh— full suite green, including the 12 new config-feature tests.commit-guard.ymlparses, hook installsyqexpressions verified against the real mikefarah binary (preset, types→JSON, invalid-YAML detection)install.ps1on a Windows machine (no pwsh available locally)