commit 4150f8458ba83e3fd4eb3a9523584218c33c84d6 from: Isaac Meerleo date: Fri Jul 17 23:53:15 2026 UTC Cover policy-selected epoch drift commit - 18e7ebf97d7549bb8c88fc683e1b6e36576be347 commit + 4150f8458ba83e3fd4eb3a9523584218c33c84d6 blob - 8ff2bc5682349f3e4f3d4140bc2508efb4caf9b8 blob + 6358664c6fd13c6651214d93911aaddb968ba44b --- regress/agent/run.sh +++ regress/agent/run.sh @@ -138,6 +138,17 @@ run_fugu_json() { rc=$? } +run_fugu_resume() { + sid=$1 + prompt=$2 + ( cd "$dir/epoch-work" && \ + FUGU_CONF=$dir/fugu.conf FUGU_LIBEXEC=$dir/libexec/fugu \ + FUGU_CA_FILE=$dir/cert.pem FUGU_RETRY_BASE_MS=50 \ + "$fugu" -r "$sid" -p "$prompt" "$dir/out" 2>"$dir/errout" + rc=$? +} + request_section() { awk -v name="$1" ' $0 == "--- " name " ---" { found = 1; next } @@ -258,6 +269,138 @@ grep -q "$KEY" "$dir/keyout" 2>/dev/null ok "agent loop: provider traffic stays credential-brokered" $? stop_stub +# A compacted System epoch survives process exit. Later Subagent requests +# use its pinned base and policy-selected source snapshots, append the current +# fixed read-only guidance, and omit the Lead-only Compaction notes. Provider +# routing remains invocation configuration: the resumed child uses a named +# route that did not exist when the Session was created. +rm -rf "$HOME/.fugu" +rm -rf "$dir/epoch-work" +mkdir -p "$HOME/.fugu" "$dir/epoch-work" +printf 'SUBAGENT-EPOCH-PERSONAL-OLD\n' > "$HOME/.fugu/FUGU.md" +printf 'SUBAGENT-EPOCH-PROJECT-OLD\n' > "$dir/epoch-work/FUGU.md" +start_stub OK SUMMARY +cat > "$dir/fugu.conf" < "$dir/epoch-input" +( cd "$dir/epoch-work" && FUGU_CONF=$dir/fugu.conf \ + FUGU_LIBEXEC=$dir/libexec/fugu FUGU_CA_FILE=$dir/cert.pem \ + FUGU_RETRY_BASE_MS=50 "$fugu" <"$dir/epoch-input" ) \ + >"$dir/out" 2>"$dir/errout" +rc=$? +ok "resumed agent epoch: compacted seed process exits cleanly" \ + $([ "$rc" -eq 0 ]; echo $?) +journal=$(ls "$sessions"/*.ndjson 2>/dev/null | head -1) +epoch_id=${journal##*/} +epoch_id=${epoch_id%.ndjson} +grep -q '"t":"system-epoch".*"reason":"compact"' "$journal" 2>/dev/null +ok "resumed agent epoch: seed records a compacted System epoch" $? +stop_stub + +printf 'SUBAGENT-EPOCH-PERSONAL-NEW\n' > "$HOME/.fugu/FUGU.md" +printf 'SUBAGENT-EPOCH-PROJECT-NEW\n' > "$dir/epoch-work/FUGU.md" +start_stub AGENTCALL AGENTREPORT AGENTSYNTH +cat > "$dir/fugu.conf" </dev/null +ok "resumed agent epoch: full child omits notes and current source bytes" \ + $([ $? -ne 0 ]; echo $?) +grep -q '^POST /epoch-live-lead HTTP/1.1' "$dir/epoch-full-lead" && \ + grep -q '"model":"SUBAGENT-EPOCH-LIVE-LEAD"' \ + "$dir/epoch-full-lead" && \ + grep -q '^POST /epoch-live-child HTTP/1.1' "$dir/epoch-full-child" && \ + grep -q '"model":"SUBAGENT-EPOCH-LIVE-CHILD"' \ + "$dir/epoch-full-child" +ok "resumed agent epoch: current Lead and named child routes stay live" $? +stop_stub + +start_stub AGENTCALL AGENTREPORT AGENTSYNTH +cat > "$dir/fugu.conf" </dev/null +ok "resumed agent epoch: restricted child suppresses all external snapshots" \ + $([ $? -ne 0 ]; echo $?) +grep -q '^POST /epoch-live-child-restricted HTTP/1.1' \ + "$dir/epoch-restricted-child" && \ + grep -q '"model":"SUBAGENT-EPOCH-LIVE-CHILD-RESTRICTED"' \ + "$dir/epoch-restricted-child" +ok "resumed agent epoch: repeated resume uses current restricted route" $? +stop_stub + # An escaped glob metacharacter is a literal future path, not an unmatched # pattern. It is absent when the coordinator snapshots protect, then the # provider stub creates the literal-star filename before the child starts. blob - 03682d6dfcd86351c3dddda856bdc83bd82a6852 blob + 47e2da6ed0602070c76831e63f4c35816433f8be --- regress/turn/run.sh +++ regress/turn/run.sh @@ -122,6 +122,20 @@ request_log_entry() { # $1 = one-based entry, $2 = out ' "$dir/reqlog" > "$request_entry_file" } +replace_epoch_variant() { # $1 = field, $2 = exact bytes, $3 = Journal + epoch_field=$1 + epoch_value=$2 + epoch_journal=$3 + epoch_hex=$(printf '%s' "$epoch_value" | + hexdump -ve '1/1 "%.2x"') || return 1 + LC_ALL=C sed -E \ + "s#\"$epoch_field\":\"[0-9a-f]*\"#\"$epoch_field\":\"$epoch_hex\"#" \ + "$epoch_journal" > "$epoch_journal.new" || return 1 + grep -q "\"$epoch_field\":\"$epoch_hex\"" \ + "$epoch_journal.new" || return 1 + mv "$epoch_journal.new" "$epoch_journal" +} + sessions=$HOME/.fugu/sessions # --- 0: startup replies are per-Role, empty, and exactly once (I10/I13) --- @@ -884,6 +898,31 @@ n=$(grep -h -c 'project context disabled for resumed s "$dir/out" "$dir/errout" 2>/dev/null | awk '{ n += $1 } END { print n + 0 }') ok "System epoch selection: restricted resume reports one notice" \ $([ "$n" -eq 1 ]; echo $?) + +# The same invocation-scoped presentation event reaches line and curses +# frontends without becoming a Turn. Curses may repaint a transcript row, so +# its raw terminal stream proves presence while the line sink pins one emit. +printf '/quit\n' > "$dir/lin" +( cd "$dir/epoch-work" && FUGU_CONF=$dir/fugu.conf \ + FUGU_LIBEXEC=$dir/libexec/fugu FUGU_CA_FILE=$dir/cert.pem \ + "$fugu" -c <"$dir/lin" >"$dir/out" 2>"$dir/errout" ) +rc=$? +n=$(grep -h -c 'project context disabled for resumed session' \ + "$dir/out" "$dir/errout" 2>/dev/null | awk '{ n += $1 } END { print n + 0 }') +ok "System epoch selection: restricted line resume reports one notice" \ + $([ "$rc" -eq 0 ] && [ "$n" -eq 1 ]; echo $?) +if [ -x "$obj/ptydrive" ]; then + printf '/quit\r' | TERM=vt100 HOME=$HOME \ + FUGU_CONF=$dir/fugu.conf FUGU_LIBEXEC=$dir/libexec/fugu \ + FUGU_CA_FILE=$dir/cert.pem FUGU_RETRY_BASE_MS=50 \ + "$obj/ptydrive" "$fugu" -c >"$dir/cursesout" 2>&1 + rc=$? + grep -a -q 'project context disabled for resumed session' \ + "$dir/cursesout" + notice_rc=$? + ok "System epoch selection: restricted curses resume shows its notice" \ + $([ "$rc" -eq 0 ] && [ "$notice_rc" -eq 0 ]; echo $?) +fi n=$(grep -c '"t":"system-epoch".*"reason":"start"' \ "$sessions"/*.ndjson 2>/dev/null) ok "System epoch selection: resumes do not rebuild the epoch" \ @@ -926,6 +965,33 @@ ok "System epoch migration: durable boundary precedes [ "$migration_line" -lt "$turn_line" ]; echo $?) stop_stub +# A second resume must reuse the additive migration epoch exactly rather than +# rebuilding it from a changed invocation or appending another migration. +start_stub "OK" +cat > "$dir/fugu.conf" < "$dir/fugu.conf" </dev/null | head -1) +epoch_id=${journal##*/} +epoch_id=${epoch_id%.ndjson} +replace_epoch_variant full "DRIFT-FULL-V0" "$journal" && \ + replace_epoch_variant restricted "DRIFT-RESTRICTED-V0" "$journal" +ok "System epoch composition drift: exact stored variants are pinned" $? +stop_stub + +start_stub "OAI_OVERFLOW OAI_SUMMARY OAI_OK" +cat > "$dir/fugu.conf" < "$dir/lin" +cat > "$dir/fugu.conf" < "$dir/fugu.conf" < "$dir/fugu.conf" < "$dir/fugu.conf" <