blun-king-cli 9.1.587 → 9.1.588
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 +11 -185
- package/LIESMICH.txt +51 -13
- package/README.md +44 -47
- package/agent-spine-plugin/.codex-plugin/plugin.json +16 -4
- package/agent-spine-plugin/CHANGELOG.md +37 -5
- package/agent-spine-plugin/README.md +3 -3
- package/agent-spine-plugin/blun.plugin.json +45 -10
- package/agent-spine-plugin/docs/artifact-evaluation.md +93 -0
- package/agent-spine-plugin/docs/host-integration.md +42 -27
- package/agent-spine-plugin/docs/preflight-recall.md +4 -2
- package/agent-spine-plugin/docs/session-timeline.md +97 -236
- package/agent-spine-plugin/docs/world-model.md +25 -0
- package/agent-spine-plugin/hooks/codex.json +1 -1
- package/agent-spine-plugin/hooks/hooks.json +1 -1
- package/agent-spine-plugin/package.json +1 -3
- package/agent-spine-plugin/scripts/check-hosts.js +3 -3
- package/agent-spine-plugin/scripts/release-check.js +10 -5
- package/agent-spine-plugin/scripts/run-checks.js +4 -1
- package/agent-spine-plugin/scripts/run-tests-hermetic.js +32 -6
- package/agent-spine-plugin/src/cli-learning.js +15 -0
- package/agent-spine-plugin/src/cli.js +2 -0
- package/agent-spine-plugin/src/hook.js +32 -32
- package/agent-spine-plugin/src/lib/action-lesson-recall.js +73 -8
- package/agent-spine-plugin/src/lib/briefing.js +146 -36
- package/agent-spine-plugin/src/lib/channel-continuity.js +19 -0
- package/agent-spine-plugin/src/lib/delivery-agent-usage.js +14 -7
- package/agent-spine-plugin/src/lib/gateway-group-response.js +128 -0
- package/agent-spine-plugin/src/lib/gateway-runs.js +24 -15
- package/agent-spine-plugin/src/lib/hook-briefing-use.js +13 -3
- package/agent-spine-plugin/src/lib/hook-context.js +16 -3
- package/agent-spine-plugin/src/lib/hook-output.js +129 -5
- package/agent-spine-plugin/src/lib/hook-timeline.js +5 -3
- package/agent-spine-plugin/src/lib/indexed-memory.js +2 -2
- package/agent-spine-plugin/src/lib/learning-artifact-evaluator.js +114 -0
- package/agent-spine-plugin/src/lib/learning-context.js +11 -4
- package/agent-spine-plugin/src/lib/learning-measurements.js +2 -2
- package/agent-spine-plugin/src/lib/mcp-runtime.js +89 -3
- package/agent-spine-plugin/src/lib/mcp-source-context.js +12 -2
- package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +91 -8
- package/agent-spine-plugin/src/lib/mcp-world-tools.js +2 -2
- package/agent-spine-plugin/src/lib/owned-file-lock.js +20 -1
- package/agent-spine-plugin/src/lib/persona-runtime.js +2 -2
- package/agent-spine-plugin/src/lib/preflight-delivery-id.js +27 -0
- package/agent-spine-plugin/src/lib/preflight.js +4 -4
- package/agent-spine-plugin/src/lib/session-timeline-codex.js +15 -0
- package/agent-spine-plugin/src/lib/session-timeline-contract.js +12 -4
- package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +36 -7
- package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +13 -10
- package/agent-spine-plugin/src/lib/session-timeline-invocation.js +1 -1
- package/agent-spine-plugin/src/lib/session-timeline-king.js +14 -0
- package/agent-spine-plugin/src/lib/session-timeline-prior.js +18 -12
- package/agent-spine-plugin/src/lib/session-timeline-provider.js +5 -0
- package/agent-spine-plugin/src/lib/session-timeline-query.js +2 -0
- package/agent-spine-plugin/src/lib/session-timeline-results.js +35 -10
- package/agent-spine-plugin/src/lib/session-timeline-source-open.js +30 -0
- package/agent-spine-plugin/src/lib/session-timeline.js +122 -75
- package/agent-spine-plugin/src/lib/source-roots.js +3 -2
- package/agent-spine-plugin/src/lib/task-knowledge-context.js +22 -1
- package/agent-spine-plugin/src/lib/timeline-continuation-update.js +100 -0
- package/agent-spine-plugin/src/lib/timeline-tool-guard.js +30 -7
- package/agent-spine-plugin/src/lib/timeline-user-feedback.js +217 -0
- package/agent-spine-plugin/src/lib/timeline-world-capture.js +233 -0
- package/agent-spine-plugin/src/lib/world-knowledge.js +59 -2
- package/agent-spine-plugin/src/lib/world-model.js +64 -9
- package/agent-spine-plugin/src/worker.js +13 -1
- package/bin/blun.js +43 -28
- package/bin/core-bootstrap.js +5 -4
- package/bin/king.js +43 -28
- package/bin/launcher-mode.js +1 -10
- package/bin/launcher-runtime.js +128 -295
- package/bin/managed-node.js +0 -0
- package/bin/managed-plugin-selection.cjs +0 -1
- package/bin/native-module-repair.js +0 -0
- package/bin/node-runtime.js +0 -0
- package/bin/node-version.js +0 -0
- package/bin/plugin-bootstrap.js +56 -120
- package/bin/private-paths.js +11 -34
- package/bin/standard-tools-bootstrap.js +34 -114
- package/bin/turn-thinking-policy.cjs +3 -11
- package/bin/update-copy.js +200 -0
- package/bin/update-lease.js +0 -0
- package/bin/update-notice.js +136 -289
- package/bin/verify-agent-behavior.cjs +122 -0
- package/bin/verify-agent-components.cjs +104 -0
- package/bin/verify-bundled-agent-sources.cjs +57 -0
- package/blun.mjs +143076 -135288
- package/bundled-agent-sources.json +701 -0
- package/package.json +12 -15
- package/standard-skills/translate-native/README.md +1293 -0
- package/standard-skills/translate-native/SKILL.md +172 -22
- package/standard-skills/translate-native/VERSION +1 -1
- package/standard-skills/translate-native/agents/openai.yaml +18 -0
- package/standard-skills/translate-native/assets/icon.svg +8 -0
- package/standard-skills/translate-native/docs/BLUN_CODE_INTEGRATION.md +76 -0
- package/standard-skills/translate-native/docs/PREMORTEM.md +489 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +2035 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1302 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +136 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HEALTH_HTTP.md +130 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +175 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +86 -0
- package/standard-skills/translate-native/integrations/AGENT_RULES.md +32 -0
- package/standard-skills/translate-native/integrations/adapters/blun-code-language-guard.js +514 -0
- package/standard-skills/translate-native/integrations/adapters/node-language-guard.js +230 -0
- package/standard-skills/translate-native/integrations/audit_log.py +327 -0
- package/standard-skills/translate-native/integrations/claude_language_hook.js +1536 -0
- package/standard-skills/translate-native/integrations/commercial_localization_profile.py +42 -0
- package/standard-skills/translate-native/integrations/delivery-policy.example.json +28 -0
- package/standard-skills/translate-native/integrations/enforced_delivery.py +543 -0
- package/standard-skills/translate-native/integrations/guard_service.py +435 -0
- package/standard-skills/translate-native/integrations/language_gateway.py +67 -0
- package/standard-skills/translate-native/integrations/mcp_auth_headers.py +198 -0
- package/standard-skills/translate-native/integrations/mcp_http_gateway.py +429 -0
- package/standard-skills/translate-native/integrations/non_language_html_entities.js +1485 -0
- package/standard-skills/translate-native/integrations/pre_output_guard.py +65 -0
- package/standard-skills/translate-native/integrations/task_router.py +101 -0
- package/standard-skills/translate-native/integrations/website_localization.py +401 -0
- package/standard-skills/translate-native/integrations/website_localization_api.py +581 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark.py +1885 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_campaign.py +1772 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_candidate.py +506 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_http.py +400 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_review_store.py +781 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_reviewer_http.py +500 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_runtime.py +1107 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_suite.py +463 -0
- package/standard-skills/translate-native/integrations/website_localization_cms.py +2835 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_client.py +875 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_dispatch.py +805 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_http.py +588 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_lifecycle_monitor.py +991 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +1441 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +414 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +1073 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_removal_dispatch.py +865 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +583 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +964 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +665 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +1153 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +675 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +1125 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification.py +674 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +444 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +1469 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +1142 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +634 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +804 -0
- package/standard-skills/translate-native/integrations/website_localization_deepl_baseline.py +922 -0
- package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +482 -0
- package/standard-skills/translate-native/integrations/website_localization_health.py +1541 -0
- package/standard-skills/translate-native/integrations/website_localization_health_http.py +372 -0
- package/standard-skills/translate-native/integrations/website_localization_http_provider.py +297 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_http.py +479 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_intake.py +363 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_queue.py +1449 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_store.py +420 -0
- package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +235 -0
- package/standard-skills/translate-native/integrations/website_localization_queue.py +671 -0
- package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +516 -0
- package/standard-skills/translate-native/integrations/website_localization_release.py +928 -0
- package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +1008 -0
- package/standard-skills/translate-native/integrations/website_localization_runner.py +276 -0
- package/standard-skills/translate-native/integrations/website_localization_runtime.py +862 -0
- package/standard-skills/translate-native/integrations/website_localization_service.py +350 -0
- package/standard-skills/translate-native/integrations/website_localization_supervisor.py +511 -0
- package/standard-skills/translate-native/integrations/website_localization_worker.py +663 -0
- package/standard-skills/translate-native/provenance.json +3 -4
- package/standard-skills/translate-native/references/commercial-localization.md +177 -0
- package/standard-skills/translate-native/scripts/blun_language_guard.py +7 -1
- package/standard-skills/translate-native/scripts/check_commercial_review.py +80 -0
- package/standard-skills/translate-native/scripts/commercial_localization_profile.py +333 -0
- package/standard-tools/language-guard/LICENSE +21 -0
- package/standard-tools/language-guard/VERSION +1 -0
- package/standard-tools/language-guard/blun_language_guard.py +7 -1
- package/standard-tools/language-guard/check_commercial_review.py +80 -0
- package/standard-tools/language-guard/commercial_localization_profile.py +333 -0
- package/standard-tools/language-guard/language_gateway.py +62 -0
- package/standard-tools/language-guard/pre_output_guard.py +64 -0
- package/standard-tools/language-guard/provenance.json +4 -11
- package/standard-tools/manifest.json +34 -11
- package/telegram-plugin/commands/access.md +2 -10
- package/telegram-plugin/dist/bridge.mjs +64041 -687
- package/telegram-plugin/dist/mcp-server.mjs +72810 -9027
- package/telegram-plugin/dist/noise.mjs +28 -63511
- package/agent-spine-plugin/CONTRIBUTING.md +0 -52
- package/agent-spine-plugin/SECURITY.md +0 -47
- package/agent-spine-plugin/docs/assignment-continuation.md +0 -48
- package/agent-spine-plugin/docs/releasing.md +0 -85
- package/agent-spine-plugin/docs/structured-completion.md +0 -67
- package/bin/abort-listener-policy.cjs +0 -43
- package/bin/active-steer-priority-policy.cjs +0 -24
- package/bin/agent-api-http-adapter.mjs +0 -446
- package/bin/agent-api-private-http-server.mjs +0 -288
- package/bin/agent-api-runtime.mjs +0 -252
- package/bin/agent-api-service-environment.mjs +0 -236
- package/bin/agent-api-service-host.mjs +0 -209
- package/bin/agent-api-service-process.mjs +0 -171
- package/bin/agent-api-session-registry.mjs +0 -428
- package/bin/agent-api-tool-broker.cjs +0 -248
- package/bin/agent-api-turn-controller.mjs +0 -461
- package/bin/agent-api-usage-journal.cjs +0 -259
- package/bin/agent-resume-snapshot.cjs +0 -241
- package/bin/agentspine-king-goal-inbox.mjs +0 -111
- package/bin/agentspine-king-goal-intake.mjs +0 -106
- package/bin/approval-rejection-stop.cjs +0 -15
- package/bin/assistant-message-offload-policy.cjs +0 -284
- package/bin/baseline-skill-performance-policy.cjs +0 -39
- package/bin/bash-search-scope-policy.cjs +0 -49
- package/bin/codebase-search-runtime.cjs +0 -23
- package/bin/cognitive-action-checkpoint.cjs +0 -1104
- package/bin/cognitive-attention-delivery.cjs +0 -76
- package/bin/cognitive-attention-policy.cjs +0 -143
- package/bin/cognitive-attention-runtime.cjs +0 -91
- package/bin/cognitive-context-projection.cjs +0 -73
- package/bin/cognitive-cross-portal-acceptance.cjs +0 -443
- package/bin/cognitive-effective-view.cjs +0 -77
- package/bin/cognitive-focus-projection.cjs +0 -206
- package/bin/cognitive-focus-scope.cjs +0 -37
- package/bin/cognitive-goal-autostart-policy.cjs +0 -72
- package/bin/cognitive-goal-time-trigger-controller.cjs +0 -146
- package/bin/cognitive-memory-adapter.cjs +0 -282
- package/bin/cognitive-memory-command.cjs +0 -293
- package/bin/cognitive-memory-provider.cjs +0 -92
- package/bin/cognitive-salience-policy.cjs +0 -159
- package/bin/cognitive-state-store.cjs +0 -508
- package/bin/cognitive-turn-lifecycle.cjs +0 -624
- package/bin/cognitive-work-focus.cjs +0 -180
- package/bin/compaction-history-archive.cjs +0 -166
- package/bin/compaction-history-startup.cjs +0 -50
- package/bin/compaction-model-policy.cjs +0 -31
- package/bin/compaction-stage-policy.cjs +0 -21
- package/bin/compaction-transaction-policy.cjs +0 -122
- package/bin/config-write-dedup-policy.cjs +0 -27
- package/bin/context-budget-ledger.cjs +0 -31
- package/bin/context-doctor-policy.cjs +0 -70
- package/bin/context-insight-policy.cjs +0 -36
- package/bin/context-performance-policy.cjs +0 -19
- package/bin/context-pressure-policy.cjs +0 -20
- package/bin/cron-run-output.cjs +0 -45
- package/bin/cron-run-store.cjs +0 -145
- package/bin/curiosity-scout-policy.cjs +0 -49
- package/bin/default-model-output-budget-policy.cjs +0 -28
- package/bin/durable-task-resume-policy.cjs +0 -130
- package/bin/durable-task-resume-runtime.cjs +0 -117
- package/bin/durable-task-resume-store.cjs +0 -88
- package/bin/editable-tool-approval-policy.cjs +0 -540
- package/bin/editable-tool-approval-runtime.cjs +0 -99
- package/bin/effective-system-prompt-cache-policy.cjs +0 -33
- package/bin/error-memory-performance-policy.cjs +0 -113
- package/bin/file-observation-policy.cjs +0 -133
- package/bin/foreground-output-capture-policy.cjs +0 -41
- package/bin/generated-source-health.cjs +0 -142
- package/bin/glob-pattern-policy.cjs +0 -13
- package/bin/goal-completion-evidence-policy.cjs +0 -120
- package/bin/grep-output-limit-policy.cjs +0 -39
- package/bin/historical-media-projection-policy.cjs +0 -48
- package/bin/history-offload-pressure-policy.cjs +0 -33
- package/bin/html-to-research-markdown.cjs +0 -147
- package/bin/identity-context-policy.cjs +0 -764
- package/bin/identity-journal-policy.cjs +0 -107
- package/bin/input-draft-persistence.cjs +0 -77
- package/bin/king-tui-function-contract.json +0 -33
- package/bin/launcher-restart-policy.cjs +0 -150
- package/bin/live-response-repetition-guard.cjs +0 -196
- package/bin/llm-config-log-dedup-policy.cjs +0 -76
- package/bin/loop-event-record-policy.cjs +0 -174
- package/bin/managed-context-startup-policy.cjs +0 -27
- package/bin/media-activity-layout-policy.cjs +0 -34
- package/bin/media-auto-retrieval-policy.cjs +0 -90
- package/bin/media-result-policy.cjs +0 -59
- package/bin/micro-compaction-policy.cjs +0 -145
- package/bin/mistake-relevance-policy.cjs +0 -319
- package/bin/model-retry-progress-policy.cjs +0 -46
- package/bin/native-large-file-io.cjs +0 -42
- package/bin/native-runtime-cache.cjs +0 -76
- package/bin/natural-presence-policy.cjs +0 -28
- package/bin/noninteractive-shell-env-policy.cjs +0 -19
- package/bin/observer-hooks.cjs +0 -14
- package/bin/outbound-claim-provenance.cjs +0 -150
- package/bin/oversized-context-offload-policy.cjs +0 -86
- package/bin/pending-media-policy.cjs +0 -182
- package/bin/pending-token-estimate-policy.cjs +0 -41
- package/bin/personal-memory-consent-policy.cjs +0 -72
- package/bin/personal-memory-performance-policy.cjs +0 -12
- package/bin/personality-choice-policy.cjs +0 -101
- package/bin/personality-memory-adapter.cjs +0 -379
- package/bin/personality-mode.cjs +0 -46
- package/bin/personality-setup-policy.cjs +0 -197
- package/bin/proactive-compaction-policy.cjs +0 -25
- package/bin/profile-identity-resolution.cjs +0 -136
- package/bin/profile-runtime.cjs +0 -318
- package/bin/profile-tool-exclusion-policy.cjs +0 -37
- package/bin/programmatic-context-isolation.cjs +0 -25
- package/bin/programmatic-tool-runtime.mjs +0 -627
- package/bin/provider-idle-timeout-policy.cjs +0 -14
- package/bin/provider-model-refresh-deadline.cjs +0 -53
- package/bin/provider-model-refresh-policy.cjs +0 -107
- package/bin/rate-limit-recovery-policy.cjs +0 -47
- package/bin/read-batch-policy.cjs +0 -32
- package/bin/read-continuation-policy.cjs +0 -59
- package/bin/recurring-cron-history-policy.cjs +0 -124
- package/bin/relationship-continuity-policy.cjs +0 -143
- package/bin/relationship-curiosity-policy.cjs +0 -107
- package/bin/relationship-learning-policy.cjs +0 -168
- package/bin/release-artifact-freeze-policy.cjs +0 -30
- package/bin/reload-plugin-bootstrap.cjs +0 -18
- package/bin/reload-queue-policy.cjs +0 -38
- package/bin/repeated-assistant-response-policy.cjs +0 -232
- package/bin/repeated-injection-projection.cjs +0 -107
- package/bin/repeated-user-message-projection.cjs +0 -8
- package/bin/research-page-result.cjs +0 -74
- package/bin/retry-checkpoint-policy.cjs +0 -13
- package/bin/runtime-exit-ledger.cjs +0 -144
- package/bin/scoped-cron-run-policy.cjs +0 -358
- package/bin/session-checkpoint-policy.cjs +0 -25
- package/bin/session-compaction-policy.cjs +0 -84
- package/bin/session-replay-policy.cjs +0 -20
- package/bin/session-replay-window-policy.cjs +0 -40
- package/bin/session-resume-checkpoint.cjs +0 -254
- package/bin/session-scrollback-archive.cjs +0 -229
- package/bin/skill-activation-performance-policy.cjs +0 -69
- package/bin/skill-listing-performance-policy.cjs +0 -92
- package/bin/soul-organization-policy.cjs +0 -78
- package/bin/soul-preservation-policy.cjs +0 -20
- package/bin/startup-preferences.cjs +0 -131
- package/bin/streaming-flush-performance-policy.cjs +0 -28
- package/bin/structured-agent-swarm-output.cjs +0 -325
- package/bin/structured-subagent-output.cjs +0 -252
- package/bin/subagent-context-fork-policy.cjs +0 -155
- package/bin/subagent-max-tokens-handoff-policy.cjs +0 -69
- package/bin/subagent-parent-responsiveness.cjs +0 -19
- package/bin/subagent-skill-policy.cjs +0 -206
- package/bin/subagent-timeout-policy.cjs +0 -182
- package/bin/subagent-tool-policy.cjs +0 -60
- package/bin/subagent-usage-rollup-policy.cjs +0 -29
- package/bin/system-prompt-context-policy.cjs +0 -124
- package/bin/system-prompt-token-cache-policy.cjs +0 -60
- package/bin/telegram-addressed-focus.cjs +0 -55
- package/bin/telegram-addressed-priority.cjs +0 -12
- package/bin/telegram-approval-relay.cjs +0 -290
- package/bin/telegram-bot-priority.cjs +0 -17
- package/bin/telegram-console-status-policy.cjs +0 -174
- package/bin/telegram-context-projection-policy.cjs +0 -141
- package/bin/telegram-delivery-lifecycle.cjs +0 -125
- package/bin/telegram-direct-focus-policy.cjs +0 -273
- package/bin/telegram-mcp-compatibility.cjs +0 -49
- package/bin/telegram-media-delivery-policy.cjs +0 -42
- package/bin/telegram-private-conversation-policy.cjs +0 -185
- package/bin/telegram-queue-handoff-policy.cjs +0 -73
- package/bin/telegram-remote-status-policy.cjs +0 -120
- package/bin/telegram-session-queue-runtime.mjs +0 -306
- package/bin/telegram-text-chunk-policy.cjs +0 -63
- package/bin/telegram-truncated-reply-policy.cjs +0 -37
- package/bin/telegram-urgent-policy.cjs +0 -45
- package/bin/telemetry-spool-policy.cjs +0 -57
- package/bin/thinking-activity-status-policy.cjs +0 -132
- package/bin/thinking-only-guard.cjs +0 -80
- package/bin/todo-list-turn-policy.cjs +0 -131
- package/bin/tool-call-loop-policy.cjs +0 -51
- package/bin/tool-file-persistence.cjs +0 -141
- package/bin/tool-result-offload-policy.cjs +0 -359
- package/bin/tool-result-offload-telemetry.cjs +0 -12
- package/bin/tool-schema-token-cache-policy.cjs +0 -41
- package/bin/tool-stream-preview-policy.cjs +0 -9
- package/bin/tui-functional-contract.cjs +0 -55
- package/bin/turn-tool-performance-policy.cjs +0 -486
- package/bin/usage-cache-efficiency-policy.cjs +0 -26
- package/bin/user-home-path-policy.cjs +0 -13
- package/bin/user-message-offload-policy.cjs +0 -103
- package/bin/user-prompt-hook-origin-policy.cjs +0 -34
- package/bin/user-tool-record-policy.cjs +0 -7
- package/bin/validated-learning-insight-policy.cjs +0 -58
- package/bin/validated-learning-outcome-trace.cjs +0 -107
- package/bin/validated-learning-performance-policy.cjs +0 -53
- package/bin/validated-learning-signal.cjs +0 -463
- package/bin/windows-bash-dialect-policy.cjs +0 -25
- package/bin/windows-node-crash-dump.cjs +0 -110
- package/bin/write-continuation-policy.cjs +0 -69
- package/codebase-index/README.md +0 -82
- package/codebase-index/codebase_index.py +0 -470
- package/standard-skills/agent-browser/SKILL.md +0 -19
- package/standard-skills/agent-browser/references/runtime.md +0 -8
- package/standard-skills/blun-session-inspector/SKILL.md +0 -41
- package/standard-skills/blun-session-inspector/scripts/inspect-session.cjs +0 -437
- package/standard-skills/design-taste-frontend/SKILL.md +0 -1206
- package/standard-skills/full-output-enforcement/SKILL.md +0 -49
- package/standard-skills/high-end-visual-design/SKILL.md +0 -98
- package/standard-skills/image-to-code/SKILL.md +0 -1228
- package/standard-skills/industrial-brutalist-ui/SKILL.md +0 -92
- package/standard-skills/minimalist-ui/SKILL.md +0 -85
- package/standard-skills/motion-design-taste/SKILL.md +0 -74
- package/standard-skills/playwright-testing/SKILL.md +0 -19
- package/standard-skills/playwright-testing/references/runtime.md +0 -7
- package/standard-skills/premortem/SKILL.md +0 -148
- package/standard-skills/redesign-existing-projects/SKILL.md +0 -178
- package/standard-skills/research-evidence/SKILL.md +0 -39
- package/standard-skills/research-evidence/references/evidence-format.md +0 -104
- package/standard-skills/research-evidence/scripts/evidence-collection.cjs +0 -260
- package/standard-skills/research-evidence/scripts/score-report.cjs +0 -130
- package/standard-skills/screenshot-lesen/SKILL.md +0 -52
- package/standard-skills/stitch-design-taste/DESIGN.md +0 -121
- package/standard-skills/stitch-design-taste/SKILL.md +0 -184
- package/standard-skills/telegram-channel/SKILL.md +0 -18
- package/standard-skills/telegram-channel/references/runtime.md +0 -7
- package/standard-skills/venture-flywheel/SKILL.md +0 -32
- package/standard-skills/venture-flywheel/identity/project-identity.cjs +0 -146
- package/standard-skills/venture-flywheel/policy/capability-engine.cjs +0 -114
- package/standard-skills/venture-flywheel/policy/repository-trust.cjs +0 -229
- package/standard-skills/venture-flywheel/references/BEISPIELE-phase0.md +0 -146
- package/standard-skills/venture-flywheel/references/CAPABILITY-MAP.md +0 -34
- package/standard-skills/venture-flywheel/references/SPEC-phase0-identity-trust.md +0 -77
- package/standard-skills/venture-flywheel/references/SPEC-phase0-state-events.md +0 -93
- package/standard-skills/venture-flywheel/schemas/capability-decision.schema.json +0 -13
- package/standard-skills/venture-flywheel/schemas/execution-event.schema.json +0 -44
- package/standard-skills/venture-flywheel/schemas/project-identity.schema.json +0 -32
- package/standard-skills/venture-flywheel/schemas/repository-trust.schema.json +0 -57
- package/standard-skills/venture-flywheel/schemas/run-transition.schema.json +0 -59
- package/standard-skills/venture-flywheel/state/execution-event.cjs +0 -191
- package/standard-skills/venture-flywheel/state/task-state-machine.cjs +0 -190
- package/standard-skills/web-lesen/SKILL.md +0 -73
- package/standard-skills/web-lesen/scripts/crawl_public.py +0 -379
- package/standard-skills/windows-mcp/SKILL.md +0 -19
- package/standard-skills/windows-mcp/references/runtime.md +0 -9
- package/telegram-plugin/DELIVERY.md +0 -36
- package/telegram-plugin/bin/telegram-approval-relay.cjs +0 -290
- package/telegram-plugin/bin/telegram-console-status-policy.cjs +0 -175
- package/telegram-plugin/bin/telegram-delivery-lifecycle.cjs +0 -125
- package/telegram-plugin/bin/telegram-direct-reply-policy.cjs +0 -48
- package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +0 -122
- package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +0 -186
- package/telegram-plugin/bin/telegram-remote-status-policy.cjs +0 -121
- package/telegram-plugin/bin/telegram-reply-parts.cjs +0 -149
- package/telegram-plugin/bin/telegram-text-chunk-policy.cjs +0 -63
- package/telegram-plugin/bin/telegram-typing-keepalive.cjs +0 -89
- package/telegram-plugin/compat/mcp-server-fa511cd1.mjs +0 -73825
- /package/{bin → scripts}/fix-node-pty-perms.js +0 -0
|
@@ -0,0 +1,922 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Secure acquisition of DeepL benchmark baselines and lawful fixtures.
|
|
3
|
+
|
|
4
|
+
The adapter calls only DeepL's documented API origins. It discovers stable
|
|
5
|
+
language support at runtime, sends exactly one complete source document, and
|
|
6
|
+
returns text-free provenance evidence beside the attested baseline artifact.
|
|
7
|
+
The durable store binds an exact acquisition to its route, policy, and job so a
|
|
8
|
+
worker restart cannot silently replace it. Credentials never enter artifacts,
|
|
9
|
+
evidence, exceptions, persisted state, or object reprs.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import hashlib
|
|
15
|
+
import importlib.util
|
|
16
|
+
import json
|
|
17
|
+
import math
|
|
18
|
+
import re
|
|
19
|
+
import socket
|
|
20
|
+
import sqlite3
|
|
21
|
+
import sys
|
|
22
|
+
import time
|
|
23
|
+
import unicodedata
|
|
24
|
+
import urllib.error
|
|
25
|
+
import urllib.request
|
|
26
|
+
from contextlib import contextmanager
|
|
27
|
+
from dataclasses import dataclass, fields, is_dataclass
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Any, Callable, Iterator, Mapping, Protocol
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
EVIDENCE_SCHEMA = "blun.website-localization-deepl-api-evidence.v1"
|
|
33
|
+
FIXTURE_EVIDENCE_SCHEMA = "blun.website-localization-lawful-baseline-fixture.v1"
|
|
34
|
+
OFFICIAL_ORIGINS = {
|
|
35
|
+
"free": "https://api-free.deepl.com",
|
|
36
|
+
"pro": "https://api.deepl.com",
|
|
37
|
+
}
|
|
38
|
+
LANGUAGES_PATH = "/v3/languages?resource=translate_text"
|
|
39
|
+
TRANSLATE_PATH = "/v2/translate"
|
|
40
|
+
MAX_REQUEST_BYTES = 128 * 1024
|
|
41
|
+
MAX_RESPONSE_BYTES = 4 * 1024 * 1024
|
|
42
|
+
MAX_AUTH_BYTES = 16 * 1024
|
|
43
|
+
MAX_LANGUAGES = 10_000
|
|
44
|
+
BCP47 = re.compile(r"^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8}){0,8}$")
|
|
45
|
+
ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
|
|
46
|
+
RIGHTS_BASES = frozenset(("owned", "licensed", "permission"))
|
|
47
|
+
STORE_SCHEMA = "blun.website-localization-baseline-acquisition-store.v1"
|
|
48
|
+
STORE_COLUMNS = (
|
|
49
|
+
"acquisition_id", "route_id", "policy_sha256", "job_sha256",
|
|
50
|
+
"artifact_json", "artifact_sha256", "evidence_json", "evidence_sha256",
|
|
51
|
+
"created_at",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _load_module(name: str, path: Path):
|
|
56
|
+
spec = importlib.util.spec_from_file_location(name, path)
|
|
57
|
+
if spec is None or spec.loader is None:
|
|
58
|
+
raise RuntimeError(f"cannot load baseline dependency: {path.name}")
|
|
59
|
+
module = importlib.util.module_from_spec(spec)
|
|
60
|
+
sys.modules[spec.name] = module
|
|
61
|
+
spec.loader.exec_module(module)
|
|
62
|
+
return module
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
_ROOT = Path(__file__).resolve().parents[1]
|
|
66
|
+
_BENCHMARK = _load_module(
|
|
67
|
+
"blun_website_localization_deepl_benchmark",
|
|
68
|
+
_ROOT / "integrations" / "website_localization_benchmark.py",
|
|
69
|
+
)
|
|
70
|
+
_WORKER = _BENCHMARK._WORKER
|
|
71
|
+
_SUITE = _BENCHMARK._SUITE
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class DeepLBaselineFailed(RuntimeError):
|
|
75
|
+
"""Content-free acquisition failure understood by durable orchestration."""
|
|
76
|
+
|
|
77
|
+
benchmark_campaign_dependency_failure = True
|
|
78
|
+
|
|
79
|
+
def __init__(self, code: str, *, retryable: bool):
|
|
80
|
+
if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
|
|
81
|
+
raise ValueError("baseline error code is invalid")
|
|
82
|
+
if not isinstance(retryable, bool):
|
|
83
|
+
raise ValueError("baseline retryability must be boolean")
|
|
84
|
+
super().__init__(code)
|
|
85
|
+
self.code = code
|
|
86
|
+
self.retryable = retryable
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass(frozen=True)
|
|
90
|
+
class HTTPResult:
|
|
91
|
+
status: int
|
|
92
|
+
headers: tuple[tuple[str, str], ...]
|
|
93
|
+
body: bytes
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class HTTPTransport(Protocol):
|
|
97
|
+
def request(
|
|
98
|
+
self,
|
|
99
|
+
method: str,
|
|
100
|
+
url: str,
|
|
101
|
+
headers: Mapping[str, str],
|
|
102
|
+
body: bytes | None,
|
|
103
|
+
*,
|
|
104
|
+
timeout: float,
|
|
105
|
+
) -> HTTPResult: ...
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class _NoRedirect(urllib.request.HTTPRedirectHandler):
|
|
109
|
+
def redirect_request(self, req, fp, code, msg, headers, newurl):
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class URLTransport:
|
|
114
|
+
"""One bounded stdlib HTTPS attempt with redirects disabled."""
|
|
115
|
+
|
|
116
|
+
def __init__(self):
|
|
117
|
+
self._opener = urllib.request.build_opener(_NoRedirect)
|
|
118
|
+
|
|
119
|
+
def request(
|
|
120
|
+
self,
|
|
121
|
+
method: str,
|
|
122
|
+
url: str,
|
|
123
|
+
headers: Mapping[str, str],
|
|
124
|
+
body: bytes | None,
|
|
125
|
+
*,
|
|
126
|
+
timeout: float,
|
|
127
|
+
) -> HTTPResult:
|
|
128
|
+
request = urllib.request.Request(
|
|
129
|
+
url, data=body, headers=dict(headers), method=method,
|
|
130
|
+
)
|
|
131
|
+
try:
|
|
132
|
+
response = self._opener.open(request, timeout=timeout)
|
|
133
|
+
except urllib.error.HTTPError as error:
|
|
134
|
+
return HTTPResult(
|
|
135
|
+
int(error.code),
|
|
136
|
+
tuple(error.headers.items()) if error.headers is not None else (),
|
|
137
|
+
b"",
|
|
138
|
+
)
|
|
139
|
+
except (urllib.error.URLError, TimeoutError, socket.timeout, OSError):
|
|
140
|
+
raise DeepLBaselineFailed("deepl.network", retryable=True) from None
|
|
141
|
+
try:
|
|
142
|
+
content = response.read(MAX_RESPONSE_BYTES + 1)
|
|
143
|
+
return HTTPResult(
|
|
144
|
+
int(response.status), tuple(response.headers.items()), content,
|
|
145
|
+
)
|
|
146
|
+
except (TimeoutError, socket.timeout, OSError):
|
|
147
|
+
raise DeepLBaselineFailed("deepl.network", retryable=True) from None
|
|
148
|
+
finally:
|
|
149
|
+
response.close()
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@dataclass(frozen=True)
|
|
153
|
+
class BaselineAcquisition:
|
|
154
|
+
artifact: dict[str, Any]
|
|
155
|
+
evidence: dict[str, Any]
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _canonical_json(value: Any, *, code: str, maximum: int) -> str:
|
|
159
|
+
return _json_bytes(value, code=code, maximum=maximum).decode("utf-8")
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _parse_stored_json(value: Any) -> Any:
|
|
163
|
+
if not isinstance(value, str) or not value:
|
|
164
|
+
raise DeepLBaselineFailed("baseline.store.state_invalid", retryable=False)
|
|
165
|
+
try:
|
|
166
|
+
if len(value.encode("utf-8")) > MAX_RESPONSE_BYTES:
|
|
167
|
+
raise ValueError("stored JSON is too large")
|
|
168
|
+
return json.loads(
|
|
169
|
+
value, object_pairs_hook=_pairs, parse_constant=_constant,
|
|
170
|
+
)
|
|
171
|
+
except (UnicodeEncodeError, ValueError, RecursionError):
|
|
172
|
+
raise DeepLBaselineFailed("baseline.store.state_invalid", retryable=False) from None
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _timestamp(value: Any) -> float:
|
|
176
|
+
value = time.time() if value is None else value
|
|
177
|
+
if (
|
|
178
|
+
isinstance(value, bool)
|
|
179
|
+
or not isinstance(value, (int, float))
|
|
180
|
+
or not math.isfinite(float(value))
|
|
181
|
+
or float(value) < 0
|
|
182
|
+
):
|
|
183
|
+
raise DeepLBaselineFailed("baseline.store.time_invalid", retryable=False)
|
|
184
|
+
return float(value)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _policy_sha256(policy: Any) -> str:
|
|
188
|
+
try:
|
|
189
|
+
validated = _BENCHMARK._validate_policy(policy)
|
|
190
|
+
payload = {
|
|
191
|
+
field: getattr(validated, field)
|
|
192
|
+
for field in validated.__dataclass_fields__
|
|
193
|
+
}
|
|
194
|
+
except Exception:
|
|
195
|
+
raise DeepLBaselineFailed("baseline.store.binding_invalid", retryable=False) from None
|
|
196
|
+
return _hash_bytes(_json_bytes(
|
|
197
|
+
payload, code="baseline.store.binding_invalid", maximum=MAX_RESPONSE_BYTES,
|
|
198
|
+
))
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _job_sha256(job_payload: Any, policy: Any) -> tuple[dict[str, Any], str]:
|
|
202
|
+
job = _validated_job(job_payload, policy)
|
|
203
|
+
return job, _hash_bytes(_json_bytes(
|
|
204
|
+
job, code="baseline.store.binding_invalid", maximum=MAX_RESPONSE_BYTES,
|
|
205
|
+
))
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _validate_acquisition(
|
|
209
|
+
acquisition: Any,
|
|
210
|
+
job_payload: Any,
|
|
211
|
+
policy: Any,
|
|
212
|
+
evidence_authority: Any,
|
|
213
|
+
) -> BaselineAcquisition:
|
|
214
|
+
if not isinstance(acquisition, BaselineAcquisition):
|
|
215
|
+
expected = tuple(field.name for field in fields(BaselineAcquisition))
|
|
216
|
+
try:
|
|
217
|
+
actual = tuple(field.name for field in fields(acquisition))
|
|
218
|
+
parameters = type(acquisition).__dataclass_params__
|
|
219
|
+
valid = (
|
|
220
|
+
is_dataclass(acquisition)
|
|
221
|
+
and not isinstance(acquisition, type)
|
|
222
|
+
and type(acquisition).__name__ == BaselineAcquisition.__name__
|
|
223
|
+
and parameters.frozen is True
|
|
224
|
+
and actual == expected
|
|
225
|
+
)
|
|
226
|
+
if not valid:
|
|
227
|
+
raise TypeError("incompatible baseline acquisition")
|
|
228
|
+
acquisition = BaselineAcquisition(**{
|
|
229
|
+
field: getattr(acquisition, field) for field in expected
|
|
230
|
+
})
|
|
231
|
+
except Exception:
|
|
232
|
+
raise DeepLBaselineFailed(
|
|
233
|
+
"baseline.store.acquisition_invalid", retryable=False,
|
|
234
|
+
) from None
|
|
235
|
+
job = _validated_job(job_payload, policy)
|
|
236
|
+
try:
|
|
237
|
+
artifact = _BENCHMARK._validate_baseline(
|
|
238
|
+
job, acquisition.artifact, policy, evidence_authority,
|
|
239
|
+
)
|
|
240
|
+
except Exception:
|
|
241
|
+
raise DeepLBaselineFailed("baseline.store.acquisition_invalid", retryable=False) from None
|
|
242
|
+
evidence = acquisition.evidence
|
|
243
|
+
if not isinstance(evidence, dict):
|
|
244
|
+
raise DeepLBaselineFailed("baseline.store.acquisition_invalid", retryable=False)
|
|
245
|
+
evidence_json = _canonical_json(
|
|
246
|
+
evidence, code="baseline.store.acquisition_invalid",
|
|
247
|
+
maximum=MAX_RESPONSE_BYTES,
|
|
248
|
+
)
|
|
249
|
+
evidence_sha256 = _hash_text(evidence_json)
|
|
250
|
+
provenance = artifact["provenance"]
|
|
251
|
+
method = provenance["method"]
|
|
252
|
+
common = (
|
|
253
|
+
provenance["evidence_sha256"] == evidence_sha256,
|
|
254
|
+
evidence.get("source_sha256") == job["source"]["sha256"],
|
|
255
|
+
evidence.get("target_locale") == job["target"]["locale"],
|
|
256
|
+
evidence.get("target_sha256") == artifact["target_sha256"],
|
|
257
|
+
)
|
|
258
|
+
if method == "official_api":
|
|
259
|
+
expected = {
|
|
260
|
+
"schema", "provider", "origin", "languages_response_sha256",
|
|
261
|
+
"request_sha256", "response_sha256", "source_sha256",
|
|
262
|
+
"source_locale", "source_language", "target_locale",
|
|
263
|
+
"target_language", "target_sha256", "model_type_used",
|
|
264
|
+
}
|
|
265
|
+
valid = (
|
|
266
|
+
set(evidence) == expected
|
|
267
|
+
and evidence.get("schema") == EVIDENCE_SCHEMA
|
|
268
|
+
and evidence.get("provider") == "DeepL"
|
|
269
|
+
and evidence.get("origin") in OFFICIAL_ORIGINS.values()
|
|
270
|
+
and evidence.get("source_locale") == job["source"]["locale"]
|
|
271
|
+
and provenance["evidence_id"] == "deepl-api:" + evidence_sha256
|
|
272
|
+
)
|
|
273
|
+
for field in (
|
|
274
|
+
"languages_response_sha256", "request_sha256", "response_sha256",
|
|
275
|
+
):
|
|
276
|
+
try:
|
|
277
|
+
_sha256(
|
|
278
|
+
evidence.get(field),
|
|
279
|
+
code="baseline.store.acquisition_invalid",
|
|
280
|
+
)
|
|
281
|
+
except DeepLBaselineFailed:
|
|
282
|
+
valid = False
|
|
283
|
+
for field in ("source_language", "target_language"):
|
|
284
|
+
if (
|
|
285
|
+
not isinstance(evidence.get(field), str)
|
|
286
|
+
or BCP47.fullmatch(evidence[field]) is None
|
|
287
|
+
):
|
|
288
|
+
valid = False
|
|
289
|
+
model = evidence.get("model_type_used")
|
|
290
|
+
if model is not None and (
|
|
291
|
+
not isinstance(model, str) or not model or len(model) > 128
|
|
292
|
+
):
|
|
293
|
+
valid = False
|
|
294
|
+
elif method == "lawful_fixture":
|
|
295
|
+
expected = {
|
|
296
|
+
"schema", "fixture_id", "fixture_revision", "supplier_id",
|
|
297
|
+
"rights_basis", "rights_evidence_sha256", "source_sha256",
|
|
298
|
+
"target_locale", "target_sha256",
|
|
299
|
+
}
|
|
300
|
+
valid = (
|
|
301
|
+
set(evidence) == expected
|
|
302
|
+
and evidence.get("schema") == FIXTURE_EVIDENCE_SCHEMA
|
|
303
|
+
and evidence.get("rights_basis") in RIGHTS_BASES
|
|
304
|
+
and provenance["evidence_id"] == "lawful-fixture:" + evidence_sha256
|
|
305
|
+
)
|
|
306
|
+
try:
|
|
307
|
+
for field in ("fixture_id", "fixture_revision", "supplier_id"):
|
|
308
|
+
_identifier(evidence.get(field), code="baseline.store.acquisition_invalid")
|
|
309
|
+
_sha256(
|
|
310
|
+
evidence.get("rights_evidence_sha256"),
|
|
311
|
+
code="baseline.store.acquisition_invalid",
|
|
312
|
+
)
|
|
313
|
+
except DeepLBaselineFailed:
|
|
314
|
+
valid = False
|
|
315
|
+
else:
|
|
316
|
+
valid = False
|
|
317
|
+
if not valid or not all(common):
|
|
318
|
+
raise DeepLBaselineFailed("baseline.store.acquisition_invalid", retryable=False)
|
|
319
|
+
return BaselineAcquisition(artifact=artifact, evidence=json.loads(evidence_json))
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
@contextmanager
|
|
323
|
+
def _transaction(connection: sqlite3.Connection) -> Iterator[None]:
|
|
324
|
+
if connection.in_transaction:
|
|
325
|
+
raise DeepLBaselineFailed("baseline.store.external_transaction", retryable=False)
|
|
326
|
+
try:
|
|
327
|
+
connection.execute("BEGIN IMMEDIATE")
|
|
328
|
+
yield
|
|
329
|
+
except Exception:
|
|
330
|
+
connection.rollback()
|
|
331
|
+
raise
|
|
332
|
+
else:
|
|
333
|
+
connection.commit()
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
class BaselineAcquisitionStore:
|
|
337
|
+
"""Durable exact-output recovery for one attested baseline acquisition."""
|
|
338
|
+
|
|
339
|
+
def __init__(self, connection: sqlite3.Connection):
|
|
340
|
+
if not isinstance(connection, sqlite3.Connection):
|
|
341
|
+
raise DeepLBaselineFailed(
|
|
342
|
+
"baseline.store.connection_invalid", retryable=False,
|
|
343
|
+
)
|
|
344
|
+
self.connection = connection
|
|
345
|
+
self.connection.row_factory = sqlite3.Row
|
|
346
|
+
self.connection.execute("PRAGMA busy_timeout = 5000")
|
|
347
|
+
with _transaction(self.connection):
|
|
348
|
+
self.connection.execute("""
|
|
349
|
+
CREATE TABLE IF NOT EXISTS benchmark_baseline_acquisitions (
|
|
350
|
+
acquisition_id TEXT PRIMARY KEY,
|
|
351
|
+
route_id TEXT NOT NULL,
|
|
352
|
+
policy_sha256 TEXT NOT NULL,
|
|
353
|
+
job_sha256 TEXT NOT NULL,
|
|
354
|
+
artifact_json TEXT NOT NULL,
|
|
355
|
+
artifact_sha256 TEXT NOT NULL,
|
|
356
|
+
evidence_json TEXT NOT NULL,
|
|
357
|
+
evidence_sha256 TEXT NOT NULL,
|
|
358
|
+
created_at REAL NOT NULL,
|
|
359
|
+
UNIQUE(route_id, policy_sha256, job_sha256)
|
|
360
|
+
)
|
|
361
|
+
""")
|
|
362
|
+
columns = tuple(
|
|
363
|
+
row[1] for row in self.connection.execute(
|
|
364
|
+
"PRAGMA table_info(benchmark_baseline_acquisitions)"
|
|
365
|
+
).fetchall()
|
|
366
|
+
)
|
|
367
|
+
if columns != STORE_COLUMNS:
|
|
368
|
+
raise DeepLBaselineFailed(
|
|
369
|
+
"baseline.store.schema_unsupported", retryable=False,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
@staticmethod
|
|
373
|
+
def _identity(
|
|
374
|
+
job_payload: Any, policy: Any, route_id: Any,
|
|
375
|
+
) -> tuple[str, str, str, str]:
|
|
376
|
+
route = _identifier(route_id, code="baseline.store.route_invalid")
|
|
377
|
+
_, job_sha256 = _job_sha256(job_payload, policy)
|
|
378
|
+
policy_sha256 = _policy_sha256(policy)
|
|
379
|
+
acquisition_id = "baseline-acquisition:" + _hash_bytes(_json_bytes(
|
|
380
|
+
{
|
|
381
|
+
"schema": STORE_SCHEMA,
|
|
382
|
+
"route_id": route,
|
|
383
|
+
"policy_sha256": policy_sha256,
|
|
384
|
+
"job_sha256": job_sha256,
|
|
385
|
+
},
|
|
386
|
+
code="baseline.store.binding_invalid", maximum=MAX_RESPONSE_BYTES,
|
|
387
|
+
))
|
|
388
|
+
return acquisition_id, route, policy_sha256, job_sha256
|
|
389
|
+
|
|
390
|
+
def load(
|
|
391
|
+
self, job_payload: Any, policy: Any, route_id: Any, *,
|
|
392
|
+
evidence_authority: Any,
|
|
393
|
+
) -> BaselineAcquisition | None:
|
|
394
|
+
identity = self._identity(job_payload, policy, route_id)
|
|
395
|
+
row = self.connection.execute("""
|
|
396
|
+
SELECT * FROM benchmark_baseline_acquisitions
|
|
397
|
+
WHERE acquisition_id = ?
|
|
398
|
+
""", (identity[0],)).fetchone()
|
|
399
|
+
if row is None:
|
|
400
|
+
return None
|
|
401
|
+
if (
|
|
402
|
+
tuple(row.keys()) != STORE_COLUMNS
|
|
403
|
+
or tuple(row[name] for name in STORE_COLUMNS[:4]) != identity
|
|
404
|
+
or isinstance(row["created_at"], bool)
|
|
405
|
+
or not isinstance(row["created_at"], (int, float))
|
|
406
|
+
or not math.isfinite(float(row["created_at"]))
|
|
407
|
+
or float(row["created_at"]) < 0
|
|
408
|
+
):
|
|
409
|
+
raise DeepLBaselineFailed("baseline.store.state_invalid", retryable=False)
|
|
410
|
+
artifact_json = row["artifact_json"]
|
|
411
|
+
evidence_json = row["evidence_json"]
|
|
412
|
+
if (
|
|
413
|
+
not isinstance(artifact_json, str)
|
|
414
|
+
or not isinstance(evidence_json, str)
|
|
415
|
+
or row["artifact_sha256"] != _hash_text(artifact_json)
|
|
416
|
+
or row["evidence_sha256"] != _hash_text(evidence_json)
|
|
417
|
+
):
|
|
418
|
+
raise DeepLBaselineFailed("baseline.store.state_invalid", retryable=False)
|
|
419
|
+
acquisition = BaselineAcquisition(
|
|
420
|
+
artifact=_parse_stored_json(artifact_json),
|
|
421
|
+
evidence=_parse_stored_json(evidence_json),
|
|
422
|
+
)
|
|
423
|
+
return _validate_acquisition(
|
|
424
|
+
acquisition, job_payload, policy, evidence_authority,
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
def save(
|
|
428
|
+
self, job_payload: Any, policy: Any, route_id: Any,
|
|
429
|
+
acquisition: Any, *, evidence_authority: Any, now: Any = None,
|
|
430
|
+
) -> BaselineAcquisition:
|
|
431
|
+
identity = self._identity(job_payload, policy, route_id)
|
|
432
|
+
verified = _validate_acquisition(
|
|
433
|
+
acquisition, job_payload, policy, evidence_authority,
|
|
434
|
+
)
|
|
435
|
+
artifact_json = _canonical_json(
|
|
436
|
+
verified.artifact, code="baseline.store.acquisition_invalid",
|
|
437
|
+
maximum=MAX_RESPONSE_BYTES,
|
|
438
|
+
)
|
|
439
|
+
evidence_json = _canonical_json(
|
|
440
|
+
verified.evidence, code="baseline.store.acquisition_invalid",
|
|
441
|
+
maximum=MAX_RESPONSE_BYTES,
|
|
442
|
+
)
|
|
443
|
+
values = identity + (
|
|
444
|
+
artifact_json, _hash_text(artifact_json), evidence_json,
|
|
445
|
+
_hash_text(evidence_json), _timestamp(now),
|
|
446
|
+
)
|
|
447
|
+
with _transaction(self.connection):
|
|
448
|
+
self.connection.execute("""
|
|
449
|
+
INSERT OR IGNORE INTO benchmark_baseline_acquisitions
|
|
450
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
451
|
+
""", values)
|
|
452
|
+
stored = self.load(
|
|
453
|
+
job_payload, policy, route_id,
|
|
454
|
+
evidence_authority=evidence_authority,
|
|
455
|
+
)
|
|
456
|
+
if stored != verified:
|
|
457
|
+
raise DeepLBaselineFailed("baseline.store.conflict", retryable=False)
|
|
458
|
+
return stored
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def resolve_baseline_acquisition(
|
|
462
|
+
store: BaselineAcquisitionStore,
|
|
463
|
+
job_payload: Any,
|
|
464
|
+
policy: Any,
|
|
465
|
+
route_id: Any,
|
|
466
|
+
acquire: Callable[[], BaselineAcquisition],
|
|
467
|
+
*,
|
|
468
|
+
evidence_authority: Any,
|
|
469
|
+
now: Any = None,
|
|
470
|
+
) -> BaselineAcquisition:
|
|
471
|
+
"""Reuse exact verified state, otherwise acquire once and persist before review."""
|
|
472
|
+
if not isinstance(store, BaselineAcquisitionStore):
|
|
473
|
+
raise TypeError("store must be BaselineAcquisitionStore")
|
|
474
|
+
if not callable(acquire):
|
|
475
|
+
raise TypeError("acquire must be callable")
|
|
476
|
+
cached = store.load(
|
|
477
|
+
job_payload, policy, route_id, evidence_authority=evidence_authority,
|
|
478
|
+
)
|
|
479
|
+
if cached is not None:
|
|
480
|
+
return cached
|
|
481
|
+
acquired = acquire()
|
|
482
|
+
return store.save(
|
|
483
|
+
job_payload, policy, route_id, acquired,
|
|
484
|
+
evidence_authority=evidence_authority, now=now,
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
@dataclass(frozen=True)
|
|
489
|
+
class _LanguageCapability:
|
|
490
|
+
code: str
|
|
491
|
+
source: bool
|
|
492
|
+
target: bool
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
def _pairs(items):
|
|
496
|
+
result = {}
|
|
497
|
+
for key, value in items:
|
|
498
|
+
if key in result:
|
|
499
|
+
raise ValueError("duplicate JSON key")
|
|
500
|
+
result[key] = value
|
|
501
|
+
return result
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def _constant(value):
|
|
505
|
+
raise ValueError("non-finite JSON number")
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def _json_bytes(value: Any, *, code: str, maximum: int) -> bytes:
|
|
509
|
+
try:
|
|
510
|
+
encoded = json.dumps(
|
|
511
|
+
value, ensure_ascii=False, allow_nan=False, sort_keys=True,
|
|
512
|
+
separators=(",", ":"),
|
|
513
|
+
).encode("utf-8")
|
|
514
|
+
except (TypeError, ValueError, RecursionError):
|
|
515
|
+
raise DeepLBaselineFailed(code, retryable=False) from None
|
|
516
|
+
if not encoded or len(encoded) > maximum:
|
|
517
|
+
raise DeepLBaselineFailed(code, retryable=False)
|
|
518
|
+
return encoded
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
def _hash_bytes(value: bytes) -> str:
|
|
522
|
+
return hashlib.sha256(value).hexdigest()
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def _hash_text(value: str) -> str:
|
|
526
|
+
return _hash_bytes(value.encode("utf-8"))
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
def _sha256(value: Any, *, code: str) -> str:
|
|
530
|
+
if not isinstance(value, str) or re.fullmatch(r"[0-9a-f]{64}", value) is None:
|
|
531
|
+
raise DeepLBaselineFailed(code, retryable=False)
|
|
532
|
+
return value
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def _identifier(value: Any, *, code: str) -> str:
|
|
536
|
+
if not isinstance(value, str) or _BENCHMARK.IDENTIFIER.fullmatch(value) is None:
|
|
537
|
+
raise DeepLBaselineFailed(code, retryable=False)
|
|
538
|
+
return value
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
def _response_headers(headers: Any) -> dict[str, str]:
|
|
542
|
+
if not isinstance(headers, tuple):
|
|
543
|
+
raise DeepLBaselineFailed("deepl.transport_invalid", retryable=True)
|
|
544
|
+
selected: dict[str, str] = {}
|
|
545
|
+
for item in headers:
|
|
546
|
+
if (
|
|
547
|
+
not isinstance(item, tuple)
|
|
548
|
+
or len(item) != 2
|
|
549
|
+
or not all(isinstance(part, str) for part in item)
|
|
550
|
+
):
|
|
551
|
+
raise DeepLBaselineFailed("deepl.transport_invalid", retryable=True)
|
|
552
|
+
name, value = item[0].lower(), item[1].strip()
|
|
553
|
+
if name in {"content-type", "content-length"}:
|
|
554
|
+
if name in selected:
|
|
555
|
+
raise DeepLBaselineFailed("deepl.response_headers", retryable=True)
|
|
556
|
+
selected[name] = value
|
|
557
|
+
return selected
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
def _parse_success(result: Any) -> tuple[Any, str]:
|
|
561
|
+
if (
|
|
562
|
+
not isinstance(result, HTTPResult)
|
|
563
|
+
or isinstance(result.status, bool)
|
|
564
|
+
or not isinstance(result.status, int)
|
|
565
|
+
):
|
|
566
|
+
raise DeepLBaselineFailed("deepl.transport_invalid", retryable=True)
|
|
567
|
+
status = result.status
|
|
568
|
+
if status != 200:
|
|
569
|
+
retryable = status == 429 or 500 <= status <= 599
|
|
570
|
+
if status == 403:
|
|
571
|
+
code = "deepl.authentication"
|
|
572
|
+
elif status == 456:
|
|
573
|
+
code = "deepl.quota_exceeded"
|
|
574
|
+
elif status == 429:
|
|
575
|
+
code = "deepl.rate_limited"
|
|
576
|
+
elif 500 <= status <= 599:
|
|
577
|
+
code = "deepl.unavailable"
|
|
578
|
+
else:
|
|
579
|
+
code = "deepl.http_error"
|
|
580
|
+
raise DeepLBaselineFailed(code, retryable=retryable)
|
|
581
|
+
headers = _response_headers(result.headers)
|
|
582
|
+
content_type = headers.get("content-type", "").lower()
|
|
583
|
+
if content_type.split(";", 1)[0].strip() != "application/json":
|
|
584
|
+
raise DeepLBaselineFailed("deepl.response_headers", retryable=True)
|
|
585
|
+
if not isinstance(result.body, bytes) or len(result.body) > MAX_RESPONSE_BYTES:
|
|
586
|
+
raise DeepLBaselineFailed("deepl.response_too_large", retryable=True)
|
|
587
|
+
length = headers.get("content-length")
|
|
588
|
+
if length:
|
|
589
|
+
if not length.isdigit() or int(length) != len(result.body):
|
|
590
|
+
raise DeepLBaselineFailed("deepl.response_headers", retryable=True)
|
|
591
|
+
if not result.body or result.body.startswith(b"\xef\xbb\xbf"):
|
|
592
|
+
raise DeepLBaselineFailed("deepl.response_invalid", retryable=True)
|
|
593
|
+
try:
|
|
594
|
+
value = json.loads(
|
|
595
|
+
result.body.decode("utf-8"), object_pairs_hook=_pairs,
|
|
596
|
+
parse_constant=_constant,
|
|
597
|
+
)
|
|
598
|
+
except (UnicodeDecodeError, ValueError, RecursionError):
|
|
599
|
+
raise DeepLBaselineFailed("deepl.response_invalid", retryable=True) from None
|
|
600
|
+
return value, _hash_bytes(result.body)
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def _validated_job(job_payload: Any, policy: Any) -> dict[str, Any]:
|
|
604
|
+
try:
|
|
605
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
606
|
+
job = _WORKER._validated_job(job_payload)
|
|
607
|
+
_BENCHMARK._validate_candidate_job_binding(job, policy)
|
|
608
|
+
if job["target"]["locale"] not in policy.required_locales:
|
|
609
|
+
raise DeepLBaselineFailed("deepl.locale_not_required", retryable=False)
|
|
610
|
+
_SUITE.case_for_job(job)
|
|
611
|
+
except DeepLBaselineFailed:
|
|
612
|
+
raise
|
|
613
|
+
except Exception:
|
|
614
|
+
raise DeepLBaselineFailed("deepl.job_invalid", retryable=False) from None
|
|
615
|
+
return job
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
class DeepLBaselineAdapter:
|
|
619
|
+
"""Acquire one current official-API baseline for one exact benchmark job."""
|
|
620
|
+
|
|
621
|
+
def __init__(
|
|
622
|
+
self,
|
|
623
|
+
account_tier: str,
|
|
624
|
+
api_key_provider: Callable[[], str],
|
|
625
|
+
*,
|
|
626
|
+
transport: HTTPTransport | None = None,
|
|
627
|
+
timeout: float = 30.0,
|
|
628
|
+
language_cache_seconds: float = 3600.0,
|
|
629
|
+
clock: Callable[[], float] = time.time,
|
|
630
|
+
operation_guard: Callable[[], Any] | None = None,
|
|
631
|
+
):
|
|
632
|
+
if account_tier not in OFFICIAL_ORIGINS:
|
|
633
|
+
raise ValueError("account_tier must be free or pro")
|
|
634
|
+
if not callable(api_key_provider):
|
|
635
|
+
raise TypeError("api_key_provider must be callable")
|
|
636
|
+
if (
|
|
637
|
+
isinstance(timeout, bool)
|
|
638
|
+
or not isinstance(timeout, (int, float))
|
|
639
|
+
or not math.isfinite(float(timeout))
|
|
640
|
+
or not 0 < float(timeout) <= 300
|
|
641
|
+
):
|
|
642
|
+
raise ValueError("timeout is outside the supported range")
|
|
643
|
+
if (
|
|
644
|
+
isinstance(language_cache_seconds, bool)
|
|
645
|
+
or not isinstance(language_cache_seconds, (int, float))
|
|
646
|
+
or not math.isfinite(float(language_cache_seconds))
|
|
647
|
+
or not 0 <= float(language_cache_seconds) <= 3600
|
|
648
|
+
):
|
|
649
|
+
raise ValueError("language_cache_seconds is outside the supported range")
|
|
650
|
+
if not callable(clock):
|
|
651
|
+
raise TypeError("clock must be callable")
|
|
652
|
+
if operation_guard is not None and not callable(operation_guard):
|
|
653
|
+
raise TypeError("operation_guard must be callable")
|
|
654
|
+
self._origin = OFFICIAL_ORIGINS[account_tier]
|
|
655
|
+
self._api_key_provider = api_key_provider
|
|
656
|
+
self._transport = URLTransport() if transport is None else transport
|
|
657
|
+
if not callable(getattr(self._transport, "request", None)):
|
|
658
|
+
raise TypeError("transport must provide request")
|
|
659
|
+
self._timeout = float(timeout)
|
|
660
|
+
self._cache_seconds = float(language_cache_seconds)
|
|
661
|
+
self._clock = clock
|
|
662
|
+
self._operation_guard = operation_guard
|
|
663
|
+
self._language_cache: tuple[
|
|
664
|
+
float, dict[str, _LanguageCapability], str
|
|
665
|
+
] | None = None
|
|
666
|
+
|
|
667
|
+
def __repr__(self) -> str:
|
|
668
|
+
return f"{type(self).__name__}(origin={self._origin!r})"
|
|
669
|
+
|
|
670
|
+
def _headers(self, *, content: bool) -> dict[str, str]:
|
|
671
|
+
try:
|
|
672
|
+
key = self._api_key_provider()
|
|
673
|
+
except Exception:
|
|
674
|
+
raise DeepLBaselineFailed("deepl.authentication", retryable=False) from None
|
|
675
|
+
if (
|
|
676
|
+
not isinstance(key, str)
|
|
677
|
+
or not key
|
|
678
|
+
or key != key.strip()
|
|
679
|
+
or not key.isascii()
|
|
680
|
+
or len(key.encode("ascii")) > MAX_AUTH_BYTES
|
|
681
|
+
or any(ord(character) < 33 or ord(character) == 127 for character in key)
|
|
682
|
+
):
|
|
683
|
+
raise DeepLBaselineFailed("deepl.authentication", retryable=False)
|
|
684
|
+
headers = {
|
|
685
|
+
"Accept": "application/json",
|
|
686
|
+
"Authorization": "DeepL-Auth-Key " + key,
|
|
687
|
+
"User-Agent": "translate-native-benchmark/1",
|
|
688
|
+
}
|
|
689
|
+
if content:
|
|
690
|
+
headers["Content-Type"] = "application/json"
|
|
691
|
+
return headers
|
|
692
|
+
|
|
693
|
+
def _request(
|
|
694
|
+
self, method: str, path: str, body: bytes | None,
|
|
695
|
+
) -> tuple[Any, str]:
|
|
696
|
+
if self._operation_guard is not None:
|
|
697
|
+
try:
|
|
698
|
+
self._operation_guard()
|
|
699
|
+
except Exception:
|
|
700
|
+
raise DeepLBaselineFailed(
|
|
701
|
+
"deepl.operation_guard_failed", retryable=True,
|
|
702
|
+
) from None
|
|
703
|
+
try:
|
|
704
|
+
result = self._transport.request(
|
|
705
|
+
method, self._origin + path,
|
|
706
|
+
self._headers(content=body is not None), body,
|
|
707
|
+
timeout=self._timeout,
|
|
708
|
+
)
|
|
709
|
+
except DeepLBaselineFailed:
|
|
710
|
+
raise
|
|
711
|
+
except Exception:
|
|
712
|
+
raise DeepLBaselineFailed("deepl.transport_failed", retryable=True) from None
|
|
713
|
+
return _parse_success(result)
|
|
714
|
+
|
|
715
|
+
def _languages(self) -> tuple[dict[str, _LanguageCapability], str]:
|
|
716
|
+
try:
|
|
717
|
+
now = float(self._clock())
|
|
718
|
+
except Exception:
|
|
719
|
+
raise DeepLBaselineFailed("deepl.clock_invalid", retryable=False) from None
|
|
720
|
+
if not math.isfinite(now) or now < 0:
|
|
721
|
+
raise DeepLBaselineFailed("deepl.clock_invalid", retryable=False)
|
|
722
|
+
if self._language_cache is not None:
|
|
723
|
+
cached_at, capabilities, response_sha256 = self._language_cache
|
|
724
|
+
if now - cached_at < self._cache_seconds:
|
|
725
|
+
return capabilities, response_sha256
|
|
726
|
+
payload, response_sha256 = self._request("GET", LANGUAGES_PATH, None)
|
|
727
|
+
if not isinstance(payload, list) or not 1 <= len(payload) <= MAX_LANGUAGES:
|
|
728
|
+
raise DeepLBaselineFailed("deepl.languages_invalid", retryable=True)
|
|
729
|
+
capabilities: dict[str, _LanguageCapability] = {}
|
|
730
|
+
for item in payload:
|
|
731
|
+
if not isinstance(item, dict):
|
|
732
|
+
raise DeepLBaselineFailed("deepl.languages_invalid", retryable=True)
|
|
733
|
+
code = item.get("lang")
|
|
734
|
+
source = item.get("usable_as_source")
|
|
735
|
+
target = item.get("usable_as_target")
|
|
736
|
+
if (
|
|
737
|
+
not isinstance(code, str)
|
|
738
|
+
or BCP47.fullmatch(code) is None
|
|
739
|
+
or not isinstance(source, bool)
|
|
740
|
+
or not isinstance(target, bool)
|
|
741
|
+
or item.get("status") != "stable"
|
|
742
|
+
):
|
|
743
|
+
raise DeepLBaselineFailed("deepl.languages_invalid", retryable=True)
|
|
744
|
+
normalized = code.lower()
|
|
745
|
+
if normalized in capabilities:
|
|
746
|
+
raise DeepLBaselineFailed("deepl.languages_invalid", retryable=True)
|
|
747
|
+
capabilities[normalized] = _LanguageCapability(code, source, target)
|
|
748
|
+
self._language_cache = (now, capabilities, response_sha256)
|
|
749
|
+
return capabilities, response_sha256
|
|
750
|
+
|
|
751
|
+
@staticmethod
|
|
752
|
+
def _resolve_language(
|
|
753
|
+
locale: Any,
|
|
754
|
+
capabilities: Mapping[str, _LanguageCapability],
|
|
755
|
+
*,
|
|
756
|
+
source: bool,
|
|
757
|
+
) -> str:
|
|
758
|
+
if not isinstance(locale, str) or BCP47.fullmatch(locale) is None:
|
|
759
|
+
raise DeepLBaselineFailed("deepl.locale_invalid", retryable=False)
|
|
760
|
+
normalized = locale.lower()
|
|
761
|
+
candidates = (normalized, normalized.split("-", 1)[0])
|
|
762
|
+
for candidate in dict.fromkeys(candidates):
|
|
763
|
+
capability = capabilities.get(candidate)
|
|
764
|
+
if capability is not None and (
|
|
765
|
+
capability.source if source else capability.target
|
|
766
|
+
):
|
|
767
|
+
return capability.code
|
|
768
|
+
role = "source" if source else "target"
|
|
769
|
+
raise DeepLBaselineFailed(
|
|
770
|
+
f"deepl.{role}_language_unsupported", retryable=False,
|
|
771
|
+
)
|
|
772
|
+
|
|
773
|
+
def acquire(
|
|
774
|
+
self,
|
|
775
|
+
job_payload: Any,
|
|
776
|
+
policy: Any,
|
|
777
|
+
*,
|
|
778
|
+
evidence_authority: Any,
|
|
779
|
+
) -> BaselineAcquisition:
|
|
780
|
+
job = _validated_job(job_payload, policy)
|
|
781
|
+
capabilities, capabilities_sha256 = self._languages()
|
|
782
|
+
source_code = self._resolve_language(
|
|
783
|
+
job["source"]["locale"], capabilities, source=True,
|
|
784
|
+
)
|
|
785
|
+
target_code = self._resolve_language(
|
|
786
|
+
job["target"]["locale"], capabilities, source=False,
|
|
787
|
+
)
|
|
788
|
+
if source_code.lower() == target_code.lower():
|
|
789
|
+
raise DeepLBaselineFailed("deepl.language_pair_invalid", retryable=False)
|
|
790
|
+
request_payload = {
|
|
791
|
+
"model_type": "prefer_quality_optimized",
|
|
792
|
+
"preserve_formatting": True,
|
|
793
|
+
"source_lang": source_code,
|
|
794
|
+
"target_lang": target_code,
|
|
795
|
+
"text": [job["source"]["text"]],
|
|
796
|
+
}
|
|
797
|
+
body = _json_bytes(
|
|
798
|
+
request_payload, code="deepl.request_too_large",
|
|
799
|
+
maximum=MAX_REQUEST_BYTES,
|
|
800
|
+
)
|
|
801
|
+
response, response_sha256 = self._request("POST", TRANSLATE_PATH, body)
|
|
802
|
+
if (
|
|
803
|
+
not isinstance(response, dict)
|
|
804
|
+
or set(response) != {"translations"}
|
|
805
|
+
or not isinstance(response["translations"], list)
|
|
806
|
+
or len(response["translations"]) != 1
|
|
807
|
+
or not isinstance(response["translations"][0], dict)
|
|
808
|
+
):
|
|
809
|
+
raise DeepLBaselineFailed("deepl.translation_invalid", retryable=True)
|
|
810
|
+
translated = response["translations"][0]
|
|
811
|
+
target_text = translated.get("text")
|
|
812
|
+
detected = translated.get("detected_source_language")
|
|
813
|
+
model = translated.get("model_type_used")
|
|
814
|
+
if (
|
|
815
|
+
not isinstance(target_text, str)
|
|
816
|
+
or not target_text.strip()
|
|
817
|
+
or "\x00" in target_text
|
|
818
|
+
or not unicodedata.is_normalized("NFC", target_text)
|
|
819
|
+
or len(target_text.encode("utf-8")) > _BENCHMARK.MAX_TEXT_BYTES
|
|
820
|
+
or (detected is not None and (
|
|
821
|
+
not isinstance(detected, str)
|
|
822
|
+
or detected.lower().split("-", 1)[0]
|
|
823
|
+
!= source_code.lower().split("-", 1)[0]
|
|
824
|
+
))
|
|
825
|
+
or (model is not None and (
|
|
826
|
+
not isinstance(model, str)
|
|
827
|
+
or not model
|
|
828
|
+
or len(model) > 128
|
|
829
|
+
))
|
|
830
|
+
):
|
|
831
|
+
raise DeepLBaselineFailed("deepl.translation_invalid", retryable=True)
|
|
832
|
+
evidence = {
|
|
833
|
+
"schema": EVIDENCE_SCHEMA,
|
|
834
|
+
"provider": "DeepL",
|
|
835
|
+
"origin": self._origin,
|
|
836
|
+
"languages_response_sha256": capabilities_sha256,
|
|
837
|
+
"request_sha256": _hash_bytes(body),
|
|
838
|
+
"response_sha256": response_sha256,
|
|
839
|
+
"source_sha256": job["source"]["sha256"],
|
|
840
|
+
"source_locale": job["source"]["locale"],
|
|
841
|
+
"source_language": source_code,
|
|
842
|
+
"target_locale": job["target"]["locale"],
|
|
843
|
+
"target_language": target_code,
|
|
844
|
+
"target_sha256": _hash_text(target_text),
|
|
845
|
+
"model_type_used": model,
|
|
846
|
+
}
|
|
847
|
+
evidence_bytes = _json_bytes(
|
|
848
|
+
evidence, code="deepl.evidence_invalid", maximum=MAX_RESPONSE_BYTES,
|
|
849
|
+
)
|
|
850
|
+
evidence_sha256 = _hash_bytes(evidence_bytes)
|
|
851
|
+
provenance = {
|
|
852
|
+
"schema": _BENCHMARK.BASELINE_PROVENANCE_SCHEMA,
|
|
853
|
+
"method": "official_api",
|
|
854
|
+
"evidence_id": "deepl-api:" + evidence_sha256,
|
|
855
|
+
"evidence_sha256": evidence_sha256,
|
|
856
|
+
}
|
|
857
|
+
try:
|
|
858
|
+
artifact = _BENCHMARK.create_baseline_artifact(
|
|
859
|
+
job_payload, target_text, policy, provenance,
|
|
860
|
+
evidence_authority=evidence_authority,
|
|
861
|
+
)
|
|
862
|
+
except Exception:
|
|
863
|
+
raise DeepLBaselineFailed("deepl.attestation_failed", retryable=False) from None
|
|
864
|
+
return BaselineAcquisition(artifact=artifact, evidence=evidence)
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
def create_lawful_fixture_acquisition(
|
|
868
|
+
job_payload: Any,
|
|
869
|
+
target_text: Any,
|
|
870
|
+
policy: Any,
|
|
871
|
+
fixture_evidence: Mapping[str, Any],
|
|
872
|
+
*,
|
|
873
|
+
evidence_authority: Any,
|
|
874
|
+
) -> BaselineAcquisition:
|
|
875
|
+
"""Attest a host-supplied fixed baseline with explicit rights evidence."""
|
|
876
|
+
job = _validated_job(job_payload, policy)
|
|
877
|
+
if (
|
|
878
|
+
not isinstance(target_text, str)
|
|
879
|
+
or not target_text.strip()
|
|
880
|
+
or "\x00" in target_text
|
|
881
|
+
or not unicodedata.is_normalized("NFC", target_text)
|
|
882
|
+
or len(target_text.encode("utf-8")) > _BENCHMARK.MAX_TEXT_BYTES
|
|
883
|
+
):
|
|
884
|
+
raise DeepLBaselineFailed("fixture.target_invalid", retryable=False)
|
|
885
|
+
expected = {
|
|
886
|
+
"schema", "fixture_id", "fixture_revision", "supplier_id",
|
|
887
|
+
"rights_basis", "rights_evidence_sha256", "source_sha256",
|
|
888
|
+
"target_locale", "target_sha256",
|
|
889
|
+
}
|
|
890
|
+
if not isinstance(fixture_evidence, Mapping) or set(fixture_evidence) != expected:
|
|
891
|
+
raise DeepLBaselineFailed("fixture.evidence_invalid", retryable=False)
|
|
892
|
+
evidence = dict(fixture_evidence)
|
|
893
|
+
_identifier(evidence.get("fixture_id"), code="fixture.evidence_invalid")
|
|
894
|
+
_identifier(evidence.get("fixture_revision"), code="fixture.evidence_invalid")
|
|
895
|
+
_identifier(evidence.get("supplier_id"), code="fixture.evidence_invalid")
|
|
896
|
+
_sha256(evidence.get("rights_evidence_sha256"), code="fixture.evidence_invalid")
|
|
897
|
+
if (
|
|
898
|
+
evidence.get("schema") != FIXTURE_EVIDENCE_SCHEMA
|
|
899
|
+
or evidence.get("rights_basis") not in RIGHTS_BASES
|
|
900
|
+
or evidence.get("source_sha256") != job["source"]["sha256"]
|
|
901
|
+
or evidence.get("target_locale") != job["target"]["locale"]
|
|
902
|
+
or evidence.get("target_sha256") != _hash_text(target_text)
|
|
903
|
+
):
|
|
904
|
+
raise DeepLBaselineFailed("fixture.evidence_invalid", retryable=False)
|
|
905
|
+
evidence_bytes = _json_bytes(
|
|
906
|
+
evidence, code="fixture.evidence_invalid", maximum=MAX_RESPONSE_BYTES,
|
|
907
|
+
)
|
|
908
|
+
evidence_sha256 = _hash_bytes(evidence_bytes)
|
|
909
|
+
provenance = {
|
|
910
|
+
"schema": _BENCHMARK.BASELINE_PROVENANCE_SCHEMA,
|
|
911
|
+
"method": "lawful_fixture",
|
|
912
|
+
"evidence_id": "lawful-fixture:" + evidence_sha256,
|
|
913
|
+
"evidence_sha256": evidence_sha256,
|
|
914
|
+
}
|
|
915
|
+
try:
|
|
916
|
+
artifact = _BENCHMARK.create_baseline_artifact(
|
|
917
|
+
job_payload, target_text, policy, provenance,
|
|
918
|
+
evidence_authority=evidence_authority,
|
|
919
|
+
)
|
|
920
|
+
except Exception:
|
|
921
|
+
raise DeepLBaselineFailed("fixture.attestation_failed", retryable=False) from None
|
|
922
|
+
return BaselineAcquisition(artifact=artifact, evidence=evidence)
|