chore: add reviewer-feedback guardrails (CLAUDE.md, pre-commit hook, skill) - #665
Conversation
…skill) Analysis of ~50 PRs from the past week identified 10 recurring themes in Copilot and Gemini code review comments. This change addresses them at development time through three layers: 1. CLAUDE.md additions (7 new rules): - Transaction safety for multi-step DB operations - UTF-8 string safety (no byte-index slicing) - Case-insensitive comparisons for paths/media types - Decorator/wrapper trait method delegation - Sensitive data redaction in logs/SSE - tempfile crate for test temporary files - Trust boundaries for worker container data 2. Pre-commit hook (scripts/pre-commit-safety.sh): Mechanical checks for unsafe byte slicing, case-sensitive extension comparisons, hardcoded /tmp paths, unredacted tool parameter logging, and non-transactional DB operations. Installed via dev-setup.sh alongside existing commit-msg hook. 3. Review checklist skill (skills/review-checklist/SKILL.md): Activates on "review"/"merge" keywords. Covers the judgment-based items that can't be linted: transaction safety, SSRF validation, approval checks, decorator delegation, test quality, and doc accuracy. [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a set of guardrails designed to proactively address common code quality issues frequently identified by AI code reviewers. It aims to improve code robustness and reduce review cycles by catching potential problems earlier in the development process by adding new development rules, an automated pre-commit hook, and a review checklist skill. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces several guardrails to improve code quality, including new development rules in CLAUDE.md, a pre-commit hook to catch common issues, and a review checklist skill. The changes are well-structured and address recurring problems. I've suggested a performance improvement for the new pre-commit script to make it faster for developers.
Note: Security Review is unavailable for this PR.
| # Support both pre-commit hook (staged files) and standalone (all changed vs main) | ||
| if git diff --cached --quiet 2>/dev/null; then | ||
| # No staged changes -- compare working tree against main | ||
| DIFF_CMD="git diff origin/main -- " | ||
| else | ||
| DIFF_CMD="git diff --cached -U0 -- " | ||
| fi | ||
|
|
||
| WARNINGS=0 | ||
|
|
||
| warn() { | ||
| if [ "$WARNINGS" -eq 0 ]; then | ||
| echo "" | ||
| echo "=== Pre-commit Safety Checks ===" | ||
| echo "" | ||
| fi | ||
| WARNINGS=$((WARNINGS + 1)) | ||
| echo " [$1] $2" | ||
| } | ||
|
|
||
| # 1. Unsafe UTF-8 byte slicing: &s[..N] or &s[..some_var] on strings | ||
| # Safe patterns: is_char_boundary, char_indices, // safety: | ||
| if $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+' | grep -E '\[\.\..*\]' | grep -vE 'is_char_boundary|char_indices|// safety:|as_bytes|Vec<|&\[u8\]|\[u8\]|bytes\(\)|&bytes' | head -3 | grep -q .; then | ||
| warn "UTF8" "Possible unsafe byte-index string slicing. Use is_char_boundary() or char_indices()." | ||
| $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+' | grep -E '\[\.\..*\]' | grep -vE 'is_char_boundary|char_indices|// safety:|as_bytes|Vec<|&\[u8\]|\[u8\]|bytes\(\)|&bytes' | head -3 | sed 's/^/ /' | ||
| fi | ||
|
|
||
| # 2. Case-sensitive file extension or media type checks | ||
| # Match: .ends_with(".png") or == "image/jpeg" without prior to_lowercase | ||
| if $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+.*ends_with\("\.([pP][nN][gG]|[jJ][pP][eE]?[gG]|[gG][iI][fF]|[wW][eE][bB][pP]|[mM][dD])"\)' | grep -vE 'to_lowercase|to_ascii_lowercase|// safety:' | head -3 | grep -q .; then | ||
| warn "CASE" "Case-sensitive file extension comparison. Normalize to lowercase first." | ||
| $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+.*ends_with\("\.([pP][nN][gG]|[jJ][pP][eE]?[gG]|[gG][iI][fF]|[wW][eE][bB][pP]|[mM][dD])"\)' | grep -vE 'to_lowercase|to_ascii_lowercase|// safety:' | head -3 | sed 's/^/ /' | ||
| fi | ||
|
|
||
| # 3. Hardcoded /tmp paths in test files | ||
| if $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+.*"/tmp/' | grep -vE 'tempfile|tempdir|// safety:' | head -3 | grep -q .; then | ||
| warn "TMPDIR" "Hardcoded /tmp path. Use tempfile::tempdir() for parallel-safe tests." | ||
| $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+.*"/tmp/' | grep -vE 'tempfile|tempdir|// safety:' | head -3 | sed 's/^/ /' | ||
| fi | ||
|
|
||
| # 4. Logging tool parameters without redaction | ||
| if $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+.*tracing::(info|debug|warn|error).*param' | grep -vE 'redact|// safety:' | head -3 | grep -q .; then | ||
| warn "REDACT" "Logging tool parameters without redaction. Use redact_params() first." | ||
| $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+.*tracing::(info|debug|warn|error).*param' | grep -vE 'redact|// safety:' | head -3 | sed 's/^/ /' | ||
| fi | ||
|
|
||
| # 5. Multi-step DB operations without transaction | ||
| if $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+.*(\.execute\(|\.query\()' | head -1 | grep -q .; then | ||
| # Check if there are multiple execute/query calls in the same hunk without transaction/tx | ||
| HUNK_COUNT=$($DIFF_CMD '*.rs' 2>/dev/null | awk ' | ||
| /^@@/ { count=0; has_tx=0 } | ||
| /^\+.*\.(execute|query)\(/ { count++ } | ||
| /^\+.*(transaction|\.tx\.|begin)/ { has_tx=1 } | ||
| /^@@/ { if (prev_count >= 2 && !prev_tx) found++ } | ||
| { prev_count=count; prev_tx=has_tx } | ||
| END { if (count >= 2 && !has_tx) found++; print found+0 } | ||
| ') | ||
| if [ "$HUNK_COUNT" -gt 0 ]; then | ||
| warn "TX" "Multiple DB operations in same hunk without transaction. Wrap in a transaction for atomicity." | ||
| fi | ||
| fi | ||
|
|
||
| if [ "$WARNINGS" -gt 0 ]; then | ||
| echo "" | ||
| echo "Found $WARNINGS potential issue(s). Fix them or add '// safety: <reason>' to suppress." | ||
| echo "" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
This script is a great addition for catching common issues early. However, it currently calls git diff up to 10 times, which can be slow, especially on large changesets. You can significantly improve performance by running git diff just once at the beginning and caching its output in a variable. This variable can then be piped to all subsequent grep and awk commands.
I've also added an early exit if there are no relevant changes to check, which further improves performance for commits that don't touch .rs files.
# Support both pre-commit hook (staged files) and standalone (all changed vs main)
if git diff --cached --quiet 2>/dev/null; then
# No staged changes -- compare working tree against main
DIFF_CMD="git diff origin/main -- "
else
DIFF_CMD="git diff --cached -U0 -- "
fi
# Cache the diff output to avoid multiple expensive git calls
DIFF_OUTPUT=$($DIFF_CMD '*.rs' 2>/dev/null)
# If there are no relevant changes, exit early.
if [ -z "$DIFF_OUTPUT" ]; then
exit 0
fi
WARNINGS=0
warn() {
if [ "$WARNINGS" -eq 0 ]; then
echo ""
echo "=== Pre-commit Safety Checks ==="
echo ""
fi
WARNINGS=$((WARNINGS + 1))
echo " [$1] $2"
}
# 1. Unsafe UTF-8 byte slicing: &s[..N] or &s[..some_var] on strings
# Safe patterns: is_char_boundary, char_indices, // safety:
if echo "$DIFF_OUTPUT" | grep -nE '^\+' | grep -E '\[\.\..*\]' | grep -vE 'is_char_boundary|char_indices|// safety:|as_bytes|Vec<|&\[u8\]|\[u8\]|bytes\(\)|&bytes' | head -3 | grep -q .; then
warn "UTF8" "Possible unsafe byte-index string slicing. Use is_char_boundary() or char_indices()."
echo "$DIFF_OUTPUT" | grep -nE '^\+' | grep -E '\[\.\..*\]' | grep -vE 'is_char_boundary|char_indices|// safety:|as_bytes|Vec<|&\[u8\]|\[u8\]|bytes\(\)|&bytes' | head -3 | sed 's/^/ /'
fi
# 2. Case-sensitive file extension or media type checks
# Match: .ends_with(".png") or == "image/jpeg" without prior to_lowercase
if echo "$DIFF_OUTPUT" | grep -nE '^\+.*ends_with\("\.([pP][nN][gG]|[jJ][pP][eE]?[gG]|[gG][iI][fF]|[wW][eE][bB][pP]|[mM][dD])"\)' | grep -vE 'to_lowercase|to_ascii_lowercase|// safety:' | head -3 | grep -q .; then
warn "CASE" "Case-sensitive file extension comparison. Normalize to lowercase first."
echo "$DIFF_OUTPUT" | grep -nE '^\+.*ends_with\("\.([pP][nN][gG]|[jJ][pP][eE]?[gG]|[gG][iI][fF]|[wW][eE][bB][pP]|[mM][dD])"\)' | grep -vE 'to_lowercase|to_ascii_lowercase|// safety:' | head -3 | sed 's/^/ /'
fi
# 3. Hardcoded /tmp paths in test files
if echo "$DIFF_OUTPUT" | grep -nE '^\+.*"/tmp/' | grep -vE 'tempfile|tempdir|// safety:' | head -3 | grep -q .; then
warn "TMPDIR" "Hardcoded /tmp path. Use tempfile::tempdir() for parallel-safe tests."
echo "$DIFF_OUTPUT" | grep -nE '^\+.*"/tmp/' | grep -vE 'tempfile|tempdir|// safety:' | head -3 | sed 's/^/ /'
fi
# 4. Logging tool parameters without redaction
if echo "$DIFF_OUTPUT" | grep -nE '^\+.*tracing::(info|debug|warn|error).*param' | grep -vE 'redact|// safety:' | head -3 | grep -q .; then
warn "REDACT" "Logging tool parameters without redaction. Use redact_params() first."
echo "$DIFF_OUTPUT" | grep -nE '^\+.*tracing::(info|debug|warn|error).*param' | grep -vE 'redact|// safety:' | head -3 | sed 's/^/ /'
fi
# 5. Multi-step DB operations without transaction
if echo "$DIFF_OUTPUT" | grep -qE '^\+.*(\.execute\(|\.query\()'; then
# Check if there are multiple execute/query calls in the same hunk without transaction/tx
HUNK_COUNT=$(echo "$DIFF_OUTPUT" | awk '
/^@@/ { count=0; has_tx=0 }
/^\+.*\.(execute|query)\(/ { count++ }
/^\+.*(transaction|\.tx\.|begin)/ { has_tx=1 }
/^@@/ { if (prev_count >= 2 && !prev_tx) found++ }
{ prev_count=count; prev_tx=has_tx }
END { if (count >= 2 && !has_tx) found++; print found+0 }
')
if [ "$HUNK_COUNT" -gt 0 ]; then
warn "TX" "Multiple DB operations in same hunk without transaction. Wrap in a transaction for atomicity."
fi
fi
if [ "$WARNINGS" -gt 0 ]; then
echo ""
echo "Found $WARNINGS potential issue(s). Fix them or add '// safety: <reason>' to suppress."
echo ""
exit 1
fiThere was a problem hiding this comment.
Fixed in f74ced1 — cached diff output in $DIFF_OUTPUT variable (single git diff call), added early exit when no .rs changes are present.
There was a problem hiding this comment.
Pull request overview
Adds development-time guardrails to reduce recurring reviewer-caught issues by documenting rules, enforcing mechanical checks in a pre-commit hook, and providing a “pre-merge checklist” skill for judgment-based review items.
Changes:
- Add a new skill (
review-checklist) that triggers on review/merge keywords and provides a pre-merge checklist. - Add
scripts/pre-commit-safety.shto run grep-based safety checks on Rust diffs (UTF-8 slicing, case-sensitivity,/tmp, redaction, transactions). - Update
scripts/dev-setup.shto install the new pre-commit hook and extendCLAUDE.mdwith new development rules + a reminder to run the safety script.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| skills/review-checklist/SKILL.md | Adds an activatable pre-merge checklist skill covering common review pitfalls. |
| scripts/pre-commit-safety.sh | Introduces a pre-commit safety checker for common Rust footguns and review patterns. |
| scripts/dev-setup.sh | Installs the new pre-commit hook alongside the existing commit-msg hook. |
| CLAUDE.md | Documents new guardrail rules and adds the safety script to the pre-commit verification list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # 1. Unsafe UTF-8 byte slicing (panics on multi-byte chars) | ||
| # 2. Case-sensitive file extension / media type comparisons | ||
| # 3. Hardcoded /tmp paths in tests (flaky in parallel runs) | ||
| # 4. Tool parameters logged without redaction (secret leaks) |
There was a problem hiding this comment.
The header comment says this hook checks 4 items, but the script also includes a 5th check for multi-step DB operations/transactions. Please update the header comment (or the implemented checks list) so it accurately reflects what the hook enforces; otherwise it’s easy for developers to miss why commits are blocked.
| # 4. Tool parameters logged without redaction (secret leaks) | |
| # 4. Tool parameters logged without redaction (secret leaks) | |
| # 5. Multi-step DB operations / transactions safety issues |
There was a problem hiding this comment.
Fixed in f74ced1 — header now lists all 5 checks.
| # 2. Case-sensitive file extension or media type checks | ||
| # Match: .ends_with(".png") or == "image/jpeg" without prior to_lowercase |
There was a problem hiding this comment.
The “Case-sensitive file extension or media type checks” comment mentions matching media type equality (e.g. == "image/jpeg"), but the actual grep only targets .ends_with(".<ext>"). Either implement the media type comparison check or adjust the comment to avoid misleading behavior expectations.
| # 2. Case-sensitive file extension or media type checks | |
| # Match: .ends_with(".png") or == "image/jpeg" without prior to_lowercase | |
| # 2. Case-sensitive file extension checks | |
| # Match: .ends_with(".png") without prior to_lowercase |
There was a problem hiding this comment.
Fixed in f74ced1 — comment now says "Case-sensitive file extension checks" only, matching the actual grep behavior.
| # Support both pre-commit hook (staged files) and standalone (all changed vs main) | ||
| if git diff --cached --quiet 2>/dev/null; then | ||
| # No staged changes -- compare working tree against main | ||
| DIFF_CMD="git diff origin/main -- " |
There was a problem hiding this comment.
Standalone mode diffs against origin/main. In clones without that remote/ref (forks, offline, shallow clones), the diff command can fail and the checks may end up being skipped silently. Consider resolving the default branch more robustly (e.g., @{upstream}, local main, or git merge-base HEAD <ref> fallback) and emitting a clear error if no baseline ref is available.
| # Support both pre-commit hook (staged files) and standalone (all changed vs main) | |
| if git diff --cached --quiet 2>/dev/null; then | |
| # No staged changes -- compare working tree against main | |
| DIFF_CMD="git diff origin/main -- " | |
| # Determine a suitable base ref for standalone diffs. | |
| resolve_base_ref() { | |
| # Prefer the current branch's upstream, then common default branches. | |
| local candidates=( | |
| "@{upstream}" | |
| "origin/HEAD" | |
| "origin/main" | |
| "origin/master" | |
| "main" | |
| "master" | |
| ) | |
| for ref in "${candidates[@]}"; do | |
| if git rev-parse --verify --quiet "$ref" >/dev/null; then | |
| echo "$ref" | |
| return 0 | |
| fi | |
| done | |
| echo "pre-commit-safety: could not determine a base Git ref for diff (tried: ${candidates[*]})." >&2 | |
| echo "pre-commit-safety: ensure your repository has an upstream or a local main/master branch." >&2 | |
| exit 1 | |
| } | |
| # Support both pre-commit hook (staged files) and standalone (all changed vs main) | |
| if git diff --cached --quiet 2>/dev/null; then | |
| # No staged changes -- compare working tree against a resolved base ref | |
| BASE_REF="$(resolve_base_ref)" | |
| DIFF_CMD="git diff ${BASE_REF} -- " |
There was a problem hiding this comment.
Fixed in f74ced1 — added resolve_base_ref() that tries @{upstream}, origin/HEAD, origin/main, origin/master, main, master in order, with a clear error if none resolve.
| # 5. Multi-step DB operations without transaction | ||
| if $DIFF_CMD '*.rs' 2>/dev/null | grep -nE '^\+.*(\.execute\(|\.query\()' | head -1 | grep -q .; then | ||
| # Check if there are multiple execute/query calls in the same hunk without transaction/tx | ||
| HUNK_COUNT=$($DIFF_CMD '*.rs' 2>/dev/null | awk ' | ||
| /^@@/ { count=0; has_tx=0 } | ||
| /^\+.*\.(execute|query)\(/ { count++ } | ||
| /^\+.*(transaction|\.tx\.|begin)/ { has_tx=1 } | ||
| /^@@/ { if (prev_count >= 2 && !prev_tx) found++ } | ||
| { prev_count=count; prev_tx=has_tx } | ||
| END { if (count >= 2 && !has_tx) found++; print found+0 } | ||
| ') | ||
| if [ "$HUNK_COUNT" -gt 0 ]; then | ||
| warn "TX" "Multiple DB operations in same hunk without transaction. Wrap in a transaction for atomicity." | ||
| fi |
There was a problem hiding this comment.
The transaction-safety check operates on git diff ... -U0 added lines only, so it will warn when you add a second .execute()/.query() inside an existing transaction that wasn’t modified in the same hunk. It’s also not suppressible via the advertised // safety: mechanism and doesn’t print the offending hunk(s), which makes it hard to act on. Consider running this check with some context (or -W like commit-msg-regression.sh), honoring // safety: markers in the awk logic, and printing a small snippet of the triggering hunks to guide fixes.
There was a problem hiding this comment.
Fixed in f74ced1 — TX check now uses -W (function context) to see surrounding transaction/begin calls, honors // safety: suppression in awk, and prints the triggering .execute()/.query() lines.
- Cache diff output in variable to avoid ~10 redundant git diff calls (Gemini) - Add early exit when no .rs files are changed (Gemini) - Fix header comment: list all 5 checks, not just 4 (Copilot) - Fix check 2 comment: only mentions file extensions, not media types (Copilot) - Add resolve_base_ref() with fallback candidates instead of hardcoded origin/main for standalone mode (Copilot) - TX check: use -W (function context) to reduce false positives, honor // safety: suppression, print triggering lines (Copilot) [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…skill) (nearai#665) * chore: add reviewer-feedback guardrails (CLAUDE.md, pre-commit hook, skill) Analysis of ~50 PRs from the past week identified 10 recurring themes in Copilot and Gemini code review comments. This change addresses them at development time through three layers: 1. CLAUDE.md additions (7 new rules): - Transaction safety for multi-step DB operations - UTF-8 string safety (no byte-index slicing) - Case-insensitive comparisons for paths/media types - Decorator/wrapper trait method delegation - Sensitive data redaction in logs/SSE - tempfile crate for test temporary files - Trust boundaries for worker container data 2. Pre-commit hook (scripts/pre-commit-safety.sh): Mechanical checks for unsafe byte slicing, case-sensitive extension comparisons, hardcoded /tmp paths, unredacted tool parameter logging, and non-transactional DB operations. Installed via dev-setup.sh alongside existing commit-msg hook. 3. Review checklist skill (skills/review-checklist/SKILL.md): Activates on "review"/"merge" keywords. Covers the judgment-based items that can't be linted: transaction safety, SSRF validation, approval checks, decorator delegation, test quality, and doc accuracy. [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback on pre-commit-safety.sh - Cache diff output in variable to avoid ~10 redundant git diff calls (Gemini) - Add early exit when no .rs files are changed (Gemini) - Fix header comment: list all 5 checks, not just 4 (Copilot) - Fix check 2 comment: only mentions file extensions, not media types (Copilot) - Add resolve_base_ref() with fallback candidates instead of hardcoded origin/main for standalone mode (Copilot) - TX check: use -W (function context) to reduce false positives, honor // safety: suppression, print triggering lines (Copilot) [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…skill) (nearai#665) * chore: add reviewer-feedback guardrails (CLAUDE.md, pre-commit hook, skill) Analysis of ~50 PRs from the past week identified 10 recurring themes in Copilot and Gemini code review comments. This change addresses them at development time through three layers: 1. CLAUDE.md additions (7 new rules): - Transaction safety for multi-step DB operations - UTF-8 string safety (no byte-index slicing) - Case-insensitive comparisons for paths/media types - Decorator/wrapper trait method delegation - Sensitive data redaction in logs/SSE - tempfile crate for test temporary files - Trust boundaries for worker container data 2. Pre-commit hook (scripts/pre-commit-safety.sh): Mechanical checks for unsafe byte slicing, case-sensitive extension comparisons, hardcoded /tmp paths, unredacted tool parameter logging, and non-transactional DB operations. Installed via dev-setup.sh alongside existing commit-msg hook. 3. Review checklist skill (skills/review-checklist/SKILL.md): Activates on "review"/"merge" keywords. Covers the judgment-based items that can't be linted: transaction safety, SSRF validation, approval checks, decorator delegation, test quality, and doc accuracy. [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback on pre-commit-safety.sh - Cache diff output in variable to avoid ~10 redundant git diff calls (Gemini) - Add early exit when no .rs files are changed (Gemini) - Fix header comment: list all 5 checks, not just 4 (Copilot) - Fix check 2 comment: only mentions file extensions, not media types (Copilot) - Add resolve_base_ref() with fallback candidates instead of hardcoded origin/main for standalone mode (Copilot) - TX check: use -W (function context) to reduce false positives, honor // safety: suppression, print triggering lines (Copilot) [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Analysis of ~50 PRs from the past week identified 10 recurring themes in Copilot and Gemini code review comments — issues that should have been caught at development time. This PR adds three layers of guardrails:
1. CLAUDE.md — 7 new development rules
.ends_with(".png")fails for.PNG/tmppaths collide in parallel runs2. Pre-commit hook —
scripts/pre-commit-safety.shMechanical grep-based checks on staged
.rsfiles for:&s[..n]withoutis_char_boundary)/tmp/paths in testsredact_params()Installed automatically via
dev-setup.sh. Suppressible with// safety: <reason>inline comments.3. Review checklist skill —
skills/review-checklist/SKILL.mdActivates on "review"/"merge" keywords. Covers judgment-based items that can't be linted:
Test plan
pre-commit-safety.shruns clean on current codebase (exit 0)dev-setup.sh&s[..100]in a.rsfileGenerated with Claude Code