@@ -142,7 +142,7 @@ jobs:
142142 shift 3
143143 local capture_args=()
144144 local capture_url=http://127.0.0.1:4173/
145- if [ "$width" = 640 ] && [ "$height" = 360 ]; then
145+ if [ "$width" = 640 ] && [ "$height" = 360 ] && [ "$state" = default ] ; then
146146 capture_args+=(--full-page)
147147 fi
148148 if [ "$state" = search-populated ]; then
@@ -162,7 +162,7 @@ jobs:
162162 local route=$1 position=$2 state=$3 width=$4 height=$5
163163 shift 5
164164 local capture_args=()
165- if [ "$width" = 640 ] && [ "$height" = 360 ]; then
165+ if [ "$width" = 640 ] && [ "$height" = 360 ] && [ "$state" = default ] ; then
166166 capture_args+=(--full-page)
167167 fi
168168 node visual-controller/scripts/pipeline_visual_capture.mjs \
@@ -218,18 +218,73 @@ jobs:
218218 "revision": os.environ["SOURCE_REVISION"],
219219 }
220220 expected_routes = {
221- "/reference/client/": {"position": "first", "surface": "python-sdk-client-reference"},
222- "/reference/serializer/": {"position": "middle", "surface": "python-sdk-serializer-reference"},
223- "/reference/testing/": {"position": "final", "surface": "python-sdk-testing-reference"},
221+ "/reference/client/": {
222+ "active": "Client",
223+ "position": "first",
224+ "surface": "python-sdk-client-reference",
225+ },
226+ "/reference/serializer/": {
227+ "active": "Serializer",
228+ "position": "middle",
229+ "surface": "python-sdk-serializer-reference",
230+ },
231+ "/reference/testing/": {
232+ "active": "Testing",
233+ "position": "final",
234+ "surface": "python-sdk-testing-reference",
235+ },
224236 }
237+
238+ def validate_reference_panel(panel, expected_active, label):
239+ if not isinstance(panel, dict):
240+ raise ValueError(f"{label} has no measured reference panel")
241+ try:
242+ active = panel["active"]
243+ drawer = panel["drawer"]
244+ reference_list = panel["list"]
245+ active_top = float(active["top"])
246+ active_bottom = float(active["bottom"])
247+ list_top = float(reference_list["top"])
248+ list_bottom = float(reference_list["bottom"])
249+ drawer_bottom = float(drawer["bottom"])
250+ client_height = float(reference_list["clientHeight"])
251+ except (KeyError, TypeError, ValueError) as error:
252+ raise ValueError(f"{label} has malformed reference panel geometry") from error
253+ if active.get("text") != expected_active:
254+ raise ValueError(f"{label} does not identify its active destination")
255+ if active_top < list_top - 1 or active_bottom > list_bottom + 1:
256+ raise ValueError(f"{label} clips its active destination")
257+ if abs(list_bottom - drawer_bottom) > 1 or client_height < 200:
258+ raise ValueError(f"{label} does not use the available drawer height")
259+ if reference_list.get("overflowY") != "auto":
260+ raise ValueError(f"{label} does not expose the qualified nested-list viewport")
261+
225262 if (
226- keyboard.get("schema") != "durable-workflow.python-docs.nested-navigation/v2 "
263+ keyboard.get("schema") != "durable-workflow.python-docs.nested-navigation/v3 "
227264 or keyboard.get("outcome") != "pass"
228265 or set(keyboard.get("routes", [])) != set(expected_routes)
229266 ):
230267 raise SystemExit("nested reference keyboard evidence did not qualify the required route positions")
231268 if keyboard.get("source") != expected_source:
232269 raise SystemExit("nested reference keyboard evidence is not bound to the captured source")
270+ regression = keyboard.get("regression", {})
271+ three_row_fixture = regression.get("three_row_list", {})
272+ if (
273+ three_row_fixture.get("visible_rows") != 3
274+ or three_row_fixture.get("geometry") != "affected fixture rejected"
275+ or three_row_fixture.get("interaction") != "affected fixture rejected"
276+ ):
277+ raise SystemExit("nested reference evidence did not exercise the three-row clipped-list fixture")
278+ try:
279+ validate_reference_panel(
280+ three_row_fixture.get("reference_panel"),
281+ expected_routes["/reference/testing/"]["active"],
282+ "three-row clipped-list fixture",
283+ )
284+ except ValueError:
285+ pass
286+ else:
287+ raise SystemExit("retained visual-evidence validation accepted the three-row clipped-list fixture")
233288 keyboard_viewports = {
234289 (entry["route"], entry["viewport"]["width"], entry["viewport"]["height"]): entry
235290 for entry in keyboard.get("viewports", [])
@@ -261,7 +316,7 @@ jobs:
261316 viewport_key = (viewport.get("width"), viewport.get("height"))
262317 page_route = urlsplit(captured.get("page_url", "")).path
263318 route_contract = expected_routes.get(page_route)
264- expected_full_page = viewport_key == (640, 360)
319+ expected_full_page = viewport_key == (640, 360) and state == "default"
265320 if (
266321 route_contract is None
267322 or captured.get("surface") != route_contract["surface"]
@@ -280,6 +335,16 @@ jobs:
280335 active_keyboard_controls = keyboard_state.get("active_keyboard_controls")
281336 if state == "navigation-open" and not active_keyboard_controls:
282337 raise SystemExit(f"{report.name} has no active drawer keyboard traversal evidence")
338+ reference_panel = keyboard_state.get("reference_panel")
339+ if state == "navigation-open":
340+ try:
341+ validate_reference_panel(
342+ reference_panel,
343+ route_contract["active"],
344+ report.name,
345+ )
346+ except ValueError as error:
347+ raise SystemExit(str(error)) from error
283348 geometry = captured["geometry"]
284349 if geometry["unreachable_controls"]:
285350 raise SystemExit(
@@ -300,18 +365,19 @@ jobs:
300365 "full_page": captured["full_page"],
301366 "pointer_unreachable_controls": geometry["unreachable_controls"],
302367 "active_keyboard_controls": active_keyboard_controls or [],
368+ "reference_panel": reference_panel,
303369 }
304370 )
305371 if observed_states != expected_states:
306372 raise SystemExit(f"nested reference state matrix does not match: {sorted(observed_states)}")
307373
308374 qualification = {
309- "schema": "durable-workflow.python-docs.nested-navigation-qualification/v2 ",
375+ "schema": "durable-workflow.python-docs.nested-navigation-qualification/v3 ",
310376 "outcome": "pass",
311377 "source": expected_source,
312378 "routes": list(expected_routes),
313379 "states": qualified_states,
314- "regression": keyboard.get(" regression") ,
380+ "regression": regression,
315381 }
316382 (evidence_root / "nested-navigation-qualification.json").write_text(
317383 f"{json.dumps(qualification, indent=2)}\n",
0 commit comments