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
|
@@ -29,11 +29,13 @@ Neither credentials nor remote response prose appears in adapter errors.
|
|
|
29
29
|
## Request
|
|
30
30
|
|
|
31
31
|
The adapter accepts only the coordinator's exact immutable
|
|
32
|
-
`blun.localization-quality-evidence-request.
|
|
33
|
-
complete field set, request ID, SHA-256 values, locale
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
`blun.localization-quality-evidence-request.v14` object. It validates the
|
|
33
|
+
complete field set, derives the request ID, and checks SHA-256 values, locale
|
|
34
|
+
profile, model identity,
|
|
35
|
+
confidence decisions, and, for commercial content, the exact locale-specific
|
|
36
|
+
commercial quality-profile binding plus its content-free targeted-review
|
|
37
|
+
summary, UTF-8 size, Unicode NFC, and the source and target text hashes before
|
|
38
|
+
authentication or transport.
|
|
37
39
|
|
|
38
40
|
It sends one canonical UTF-8 JSON document:
|
|
39
41
|
|
|
@@ -43,7 +45,7 @@ It sends one canonical UTF-8 JSON document:
|
|
|
43
45
|
"request_id": "blun-l10n-evidence-<64 lowercase hexadecimal characters>",
|
|
44
46
|
"request_sha256": "<SHA-256 of the canonical inner request>",
|
|
45
47
|
"request": {
|
|
46
|
-
"schema": "blun.localization-quality-evidence-request.
|
|
48
|
+
"schema": "blun.localization-quality-evidence-request.v14",
|
|
47
49
|
"request_id": "<same request ID>",
|
|
48
50
|
"source_locale": "en-IE",
|
|
49
51
|
"target_locale": "fi-FI",
|
|
@@ -53,6 +55,11 @@ It sends one canonical UTF-8 JSON document:
|
|
|
53
55
|
"source_sha256": "<source-text hash>",
|
|
54
56
|
"target_sha256": "<target-text hash>",
|
|
55
57
|
"content_type": "headline",
|
|
58
|
+
"commercial_review_routing": null,
|
|
59
|
+
"commercial_review_routing_contract_sha256": null,
|
|
60
|
+
"commercial_review_routing_contract": null,
|
|
61
|
+
"commercial_review_resolution_contract_sha256": null,
|
|
62
|
+
"commercial_review_resolution_contract": null,
|
|
56
63
|
"quality_profile": {
|
|
57
64
|
"locale": "fi-FI",
|
|
58
65
|
"version": "<locale profile version>",
|
|
@@ -63,13 +70,57 @@ It sends one canonical UTF-8 JSON document:
|
|
|
63
70
|
```
|
|
64
71
|
|
|
65
72
|
The abbreviated example omits other required inner fields for readability.
|
|
66
|
-
Production requests always contain exactly the full
|
|
67
|
-
requests include `commercial_profile
|
|
68
|
-
summary
|
|
73
|
+
Production requests always contain exactly the full v14 field set. Commercial
|
|
74
|
+
requests include `commercial_profile`, the matching `commercial_review`
|
|
75
|
+
summary, and `quality_profile.commercial` with the same profile identifier plus
|
|
76
|
+
its exact locale-specific version and SHA-256 digest. The summary binds the
|
|
77
|
+
exact advertised commercial review-evidence-contract SHA-256, so a prior
|
|
78
|
+
structurally valid report cannot be reinterpreted under a changed contract. An unresolved commercial
|
|
79
|
+
summary additionally carries the canonical advertised resolution-contract
|
|
80
|
+
SHA-256 and the complete content-free resolution contract. Both fields are
|
|
81
|
+
part of the deterministic request ID, so a reviewer can resolve the targeted
|
|
82
|
+
uncertainty without separate capability discovery. The coordinator and HTTP
|
|
83
|
+
adapter independently reconstruct the current contract and reject a missing,
|
|
84
|
+
stale, substituted, or merely self-rehashed object before provider access.
|
|
85
|
+
Verified commercial results and non-commercial requests require both fields
|
|
86
|
+
to be `null`.
|
|
87
|
+
Every commercial request also carries
|
|
88
|
+
`commercial_review_routing_contract_sha256`, even when the commercial review
|
|
89
|
+
is already verified and no private offer route is needed. This lets the
|
|
90
|
+
evidence provider issue the receipt against the same exact public contract
|
|
91
|
+
digest that the receipt verifier, signed approval, and CMS evidence later
|
|
92
|
+
require. Non-commercial requests require this field to be `null`.
|
|
93
|
+
An unresolved commercial request also carries a private
|
|
94
|
+
`commercial_review_routing` object. It maps every zero-based opaque offer index
|
|
95
|
+
to its ordered, non-overlapping source and target Unicode code-point spans and
|
|
96
|
+
binds both complete text lengths. The object contains no configured offer ID,
|
|
97
|
+
text, price, brand, or reviewer prose. It also carries the exact SHA-256 of the
|
|
98
|
+
separately advertised machine-readable routing contract. The sibling
|
|
99
|
+
`commercial_review_routing_contract` field contains that complete content-free
|
|
100
|
+
contract, so a remote reviewer does not depend on separate capability
|
|
101
|
+
discovery. The adapter reconstructs the canonical object and validates the
|
|
102
|
+
route against the exact source, target, summary, and profile before
|
|
103
|
+
authentication or transport. Route, digest, and full contract are part of the
|
|
104
|
+
deterministic request ID. Verified commercial results and non-commercial
|
|
105
|
+
requests require both route and routing contract to be `null`.
|
|
106
|
+
Non-commercial requests require every commercial field to be `null` and forbid
|
|
107
|
+
the nested commercial quality profile.
|
|
108
|
+
Source and
|
|
69
109
|
target text are intentionally present because this external step verifies the
|
|
70
110
|
existing source-blind native review and the separate source-aware fidelity
|
|
71
111
|
review. The service must preserve their confidentiality.
|
|
72
112
|
|
|
113
|
+
The suffix of `request_id` is the SHA-256 of canonical UTF-8 JSON containing
|
|
114
|
+
exactly `schema`, `evidence_revision`, `event_id`, `plan_id`, `job_id`,
|
|
115
|
+
`result_sha256`, both text hashes, both locales, `content_type`, glossary and
|
|
116
|
+
policy versions, provider/model identity, software version, both confidence
|
|
117
|
+
decisions, the complete locale quality profile, commercial profile and review,
|
|
118
|
+
the routing-contract digest, the conditional commercial review-routing object,
|
|
119
|
+
its complete routing contract, the resolution-contract hash, and both escalation
|
|
120
|
+
flags. The full texts and `request_id` itself are excluded from that identity;
|
|
121
|
+
their exact bytes are already bound by `source_sha256` and `target_sha256`.
|
|
122
|
+
The durable store and HTTP adapter independently recompute this same identity.
|
|
123
|
+
|
|
73
124
|
The adapter adds:
|
|
74
125
|
|
|
75
126
|
```text
|
|
@@ -109,11 +160,15 @@ numbers, a UTF-8 byte-order mark, wrong bindings, ambiguous content types,
|
|
|
109
160
|
incorrect lengths, and oversized bodies. The release coordinator then applies
|
|
110
161
|
its existing independent receipt checks. Each opaque receipt must verify
|
|
111
162
|
against the complete canonical
|
|
112
|
-
`blun.localization-quality-receipt-binding.
|
|
163
|
+
`blun.localization-quality-receipt-binding.v9` object supplied by the release
|
|
113
164
|
coordinator, including the review purpose, job and result hashes, both texts
|
|
114
165
|
and locales, content type, glossary and policy versions, provider/model and
|
|
115
166
|
software identities, locale quality and commercial profiles, the exact
|
|
116
|
-
commercial review scope,
|
|
167
|
+
commercial review scope, canonical resolution-contract SHA-256, confidence,
|
|
168
|
+
the exact public offer-routing-contract SHA-256, the private offer-routing
|
|
169
|
+
context, escalation requirements, and the exact
|
|
170
|
+
evidence request ID and revision from
|
|
171
|
+
this response. Reuse across
|
|
117
172
|
a changed field or between quality,
|
|
118
173
|
qualified-human, and independent-model review purposes must fail closed.
|
|
119
174
|
Legal content still requires a
|
|
@@ -80,7 +80,7 @@ The JSON envelope has exactly four fields:
|
|
|
80
80
|
"request_id": "<deterministic phase request ID>",
|
|
81
81
|
"request_sha256": "<SHA-256 of canonical request JSON>",
|
|
82
82
|
"request": {
|
|
83
|
-
"schema": "blun.website-localization-worker.
|
|
83
|
+
"schema": "blun.website-localization-worker.v9",
|
|
84
84
|
"request_id": "<same deterministic phase request ID>",
|
|
85
85
|
"phase": "transcreation",
|
|
86
86
|
"provider_id": "customer-llm",
|
|
@@ -98,6 +98,24 @@ the `target_native` input intentionally excludes the source text and
|
|
|
98
98
|
source-language glossary terms; reconstructing or fetching that source would
|
|
99
99
|
invalidate the independent, source-blind review.
|
|
100
100
|
|
|
101
|
+
For commercial content, only `source_fidelity` receives
|
|
102
|
+
`commercial_review_evidence_contract`. This is the complete content-free,
|
|
103
|
+
SHA-256-bound public contract for the required offer registry, Unicode spans,
|
|
104
|
+
ten checks, exact per-offer verdict coverage, deterministic aggregate-status
|
|
105
|
+
derivation, limits, and fail-closed trust boundary. The
|
|
106
|
+
worker verifies it against the installed public commercial profile before the
|
|
107
|
+
first provider call. Transcreation and source-blind native review do not receive
|
|
108
|
+
this contract. The provider still returns the private evidence only under
|
|
109
|
+
`response_schema.commercial_review`; the public contract itself contains no
|
|
110
|
+
project price, brand, source, target, span, or reviewer prose.
|
|
111
|
+
|
|
112
|
+
Commercial plan v4 and job v4 payloads also bind the exact public
|
|
113
|
+
offer-routing-contract SHA-256. Worker v8 reconstructs that contract together
|
|
114
|
+
with the review-evidence contract before any provider request, so queue health,
|
|
115
|
+
lease validation, retries, and provider invocation reject obsolete routing
|
|
116
|
+
semantics under the same deterministic job identity. Non-commercial jobs omit
|
|
117
|
+
both commercial contract digests.
|
|
118
|
+
|
|
101
119
|
`request_sha256` is the lowercase hexadecimal SHA-256 of `request` encoded as
|
|
102
120
|
UTF-8 JSON with keys sorted, no insignificant whitespace, native Unicode
|
|
103
121
|
characters unescaped, and non-finite numbers forbidden. The bundled adapter
|
|
@@ -25,11 +25,18 @@ retry and its attempt limit.
|
|
|
25
25
|
## Request
|
|
26
26
|
|
|
27
27
|
The adapter canonicalizes the complete
|
|
28
|
-
`blun.localization-quality-receipt-binding.
|
|
28
|
+
`blun.localization-quality-receipt-binding.v9` object and validates its native
|
|
29
29
|
Unicode text, hashes, locales, content type, glossary and policy versions,
|
|
30
30
|
provider/model identities, software version, two-pass confidence, locale
|
|
31
|
-
quality profile,
|
|
32
|
-
|
|
31
|
+
quality profile, exact locale-specific commercial profile when applicable,
|
|
32
|
+
matching targeted-review summary and its exact review-evidence-contract
|
|
33
|
+
SHA-256, the exact current offer-routing-contract SHA-256, the canonical
|
|
34
|
+
resolution-contract SHA-256
|
|
35
|
+
and the private, text-free mapping from opaque offer indexes to exact source
|
|
36
|
+
and target Unicode code-point spans for unresolved commercial review,
|
|
37
|
+
escalation requirements, review purpose,
|
|
38
|
+
canonical quality-evidence request ID, and evidence revision.
|
|
39
|
+
It then sends HTTP POST with JSON content type and these
|
|
33
40
|
protected headers:
|
|
34
41
|
|
|
35
42
|
- `Idempotency-Key`;
|
|
@@ -44,15 +51,24 @@ The body is exactly:
|
|
|
44
51
|
"request_id": "blun-l10n-receipt-<sha256>",
|
|
45
52
|
"binding_sha256": "<canonical binding hash>",
|
|
46
53
|
"receipt_sha256": "<opaque receipt hash>",
|
|
47
|
-
"binding": {"schema": "blun.localization-quality-receipt-binding.
|
|
54
|
+
"binding": {"schema": "blun.localization-quality-receipt-binding.v9"},
|
|
48
55
|
"receipt": "<opaque receipt>"
|
|
49
56
|
}
|
|
50
57
|
```
|
|
51
58
|
|
|
52
59
|
The deterministic request ID is derived from both hashes. Identical retries
|
|
53
60
|
therefore address the same verification operation, while any changed receipt
|
|
54
|
-
or binding dimension
|
|
61
|
+
or binding dimension—including the evidence request ID or revision—receives a
|
|
62
|
+
different identity. The remote service must
|
|
55
63
|
treat an idempotency-key collision with different bytes as a terminal error.
|
|
64
|
+
The adapter recomputes the commercial resolution-contract digest from the
|
|
65
|
+
installed profile before authentication or transport. Verified commercial and
|
|
66
|
+
non-commercial bindings require both that digest and the routing object to be
|
|
67
|
+
`null`. For unresolved review, it validates span order, bounds, text lengths,
|
|
68
|
+
offer count, and exact opaque index order before any credential callback or
|
|
69
|
+
network access. It also reconstructs and requires the exact digest of the
|
|
70
|
+
separately advertised machine-readable routing contract. The routing object
|
|
71
|
+
never contains configured offer IDs, text, prices, brands, or reviewer prose.
|
|
56
72
|
|
|
57
73
|
## Response
|
|
58
74
|
|
|
@@ -83,4 +99,6 @@ statuses, binding mismatches, and explicit negative verdicts are terminal.
|
|
|
83
99
|
|
|
84
100
|
The same adapter can be configured separately for quality, qualified-human,
|
|
85
101
|
and independent-model receipts. Purpose is part of the signed binding, so a
|
|
86
|
-
receipt accepted for one route cannot satisfy another route.
|
|
102
|
+
receipt accepted for one route cannot satisfy another route. Evidence context
|
|
103
|
+
is also part of the binding, so a receipt cannot be relabelled beneath a newer
|
|
104
|
+
provider response envelope.
|
|
@@ -27,11 +27,32 @@ _SPEC.loader.exec_module(_IMPL)
|
|
|
27
27
|
|
|
28
28
|
hashlib = _IMPL.hashlib
|
|
29
29
|
PUBLIC_PROFILE_SCHEMA = _IMPL.PUBLIC_PROFILE_SCHEMA
|
|
30
|
+
REVIEW_EVIDENCE_CAPABILITIES_SCHEMA = (
|
|
31
|
+
_IMPL.REVIEW_EVIDENCE_CAPABILITIES_SCHEMA
|
|
32
|
+
)
|
|
30
33
|
REVIEW_SUMMARY_CAPABILITIES_SCHEMA = _IMPL.REVIEW_SUMMARY_CAPABILITIES_SCHEMA
|
|
31
34
|
REVIEW_SUMMARY_SCHEMA = _IMPL.REVIEW_SUMMARY_SCHEMA
|
|
35
|
+
REVIEW_ROUTING_CAPABILITIES_SCHEMA = (
|
|
36
|
+
_IMPL.REVIEW_ROUTING_CAPABILITIES_SCHEMA
|
|
37
|
+
)
|
|
38
|
+
REVIEW_ROUTING_SCHEMA = _IMPL.REVIEW_ROUTING_SCHEMA
|
|
39
|
+
EVIDENCE_BINDING_SCHEMA = _IMPL.EVIDENCE_BINDING_SCHEMA
|
|
40
|
+
REVIEW_RESOLUTION_CAPABILITIES_SCHEMA = (
|
|
41
|
+
_IMPL.REVIEW_RESOLUTION_CAPABILITIES_SCHEMA
|
|
42
|
+
)
|
|
43
|
+
REVIEW_RESOLUTION_SCHEMA = _IMPL.REVIEW_RESOLUTION_SCHEMA
|
|
44
|
+
COMMERCIAL_LOCALE_PROFILE_SCHEMA = _IMPL.COMMERCIAL_LOCALE_PROFILE_SCHEMA
|
|
45
|
+
COMMERCIAL_RENDERING_REFERENCE_SCHEMA = (
|
|
46
|
+
_IMPL.COMMERCIAL_RENDERING_REFERENCE_SCHEMA
|
|
47
|
+
)
|
|
32
48
|
DIMENSIONS = _IMPL.DIMENSIONS
|
|
33
49
|
_canonical_json = _IMPL._canonical_json
|
|
50
|
+
evidence_sha256 = _IMPL.evidence_sha256
|
|
51
|
+
public_review_evidence_contract = _IMPL.public_review_evidence_contract
|
|
34
52
|
public_review_summary_contract = _IMPL.public_review_summary_contract
|
|
53
|
+
public_review_routing_contract = _IMPL.public_review_routing_contract
|
|
54
|
+
public_review_resolution_contract = _IMPL.public_review_resolution_contract
|
|
55
|
+
validate_review_resolution = _IMPL.validate_review_resolution
|
|
35
56
|
public_profile = _IMPL.public_profile
|
|
36
57
|
CREATION_GUIDANCE = _IMPL.CREATION_GUIDANCE
|
|
37
58
|
NATIVE_GUIDANCE = _IMPL.NATIVE_GUIDANCE
|
|
@@ -40,3 +61,5 @@ CommercialReviewBlocked = _IMPL.CommercialReviewBlocked
|
|
|
40
61
|
review_contract = _IMPL.review_contract
|
|
41
62
|
validate_review = _IMPL.validate_review
|
|
42
63
|
validate_summary = _IMPL.validate_summary
|
|
64
|
+
validate_review_routing_context = _IMPL.validate_review_routing_context
|
|
65
|
+
review_routing_context = _IMPL.review_routing_context
|
|
@@ -21,8 +21,8 @@ from pathlib import Path
|
|
|
21
21
|
from typing import Any, Iterable, Mapping, Sequence
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
SCHEMA = "blun.website-localization-plan.
|
|
25
|
-
JOB_SCHEMA = "blun.website-localization-job.
|
|
24
|
+
SCHEMA = "blun.website-localization-plan.v5"
|
|
25
|
+
JOB_SCHEMA = "blun.website-localization-job.v5"
|
|
26
26
|
EU_LANGUAGE_SOURCE = (
|
|
27
27
|
"https://european-union.europa.eu/principles-countries-history/languages_en"
|
|
28
28
|
)
|
|
@@ -42,7 +42,7 @@ CONTENT_TYPES = frozenset({
|
|
|
42
42
|
"commercial",
|
|
43
43
|
})
|
|
44
44
|
QUALITY_PASSES = ("target_native", "source_fidelity")
|
|
45
|
-
COMMERCIAL_PROFILE = "translate-native.commercial.
|
|
45
|
+
COMMERCIAL_PROFILE = "translate-native.commercial.v13"
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
class LocalizationPlanBlocked(ValueError):
|
|
@@ -78,6 +78,25 @@ def _load_quality_profiles():
|
|
|
78
78
|
|
|
79
79
|
|
|
80
80
|
_QUALITY_PROFILES = _load_quality_profiles()
|
|
81
|
+
COMMERCIAL_RENDERING_REGISTRY_SCHEMA = (
|
|
82
|
+
_QUALITY_PROFILES.COMMERCIAL_RENDERING_REGISTRY_SCHEMA
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _load_commercial_profile():
|
|
87
|
+
path = Path(__file__).with_name("commercial_localization_profile.py")
|
|
88
|
+
spec = importlib.util.spec_from_file_location(
|
|
89
|
+
"blun_website_planner_commercial_profile", path,
|
|
90
|
+
)
|
|
91
|
+
if spec is None or spec.loader is None:
|
|
92
|
+
raise RuntimeError("cannot load commercial localization profile")
|
|
93
|
+
module = importlib.util.module_from_spec(spec)
|
|
94
|
+
sys.modules[spec.name] = module
|
|
95
|
+
spec.loader.exec_module(module)
|
|
96
|
+
return module
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
_COMMERCIAL = _load_commercial_profile()
|
|
81
100
|
|
|
82
101
|
|
|
83
102
|
def _locale(locale: str, eu_code: str, language: str, native_name: str, script: str) -> LocaleProfile:
|
|
@@ -123,6 +142,126 @@ def quality_profile_for(locale: str) -> dict[str, Any]:
|
|
|
123
142
|
return _QUALITY_PROFILES.quality_profile_for(locale)
|
|
124
143
|
|
|
125
144
|
|
|
145
|
+
def commercial_quality_profile_for(locale: str) -> dict[str, Any]:
|
|
146
|
+
return _QUALITY_PROFILES.commercial_quality_profile_for(
|
|
147
|
+
locale,
|
|
148
|
+
COMMERCIAL_PROFILE,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def commercial_rendering_registry() -> dict[str, Any]:
|
|
153
|
+
return _QUALITY_PROFILES.commercial_rendering_registry(COMMERCIAL_PROFILE)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def commercial_review_evidence_contract_sha256() -> str:
|
|
157
|
+
"""Return the exact current evidence-contract generation or fail closed."""
|
|
158
|
+
try:
|
|
159
|
+
contract = _COMMERCIAL.public_review_evidence_contract(
|
|
160
|
+
COMMERCIAL_PROFILE,
|
|
161
|
+
)
|
|
162
|
+
public_contract = _COMMERCIAL.public_profile(COMMERCIAL_PROFILE)[
|
|
163
|
+
"review_evidence_contract"
|
|
164
|
+
]
|
|
165
|
+
if not isinstance(contract, dict) or not isinstance(
|
|
166
|
+
public_contract, dict
|
|
167
|
+
):
|
|
168
|
+
raise TypeError
|
|
169
|
+
unsigned = dict(contract)
|
|
170
|
+
digest = unsigned.pop("sha256")
|
|
171
|
+
computed_digest = _digest(unsigned)
|
|
172
|
+
except (KeyError, TypeError, ValueError) as error:
|
|
173
|
+
raise LocalizationPlanBlocked(
|
|
174
|
+
"commercial review-evidence contract is invalid"
|
|
175
|
+
) from error
|
|
176
|
+
if (
|
|
177
|
+
contract != public_contract
|
|
178
|
+
or contract.get("schema")
|
|
179
|
+
!= _COMMERCIAL.REVIEW_EVIDENCE_CAPABILITIES_SCHEMA
|
|
180
|
+
or contract.get("result_schema") != COMMERCIAL_PROFILE
|
|
181
|
+
or contract.get("profile") != COMMERCIAL_PROFILE
|
|
182
|
+
or not isinstance(digest, str)
|
|
183
|
+
or re.fullmatch(r"[0-9a-f]{64}", digest) is None
|
|
184
|
+
or digest != computed_digest
|
|
185
|
+
):
|
|
186
|
+
raise LocalizationPlanBlocked(
|
|
187
|
+
"commercial review-evidence contract is invalid"
|
|
188
|
+
)
|
|
189
|
+
return digest
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def commercial_review_routing_contract_sha256() -> str:
|
|
193
|
+
"""Return the exact current private-routing contract or fail closed."""
|
|
194
|
+
try:
|
|
195
|
+
contract = _COMMERCIAL.public_review_routing_contract(
|
|
196
|
+
COMMERCIAL_PROFILE,
|
|
197
|
+
)
|
|
198
|
+
public_contract = _COMMERCIAL.public_profile(COMMERCIAL_PROFILE)[
|
|
199
|
+
"review_routing_contract"
|
|
200
|
+
]
|
|
201
|
+
if not isinstance(contract, dict) or not isinstance(
|
|
202
|
+
public_contract, dict
|
|
203
|
+
):
|
|
204
|
+
raise TypeError
|
|
205
|
+
unsigned = dict(contract)
|
|
206
|
+
digest = unsigned.pop("sha256")
|
|
207
|
+
computed_digest = _digest(unsigned)
|
|
208
|
+
except (KeyError, TypeError, ValueError) as error:
|
|
209
|
+
raise LocalizationPlanBlocked(
|
|
210
|
+
"commercial review-routing contract is invalid"
|
|
211
|
+
) from error
|
|
212
|
+
if (
|
|
213
|
+
contract != public_contract
|
|
214
|
+
or contract.get("schema")
|
|
215
|
+
!= _COMMERCIAL.REVIEW_ROUTING_CAPABILITIES_SCHEMA
|
|
216
|
+
or contract.get("result_schema") != _COMMERCIAL.REVIEW_ROUTING_SCHEMA
|
|
217
|
+
or contract.get("profile") != COMMERCIAL_PROFILE
|
|
218
|
+
or not isinstance(digest, str)
|
|
219
|
+
or re.fullmatch(r"[0-9a-f]{64}", digest) is None
|
|
220
|
+
or digest != computed_digest
|
|
221
|
+
):
|
|
222
|
+
raise LocalizationPlanBlocked(
|
|
223
|
+
"commercial review-routing contract is invalid"
|
|
224
|
+
)
|
|
225
|
+
return digest
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def commercial_review_resolution_contract_sha256() -> str:
|
|
229
|
+
"""Return the exact current review-resolution contract or fail closed."""
|
|
230
|
+
try:
|
|
231
|
+
contract = _COMMERCIAL.public_review_resolution_contract(
|
|
232
|
+
COMMERCIAL_PROFILE,
|
|
233
|
+
)
|
|
234
|
+
public_contract = _COMMERCIAL.public_profile(COMMERCIAL_PROFILE)[
|
|
235
|
+
"review_resolution_contract"
|
|
236
|
+
]
|
|
237
|
+
if not isinstance(contract, dict) or not isinstance(
|
|
238
|
+
public_contract, dict
|
|
239
|
+
):
|
|
240
|
+
raise TypeError
|
|
241
|
+
unsigned = dict(contract)
|
|
242
|
+
digest = unsigned.pop("sha256")
|
|
243
|
+
computed_digest = _digest(unsigned)
|
|
244
|
+
except (KeyError, TypeError, ValueError) as error:
|
|
245
|
+
raise LocalizationPlanBlocked(
|
|
246
|
+
"commercial review-resolution contract is invalid"
|
|
247
|
+
) from error
|
|
248
|
+
if (
|
|
249
|
+
contract != public_contract
|
|
250
|
+
or contract.get("schema")
|
|
251
|
+
!= _COMMERCIAL.REVIEW_RESOLUTION_CAPABILITIES_SCHEMA
|
|
252
|
+
or contract.get("result_schema")
|
|
253
|
+
!= _COMMERCIAL.REVIEW_RESOLUTION_SCHEMA
|
|
254
|
+
or contract.get("profile") != COMMERCIAL_PROFILE
|
|
255
|
+
or not isinstance(digest, str)
|
|
256
|
+
or re.fullmatch(r"[0-9a-f]{64}", digest) is None
|
|
257
|
+
or digest != computed_digest
|
|
258
|
+
):
|
|
259
|
+
raise LocalizationPlanBlocked(
|
|
260
|
+
"commercial review-resolution contract is invalid"
|
|
261
|
+
)
|
|
262
|
+
return digest
|
|
263
|
+
|
|
264
|
+
|
|
126
265
|
@dataclass(frozen=True)
|
|
127
266
|
class LocalizationJob:
|
|
128
267
|
job_id: str
|
|
@@ -139,9 +278,43 @@ class LocalizationJob:
|
|
|
139
278
|
model_id: str
|
|
140
279
|
model_version: str
|
|
141
280
|
software_version: str
|
|
281
|
+
commercial_review_evidence_contract_sha256: str | None = None
|
|
282
|
+
commercial_review_routing_contract_sha256: str | None = None
|
|
283
|
+
commercial_review_resolution_contract_sha256: str | None = None
|
|
142
284
|
|
|
143
285
|
def as_payload(self) -> dict[str, Any]:
|
|
144
286
|
"""Return the provider-neutral queue payload for one target locale."""
|
|
287
|
+
commercial = (
|
|
288
|
+
commercial_quality_profile_for(self.target.locale)
|
|
289
|
+
if self.content_type == "commercial"
|
|
290
|
+
else None
|
|
291
|
+
)
|
|
292
|
+
commercial_evidence_sha256 = (
|
|
293
|
+
commercial_review_evidence_contract_sha256()
|
|
294
|
+
if commercial is not None
|
|
295
|
+
else None
|
|
296
|
+
)
|
|
297
|
+
commercial_routing_sha256 = (
|
|
298
|
+
commercial_review_routing_contract_sha256()
|
|
299
|
+
if commercial is not None
|
|
300
|
+
else None
|
|
301
|
+
)
|
|
302
|
+
commercial_resolution_sha256 = (
|
|
303
|
+
commercial_review_resolution_contract_sha256()
|
|
304
|
+
if commercial is not None
|
|
305
|
+
else None
|
|
306
|
+
)
|
|
307
|
+
if (
|
|
308
|
+
self.commercial_review_evidence_contract_sha256
|
|
309
|
+
!= commercial_evidence_sha256
|
|
310
|
+
or self.commercial_review_routing_contract_sha256
|
|
311
|
+
!= commercial_routing_sha256
|
|
312
|
+
or self.commercial_review_resolution_contract_sha256
|
|
313
|
+
!= commercial_resolution_sha256
|
|
314
|
+
):
|
|
315
|
+
raise LocalizationPlanBlocked(
|
|
316
|
+
"commercial review contract binding is stale"
|
|
317
|
+
)
|
|
145
318
|
return {
|
|
146
319
|
"schema": JOB_SCHEMA,
|
|
147
320
|
"job_id": self.job_id,
|
|
@@ -165,7 +338,23 @@ class LocalizationJob:
|
|
|
165
338
|
"software_version": self.software_version,
|
|
166
339
|
"quality_passes": list(QUALITY_PASSES),
|
|
167
340
|
"release_required": True,
|
|
168
|
-
**(
|
|
341
|
+
**(
|
|
342
|
+
{
|
|
343
|
+
"commercial_profile": COMMERCIAL_PROFILE,
|
|
344
|
+
"commercial_quality_profile": commercial,
|
|
345
|
+
"commercial_review_evidence_contract_sha256": (
|
|
346
|
+
commercial_evidence_sha256
|
|
347
|
+
),
|
|
348
|
+
"commercial_review_routing_contract_sha256": (
|
|
349
|
+
commercial_routing_sha256
|
|
350
|
+
),
|
|
351
|
+
"commercial_review_resolution_contract_sha256": (
|
|
352
|
+
commercial_resolution_sha256
|
|
353
|
+
),
|
|
354
|
+
}
|
|
355
|
+
if commercial is not None
|
|
356
|
+
else {}
|
|
357
|
+
),
|
|
169
358
|
}
|
|
170
359
|
|
|
171
360
|
|
|
@@ -319,11 +508,38 @@ def plan_website_localization(
|
|
|
319
508
|
"software_version": software_version,
|
|
320
509
|
"quality_passes": QUALITY_PASSES,
|
|
321
510
|
}
|
|
511
|
+
commercial_evidence_sha256 = None
|
|
512
|
+
commercial_routing_sha256 = None
|
|
513
|
+
commercial_resolution_sha256 = None
|
|
322
514
|
if content_type == "commercial":
|
|
323
515
|
common["commercial_profile"] = COMMERCIAL_PROFILE
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
516
|
+
commercial_evidence_sha256 = (
|
|
517
|
+
commercial_review_evidence_contract_sha256()
|
|
518
|
+
)
|
|
519
|
+
common["commercial_review_evidence_contract_sha256"] = (
|
|
520
|
+
commercial_evidence_sha256
|
|
521
|
+
)
|
|
522
|
+
commercial_routing_sha256 = (
|
|
523
|
+
commercial_review_routing_contract_sha256()
|
|
524
|
+
)
|
|
525
|
+
common["commercial_review_routing_contract_sha256"] = (
|
|
526
|
+
commercial_routing_sha256
|
|
527
|
+
)
|
|
528
|
+
commercial_resolution_sha256 = (
|
|
529
|
+
commercial_review_resolution_contract_sha256()
|
|
530
|
+
)
|
|
531
|
+
common["commercial_review_resolution_contract_sha256"] = (
|
|
532
|
+
commercial_resolution_sha256
|
|
533
|
+
)
|
|
534
|
+
jobs_list = []
|
|
535
|
+
for profile in profiles:
|
|
536
|
+
job_binding = {**common, "target": asdict(profile)}
|
|
537
|
+
if content_type == "commercial":
|
|
538
|
+
job_binding["commercial_quality_profile"] = (
|
|
539
|
+
commercial_quality_profile_for(profile.locale)
|
|
540
|
+
)
|
|
541
|
+
jobs_list.append(LocalizationJob(
|
|
542
|
+
job_id="blun-l10n-" + _digest(job_binding),
|
|
327
543
|
source_id=source_id,
|
|
328
544
|
source_revision=source_revision,
|
|
329
545
|
source_text=source_text,
|
|
@@ -337,9 +553,17 @@ def plan_website_localization(
|
|
|
337
553
|
model_id=model_id,
|
|
338
554
|
model_version=model_version,
|
|
339
555
|
software_version=software_version,
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
556
|
+
commercial_review_evidence_contract_sha256=(
|
|
557
|
+
commercial_evidence_sha256
|
|
558
|
+
),
|
|
559
|
+
commercial_review_routing_contract_sha256=(
|
|
560
|
+
commercial_routing_sha256
|
|
561
|
+
),
|
|
562
|
+
commercial_review_resolution_contract_sha256=(
|
|
563
|
+
commercial_resolution_sha256
|
|
564
|
+
),
|
|
565
|
+
))
|
|
566
|
+
jobs = tuple(jobs_list)
|
|
343
567
|
plan_binding = {
|
|
344
568
|
**common,
|
|
345
569
|
"target_locales": [job.target.locale for job in jobs],
|
|
@@ -734,7 +734,10 @@ def _validate_worker_result(job: dict[str, Any], result: Any) -> dict[str, Any]:
|
|
|
734
734
|
"source_locale", "target_locale", "content_type", "glossary_version",
|
|
735
735
|
"policy_version", "provider", "software_version", "candidate",
|
|
736
736
|
"quality_passes", "integrity", "review_confidence",
|
|
737
|
-
"quality_profile", "commercial_review", "
|
|
737
|
+
"quality_profile", "commercial_review", "commercial_review_routing",
|
|
738
|
+
"commercial_review_routing_contract_sha256",
|
|
739
|
+
"commercial_review_resolution_contract_sha256",
|
|
740
|
+
"human_review_required",
|
|
738
741
|
"independent_review_required", "release_required",
|
|
739
742
|
}
|
|
740
743
|
if not isinstance(result, dict) or set(result) != expected_keys:
|
|
@@ -771,16 +774,49 @@ def _validate_worker_result(job: dict[str, Any], result: Any) -> dict[str, Any]:
|
|
|
771
774
|
job["content_type"] != "legal" and "low" in review_confidence.values()
|
|
772
775
|
)
|
|
773
776
|
commercial_review = result["commercial_review"]
|
|
777
|
+
commercial_review_routing = result["commercial_review_routing"]
|
|
778
|
+
commercial_routing_contract_sha256 = result[
|
|
779
|
+
"commercial_review_routing_contract_sha256"
|
|
780
|
+
]
|
|
781
|
+
commercial_resolution_contract_sha256 = result[
|
|
782
|
+
"commercial_review_resolution_contract_sha256"
|
|
783
|
+
]
|
|
774
784
|
if job["content_type"] == "commercial":
|
|
785
|
+
if (
|
|
786
|
+
commercial_routing_contract_sha256
|
|
787
|
+
!= job["commercial_review_routing_contract_sha256"]
|
|
788
|
+
or commercial_resolution_contract_sha256
|
|
789
|
+
!= job["commercial_review_resolution_contract_sha256"]
|
|
790
|
+
):
|
|
791
|
+
raise BenchmarkBlocked(
|
|
792
|
+
"benchmark.candidate.commercial_review_invalid"
|
|
793
|
+
)
|
|
775
794
|
try:
|
|
776
|
-
_WORKER._COMMERCIAL.validate_summary(
|
|
795
|
+
commercial_review = _WORKER._COMMERCIAL.validate_summary(
|
|
777
796
|
commercial_review,
|
|
778
797
|
job["commercial_profile"],
|
|
779
798
|
review_required=expected_independent_review,
|
|
780
799
|
)
|
|
800
|
+
if commercial_review["status"] == "review_required":
|
|
801
|
+
_WORKER._COMMERCIAL.validate_review_routing_context(
|
|
802
|
+
commercial_review_routing,
|
|
803
|
+
job["source"]["text"],
|
|
804
|
+
candidate,
|
|
805
|
+
commercial_review,
|
|
806
|
+
job["commercial_profile"],
|
|
807
|
+
)
|
|
808
|
+
elif commercial_review_routing is not None:
|
|
809
|
+
raise _WORKER._COMMERCIAL.CommercialReviewBlocked(
|
|
810
|
+
"review.commercial.routing_invalid",
|
|
811
|
+
)
|
|
781
812
|
except _WORKER._COMMERCIAL.CommercialReviewBlocked:
|
|
782
813
|
raise BenchmarkBlocked("benchmark.candidate.commercial_review_invalid") from None
|
|
783
|
-
elif
|
|
814
|
+
elif any(value is not None for value in (
|
|
815
|
+
commercial_review,
|
|
816
|
+
commercial_review_routing,
|
|
817
|
+
commercial_routing_contract_sha256,
|
|
818
|
+
commercial_resolution_contract_sha256,
|
|
819
|
+
)):
|
|
784
820
|
raise BenchmarkBlocked("benchmark.candidate.commercial_review_invalid")
|
|
785
821
|
expected_quality_profile = {
|
|
786
822
|
"locale": job["target"]["locale"],
|