fffiloni commited on
Commit
61c6c9a
·
verified ·
1 Parent(s): 704b329

Upload 58 files

Browse files
Files changed (36) hide show
  1. tests/test_v52_ui_fixes.py +1 -1
  2. tests/test_v57_live_pi_traces.py +1 -1
  3. tests/test_v58_stable_refresh_pi_stdout.py +1 -1
  4. tests/test_v59_job_log_progress_clean.py +1 -1
  5. tests/test_v60_cancel_persist_delete_run.py +1 -1
  6. tests/test_v61_stabilize_buttons_runtime.py +1 -1
  7. tests/test_v62_progress_perf_clean_delete.py +1 -1
  8. tests/test_v63_delete_import_fix.py +1 -1
  9. tests/test_v64_delete_clean_events_timeline.py +1 -1
  10. tests/test_v65_floating_form_timeline.py +1 -1
  11. tests/test_v66_clean_qwen_coder_path.py +1 -1
  12. tests/test_v67_monotonic_progress_events.py +1 -1
  13. tests/test_v68_stable_events_timeline_centering.py +1 -1
  14. tests/test_v69_unified_progress_state.py +2 -2
  15. tests/test_v70_progress_resume_events_latency.py +1 -1
  16. tests/test_v71_compact_stable_progress.py +1 -1
  17. tests/test_v72_clear_modes_space_link_gating.py +1 -1
  18. tests/test_v73_toast_timer_clean_active_run.py +1 -1
  19. tests/test_v74_grouped_timeline_rings.py +1 -1
  20. tests/test_v75_runs_sort_timeline_cost_note.py +1 -1
  21. tests/test_v76_coherent_progress_status_colors.py +1 -1
  22. tests/test_v77_terminal_report_refresh_no_launch_result.py +1 -1
  23. tests/test_v78_report_preview_cost_note_cleanup.py +1 -1
  24. tests/test_v79_remove_active_report_preview.py +1 -1
  25. tests/test_v80_topbar_clean_timeline_failure_feedback.py +1 -1
  26. tests/test_v81_robust_timeline_color_feedback.py +2 -2
  27. tests/test_v82_elegant_failure_trace_timeline.py +40 -0
  28. tests/test_v83_success_progress_bar_color.py +44 -0
  29. tests/test_v84_hardware_fallback_visual_state.py +36 -0
  30. tests/test_v85_failure_reason_feedback.py +41 -0
  31. tests/test_v86_hf_error_detail_reasons.py +42 -0
  32. tests/test_v87_validation_panel_prefill_separation.py +50 -0
  33. tests/test_v88_validation_schema_kwargs_sanitizer.py +35 -0
  34. tests/test_v89_main_validation_zerogpu_contract_layout.py +53 -0
  35. tests/test_v90_pi_model_mismatch_warning.py +44 -0
  36. tests/test_v91_pi_model_detection_from_published_traces.py +29 -0
tests/test_v52_ui_fixes.py CHANGED
@@ -35,6 +35,6 @@ def test_runs_explorer_is_limited_to_five_rows_with_pagination():
35
 
36
  def test_progress_endpoint_uses_view_model_links_for_job_url():
37
  app_py = Path("app.py").read_text(encoding="utf-8")
38
- assert '"version": "v81-robust-timeline-color-feedback"' in app_py
39
  assert 'view = build_run_view_model(run_id, bundle, bucket_source=bucket_source)' in app_py
40
  assert '"links": view.get("links")' in app_py
 
35
 
36
  def test_progress_endpoint_uses_view_model_links_for_job_url():
37
  app_py = Path("app.py").read_text(encoding="utf-8")
38
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in app_py
39
  assert 'view = build_run_view_model(run_id, bundle, bucket_source=bucket_source)' in app_py
40
  assert '"links": view.get("links")' in app_py
tests/test_v57_live_pi_traces.py CHANGED
@@ -32,4 +32,4 @@ def test_ui_has_pi_live_trace_panel_and_renderer():
32
 
33
 
34
  def test_app_version_v57():
35
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
32
 
33
 
34
  def test_app_version_v57():
35
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v58_stable_refresh_pi_stdout.py CHANGED
@@ -23,4 +23,4 @@ def test_elapsed_ticks_client_side_each_second():
23
 
24
 
25
  def test_app_version_v62():
26
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
23
 
24
 
25
  def test_app_version_v62():
