Spaces:
Running
Running
A5-R3-R3A dormant dual-path snapshot identity
#110
by GuXiaopeng - opened
- core/generation_runner.py +93 -0
- managed_auth.py +14 -12
- task_executor.py +113 -0
core/generation_runner.py
CHANGED
|
@@ -221,6 +221,7 @@ class GenerationRunner:
|
|
| 221 |
executor_instance_id: str = "",
|
| 222 |
confirmed_checkpoint_seq: int | None = None,
|
| 223 |
confirmed_checkpoint_stage: str = "",
|
|
|
|
| 224 |
progress_callback: ProgressCallback | None = None,
|
| 225 |
cancel_checker: Callable[[], bool] | None = None,
|
| 226 |
):
|
|
@@ -232,6 +233,9 @@ class GenerationRunner:
|
|
| 232 |
None if confirmed_checkpoint_seq is None else max(0, int(confirmed_checkpoint_seq))
|
| 233 |
)
|
| 234 |
self.confirmed_checkpoint_stage = str(confirmed_checkpoint_stage or "")[:120]
|
|
|
|
|
|
|
|
|
|
| 235 |
self.progress_callback = progress_callback or (lambda **_: None)
|
| 236 |
self.cancel_checker = cancel_checker or (lambda: False)
|
| 237 |
expected_hash = str(self.request.get("request_hash") or "")
|
|
@@ -2809,6 +2813,87 @@ class GenerationRunner:
|
|
| 2809 |
output.append(str(path))
|
| 2810 |
return output
|
| 2811 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2812 |
def _run_impl(self) -> dict[str, Any]:
|
| 2813 |
req = self.request
|
| 2814 |
mode = str(req.get("mode") or "").lower()
|
|
@@ -2817,6 +2902,9 @@ class GenerationRunner:
|
|
| 2817 |
target_words = int(req.get("target_words") or 0)
|
| 2818 |
if not APP_CONFIG["target_words_min"] <= target_words <= APP_CONFIG["target_words_max"]:
|
| 2819 |
raise RuntimeError("target_words_out_of_range")
|
|
|
|
|
|
|
|
|
|
| 2820 |
|
| 2821 |
# A2: provider credentials are adapter-owned. DeepSeek remains the
|
| 2822 |
# current default adapter, but the runner no longer hard-codes it as the
|
|
@@ -2851,6 +2939,11 @@ class GenerationRunner:
|
|
| 2851 |
quality_diagnostics = list(state.get("quality_diagnostics") or [])
|
| 2852 |
quality_notes = list(state.get("quality_notes") or [])
|
| 2853 |
state.setdefault("plan_policy_snapshot", copy.deepcopy(plan_policy_snapshot))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2854 |
self._evidence_coverage_events = list(state.get("evidence_coverage_events") or [])
|
| 2855 |
if str(state.get("evidence_status") or "") == "limited":
|
| 2856 |
self._preview_evidence_status = "limited"
|
|
|
|
| 221 |
executor_instance_id: str = "",
|
| 222 |
confirmed_checkpoint_seq: int | None = None,
|
| 223 |
confirmed_checkpoint_stage: str = "",
|
| 224 |
+
trusted_task_policy_snapshot: dict[str, Any] | None = None,
|
| 225 |
progress_callback: ProgressCallback | None = None,
|
| 226 |
cancel_checker: Callable[[], bool] | None = None,
|
| 227 |
):
|
|
|
|
| 233 |
None if confirmed_checkpoint_seq is None else max(0, int(confirmed_checkpoint_seq))
|
| 234 |
)
|
| 235 |
self.confirmed_checkpoint_stage = str(confirmed_checkpoint_stage or "")[:120]
|
| 236 |
+
self.trusted_task_policy_snapshot = copy.deepcopy(
|
| 237 |
+
dict(trusted_task_policy_snapshot or {})
|
| 238 |
+
)
|
| 239 |
self.progress_callback = progress_callback or (lambda **_: None)
|
| 240 |
self.cancel_checker = cancel_checker or (lambda: False)
|
| 241 |
expected_hash = str(self.request.get("request_hash") or "")
|
|
|
|
| 2813 |
output.append(str(path))
|
| 2814 |
return output
|
| 2815 |
|
| 2816 |
+
def _validate_trusted_task_policy_for_execution(self, mode: str, target_words: int) -> dict[str, Any] | None:
|
| 2817 |
+
snapshot = copy.deepcopy(self.trusted_task_policy_snapshot)
|
| 2818 |
+
if not snapshot:
|
| 2819 |
+
return None
|
| 2820 |
+
resolved = snapshot.get("resolved_policy")
|
| 2821 |
+
if not isinstance(resolved, dict):
|
| 2822 |
+
raise RuntimeError("trusted_task_policy_snapshot_invalid")
|
| 2823 |
+
|
| 2824 |
+
task_id = str(snapshot.get("task_id") or "").strip()
|
| 2825 |
+
request_task_id = str(self.request.get("task_id") or "").strip()
|
| 2826 |
+
if not task_id or task_id != request_task_id:
|
| 2827 |
+
raise RuntimeError("trusted_task_policy_task_mismatch")
|
| 2828 |
+
|
| 2829 |
+
tier = str(snapshot.get("product_tier") or "").strip().upper()
|
| 2830 |
+
entitlement_class = str(snapshot.get("entitlement_class") or "").strip().upper()
|
| 2831 |
+
if tier not in {"STANDARD", "FLAGSHIP"}:
|
| 2832 |
+
raise RuntimeError("trusted_task_policy_product_tier_invalid")
|
| 2833 |
+
if entitlement_class not in {"STANDARD_TRIAL", "STANDARD_PAID", "FLAGSHIP_PAID"}:
|
| 2834 |
+
raise RuntimeError("trusted_task_policy_entitlement_invalid")
|
| 2835 |
+
if tier == "STANDARD" and entitlement_class == "FLAGSHIP_PAID":
|
| 2836 |
+
raise RuntimeError("trusted_task_policy_entitlement_mismatch")
|
| 2837 |
+
if tier == "FLAGSHIP" and entitlement_class != "FLAGSHIP_PAID":
|
| 2838 |
+
raise RuntimeError("trusted_task_policy_entitlement_mismatch")
|
| 2839 |
+
if str(resolved.get("product_tier") or "").strip().upper() != tier:
|
| 2840 |
+
raise RuntimeError("trusted_task_policy_product_tier_mismatch")
|
| 2841 |
+
if str(resolved.get("snapshot_schema_version") or "") != str(snapshot.get("snapshot_schema_version") or ""):
|
| 2842 |
+
raise RuntimeError("trusted_task_policy_schema_mismatch")
|
| 2843 |
+
for field in ("product_policy_version", "word_count_policy_version", "model_policy_version", "cost_policy_version"):
|
| 2844 |
+
if str(resolved.get(field) or "") != str(snapshot.get(field) or ""):
|
| 2845 |
+
raise RuntimeError("trusted_task_policy_version_mismatch")
|
| 2846 |
+
for field in ("billing_policy_version", "trial_policy_version"):
|
| 2847 |
+
resolved_value = str(resolved.get(field) or "").strip() or None
|
| 2848 |
+
snapshot_value = str(snapshot.get(field) or "").strip() or None
|
| 2849 |
+
if resolved_value != snapshot_value:
|
| 2850 |
+
raise RuntimeError("trusted_task_policy_version_mismatch")
|
| 2851 |
+
if str(resolved.get("manuscript_mode") or "").strip().lower() != mode:
|
| 2852 |
+
raise RuntimeError("trusted_task_policy_mode_mismatch")
|
| 2853 |
+
minimum = int(snapshot.get("min_body_words") or 0)
|
| 2854 |
+
maximum = int(snapshot.get("max_body_words") or 0)
|
| 2855 |
+
if minimum <= 0 or maximum < minimum or not minimum <= target_words <= maximum:
|
| 2856 |
+
raise RuntimeError("trusted_task_policy_word_range_mismatch")
|
| 2857 |
+
word_count = resolved.get("word_count") if isinstance(resolved.get("word_count"), dict) else {}
|
| 2858 |
+
if (
|
| 2859 |
+
int(word_count.get("min_body_words") or 0) != minimum
|
| 2860 |
+
or int(word_count.get("max_body_words") or 0) != maximum
|
| 2861 |
+
or str(word_count.get("counting_contract_version") or "") != str(snapshot.get("counting_contract_version") or "")
|
| 2862 |
+
):
|
| 2863 |
+
raise RuntimeError("trusted_task_policy_word_policy_mismatch")
|
| 2864 |
+
|
| 2865 |
+
envelope = {
|
| 2866 |
+
"task_id": task_id,
|
| 2867 |
+
"snapshot_schema_version": str(snapshot.get("snapshot_schema_version") or ""),
|
| 2868 |
+
"product_tier": str(snapshot.get("product_tier") or ""),
|
| 2869 |
+
"product_policy_version": str(snapshot.get("product_policy_version") or ""),
|
| 2870 |
+
"word_count_policy_version": str(snapshot.get("word_count_policy_version") or ""),
|
| 2871 |
+
"model_policy_version": str(snapshot.get("model_policy_version") or ""),
|
| 2872 |
+
"cost_policy_version": str(snapshot.get("cost_policy_version") or ""),
|
| 2873 |
+
"billing_policy_version": str(snapshot.get("billing_policy_version") or "").strip() or None,
|
| 2874 |
+
"trial_policy_version": str(snapshot.get("trial_policy_version") or "").strip() or None,
|
| 2875 |
+
"entitlement_class": str(snapshot.get("entitlement_class") or "").strip() or None,
|
| 2876 |
+
"min_body_words": minimum,
|
| 2877 |
+
"max_body_words": maximum,
|
| 2878 |
+
"counting_contract_version": str(snapshot.get("counting_contract_version") or ""),
|
| 2879 |
+
"resolved_policy": resolved,
|
| 2880 |
+
}
|
| 2881 |
+
observed_sha = hashlib.sha256(
|
| 2882 |
+
json.dumps(envelope, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
| 2883 |
+
).hexdigest()
|
| 2884 |
+
if observed_sha != str(snapshot.get("snapshot_sha256") or "").strip().lower():
|
| 2885 |
+
raise RuntimeError("trusted_task_policy_snapshot_sha_mismatch")
|
| 2886 |
+
|
| 2887 |
+
model = resolved.get("model") if isinstance(resolved.get("model"), dict) else {}
|
| 2888 |
+
routes = model.get("routes") if isinstance(model.get("routes"), dict) else {}
|
| 2889 |
+
if not routes:
|
| 2890 |
+
raise RuntimeError("trusted_task_policy_model_routes_missing")
|
| 2891 |
+
# A5-R3-R3A closes snapshot identity only. It deliberately does not
|
| 2892 |
+
# reinterpret fine-grained logical-node routes as the legacy coarse
|
| 2893 |
+
# capability roles. Product execution remains fail-closed until the
|
| 2894 |
+
# separate logical-node execution contract is implemented.
|
| 2895 |
+
raise RuntimeError("trusted_task_policy_model_route_contract_not_ready")
|
| 2896 |
+
|
| 2897 |
def _run_impl(self) -> dict[str, Any]:
|
| 2898 |
req = self.request
|
| 2899 |
mode = str(req.get("mode") or "").lower()
|
|
|
|
| 2902 |
target_words = int(req.get("target_words") or 0)
|
| 2903 |
if not APP_CONFIG["target_words_min"] <= target_words <= APP_CONFIG["target_words_max"]:
|
| 2904 |
raise RuntimeError("target_words_out_of_range")
|
| 2905 |
+
trusted_task_policy_snapshot = self._validate_trusted_task_policy_for_execution(
|
| 2906 |
+
mode, target_words
|
| 2907 |
+
)
|
| 2908 |
|
| 2909 |
# A2: provider credentials are adapter-owned. DeepSeek remains the
|
| 2910 |
# current default adapter, but the runner no longer hard-codes it as the
|
|
|
|
| 2939 |
quality_diagnostics = list(state.get("quality_diagnostics") or [])
|
| 2940 |
quality_notes = list(state.get("quality_notes") or [])
|
| 2941 |
state.setdefault("plan_policy_snapshot", copy.deepcopy(plan_policy_snapshot))
|
| 2942 |
+
if trusted_task_policy_snapshot is not None:
|
| 2943 |
+
state.setdefault(
|
| 2944 |
+
"trusted_task_policy_snapshot",
|
| 2945 |
+
copy.deepcopy(trusted_task_policy_snapshot),
|
| 2946 |
+
)
|
| 2947 |
self._evidence_coverage_events = list(state.get("evidence_coverage_events") or [])
|
| 2948 |
if str(state.get("evidence_status") or "") == "limited":
|
| 2949 |
self._preview_evidence_status = "limited"
|
managed_auth.py
CHANGED
|
@@ -342,24 +342,26 @@ def start_generation_task(
|
|
| 342 |
raise RuntimeError("idempotency_key_required")
|
| 343 |
projection = get_product_ui_projection()
|
| 344 |
normalized_tier = str(product_tier or "").strip().upper()
|
| 345 |
-
|
|
|
|
| 346 |
if normalized_tier not in projection.get("products", {}):
|
| 347 |
raise RuntimeError("product_tier_required")
|
| 348 |
-
|
| 349 |
-
# snapshot ownership is separately authorized, never fall through to the
|
| 350 |
-
# legacy quota task path.
|
| 351 |
-
raise RuntimeError("a5_product_task_path_not_authorized")
|
| 352 |
-
if normalized_tier:
|
| 353 |
raise RuntimeError("product_tier_not_available_in_legacy_mode")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 354 |
result = _edge_call(
|
| 355 |
"task_start",
|
| 356 |
normalized,
|
| 357 |
-
|
| 358 |
-
"idempotency_key": normalized,
|
| 359 |
-
"mode": str(mode or "").strip().lower(),
|
| 360 |
-
"interface_language": str(interface_language or "zh").strip(),
|
| 361 |
-
"target_words": int(target_words),
|
| 362 |
-
},
|
| 363 |
key_prefix="sp_task_start",
|
| 364 |
)
|
| 365 |
if result is None:
|
|
|
|
| 342 |
raise RuntimeError("idempotency_key_required")
|
| 343 |
projection = get_product_ui_projection()
|
| 344 |
normalized_tier = str(product_tier or "").strip().upper()
|
| 345 |
+
product_mode = projection.get("mode") == "a5_product"
|
| 346 |
+
if product_mode:
|
| 347 |
if normalized_tier not in projection.get("products", {}):
|
| 348 |
raise RuntimeError("product_tier_required")
|
| 349 |
+
elif normalized_tier:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
raise RuntimeError("product_tier_not_available_in_legacy_mode")
|
| 351 |
+
payload = {
|
| 352 |
+
"idempotency_key": normalized,
|
| 353 |
+
"mode": str(mode or "").strip().lower(),
|
| 354 |
+
"interface_language": str(interface_language or "zh").strip(),
|
| 355 |
+
"target_words": int(target_words),
|
| 356 |
+
}
|
| 357 |
+
if product_mode:
|
| 358 |
+
# Product tier is user intent only. Worker/D1 resolves entitlement and
|
| 359 |
+
# freezes the trusted TaskPolicySnapshot; browser state is never authority.
|
| 360 |
+
payload["product_tier"] = normalized_tier
|
| 361 |
result = _edge_call(
|
| 362 |
"task_start",
|
| 363 |
normalized,
|
| 364 |
+
payload,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 365 |
key_prefix="sp_task_start",
|
| 366 |
)
|
| 367 |
if result is None:
|
task_executor.py
CHANGED
|
@@ -11,6 +11,7 @@ Worker so quota is never left reserved by an unowned task.
|
|
| 11 |
from __future__ import annotations
|
| 12 |
|
| 13 |
import argparse
|
|
|
|
| 14 |
import json
|
| 15 |
import logging
|
| 16 |
import os
|
|
@@ -409,6 +410,106 @@ def _cleanup_user_cancelled_task_artifacts(task_dir: Path, request_data: dict) -
|
|
| 409 |
logging.warning("[SP_EXECUTOR] cancel_task_cleanup_error task_id=%s error=%s", task_dir.name, _safe(exc, 160))
|
| 410 |
|
| 411 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
def _load_request(task_dir: Path) -> dict:
|
| 413 |
path = task_dir / "request.json"
|
| 414 |
if not path.is_file():
|
|
@@ -441,6 +542,11 @@ def _bootstrap_claim(*, task_dir: Path, task_id: str, user_id: int, request_data
|
|
| 441 |
raise RuntimeError("executor_claim_identity_mismatch")
|
| 442 |
if int(task.get("target_words") or 0) != int(request_data.get("target_words") or 0):
|
| 443 |
raise RuntimeError("target_words_claim_mismatch")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
try:
|
| 445 |
with checkpoint_authority_lock(task_dir):
|
| 446 |
_atomic_json(
|
|
@@ -454,6 +560,12 @@ def _bootstrap_claim(*, task_dir: Path, task_id: str, user_id: int, request_data
|
|
| 454 |
"executor_instance_id": instance_id,
|
| 455 |
"worker_checkpoint_seq": int(task.get("checkpoint_seq") or 0),
|
| 456 |
"worker_checkpoint_stage": str(task.get("checkpoint_stage") or "")[:120],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 457 |
"claimed_at": datetime.now(timezone.utc).isoformat(),
|
| 458 |
},
|
| 459 |
)
|
|
@@ -569,6 +681,7 @@ def main() -> int:
|
|
| 569 |
executor_instance_id=instance_id,
|
| 570 |
confirmed_checkpoint_seq=remote_checkpoint_seq,
|
| 571 |
confirmed_checkpoint_stage=remote_checkpoint_stage,
|
|
|
|
| 572 |
progress_callback=state.touch,
|
| 573 |
cancel_checker=state.cancelled,
|
| 574 |
)
|
|
|
|
| 11 |
from __future__ import annotations
|
| 12 |
|
| 13 |
import argparse
|
| 14 |
+
import hashlib
|
| 15 |
import json
|
| 16 |
import logging
|
| 17 |
import os
|
|
|
|
| 410 |
logging.warning("[SP_EXECUTOR] cancel_task_cleanup_error task_id=%s error=%s", task_dir.name, _safe(exc, 160))
|
| 411 |
|
| 412 |
|
| 413 |
+
def _snapshot_nullable_version(value):
|
| 414 |
+
text = str(value or "").strip()
|
| 415 |
+
return text or None
|
| 416 |
+
|
| 417 |
+
|
| 418 |
+
def _trusted_task_policy_snapshot_envelope(snapshot: dict, resolved: dict) -> dict:
|
| 419 |
+
return {
|
| 420 |
+
"task_id": str(snapshot.get("task_id") or ""),
|
| 421 |
+
"snapshot_schema_version": str(snapshot.get("snapshot_schema_version") or ""),
|
| 422 |
+
"product_tier": str(snapshot.get("product_tier") or ""),
|
| 423 |
+
"product_policy_version": str(snapshot.get("product_policy_version") or ""),
|
| 424 |
+
"word_count_policy_version": str(snapshot.get("word_count_policy_version") or ""),
|
| 425 |
+
"model_policy_version": str(snapshot.get("model_policy_version") or ""),
|
| 426 |
+
"cost_policy_version": str(snapshot.get("cost_policy_version") or ""),
|
| 427 |
+
"billing_policy_version": _snapshot_nullable_version(snapshot.get("billing_policy_version")),
|
| 428 |
+
"trial_policy_version": _snapshot_nullable_version(snapshot.get("trial_policy_version")),
|
| 429 |
+
"entitlement_class": _snapshot_nullable_version(snapshot.get("entitlement_class")),
|
| 430 |
+
"min_body_words": int(snapshot.get("min_body_words") or 0),
|
| 431 |
+
"max_body_words": int(snapshot.get("max_body_words") or 0),
|
| 432 |
+
"counting_contract_version": str(snapshot.get("counting_contract_version") or ""),
|
| 433 |
+
"resolved_policy": resolved,
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
|
| 437 |
+
def _validate_trusted_task_policy_snapshot(claim: dict, task: dict, request_data: dict) -> dict | None:
|
| 438 |
+
raw = claim.get("task_policy_snapshot")
|
| 439 |
+
if raw is None:
|
| 440 |
+
return None
|
| 441 |
+
if not isinstance(raw, dict):
|
| 442 |
+
raise RuntimeError("task_policy_snapshot_invalid")
|
| 443 |
+
snapshot = dict(raw)
|
| 444 |
+
resolved = snapshot.get("resolved_policy")
|
| 445 |
+
if not isinstance(resolved, dict):
|
| 446 |
+
raise RuntimeError("task_policy_snapshot_resolved_policy_missing")
|
| 447 |
+
|
| 448 |
+
snapshot_task_id = str(snapshot.get("task_id") or "").strip()
|
| 449 |
+
claimed_task_id = str(task.get("task_id") or "").strip()
|
| 450 |
+
request_task_id = str(request_data.get("task_id") or "").strip()
|
| 451 |
+
if not snapshot_task_id or snapshot_task_id != claimed_task_id or snapshot_task_id != request_task_id:
|
| 452 |
+
raise RuntimeError("task_policy_snapshot_task_mismatch")
|
| 453 |
+
|
| 454 |
+
tier = str(snapshot.get("product_tier") or "").strip().upper()
|
| 455 |
+
entitlement_class = str(snapshot.get("entitlement_class") or "").strip().upper()
|
| 456 |
+
if tier not in {"STANDARD", "FLAGSHIP"}:
|
| 457 |
+
raise RuntimeError("task_policy_snapshot_product_tier_invalid")
|
| 458 |
+
if entitlement_class not in {"STANDARD_TRIAL", "STANDARD_PAID", "FLAGSHIP_PAID"}:
|
| 459 |
+
raise RuntimeError("task_policy_snapshot_entitlement_invalid")
|
| 460 |
+
if tier == "STANDARD" and entitlement_class == "FLAGSHIP_PAID":
|
| 461 |
+
raise RuntimeError("task_policy_snapshot_entitlement_mismatch")
|
| 462 |
+
if tier == "FLAGSHIP" and entitlement_class != "FLAGSHIP_PAID":
|
| 463 |
+
raise RuntimeError("task_policy_snapshot_entitlement_mismatch")
|
| 464 |
+
|
| 465 |
+
if str(resolved.get("snapshot_schema_version") or "") != str(snapshot.get("snapshot_schema_version") or ""):
|
| 466 |
+
raise RuntimeError("task_policy_snapshot_schema_mismatch")
|
| 467 |
+
if str(resolved.get("product_tier") or "").strip().upper() != tier:
|
| 468 |
+
raise RuntimeError("task_policy_snapshot_product_tier_mismatch")
|
| 469 |
+
version_fields = (
|
| 470 |
+
"product_policy_version",
|
| 471 |
+
"word_count_policy_version",
|
| 472 |
+
"model_policy_version",
|
| 473 |
+
"cost_policy_version",
|
| 474 |
+
)
|
| 475 |
+
for field in version_fields:
|
| 476 |
+
if str(resolved.get(field) or "") != str(snapshot.get(field) or ""):
|
| 477 |
+
raise RuntimeError("task_policy_snapshot_policy_version_mismatch")
|
| 478 |
+
for field in ("billing_policy_version", "trial_policy_version"):
|
| 479 |
+
if _snapshot_nullable_version(resolved.get(field)) != _snapshot_nullable_version(snapshot.get(field)):
|
| 480 |
+
raise RuntimeError("task_policy_snapshot_policy_version_mismatch")
|
| 481 |
+
|
| 482 |
+
if str(resolved.get("manuscript_mode") or "").strip().lower() != str(task.get("mode") or "").strip().lower():
|
| 483 |
+
raise RuntimeError("task_policy_snapshot_mode_mismatch")
|
| 484 |
+
target_words = int(task.get("target_words") or 0)
|
| 485 |
+
if target_words != int(request_data.get("target_words") or 0):
|
| 486 |
+
raise RuntimeError("target_words_claim_mismatch")
|
| 487 |
+
minimum = int(snapshot.get("min_body_words") or 0)
|
| 488 |
+
maximum = int(snapshot.get("max_body_words") or 0)
|
| 489 |
+
if minimum <= 0 or maximum < minimum or not minimum <= target_words <= maximum:
|
| 490 |
+
raise RuntimeError("task_policy_snapshot_word_range_mismatch")
|
| 491 |
+
word_count = resolved.get("word_count") if isinstance(resolved.get("word_count"), dict) else {}
|
| 492 |
+
if (
|
| 493 |
+
int(word_count.get("min_body_words") or 0) != minimum
|
| 494 |
+
or int(word_count.get("max_body_words") or 0) != maximum
|
| 495 |
+
or str(word_count.get("counting_contract_version") or "") != str(snapshot.get("counting_contract_version") or "")
|
| 496 |
+
):
|
| 497 |
+
raise RuntimeError("task_policy_snapshot_word_policy_mismatch")
|
| 498 |
+
|
| 499 |
+
observed = hashlib.sha256(
|
| 500 |
+
json.dumps(
|
| 501 |
+
_trusted_task_policy_snapshot_envelope(snapshot, resolved),
|
| 502 |
+
ensure_ascii=False,
|
| 503 |
+
sort_keys=True,
|
| 504 |
+
separators=(",", ":"),
|
| 505 |
+
).encode("utf-8")
|
| 506 |
+
).hexdigest()
|
| 507 |
+
expected = str(snapshot.get("snapshot_sha256") or "").strip().lower()
|
| 508 |
+
if not re.fullmatch(r"[a-f0-9]{64}", expected) or observed != expected:
|
| 509 |
+
raise RuntimeError("task_policy_snapshot_sha_mismatch")
|
| 510 |
+
return snapshot
|
| 511 |
+
|
| 512 |
+
|
| 513 |
def _load_request(task_dir: Path) -> dict:
|
| 514 |
path = task_dir / "request.json"
|
| 515 |
if not path.is_file():
|
|
|
|
| 542 |
raise RuntimeError("executor_claim_identity_mismatch")
|
| 543 |
if int(task.get("target_words") or 0) != int(request_data.get("target_words") or 0):
|
| 544 |
raise RuntimeError("target_words_claim_mismatch")
|
| 545 |
+
trusted_task_policy_snapshot = _validate_trusted_task_policy_snapshot(
|
| 546 |
+
claim, task, request_data
|
| 547 |
+
)
|
| 548 |
+
if trusted_task_policy_snapshot is not None:
|
| 549 |
+
task["_trusted_task_policy_snapshot"] = trusted_task_policy_snapshot
|
| 550 |
try:
|
| 551 |
with checkpoint_authority_lock(task_dir):
|
| 552 |
_atomic_json(
|
|
|
|
| 560 |
"executor_instance_id": instance_id,
|
| 561 |
"worker_checkpoint_seq": int(task.get("checkpoint_seq") or 0),
|
| 562 |
"worker_checkpoint_stage": str(task.get("checkpoint_stage") or "")[:120],
|
| 563 |
+
"task_policy_snapshot_sha256": str(
|
| 564 |
+
(trusted_task_policy_snapshot or {}).get("snapshot_sha256") or ""
|
| 565 |
+
),
|
| 566 |
+
"task_policy_product_tier": str(
|
| 567 |
+
(trusted_task_policy_snapshot or {}).get("product_tier") or ""
|
| 568 |
+
),
|
| 569 |
"claimed_at": datetime.now(timezone.utc).isoformat(),
|
| 570 |
},
|
| 571 |
)
|
|
|
|
| 681 |
executor_instance_id=instance_id,
|
| 682 |
confirmed_checkpoint_seq=remote_checkpoint_seq,
|
| 683 |
confirmed_checkpoint_stage=remote_checkpoint_stage,
|
| 684 |
+
trusted_task_policy_snapshot=task.get("_trusted_task_policy_snapshot"),
|
| 685 |
progress_callback=state.touch,
|
| 686 |
cancel_checker=state.cancelled,
|
| 687 |
)
|