blun-king-cli 9.1.597 → 9.1.600
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +17 -1
- package/agent-spine-plugin/CHANGELOG.md +1 -1
- package/agent-spine-plugin/docs/host-integration.md +1 -15
- package/agent-spine-plugin/docs/preflight-recall.md +1 -1
- package/agent-spine-plugin/scripts/check-install.js +1 -6
- package/agent-spine-plugin/scripts/hermetic-process.js +8 -0
- package/agent-spine-plugin/scripts/release-check.js +2 -3
- package/agent-spine-plugin/scripts/run-tests-hermetic.js +8 -11
- package/agent-spine-plugin/src/hook.js +40 -40
- package/agent-spine-plugin/src/lib/briefing.js +6 -3
- package/agent-spine-plugin/src/lib/hook-context.js +63 -64
- package/agent-spine-plugin/src/lib/hook-output.js +115 -94
- package/agent-spine-plugin/src/lib/hook-timeline.js +20 -11
- package/agent-spine-plugin/src/lib/host-instruction-budget.js +8 -14
- package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +0 -7
- package/agent-spine-plugin/src/lib/pre-answer-timeline-recall.js +104 -0
- package/agent-spine-plugin/src/lib/session-timeline-codex.js +0 -4
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-source.js +0 -3
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-storage.js +0 -4
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-transport.js +0 -2
- package/agent-spine-plugin/src/lib/session-timeline-enrollment.js +0 -22
- package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +0 -4
- package/agent-spine-plugin/src/lib/session-timeline-prior.js +42 -50
- package/agent-spine-plugin/src/lib/session-timeline-provider.js +0 -3
- package/agent-spine-plugin/src/lib/session-timeline-query.js +0 -1
- package/agent-spine-plugin/src/lib/session-timeline-sid-acl.js +0 -4
- package/agent-spine-plugin/src/lib/session-timeline-source.js +0 -3
- package/agent-spine-plugin/src/lib/session-timeline-transport.js +0 -8
- package/agent-spine-plugin/src/lib/session-timeline-windows-acl.js +0 -3
- package/agent-spine-plugin/src/lib/session-timeline.js +370 -408
- package/agent-spine-plugin/src/lib/source-roots.js +26 -16
- package/agent-spine-plugin/src/lib/timeline-user-feedback.js +0 -1
- package/bin/core-bootstrap.js +18 -10
- package/bin/launcher-mode.js +5 -0
- package/bin/launcher-runtime.js +27 -0
- package/bin/verify-bundled-agent-sources.cjs +28 -2
- package/blun.mjs +798 -143
- package/bundled-agent-sources.json +192 -155
- package/package.json +1 -1
- package/standard-skills/translate-native/README.md +1334 -1
- package/standard-skills/translate-native/SKILL.md +1 -1
- package/standard-skills/translate-native/VERSION +1 -1
- package/standard-skills/translate-native/docs/PREMORTEM.md +901 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +208 -41
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1319 -77
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +66 -11
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +19 -1
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +24 -6
- package/standard-skills/translate-native/integrations/commercial_localization_profile.py +23 -0
- package/standard-skills/translate-native/integrations/website_localization.py +234 -10
- package/standard-skills/translate-native/integrations/website_localization_benchmark.py +39 -3
- package/standard-skills/translate-native/integrations/website_localization_cms.py +512 -10
- package/standard-skills/translate-native/integrations/website_localization_cms_client.py +116 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +101 -11
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +12 -1
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +186 -24
- package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +64 -1
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +528 -5
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_auth.py +918 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_auth_runtime.py +609 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_client.py +885 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_http.py +1244 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +220 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_sidecar_adapter.py +331 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_capabilities_http.py +444 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_client.py +673 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch.py +1317 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_client.py +826 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_http.py +1152 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_openapi.py +896 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_runtime.py +621 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_http.py +1180 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_runtime.py +1479 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +133 -17
- package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +319 -4
- package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +72 -2
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +13 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +56 -13
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_openapi.py +335 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +66 -1
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +73 -7
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +93 -9
- package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +221 -11
- package/standard-skills/translate-native/integrations/website_localization_health.py +6 -0
- package/standard-skills/translate-native/integrations/website_localization_http_provider.py +1 -1
- package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +350 -0
- package/standard-skills/translate-native/integrations/website_localization_queue.py +126 -56
- package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +166 -13
- package/standard-skills/translate-native/integrations/website_localization_release.py +423 -17
- package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +168 -13
- package/standard-skills/translate-native/integrations/website_localization_runner.py +10 -0
- package/standard-skills/translate-native/integrations/website_localization_worker.py +213 -9
- package/standard-skills/translate-native/provenance.json +2 -2
- package/standard-skills/translate-native/references/commercial-localization.md +96 -17
- package/standard-skills/translate-native/scripts/blun_language_guard.py +3 -1
- package/standard-skills/translate-native/scripts/check_commercial_review.py +69 -9
- package/standard-skills/translate-native/scripts/commercial_localization_profile.py +829 -31
- package/standard-tools/language-guard/VERSION +1 -1
- package/standard-tools/language-guard/blun_language_guard.py +3 -1
- package/standard-tools/language-guard/check_commercial_review.py +69 -9
- package/standard-tools/language-guard/commercial_localization_profile.py +829 -31
- package/standard-tools/language-guard/provenance.json +2 -2
- package/standard-tools/manifest.json +1 -1
- package/worker-host.mjs +215 -82
- package/agent-spine-plugin/scripts/check-install-king.js +0 -37
package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py
CHANGED
|
@@ -19,13 +19,14 @@ from typing import Any, Callable, Mapping, Protocol
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
SCHEMA = "blun.website-localization-release-coordinator.v1"
|
|
22
|
-
EVIDENCE_REQUEST_SCHEMA = "blun.localization-quality-evidence-request.
|
|
22
|
+
EVIDENCE_REQUEST_SCHEMA = "blun.localization-quality-evidence-request.v14"
|
|
23
23
|
EVIDENCE_RESPONSE_SCHEMA = "blun.localization-quality-evidence-response.v2"
|
|
24
24
|
INDEPENDENT_MODEL_REVIEW_SCHEMA = "blun.independent-model-review.v1"
|
|
25
25
|
EVIDENCE_STATE_SCHEMA = "blun.localization-quality-evidence-state.v1"
|
|
26
26
|
TOKEN = re.compile(r"^[A-Za-z0-9_.:-]{1,256}$")
|
|
27
27
|
ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
|
|
28
28
|
SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
|
29
|
+
REQUEST_ID = re.compile(r"^blun-l10n-evidence-[0-9a-f]{64}$")
|
|
29
30
|
MAX_RECEIPT_LENGTH = 16_384
|
|
30
31
|
MAX_ATTEMPTS = 20
|
|
31
32
|
MAX_LEASE_SECONDS = 3_600
|
|
@@ -36,6 +37,18 @@ _EVIDENCE_COLUMNS = (
|
|
|
36
37
|
"next_attempt_at", "lease_owner", "lease_token", "lease_expires_at",
|
|
37
38
|
"last_error_code", "created_at", "updated_at",
|
|
38
39
|
)
|
|
40
|
+
EVIDENCE_REQUEST_IDENTITY_FIELDS = (
|
|
41
|
+
"schema", "evidence_revision", "event_id", "plan_id", "job_id",
|
|
42
|
+
"result_sha256", "source_sha256", "target_sha256", "source_locale",
|
|
43
|
+
"target_locale", "content_type", "glossary_version", "policy_version",
|
|
44
|
+
"provider", "software_version", "review_confidence", "quality_profile",
|
|
45
|
+
"commercial_profile", "commercial_review", "commercial_review_routing",
|
|
46
|
+
"commercial_review_routing_contract_sha256",
|
|
47
|
+
"commercial_review_routing_contract",
|
|
48
|
+
"commercial_review_resolution_contract_sha256",
|
|
49
|
+
"commercial_review_resolution_contract", "human_review_required",
|
|
50
|
+
"independent_review_required",
|
|
51
|
+
)
|
|
39
52
|
|
|
40
53
|
|
|
41
54
|
def _load_module(name: str, path: Path):
|
|
@@ -137,9 +150,14 @@ class QualityEvidenceRequest:
|
|
|
137
150
|
source_text: str
|
|
138
151
|
target_text: str
|
|
139
152
|
review_confidence: dict[str, str]
|
|
140
|
-
quality_profile: dict[str,
|
|
153
|
+
quality_profile: dict[str, Any]
|
|
141
154
|
commercial_profile: str | None
|
|
142
155
|
commercial_review: dict[str, Any] | None
|
|
156
|
+
commercial_review_routing: dict[str, Any] | None
|
|
157
|
+
commercial_review_routing_contract_sha256: str | None
|
|
158
|
+
commercial_review_routing_contract: dict[str, Any] | None
|
|
159
|
+
commercial_review_resolution_contract_sha256: str | None
|
|
160
|
+
commercial_review_resolution_contract: dict[str, Any] | None
|
|
143
161
|
human_review_required: bool
|
|
144
162
|
independent_review_required: bool
|
|
145
163
|
|
|
@@ -213,6 +231,107 @@ def _hash(value: str) -> str:
|
|
|
213
231
|
return hashlib.sha256(value.encode("utf-8")).hexdigest()
|
|
214
232
|
|
|
215
233
|
|
|
234
|
+
def _request_id_for_payload(payload: dict[str, Any]) -> str:
|
|
235
|
+
identity = {
|
|
236
|
+
field: payload[field]
|
|
237
|
+
for field in EVIDENCE_REQUEST_IDENTITY_FIELDS
|
|
238
|
+
}
|
|
239
|
+
return "blun-l10n-evidence-" + _hash(_canonical_json(identity))
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def _validated_request_payload(request: Any) -> dict[str, Any]:
|
|
243
|
+
if not isinstance(request, QualityEvidenceRequest):
|
|
244
|
+
raise LocalizationReleaseCoordinatorBlocked("evidence.request.invalid")
|
|
245
|
+
try:
|
|
246
|
+
payload = request.as_payload()
|
|
247
|
+
except Exception:
|
|
248
|
+
raise LocalizationReleaseCoordinatorBlocked("evidence.request.invalid") from None
|
|
249
|
+
if (
|
|
250
|
+
not isinstance(payload, dict)
|
|
251
|
+
or set(payload) != set(EVIDENCE_REQUEST_IDENTITY_FIELDS) | {
|
|
252
|
+
"request_id", "source_text", "target_text",
|
|
253
|
+
}
|
|
254
|
+
or payload.get("schema") != EVIDENCE_REQUEST_SCHEMA
|
|
255
|
+
or payload.get("request_id") != request.request_id
|
|
256
|
+
or not isinstance(request.request_id, str)
|
|
257
|
+
or REQUEST_ID.fullmatch(request.request_id) is None
|
|
258
|
+
or not isinstance(payload.get("source_text"), str)
|
|
259
|
+
or not isinstance(payload.get("target_text"), str)
|
|
260
|
+
or not isinstance(payload.get("source_sha256"), str)
|
|
261
|
+
or not isinstance(payload.get("target_sha256"), str)
|
|
262
|
+
or SHA256.fullmatch(payload["source_sha256"]) is None
|
|
263
|
+
or SHA256.fullmatch(payload["target_sha256"]) is None
|
|
264
|
+
or _hash(payload["source_text"]) != payload["source_sha256"]
|
|
265
|
+
or _hash(payload["target_text"]) != payload["target_sha256"]
|
|
266
|
+
):
|
|
267
|
+
raise LocalizationReleaseCoordinatorBlocked("evidence.request.invalid")
|
|
268
|
+
if request.request_id != _request_id_for_payload(payload):
|
|
269
|
+
raise LocalizationReleaseCoordinatorBlocked(
|
|
270
|
+
"evidence.request_id.binding_mismatch",
|
|
271
|
+
)
|
|
272
|
+
commercial_review = payload["commercial_review"]
|
|
273
|
+
commercial_profile = payload["commercial_profile"]
|
|
274
|
+
try:
|
|
275
|
+
current_routing_contract = (
|
|
276
|
+
_CMS._COMMERCIAL.public_review_routing_contract(
|
|
277
|
+
commercial_profile,
|
|
278
|
+
)
|
|
279
|
+
if isinstance(commercial_profile, str)
|
|
280
|
+
and isinstance(commercial_review, dict)
|
|
281
|
+
else None
|
|
282
|
+
)
|
|
283
|
+
expected_routing_contract_sha256 = (
|
|
284
|
+
current_routing_contract["sha256"]
|
|
285
|
+
if current_routing_contract is not None
|
|
286
|
+
else None
|
|
287
|
+
)
|
|
288
|
+
except (KeyError, TypeError, ValueError):
|
|
289
|
+
raise LocalizationReleaseCoordinatorBlocked(
|
|
290
|
+
"evidence.request.invalid",
|
|
291
|
+
) from None
|
|
292
|
+
expected_routing_contract = (
|
|
293
|
+
current_routing_contract
|
|
294
|
+
if isinstance(commercial_review, dict)
|
|
295
|
+
and commercial_review.get("status") == "review_required"
|
|
296
|
+
else None
|
|
297
|
+
)
|
|
298
|
+
if (
|
|
299
|
+
payload["commercial_review_routing_contract_sha256"]
|
|
300
|
+
!= expected_routing_contract_sha256
|
|
301
|
+
or payload["commercial_review_routing_contract"]
|
|
302
|
+
!= expected_routing_contract
|
|
303
|
+
or (
|
|
304
|
+
payload["commercial_review_routing"] is None
|
|
305
|
+
) != (expected_routing_contract is None)
|
|
306
|
+
):
|
|
307
|
+
raise LocalizationReleaseCoordinatorBlocked("evidence.request.invalid")
|
|
308
|
+
try:
|
|
309
|
+
expected_resolution_contract = (
|
|
310
|
+
_CMS._COMMERCIAL.public_review_resolution_contract(
|
|
311
|
+
commercial_profile,
|
|
312
|
+
)
|
|
313
|
+
if isinstance(commercial_review, dict)
|
|
314
|
+
and commercial_review.get("status") == "review_required"
|
|
315
|
+
else None
|
|
316
|
+
)
|
|
317
|
+
except (KeyError, TypeError, ValueError):
|
|
318
|
+
raise LocalizationReleaseCoordinatorBlocked(
|
|
319
|
+
"evidence.request.invalid",
|
|
320
|
+
) from None
|
|
321
|
+
if (
|
|
322
|
+
payload["commercial_review_resolution_contract"]
|
|
323
|
+
!= expected_resolution_contract
|
|
324
|
+
or payload["commercial_review_resolution_contract_sha256"]
|
|
325
|
+
!= (
|
|
326
|
+
expected_resolution_contract["sha256"]
|
|
327
|
+
if expected_resolution_contract is not None
|
|
328
|
+
else None
|
|
329
|
+
)
|
|
330
|
+
):
|
|
331
|
+
raise LocalizationReleaseCoordinatorBlocked("evidence.request.invalid")
|
|
332
|
+
return payload
|
|
333
|
+
|
|
334
|
+
|
|
216
335
|
def _token(value: Any, code: str) -> str:
|
|
217
336
|
if not isinstance(value, str) or TOKEN.fullmatch(value) is None:
|
|
218
337
|
raise LocalizationReleaseCoordinatorBlocked(code)
|
|
@@ -309,15 +428,17 @@ class QualityEvidenceStateStore:
|
|
|
309
428
|
|
|
310
429
|
@staticmethod
|
|
311
430
|
def _binding(request: QualityEvidenceRequest) -> tuple[str, ...]:
|
|
312
|
-
|
|
313
|
-
raise LocalizationReleaseCoordinatorBlocked("evidence.request.invalid")
|
|
431
|
+
payload = _validated_request_payload(request)
|
|
314
432
|
values = (
|
|
315
|
-
|
|
316
|
-
_token(
|
|
317
|
-
_token(
|
|
318
|
-
_token(
|
|
319
|
-
|
|
320
|
-
_token(
|
|
433
|
+
payload["request_id"],
|
|
434
|
+
_token(payload["event_id"], "coordinator.event_id.invalid"),
|
|
435
|
+
_token(payload["plan_id"], "evidence.plan_id.invalid"),
|
|
436
|
+
_token(payload["job_id"], "evidence.job_id.invalid"),
|
|
437
|
+
payload["result_sha256"],
|
|
438
|
+
_token(
|
|
439
|
+
payload["evidence_revision"],
|
|
440
|
+
"coordinator.evidence_revision.invalid",
|
|
441
|
+
),
|
|
321
442
|
)
|
|
322
443
|
if not isinstance(values[4], str) or SHA256.fullmatch(values[4]) is None:
|
|
323
444
|
raise LocalizationReleaseCoordinatorBlocked("evidence.result_sha256.invalid")
|
|
@@ -656,6 +777,25 @@ def _request(
|
|
|
656
777
|
result_sha256: str,
|
|
657
778
|
evidence_revision: str,
|
|
658
779
|
) -> QualityEvidenceRequest:
|
|
780
|
+
commercial_profile = job.as_payload().get("commercial_profile")
|
|
781
|
+
commercial_review = json.loads(_canonical_json(result["commercial_review"]))
|
|
782
|
+
commercial_review_routing = json.loads(_canonical_json(
|
|
783
|
+
result["commercial_review_routing"],
|
|
784
|
+
))
|
|
785
|
+
routing_contract = (
|
|
786
|
+
_CMS._COMMERCIAL.public_review_routing_contract(commercial_profile)
|
|
787
|
+
if commercial_profile is not None
|
|
788
|
+
and commercial_review["status"] == "review_required"
|
|
789
|
+
else None
|
|
790
|
+
)
|
|
791
|
+
resolution_contract = (
|
|
792
|
+
_CMS._COMMERCIAL.public_review_resolution_contract(
|
|
793
|
+
commercial_profile,
|
|
794
|
+
)
|
|
795
|
+
if commercial_profile is not None
|
|
796
|
+
and commercial_review["status"] == "review_required"
|
|
797
|
+
else None
|
|
798
|
+
)
|
|
659
799
|
binding = {
|
|
660
800
|
"schema": EVIDENCE_REQUEST_SCHEMA,
|
|
661
801
|
"evidence_revision": evidence_revision,
|
|
@@ -674,12 +814,24 @@ def _request(
|
|
|
674
814
|
"software_version": result["software_version"],
|
|
675
815
|
"review_confidence": json.loads(_canonical_json(result["review_confidence"])),
|
|
676
816
|
"quality_profile": json.loads(_canonical_json(result["quality_profile"])),
|
|
677
|
-
"commercial_profile":
|
|
678
|
-
"commercial_review":
|
|
817
|
+
"commercial_profile": commercial_profile,
|
|
818
|
+
"commercial_review": commercial_review,
|
|
819
|
+
"commercial_review_routing": commercial_review_routing,
|
|
820
|
+
"commercial_review_routing_contract_sha256": result[
|
|
821
|
+
"commercial_review_routing_contract_sha256"
|
|
822
|
+
],
|
|
823
|
+
"commercial_review_routing_contract": routing_contract,
|
|
824
|
+
"commercial_review_resolution_contract_sha256": (
|
|
825
|
+
result["commercial_review_resolution_contract_sha256"]
|
|
826
|
+
if commercial_review is not None
|
|
827
|
+
and commercial_review["status"] == "review_required"
|
|
828
|
+
else None
|
|
829
|
+
),
|
|
830
|
+
"commercial_review_resolution_contract": resolution_contract,
|
|
679
831
|
"human_review_required": result["human_review_required"],
|
|
680
832
|
"independent_review_required": result["independent_review_required"],
|
|
681
833
|
}
|
|
682
|
-
request_id =
|
|
834
|
+
request_id = _request_id_for_payload(binding)
|
|
683
835
|
return QualityEvidenceRequest(
|
|
684
836
|
**binding,
|
|
685
837
|
request_id=request_id,
|
|
@@ -692,6 +844,7 @@ def _obtain_evidence(
|
|
|
692
844
|
provider: Any,
|
|
693
845
|
request: QualityEvidenceRequest,
|
|
694
846
|
) -> tuple[str, str | None, dict[str, Any] | None]:
|
|
847
|
+
_validated_request_payload(request)
|
|
695
848
|
obtain = getattr(provider, "obtain", None)
|
|
696
849
|
if not callable(obtain):
|
|
697
850
|
raise LocalizationReleaseCoordinatorBlocked("evidence.provider.invalid")
|
|
@@ -949,6 +1102,8 @@ def run_next_release(
|
|
|
949
1102
|
quality_receipt,
|
|
950
1103
|
guarded_quality_verifier,
|
|
951
1104
|
approval_authority,
|
|
1105
|
+
evidence_request_id=request.request_id,
|
|
1106
|
+
evidence_revision=request.evidence_revision,
|
|
952
1107
|
now=approval_now,
|
|
953
1108
|
ttl_seconds=approval_ttl_seconds,
|
|
954
1109
|
human_review_receipt=human_receipt,
|
|
@@ -136,6 +136,15 @@ def _retry_delay(attempt: int, base: float, maximum: float) -> float:
|
|
|
136
136
|
return min(maximum, base * (2 ** min(attempt - 1, 30)))
|
|
137
137
|
|
|
138
138
|
|
|
139
|
+
def _current_job_binding(payload: dict[str, Any]) -> bool:
|
|
140
|
+
"""Return False only for an expected current-worker binding rejection."""
|
|
141
|
+
try:
|
|
142
|
+
_WORKER._validated_job(payload)
|
|
143
|
+
except _WORKER.LocalizationWorkerBlocked:
|
|
144
|
+
return False
|
|
145
|
+
return True
|
|
146
|
+
|
|
147
|
+
|
|
139
148
|
def run_next_localization_job(
|
|
140
149
|
queue: Any,
|
|
141
150
|
worker_id: str,
|
|
@@ -177,6 +186,7 @@ def run_next_localization_job(
|
|
|
177
186
|
claim_arguments = {
|
|
178
187
|
"now": _now(clock),
|
|
179
188
|
"lease_seconds": lease_seconds,
|
|
189
|
+
"binding_validator": _current_job_binding,
|
|
180
190
|
}
|
|
181
191
|
if eligible_plan_ids is not None:
|
|
182
192
|
claim_arguments["eligible_plan_ids"] = eligible_plan_ids
|
|
@@ -20,10 +20,10 @@ from pathlib import Path
|
|
|
20
20
|
from typing import Any, Callable, Mapping, Protocol
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
WORKER_SCHEMA = "blun.website-localization-worker.
|
|
23
|
+
WORKER_SCHEMA = "blun.website-localization-worker.v9"
|
|
24
24
|
CANDIDATE_SCHEMA = "blun.website-localization-candidate.v1"
|
|
25
25
|
REVIEW_SCHEMA = "blun.website-localization-review.v2"
|
|
26
|
-
RESULT_SCHEMA = "blun.website-localization-result.
|
|
26
|
+
RESULT_SCHEMA = "blun.website-localization-result.v10"
|
|
27
27
|
MAX_TEXT_BYTES = 2_000_000
|
|
28
28
|
MAX_FIELD_LENGTH = 2_000
|
|
29
29
|
ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
|
|
@@ -456,7 +456,7 @@ def _base_context(job: dict[str, Any], assets: LocalizationAssets) -> dict[str,
|
|
|
456
456
|
}
|
|
457
457
|
if any(quality_profile[name] != value for name, value in expected_quality.items()):
|
|
458
458
|
raise LocalizationWorkerBlocked("quality_profile.binding_mismatch", retryable=False)
|
|
459
|
-
|
|
459
|
+
context = {
|
|
460
460
|
"job_id": job["job_id"],
|
|
461
461
|
"target": job["target"],
|
|
462
462
|
"content_type": job["content_type"],
|
|
@@ -468,6 +468,122 @@ def _base_context(job: dict[str, Any], assets: LocalizationAssets) -> dict[str,
|
|
|
468
468
|
"protected_terms": list(assets.protected_terms),
|
|
469
469
|
"quality_profile": quality_profile,
|
|
470
470
|
}
|
|
471
|
+
if job["content_type"] == "commercial":
|
|
472
|
+
commercial_quality = _PLANNER.commercial_quality_profile_for(
|
|
473
|
+
job["target"]["locale"]
|
|
474
|
+
)
|
|
475
|
+
if job.get("commercial_quality_profile") != commercial_quality:
|
|
476
|
+
raise LocalizationWorkerBlocked(
|
|
477
|
+
"commercial_quality_profile.binding_mismatch",
|
|
478
|
+
retryable=False,
|
|
479
|
+
)
|
|
480
|
+
context["commercial_quality_profile"] = commercial_quality
|
|
481
|
+
return context
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def _commercial_review_evidence_contract(profile: str) -> dict[str, Any]:
|
|
485
|
+
"""Resolve the exact public evidence contract before any provider access."""
|
|
486
|
+
try:
|
|
487
|
+
contract = _COMMERCIAL.public_review_evidence_contract(profile)
|
|
488
|
+
public_contract = _COMMERCIAL.public_profile(profile)[
|
|
489
|
+
"review_evidence_contract"
|
|
490
|
+
]
|
|
491
|
+
if not isinstance(contract, dict) or not isinstance(
|
|
492
|
+
public_contract, dict
|
|
493
|
+
):
|
|
494
|
+
raise TypeError
|
|
495
|
+
unsigned = dict(contract)
|
|
496
|
+
digest = unsigned.pop("sha256")
|
|
497
|
+
except (KeyError, TypeError, ValueError) as error:
|
|
498
|
+
raise LocalizationWorkerBlocked(
|
|
499
|
+
"commercial_review_evidence_contract.binding_mismatch",
|
|
500
|
+
retryable=False,
|
|
501
|
+
) from error
|
|
502
|
+
if (
|
|
503
|
+
contract != public_contract
|
|
504
|
+
or contract.get("schema")
|
|
505
|
+
!= _COMMERCIAL.REVIEW_EVIDENCE_CAPABILITIES_SCHEMA
|
|
506
|
+
or contract.get("result_schema") != profile
|
|
507
|
+
or contract.get("profile") != profile
|
|
508
|
+
or not isinstance(digest, str)
|
|
509
|
+
or len(digest) != 64
|
|
510
|
+
or digest != _hash_json(unsigned)
|
|
511
|
+
):
|
|
512
|
+
raise LocalizationWorkerBlocked(
|
|
513
|
+
"commercial_review_evidence_contract.binding_mismatch",
|
|
514
|
+
retryable=False,
|
|
515
|
+
)
|
|
516
|
+
return json.loads(_canonical_json(contract))
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
def _commercial_review_routing_contract(profile: str) -> dict[str, Any]:
|
|
520
|
+
"""Resolve the exact private-routing contract before provider access."""
|
|
521
|
+
try:
|
|
522
|
+
contract = _COMMERCIAL.public_review_routing_contract(profile)
|
|
523
|
+
public_contract = _COMMERCIAL.public_profile(profile)[
|
|
524
|
+
"review_routing_contract"
|
|
525
|
+
]
|
|
526
|
+
if not isinstance(contract, dict) or not isinstance(
|
|
527
|
+
public_contract, dict
|
|
528
|
+
):
|
|
529
|
+
raise TypeError
|
|
530
|
+
unsigned = dict(contract)
|
|
531
|
+
digest = unsigned.pop("sha256")
|
|
532
|
+
except (KeyError, TypeError, ValueError) as error:
|
|
533
|
+
raise LocalizationWorkerBlocked(
|
|
534
|
+
"commercial_review_routing_contract.binding_mismatch",
|
|
535
|
+
retryable=False,
|
|
536
|
+
) from error
|
|
537
|
+
if (
|
|
538
|
+
contract != public_contract
|
|
539
|
+
or contract.get("schema")
|
|
540
|
+
!= _COMMERCIAL.REVIEW_ROUTING_CAPABILITIES_SCHEMA
|
|
541
|
+
or contract.get("result_schema") != _COMMERCIAL.REVIEW_ROUTING_SCHEMA
|
|
542
|
+
or contract.get("profile") != profile
|
|
543
|
+
or not isinstance(digest, str)
|
|
544
|
+
or len(digest) != 64
|
|
545
|
+
or digest != _hash_json(unsigned)
|
|
546
|
+
):
|
|
547
|
+
raise LocalizationWorkerBlocked(
|
|
548
|
+
"commercial_review_routing_contract.binding_mismatch",
|
|
549
|
+
retryable=False,
|
|
550
|
+
)
|
|
551
|
+
return json.loads(_canonical_json(contract))
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def _commercial_review_resolution_contract(profile: str) -> dict[str, Any]:
|
|
555
|
+
"""Resolve the exact public resolution contract before provider access."""
|
|
556
|
+
try:
|
|
557
|
+
contract = _COMMERCIAL.public_review_resolution_contract(profile)
|
|
558
|
+
public_contract = _COMMERCIAL.public_profile(profile)[
|
|
559
|
+
"review_resolution_contract"
|
|
560
|
+
]
|
|
561
|
+
if not isinstance(contract, dict) or not isinstance(
|
|
562
|
+
public_contract, dict
|
|
563
|
+
):
|
|
564
|
+
raise TypeError
|
|
565
|
+
unsigned = dict(contract)
|
|
566
|
+
digest = unsigned.pop("sha256")
|
|
567
|
+
except (KeyError, TypeError, ValueError) as error:
|
|
568
|
+
raise LocalizationWorkerBlocked(
|
|
569
|
+
"commercial_review_resolution_contract.binding_mismatch",
|
|
570
|
+
retryable=False,
|
|
571
|
+
) from error
|
|
572
|
+
if (
|
|
573
|
+
contract != public_contract
|
|
574
|
+
or contract.get("schema")
|
|
575
|
+
!= _COMMERCIAL.REVIEW_RESOLUTION_CAPABILITIES_SCHEMA
|
|
576
|
+
or contract.get("result_schema") != _COMMERCIAL.REVIEW_RESOLUTION_SCHEMA
|
|
577
|
+
or contract.get("profile") != profile
|
|
578
|
+
or not isinstance(digest, str)
|
|
579
|
+
or len(digest) != 64
|
|
580
|
+
or digest != _hash_json(unsigned)
|
|
581
|
+
):
|
|
582
|
+
raise LocalizationWorkerBlocked(
|
|
583
|
+
"commercial_review_resolution_contract.binding_mismatch",
|
|
584
|
+
retryable=False,
|
|
585
|
+
)
|
|
586
|
+
return json.loads(_canonical_json(contract))
|
|
471
587
|
|
|
472
588
|
|
|
473
589
|
def run_localization_job(
|
|
@@ -490,8 +606,44 @@ def run_localization_job(
|
|
|
490
606
|
locale = job["target"]["locale"]
|
|
491
607
|
base = _base_context(job, assets)
|
|
492
608
|
commercial = job["content_type"] == "commercial"
|
|
609
|
+
commercial_evidence_contract = None
|
|
610
|
+
commercial_routing_contract = None
|
|
611
|
+
commercial_resolution_contract = None
|
|
493
612
|
if commercial:
|
|
494
613
|
base["commercial_profile"] = job["commercial_profile"]
|
|
614
|
+
commercial_evidence_contract = _commercial_review_evidence_contract(
|
|
615
|
+
job["commercial_profile"]
|
|
616
|
+
)
|
|
617
|
+
if (
|
|
618
|
+
job["commercial_review_evidence_contract_sha256"]
|
|
619
|
+
!= commercial_evidence_contract["sha256"]
|
|
620
|
+
):
|
|
621
|
+
raise LocalizationWorkerBlocked(
|
|
622
|
+
"commercial_review_evidence_contract.binding_mismatch",
|
|
623
|
+
retryable=False,
|
|
624
|
+
)
|
|
625
|
+
commercial_routing_contract = _commercial_review_routing_contract(
|
|
626
|
+
job["commercial_profile"]
|
|
627
|
+
)
|
|
628
|
+
if (
|
|
629
|
+
job["commercial_review_routing_contract_sha256"]
|
|
630
|
+
!= commercial_routing_contract["sha256"]
|
|
631
|
+
):
|
|
632
|
+
raise LocalizationWorkerBlocked(
|
|
633
|
+
"commercial_review_routing_contract.binding_mismatch",
|
|
634
|
+
retryable=False,
|
|
635
|
+
)
|
|
636
|
+
commercial_resolution_contract = _commercial_review_resolution_contract(
|
|
637
|
+
job["commercial_profile"]
|
|
638
|
+
)
|
|
639
|
+
if (
|
|
640
|
+
job["commercial_review_resolution_contract_sha256"]
|
|
641
|
+
!= commercial_resolution_contract["sha256"]
|
|
642
|
+
):
|
|
643
|
+
raise LocalizationWorkerBlocked(
|
|
644
|
+
"commercial_review_resolution_contract.binding_mismatch",
|
|
645
|
+
retryable=False,
|
|
646
|
+
)
|
|
495
647
|
full_glossary = [asdict(term) for term in assets.glossary]
|
|
496
648
|
target_terms = [
|
|
497
649
|
{"target": term.target}
|
|
@@ -563,6 +715,15 @@ def run_localization_job(
|
|
|
563
715
|
"source": job["source"],
|
|
564
716
|
"candidate": candidate,
|
|
565
717
|
"glossary": full_glossary,
|
|
718
|
+
**(
|
|
719
|
+
{
|
|
720
|
+
"commercial_review_evidence_contract": (
|
|
721
|
+
commercial_evidence_contract
|
|
722
|
+
),
|
|
723
|
+
}
|
|
724
|
+
if commercial
|
|
725
|
+
else {}
|
|
726
|
+
),
|
|
566
727
|
"response_schema": {
|
|
567
728
|
"schema": REVIEW_SCHEMA,
|
|
568
729
|
"phase": "source_fidelity",
|
|
@@ -576,6 +737,7 @@ def run_localization_job(
|
|
|
576
737
|
})
|
|
577
738
|
fidelity_response, request_hash, response_hash = _invoke(provider, fidelity_request)
|
|
578
739
|
commercial_summary = None
|
|
740
|
+
commercial_review_routing = None
|
|
579
741
|
commercial_escalation_required = False
|
|
580
742
|
if commercial:
|
|
581
743
|
# Hash above binds the complete evidence, even though the ordinary
|
|
@@ -585,13 +747,36 @@ def run_localization_job(
|
|
|
585
747
|
try:
|
|
586
748
|
commercial_summary = _COMMERCIAL.validate_review(
|
|
587
749
|
commercial_review, job["source"]["text"], candidate,
|
|
588
|
-
job["commercial_profile"],
|
|
750
|
+
job["commercial_profile"],
|
|
751
|
+
target_locale=locale,
|
|
752
|
+
commercial_quality_profile_version=(
|
|
753
|
+
job["commercial_quality_profile"]["version"]
|
|
754
|
+
),
|
|
755
|
+
commercial_quality_profile_sha256=(
|
|
756
|
+
job["commercial_quality_profile"]["sha256"]
|
|
757
|
+
),
|
|
758
|
+
allow_uncertain=True,
|
|
589
759
|
)
|
|
590
760
|
except _COMMERCIAL.CommercialReviewBlocked as error:
|
|
591
761
|
raise LocalizationWorkerBlocked(error.code, retryable=False) from None
|
|
592
762
|
commercial_escalation_required = (
|
|
593
763
|
commercial_summary["status"] == "review_required"
|
|
594
764
|
)
|
|
765
|
+
if commercial_escalation_required:
|
|
766
|
+
try:
|
|
767
|
+
commercial_review_routing = (
|
|
768
|
+
_COMMERCIAL.review_routing_context(
|
|
769
|
+
commercial_review,
|
|
770
|
+
job["source"]["text"],
|
|
771
|
+
candidate,
|
|
772
|
+
commercial_summary,
|
|
773
|
+
job["commercial_profile"],
|
|
774
|
+
)
|
|
775
|
+
)
|
|
776
|
+
except _COMMERCIAL.CommercialReviewBlocked as error:
|
|
777
|
+
raise LocalizationWorkerBlocked(
|
|
778
|
+
error.code, retryable=False,
|
|
779
|
+
) from None
|
|
595
780
|
findings, fidelity_confidence = _review(
|
|
596
781
|
fidelity_response,
|
|
597
782
|
"source_fidelity",
|
|
@@ -625,6 +810,18 @@ def run_localization_job(
|
|
|
625
810
|
)
|
|
626
811
|
progress("integrity")
|
|
627
812
|
|
|
813
|
+
quality_result = {
|
|
814
|
+
"locale": locale,
|
|
815
|
+
"version": job["target"]["quality_profile_version"],
|
|
816
|
+
"sha256": job["target"]["quality_profile_sha256"],
|
|
817
|
+
}
|
|
818
|
+
if commercial:
|
|
819
|
+
quality_result["commercial"] = {
|
|
820
|
+
"profile": job["commercial_profile"],
|
|
821
|
+
"version": job["commercial_quality_profile"]["version"],
|
|
822
|
+
"sha256": job["commercial_quality_profile"]["sha256"],
|
|
823
|
+
}
|
|
824
|
+
|
|
628
825
|
return {
|
|
629
826
|
"schema": RESULT_SCHEMA,
|
|
630
827
|
"worker_schema": WORKER_SCHEMA,
|
|
@@ -648,12 +845,19 @@ def run_localization_job(
|
|
|
648
845
|
"target_native": native_confidence,
|
|
649
846
|
"source_fidelity": fidelity_confidence,
|
|
650
847
|
},
|
|
651
|
-
"quality_profile":
|
|
652
|
-
"locale": locale,
|
|
653
|
-
"version": job["target"]["quality_profile_version"],
|
|
654
|
-
"sha256": job["target"]["quality_profile_sha256"],
|
|
655
|
-
},
|
|
848
|
+
"quality_profile": quality_result,
|
|
656
849
|
"commercial_review": commercial_summary,
|
|
850
|
+
"commercial_review_routing": commercial_review_routing,
|
|
851
|
+
"commercial_review_routing_contract_sha256": (
|
|
852
|
+
commercial_routing_contract["sha256"]
|
|
853
|
+
if commercial_routing_contract is not None
|
|
854
|
+
else None
|
|
855
|
+
),
|
|
856
|
+
"commercial_review_resolution_contract_sha256": (
|
|
857
|
+
commercial_resolution_contract["sha256"]
|
|
858
|
+
if commercial_resolution_contract is not None
|
|
859
|
+
else None
|
|
860
|
+
),
|
|
657
861
|
"human_review_required": job["content_type"] == "legal",
|
|
658
862
|
"independent_review_required": (
|
|
659
863
|
job["content_type"] != "legal"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "translate-native",
|
|
3
|
-
"version": "6.
|
|
4
|
-
"sourceCommit": "
|
|
3
|
+
"version": "6.155.0",
|
|
4
|
+
"sourceCommit": "21efc66da8f77992c8c63ac0f145a106c31e7eb2",
|
|
5
5
|
"sourceRepository": "https://github.com/Maykbiletti/translate-native"
|
|
6
6
|
}
|