26
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v59_job_log_progress_clean.py CHANGED
@@ -51,4 +51,4 @@ def test_progress_renderer_no_longer_sets_active_run_link_buttons():
51
 
52
 
53
  def test_app_version_v59():
54
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
51
 
52
 
53
  def test_app_version_v59():
54
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v60_cancel_persist_delete_run.py CHANGED
@@ -44,4 +44,4 @@ def test_active_run_still_only_has_cancel_button():
44
 
45
 
46
  def test_app_version_v60():
47
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
44
 
45
 
46
  def test_app_version_v60():
47
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v61_stabilize_buttons_runtime.py CHANGED
@@ -45,4 +45,4 @@ setTimeout(()=>process.exit(0), 25);
45
 
46
 
47
  def test_app_version_v61():
48
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
45
 
46
 
47
  def test_app_version_v61():
48
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v62_progress_perf_clean_delete.py CHANGED
@@ -40,4 +40,4 @@ def test_delete_selected_run_clears_ui_and_refreshes_runs():
40
 
41
 
42
  def test_app_version_v62():
43
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
40
 
41
 
42
  def test_app_version_v62():
43
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v63_delete_import_fix.py CHANGED
@@ -14,4 +14,4 @@ def test_bucket_delete_helper_exists():
14
 
15
 
16
  def test_app_version_v63():
17
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
14
 
15
 
16
  def test_app_version_v63():
17
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v64_delete_clean_events_timeline.py CHANGED
@@ -50,4 +50,4 @@ def test_timeline_has_stopped_state_without_running_animation_confusion():
50
 
51
 
52
  def test_app_version_v64():
53
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
50
 
51
 
52
  def test_app_version_v64():
53
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v65_floating_form_timeline.py CHANGED
@@ -57,4 +57,4 @@ def test_frontend_timeline_supports_stopped_status():
57
 
58
 
59
  def test_app_version_v65():
60
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
57
 
58
 
59
  def test_app_version_v65():
60
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v66_clean_qwen_coder_path.py CHANGED
@@ -19,4 +19,4 @@ def test_preferred_gpu_stays_zerogpu_only_and_fallback_a10g_large_default():
19
 
20
 
21
  def test_app_version_v66():
22
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
19
 
20
 
21
  def test_app_version_v66():
22
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v67_monotonic_progress_events.py CHANGED
@@ -36,4 +36,4 @@ def test_light_poll_cannot_reset_timeline_signature_to_earlier_steps():
36
 
37
 
38
  def test_app_version_v67():
39
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
36
 
37
 
38
  def test_app_version_v67():
39
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v68_stable_events_timeline_centering.py CHANGED
@@ -31,4 +31,4 @@ def test_timeline_centers_even_when_signature_is_unchanged():
31
 
32
 
33
  def test_app_version_v68():
34
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
31
 
32
 
33
  def test_app_version_v68():
34
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v69_unified_progress_state.py CHANGED
@@ -7,7 +7,7 @@ def test_current_step_uses_stabilized_timeline_not_view_header():
7
  assert "const stable=stabilizeProgressPayload(p,view)" in render
8
  assert "setText('currentStep',stable.currentStepLabel" in render
9
  assert "header.current_phase_label" not in render
10
- assert "animateProgressBar(progress,runStatus,stable.currentStep)" in render
11
 
12
 
13
  def test_events_and_last_event_use_same_stable_event_source():
@@ -33,4 +33,4 @@ def test_timeline_centering_css_escape_is_safe():
33
 
34
 
35
  def test_app_version_v69():
36
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
7
  assert "const stable=stabilizeProgressPayload(p,view)" in render
8
  assert "setText('currentStep',stable.currentStepLabel" in render
9
  assert "header.current_phase_label" not in render
10
+ assert "animateProgressBar(progress,visualRunStatus,stable.currentStep)" in render
11
 
12
 
13
  def test_events_and_last_event_use_same_stable_event_source():
 
33
 
34
 
35
  def test_app_version_v69():
36
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v70_progress_resume_events_latency.py CHANGED
@@ -58,4 +58,4 @@ def test_resume_latest_falls_back_to_latest_run():
58
 
59
 
60
  def test_app_version_v70():
61
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
58
 
59
 
60
  def test_app_version_v70():
61
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v71_compact_stable_progress.py CHANGED
@@ -32,4 +32,4 @@ def test_refresh_progress_prefers_canonical_status():
32
 
