From 73770ce9d048095f99160681c5ee44946cdd105c Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 26 Sep 2026 11:51:09 -0400 Subject: [PATCH 01/16] chore(repo-sweep): seed hygiene sweep Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01EYihoan7ULtdu32i34NaTq From 5ef303f372a7fa3bfc55b98008b56cad2b05d9eb Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 26 Sep 2026 13:11:23 -0400 Subject: [PATCH 02/16] refactor: simplify local CI scripts and repin ci-workflows to v0.29.1 Repo-wide batch-simplify sweep (code and docs tiers). Each group was checked by a separate verifier that tried to find a behavior change. - .cursor/install.sh: one install_release helper for the six tarball installers and one ensure check for pinned versions. typos 1.50.1 and editorconfig-checker 3.11.2 now match the ci-workflows v0.29.1 defaults (SHA256s confirmed against the downloaded assets). - .cursor/check.sh: one run_lane runner. lane_eol now fails when git diff, mktemp, rev-parse or cp fails instead of reporting a clean index, and the script exits 1 outside a git checkout instead of passing lanes with nothing to check. - .github/workflows/ci.yml: every ci-workflows ref moved from v0.27.1 to v0.29.1; only comments changed in the actions this repo calls. - .github/scripts/pr-section-drift.mjs: tidied; exit codes, output and exports unchanged. Two duplicate tests merged (25 tests). - .gitignore: dropped a line the .claude/*.local.* glob already covered. - SECURITY.md, PULL_REQUEST_TEMPLATE.md: current GitHub docs URLs and the renamed "Security and quality" tab. - Em dashes removed from every file this repo owns. Scope decisions: - Which groups to run: code groups and the docs tier, all on Opus. - Tool versions: match the latest ci-workflows release (v0.29.1); versions past its defaults belong in ci-workflows. - Pre-existing lane_eol false pass: fix in this step. - ai-slop.json list-idiom history sentence: remove. - export PATH in check.sh: remove (no effect when PATH is exported). - Em dashes: remove from every repo-owned file; synced files change upstream in standards. - pr-body-contract.md sync status missing from README: left for a later docs step. Playbook: hygiene Playbook-Step: code-tidying:batch-simplify@0.23.2 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01EYihoan7ULtdu32i34NaTq --- .claude/ai-slop.json | 2 +- .cursor/check.sh | 144 +++++++-------------- .cursor/install.sh | 151 +++++++++------------- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/dependabot.yml | 4 +- .github/scripts/pr-section-drift.mjs | 74 ++++------- .github/scripts/pr-section-drift.test.mjs | 6 +- .github/workflows/ci.yml | 58 ++++----- .gitignore | 34 ++--- .work-item-tracker.json | 2 +- SECURITY.md | 4 +- 11 files changed, 181 insertions(+), 300 deletions(-) diff --git a/.claude/ai-slop.json b/.claude/ai-slop.json index 34087a1..8c6e65c 100644 --- a/.claude/ai-slop.json +++ b/.claude/ai-slop.json @@ -1,5 +1,5 @@ { "excluded_paths": [], "em_dash_allowed_paths": [], - "_comment": "Only text this repository does not own may be excluded here, and nothing currently qualifies. CODE_OF_CONDUCT.md is adapted from Contributor Covenant v2.1 under CC BY 4.0 and is maintained as this organization's own policy, so it is audited and edited like every other file. .claude/rules/pr-body-contract.md is sync-managed from melodic-software/standards; it stays in scope so findings there are reported and filed upstream, never edited here. The em-dash rule is zero-tolerance and runs on every file: the former '- **Term** — definition' list idiom was rewritten to '- **Term**: definition' rather than exempted. Before adding a path to either list, name whose text it is and why it cannot be changed here." + "_comment": "Only text this repository does not own may be excluded here, and nothing currently qualifies. CODE_OF_CONDUCT.md is adapted from Contributor Covenant v2.1 under CC BY 4.0 and is maintained as this organization's own policy, so it is audited and edited like every other file. .claude/rules/pr-body-contract.md is sync-managed from melodic-software/standards; it stays in scope so findings there are filed upstream, never edited here. The em-dash rule is zero-tolerance on every file. Before adding a path to either list, name whose text it is and why it cannot be changed here." } diff --git a/.cursor/check.sh b/.cursor/check.sh index 19ae2a1..c0a6f61 100755 --- a/.cursor/check.sh +++ b/.cursor/check.sh @@ -11,21 +11,25 @@ # when any lane fails. set -uo pipefail -cd -- "$(git rev-parse --show-toplevel 2>/dev/null || echo .)" || exit 1 +top="$(git rev-parse --show-toplevel)" && cd -- "$top" || exit 1 # Fall back onto a per-user bin in case install.sh placed tools there. case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) PATH="$HOME/.local/bin:$PATH" ;; esac -export PATH PASSED=() FAILED=() -record() { - local name="$1" rc="$2" - if [[ "$rc" -eq 0 ]]; then +heading() { printf '\n\033[1m── %s ──\033[0m\n' "$1" >&2; } + +# run_lane : run one lane under a heading and record its verdict. +run_lane() { + local name="$1" + shift + heading "$name" + if "$@"; then PASSED+=("$name") printf '\033[32m✓ %s\033[0m\n' "$name" >&2 else @@ -34,18 +38,26 @@ record() { fi } -heading() { printf '\n\033[1m── %s ──\033[0m\n' "$1" >&2; } - # --- Lanes with multi-step logic -------------------------------------------- +# typos skips hidden paths unless they are named. The synced _typos.toml +# cannot set ignore-hidden = false; CI's typos job has the same follow-up. +# Skip index entries that are gone from the worktree: an unstaged deletion is +# still listed, and typos exits 64 when an explicit path is missing. +lane_typos() { + local hidden=() path + while IFS= read -r -d '' path; do + [[ "$path" == .* && -f "$path" ]] && hidden+=("$path") + done < <(git ls-files -z) + typos --config _typos.toml . "${hidden[@]}" +} + lane_jsonschema() { local rc=0 forms=() f check-jsonschema --builtin-schema vendor.dependabot .github/dependabot.yml || rc=1 check-jsonschema --builtin-schema vendor.github-workflows .github/workflows/*.yml || rc=1 for f in .github/ISSUE_TEMPLATE/*.yml .github/ISSUE_TEMPLATE/*.yaml; do - [[ -e "$f" ]] || continue - [[ "$(basename -- "$f")" == config.yml ]] && continue - forms+=("$f") + [[ -e "$f" && "$(basename -- "$f")" != config.yml ]] && forms+=("$f") done if [[ ${#forms[@]} -eq 0 ]]; then # Match ci.yml's roster step: an empty set is a failed derivation, not a @@ -82,39 +94,27 @@ lane_shellcheck() { # there, leaving the caller's index and working tree untouched. CI itself # runs on a clean checkout, so this extra isolation is local-only. lane_eol() { - local tmp tmpindex tmpwt gitdir before after drift rc=0 - gitdir="$(git rev-parse --absolute-git-dir)" - tmp="$(mktemp -d)" - tmpindex="$tmp/index" - tmpwt="$tmp/wt" - mkdir -p "$tmpwt" - cp -- "$(git rev-parse --git-path index)" "$tmpindex" - before="$(GIT_DIR="$gitdir" GIT_INDEX_FILE="$tmpindex" git write-tree)" || { - rm -rf "$tmp" - return 1 - } - GIT_DIR="$gitdir" GIT_INDEX_FILE="$tmpindex" GIT_WORK_TREE="$tmpwt" git checkout-index --all || { - rm -rf "$tmp" - return 1 - } - GIT_DIR="$gitdir" GIT_INDEX_FILE="$tmpindex" GIT_WORK_TREE="$tmpwt" git add --renormalize -- . || { - rm -rf "$tmp" - return 1 - } - after="$(GIT_DIR="$gitdir" GIT_INDEX_FILE="$tmpindex" git write-tree)" || { - rm -rf "$tmp" - return 1 - } + local tmp gitdir before after drift rc=0 + tmp="$(mktemp -d)" || return 1 + gitdir="$(git rev-parse --absolute-git-dir)" && + mkdir -p "$tmp/wt" && + cp -- "$(git rev-parse --git-path index)" "$tmp/index" && + before="$(GIT_DIR="$gitdir" GIT_INDEX_FILE="$tmp/index" git write-tree)" && + GIT_DIR="$gitdir" GIT_INDEX_FILE="$tmp/index" GIT_WORK_TREE="$tmp/wt" git checkout-index --all && + GIT_DIR="$gitdir" GIT_INDEX_FILE="$tmp/index" GIT_WORK_TREE="$tmp/wt" git add --renormalize -- . && + after="$(GIT_DIR="$gitdir" GIT_INDEX_FILE="$tmp/index" git write-tree)" || rc=1 rm -rf "$tmp" - drift="$(git diff --name-only "$before" "$after")" - if [[ -z "$drift" ]]; then - echo "index EOL clean" - else + [[ "$rc" -eq 0 ]] || return 1 + if ! drift="$(git diff --name-only "$before" "$after")"; then + echo "eol-renormalize: git diff failed; cannot tell whether the index has EOL drift" >&2 + return 1 + fi + if [[ -n "$drift" ]]; then echo "EOL drift (fix: git add --renormalize . && git commit):" >&2 printf '%s\n' "$drift" >&2 - rc=1 + return 1 fi - return "$rc" + echo "index EOL clean" } lane_pr_section_drift() { @@ -126,65 +126,21 @@ lane_pr_section_drift() { # --- Run every lane --------------------------------------------------------- -heading markdown -markdownlint-cli2 --config .markdownlint-cli2.jsonc "**/*.md" -record markdown "$?" - -heading typos -# typos skips hidden paths unless they are named. The synced _typos.toml -# cannot set ignore-hidden = false; CI's typos job has the same follow-up. -# Skip index entries that are gone from the worktree: an unstaged deletion is -# still listed, and typos exits 64 when an explicit path is missing. -hidden=() -while IFS= read -r -d '' path; do - case "$path" in - .*) - if [[ -f "$path" ]]; then - hidden+=("$path") - fi - ;; - *) ;; - esac -done < <(git ls-files -z) -typos --config _typos.toml . "${hidden[@]}" -record typos "$?" - -heading editorconfig -ec -config .editorconfig-checker.json -record editorconfig "$?" - -heading gitleaks -gitleaks dir --config .gitleaks.toml --no-banner . -record gitleaks "$?" - -heading links -lychee --offline --no-progress --config lychee.toml \ +run_lane markdown markdownlint-cli2 --config .markdownlint-cli2.jsonc "**/*.md" +run_lane typos lane_typos +run_lane editorconfig ec -config .editorconfig-checker.json +run_lane gitleaks gitleaks dir --config .gitleaks.toml --no-banner . +run_lane links lychee --offline --no-progress --config lychee.toml \ "**/*.md" ".claude/**/*.md" ".github/**/*.md" -record links "$?" - -heading actionlint -actionlint -color -record actionlint "$?" - -heading jsonschema -lane_jsonschema -record jsonschema "$?" - -heading shellcheck -lane_shellcheck -record shellcheck "$?" - -heading eol-renormalize -lane_eol -record eol-renormalize "$?" - -heading pr-section-drift -lane_pr_section_drift -record pr-section-drift "$?" +run_lane actionlint actionlint -color +run_lane jsonschema lane_jsonschema +run_lane shellcheck lane_shellcheck +run_lane eol-renormalize lane_eol +run_lane pr-section-drift lane_pr_section_drift # --- Summary ---------------------------------------------------------------- -printf '\n\033[1m── ci-status ──\033[0m\n' >&2 +heading ci-status printf 'passed: %d failed: %d\n' "${#PASSED[@]}" "${#FAILED[@]}" >&2 if [[ ${#FAILED[@]} -gt 0 ]]; then printf 'failing lanes: %s\n' "${FAILED[*]}" >&2 diff --git a/.cursor/install.sh b/.cursor/install.sh index 926b396..34e8105 100755 --- a/.cursor/install.sh +++ b/.cursor/install.sh @@ -4,7 +4,7 @@ # This repo ships only community-health files, so its "build" is the same # lint/hygiene suite CI runs (see .github/workflows/ci.yml). That suite is a set # of standalone tools; this script installs each one pinned to the exact version -# the CI composite actions use (melodic-software/ci-workflows v0.17.2), so a +# the CI composite actions use (melodic-software/ci-workflows v0.29.1), so a # local run of .cursor/check.sh reproduces CI verdicts byte for byte. # # Idempotent and safe to re-run: every tool is skipped when the pinned version @@ -12,12 +12,12 @@ # SHA-256 the CI action pins before it is trusted (fail closed). set -euo pipefail -# --- Pins (authority: melodic-software/ci-workflows v0.17.2 action defaults) -- +# --- Pins (authority: melodic-software/ci-workflows v0.29.1 action defaults) -- MARKDOWNLINT_VERSION="0.23.2" -TYPOS_VERSION="1.49.0" -TYPOS_SHA256="48bd2d58e02ce713b8c0f1aa239e68ee4f7d8c551013135806e6aed3938d9e10" -EC_VERSION="3.11.1" -EC_SHA256="5a37922963248451e88149251e49f6ae08f69717a3918202a51fe9945e19691e" +TYPOS_VERSION="1.50.1" +TYPOS_SHA256="edf0545109aee6a22751d04ddecb97c45be47d3aa0409564fb895eeeace91b1e" +EC_VERSION="3.11.2" +EC_SHA256="bc815e5b3b1891a0ee9e1242fe3475312655f8b0f4c4a79510be0a009294571a" GITLEAKS_VERSION="8.30.1" GITLEAKS_SHA256="551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb" LYCHEE_VERSION="0.24.2" @@ -53,7 +53,7 @@ trap 'rm -rf "$WORK"' EXIT log() { printf 'install: %s\n' "$*" >&2; } -# verify_sha — abort the whole install on mismatch. A hygiene +# verify_sha : abort the whole install on mismatch. A hygiene # toolchain that silently installed an unverified binary is worse than a hard # failure the operator can see and re-run. verify_sha() { @@ -72,100 +72,71 @@ install_bin() { log "installed $name -> $BIN_DIR/$name" } -install_typos() { - local cur - cur="$(typos --version 2>/dev/null || true)" - if [[ "$cur" == *"$TYPOS_VERSION"* ]]; then - log "typos $TYPOS_VERSION present; skipping" - return 0 +# ensure