#!/bin/sh
# The arc's own sections are Chris's to set. A new one added by this
# session was refused work he never asked for, and a fix found while
# implementing an item is part of that item rather than a section or an
# entry of its own. So a patch may not add a top-level entry to the
# plan: the number of them has to be what gold already holds.
top_level_count()
{
awk '/^<li>/ {count++} END {print count + 0}' "$1"
}
check_top_level()
{
plan="$1"
gold_plan="$GOLD/$plan"
if [ ! -f "$gold_plan" ]; then
return 0
fi
here=`top_level_count "$plan"`
there=`top_level_count "$gold_plan"`
allowed=${SANCTIONED_ENTRIES:-0}
if [ "$here" -gt "`expr $there + $allowed`" ]; then
echo "check_devlog: FAIL the plan grew by `expr $here - $there`"
echo " entry(s) written at its outer edge. Those are Chris's to"
echo " add: work belongs under the item it is part of, and a"
echo " fix found while doing an item is part of that item."
return 1
fi
return 0
}
# Refuses a plan that carries a checkmark this session put there, or a
# typed outline label, or unbalanced list tags. Only Chris sets a
# checkmark; a plan file is compared against gold to find any that were
# added since.
#
# Where Chris has asked in so many words for entries to be added at the
# outer edge, run this with SANCTIONED_ENTRIES set to how many he asked
# for, and that many are allowed. Any beyond that are still refused, so
# the number has to be written down and shown in the round's output.
#
# Where Chris has said in so many words which items to check, run this
# with CONFIRMED_CHECKS set to how many he asked for, and that many are
# allowed. Any beyond that number are still refused, so the count has to
# be written down and shown in the round's output rather than the guard
# being stepped around.
GOLD=${GOLD:-/home/claude/gold}
CONFIRMED_CHECKS=${CONFIRMED_CHECKS:-0}
plan="$1"
# With no plan named, take the newest dated arc folder that holds one.
# Naming one arc here meant the check went on reading that arc long
# after the work had moved to the next, so it passed a plan nobody was
# writing in.
if [ -z "$plan" ]; then
plan=`ls -d devlog/v10/*/plan.html 2>/dev/null | sort | tail -1`
fi
if [ -z "$plan" ] || [ ! -f "$plan" ]; then
echo "check_devlog: FAIL no plan to read"
exit 1
fi
fail=0
# A checkmark is written with either class the plans use, so both are
# counted. Counting one of them let eighteen checkmarks through unseen.
marks='class="\(check\|done\)">✓'
here=`grep -c "$marks" "$plan"`
there=`git -C "$GOLD" show "confirmed-head:$plan" 2>/dev/null | \
grep -c "$marks"`
if [ "$there" = "" ]; then
there=0
fi
added=$((here - there))
if [ "$added" -gt "$CONFIRMED_CHECKS" ]; then
echo "check_devlog: FAIL added $added checkmark(s), $CONFIRMED_CHECKS"
echo " confirmed; only Chris sets those. Use the waiting marker."
fail=1
elif [ "$added" -gt 0 ]; then
echo "check_devlog: $added checkmark(s) added, which Chris asked for"
fi
opens=`grep -o '<li' "$plan" | wc -l`
closes=`grep -o '</li>' "$plan" | wc -l`
if [ "$opens" != "$closes" ]; then
echo "check_devlog: FAIL $opens <li> against $closes </li>"
fail=1
fi
opens=`grep -o '<ol' "$plan" | wc -l`
closes=`grep -o '</ol>' "$plan" | wc -l`
if [ "$opens" != "$closes" ]; then
echo "check_devlog: FAIL $opens <ol> against $closes </ol>"
fail=1
fi
typed=`grep -cE '<li[^>]*>[[:space:]]*(<[^>]+>)*[[:space:]]*([IVX]+|[A-Z]|[0-9]+)\.' "$plan"`
if [ "$typed" -gt 0 ]; then
echo "check_devlog: FAIL $typed typed outline label(s)"
fail=1
fi
if ! check_top_level "$plan"; then
fail=1
fi
# The plan rule says no sentence in an entry runs past about twenty
# words, and that rule was the one with no check behind it: a round
# wrote an entry of nine long sentences and nothing caught it. The plan
# is append-only and holds older entries written before this check, so
# only the lines this patch adds are read, found by diffing against the
# copy gold holds. Each added line's prose is pulled out tag-free, split
# into sentences on a period, and any sentence past the limit is named.
# A title in <strong> is dropped first, since a full-sentence title does
# not count toward the sentence rule, and a few words of slack are
# allowed over twenty, since the rule says "about".
WORD_LIMIT=${DEVLOG_WORD_LIMIT:-24}
added_lines=`git -C "$GOLD" show "confirmed-head:$plan" 2>/dev/null | \
diff - "$plan" | grep '^>' | sed 's/^> //'`
long_sentences=`echo "$added_lines" | awk -v limit="$WORD_LIMIT" '
{
line = $0
gsub(/<strong>[^<]*<\/strong>/, "", line)
gsub(/<[^>]*>/, " ", line)
gsub(/&#[0-9]+;/, "", line)
gsub(/&[a-z]+;/, "", line)
prose = prose " " line
}
END {
n = split(prose, parts, /[.!?]/)
for (i = 1; i <= n; i++) {
sentence = parts[i]
words = split(sentence, w, /[ \t]+/)
count = 0
for (j = 1; j <= words; j++) {
if (w[j] != "") {
count++
}
}
if (count > limit) {
printf "%d\n", count
}
}
}
'`
if [ -n "$long_sentences" ]; then
worst=`echo "$long_sentences" | sort -rn | head -1`
many=`echo "$long_sentences" | wc -l | tr -d ' '`
echo "check_devlog: FAIL $many added sentence(s) past $WORD_LIMIT words,"
echo " the longest $worst. Each entry sentence stays near twenty"
echo " words; split the long ones or move detail to a nested part."
fail=1
fi
if [ "$fail" = "0" ]; then
echo "check_devlog: PASS $plan"
fi
exit $fail