33
 
34
  def test_app_version_v71():
35
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
32
 
33
 
34
  def test_app_version_v71():
35
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v72_clear_modes_space_link_gating.py CHANGED
@@ -32,4 +32,4 @@ def test_launch_result_removed_and_selected_links_are_still_gated():
32
  assert "setLink('selectedOpenSettings',ready&&summary.target_space_url" in runs_js
33
 
34
  def test_app_version_v72():
35
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
32
  assert "setLink('selectedOpenSettings',ready&&summary.target_space_url" in runs_js
33
 
34
  def test_app_version_v72():
35
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v73_toast_timer_clean_active_run.py CHANGED
@@ -27,4 +27,4 @@ def test_progress_poll_errors_use_floating_toast_not_internal_banner():
27
 
28
 
29
  def test_app_version_v73():
30
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
27
 
28
 
29
  def test_app_version_v73():
30
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v74_grouped_timeline_rings.py CHANGED
@@ -41,4 +41,4 @@ def test_timeline_dots_use_conic_gradient_ring():
41
 
42
 
43
  def test_app_version_v74():
44
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
41
 
42
 
43
  def test_app_version_v74():
44
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v75_runs_sort_timeline_cost_note.py CHANGED
@@ -38,4 +38,4 @@ def test_inference_provider_cost_note_is_visible_near_pi_model():
38
 
39
 
40
  def test_app_version_v75():
41
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
38
 
39
 
40
  def test_app_version_v75():
41
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v76_coherent_progress_status_colors.py CHANGED
@@ -50,4 +50,4 @@ def test_failed_events_superseded_by_later_step_are_shown_as_recovered_warning()
50
 
51
 
52
  def test_app_version_v76():
53
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
50
 
51
 
52
  def test_app_version_v76():
53
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v77_terminal_report_refresh_no_launch_result.py CHANGED
@@ -23,4 +23,4 @@ def test_terminal_run_still_refreshes_selected_run_detail_without_active_report_
23
 
24
 
25
  def test_app_version_v77():
26
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
23
 
24
 
25
  def test_app_version_v77():
26
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v78_report_preview_cost_note_cleanup.py CHANGED
@@ -36,4 +36,4 @@ def test_active_run_report_preview_block_removed():
36
 
37
 
38
  def test_app_version_v78():
39
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
36
 
37
 
38
  def test_app_version_v78():
39
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v79_remove_active_report_preview.py CHANGED
@@ -27,4 +27,4 @@ def test_selected_run_report_preview_support_can_remain_if_used_elsewhere():
27
 
28
 
29
  def test_app_version_v79():
30
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
27
 
28
 
29
  def test_app_version_v79():
30
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v80_topbar_clean_timeline_failure_feedback.py CHANGED
@@ -31,4 +31,4 @@ def test_recovered_failure_has_warning_color_not_green():
31
 
32
 
33
  def test_app_version_v80():
34
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
31
 
32
 
33
  def test_app_version_v80():
34
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v81_robust_timeline_color_feedback.py CHANGED
@@ -16,7 +16,7 @@ def test_timeline_prefers_problem_group_for_scroll_on_selected_old_runs():
16
  assert "function firstProblemGroupKey" in js
17
  assert "function currentCompactGroupKey(fullItems=[],overallStatus='')" in js
18
  assert "const problem=firstProblemGroupKey(fullItems,overallStatus)" in js
19
- assert "const currentKey=currentCompactGroupKey(fullList,overallStatus)" in js
20
 
21
 
22
  def test_timeline_scroll_resets_cleanly_between_selected_runs():
@@ -34,4 +34,4 @@ def test_recovered_failures_remain_amber_not_green():
34
 
35
 
36
  def test_app_version_v81():
37
- assert '"version": "v81-robust-timeline-color-feedback"' in Path("app.py").read_text(encoding="utf-8")
 
16
  assert "function firstProblemGroupKey" in js
17
  assert "function currentCompactGroupKey(fullItems=[],overallStatus='')" in js
18
  assert "const problem=firstProblemGroupKey(fullItems,overallStatus)" in js
19
+ assert "const currentKey=trace.key||currentCompactGroupKey(fullList,overallStatus)" in js
20
 
21
 
22
  def test_timeline_scroll_resets_cleanly_between_selected_runs():
 
34
 
35
 
36
  def test_app_version_v81():
