fix(#1257): confirm delivery by draft transition, not prompt detection (adopts #1262) (#1332)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-infra-01 <[email protected]>
This commit was merged in pull request #1332.
This commit is contained in:
@@ -4,10 +4,13 @@
|
||||
#
|
||||
# 1. DELIVERED — a REPL that renders a `❯ ` input box and submits on Enter
|
||||
# (text scrolls to history, box clears) => exit 0 "✓ delivered".
|
||||
# 2. UNCONFIRMED — a pane with NO locatable prompt glyph. This is the exact
|
||||
# historical FALSE POSITIVE: pre-patch it printed "✓ delivered"
|
||||
# exit 0; post-patch it MUST fail loud (exit 2, stderr
|
||||
# "could not confirm submission").
|
||||
# 2. DELIVERED — a pane with NO prompt glyph that DOES submit => exit 0. A pi
|
||||
# seat is this fixture (U+2500 rule, no glyph). Reshaped for
|
||||
# #1257; see the note at the fixture for why the old exit-2
|
||||
# assertion was wrong.
|
||||
# 2b. UNCONFIRMED— a glyphless pane that never submits (raw/no-echo hung TUI)
|
||||
# => must fail loud. This carries the historical
|
||||
# false-positive guard that fixture 2 used to be credited with.
|
||||
# 3. DRAFT — a `❯ `-prompt pane that never submits (message stays on the
|
||||
# input line) => exit 2, stderr "unsubmitted draft".
|
||||
# 4. DELIVERED — a pane whose input box is two `─` rules with NO prompt glyph
|
||||
@@ -17,10 +20,16 @@
|
||||
# 5. DRAFT — the same glyphless box, holding our tail across every flush
|
||||
# (box shape) Enter => exit 2, stderr "unsubmitted draft". Pre-#1362 this
|
||||
# also reported unconfirmed, so the true state was invisible.
|
||||
# 6. DELIVERED — a SHAPELESS REPL (no glyph, no box) that submits => exit 0.
|
||||
# The 2026-09-04 scratch probe regression: shape probing alone reports "may
|
||||
# be UNDELIVERED" on this pane while the message is consumed; the cursor-row
|
||||
# draft transition is the authoritative runtime-agnostic verdict.
|
||||
# 6b. UNCONFIRMED— a shapeless pane in raw/no-echo mode that never reads stdin
|
||||
# (shapeless) => exit 2 "could not confirm submission" (never delivered).
|
||||
set -uo pipefail
|
||||
|
||||
HERE=$(cd -- "$(dirname -- "$0")" && pwd)
|
||||
SEND="$HERE/send-message.sh"
|
||||
SEND="${SEND:-$HERE/send-message.sh}"
|
||||
SOCKET="verdict-test-$RANDOM-$$"
|
||||
TMP=$(mktemp -d)
|
||||
trap 'tmux -L "$SOCKET" kill-server >/dev/null 2>&1 || true; rm -rf "$TMP"' EXIT
|
||||
@@ -44,19 +53,44 @@ else
|
||||
no "delivered: ❯-prompt REPL that submits => exit 0 ✓ delivered" "rc=$rc out=[$out] err=[$(cat "$TMP/e1")]"
|
||||
fi
|
||||
|
||||
# --- Fixture 2: NO prompt glyph (default bash PS1). THE regression: pre-patch this
|
||||
# was a silent false-positive "delivered"; post-patch it must be unconfirmed→exit 2.
|
||||
# --- Fixture 2: NO prompt glyph, and the pane DOES submit (interactive bash).
|
||||
# RESHAPED 2026-08-16 (#1257), deliberately. This fixture previously asserted
|
||||
# exit 2 here and was labelled "false-positive FIXED". That assertion was wrong,
|
||||
# and locking it in is what kept E7 alive: the pane submits, so "delivered" is
|
||||
# the truth, and a pi seat — whose input box is a bare U+2500 rule with no glyph
|
||||
# — IS this fixture. Reporting exit 2 for it told operators a delivered message
|
||||
# may be undelivered, and the retry that advice invites is the duplicate.
|
||||
#
|
||||
# The guard this fixture was reaching for is real and is NOT dropped: "never
|
||||
# infer delivered from absence" is now enforced positively by fixture 2b below
|
||||
# (glyphless AND not submitting => must fail) and by fixture 3 (locatable box
|
||||
# still carrying our tail => draft). Absence alone decides nothing either way.
|
||||
tmux -L "$SOCKET" new-session -d -s noglyph -c "$TMP" \
|
||||
'PS1="sh-noglyph$ " exec bash --noprofile --norc -i'
|
||||
sleep 0.3
|
||||
if out=$("$SEND" -L "$SOCKET" -t "=noglyph" -m "verdict fixture two must fail loud" 2>"$TMP/e2"); then
|
||||
no "unconfirmed: glyphless pane must NOT report success" "expected exit 2, got 0 (out=[$out])"
|
||||
out=$("$SEND" -L "$SOCKET" -t "=noglyph" -m "verdict fixture two must fail loud" 2>"$TMP/e2"); rc=$?
|
||||
if [ "$rc" -eq 0 ] && grep -qF "✓ delivered" <<<"$out"; then
|
||||
ok "delivered: glyphless pane that submits => exit 0 (runtime-agnostic, E7 FIXED)"
|
||||
else
|
||||
no "delivered: glyphless pane that submits => exit 0" "rc=$rc out=[$out] err=[$(cat "$TMP/e2")]"
|
||||
fi
|
||||
|
||||
# --- Fixture 2b: NO prompt glyph AND never submits — a hung managed TUI holding the
|
||||
# terminal in raw/no-echo, which is what a stuck agent seat actually is (measured
|
||||
# on live pi: stty -echo -icanon). Nothing is echoed, nothing is consumed, so
|
||||
# there is no positive evidence of submission and the tool MUST fail loud. This
|
||||
# is the historical false-positive guard, kept as a positive test.
|
||||
tmux -L "$SOCKET" new-session -d -s rawstuck -c "$TMP" \
|
||||
'bash --noprofile --norc -c "stty -echo -icanon min 1 time 0 2>/dev/null; exec sleep infinity"'
|
||||
sleep 0.3
|
||||
if out=$("$SEND" -L "$SOCKET" -t "=rawstuck" -r 1 -m "verdict fixture two-b never submitted" 2>"$TMP/e2b"); then
|
||||
no "unconfirmed: glyphless hung TUI must NOT report success" "expected non-zero, got 0 (out=[$out])"
|
||||
else
|
||||
rc=$?
|
||||
if [ "$rc" -eq 2 ] && grep -qF "could not confirm submission" "$TMP/e2"; then
|
||||
ok "unconfirmed: glyphless pane => exit 2 + 'could not confirm submission' (false-positive FIXED)"
|
||||
if [ "$rc" -ne 0 ] && grep -qF "could not confirm submission" "$TMP/e2b"; then
|
||||
ok "unconfirmed: glyphless hung TUI (raw/no-echo) => non-zero + 'could not confirm submission'"
|
||||
else
|
||||
no "unconfirmed: glyphless pane => exit 2 + stderr" "rc=$rc err=[$(cat "$TMP/e2")]"
|
||||
no "unconfirmed: glyphless hung TUI => non-zero + stderr" "rc=$rc err=[$(cat "$TMP/e2b")]"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -126,6 +160,51 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Fixtures 6 and 6b: a SHAPELESS REPL. The pane renders nothing at all: no
|
||||
# prompt glyph and no rule box, so locate_input_box() alone can never see it
|
||||
# and shape-probing alone reports "may be UNDELIVERED" on a delivered message
|
||||
# (measured live 2026-09-04, scratch probe: a shapeless consumer CONSUMED the
|
||||
# message while the shipped shape probe exited 2 with retry advice - the exact
|
||||
# #1257 regression). The cursor-row draft transition is the authoritative,
|
||||
# runtime-agnostic delivered verdict: fixture 6's consumer submits => exit 0.
|
||||
# Fixture 6b is the guard arm: a shapeless pane whose foreground never reads
|
||||
# stdin keeps the echoed paste on the cursor line across every flush Enter =>
|
||||
# DRAFT => exit 2, never delivered.
|
||||
cat > "$TMP/shapeless.py" <<'SHAPELESS'
|
||||
import sys
|
||||
for line in sys.stdin:
|
||||
pass # consume and render nothing
|
||||
SHAPELESS
|
||||
tmux -L "$SOCKET" new-session -d -s shapeless -c "$TMP" "exec python3 -u '$TMP/shapeless.py'"
|
||||
sleep 0.3
|
||||
out=$("$SEND" -L "$SOCKET" -t "=shapeless" -m "fixture six shapeless consumed ok" 2>"$TMP/e6"); rc=$?
|
||||
if [ "$rc" -eq 0 ] && grep -qF "✓ delivered" <<<"$out"; then
|
||||
ok "delivered: shapeless REPL that submits => exit 0 ✓ delivered (probe regression)"
|
||||
else
|
||||
no "delivered: shapeless REPL that submits => exit 0 ✓ delivered" "rc=$rc out=[$out] err=[$(cat "$TMP/e6")]"
|
||||
fi
|
||||
|
||||
# MEASURED LIMIT (2026-09-04, this suite's development): a shapeless pane in
|
||||
# COOKED mode whose foreground never reads stdin (e.g. 'sleep infinity') scrolls
|
||||
# its kernel echo off the cursor row on the flush Enter, so no runtime-agnostic
|
||||
# signal available to the sender distinguishes it from a delivering pane. The
|
||||
# non-reading guard therefore requires either a locatable box still carrying the
|
||||
# tail (fixture 3) or raw/no-echo mode (fixture 2b). Real REPL seats read stdin,
|
||||
# which is why this limit is not reachable against agent seats; recorded here so
|
||||
# nobody rediscovers it as a silent gap.
|
||||
tmux -L "$SOCKET" new-session -d -s shapelessraw -c "$TMP" 'stty raw -echo; exec sleep infinity'
|
||||
sleep 0.3
|
||||
if out=$("$SEND" -L "$SOCKET" -t "=shapelessraw" -r 1 -m "fixture six b shapeless raw never consumed" 2>"$TMP/e6b"); then
|
||||
no "unconfirmed: shapeless raw non-reading pane must NOT report success" "expected exit 2, got 0 (out=[$out])"
|
||||
else
|
||||
rc=$?
|
||||
if [ "$rc" -eq 2 ] && grep -qF "could not confirm submission" "$TMP/e6b"; then
|
||||
ok "unconfirmed: shapeless raw non-reading pane => exit 2 + 'could not confirm submission'"
|
||||
else
|
||||
no "unconfirmed: shapeless raw non-reading pane => exit 2 + stderr" "rc=$rc err=[$(cat "$TMP/e6b")]"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "---"
|
||||
echo "PASS=$PASS FAIL=$FAIL"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
|
||||
Reference in New Issue
Block a user