Three reports from the creator, plus two bugs the real clip exposed. 1. A video layer was INVISIBLE in the preview. The pane's per-layer Image is Collapsed by default and switched on by a whitelist of DataTriggers; MediaSource matched none, so the clip decoded into a bitmap that nothing displayed. Same defect the alert box hit on 2026-09-26 and the scoreboard after it — now recorded at the top of docs/ai/ui-surface.md with a test that asserts the bound Image is Visible (`MediaPreviewDisplayTests`). 2. Play is no longer tied to Loop: the button is always enabled (creator ruling — Loop must not toggle Play). Loop still restarts a finished clip, which is the behaviour that was broken. 3. Geometry is now the LAST section of the properties list for every draggable element, with opacity at the top; the web source's duplicate geometry block is gone (it now uses the shared one, which had been sitting above the media panel). 4. The physical mouse-drag test is deleted. It injected real cursor movement, hijacked whatever machine ran it, and failed whenever the desktop was busy. The arithmetic it covered now lives in `Helpers/DragReorderMath.cs` — pure, and covered by `DragReorderMathTests` (threshold, up/down moves, no-op and out-of-range). The two persistence tests were already synthetic. 5. Real-clip check (creator's `test_greenscreen_moving_subject.mp4`, 1920×1080): the detector REJECTED it — a fully saturated green sits at value 1.0 and the detector's 0.98 brightness ceiling threw it away. White highlights are excluded by the saturation floor, which is the property that actually separates them, so the ceiling is gone. With it fixed, the clip is detected as green (high confidence), and keyed through our own pipe 97.8% of pixels go transparent. Measured: keying with the canonical #00B140 keys 0.0% of this clip — which is why the key colour comes from the measured screen. Tests: 567 passed, 0 failed, clean build 0 warnings. The gate's scope check flags `Assets/Videos/test_greenscreen_moving_subject.mp4` — the creator's working copy, deliberately not committed; the fixture lives under ytLive.Tests/Fixtures.
84 lines
3.2 KiB
Bash
84 lines
3.2 KiB
Bash
#!/usr/bin/env bash
|
|
# verify.sh — One gate before committing: clean build (0 warnings) + full test run + scope check.
|
|
# Usage: ./scripts/verify.sh "file1.cs" "file2.cs" ...
|
|
#
|
|
# Why a clean build? An incremental build SKIPS recompiling unchanged projects, so a
|
|
# "0 Warning(s)" from an incremental build can be a lie (CS8601 slipped past this way on
|
|
# 2026-08-29). This script forces a full rebuild so the 0-warning claim is only ever made
|
|
# against fresh compiler output.
|
|
#
|
|
# Requires WINDOWS dotnet (never Linux dotnet — it re-downloads the windowsdesktop packs
|
|
# over the slow 9p bridge; see docs/ai/environment.md -> Run). Reads the Windows path from the
|
|
# WSL mount.
|
|
|
|
set -euo pipefail
|
|
|
|
DOTNET="/mnt/c/Program Files/dotnet/dotnet.exe"
|
|
[ -x "$DOTNET" ] || { echo "❌ Windows dotnet not found at $DOTNET"; exit 1; }
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
ROOTWIN="$(wslpath -w "$ROOT")"
|
|
|
|
echo "══ 1/4 DOC BUDGETS ══"
|
|
# The map stays cheap to read. A commit that PADS a capped file instead of replacing or
|
|
# moving detail fails here (see AGENTS.md -> Reading budget).
|
|
check_budget() {
|
|
local rel="$1" cap="$2" lines
|
|
[ -f "$ROOT/$rel" ] || { echo "✗ $rel is missing"; exit 1; }
|
|
lines=$(wc -l < "$ROOT/$rel")
|
|
if [ "$lines" -gt "$cap" ]; then
|
|
echo "✗ $rel is $lines lines (cap $cap)."
|
|
echo " Move the detail to docs/ai/<subsystem>.md, MyMistakes.md or git log — do not pad."
|
|
exit 1
|
|
fi
|
|
printf " ✓ %-12s %3s/%s lines\n" "$rel" "$lines" "$cap"
|
|
}
|
|
check_budget "AGENTS.md" 210
|
|
check_budget "ai.md" 100
|
|
check_budget "HANDOFF.md" 40
|
|
check_budget "TASKS.md" 120
|
|
|
|
echo "══ 2/4 CLEAN BUILD (expect 0 warnings) ══"
|
|
"$DOTNET" clean "$ROOTWIN\\ytLive.csproj" > /dev/null
|
|
OUT="$("$DOTNET" build "$ROOTWIN\\ytLive.csproj" 2>&1)"
|
|
if echo "$OUT" | grep -qI ": warning"; then
|
|
echo "✗ WARNINGS FOUND:"
|
|
echo "$OUT" | grep -iE ": warning" | sort -u
|
|
exit 1
|
|
fi
|
|
echo "$OUT" | grep -E "Build succeeded" || { echo "$OUT" | tail -5; exit 1; }
|
|
echo "✓ Build clean, 0 warnings."
|
|
|
|
echo "══ 3/4 TEST SUITE ══"
|
|
TESTDLL="$ROOTWIN\\ytLive.Tests\\bin\\Debug\\net8.0-windows10.0.19041.0\\ytLive.Tests.dll"
|
|
"$DOTNET" build "$ROOTWIN\\ytLive.Tests\\ytLive.Tests.csproj" > /dev/null
|
|
set +e
|
|
TEST_ARGS=("$TESTDLL")
|
|
if [ "${PHYSICAL_TESTS:-0}" != "1" ]; then
|
|
TEST_ARGS+=("--TestCaseFilter:FullyQualifiedName!~RealMouseDrag")
|
|
fi
|
|
RUN_RAW="$("$DOTNET" vstest "${TEST_ARGS[@]}" 2>&1)"
|
|
TEST_EXIT=$?
|
|
set -e
|
|
echo "$RUN_RAW" | grep -iE "Passed!|Failed!" | tail -1
|
|
|
|
# Known pre-existing failures (see HANDOFF.md: do not chase). Anything beyond
|
|
# these is a real regression and fails the gate.
|
|
FAILS="$(echo "$RUN_RAW" | grep -iE "\[FAIL\]" || true)"
|
|
KNOWN=$(echo "$FAILS" | grep -cE "Mix_HonorsProviderGains_AndGameMute_KillsTheLoopback|Round_Clip_Corner_Is_Grabbable_And_Shape_Is_Circle" || true)
|
|
echo "$FAILS" | sort -u || true
|
|
|
|
if [ "$TEST_EXIT" -ne 0 ] && [ "$KNOWN" -eq 0 ]; then
|
|
echo "✗ TEST FAILURES that are NOT the known pre-existing pair — investigate."
|
|
exit 1
|
|
fi
|
|
if [ "$TEST_EXIT" -ne 0 ]; then
|
|
echo "⚠ Test exit=$TEST_EXIT but only the 2 known pre-existing failures present (OK)."
|
|
fi
|
|
|
|
echo "══ 4/4 SCOPE CHECK ══"
|
|
"$ROOT/scripts/scope-check.sh" "$@"
|
|
|
|
echo ""
|
|
echo "✓ All gates passed — safe to commit."
|