kb: a ledger excuses only the kb file its write published (improvise-yea8)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Edward Langley
2026-09-22 21:09:17 -07:00
parent b3a41bca57
commit d90c45c14e
2 changed files with 25 additions and 8 deletions
+15 -4
View File
@@ -72,7 +72,7 @@ acquire_lock() {
scratch=()
new_cand() {
cand="$(mktemp "$KB.cand.XXXXXX")"
scratch+=("$cand" "$cand.delta" "$cand.removed" "$cand.ledger" "$cand.base")
scratch+=("$cand" "$cand.delta" "$cand.removed" "$cand.ledger" "$cand.base" "$cand.stamped")
}
# What `kb rm` removed that HEAD still has: the record that tells an intended
@@ -83,6 +83,14 @@ ledger_path() {
fi
}
# A ledger speaks only for the kb FILE this tool last published, named on its
# first line; bytes alone are not enough, since a restore can reproduce them.
file_stamp() {
printf '%s %s' "$(stamp_of "$1")" \
"$(stat -c '%i %.9Y' "$1" 2>/dev/null || stat -f '%i %Fm' "$1")"
}
ledger_holds() { [ -f "$1" ] && [ "$(head -n 1 "$1")" = "% kb-stamp $(file_stamp "$2")" ]; }
# The committed knowledge base, which no write may end up short of.
# KB_BASELINE is the test seam, naming a file.
baseline_to() {
@@ -140,19 +148,22 @@ commit() { # $1 = candidate, $2 = stamp of the kb as read, $3 = keys a rm remove
echo "kb: cannot read the committed kb.pl to compare against; $KB is unchanged" >&2
exit 3
fi
{ if [ -f "$ledger" ]; then cat "$ledger"; fi
{ if ledger_holds "$ledger" "$KB"; then cat "$ledger"; fi
if [ -n "$removing" ]; then cat "$removing"; fi; } > "$cand.removed"
if ! merge complete "$cand.base" "$cand" "$cand.removed" "$cand.ledger"; then
echo "kb: REFUSED -- clauses HEAD has are gone, with no kb rm recorded; $KB is unchanged." >&2
echo "kb: restore it from HEAD and re-apply your deltas, or commit the removal." >&2
echo "kb: restore it from HEAD (git show HEAD:prolog-sessions/kb.pl) and re-apply your deltas." >&2
echo "kb: do NOT commit this kb.pl: a committed loss becomes the floor this check compares against." >&2
echo "kb: to drop a clause on purpose, restore first and then kb rm it." >&2
exit 1
fi
if ! check_file "$cand"; then
echo "kb: REFUSED -- kb_consistent fails on the result; $KB is unchanged" >&2
exit 1
fi
{ printf '%% kb-stamp %s\n' "$(file_stamp "$cand")"; cat "$cand.ledger"; } > "$cand.stamped"
kill_hook "$cand"
mv -f "$cand.ledger" "$ledger"
mv -f "$cand.stamped" "$ledger"
mv -f "$cand" "$KB"
}