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
package/standard-skills/translate-native/integrations/website_localization_benchmark_campaign.py
ADDED
|
@@ -0,0 +1,1772 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Durable, provider-neutral execution for a complete benchmark campaign.
|
|
3
|
+
|
|
4
|
+
The trusted host owns the SQLite connection and every external adapter. One
|
|
5
|
+
runner invocation claims at most one exact suite-case/locale pair. Stored
|
|
6
|
+
results contain no source, candidate, baseline, reference, or reviewer prose.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
import importlib.util
|
|
13
|
+
import json
|
|
14
|
+
import math
|
|
15
|
+
import re
|
|
16
|
+
import secrets
|
|
17
|
+
import sqlite3
|
|
18
|
+
import sys
|
|
19
|
+
import time
|
|
20
|
+
import unicodedata
|
|
21
|
+
from contextlib import contextmanager
|
|
22
|
+
from dataclasses import asdict, dataclass, fields, is_dataclass
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Any, Callable, Iterator, Mapping, Protocol
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
SCHEMA_VERSION = 3
|
|
28
|
+
HEALTH_SCHEMA = "blun.website-localization-benchmark-campaign-health.v1"
|
|
29
|
+
MAX_ATTEMPTS = 20
|
|
30
|
+
MAX_LEASE_SECONDS = 86_400.0
|
|
31
|
+
MAX_STALE_SECONDS = 31_536_000.0
|
|
32
|
+
MAX_RESULT_BYTES = 2_000_000
|
|
33
|
+
ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
|
|
34
|
+
HEALTH_REASON = re.compile(r"^[a-z][a-z0-9_.-]{0,255}$")
|
|
35
|
+
STATUSES = ("pending", "leased", "retry_wait", "succeeded", "failed")
|
|
36
|
+
CAMPAIGN_COLUMNS = (
|
|
37
|
+
"campaign_id", "policy_sha256", "suite_sha256", "work_count",
|
|
38
|
+
"created_at", "updated_at",
|
|
39
|
+
)
|
|
40
|
+
WORK_COLUMNS = (
|
|
41
|
+
"work_id", "campaign_id", "target_locale", "suite_case_key", "status",
|
|
42
|
+
"attempts", "max_attempts", "next_attempt_at", "lease_owner",
|
|
43
|
+
"lease_token", "lease_expires_at", "last_error_code",
|
|
44
|
+
"last_error_detail_hash", "result_json", "result_sha256", "created_at",
|
|
45
|
+
"updated_at",
|
|
46
|
+
)
|
|
47
|
+
REPORT_COLUMNS = (
|
|
48
|
+
"campaign_id", "policy_sha256", "results_sha256", "report_json",
|
|
49
|
+
"report_sha256", "created_at",
|
|
50
|
+
)
|
|
51
|
+
REPORT_STATE_COLUMNS = (
|
|
52
|
+
"campaign_id", "status", "attempts", "max_attempts", "next_attempt_at",
|
|
53
|
+
"lease_owner", "lease_token", "lease_expires_at", "last_error_code",
|
|
54
|
+
"last_error_detail_hash", "created_at", "updated_at",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _load_module(name: str, path: Path):
|
|
59
|
+
spec = importlib.util.spec_from_file_location(name, path)
|
|
60
|
+
if spec is None or spec.loader is None:
|
|
61
|
+
raise RuntimeError(f"cannot load benchmark campaign dependency: {path.name}")
|
|
62
|
+
module = importlib.util.module_from_spec(spec)
|
|
63
|
+
sys.modules[spec.name] = module
|
|
64
|
+
spec.loader.exec_module(module)
|
|
65
|
+
return module
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
_ROOT = Path(__file__).resolve().parents[1]
|
|
69
|
+
_BENCHMARK = _load_module(
|
|
70
|
+
"blun_website_localization_campaign_benchmark",
|
|
71
|
+
_ROOT / "integrations" / "website_localization_benchmark.py",
|
|
72
|
+
)
|
|
73
|
+
_PLANNER = _BENCHMARK._PLANNER
|
|
74
|
+
_SUITE = _BENCHMARK._SUITE
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class BenchmarkCampaignBlocked(RuntimeError):
|
|
78
|
+
"""Content-free campaign failure safe for operational status."""
|
|
79
|
+
|
|
80
|
+
def __init__(self, code: str):
|
|
81
|
+
if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
|
|
82
|
+
raise ValueError("campaign error code is invalid")
|
|
83
|
+
super().__init__(code)
|
|
84
|
+
self.code = code
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class BenchmarkCampaignDependencyFailed(RuntimeError):
|
|
88
|
+
"""Host-declared dependency failure with explicit retry ownership."""
|
|
89
|
+
|
|
90
|
+
def __init__(self, code: str, *, retryable: bool):
|
|
91
|
+
if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
|
|
92
|
+
raise ValueError("campaign dependency error code is invalid")
|
|
93
|
+
if not isinstance(retryable, bool):
|
|
94
|
+
raise ValueError("campaign dependency retryability must be boolean")
|
|
95
|
+
super().__init__(code)
|
|
96
|
+
self.code = code
|
|
97
|
+
self.retryable = retryable
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass(frozen=True)
|
|
101
|
+
class ClaimedBenchmarkCase:
|
|
102
|
+
work_id: str
|
|
103
|
+
campaign_id: str
|
|
104
|
+
target_locale: str
|
|
105
|
+
suite_case_key: str
|
|
106
|
+
job_payload: dict[str, Any]
|
|
107
|
+
attempt: int
|
|
108
|
+
max_attempts: int
|
|
109
|
+
lease_owner: str
|
|
110
|
+
lease_token: str
|
|
111
|
+
lease_expires_at: float
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass(frozen=True)
|
|
115
|
+
class BenchmarkCaseInputs:
|
|
116
|
+
candidate_result: Mapping[str, Any]
|
|
117
|
+
baseline_artifact: Mapping[str, Any]
|
|
118
|
+
assets: Any
|
|
119
|
+
native_reference_artifact: Mapping[str, Any]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@dataclass(frozen=True)
|
|
123
|
+
class BenchmarkCampaignOutcome:
|
|
124
|
+
work_id: str
|
|
125
|
+
target_locale: str
|
|
126
|
+
suite_case_key: str
|
|
127
|
+
status: str
|
|
128
|
+
attempt: int
|
|
129
|
+
max_attempts: int
|
|
130
|
+
next_attempt_at: float
|
|
131
|
+
error_code: str | None
|
|
132
|
+
error_detail_hash: str | None
|
|
133
|
+
result_sha256: str | None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@dataclass(frozen=True)
|
|
137
|
+
class ClaimedBenchmarkReport:
|
|
138
|
+
campaign_id: str
|
|
139
|
+
attempt: int
|
|
140
|
+
max_attempts: int
|
|
141
|
+
lease_owner: str
|
|
142
|
+
lease_token: str
|
|
143
|
+
lease_expires_at: float
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@dataclass(frozen=True)
|
|
147
|
+
class BenchmarkReportFinalizationOutcome:
|
|
148
|
+
campaign_id: str
|
|
149
|
+
status: str
|
|
150
|
+
attempt: int
|
|
151
|
+
max_attempts: int
|
|
152
|
+
next_attempt_at: float
|
|
153
|
+
error_code: str | None
|
|
154
|
+
error_detail_hash: str | None
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@dataclass(frozen=True)
|
|
158
|
+
class BenchmarkCampaignHealth:
|
|
159
|
+
campaign_id: str
|
|
160
|
+
status: str
|
|
161
|
+
reasons: tuple[str, ...]
|
|
162
|
+
counts: tuple[tuple[str, int], ...]
|
|
163
|
+
work_count: int
|
|
164
|
+
report_ready: bool
|
|
165
|
+
last_progress_at: float | None
|
|
166
|
+
|
|
167
|
+
def as_payload(self) -> dict[str, Any]:
|
|
168
|
+
return {
|
|
169
|
+
"schema": HEALTH_SCHEMA,
|
|
170
|
+
"campaign_id": self.campaign_id,
|
|
171
|
+
"status": self.status,
|
|
172
|
+
"reasons": list(self.reasons),
|
|
173
|
+
"counts": dict(self.counts),
|
|
174
|
+
"work_count": self.work_count,
|
|
175
|
+
"report_ready": self.report_ready,
|
|
176
|
+
"last_progress_at": self.last_progress_at,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class BenchmarkInputResolver(Protocol):
|
|
181
|
+
def __call__(self, job_payload: dict[str, Any]) -> BenchmarkCaseInputs: ...
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class GuardedBenchmarkInputResolver(Protocol):
|
|
185
|
+
def resolve_with_operation_guard(
|
|
186
|
+
self,
|
|
187
|
+
job_payload: dict[str, Any],
|
|
188
|
+
operation_guard: Callable[[], None],
|
|
189
|
+
) -> BenchmarkCaseInputs: ...
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _benchmark_case_inputs(value: Any) -> BenchmarkCaseInputs:
|
|
193
|
+
if isinstance(value, BenchmarkCaseInputs):
|
|
194
|
+
return value
|
|
195
|
+
expected = tuple(field.name for field in fields(BenchmarkCaseInputs))
|
|
196
|
+
try:
|
|
197
|
+
actual = tuple(field.name for field in fields(value))
|
|
198
|
+
parameters = type(value).__dataclass_params__
|
|
199
|
+
valid = (
|
|
200
|
+
is_dataclass(value)
|
|
201
|
+
and not isinstance(value, type)
|
|
202
|
+
and type(value).__name__ == BenchmarkCaseInputs.__name__
|
|
203
|
+
and parameters.frozen is True
|
|
204
|
+
and actual == expected
|
|
205
|
+
)
|
|
206
|
+
if not valid:
|
|
207
|
+
raise TypeError("incompatible benchmark inputs")
|
|
208
|
+
return BenchmarkCaseInputs(**{
|
|
209
|
+
field: getattr(value, field) for field in expected
|
|
210
|
+
})
|
|
211
|
+
except Exception:
|
|
212
|
+
raise BenchmarkCampaignDependencyFailed(
|
|
213
|
+
"inputs_invalid", retryable=False,
|
|
214
|
+
) from None
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _canonical_json(value: Any) -> str:
|
|
218
|
+
try:
|
|
219
|
+
return json.dumps(
|
|
220
|
+
value, ensure_ascii=False, allow_nan=False, sort_keys=True,
|
|
221
|
+
separators=(",", ":"),
|
|
222
|
+
)
|
|
223
|
+
except (TypeError, ValueError) as error:
|
|
224
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.input_invalid") from error
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _hash_json(value: Any) -> str:
|
|
228
|
+
return hashlib.sha256(_canonical_json(value).encode("utf-8")).hexdigest()
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def _hash_text(value: str) -> str:
|
|
232
|
+
return hashlib.sha256(value.encode("utf-8")).hexdigest()
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _results_sha256(result_sha256s: Any) -> str:
|
|
236
|
+
if not isinstance(result_sha256s, (tuple, list)) or any(
|
|
237
|
+
not isinstance(value, str)
|
|
238
|
+
or re.fullmatch(r"[0-9a-f]{64}", value) is None
|
|
239
|
+
for value in result_sha256s
|
|
240
|
+
):
|
|
241
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.state_invalid")
|
|
242
|
+
return _hash_json(list(result_sha256s))
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _timestamp(value: Any = None) -> float:
|
|
246
|
+
value = time.time() if value is None else value
|
|
247
|
+
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
|
248
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.time_invalid")
|
|
249
|
+
value = float(value)
|
|
250
|
+
if value < 0 or not math.isfinite(value):
|
|
251
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.time_invalid")
|
|
252
|
+
return value
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _assert_policy_current(policy: Any, now: float) -> None:
|
|
256
|
+
if now > policy.valid_until:
|
|
257
|
+
raise BenchmarkCampaignBlocked(
|
|
258
|
+
"benchmark.campaign.validity_expired",
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def _duration(value: Any, *, allow_zero: bool = False) -> float:
|
|
263
|
+
value = _timestamp(value)
|
|
264
|
+
if (value < 0 if allow_zero else value <= 0) or value > MAX_LEASE_SECONDS:
|
|
265
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.duration_invalid")
|
|
266
|
+
return value
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _identifier(value: Any) -> str:
|
|
270
|
+
if (
|
|
271
|
+
not isinstance(value, str) or not value or value != value.strip()
|
|
272
|
+
or len(value) > 256 or "\x00" in value
|
|
273
|
+
or not unicodedata.is_normalized("NFC", value)
|
|
274
|
+
):
|
|
275
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.identity_invalid")
|
|
276
|
+
return value
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _policy_binding(policy: Any) -> dict[str, Any]:
|
|
280
|
+
validated = _BENCHMARK._validate_policy(policy)
|
|
281
|
+
return json.loads(_canonical_json(asdict(validated)))
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _campaign_identity(policy: Any) -> tuple[str, str]:
|
|
285
|
+
policy_sha256 = _hash_json(_policy_binding(policy))
|
|
286
|
+
return "benchmark-campaign-" + policy_sha256, policy_sha256
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def _expected_work(policy: Any) -> tuple[tuple[str, str, str], ...]:
|
|
290
|
+
campaign_id, policy_sha256 = _campaign_identity(policy)
|
|
291
|
+
return tuple(
|
|
292
|
+
(
|
|
293
|
+
"benchmark-work-" + _hash_json({
|
|
294
|
+
"campaign_id": campaign_id,
|
|
295
|
+
"policy_sha256": policy_sha256,
|
|
296
|
+
"suite_sha256": policy.suite_sha256,
|
|
297
|
+
"target_locale": locale,
|
|
298
|
+
"suite_case_key": case["key"],
|
|
299
|
+
}),
|
|
300
|
+
locale,
|
|
301
|
+
case["key"],
|
|
302
|
+
)
|
|
303
|
+
for locale in policy.required_locales
|
|
304
|
+
for case in _SUITE.manifest()["cases"]
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def _job_payload(policy: Any, locale: str, case_key: str) -> dict[str, Any]:
|
|
309
|
+
cases = {item["key"]: item for item in _SUITE.manifest()["cases"]}
|
|
310
|
+
case = cases.get(case_key)
|
|
311
|
+
if case is None:
|
|
312
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.state_invalid")
|
|
313
|
+
try:
|
|
314
|
+
return _PLANNER.plan_website_localization(
|
|
315
|
+
source_id=case["source_id"],
|
|
316
|
+
source_revision=case["source_revision"],
|
|
317
|
+
source_text=case["source_text"],
|
|
318
|
+
source_locale=case["source_locale"],
|
|
319
|
+
content_type=case["content_type"],
|
|
320
|
+
glossary_version=policy.candidate_glossary_version,
|
|
321
|
+
policy_version=policy.candidate_policy_version,
|
|
322
|
+
provider_id=policy.candidate_provider_id,
|
|
323
|
+
model_id=policy.candidate_model_id,
|
|
324
|
+
model_version=policy.candidate_model_version,
|
|
325
|
+
software_version=policy.candidate_software_version,
|
|
326
|
+
target_locales=[locale],
|
|
327
|
+
).jobs[0].as_payload()
|
|
328
|
+
except Exception:
|
|
329
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.state_invalid") from None
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
@contextmanager
|
|
333
|
+
def _transaction(connection: sqlite3.Connection) -> Iterator[None]:
|
|
334
|
+
if connection.in_transaction:
|
|
335
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.external_transaction")
|
|
336
|
+
try:
|
|
337
|
+
connection.execute("BEGIN IMMEDIATE")
|
|
338
|
+
yield
|
|
339
|
+
except Exception:
|
|
340
|
+
connection.rollback()
|
|
341
|
+
raise
|
|
342
|
+
else:
|
|
343
|
+
connection.commit()
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
class BenchmarkCampaignStore:
|
|
347
|
+
"""Dedicated SQLite campaign queue with exact policy and suite binding."""
|
|
348
|
+
|
|
349
|
+
def __init__(self, connection: sqlite3.Connection):
|
|
350
|
+
if not isinstance(connection, sqlite3.Connection):
|
|
351
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.connection_invalid")
|
|
352
|
+
self.connection = connection
|
|
353
|
+
self.connection.row_factory = sqlite3.Row
|
|
354
|
+
self.connection.execute("PRAGMA foreign_keys = ON")
|
|
355
|
+
self.connection.execute("PRAGMA busy_timeout = 5000")
|
|
356
|
+
version = int(self.connection.execute("PRAGMA user_version").fetchone()[0])
|
|
357
|
+
if version not in {0, 1, 2, SCHEMA_VERSION}:
|
|
358
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.schema_unsupported")
|
|
359
|
+
if version == 0:
|
|
360
|
+
self._create_schema()
|
|
361
|
+
elif version == 1:
|
|
362
|
+
self._migrate_v1()
|
|
363
|
+
elif version == 2:
|
|
364
|
+
self._migrate_v2()
|
|
365
|
+
self._verify_schema()
|
|
366
|
+
|
|
367
|
+
def _create_schema(self) -> None:
|
|
368
|
+
with _transaction(self.connection):
|
|
369
|
+
self.connection.execute("""
|
|
370
|
+
CREATE TABLE benchmark_campaigns (
|
|
371
|
+
campaign_id TEXT PRIMARY KEY,
|
|
372
|
+
policy_sha256 TEXT NOT NULL,
|
|
373
|
+
suite_sha256 TEXT NOT NULL,
|
|
374
|
+
work_count INTEGER NOT NULL CHECK (work_count > 0),
|
|
375
|
+
created_at REAL NOT NULL,
|
|
376
|
+
updated_at REAL NOT NULL
|
|
377
|
+
)
|
|
378
|
+
""")
|
|
379
|
+
self.connection.execute(f"""
|
|
380
|
+
CREATE TABLE benchmark_campaign_work (
|
|
381
|
+
work_id TEXT PRIMARY KEY,
|
|
382
|
+
campaign_id TEXT NOT NULL,
|
|
383
|
+
target_locale TEXT NOT NULL,
|
|
384
|
+
suite_case_key TEXT NOT NULL,
|
|
385
|
+
status TEXT NOT NULL CHECK (status IN {STATUSES}),
|
|
386
|
+
attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts >= 0),
|
|
387
|
+
max_attempts INTEGER NOT NULL CHECK (max_attempts BETWEEN 1 AND {MAX_ATTEMPTS}),
|
|
388
|
+
next_attempt_at REAL NOT NULL,
|
|
389
|
+
lease_owner TEXT,
|
|
390
|
+
lease_token TEXT,
|
|
391
|
+
lease_expires_at REAL,
|
|
392
|
+
last_error_code TEXT,
|
|
393
|
+
last_error_detail_hash TEXT,
|
|
394
|
+
result_json TEXT,
|
|
395
|
+
result_sha256 TEXT,
|
|
396
|
+
created_at REAL NOT NULL,
|
|
397
|
+
updated_at REAL NOT NULL,
|
|
398
|
+
UNIQUE (campaign_id, target_locale, suite_case_key),
|
|
399
|
+
FOREIGN KEY (campaign_id) REFERENCES benchmark_campaigns (campaign_id)
|
|
400
|
+
)
|
|
401
|
+
""")
|
|
402
|
+
self.connection.execute("""
|
|
403
|
+
CREATE INDEX benchmark_campaign_ready
|
|
404
|
+
ON benchmark_campaign_work
|
|
405
|
+
(campaign_id, status, next_attempt_at, target_locale, suite_case_key)
|
|
406
|
+
""")
|
|
407
|
+
self.connection.execute("""
|
|
408
|
+
CREATE TABLE benchmark_campaign_reports (
|
|
409
|
+
campaign_id TEXT PRIMARY KEY,
|
|
410
|
+
policy_sha256 TEXT NOT NULL,
|
|
411
|
+
results_sha256 TEXT NOT NULL,
|
|
412
|
+
report_json TEXT NOT NULL,
|
|
413
|
+
report_sha256 TEXT NOT NULL,
|
|
414
|
+
created_at REAL NOT NULL,
|
|
415
|
+
FOREIGN KEY (campaign_id) REFERENCES benchmark_campaigns (campaign_id)
|
|
416
|
+
)
|
|
417
|
+
""")
|
|
418
|
+
self._create_report_state_table()
|
|
419
|
+
self._populate_report_state()
|
|
420
|
+
self.connection.execute(f"PRAGMA user_version = {SCHEMA_VERSION}")
|
|
421
|
+
|
|
422
|
+
def _migrate_v1(self) -> None:
|
|
423
|
+
self._verify_legacy_schema()
|
|
424
|
+
with _transaction(self.connection):
|
|
425
|
+
self.connection.execute("""
|
|
426
|
+
CREATE TABLE benchmark_campaign_reports (
|
|
427
|
+
campaign_id TEXT PRIMARY KEY,
|
|
428
|
+
policy_sha256 TEXT NOT NULL,
|
|
429
|
+
results_sha256 TEXT NOT NULL,
|
|
430
|
+
report_json TEXT NOT NULL,
|
|
431
|
+
report_sha256 TEXT NOT NULL,
|
|
432
|
+
created_at REAL NOT NULL,
|
|
433
|
+
FOREIGN KEY (campaign_id) REFERENCES benchmark_campaigns (campaign_id)
|
|
434
|
+
)
|
|
435
|
+
""")
|
|
436
|
+
self._create_report_state_table()
|
|
437
|
+
self._populate_report_state()
|
|
438
|
+
self.connection.execute(f"PRAGMA user_version = {SCHEMA_VERSION}")
|
|
439
|
+
|
|
440
|
+
def _migrate_v2(self) -> None:
|
|
441
|
+
self._verify_v2_schema()
|
|
442
|
+
with _transaction(self.connection):
|
|
443
|
+
self._create_report_state_table()
|
|
444
|
+
self._populate_report_state()
|
|
445
|
+
self.connection.execute(f"PRAGMA user_version = {SCHEMA_VERSION}")
|
|
446
|
+
|
|
447
|
+
def _create_report_state_table(self) -> None:
|
|
448
|
+
self.connection.execute(f"""
|
|
449
|
+
CREATE TABLE benchmark_campaign_report_state (
|
|
450
|
+
campaign_id TEXT PRIMARY KEY,
|
|
451
|
+
status TEXT NOT NULL CHECK (status IN {STATUSES}),
|
|
452
|
+
attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts >= 0),
|
|
453
|
+
max_attempts INTEGER NOT NULL CHECK (
|
|
454
|
+
max_attempts BETWEEN 1 AND {MAX_ATTEMPTS}
|
|
455
|
+
),
|
|
456
|
+
next_attempt_at REAL NOT NULL,
|
|
457
|
+
lease_owner TEXT,
|
|
458
|
+
lease_token TEXT,
|
|
459
|
+
lease_expires_at REAL,
|
|
460
|
+
last_error_code TEXT,
|
|
461
|
+
last_error_detail_hash TEXT,
|
|
462
|
+
created_at REAL NOT NULL,
|
|
463
|
+
updated_at REAL NOT NULL,
|
|
464
|
+
FOREIGN KEY (campaign_id) REFERENCES benchmark_campaigns (campaign_id)
|
|
465
|
+
)
|
|
466
|
+
""")
|
|
467
|
+
|
|
468
|
+
def _populate_report_state(self) -> None:
|
|
469
|
+
self.connection.execute("""
|
|
470
|
+
INSERT INTO benchmark_campaign_report_state (
|
|
471
|
+
campaign_id, status, attempts, max_attempts, next_attempt_at,
|
|
472
|
+
created_at, updated_at
|
|
473
|
+
)
|
|
474
|
+
SELECT c.campaign_id,
|
|
475
|
+
CASE WHEN r.campaign_id IS NULL THEN 'pending' ELSE 'succeeded' END,
|
|
476
|
+
CASE WHEN r.campaign_id IS NULL THEN 0 ELSE 1 END,
|
|
477
|
+
MIN(w.max_attempts), c.updated_at, c.created_at, c.updated_at
|
|
478
|
+
FROM benchmark_campaigns AS c
|
|
479
|
+
JOIN benchmark_campaign_work AS w ON w.campaign_id = c.campaign_id
|
|
480
|
+
LEFT JOIN benchmark_campaign_reports AS r
|
|
481
|
+
ON r.campaign_id = c.campaign_id
|
|
482
|
+
GROUP BY c.campaign_id
|
|
483
|
+
""")
|
|
484
|
+
|
|
485
|
+
def _verify_legacy_schema(self) -> None:
|
|
486
|
+
campaign = tuple(
|
|
487
|
+
row["name"] for row in
|
|
488
|
+
self.connection.execute("PRAGMA table_info(benchmark_campaigns)")
|
|
489
|
+
)
|
|
490
|
+
work = tuple(
|
|
491
|
+
row["name"] for row in
|
|
492
|
+
self.connection.execute("PRAGMA table_info(benchmark_campaign_work)")
|
|
493
|
+
)
|
|
494
|
+
if campaign != CAMPAIGN_COLUMNS or work != WORK_COLUMNS:
|
|
495
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.schema_invalid")
|
|
496
|
+
|
|
497
|
+
def _verify_v2_schema(self) -> None:
|
|
498
|
+
self._verify_legacy_schema()
|
|
499
|
+
report = tuple(
|
|
500
|
+
row["name"] for row in
|
|
501
|
+
self.connection.execute("PRAGMA table_info(benchmark_campaign_reports)")
|
|
502
|
+
)
|
|
503
|
+
if report != REPORT_COLUMNS:
|
|
504
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.schema_invalid")
|
|
505
|
+
|
|
506
|
+
def _verify_schema(self) -> None:
|
|
507
|
+
self._verify_legacy_schema()
|
|
508
|
+
self._verify_v2_schema()
|
|
509
|
+
report_state = tuple(
|
|
510
|
+
row["name"] for row in self.connection.execute(
|
|
511
|
+
"PRAGMA table_info(benchmark_campaign_report_state)"
|
|
512
|
+
)
|
|
513
|
+
)
|
|
514
|
+
if report_state != REPORT_STATE_COLUMNS:
|
|
515
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.schema_invalid")
|
|
516
|
+
|
|
517
|
+
def create(self, policy: Any, *, max_attempts: int = 3, now: Any = None) -> str:
|
|
518
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
519
|
+
if isinstance(max_attempts, bool) or not isinstance(max_attempts, int):
|
|
520
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.attempts_invalid")
|
|
521
|
+
if not 1 <= max_attempts <= MAX_ATTEMPTS:
|
|
522
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.attempts_invalid")
|
|
523
|
+
now = _timestamp(now)
|
|
524
|
+
_assert_policy_current(policy, now)
|
|
525
|
+
campaign_id, policy_sha256 = _campaign_identity(policy)
|
|
526
|
+
expected = _expected_work(policy)
|
|
527
|
+
with _transaction(self.connection):
|
|
528
|
+
row = self.connection.execute(
|
|
529
|
+
"SELECT * FROM benchmark_campaigns WHERE campaign_id = ?",
|
|
530
|
+
(campaign_id,),
|
|
531
|
+
).fetchone()
|
|
532
|
+
if row is None:
|
|
533
|
+
self.connection.execute("""
|
|
534
|
+
INSERT INTO benchmark_campaigns (
|
|
535
|
+
campaign_id, policy_sha256, suite_sha256, work_count,
|
|
536
|
+
created_at, updated_at
|
|
537
|
+
) VALUES (?, ?, ?, ?, ?, ?)
|
|
538
|
+
""", (
|
|
539
|
+
campaign_id, policy_sha256, policy.suite_sha256,
|
|
540
|
+
len(expected), now, now,
|
|
541
|
+
))
|
|
542
|
+
self.connection.executemany("""
|
|
543
|
+
INSERT INTO benchmark_campaign_work (
|
|
544
|
+
work_id, campaign_id, target_locale, suite_case_key,
|
|
545
|
+
status, attempts, max_attempts, next_attempt_at,
|
|
546
|
+
created_at, updated_at
|
|
547
|
+
) VALUES (?, ?, ?, ?, 'pending', 0, ?, ?, ?, ?)
|
|
548
|
+
""", (
|
|
549
|
+
(work_id, campaign_id, locale, case_key, max_attempts, now, now, now)
|
|
550
|
+
for work_id, locale, case_key in expected
|
|
551
|
+
))
|
|
552
|
+
self.connection.execute("""
|
|
553
|
+
INSERT INTO benchmark_campaign_report_state (
|
|
554
|
+
campaign_id, status, attempts, max_attempts,
|
|
555
|
+
next_attempt_at, created_at, updated_at
|
|
556
|
+
) VALUES (?, 'pending', 0, ?, ?, ?, ?)
|
|
557
|
+
""", (campaign_id, max_attempts, now, now, now))
|
|
558
|
+
self._verify_binding_locked(policy, campaign_id)
|
|
559
|
+
configured = self.connection.execute("""
|
|
560
|
+
SELECT MIN(max_attempts) AS minimum, MAX(max_attempts) AS maximum
|
|
561
|
+
FROM benchmark_campaign_work WHERE campaign_id = ?
|
|
562
|
+
""", (campaign_id,)).fetchone()
|
|
563
|
+
if (
|
|
564
|
+
configured["minimum"] != max_attempts
|
|
565
|
+
or configured["maximum"] != max_attempts
|
|
566
|
+
):
|
|
567
|
+
raise BenchmarkCampaignBlocked(
|
|
568
|
+
"benchmark.campaign.attempts_mismatch",
|
|
569
|
+
)
|
|
570
|
+
return campaign_id
|
|
571
|
+
|
|
572
|
+
def _verify_binding_locked(self, policy: Any, campaign_id: str) -> None:
|
|
573
|
+
expected_id, policy_sha256 = _campaign_identity(policy)
|
|
574
|
+
if campaign_id != expected_id:
|
|
575
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.policy_mismatch")
|
|
576
|
+
campaign = self.connection.execute(
|
|
577
|
+
"SELECT * FROM benchmark_campaigns WHERE campaign_id = ?",
|
|
578
|
+
(campaign_id,),
|
|
579
|
+
).fetchone()
|
|
580
|
+
if campaign is None or (
|
|
581
|
+
campaign["policy_sha256"] != policy_sha256
|
|
582
|
+
or campaign["suite_sha256"] != policy.suite_sha256
|
|
583
|
+
or campaign["work_count"] != len(_expected_work(policy))
|
|
584
|
+
):
|
|
585
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.state_invalid")
|
|
586
|
+
observed = {
|
|
587
|
+
(row["work_id"], row["target_locale"], row["suite_case_key"])
|
|
588
|
+
for row in self.connection.execute("""
|
|
589
|
+
SELECT work_id, target_locale, suite_case_key
|
|
590
|
+
FROM benchmark_campaign_work WHERE campaign_id = ?
|
|
591
|
+
""", (campaign_id,))
|
|
592
|
+
}
|
|
593
|
+
if observed != set(_expected_work(policy)):
|
|
594
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.state_invalid")
|
|
595
|
+
|
|
596
|
+
def claim(
|
|
597
|
+
self, policy: Any, campaign_id: str, worker_id: Any, *,
|
|
598
|
+
now: Any = None, lease_seconds: Any = 300,
|
|
599
|
+
) -> ClaimedBenchmarkCase | None:
|
|
600
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
601
|
+
worker_id = _identifier(worker_id)
|
|
602
|
+
now = _timestamp(now)
|
|
603
|
+
_assert_policy_current(policy, now)
|
|
604
|
+
lease_seconds = _duration(lease_seconds)
|
|
605
|
+
with _transaction(self.connection):
|
|
606
|
+
self._verify_binding_locked(policy, campaign_id)
|
|
607
|
+
expired = self.connection.execute("""
|
|
608
|
+
SELECT work_id, attempts, max_attempts
|
|
609
|
+
FROM benchmark_campaign_work
|
|
610
|
+
WHERE campaign_id = ? AND status = 'leased'
|
|
611
|
+
AND lease_expires_at <= ?
|
|
612
|
+
""", (campaign_id, now)).fetchall()
|
|
613
|
+
for row in expired:
|
|
614
|
+
terminal = row["attempts"] >= row["max_attempts"]
|
|
615
|
+
self.connection.execute("""
|
|
616
|
+
UPDATE benchmark_campaign_work
|
|
617
|
+
SET status = ?, next_attempt_at = ?, lease_owner = NULL,
|
|
618
|
+
lease_token = NULL, lease_expires_at = NULL,
|
|
619
|
+
last_error_code = 'benchmark.campaign.lease_expired',
|
|
620
|
+
updated_at = ? WHERE work_id = ?
|
|
621
|
+
""", (
|
|
622
|
+
"failed" if terminal else "retry_wait", now, now,
|
|
623
|
+
row["work_id"],
|
|
624
|
+
))
|
|
625
|
+
row = self.connection.execute("""
|
|
626
|
+
SELECT * FROM benchmark_campaign_work
|
|
627
|
+
WHERE campaign_id = ?
|
|
628
|
+
AND status IN ('pending', 'retry_wait')
|
|
629
|
+
AND next_attempt_at <= ? AND attempts < max_attempts
|
|
630
|
+
ORDER BY target_locale, suite_case_key LIMIT 1
|
|
631
|
+
""", (campaign_id, now)).fetchone()
|
|
632
|
+
if row is None:
|
|
633
|
+
return None
|
|
634
|
+
token = secrets.token_urlsafe(32)
|
|
635
|
+
attempt = row["attempts"] + 1
|
|
636
|
+
expires = now + lease_seconds
|
|
637
|
+
changed = self.connection.execute("""
|
|
638
|
+
UPDATE benchmark_campaign_work
|
|
639
|
+
SET status = 'leased', attempts = ?, lease_owner = ?,
|
|
640
|
+
lease_token = ?, lease_expires_at = ?, updated_at = ?
|
|
641
|
+
WHERE work_id = ? AND status IN ('pending', 'retry_wait')
|
|
642
|
+
""", (
|
|
643
|
+
attempt, worker_id, token, expires, now, row["work_id"],
|
|
644
|
+
)).rowcount
|
|
645
|
+
if changed != 1:
|
|
646
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.claim_lost")
|
|
647
|
+
return ClaimedBenchmarkCase(
|
|
648
|
+
work_id=row["work_id"], campaign_id=campaign_id,
|
|
649
|
+
target_locale=row["target_locale"],
|
|
650
|
+
suite_case_key=row["suite_case_key"],
|
|
651
|
+
job_payload=_job_payload(policy, row["target_locale"], row["suite_case_key"]),
|
|
652
|
+
attempt=attempt, max_attempts=row["max_attempts"],
|
|
653
|
+
lease_owner=worker_id, lease_token=token, lease_expires_at=expires,
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
def renew(self, claim: ClaimedBenchmarkCase, *, now: Any, lease_seconds: Any) -> ClaimedBenchmarkCase:
|
|
657
|
+
now = _timestamp(now)
|
|
658
|
+
lease_seconds = _duration(lease_seconds)
|
|
659
|
+
expires = now + lease_seconds
|
|
660
|
+
with _transaction(self.connection):
|
|
661
|
+
self._assert_live_locked(claim, now)
|
|
662
|
+
self.connection.execute("""
|
|
663
|
+
UPDATE benchmark_campaign_work SET lease_expires_at = ?, updated_at = ?
|
|
664
|
+
WHERE work_id = ?
|
|
665
|
+
""", (expires, now, claim.work_id))
|
|
666
|
+
return ClaimedBenchmarkCase(**{**asdict(claim), "lease_expires_at": expires})
|
|
667
|
+
|
|
668
|
+
def _assert_live_locked(self, claim: Any, now: float) -> sqlite3.Row:
|
|
669
|
+
if not isinstance(claim, ClaimedBenchmarkCase):
|
|
670
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.claim_invalid")
|
|
671
|
+
row = self.connection.execute(
|
|
672
|
+
"SELECT * FROM benchmark_campaign_work WHERE work_id = ?",
|
|
673
|
+
(claim.work_id,),
|
|
674
|
+
).fetchone()
|
|
675
|
+
if row is None or (
|
|
676
|
+
row["status"] != "leased"
|
|
677
|
+
or row["campaign_id"] != claim.campaign_id
|
|
678
|
+
or row["target_locale"] != claim.target_locale
|
|
679
|
+
or row["suite_case_key"] != claim.suite_case_key
|
|
680
|
+
or row["attempts"] != claim.attempt
|
|
681
|
+
or row["lease_owner"] != claim.lease_owner
|
|
682
|
+
or row["lease_token"] != claim.lease_token
|
|
683
|
+
or row["lease_expires_at"] != claim.lease_expires_at
|
|
684
|
+
or row["lease_expires_at"] <= now
|
|
685
|
+
):
|
|
686
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.lease_lost")
|
|
687
|
+
return row
|
|
688
|
+
|
|
689
|
+
def complete(
|
|
690
|
+
self, policy: Any, claim: ClaimedBenchmarkCase, result: Any, authority: Any,
|
|
691
|
+
*, now: Any,
|
|
692
|
+
) -> BenchmarkCampaignOutcome:
|
|
693
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
694
|
+
if not isinstance(result, Mapping):
|
|
695
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.result_invalid")
|
|
696
|
+
signed = json.loads(_canonical_json(dict(result)))
|
|
697
|
+
try:
|
|
698
|
+
validated = _BENCHMARK._validated_case_result(signed, policy, authority)
|
|
699
|
+
except _BENCHMARK.BenchmarkBlocked as error:
|
|
700
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.result_invalid") from error
|
|
701
|
+
if (
|
|
702
|
+
validated["target_locale"] != claim.target_locale
|
|
703
|
+
or validated["suite"]["case_key"] != claim.suite_case_key
|
|
704
|
+
):
|
|
705
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.result_mismatch")
|
|
706
|
+
encoded = _canonical_json(signed)
|
|
707
|
+
if len(encoded.encode("utf-8")) > MAX_RESULT_BYTES:
|
|
708
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.result_invalid")
|
|
709
|
+
now = _timestamp(now)
|
|
710
|
+
_assert_policy_current(policy, now)
|
|
711
|
+
with _transaction(self.connection):
|
|
712
|
+
self._verify_binding_locked(policy, claim.campaign_id)
|
|
713
|
+
self._assert_live_locked(claim, now)
|
|
714
|
+
digest = _hash_text(encoded)
|
|
715
|
+
self.connection.execute("""
|
|
716
|
+
UPDATE benchmark_campaign_work
|
|
717
|
+
SET status = 'succeeded', lease_owner = NULL, lease_token = NULL,
|
|
718
|
+
lease_expires_at = NULL, last_error_code = NULL,
|
|
719
|
+
last_error_detail_hash = NULL, result_json = ?,
|
|
720
|
+
result_sha256 = ?, updated_at = ? WHERE work_id = ?
|
|
721
|
+
""", (encoded, digest, now, claim.work_id))
|
|
722
|
+
return self._outcome(claim)
|
|
723
|
+
|
|
724
|
+
def transition_failure(
|
|
725
|
+
self, policy: Any, claim: ClaimedBenchmarkCase, code: Any, *,
|
|
726
|
+
retryable: bool, delay_seconds: Any = 0, detail: str | None = None,
|
|
727
|
+
now: Any,
|
|
728
|
+
) -> BenchmarkCampaignOutcome:
|
|
729
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
730
|
+
code = _identifier(code)
|
|
731
|
+
if ERROR_CODE.fullmatch(code) is None or not isinstance(retryable, bool):
|
|
732
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.failure_invalid")
|
|
733
|
+
delay = _duration(delay_seconds, allow_zero=True)
|
|
734
|
+
now = _timestamp(now)
|
|
735
|
+
if detail is not None and (
|
|
736
|
+
not isinstance(detail, str) or "\x00" in detail
|
|
737
|
+
or not unicodedata.is_normalized("NFC", detail)
|
|
738
|
+
):
|
|
739
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.failure_invalid")
|
|
740
|
+
with _transaction(self.connection):
|
|
741
|
+
self._verify_binding_locked(policy, claim.campaign_id)
|
|
742
|
+
row = self._assert_live_locked(claim, now)
|
|
743
|
+
will_retry = retryable and row["attempts"] < row["max_attempts"]
|
|
744
|
+
self.connection.execute("""
|
|
745
|
+
UPDATE benchmark_campaign_work
|
|
746
|
+
SET status = ?, next_attempt_at = ?, lease_owner = NULL,
|
|
747
|
+
lease_token = NULL, lease_expires_at = NULL,
|
|
748
|
+
last_error_code = ?, last_error_detail_hash = ?, updated_at = ?
|
|
749
|
+
WHERE work_id = ?
|
|
750
|
+
""", (
|
|
751
|
+
"retry_wait" if will_retry else "failed",
|
|
752
|
+
now + delay if will_retry else now,
|
|
753
|
+
code, None if detail is None else _hash_text(detail), now,
|
|
754
|
+
claim.work_id,
|
|
755
|
+
))
|
|
756
|
+
return self._outcome(claim)
|
|
757
|
+
|
|
758
|
+
def _outcome(self, claim: ClaimedBenchmarkCase) -> BenchmarkCampaignOutcome:
|
|
759
|
+
row = self.connection.execute(
|
|
760
|
+
"SELECT * FROM benchmark_campaign_work WHERE work_id = ?",
|
|
761
|
+
(claim.work_id,),
|
|
762
|
+
).fetchone()
|
|
763
|
+
return BenchmarkCampaignOutcome(
|
|
764
|
+
work_id=row["work_id"], target_locale=row["target_locale"],
|
|
765
|
+
suite_case_key=row["suite_case_key"], status=row["status"],
|
|
766
|
+
attempt=row["attempts"], max_attempts=row["max_attempts"],
|
|
767
|
+
next_attempt_at=row["next_attempt_at"],
|
|
768
|
+
error_code=row["last_error_code"],
|
|
769
|
+
error_detail_hash=row["last_error_detail_hash"],
|
|
770
|
+
result_sha256=row["result_sha256"],
|
|
771
|
+
)
|
|
772
|
+
|
|
773
|
+
def status(self, policy: Any, campaign_id: str) -> dict[str, Any]:
|
|
774
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
775
|
+
with _transaction(self.connection):
|
|
776
|
+
self._verify_binding_locked(policy, campaign_id)
|
|
777
|
+
rows = self.connection.execute("""
|
|
778
|
+
SELECT status, COUNT(*) AS count FROM benchmark_campaign_work
|
|
779
|
+
WHERE campaign_id = ? GROUP BY status
|
|
780
|
+
""", (campaign_id,)).fetchall()
|
|
781
|
+
errors = self.connection.execute("""
|
|
782
|
+
SELECT last_error_code, COUNT(*) AS count
|
|
783
|
+
FROM benchmark_campaign_work
|
|
784
|
+
WHERE campaign_id = ? AND last_error_code IS NOT NULL
|
|
785
|
+
GROUP BY last_error_code ORDER BY last_error_code
|
|
786
|
+
""", (campaign_id,)).fetchall()
|
|
787
|
+
report_state = self._report_state_locked(campaign_id)
|
|
788
|
+
counts = {name: 0 for name in STATUSES}
|
|
789
|
+
counts.update({row["status"]: row["count"] for row in rows})
|
|
790
|
+
return {
|
|
791
|
+
"campaign_id": campaign_id,
|
|
792
|
+
"policy_sha256": _campaign_identity(policy)[1],
|
|
793
|
+
"suite_sha256": policy.suite_sha256,
|
|
794
|
+
"valid_until": policy.valid_until,
|
|
795
|
+
"work_count": len(_expected_work(policy)),
|
|
796
|
+
"counts": counts,
|
|
797
|
+
"error_counts": {
|
|
798
|
+
row["last_error_code"]: row["count"] for row in errors
|
|
799
|
+
},
|
|
800
|
+
"complete": counts["succeeded"] == len(_expected_work(policy)),
|
|
801
|
+
"blocked": (
|
|
802
|
+
counts["failed"] > 0 or report_state["status"] == "failed"
|
|
803
|
+
),
|
|
804
|
+
"report_finalization": {
|
|
805
|
+
"status": report_state["status"],
|
|
806
|
+
"attempt": report_state["attempts"],
|
|
807
|
+
"max_attempts": report_state["max_attempts"],
|
|
808
|
+
"next_attempt_at": report_state["next_attempt_at"],
|
|
809
|
+
"error_code": report_state["last_error_code"],
|
|
810
|
+
},
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
def _complete_results_locked(
|
|
814
|
+
self, policy: Any, campaign_id: str,
|
|
815
|
+
) -> tuple[list[dict[str, Any]], tuple[str, ...]]:
|
|
816
|
+
self._verify_binding_locked(policy, campaign_id)
|
|
817
|
+
rows = self.connection.execute("""
|
|
818
|
+
SELECT status, result_json, result_sha256
|
|
819
|
+
FROM benchmark_campaign_work WHERE campaign_id = ?
|
|
820
|
+
ORDER BY target_locale, suite_case_key
|
|
821
|
+
""", (campaign_id,)).fetchall()
|
|
822
|
+
if any(row["status"] != "succeeded" for row in rows):
|
|
823
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.incomplete")
|
|
824
|
+
results = []
|
|
825
|
+
result_sha256s = []
|
|
826
|
+
for row in rows:
|
|
827
|
+
if (
|
|
828
|
+
not isinstance(row["result_json"], str)
|
|
829
|
+
or row["result_sha256"] != _hash_text(row["result_json"])
|
|
830
|
+
):
|
|
831
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.state_invalid")
|
|
832
|
+
try:
|
|
833
|
+
result = json.loads(row["result_json"])
|
|
834
|
+
except (TypeError, json.JSONDecodeError):
|
|
835
|
+
raise BenchmarkCampaignBlocked(
|
|
836
|
+
"benchmark.campaign.state_invalid",
|
|
837
|
+
) from None
|
|
838
|
+
if _canonical_json(result) != row["result_json"]:
|
|
839
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.state_invalid")
|
|
840
|
+
results.append(result)
|
|
841
|
+
result_sha256s.append(row["result_sha256"])
|
|
842
|
+
return results, tuple(result_sha256s)
|
|
843
|
+
|
|
844
|
+
def report_finalization_required(self, policy: Any, campaign_id: str) -> bool:
|
|
845
|
+
"""Return whether exact complete work still lacks its immutable report."""
|
|
846
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
847
|
+
with _transaction(self.connection):
|
|
848
|
+
self._verify_binding_locked(policy, campaign_id)
|
|
849
|
+
incomplete = self.connection.execute("""
|
|
850
|
+
SELECT 1 FROM benchmark_campaign_work
|
|
851
|
+
WHERE campaign_id = ? AND status != 'succeeded' LIMIT 1
|
|
852
|
+
""", (campaign_id,)).fetchone()
|
|
853
|
+
if incomplete is not None:
|
|
854
|
+
return False
|
|
855
|
+
self._complete_results_locked(policy, campaign_id)
|
|
856
|
+
state = self._report_state_locked(campaign_id)
|
|
857
|
+
report = self.connection.execute("""
|
|
858
|
+
SELECT 1 FROM benchmark_campaign_reports WHERE campaign_id = ?
|
|
859
|
+
""", (campaign_id,)).fetchone()
|
|
860
|
+
if state["status"] == "succeeded":
|
|
861
|
+
if report is None:
|
|
862
|
+
raise BenchmarkCampaignBlocked(
|
|
863
|
+
"benchmark.campaign.report_state_invalid",
|
|
864
|
+
)
|
|
865
|
+
return False
|
|
866
|
+
return state["status"] != "failed"
|
|
867
|
+
|
|
868
|
+
def _report_state_locked(self, campaign_id: str) -> sqlite3.Row:
|
|
869
|
+
row = self.connection.execute("""
|
|
870
|
+
SELECT * FROM benchmark_campaign_report_state WHERE campaign_id = ?
|
|
871
|
+
""", (campaign_id,)).fetchone()
|
|
872
|
+
try:
|
|
873
|
+
if row is None or tuple(row.keys()) != REPORT_STATE_COLUMNS:
|
|
874
|
+
raise ValueError
|
|
875
|
+
if row["status"] not in STATUSES or row["status"] == "leased" and (
|
|
876
|
+
row["lease_owner"] is None
|
|
877
|
+
or row["lease_token"] is None
|
|
878
|
+
or row["lease_expires_at"] is None
|
|
879
|
+
):
|
|
880
|
+
raise ValueError
|
|
881
|
+
if row["status"] != "leased" and any(
|
|
882
|
+
row[name] is not None
|
|
883
|
+
for name in ("lease_owner", "lease_token", "lease_expires_at")
|
|
884
|
+
):
|
|
885
|
+
raise ValueError
|
|
886
|
+
attempts = row["attempts"]
|
|
887
|
+
maximum = row["max_attempts"]
|
|
888
|
+
configured = self.connection.execute("""
|
|
889
|
+
SELECT MIN(max_attempts) AS minimum,
|
|
890
|
+
MAX(max_attempts) AS maximum
|
|
891
|
+
FROM benchmark_campaign_work WHERE campaign_id = ?
|
|
892
|
+
""", (campaign_id,)).fetchone()
|
|
893
|
+
if (
|
|
894
|
+
isinstance(attempts, bool)
|
|
895
|
+
or isinstance(maximum, bool)
|
|
896
|
+
or not isinstance(attempts, int)
|
|
897
|
+
or not isinstance(maximum, int)
|
|
898
|
+
or not 0 <= attempts <= maximum <= MAX_ATTEMPTS
|
|
899
|
+
or configured["minimum"] != configured["maximum"]
|
|
900
|
+
or maximum != configured["minimum"]
|
|
901
|
+
):
|
|
902
|
+
raise ValueError
|
|
903
|
+
if row["status"] == "pending" and (
|
|
904
|
+
attempts != 0 or row["last_error_code"] is not None
|
|
905
|
+
):
|
|
906
|
+
raise ValueError
|
|
907
|
+
if row["status"] in {"leased", "retry_wait", "failed", "succeeded"}:
|
|
908
|
+
if attempts < 1:
|
|
909
|
+
raise ValueError
|
|
910
|
+
if row["status"] in {"retry_wait", "failed"}:
|
|
911
|
+
if row["last_error_code"] is None:
|
|
912
|
+
raise ValueError
|
|
913
|
+
elif row["last_error_code"] is not None:
|
|
914
|
+
raise ValueError
|
|
915
|
+
code = row["last_error_code"]
|
|
916
|
+
if code is not None and ERROR_CODE.fullmatch(code) is None:
|
|
917
|
+
raise ValueError
|
|
918
|
+
detail = row["last_error_detail_hash"]
|
|
919
|
+
if detail is not None and re.fullmatch(r"[0-9a-f]{64}", detail) is None:
|
|
920
|
+
raise ValueError
|
|
921
|
+
if row["status"] in {"pending", "leased", "succeeded"} and detail is not None:
|
|
922
|
+
raise ValueError
|
|
923
|
+
created = _timestamp(row["created_at"])
|
|
924
|
+
updated = _timestamp(row["updated_at"])
|
|
925
|
+
_timestamp(row["next_attempt_at"])
|
|
926
|
+
if created > updated:
|
|
927
|
+
raise ValueError
|
|
928
|
+
if row["status"] == "leased":
|
|
929
|
+
_identifier(row["lease_owner"])
|
|
930
|
+
_identifier(row["lease_token"])
|
|
931
|
+
_timestamp(row["lease_expires_at"])
|
|
932
|
+
except Exception:
|
|
933
|
+
raise BenchmarkCampaignBlocked(
|
|
934
|
+
"benchmark.campaign.report_state_invalid",
|
|
935
|
+
) from None
|
|
936
|
+
return row
|
|
937
|
+
|
|
938
|
+
def claim_report_finalization(
|
|
939
|
+
self, policy: Any, campaign_id: str, worker_id: Any, *,
|
|
940
|
+
now: Any, lease_seconds: Any = 300,
|
|
941
|
+
) -> ClaimedBenchmarkReport | None:
|
|
942
|
+
"""Claim one due report-finalization attempt after all cases succeed."""
|
|
943
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
944
|
+
worker_id = _identifier(worker_id)
|
|
945
|
+
now = _timestamp(now)
|
|
946
|
+
_assert_policy_current(policy, now)
|
|
947
|
+
lease_seconds = _duration(lease_seconds)
|
|
948
|
+
with _transaction(self.connection):
|
|
949
|
+
self._verify_binding_locked(policy, campaign_id)
|
|
950
|
+
self._complete_results_locked(policy, campaign_id)
|
|
951
|
+
row = self._report_state_locked(campaign_id)
|
|
952
|
+
if row["status"] == "leased" and row["lease_expires_at"] <= now:
|
|
953
|
+
terminal = row["attempts"] >= row["max_attempts"]
|
|
954
|
+
self.connection.execute("""
|
|
955
|
+
UPDATE benchmark_campaign_report_state
|
|
956
|
+
SET status = ?, next_attempt_at = ?, lease_owner = NULL,
|
|
957
|
+
lease_token = NULL, lease_expires_at = NULL,
|
|
958
|
+
last_error_code = 'benchmark.campaign.report_lease_expired',
|
|
959
|
+
last_error_detail_hash = NULL, updated_at = ?
|
|
960
|
+
WHERE campaign_id = ?
|
|
961
|
+
""", (
|
|
962
|
+
"failed" if terminal else "retry_wait", now, now, campaign_id,
|
|
963
|
+
))
|
|
964
|
+
row = self._report_state_locked(campaign_id)
|
|
965
|
+
if row["status"] in {"succeeded", "failed", "leased"}:
|
|
966
|
+
return None
|
|
967
|
+
if row["next_attempt_at"] > now:
|
|
968
|
+
return None
|
|
969
|
+
attempt = row["attempts"] + 1
|
|
970
|
+
token = secrets.token_urlsafe(32)
|
|
971
|
+
expires = now + lease_seconds
|
|
972
|
+
changed = self.connection.execute("""
|
|
973
|
+
UPDATE benchmark_campaign_report_state
|
|
974
|
+
SET status = 'leased', attempts = ?, lease_owner = ?,
|
|
975
|
+
lease_token = ?, lease_expires_at = ?,
|
|
976
|
+
last_error_code = NULL, last_error_detail_hash = NULL,
|
|
977
|
+
updated_at = ?
|
|
978
|
+
WHERE campaign_id = ? AND status IN ('pending', 'retry_wait')
|
|
979
|
+
""", (attempt, worker_id, token, expires, now, campaign_id)).rowcount
|
|
980
|
+
if changed != 1:
|
|
981
|
+
raise BenchmarkCampaignBlocked(
|
|
982
|
+
"benchmark.campaign.report_claim_lost",
|
|
983
|
+
)
|
|
984
|
+
return ClaimedBenchmarkReport(
|
|
985
|
+
campaign_id, attempt, row["max_attempts"], worker_id, token, expires,
|
|
986
|
+
)
|
|
987
|
+
|
|
988
|
+
def _assert_report_claim_locked(
|
|
989
|
+
self, claim: Any, now: float,
|
|
990
|
+
) -> sqlite3.Row:
|
|
991
|
+
if not isinstance(claim, ClaimedBenchmarkReport):
|
|
992
|
+
raise BenchmarkCampaignBlocked(
|
|
993
|
+
"benchmark.campaign.report_claim_invalid",
|
|
994
|
+
)
|
|
995
|
+
row = self._report_state_locked(claim.campaign_id)
|
|
996
|
+
if (
|
|
997
|
+
row["status"] != "leased"
|
|
998
|
+
or row["attempts"] != claim.attempt
|
|
999
|
+
or row["max_attempts"] != claim.max_attempts
|
|
1000
|
+
or row["lease_owner"] != claim.lease_owner
|
|
1001
|
+
or row["lease_token"] != claim.lease_token
|
|
1002
|
+
or row["lease_expires_at"] != claim.lease_expires_at
|
|
1003
|
+
or row["lease_expires_at"] <= now
|
|
1004
|
+
):
|
|
1005
|
+
raise BenchmarkCampaignBlocked(
|
|
1006
|
+
"benchmark.campaign.report_lease_lost",
|
|
1007
|
+
)
|
|
1008
|
+
return row
|
|
1009
|
+
|
|
1010
|
+
def renew_report_finalization(
|
|
1011
|
+
self, claim: ClaimedBenchmarkReport, *, now: Any, lease_seconds: Any,
|
|
1012
|
+
) -> ClaimedBenchmarkReport:
|
|
1013
|
+
now = _timestamp(now)
|
|
1014
|
+
lease_seconds = _duration(lease_seconds)
|
|
1015
|
+
expires = now + lease_seconds
|
|
1016
|
+
with _transaction(self.connection):
|
|
1017
|
+
self._assert_report_claim_locked(claim, now)
|
|
1018
|
+
self.connection.execute("""
|
|
1019
|
+
UPDATE benchmark_campaign_report_state
|
|
1020
|
+
SET lease_expires_at = ?, updated_at = ? WHERE campaign_id = ?
|
|
1021
|
+
""", (expires, now, claim.campaign_id))
|
|
1022
|
+
return ClaimedBenchmarkReport(**{
|
|
1023
|
+
**asdict(claim), "lease_expires_at": expires,
|
|
1024
|
+
})
|
|
1025
|
+
|
|
1026
|
+
def complete_report_finalization(
|
|
1027
|
+
self, policy: Any, claim: ClaimedBenchmarkReport, *, now: Any,
|
|
1028
|
+
) -> BenchmarkReportFinalizationOutcome:
|
|
1029
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
1030
|
+
now = _timestamp(now)
|
|
1031
|
+
_assert_policy_current(policy, now)
|
|
1032
|
+
with _transaction(self.connection):
|
|
1033
|
+
self._verify_binding_locked(policy, claim.campaign_id)
|
|
1034
|
+
self._assert_report_claim_locked(claim, now)
|
|
1035
|
+
if self.connection.execute("""
|
|
1036
|
+
SELECT 1 FROM benchmark_campaign_reports WHERE campaign_id = ?
|
|
1037
|
+
""", (claim.campaign_id,)).fetchone() is None:
|
|
1038
|
+
raise BenchmarkCampaignBlocked(
|
|
1039
|
+
"benchmark.campaign.report_missing",
|
|
1040
|
+
)
|
|
1041
|
+
self.connection.execute("""
|
|
1042
|
+
UPDATE benchmark_campaign_report_state
|
|
1043
|
+
SET status = 'succeeded', next_attempt_at = ?,
|
|
1044
|
+
lease_owner = NULL, lease_token = NULL,
|
|
1045
|
+
lease_expires_at = NULL, last_error_code = NULL,
|
|
1046
|
+
last_error_detail_hash = NULL, updated_at = ?
|
|
1047
|
+
WHERE campaign_id = ?
|
|
1048
|
+
""", (now, now, claim.campaign_id))
|
|
1049
|
+
return self._report_outcome(claim.campaign_id)
|
|
1050
|
+
|
|
1051
|
+
def transition_report_failure(
|
|
1052
|
+
self, policy: Any, claim: ClaimedBenchmarkReport, code: Any, *,
|
|
1053
|
+
retryable: bool, delay_seconds: Any = 0, detail: str | None = None,
|
|
1054
|
+
now: Any,
|
|
1055
|
+
) -> BenchmarkReportFinalizationOutcome:
|
|
1056
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
1057
|
+
code = _identifier(code)
|
|
1058
|
+
if ERROR_CODE.fullmatch(code) is None or not isinstance(retryable, bool):
|
|
1059
|
+
raise BenchmarkCampaignBlocked(
|
|
1060
|
+
"benchmark.campaign.report_failure_invalid",
|
|
1061
|
+
)
|
|
1062
|
+
delay = _duration(delay_seconds, allow_zero=True)
|
|
1063
|
+
now = _timestamp(now)
|
|
1064
|
+
if detail is not None and (
|
|
1065
|
+
not isinstance(detail, str) or "\x00" in detail
|
|
1066
|
+
or not unicodedata.is_normalized("NFC", detail)
|
|
1067
|
+
):
|
|
1068
|
+
raise BenchmarkCampaignBlocked(
|
|
1069
|
+
"benchmark.campaign.report_failure_invalid",
|
|
1070
|
+
)
|
|
1071
|
+
with _transaction(self.connection):
|
|
1072
|
+
self._verify_binding_locked(policy, claim.campaign_id)
|
|
1073
|
+
row = self._assert_report_claim_locked(claim, now)
|
|
1074
|
+
will_retry = retryable and row["attempts"] < row["max_attempts"]
|
|
1075
|
+
self.connection.execute("""
|
|
1076
|
+
UPDATE benchmark_campaign_report_state
|
|
1077
|
+
SET status = ?, next_attempt_at = ?, lease_owner = NULL,
|
|
1078
|
+
lease_token = NULL, lease_expires_at = NULL,
|
|
1079
|
+
last_error_code = ?, last_error_detail_hash = ?, updated_at = ?
|
|
1080
|
+
WHERE campaign_id = ?
|
|
1081
|
+
""", (
|
|
1082
|
+
"retry_wait" if will_retry else "failed",
|
|
1083
|
+
now + delay if will_retry else now,
|
|
1084
|
+
code, None if detail is None else _hash_text(detail), now,
|
|
1085
|
+
claim.campaign_id,
|
|
1086
|
+
))
|
|
1087
|
+
return self._report_outcome(claim.campaign_id)
|
|
1088
|
+
|
|
1089
|
+
def _report_outcome(
|
|
1090
|
+
self, campaign_id: str,
|
|
1091
|
+
) -> BenchmarkReportFinalizationOutcome:
|
|
1092
|
+
row = self.connection.execute("""
|
|
1093
|
+
SELECT * FROM benchmark_campaign_report_state WHERE campaign_id = ?
|
|
1094
|
+
""", (campaign_id,)).fetchone()
|
|
1095
|
+
return BenchmarkReportFinalizationOutcome(
|
|
1096
|
+
campaign_id=campaign_id,
|
|
1097
|
+
status=row["status"],
|
|
1098
|
+
attempt=row["attempts"],
|
|
1099
|
+
max_attempts=row["max_attempts"],
|
|
1100
|
+
next_attempt_at=row["next_attempt_at"],
|
|
1101
|
+
error_code=row["last_error_code"],
|
|
1102
|
+
error_detail_hash=row["last_error_detail_hash"],
|
|
1103
|
+
)
|
|
1104
|
+
|
|
1105
|
+
def _verified_report_row(
|
|
1106
|
+
self,
|
|
1107
|
+
row: Any,
|
|
1108
|
+
policy: Any,
|
|
1109
|
+
campaign_id: str,
|
|
1110
|
+
results: list[dict[str, Any]],
|
|
1111
|
+
result_sha256s: tuple[str, ...],
|
|
1112
|
+
authority: Any,
|
|
1113
|
+
*,
|
|
1114
|
+
now: float,
|
|
1115
|
+
) -> dict[str, Any]:
|
|
1116
|
+
try:
|
|
1117
|
+
if row is None or tuple(row.keys()) != REPORT_COLUMNS:
|
|
1118
|
+
raise ValueError
|
|
1119
|
+
report_json = row["report_json"]
|
|
1120
|
+
if (
|
|
1121
|
+
row["campaign_id"] != campaign_id
|
|
1122
|
+
or row["policy_sha256"] != _campaign_identity(policy)[1]
|
|
1123
|
+
or row["results_sha256"] != _results_sha256(result_sha256s)
|
|
1124
|
+
or not isinstance(report_json, str)
|
|
1125
|
+
or not report_json
|
|
1126
|
+
or len(report_json.encode("utf-8")) > MAX_RESULT_BYTES
|
|
1127
|
+
or row["report_sha256"] != _hash_text(report_json)
|
|
1128
|
+
or _timestamp(row["created_at"]) > now
|
|
1129
|
+
):
|
|
1130
|
+
raise ValueError
|
|
1131
|
+
report = json.loads(report_json)
|
|
1132
|
+
if _canonical_json(report) != report_json:
|
|
1133
|
+
raise ValueError
|
|
1134
|
+
return _BENCHMARK.verify_benchmark_report(
|
|
1135
|
+
policy,
|
|
1136
|
+
report,
|
|
1137
|
+
results,
|
|
1138
|
+
evidence_authority=authority,
|
|
1139
|
+
)
|
|
1140
|
+
except Exception:
|
|
1141
|
+
raise BenchmarkCampaignBlocked(
|
|
1142
|
+
"benchmark.campaign.report_invalid",
|
|
1143
|
+
) from None
|
|
1144
|
+
|
|
1145
|
+
def _mark_unclaimed_report_succeeded(
|
|
1146
|
+
self, campaign_id: str, *, now: float,
|
|
1147
|
+
) -> None:
|
|
1148
|
+
with _transaction(self.connection):
|
|
1149
|
+
state = self._report_state_locked(campaign_id)
|
|
1150
|
+
if state["status"] == "leased":
|
|
1151
|
+
return
|
|
1152
|
+
if self.connection.execute("""
|
|
1153
|
+
SELECT 1 FROM benchmark_campaign_reports WHERE campaign_id = ?
|
|
1154
|
+
""", (campaign_id,)).fetchone() is None:
|
|
1155
|
+
raise BenchmarkCampaignBlocked(
|
|
1156
|
+
"benchmark.campaign.report_missing",
|
|
1157
|
+
)
|
|
1158
|
+
self.connection.execute("""
|
|
1159
|
+
UPDATE benchmark_campaign_report_state
|
|
1160
|
+
SET status = 'succeeded', attempts = MAX(attempts, 1),
|
|
1161
|
+
next_attempt_at = ?, lease_owner = NULL, lease_token = NULL,
|
|
1162
|
+
lease_expires_at = NULL, last_error_code = NULL,
|
|
1163
|
+
last_error_detail_hash = NULL, updated_at = ?
|
|
1164
|
+
WHERE campaign_id = ?
|
|
1165
|
+
""", (now, now, campaign_id))
|
|
1166
|
+
|
|
1167
|
+
def load_report(
|
|
1168
|
+
self,
|
|
1169
|
+
policy: Any,
|
|
1170
|
+
campaign_id: str,
|
|
1171
|
+
authority: Any,
|
|
1172
|
+
*,
|
|
1173
|
+
now: Any,
|
|
1174
|
+
) -> dict[str, Any]:
|
|
1175
|
+
"""Load one already finalized report without signing or writing state."""
|
|
1176
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
1177
|
+
now = _timestamp(now)
|
|
1178
|
+
_assert_policy_current(policy, now)
|
|
1179
|
+
if self.connection.in_transaction:
|
|
1180
|
+
raise BenchmarkCampaignBlocked(
|
|
1181
|
+
"benchmark.campaign.external_transaction",
|
|
1182
|
+
)
|
|
1183
|
+
self.connection.execute("BEGIN")
|
|
1184
|
+
try:
|
|
1185
|
+
results, result_sha256s = self._complete_results_locked(
|
|
1186
|
+
policy, campaign_id,
|
|
1187
|
+
)
|
|
1188
|
+
state = self._report_state_locked(campaign_id)
|
|
1189
|
+
stored = self.connection.execute("""
|
|
1190
|
+
SELECT * FROM benchmark_campaign_reports
|
|
1191
|
+
WHERE campaign_id = ?
|
|
1192
|
+
""", (campaign_id,)).fetchone()
|
|
1193
|
+
if _timestamp(state["updated_at"]) > now:
|
|
1194
|
+
raise BenchmarkCampaignBlocked(
|
|
1195
|
+
"benchmark.campaign.report_state_invalid",
|
|
1196
|
+
)
|
|
1197
|
+
if state["status"] != "succeeded" or stored is None:
|
|
1198
|
+
if state["status"] == "succeeded" or stored is not None:
|
|
1199
|
+
raise BenchmarkCampaignBlocked(
|
|
1200
|
+
"benchmark.campaign.report_state_invalid",
|
|
1201
|
+
)
|
|
1202
|
+
raise BenchmarkCampaignBlocked(
|
|
1203
|
+
"benchmark.campaign.report_missing",
|
|
1204
|
+
)
|
|
1205
|
+
finally:
|
|
1206
|
+
self.connection.rollback()
|
|
1207
|
+
return self._verified_report_row(
|
|
1208
|
+
stored,
|
|
1209
|
+
policy,
|
|
1210
|
+
campaign_id,
|
|
1211
|
+
results,
|
|
1212
|
+
result_sha256s,
|
|
1213
|
+
authority,
|
|
1214
|
+
now=now,
|
|
1215
|
+
)
|
|
1216
|
+
|
|
1217
|
+
def health(
|
|
1218
|
+
self,
|
|
1219
|
+
policy: Any,
|
|
1220
|
+
campaign_id: str,
|
|
1221
|
+
authority: Any,
|
|
1222
|
+
*,
|
|
1223
|
+
now: Any,
|
|
1224
|
+
stale_after_seconds: Any = 3600,
|
|
1225
|
+
) -> BenchmarkCampaignHealth:
|
|
1226
|
+
"""Return a read-only, text-free health snapshot for one campaign."""
|
|
1227
|
+
now = _timestamp(now)
|
|
1228
|
+
stale_after_seconds = _timestamp(stale_after_seconds)
|
|
1229
|
+
if not 0 < stale_after_seconds <= MAX_STALE_SECONDS:
|
|
1230
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.stale_threshold_invalid")
|
|
1231
|
+
counts = {name: 0 for name in STATUSES}
|
|
1232
|
+
work_count = 0
|
|
1233
|
+
last_progress_at: float | None = None
|
|
1234
|
+
results: list[dict[str, Any]] = []
|
|
1235
|
+
result_sha256s: list[str] = []
|
|
1236
|
+
report_row = None
|
|
1237
|
+
report_state = None
|
|
1238
|
+
policy_expired = False
|
|
1239
|
+
reasons: set[str] = set()
|
|
1240
|
+
try:
|
|
1241
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
1242
|
+
policy_expired = now > policy.valid_until
|
|
1243
|
+
if self.connection.in_transaction:
|
|
1244
|
+
raise BenchmarkCampaignBlocked(
|
|
1245
|
+
"benchmark.campaign.external_transaction",
|
|
1246
|
+
)
|
|
1247
|
+
self.connection.execute("BEGIN")
|
|
1248
|
+
try:
|
|
1249
|
+
self._verify_binding_locked(policy, campaign_id)
|
|
1250
|
+
rows = self.connection.execute("""
|
|
1251
|
+
SELECT * FROM benchmark_campaign_work
|
|
1252
|
+
WHERE campaign_id = ?
|
|
1253
|
+
ORDER BY target_locale, suite_case_key
|
|
1254
|
+
""", (campaign_id,)).fetchall()
|
|
1255
|
+
work_count = len(rows)
|
|
1256
|
+
due = False
|
|
1257
|
+
live_lease = False
|
|
1258
|
+
for row in rows:
|
|
1259
|
+
status = row["status"]
|
|
1260
|
+
if status not in counts:
|
|
1261
|
+
raise ValueError
|
|
1262
|
+
counts[status] += 1
|
|
1263
|
+
attempts = row["attempts"]
|
|
1264
|
+
maximum = row["max_attempts"]
|
|
1265
|
+
if (
|
|
1266
|
+
isinstance(attempts, bool)
|
|
1267
|
+
or isinstance(maximum, bool)
|
|
1268
|
+
or not isinstance(attempts, int)
|
|
1269
|
+
or not isinstance(maximum, int)
|
|
1270
|
+
or not 0 <= attempts <= maximum <= MAX_ATTEMPTS
|
|
1271
|
+
):
|
|
1272
|
+
raise ValueError
|
|
1273
|
+
created_at = _timestamp(row["created_at"])
|
|
1274
|
+
updated_at = _timestamp(row["updated_at"])
|
|
1275
|
+
next_attempt_at = _timestamp(row["next_attempt_at"])
|
|
1276
|
+
if created_at > updated_at or updated_at > now:
|
|
1277
|
+
raise ValueError
|
|
1278
|
+
last_progress_at = max(
|
|
1279
|
+
updated_at,
|
|
1280
|
+
last_progress_at if last_progress_at is not None else updated_at,
|
|
1281
|
+
)
|
|
1282
|
+
lease_values = (
|
|
1283
|
+
row["lease_owner"], row["lease_token"],
|
|
1284
|
+
row["lease_expires_at"],
|
|
1285
|
+
)
|
|
1286
|
+
if status == "leased":
|
|
1287
|
+
_identifier(row["lease_owner"])
|
|
1288
|
+
_identifier(row["lease_token"])
|
|
1289
|
+
expires_at = _timestamp(row["lease_expires_at"])
|
|
1290
|
+
if attempts < 1:
|
|
1291
|
+
raise ValueError
|
|
1292
|
+
if expires_at <= now:
|
|
1293
|
+
reasons.add("benchmark.campaign.lease_expired")
|
|
1294
|
+
due = True
|
|
1295
|
+
else:
|
|
1296
|
+
live_lease = True
|
|
1297
|
+
elif any(value is not None for value in lease_values):
|
|
1298
|
+
raise ValueError
|
|
1299
|
+
if status == "pending":
|
|
1300
|
+
if attempts != 0 or row["last_error_code"] is not None:
|
|
1301
|
+
raise ValueError
|
|
1302
|
+
due = due or next_attempt_at <= now
|
|
1303
|
+
elif status in {"retry_wait", "failed"}:
|
|
1304
|
+
if attempts < 1:
|
|
1305
|
+
raise ValueError
|
|
1306
|
+
if status == "retry_wait":
|
|
1307
|
+
if attempts >= maximum:
|
|
1308
|
+
raise ValueError
|
|
1309
|
+
due = due or next_attempt_at <= now
|
|
1310
|
+
elif status == "succeeded" and row["last_error_code"] is not None:
|
|
1311
|
+
raise ValueError
|
|
1312
|
+
code = row["last_error_code"]
|
|
1313
|
+
if code is not None:
|
|
1314
|
+
if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
|
|
1315
|
+
raise ValueError
|
|
1316
|
+
reasons.add("benchmark.campaign.error." + code)
|
|
1317
|
+
elif status in {"retry_wait", "failed"}:
|
|
1318
|
+
raise ValueError
|
|
1319
|
+
detail_hash = row["last_error_detail_hash"]
|
|
1320
|
+
if detail_hash is not None and re.fullmatch(
|
|
1321
|
+
r"[0-9a-f]{64}", detail_hash,
|
|
1322
|
+
) is None:
|
|
1323
|
+
raise ValueError
|
|
1324
|
+
if status in {"pending", "succeeded"} and detail_hash is not None:
|
|
1325
|
+
raise ValueError
|
|
1326
|
+
result_json = row["result_json"]
|
|
1327
|
+
result_sha256 = row["result_sha256"]
|
|
1328
|
+
if status == "succeeded":
|
|
1329
|
+
if (
|
|
1330
|
+
not isinstance(result_json, str)
|
|
1331
|
+
or result_sha256 != _hash_text(result_json)
|
|
1332
|
+
or attempts < 1
|
|
1333
|
+
):
|
|
1334
|
+
raise ValueError
|
|
1335
|
+
result = json.loads(result_json)
|
|
1336
|
+
if _canonical_json(result) != result_json:
|
|
1337
|
+
raise ValueError
|
|
1338
|
+
validated = _BENCHMARK._validated_case_result(
|
|
1339
|
+
result, policy, authority,
|
|
1340
|
+
)
|
|
1341
|
+
if (
|
|
1342
|
+
validated["target_locale"] != row["target_locale"]
|
|
1343
|
+
or validated["suite"]["case_key"] != row["suite_case_key"]
|
|
1344
|
+
):
|
|
1345
|
+
raise ValueError
|
|
1346
|
+
results.append(result)
|
|
1347
|
+
result_sha256s.append(result_sha256)
|
|
1348
|
+
elif result_json is not None or result_sha256 is not None:
|
|
1349
|
+
raise ValueError
|
|
1350
|
+
if work_count != len(_expected_work(policy)):
|
|
1351
|
+
raise ValueError
|
|
1352
|
+
report_row = self.connection.execute("""
|
|
1353
|
+
SELECT * FROM benchmark_campaign_reports
|
|
1354
|
+
WHERE campaign_id = ?
|
|
1355
|
+
""", (campaign_id,)).fetchone()
|
|
1356
|
+
report_state = self._report_state_locked(campaign_id)
|
|
1357
|
+
report_updated_at = _timestamp(report_state["updated_at"])
|
|
1358
|
+
if report_updated_at > now:
|
|
1359
|
+
raise ValueError
|
|
1360
|
+
last_progress_at = max(
|
|
1361
|
+
report_updated_at,
|
|
1362
|
+
last_progress_at
|
|
1363
|
+
if last_progress_at is not None
|
|
1364
|
+
else report_updated_at,
|
|
1365
|
+
)
|
|
1366
|
+
finally:
|
|
1367
|
+
self.connection.rollback()
|
|
1368
|
+
except Exception:
|
|
1369
|
+
return BenchmarkCampaignHealth(
|
|
1370
|
+
campaign_id=(
|
|
1371
|
+
campaign_id
|
|
1372
|
+
if isinstance(campaign_id, str) and re.fullmatch(
|
|
1373
|
+
r"benchmark-campaign-[0-9a-f]{64}", campaign_id,
|
|
1374
|
+
) is not None
|
|
1375
|
+
else "invalid"
|
|
1376
|
+
),
|
|
1377
|
+
status="blocked",
|
|
1378
|
+
reasons=("benchmark.campaign.state_invalid",),
|
|
1379
|
+
counts=tuple(sorted(counts.items())),
|
|
1380
|
+
work_count=work_count,
|
|
1381
|
+
report_ready=False,
|
|
1382
|
+
last_progress_at=last_progress_at,
|
|
1383
|
+
)
|
|
1384
|
+
|
|
1385
|
+
complete = counts["succeeded"] == work_count
|
|
1386
|
+
report_ready = False
|
|
1387
|
+
if policy_expired:
|
|
1388
|
+
reasons.add("benchmark.campaign.validity_expired")
|
|
1389
|
+
if counts["failed"]:
|
|
1390
|
+
reasons.add("benchmark.campaign.failed")
|
|
1391
|
+
if (
|
|
1392
|
+
not complete
|
|
1393
|
+
and not counts["failed"]
|
|
1394
|
+
and not live_lease
|
|
1395
|
+
and due
|
|
1396
|
+
and last_progress_at is not None
|
|
1397
|
+
and now - last_progress_at > stale_after_seconds
|
|
1398
|
+
):
|
|
1399
|
+
reasons.add("benchmark.campaign.stalled")
|
|
1400
|
+
report_status = report_state["status"]
|
|
1401
|
+
report_error = report_state["last_error_code"]
|
|
1402
|
+
if report_error is not None:
|
|
1403
|
+
reasons.add("benchmark.campaign.report_error." + report_error)
|
|
1404
|
+
if report_status == "leased" and report_state["lease_expires_at"] <= now:
|
|
1405
|
+
reasons.add("benchmark.campaign.report_lease_expired")
|
|
1406
|
+
if report_status == "failed":
|
|
1407
|
+
reasons.add("benchmark.campaign.report_failed")
|
|
1408
|
+
if not complete and (
|
|
1409
|
+
report_status != "pending" or report_row is not None
|
|
1410
|
+
):
|
|
1411
|
+
reasons.add("benchmark.campaign.report_state_invalid")
|
|
1412
|
+
elif complete and report_status == "succeeded" and report_row is None:
|
|
1413
|
+
reasons.add("benchmark.campaign.report_state_invalid")
|
|
1414
|
+
elif complete and report_status != "succeeded":
|
|
1415
|
+
reasons.add("benchmark.campaign.report_missing")
|
|
1416
|
+
elif complete:
|
|
1417
|
+
try:
|
|
1418
|
+
self._verified_report_row(
|
|
1419
|
+
report_row,
|
|
1420
|
+
policy,
|
|
1421
|
+
campaign_id,
|
|
1422
|
+
results,
|
|
1423
|
+
tuple(result_sha256s),
|
|
1424
|
+
authority,
|
|
1425
|
+
now=now,
|
|
1426
|
+
)
|
|
1427
|
+
report_ready = not policy_expired
|
|
1428
|
+
except Exception:
|
|
1429
|
+
reasons.add("benchmark.campaign.report_invalid")
|
|
1430
|
+
elif report_row is not None:
|
|
1431
|
+
reasons.add("benchmark.campaign.report_invalid")
|
|
1432
|
+
blocking = counts["failed"] > 0 or bool({
|
|
1433
|
+
"benchmark.campaign.report_failed",
|
|
1434
|
+
"benchmark.campaign.report_invalid",
|
|
1435
|
+
"benchmark.campaign.report_state_invalid",
|
|
1436
|
+
"benchmark.campaign.validity_expired",
|
|
1437
|
+
} & reasons)
|
|
1438
|
+
status = "blocked" if blocking else ("degraded" if reasons else "healthy")
|
|
1439
|
+
return BenchmarkCampaignHealth(
|
|
1440
|
+
campaign_id=campaign_id,
|
|
1441
|
+
status=status,
|
|
1442
|
+
reasons=tuple(sorted(reasons)),
|
|
1443
|
+
counts=tuple(sorted(counts.items())),
|
|
1444
|
+
work_count=work_count,
|
|
1445
|
+
report_ready=report_ready,
|
|
1446
|
+
last_progress_at=last_progress_at,
|
|
1447
|
+
)
|
|
1448
|
+
|
|
1449
|
+
def summarize(
|
|
1450
|
+
self,
|
|
1451
|
+
policy: Any,
|
|
1452
|
+
campaign_id: str,
|
|
1453
|
+
authority: Any,
|
|
1454
|
+
*,
|
|
1455
|
+
now: Any = None,
|
|
1456
|
+
operation_guard: Callable[[], Any] | None = None,
|
|
1457
|
+
) -> dict[str, Any]:
|
|
1458
|
+
policy = _BENCHMARK._validate_policy(policy)
|
|
1459
|
+
now = _timestamp(now)
|
|
1460
|
+
_assert_policy_current(policy, now)
|
|
1461
|
+
if operation_guard is not None and not callable(operation_guard):
|
|
1462
|
+
raise TypeError("operation_guard must be callable")
|
|
1463
|
+
|
|
1464
|
+
def guard() -> None:
|
|
1465
|
+
if operation_guard is None:
|
|
1466
|
+
return
|
|
1467
|
+
try:
|
|
1468
|
+
operation_guard()
|
|
1469
|
+
except BenchmarkCampaignBlocked as error:
|
|
1470
|
+
if error.code == "benchmark.campaign.validity_expired":
|
|
1471
|
+
raise
|
|
1472
|
+
raise BenchmarkCampaignBlocked(
|
|
1473
|
+
"benchmark.campaign.operation_guard_failed",
|
|
1474
|
+
) from None
|
|
1475
|
+
except Exception:
|
|
1476
|
+
raise BenchmarkCampaignBlocked(
|
|
1477
|
+
"benchmark.campaign.operation_guard_failed",
|
|
1478
|
+
) from None
|
|
1479
|
+
|
|
1480
|
+
with _transaction(self.connection):
|
|
1481
|
+
results, result_sha256s = self._complete_results_locked(
|
|
1482
|
+
policy, campaign_id,
|
|
1483
|
+
)
|
|
1484
|
+
stored = self.connection.execute("""
|
|
1485
|
+
SELECT * FROM benchmark_campaign_reports
|
|
1486
|
+
WHERE campaign_id = ?
|
|
1487
|
+
""", (campaign_id,)).fetchone()
|
|
1488
|
+
if stored is not None:
|
|
1489
|
+
guard()
|
|
1490
|
+
report = self._verified_report_row(
|
|
1491
|
+
stored, policy, campaign_id, results, result_sha256s,
|
|
1492
|
+
authority, now=now,
|
|
1493
|
+
)
|
|
1494
|
+
self._mark_unclaimed_report_succeeded(campaign_id, now=now)
|
|
1495
|
+
return report
|
|
1496
|
+
guard()
|
|
1497
|
+
report = _BENCHMARK.summarize_benchmark(
|
|
1498
|
+
policy, results, evidence_authority=authority,
|
|
1499
|
+
)
|
|
1500
|
+
report = _BENCHMARK.verify_benchmark_report(
|
|
1501
|
+
policy, report, results, evidence_authority=authority,
|
|
1502
|
+
)
|
|
1503
|
+
report_json = _canonical_json(report)
|
|
1504
|
+
if len(report_json.encode("utf-8")) > MAX_RESULT_BYTES:
|
|
1505
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.report_invalid")
|
|
1506
|
+
results_sha256 = _results_sha256(result_sha256s)
|
|
1507
|
+
guard()
|
|
1508
|
+
with _transaction(self.connection):
|
|
1509
|
+
current_results, current_sha256s = self._complete_results_locked(
|
|
1510
|
+
policy, campaign_id,
|
|
1511
|
+
)
|
|
1512
|
+
if _results_sha256(current_sha256s) != results_sha256:
|
|
1513
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.state_invalid")
|
|
1514
|
+
stored = self.connection.execute("""
|
|
1515
|
+
SELECT * FROM benchmark_campaign_reports
|
|
1516
|
+
WHERE campaign_id = ?
|
|
1517
|
+
""", (campaign_id,)).fetchone()
|
|
1518
|
+
if stored is None:
|
|
1519
|
+
self.connection.execute("""
|
|
1520
|
+
INSERT INTO benchmark_campaign_reports (
|
|
1521
|
+
campaign_id, policy_sha256, results_sha256,
|
|
1522
|
+
report_json, report_sha256, created_at
|
|
1523
|
+
) VALUES (?, ?, ?, ?, ?, ?)
|
|
1524
|
+
""", (
|
|
1525
|
+
campaign_id,
|
|
1526
|
+
_campaign_identity(policy)[1],
|
|
1527
|
+
results_sha256,
|
|
1528
|
+
report_json,
|
|
1529
|
+
_hash_text(report_json),
|
|
1530
|
+
now,
|
|
1531
|
+
))
|
|
1532
|
+
if stored is not None:
|
|
1533
|
+
report = self._verified_report_row(
|
|
1534
|
+
stored, policy, campaign_id, current_results, current_sha256s,
|
|
1535
|
+
authority, now=now,
|
|
1536
|
+
)
|
|
1537
|
+
self._mark_unclaimed_report_succeeded(campaign_id, now=now)
|
|
1538
|
+
return report
|
|
1539
|
+
self._mark_unclaimed_report_succeeded(campaign_id, now=now)
|
|
1540
|
+
return report
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
def _retry_delay(attempt: int, base: float, maximum: float) -> float:
|
|
1544
|
+
return min(maximum, base * (2 ** min(attempt - 1, 30)))
|
|
1545
|
+
|
|
1546
|
+
|
|
1547
|
+
def run_benchmark_report_finalization(
|
|
1548
|
+
store: BenchmarkCampaignStore,
|
|
1549
|
+
policy: Any,
|
|
1550
|
+
campaign_id: str,
|
|
1551
|
+
worker_id: Any,
|
|
1552
|
+
authority: Any,
|
|
1553
|
+
*,
|
|
1554
|
+
clock: Callable[[], float] = time.time,
|
|
1555
|
+
operation_guard: Callable[[float], Any] | None = None,
|
|
1556
|
+
lease_seconds: Any = 300,
|
|
1557
|
+
retry_base_seconds: Any = 5,
|
|
1558
|
+
retry_max_seconds: Any = 3600,
|
|
1559
|
+
) -> BenchmarkReportFinalizationOutcome | None:
|
|
1560
|
+
"""Finalize at most one report attempt with durable bounded recovery."""
|
|
1561
|
+
if not isinstance(store, BenchmarkCampaignStore) or not callable(clock):
|
|
1562
|
+
raise BenchmarkCampaignBlocked(
|
|
1563
|
+
"benchmark.campaign.report_dependency_invalid",
|
|
1564
|
+
)
|
|
1565
|
+
if operation_guard is not None and not callable(operation_guard):
|
|
1566
|
+
raise BenchmarkCampaignBlocked(
|
|
1567
|
+
"benchmark.campaign.report_dependency_invalid",
|
|
1568
|
+
)
|
|
1569
|
+
lease_seconds = _duration(lease_seconds)
|
|
1570
|
+
retry_base_seconds = _duration(retry_base_seconds, allow_zero=True)
|
|
1571
|
+
retry_max_seconds = _duration(retry_max_seconds, allow_zero=True)
|
|
1572
|
+
if retry_base_seconds > retry_max_seconds:
|
|
1573
|
+
raise BenchmarkCampaignBlocked(
|
|
1574
|
+
"benchmark.campaign.report_retry_invalid",
|
|
1575
|
+
)
|
|
1576
|
+
now = _timestamp(clock())
|
|
1577
|
+
claim = store.claim_report_finalization(
|
|
1578
|
+
policy, campaign_id, worker_id, now=now, lease_seconds=lease_seconds,
|
|
1579
|
+
)
|
|
1580
|
+
if claim is None:
|
|
1581
|
+
return None
|
|
1582
|
+
active_claim = claim
|
|
1583
|
+
|
|
1584
|
+
def renew() -> None:
|
|
1585
|
+
nonlocal active_claim
|
|
1586
|
+
current_now = _timestamp(clock())
|
|
1587
|
+
_assert_policy_current(policy, current_now)
|
|
1588
|
+
if operation_guard is not None:
|
|
1589
|
+
try:
|
|
1590
|
+
operation_guard(lease_seconds)
|
|
1591
|
+
except Exception:
|
|
1592
|
+
raise BenchmarkCampaignBlocked(
|
|
1593
|
+
"benchmark.campaign.operation_guard_failed",
|
|
1594
|
+
) from None
|
|
1595
|
+
active_claim = store.renew_report_finalization(
|
|
1596
|
+
active_claim, now=current_now, lease_seconds=lease_seconds,
|
|
1597
|
+
)
|
|
1598
|
+
|
|
1599
|
+
try:
|
|
1600
|
+
store.summarize(
|
|
1601
|
+
policy,
|
|
1602
|
+
campaign_id,
|
|
1603
|
+
authority,
|
|
1604
|
+
now=_timestamp(clock()),
|
|
1605
|
+
operation_guard=renew,
|
|
1606
|
+
)
|
|
1607
|
+
renew()
|
|
1608
|
+
return store.complete_report_finalization(
|
|
1609
|
+
policy, active_claim, now=_timestamp(clock()),
|
|
1610
|
+
)
|
|
1611
|
+
except Exception as error:
|
|
1612
|
+
code = getattr(error, "code", None)
|
|
1613
|
+
if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
|
|
1614
|
+
code = "benchmark.campaign.report_unexpected"
|
|
1615
|
+
if code == "benchmark.campaign.operation_guard_failed":
|
|
1616
|
+
raise
|
|
1617
|
+
terminal = {
|
|
1618
|
+
"benchmark.campaign.policy_mismatch",
|
|
1619
|
+
"benchmark.campaign.report_invalid",
|
|
1620
|
+
"benchmark.campaign.report_state_invalid",
|
|
1621
|
+
"benchmark.campaign.state_invalid",
|
|
1622
|
+
"benchmark.campaign.validity_expired",
|
|
1623
|
+
}
|
|
1624
|
+
retryable = code not in terminal
|
|
1625
|
+
delay = _retry_delay(
|
|
1626
|
+
active_claim.attempt, retry_base_seconds, retry_max_seconds,
|
|
1627
|
+
) if retryable else 0
|
|
1628
|
+
return store.transition_report_failure(
|
|
1629
|
+
policy,
|
|
1630
|
+
active_claim,
|
|
1631
|
+
code,
|
|
1632
|
+
retryable=retryable,
|
|
1633
|
+
delay_seconds=delay,
|
|
1634
|
+
detail=type(error).__name__,
|
|
1635
|
+
now=_timestamp(clock()),
|
|
1636
|
+
)
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
def run_next_benchmark_case(
|
|
1640
|
+
store: BenchmarkCampaignStore,
|
|
1641
|
+
policy: Any,
|
|
1642
|
+
campaign_id: str,
|
|
1643
|
+
worker_id: str,
|
|
1644
|
+
input_resolver: BenchmarkInputResolver,
|
|
1645
|
+
reviewer: Any,
|
|
1646
|
+
*,
|
|
1647
|
+
blinding_key: bytes,
|
|
1648
|
+
native_reference_verifier: Any,
|
|
1649
|
+
evidence_authority: Any,
|
|
1650
|
+
clock: Callable[[], float] = time.time,
|
|
1651
|
+
lease_seconds: Any = 300,
|
|
1652
|
+
retry_base_seconds: Any = 5,
|
|
1653
|
+
retry_max_seconds: Any = 3600,
|
|
1654
|
+
operation_guard: Callable[[float], Any] | None = None,
|
|
1655
|
+
) -> BenchmarkCampaignOutcome | None:
|
|
1656
|
+
"""Resolve and evaluate at most one durable benchmark case."""
|
|
1657
|
+
if not isinstance(store, BenchmarkCampaignStore):
|
|
1658
|
+
raise TypeError("store must be BenchmarkCampaignStore")
|
|
1659
|
+
if not callable(input_resolver) or not callable(clock):
|
|
1660
|
+
raise TypeError("input_resolver and clock must be callable")
|
|
1661
|
+
if operation_guard is not None and not callable(operation_guard):
|
|
1662
|
+
raise TypeError("operation_guard must be callable")
|
|
1663
|
+
lease_seconds = _duration(lease_seconds)
|
|
1664
|
+
retry_base_seconds = _duration(retry_base_seconds, allow_zero=True)
|
|
1665
|
+
retry_max_seconds = _duration(retry_max_seconds, allow_zero=True)
|
|
1666
|
+
if retry_base_seconds > retry_max_seconds:
|
|
1667
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.retry_invalid")
|
|
1668
|
+
claim = store.claim(
|
|
1669
|
+
policy, campaign_id, worker_id, now=_timestamp(clock()),
|
|
1670
|
+
lease_seconds=lease_seconds,
|
|
1671
|
+
)
|
|
1672
|
+
if claim is None:
|
|
1673
|
+
return None
|
|
1674
|
+
active = claim
|
|
1675
|
+
|
|
1676
|
+
def renew(_: str) -> None:
|
|
1677
|
+
nonlocal active
|
|
1678
|
+
current_now = _timestamp(clock())
|
|
1679
|
+
_assert_policy_current(policy, current_now)
|
|
1680
|
+
if operation_guard is not None:
|
|
1681
|
+
try:
|
|
1682
|
+
operation_guard(lease_seconds)
|
|
1683
|
+
except Exception:
|
|
1684
|
+
raise BenchmarkCampaignBlocked("benchmark.campaign.operation_guard_failed") from None
|
|
1685
|
+
active = store.renew(
|
|
1686
|
+
active, now=current_now, lease_seconds=lease_seconds,
|
|
1687
|
+
)
|
|
1688
|
+
|
|
1689
|
+
try:
|
|
1690
|
+
renew("dependencies")
|
|
1691
|
+
guarded_resolve = getattr(
|
|
1692
|
+
input_resolver, "resolve_with_operation_guard", None,
|
|
1693
|
+
)
|
|
1694
|
+
if callable(guarded_resolve):
|
|
1695
|
+
inputs = _benchmark_case_inputs(guarded_resolve(
|
|
1696
|
+
claim.job_payload,
|
|
1697
|
+
lambda: renew("dependency_operation"),
|
|
1698
|
+
))
|
|
1699
|
+
else:
|
|
1700
|
+
inputs = _benchmark_case_inputs(input_resolver(claim.job_payload))
|
|
1701
|
+
renew("benchmark")
|
|
1702
|
+
result = _BENCHMARK.run_blind_benchmark_case(
|
|
1703
|
+
claim.job_payload,
|
|
1704
|
+
inputs.candidate_result,
|
|
1705
|
+
inputs.baseline_artifact,
|
|
1706
|
+
inputs.assets,
|
|
1707
|
+
policy,
|
|
1708
|
+
reviewer,
|
|
1709
|
+
blinding_key=blinding_key,
|
|
1710
|
+
native_reference_artifact=inputs.native_reference_artifact,
|
|
1711
|
+
native_reference_verifier=native_reference_verifier,
|
|
1712
|
+
evidence_authority=evidence_authority,
|
|
1713
|
+
progress_callback=renew,
|
|
1714
|
+
)
|
|
1715
|
+
except BenchmarkCampaignDependencyFailed as error:
|
|
1716
|
+
code = "benchmark.campaign.dependency." + error.code
|
|
1717
|
+
if len(code) > 128:
|
|
1718
|
+
code = "benchmark.campaign.dependency_failed"
|
|
1719
|
+
retryable = error.retryable
|
|
1720
|
+
except _BENCHMARK.BenchmarkBlocked as error:
|
|
1721
|
+
code = error.code
|
|
1722
|
+
declared_retryability = getattr(error, "retryable", None)
|
|
1723
|
+
retryable = (
|
|
1724
|
+
declared_retryability
|
|
1725
|
+
if isinstance(declared_retryability, bool)
|
|
1726
|
+
else code.startswith("reviewer.") or code in {
|
|
1727
|
+
"benchmark.attestation.sign_failed",
|
|
1728
|
+
"benchmark.attestation.verify_failed",
|
|
1729
|
+
}
|
|
1730
|
+
)
|
|
1731
|
+
except BenchmarkCampaignBlocked as error:
|
|
1732
|
+
if error.code != "benchmark.campaign.validity_expired":
|
|
1733
|
+
raise
|
|
1734
|
+
code = error.code
|
|
1735
|
+
retryable = False
|
|
1736
|
+
except Exception as error:
|
|
1737
|
+
if getattr(error, "benchmark_campaign_dependency_failure", None) is True:
|
|
1738
|
+
dependency_code = getattr(error, "code", None)
|
|
1739
|
+
dependency_retryable = getattr(error, "retryable", None)
|
|
1740
|
+
if (
|
|
1741
|
+
isinstance(dependency_code, str)
|
|
1742
|
+
and ERROR_CODE.fullmatch(dependency_code) is not None
|
|
1743
|
+
and isinstance(dependency_retryable, bool)
|
|
1744
|
+
):
|
|
1745
|
+
code = "benchmark.campaign.dependency." + dependency_code
|
|
1746
|
+
if len(code) > 128:
|
|
1747
|
+
code = "benchmark.campaign.dependency_failed"
|
|
1748
|
+
retryable = dependency_retryable
|
|
1749
|
+
else:
|
|
1750
|
+
code = "benchmark.campaign.unexpected"
|
|
1751
|
+
retryable = True
|
|
1752
|
+
else:
|
|
1753
|
+
code = "benchmark.campaign.unexpected"
|
|
1754
|
+
retryable = True
|
|
1755
|
+
else:
|
|
1756
|
+
try:
|
|
1757
|
+
return store.complete(
|
|
1758
|
+
policy, active, result, evidence_authority,
|
|
1759
|
+
now=_timestamp(clock()),
|
|
1760
|
+
)
|
|
1761
|
+
except BenchmarkCampaignBlocked as error:
|
|
1762
|
+
if error.code != "benchmark.campaign.validity_expired":
|
|
1763
|
+
raise
|
|
1764
|
+
code = error.code
|
|
1765
|
+
retryable = False
|
|
1766
|
+
return store.transition_failure(
|
|
1767
|
+
policy, active, code, retryable=retryable,
|
|
1768
|
+
delay_seconds=_retry_delay(
|
|
1769
|
+
claim.attempt, retry_base_seconds, retry_max_seconds,
|
|
1770
|
+
),
|
|
1771
|
+
now=_timestamp(clock()),
|
|
1772
|
+
)
|