37
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v82_elegant_failure_trace_timeline.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_timeline_has_explicit_failure_trace_note():
5
+ html = Path("web/index.html").read_text(encoding="utf-8")
6
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
7
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
8
+ assert 'id="timelineTraceNote"' in html
9
+ assert "function timelineTraceModel" in js
10
+ assert "function renderTimelineTraceNote" in js
11
+ assert "Failure trace" in js
12
+ assert ".timeline-trace-note.failed" in css
13
+
14
+
15
+ def test_failure_trace_styles_breakpoint_and_post_failure_tail():
16
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
17
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
18
+ assert "function traceClassForStep" in js
19
+ assert "trace-breakpoint" in js
20
+ assert "trace-post-failure" in js
21
+ assert "timeline.trace-failed .step.trace-breakpoint" in css
22
+ assert "repeating-linear-gradient" in css
23
+
24
+
25
+ def test_old_runs_merge_events_before_stabilizing_timeline():
26
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
27
+ render = js.split("function renderRunViewModel", 1)[1].split("function renderProgress", 1)[0]
28
+ assert render.index("mergeStableEvents") < render.index("stabilizeProgressPayload")
29
+ render_progress = js.split("function renderProgress", 1)[1]
30
+ assert render_progress.index("mergeStableEvents") < render_progress.index("stabilizeProgressPayload")
31
+
32
+
33
+ def test_backend_timeline_failed_item_fallback_exists():
34
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
35
+ assert "function failedItemInfoForGroup" in js
36
+ assert "failedItemInfoForGroup(group,byStep)" in js
37
+
38
+
39
+ def test_app_version_v82():
40
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v83_success_progress_bar_color.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ from src.progress import progress_from_events
4
+
5
+
6
+ def test_frontend_success_detection_covers_real_success_statuses():
7
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
8
+ components = Path("web/static/components.js").read_text(encoding="utf-8")
9
+ for token in [
10
+ "full_inference_candidate_health_passed",
11
+ "full_inference_success",
12
+ "health_only",
13
+ "repair_success",
14
+ ]:
15
+ assert token in js
16
+ assert token in components
17
+ assert "let klass=visualStatusClass(status);if(value>=100&&klass==='neutral')klass='success'" in js
18
+
19
+
20
+ def test_progress_bar_prefers_backend_visual_status():
21
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
22
+ assert "const visualRunStatus=p.visual_status||runStatus" in js
23
+ assert "animateProgressBar(progress,visualRunStatus" in js
24
+ assert "animateProgressBar(progress,p.visual_status||p.status" in js
25
+
26
+
27
+ def test_backend_visual_status_success_for_health_only():
28
+ result = progress_from_events([
29
+ {"ts": "2026-06-02T10:00:00+00:00", "step": "done", "status": "health_only"}
30
+ ], state={"status": "health_only"})
31
+ assert result["status"] == "health_only"
32
+ assert result["visual_status"] == "success"
33
+ assert result["progress"] == 100
34
+
35
+
36
+ def test_backend_visual_status_stopped_for_manual_or_blocker():
37
+ result = progress_from_events([
38
+ {"ts": "2026-06-02T10:00:00+00:00", "step": "done", "status": "manual_hardware_required"}
39
+ ], state={"status": "manual_hardware_required"})
40
+ assert result["visual_status"] == "stopped"
41
+
42
+
43
+ def test_app_version_v83():
44
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v84_hardware_fallback_visual_state.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_hardware_fallback_has_dedicated_timeline_status_not_recovered_incident():
5
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
6
+ assert "function isHardwareFallbackEvent" in js
7
+ assert "function isExpectedFallbackFailure" in js
8
+ assert "return 'fallback'" in js
9
+ assert "status==='fallback'" in js
10
+ assert "Hardware fallback" in js
11
+ assert "Recovered after an incident at Hardware" not in js
12
+
13
+
14
+ def test_fallback_trace_message_is_neutral_routing_language():
15
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
16
+ assert "ZeroGPU was not used for this run" in js
17
+ assert "switched to the fallback GPU" in js
18
+ assert "const title=trace.mode==='failed'?'Failure trace':(trace.mode==='fallback'?'Hardware fallback':'Recovered incident')" in js
19
+
20
+
21
+ def test_hardware_fallback_has_blue_visual_style():
22
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
23
+ assert ".step.status-fallback" in css
24
+ assert ".timeline-trace-note.fallback" in css
25
+ assert ".timeline.trace-fallback .step.trace-fallback" in css
26
+ assert ".activity-row.hardware-fallback" in css
27
+
28
+
29
+ def test_activity_feed_labels_hardware_fallback_as_route():
30
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
31
+ assert "return'hardware-fallback'" in js
32
+ assert "fallback route" in js
33
+
34
+
35
+ def test_app_version_v84():
36
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v85_failure_reason_feedback.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_failure_and_fallback_reason_helpers_exist():
5
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
6
+ assert "function eventReason" in js
7
+ assert "function zeroGpuReason" in js
8
+ assert "function failureReasonForGroup" in js
9
+ assert "function fallbackReasonForGroup" in js
10
+ assert "quota" in js
11
+ assert "ZeroGPU was unavailable" in js
12
+
13
+
14
+ def test_timeline_trace_note_displays_reason():
15
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
16
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
17
+ assert "trace.reason" in js
18
+ assert '<b>Reason:</b>' in js
19
+ assert "trace-reason" in js
20
+ assert ".timeline-trace-note .trace-reason" in css
21
+
22
+
23
+ def test_timeline_step_has_reason_tooltip_and_short_reason_line():
24
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
25
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
26
+ assert "reasonForTimelineItem" in js
27
+ assert "step-reason" in js
28
+ assert 'title="${escapeHtml(reason)}"' in js
29
+ assert ".step .step-reason" in css
30
+
31
+
32
+ def test_activity_feed_can_show_event_reason_detail():
33
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
34
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
35
+ assert "event-reason" in js
36
+ assert "const reason=eventReason(item)" in js
37
+ assert ".activity-row .event-reason" in css
38
+
39
+
40
+ def test_app_version_v85():
41
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v86_hf_error_detail_reasons.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_frontend_reads_error_reason_from_event_data_before_generic_message():
5
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
6
+ assert "data.hf_error_detail" in js
7
+ assert "data.hf_error_message" in js
8
+ assert "data.response_text" in js
9
+ assert "data.response_body" in js
10
+ assert "data.error" in js
11
+ assert "data.reason" in js
12
+ assert "event.message" in js
13
+
14
+
15
+ def test_zerogpu_reason_detects_quota_usage_exceeded_terms():
16
+ js = Path("web/static/progress.js").read_text(encoding="utf-8")
17
+ assert "lower.includes('quota')" in js
18
+ assert "lower.includes('usage')" in js
19
+ assert "lower.includes('exceeded')" in js
20
+ assert "ZeroGPU was unavailable" in js
21
+
22
+
23
+ def test_worker_extracts_hf_http_exception_response_details():
24
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
25
+ assert "def exception_payload" in worker
26
+ assert "response.text" in worker
27
+ assert "response.json()" in worker
28
+ assert '"hf_error_detail"' in worker
29
+ assert '"hf_error_message"' in worker
30
+ assert '"status_code"' in worker
31
+
32
+
33
+ def test_space_hardware_events_include_hf_error_payload():
34
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
35
+ assert "exc_payload = exception_payload(exc)" in worker
36
+ assert "create_repo_space_hardware" in worker
37
+ assert "**exc_payload" in worker
38
+ assert "Could not create Space with requested hardware" in worker
39
+
40
+
41
+ def test_app_version_v86():
42
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v87_validation_panel_prefill_separation.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_validation_launch_does_not_replace_active_run():
5
+ js = Path("web/static/app.js").read_text(encoding="utf-8")
6
+ launch = js.split("async function launchValidate", 1)[1].split("async function refreshRunReportPreview", 1)[0]
7
+ assert "setActiveRun(result)" not in launch
8
+ assert "renderValidationLaunchResult(result)" in launch
9
+ assert "startValidationPolling(result.run_id)" in launch
10
+ assert "state.validationRunId" in js
11
+ assert "validationPoll" in js
12
+
13
+
14
+ def test_validation_prefill_copies_args_kwargs_from_selected_run():
15
+ js = Path("web/static/app.js").read_text(encoding="utf-8")
16
+ assert "function validationPrefillFromDetail" in js
17
+ assert "smoke.test_args" in js
18
+ assert "launch.test_args_json" in js
19
+ assert "smoke.test_kwargs" in js
20
+ assert "launch.test_kwargs_json" in js
21
+ assert "setInputValue('testArgs',prettyJson(prefill.args))" in js
22
+ assert "setInputValue('testKwargs',prettyJson(prefill.kwargs))" in js
23
+
24
+
25
+ def test_validation_form_enforces_json_array_and_object():
26
+ js = Path("web/static/app.js").read_text(encoding="utf-8")
27
+ app = Path("app.py").read_text(encoding="utf-8")
28
+ assert "Test args must be a JSON array" in js
29
+ assert "Test kwargs must be a JSON object" in js
30
+ assert "test_args_json must be a JSON array" in app
31
+ assert "test_kwargs_json must be a JSON object" in app
32
+
33
+
34
+ def test_validation_ui_explains_separate_validation_run():
35
+ html = Path("web/index.html").read_text(encoding="utf-8")
36
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
37
+ assert "Validation launches a separate validation run" in html
38
+ assert "does not replace the current Active Run" in html
39
+ assert ".validation-help" in css
40
+
41
+
42
+ def test_default_validation_args_are_positional_not_inputs_object():
43
+ html = Path("web/index.html").read_text(encoding="utf-8")
44
+ test_args = html.split('id="testArgs"', 1)[1].split("</textarea>", 1)[0]
45
+ assert '"inputs"' not in test_args
46
+ assert "Explain the concept of agentic AI" in test_args
47
+
48
+
49
+ def test_app_version_v87():
50
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v88_validation_schema_kwargs_sanitizer.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_validation_worker_extracts_endpoint_parameters_from_schema():
5
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
6
+ assert "def endpoint_schema_for_api" in worker
7
+ assert "def endpoint_parameter_names" in worker
8
+ assert "parameter_name" in worker
9
+ assert "endpoint_parameters" in worker
10
+
11
+
12
+ def test_validation_worker_sanitizes_unsupported_kwargs():
13
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
14
+ assert "def sanitize_kwargs_for_schema" in worker
15
+ assert "safe_kwargs, dropped_kwargs, endpoint_parameters" in worker
16
+ assert "Ignored unsupported validation kwargs" in worker
17
+ assert "ignored_test_kwargs" in worker
18
+ assert "original_test_kwargs" in worker
19
+
20
+
21
+ def test_validation_worker_retries_when_gradio_rejects_kwargs():
22
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
23
+ assert "not a valid key-word argument" in worker
24
+ assert "Retrying validation without keyword arguments" in worker
25
+ assert "client.predict(*test_args, api_name=api_name)" in worker
26
+
27
+
28
+ def test_validation_ui_explains_endpoint_specific_kwargs():
29
+ html = Path("web/index.html").read_text(encoding="utf-8")
30
+ assert "Test kwargs are endpoint-specific" in html
31
+ assert "ignores unsupported kwargs with a warning" in html
32
+
33
+
34
+ def test_app_version_v88():
35
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v89_main_validation_zerogpu_contract_layout.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_space_test_panel_is_inside_workspace_after_active_run():
5
+ html = Path("web/index.html").read_text(encoding="utf-8")
6
+ active_idx = html.index('id="activeRunPanel"')
7
+ space_test_idx = html.index('id="spaceTestSection"')
8
+ runs_idx = html.index('id="runsExplorerPanel"')
9
+ workspace_end = html.index('</section>', runs_idx)
10
+ assert active_idx < space_test_idx < runs_idx
11
+ assert space_test_idx < workspace_end
12
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
13
+ assert "v89: Space Test lives under Active Run" in css
14
+ assert "workspace-grid > .space-test-panel" in css
15
+ assert "grid-column:2" in css
16
+
17
+
18
+ def test_build_job_passes_expected_output_type_to_worker():
19
+ app = Path("app.py").read_text(encoding="utf-8")
20
+ jobs = Path("src/jobs.py").read_text(encoding="utf-8")
21
+ assert "expected_output_type=payload.get(\"expected_output_type\")" in app
22
+ assert "expected_output_type: str | None = None" in jobs
23
+ assert 'env["EXPECTED_OUTPUT_TYPE"]' in jobs
24
+
25
+
26
+ def test_main_worker_runs_live_generation_smoke_and_zerogpu_contract():
27
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
28
+ assert "def run_generation_smoke" in worker
29
+ assert "Calling live generation endpoint for ZeroGPU timing" in worker
30
+ assert "measured_zero_gpu_recommendation" in worker
31
+ assert "recommendation_source" in worker
32
+ assert "recommendation_confidence" in worker
33
+ assert "observed_latency_seconds" in worker
34
+
35
+
36
+ def test_inference_gate_uses_generation_smoke_success():
37
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
38
+ assert "generation_smoke: dict | None" in worker
39
+ assert "generation_smoke_passed" in worker
40
+ assert "zero_gpu_duration_measured" in worker
41
+ assert "full_inference_success" in worker
42
+ assert "live generation smoke test passed" in worker.lower()
43
+
44
+
45
+ def test_report_and_state_include_generation_smoke():
46
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
47
+ assert '"generation_smoke": generation_smoke' in worker
48
+ assert "Live generation smoke / ZeroGPU duration" in worker
49
+ assert "zero_gpu_duration_recommendation" in worker
50
+
51
+
52
+ def test_app_version_v89():
53
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v90_pi_model_mismatch_warning.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_worker_detects_pi_model_resolution_and_mismatch():
5
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
6
+ assert "def detect_pi_model_resolution" in worker
7
+ assert "def extract_pi_models_from_text" in worker
8
+ assert "Kimi" in worker
9
+ assert "pi_model_resolution.json" in worker
10
+ assert "mismatch" in worker
11
+ assert "emit_pi_model_resolution" in worker
12
+
13
+
14
+ def test_worker_emits_pi_model_mismatch_event_and_state():
15
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
16
+ assert "Pi assistant model appears to differ from the requested model" in worker
17
+ assert '"pi_model_resolution": pi_model_resolution' in worker
18
+ assert "## Pi assistant model" in worker
19
+
20
+
21
+ def test_bucket_exposes_pi_model_resolution_to_ui():
22
+ bucket = Path("src/bucket.py").read_text(encoding="utf-8")
23
+ assert "pi_model_resolution.json" in bucket
24
+ assert '"pi_model_resolution"' in bucket
25
+
26
+
27
+ def test_ui_warns_when_pi_provider_model_changed():
28
+ runs = Path("web/static/runs.js").read_text(encoding="utf-8")
29
+ progress = Path("web/static/progress.js").read_text(encoding="utf-8")
30
+ css = Path("web/static/app.css").read_text(encoding="utf-8")
31
+ assert "Pi assistant model changed" in runs
32
+ assert "Inference Providers routing/fallback" in runs
33
+ assert "pi_model_resolution" in progress
34
+ assert "v90: Pi/provider model mismatch warning" in css
35
+
36
+
37
+ def test_pi_model_resolution_step_is_in_timeline():
38
+ progress = Path("web/static/progress.js").read_text(encoding="utf-8")
39
+ assert "pi_model_resolution" in progress
40
+ assert "Pi verify" in progress
41
+
42
+
43
+ def test_app_version_v90():
44
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")
tests/test_v91_pi_model_detection_from_published_traces.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+
4
+ def test_bucket_can_reconstruct_pi_model_resolution_from_published_traces():
5
+ bucket = Path("src/bucket.py").read_text(encoding="utf-8")
6
+ assert "def _trace_based_pi_model_resolution" in bucket
7
+ assert "traces/redacted/**/*.jsonl" in bucket
8
+ assert "logs/pi_output.txt" in bucket
9
+ assert "published_pi_traces" in bucket
10
+ assert "_extract_pi_models_from_text" in bucket
11
+
12
+
13
+ def test_read_run_bundle_uses_trace_fallback_when_resolution_file_missing():
14
+ bucket = Path("src/bucket.py").read_text(encoding="utf-8")
15
+ assert 'if not bundle.get("pi_model_resolution")' in bucket
16
+ assert '_trace_based_pi_model_resolution(run_id, bundle' in bucket
17
+ assert '"pi_model_resolution": pi_model_resolution' in bucket
18
+
19
+
20
+ def test_worker_marks_model_resolution_source_as_after_trace_sync():
21
+ worker = Path("src/worker_payload.py").read_text(encoding="utf-8")
22
+ assert "Pi sessions are the source of truth" in worker
23
+ assert "published_pi_traces_after_sync" in worker
24
+ assert "collect_pi_traces(run_dir, events_path)" in worker
25
+ assert "detect_pi_model_resolution(pi_model, run_dir, pi_out)" in worker
26
+
27
+
28
+ def test_app_version_v91():
29
+ assert '"version": "v91-pi-model-detection-from-published-traces"' in Path("app.py").read_text(encoding="utf-8")