feat(engine): let a message say it needs no answer, and count debt without losing sight of the rest
Rule 7 (0.5.0) shipped an obligation on a format with four fields, none of which could tell a question from a notice. Two consequences fell out of that gap: the injection had to name both terminal states and prefer neither, and coord-count.sh had to treat every unarchived file as a reply owed. The fifth field closes both. coord-send.sh --fyi writes reply-expected: no; omitting it writes yes. Absent means expected, because every message already on disk lacks the field - so a forgotten flag over-counts debt, which is visible, rather than creating debt nobody sees. A reply is not a special case. A broadcast is always no: --reply-to resolves inside the recipient's own mailbox and a broadcast never lands there, so there is no reply path to promise. coord-count.sh now prints TWO integers per mailbox, not one. Replacing pending with debt was the obvious reading of "count debt rather than unarchived messages" and it is wrong here: board.sh counts the same inbox files itself, so a debt-only count would put two different numbers under one name with nothing to reconcile them, and a mailbox holding only notices would read as empty while its messages keep being re-injected. The field is frontmatter and only frontmatter - a body line claiming "reply-expected: no" at column 0 cannot silence a real debt, and a file without valid frontmatter counts as owing a reply. Section 20's wording changed because its stated reason expired, but its second half matters more now, not less: the marking is a DECLARATION, not an instruction. Without that clause one word in an untrusted message becomes a lever that mints obligations in another repo. coord-selftest 136 -> 151. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016iJoZVmU2guTEZcMghk88z
This commit is contained in:
parent
261a75bd7b
commit
c0ccb1d611
8 changed files with 314 additions and 29 deletions
|
|
@ -1,7 +1,15 @@
|
|||
#!/bin/bash
|
||||
# coord-count.sh - count PENDING directed messages per mailbox WITHOUT
|
||||
# delivering anything. Prints one "<mailbox>\t<count>" line per mailbox that
|
||||
# has unhandled mail, sorted by name; prints nothing when none do.
|
||||
# delivering anything. Prints one "<mailbox>\t<pending>\t<debt>" line per mailbox
|
||||
# that has unhandled mail, sorted by name; prints nothing when none do.
|
||||
#
|
||||
# TWO INTEGERS, NOT ONE. <pending> is every unhandled message; <debt> is the
|
||||
# subset whose sender declared it expects a reply (frontmatter reply-expected,
|
||||
# 0.11.0). Replacing the first with the second was the obvious reading of "count
|
||||
# debt rather than unarchived messages", and it is wrong here: board.sh counts
|
||||
# the same inbox files itself, so a debt-only count would put two different
|
||||
# numbers under one name with nothing to reconcile them - and a mailbox holding
|
||||
# only notices would read as empty while its messages keep being re-injected.
|
||||
#
|
||||
# WHY THIS IS NOT coord-inbox.sh --repo <x>: reading IS delivery. The read path
|
||||
# prints a broadcast and then records it as seen, so asking it "what is pending
|
||||
|
|
@ -40,6 +48,20 @@ done
|
|||
|
||||
[ -d "$COORD" ] || exit 0
|
||||
|
||||
# Does this message owe a reply? Absent field means YES: every message written
|
||||
# before 0.11.0 lacks it, so absence has to keep meaning what it always meant.
|
||||
# The read is bounded to the frontmatter block - a body line is untrusted
|
||||
# cross-repo input and must not be able to silence a real debt by claiming
|
||||
# "reply-expected: no" at column 0. That is stricter than the grep -m1 the older
|
||||
# fields use, where frontmatter-comes-first happens to save them. A file without
|
||||
# two '---' terminators has no frontmatter to trust, so it counts as debt.
|
||||
owes_reply() {
|
||||
[ "$(head -1 "$1" 2>/dev/null)" = "---" ] || return 0
|
||||
[ "$(grep -c '^---$' "$1" 2>/dev/null)" -ge 2 ] || return 0
|
||||
sed -n '2,/^---$/p' "$1" 2>/dev/null | grep -q '^reply-expected: no$' && return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
# Glob expansion under LC_ALL=C is already name-sorted. An unmatched glob
|
||||
# expands to the literal pattern, which fails the -d test and is skipped.
|
||||
for d in "$COORD"/*; do
|
||||
|
|
@ -51,12 +73,18 @@ for d in "$COORD"/*; do
|
|||
[ -d "$d/inbox" ] || continue
|
||||
# *.md is the message grammar; a stray file must not inflate a total the
|
||||
# operator reads as "replies owed".
|
||||
n="$(ls "$d/inbox"/*.md 2>/dev/null | wc -l | tr -d ' ')"
|
||||
[ -n "$n" ] || n=0
|
||||
n=0; owed=0
|
||||
for m in "$d/inbox"/*.md; do
|
||||
[ -e "$m" ] || continue
|
||||
n=$((n + 1))
|
||||
owes_reply "$m" && owed=$((owed + 1))
|
||||
done
|
||||
[ "$n" -gt 0 ] || continue
|
||||
# Absent, not zero: the question is "who is owed a reply", and a list of
|
||||
# zeroes answers a different one at every reader's expense.
|
||||
printf '%s\t%s\n' "$name" "$n"
|
||||
# Absent, not zero: the question is "who has unhandled mail", and a list of
|
||||
# zeroes answers a different one at every reader's expense. A mailbox holding
|
||||
# only notices IS listed, with a debt of 0 - it has mail that will be
|
||||
# re-injected until someone closes it, which is the thing worth knowing.
|
||||
printf '%s\t%s\t%s\n' "$name" "$n" "$owed"
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue