Spaces:
Sleeping
Sleeping
Bundle iPhone benchmark v0.2.1
Browse filesAdds strict physical-device and iOS minimum validation plus the exact-adapter preflight contract.
- VERSION +1 -1
- profiles/iphone-v0.1.json +16 -8
- scorer.py +57 -2
VERSION
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
0.2.
|
|
|
|
| 1 |
+
0.2.1
|
profiles/iphone-v0.1.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
{
|
| 2 |
"profile_id": "iphone-v0.1",
|
| 3 |
-
"profile_version": "0.1.
|
| 4 |
-
"benchmark_version": "0.2.
|
| 5 |
"reference_platform": "iPhone",
|
| 6 |
"status": "active",
|
| 7 |
"scope": "The first public reference track. Canonical tasks and scoring remain platform-neutral so an Android profile can be added later without changing task IDs.",
|
|
@@ -82,15 +82,23 @@
|
|
| 82 |
"SystemLanguageModel.default",
|
| 83 |
"Qwen/Qwen2.5-0.5B-Instruct-GGUF Q4_K_M through pinned llama.cpp"
|
| 84 |
],
|
| 85 |
-
"
|
| 86 |
-
"
|
| 87 |
-
"
|
| 88 |
-
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
| 90 |
],
|
| 91 |
-
"
|
|
|
|
| 92 |
},
|
| 93 |
"task_sets": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
"smoke": [
|
| 95 |
"PERM-001",
|
| 96 |
"PERM-003",
|
|
|
|
| 1 |
{
|
| 2 |
"profile_id": "iphone-v0.1",
|
| 3 |
+
"profile_version": "0.1.1",
|
| 4 |
+
"benchmark_version": "0.2.1",
|
| 5 |
"reference_platform": "iPhone",
|
| 6 |
"status": "active",
|
| 7 |
"scope": "The first public reference track. Canonical tasks and scoring remain platform-neutral so an Android profile can be added later without changing task IDs.",
|
|
|
|
| 82 |
"SystemLanguageModel.default",
|
| 83 |
"Qwen/Qwen2.5-0.5B-Instruct-GGUF Q4_K_M through pinned llama.cpp"
|
| 84 |
],
|
| 85 |
+
"preflight_tasks": [
|
| 86 |
+
"PERM-001",
|
| 87 |
+
"PERM-002"
|
| 88 |
+
],
|
| 89 |
+
"preflight_synthetic_tools": [
|
| 90 |
+
"contacts.search",
|
| 91 |
+
"messages.send",
|
| 92 |
+
"phone.call"
|
| 93 |
],
|
| 94 |
+
"fixture_policy": "For every task, expose inert adapters with exactly the names and argument schemas declared in that task's available_tools field. A generic substitute tool is not score-equivalent.",
|
| 95 |
+
"side_effect_policy": "All tools operate on synthetic in-app fixtures or capture proposed actions for host confirmation. No real message, call, contact lookup, file, account, or device side effect is allowed."
|
| 96 |
},
|
| 97 |
"task_sets": {
|
| 98 |
+
"preflight": [
|
| 99 |
+
"PERM-001",
|
| 100 |
+
"PERM-002"
|
| 101 |
+
],
|
| 102 |
"smoke": [
|
| 103 |
"PERM-001",
|
| 104 |
"PERM-003",
|
scorer.py
CHANGED
|
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
| 9 |
|
| 10 |
import argparse
|
| 11 |
import json
|
|
|
|
| 12 |
import statistics
|
| 13 |
from collections import defaultdict
|
| 14 |
from pathlib import Path
|
|
@@ -64,6 +65,24 @@ def profile_execution_mode(profile: dict[str, Any], task_id: str) -> str | None:
|
|
| 64 |
return None
|
| 65 |
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
def validate_profile_result(
|
| 68 |
profile: dict[str, Any],
|
| 69 |
task: dict[str, Any],
|
|
@@ -83,10 +102,46 @@ def validate_profile_result(
|
|
| 83 |
errors.append(f"execution_mode must be {expected_mode}")
|
| 84 |
|
| 85 |
device = result.get("device") or {}
|
|
|
|
| 86 |
if device.get("os") != "iOS":
|
| 87 |
errors.append("device.os must be iOS")
|
| 88 |
-
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
for dotted_path in profile.get("required_metadata") or []:
|
| 92 |
if deep_get(result, dotted_path) is None:
|
|
|
|
| 9 |
|
| 10 |
import argparse
|
| 11 |
import json
|
| 12 |
+
import re
|
| 13 |
import statistics
|
| 14 |
from collections import defaultdict
|
| 15 |
from pathlib import Path
|
|
|
|
| 65 |
return None
|
| 66 |
|
| 67 |
|
| 68 |
+
def version_numbers(value: Any) -> tuple[int, ...] | None:
|
| 69 |
+
if not isinstance(value, str):
|
| 70 |
+
return None
|
| 71 |
+
numbers = tuple(int(part) for part in re.findall(r"\d+", value))
|
| 72 |
+
return numbers or None
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def version_at_least(actual: Any, minimum: Any) -> bool:
|
| 76 |
+
actual_numbers = version_numbers(actual)
|
| 77 |
+
minimum_numbers = version_numbers(minimum)
|
| 78 |
+
if actual_numbers is None or minimum_numbers is None:
|
| 79 |
+
return False
|
| 80 |
+
width = max(len(actual_numbers), len(minimum_numbers))
|
| 81 |
+
return actual_numbers + (0,) * (width - len(actual_numbers)) >= (
|
| 82 |
+
minimum_numbers + (0,) * (width - len(minimum_numbers))
|
| 83 |
+
)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
def validate_profile_result(
|
| 87 |
profile: dict[str, Any],
|
| 88 |
task: dict[str, Any],
|
|
|
|
| 102 |
errors.append(f"execution_mode must be {expected_mode}")
|
| 103 |
|
| 104 |
device = result.get("device") or {}
|
| 105 |
+
requirements = profile.get("requirements") or {}
|
| 106 |
if device.get("os") != "iOS":
|
| 107 |
errors.append("device.os must be iOS")
|
| 108 |
+
minimum_os = requirements.get("minimum_os")
|
| 109 |
+
if minimum_os and not version_at_least(device.get("os_version"), minimum_os):
|
| 110 |
+
errors.append(f"device.os_version must be at least {minimum_os}")
|
| 111 |
+
if requirements.get("physical_device") and device.get("is_simulator") is not False:
|
| 112 |
+
errors.append("profile rows require a physical iPhone")
|
| 113 |
+
if (
|
| 114 |
+
requirements.get("low_power_mode") is False
|
| 115 |
+
and device.get("low_power_mode") is not False
|
| 116 |
+
):
|
| 117 |
+
errors.append("Low Power Mode must be disabled")
|
| 118 |
+
allowed_thermal_states = set(requirements.get("starting_thermal_state") or [])
|
| 119 |
+
thermal_start = (result.get("metrics") or {}).get("thermal_state_start")
|
| 120 |
+
if allowed_thermal_states and thermal_start not in allowed_thermal_states:
|
| 121 |
+
errors.append(
|
| 122 |
+
"metrics.thermal_state_start must be one of "
|
| 123 |
+
+ ", ".join(sorted(allowed_thermal_states))
|
| 124 |
+
)
|
| 125 |
+
minimum_storage = requirements.get("minimum_free_storage_mb")
|
| 126 |
+
free_storage = device.get("free_storage_mb")
|
| 127 |
+
if (
|
| 128 |
+
isinstance(minimum_storage, (int, float))
|
| 129 |
+
and not (
|
| 130 |
+
isinstance(free_storage, (int, float))
|
| 131 |
+
and free_storage >= minimum_storage
|
| 132 |
+
)
|
| 133 |
+
):
|
| 134 |
+
errors.append(
|
| 135 |
+
f"device.free_storage_mb must be at least {minimum_storage}"
|
| 136 |
+
)
|
| 137 |
+
if (
|
| 138 |
+
requirements.get("apple_intelligence_required_for_system_model")
|
| 139 |
+
and (result.get("model") or {}).get("source_type") == "os_managed"
|
| 140 |
+
):
|
| 141 |
+
if device.get("apple_intelligence_enabled") is not True:
|
| 142 |
+
errors.append("Apple Intelligence must be enabled for the system-model lane")
|
| 143 |
+
if device.get("apple_intelligence_availability") != "available":
|
| 144 |
+
errors.append("the Apple system model must report available")
|
| 145 |
|
| 146 |
for dotted_path in profile.get("required_metadata") or []:
|
| 147 |
if deep_get(result, dotted_path) is None:
|