#!/bin/sh
# Reads a draft and names every banned word and every sentence that
# describes how it is being said rather than what was found.
#
# check_words.sh draft.txt check a draft, and stamp that it was
# checked this round
# check_words.sh --test run the self-test over the matcher
#
# Two kinds of fault are looked for.
#
# The first is a fixed list: words Chris has asked never to appear.
#
# The second is a shape, which is where the failures keep happening.
# Every banned lead-in occupies the same slot: a clause whose subject is
# the writer and whose verb is about speaking, placed in front of a
# fact. "Let me be plain", "I will say so", "I should note" are all that
# shape. The cure is not a longer list but a rule about sentence
# openers, since that is where they live: no sentence may open with a
# clause about how it is being said. Write the fact with the thing as
# its subject instead.
#
# WHY THE STAMP. The list has never been the weak part: the word that
# reached Chris last was already on it. What failed was that the check
# ran over a patch and never over the response. So a run against a draft
# leaves a stamp naming what Chris said this round, and cut_patch.sh
# refuses to cut without a stamp for the round it is in.
#
# A patch is read as the lines it adds. A line a patch takes away
# carries the old wording, and taking a banned word out of the codebase
# must not be reported as putting one in.
#
# Exits non-zero when anything is found, so it can gate a send.
WORDS='harness|ctor|rails|sidecar|fixture|nit|goldens|slug|seamless'
WORDS="$WORDS|proof|proven|honest|honestly|honesty|dishonest|genuinely"
WORDS="$WORDS|plainly|frankly|candidly|candid|candor|truthfully"
WORDS="$WORDS|sincerely|transparently|openly"
# "actually" says what came before it was not so, which is the same
# implication as the rest of this list, and the process file names it
# among them. It went out three times with the check quiet on it.
WORDS="$WORDS|actually"
# A bare "let" matched a JavaScript declaration, so a patch carrying
# "let menu = button.nextElementSibling;" was refused. Only the forms
# naming a speaker are the shape.
SHAPES='let me|let us|let'"'"'s say|i will say|i will be|i should say'
SHAPES="$SHAPES|i should note|i want to be|i have to say|i must say"
SHAPES="$SHAPES|to be (honest|fair|clear|blunt|direct|frank)"
SHAPES="$SHAPES|in (all )?(fairness|honesty)"
SHAPES="$SHAPES|for what it""'""s worth"
SHAPES="$SHAPES|the (honest|plain|simple) (truth|answer|finding)"
SHAPES="$SHAPES|my (honest|candid) (read|view)|no dressing|dress it up"
SHAPES="$SHAPES|straight with you|be straight|being straight"
SHAPES="$SHAPES|the (truth|reality) is|in truth|to be sure"
STAMP=${STAMP:-/home/claude/words_checked.txt}
SAID=${SAID:-/home/claude/said_this_round.txt}
# runs the matcher over one file and names what it found
check_file()
{
found=0
reading="$1"
if head -1 "$1" | grep -q "^diff --git"; then
reading=`mktemp`
grep "^+" "$1" | grep -v "^+++" > "$reading"
fi
if grep -n -i -E "\\b($WORDS)\\b" "$reading"; then
echo "check: the words above are asked never to appear"
found=1
fi
if grep -n -i -E "\\b($SHAPES)\\b" "$reading"; then
echo "check: the clauses above say how you are speaking, not"
echo "what you found; cut the clause and let the fact carry"
echo "itself"
found=1
fi
if [ "$reading" != "$1" ]; then
rm -f "$reading"
fi
return $found
}
# Walks every banned word through every capitalization and every
# surrounding mark, and reports any the matcher misses. The space is
# finite and every point in it is tried, so a miss cannot hide in a
# corner of it. A few ordinary sentences are tried as well, since a
# matcher that flagged everything would pass the first half by itself.
run_self_test()
{
scratch=`mktemp`
missed=0
tried=0
for word in `echo "$WORDS" | tr '|' ' '`; do
for shape in "%s" "%s." "(%s)" " %s," "the %s thing"; do
upper=`echo $word | tr 'a-z' 'A-Z'`
for form in "$word" "$upper"; do
printf "a sentence with $shape in it\n" "$form" \
> "$scratch"
tried=`expr $tried + 1`
if ! grep -q -i -E "\\b($WORDS)\\b" "$scratch"; then
echo "self-test: missed [$form] in [$shape]"
missed=`expr $missed + 1`
fi
done
done
done
cat > "$scratch" <<'CLEANEOF'
The decoder read every packet of the file to its end.
A tone of four hundred and forty cycles a second came back.
Ninety-two frames of ninety-five decode, and three are refused.
The check reports the line and the word it found.
Createdb succeeded and the users table has fourteen columns.
CLEANEOF
for line in 1 2 3 4 5; do
sed -n "${line}p" "$scratch" > "$scratch.one"
tried=`expr $tried + 1`
if grep -q -i -E "\\b($WORDS)\\b" "$scratch.one" ||
grep -q -i -E "($SHAPES)" "$scratch.one"; then
echo "self-test: flagged an ordinary sentence, line $line"
missed=`expr $missed + 1`
fi
done
rm -f "$scratch" "$scratch.one"
if [ "$missed" -eq 0 ]; then
echo "self-test: $tried cases tried, none missed"
return 0
fi
echo "self-test: $missed of $tried cases went wrong"
return 1
}
if [ "$1" = "--test" ]; then
run_self_test
exit $?
fi
draft=${1:-}
if [ -z "$draft" ] || [ ! -f "$draft" ]; then
echo "check: name a file holding the draft"
exit 2
fi
if check_file "$draft"; then
# A review owed to Chris has to appear in the response. Recording it
# cleared the count once, which let a review reach a file and never
# reach him. The count clears here, where the response is read.
owed=${REVIEW_OWED:-/home/claude/review_owed.txt}
rounds=${ROUND_COUNT:-/home/claude/round_count.txt}
if [ -s "$owed" ]; then
carried=0
while read -r line
do
piece=`echo "$line" | cut -c1-40`
if [ ${#piece} -gt 20 ] && grep -qF "$piece" "$1"; then
carried=`expr $carried + 1`
fi
done < "$owed"
if [ "$carried" -lt 3 ]; then
echo "check: a review is owed to Chris and this response does"
echo " not carry it. Put the review in the response."
exit 1
fi
printf "0 shown\n" > "$rounds"
rm -f "$owed"
echo "check: the review is in the response; the count is 0"
fi
echo "check: nothing found"
# The stamp names the round, so a check run for an earlier round
# cannot stand in for this one.
if [ -f "$SAID" ]; then
cksum < "$SAID" | awk '{print $1"-"$2}' > "$STAMP"
else
echo "none" > "$STAMP"
fi
exit 0
fi
exit 1