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.
Files changed (436) hide show
  1. package/CHANGELOG.md +11 -185
  2. package/LIESMICH.txt +51 -13
  3. package/README.md +44 -47
  4. package/agent-spine-plugin/.codex-plugin/plugin.json +16 -4
  5. package/agent-spine-plugin/CHANGELOG.md +37 -5
  6. package/agent-spine-plugin/README.md +3 -3
  7. package/agent-spine-plugin/blun.plugin.json +45 -10
  8. package/agent-spine-plugin/docs/artifact-evaluation.md +93 -0
  9. package/agent-spine-plugin/docs/host-integration.md +42 -27
  10. package/agent-spine-plugin/docs/preflight-recall.md +4 -2
  11. package/agent-spine-plugin/docs/session-timeline.md +97 -236
  12. package/agent-spine-plugin/docs/world-model.md +25 -0
  13. package/agent-spine-plugin/hooks/codex.json +1 -1
  14. package/agent-spine-plugin/hooks/hooks.json +1 -1
  15. package/agent-spine-plugin/package.json +1 -3
  16. package/agent-spine-plugin/scripts/check-hosts.js +3 -3
  17. package/agent-spine-plugin/scripts/release-check.js +10 -5
  18. package/agent-spine-plugin/scripts/run-checks.js +4 -1
  19. package/agent-spine-plugin/scripts/run-tests-hermetic.js +32 -6
  20. package/agent-spine-plugin/src/cli-learning.js +15 -0
  21. package/agent-spine-plugin/src/cli.js +2 -0
  22. package/agent-spine-plugin/src/hook.js +32 -32
  23. package/agent-spine-plugin/src/lib/action-lesson-recall.js +73 -8
  24. package/agent-spine-plugin/src/lib/briefing.js +146 -36
  25. package/agent-spine-plugin/src/lib/channel-continuity.js +19 -0
  26. package/agent-spine-plugin/src/lib/delivery-agent-usage.js +14 -7
  27. package/agent-spine-plugin/src/lib/gateway-group-response.js +128 -0
  28. package/agent-spine-plugin/src/lib/gateway-runs.js +24 -15
  29. package/agent-spine-plugin/src/lib/hook-briefing-use.js +13 -3
  30. package/agent-spine-plugin/src/lib/hook-context.js +16 -3
  31. package/agent-spine-plugin/src/lib/hook-output.js +129 -5
  32. package/agent-spine-plugin/src/lib/hook-timeline.js +5 -3
  33. package/agent-spine-plugin/src/lib/indexed-memory.js +2 -2
  34. package/agent-spine-plugin/src/lib/learning-artifact-evaluator.js +114 -0
  35. package/agent-spine-plugin/src/lib/learning-context.js +11 -4
  36. package/agent-spine-plugin/src/lib/learning-measurements.js +2 -2
  37. package/agent-spine-plugin/src/lib/mcp-runtime.js +89 -3
  38. package/agent-spine-plugin/src/lib/mcp-source-context.js +12 -2
  39. package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +91 -8
  40. package/agent-spine-plugin/src/lib/mcp-world-tools.js +2 -2
  41. package/agent-spine-plugin/src/lib/owned-file-lock.js +20 -1
  42. package/agent-spine-plugin/src/lib/persona-runtime.js +2 -2
  43. package/agent-spine-plugin/src/lib/preflight-delivery-id.js +27 -0
  44. package/agent-spine-plugin/src/lib/preflight.js +4 -4
  45. package/agent-spine-plugin/src/lib/session-timeline-codex.js +15 -0
  46. package/agent-spine-plugin/src/lib/session-timeline-contract.js +12 -4
  47. package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +36 -7
  48. package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +13 -10
  49. package/agent-spine-plugin/src/lib/session-timeline-invocation.js +1 -1
  50. package/agent-spine-plugin/src/lib/session-timeline-king.js +14 -0
  51. package/agent-spine-plugin/src/lib/session-timeline-prior.js +18 -12
  52. package/agent-spine-plugin/src/lib/session-timeline-provider.js +5 -0
  53. package/agent-spine-plugin/src/lib/session-timeline-query.js +2 -0
  54. package/agent-spine-plugin/src/lib/session-timeline-results.js +35 -10
  55. package/agent-spine-plugin/src/lib/session-timeline-source-open.js +30 -0
  56. package/agent-spine-plugin/src/lib/session-timeline.js +122 -75
  57. package/agent-spine-plugin/src/lib/source-roots.js +3 -2
  58. package/agent-spine-plugin/src/lib/task-knowledge-context.js +22 -1
  59. package/agent-spine-plugin/src/lib/timeline-continuation-update.js +100 -0
  60. package/agent-spine-plugin/src/lib/timeline-tool-guard.js +30 -7
  61. package/agent-spine-plugin/src/lib/timeline-user-feedback.js +217 -0
  62. package/agent-spine-plugin/src/lib/timeline-world-capture.js +233 -0
  63. package/agent-spine-plugin/src/lib/world-knowledge.js +59 -2
  64. package/agent-spine-plugin/src/lib/world-model.js +64 -9
  65. package/agent-spine-plugin/src/worker.js +13 -1
  66. package/bin/blun.js +43 -28
  67. package/bin/core-bootstrap.js +5 -4
  68. package/bin/king.js +43 -28
  69. package/bin/launcher-mode.js +1 -10
  70. package/bin/launcher-runtime.js +128 -295
  71. package/bin/managed-node.js +0 -0
  72. package/bin/managed-plugin-selection.cjs +0 -1
  73. package/bin/native-module-repair.js +0 -0
  74. package/bin/node-runtime.js +0 -0
  75. package/bin/node-version.js +0 -0
  76. package/bin/plugin-bootstrap.js +56 -120
  77. package/bin/private-paths.js +11 -34
  78. package/bin/standard-tools-bootstrap.js +34 -114
  79. package/bin/turn-thinking-policy.cjs +3 -11
  80. package/bin/update-copy.js +200 -0
  81. package/bin/update-lease.js +0 -0
  82. package/bin/update-notice.js +136 -289
  83. package/bin/verify-agent-behavior.cjs +122 -0
  84. package/bin/verify-agent-components.cjs +104 -0
  85. package/bin/verify-bundled-agent-sources.cjs +57 -0
  86. package/blun.mjs +143076 -135288
  87. package/bundled-agent-sources.json +701 -0
  88. package/package.json +12 -15
  89. package/standard-skills/translate-native/README.md +1293 -0
  90. package/standard-skills/translate-native/SKILL.md +172 -22
  91. package/standard-skills/translate-native/VERSION +1 -1
  92. package/standard-skills/translate-native/agents/openai.yaml +18 -0
  93. package/standard-skills/translate-native/assets/icon.svg +8 -0
  94. package/standard-skills/translate-native/docs/BLUN_CODE_INTEGRATION.md +76 -0
  95. package/standard-skills/translate-native/docs/PREMORTEM.md +489 -0
  96. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +2035 -0
  97. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1302 -0
  98. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +136 -0
  99. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HEALTH_HTTP.md +130 -0
  100. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +175 -0
  101. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +86 -0
  102. package/standard-skills/translate-native/integrations/AGENT_RULES.md +32 -0
  103. package/standard-skills/translate-native/integrations/adapters/blun-code-language-guard.js +514 -0
  104. package/standard-skills/translate-native/integrations/adapters/node-language-guard.js +230 -0
  105. package/standard-skills/translate-native/integrations/audit_log.py +327 -0
  106. package/standard-skills/translate-native/integrations/claude_language_hook.js +1536 -0
  107. package/standard-skills/translate-native/integrations/commercial_localization_profile.py +42 -0
  108. package/standard-skills/translate-native/integrations/delivery-policy.example.json +28 -0
  109. package/standard-skills/translate-native/integrations/enforced_delivery.py +543 -0
  110. package/standard-skills/translate-native/integrations/guard_service.py +435 -0
  111. package/standard-skills/translate-native/integrations/language_gateway.py +67 -0
  112. package/standard-skills/translate-native/integrations/mcp_auth_headers.py +198 -0
  113. package/standard-skills/translate-native/integrations/mcp_http_gateway.py +429 -0
  114. package/standard-skills/translate-native/integrations/non_language_html_entities.js +1485 -0
  115. package/standard-skills/translate-native/integrations/pre_output_guard.py +65 -0
  116. package/standard-skills/translate-native/integrations/task_router.py +101 -0
  117. package/standard-skills/translate-native/integrations/website_localization.py +401 -0
  118. package/standard-skills/translate-native/integrations/website_localization_api.py +581 -0
  119. package/standard-skills/translate-native/integrations/website_localization_benchmark.py +1885 -0
  120. package/standard-skills/translate-native/integrations/website_localization_benchmark_campaign.py +1772 -0
  121. package/standard-skills/translate-native/integrations/website_localization_benchmark_candidate.py +506 -0
  122. package/standard-skills/translate-native/integrations/website_localization_benchmark_http.py +400 -0
  123. package/standard-skills/translate-native/integrations/website_localization_benchmark_review_store.py +781 -0
  124. package/standard-skills/translate-native/integrations/website_localization_benchmark_reviewer_http.py +500 -0
  125. package/standard-skills/translate-native/integrations/website_localization_benchmark_runtime.py +1107 -0
  126. package/standard-skills/translate-native/integrations/website_localization_benchmark_suite.py +463 -0
  127. package/standard-skills/translate-native/integrations/website_localization_cms.py +2835 -0
  128. package/standard-skills/translate-native/integrations/website_localization_cms_client.py +875 -0
  129. package/standard-skills/translate-native/integrations/website_localization_cms_dispatch.py +805 -0
  130. package/standard-skills/translate-native/integrations/website_localization_cms_http.py +588 -0
  131. package/standard-skills/translate-native/integrations/website_localization_cms_lifecycle_monitor.py +991 -0
  132. package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +1441 -0
  133. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +414 -0
  134. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +1073 -0
  135. package/standard-skills/translate-native/integrations/website_localization_cms_removal_dispatch.py +865 -0
  136. package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +583 -0
  137. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +964 -0
  138. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +665 -0
  139. package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +1153 -0
  140. package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +675 -0
  141. package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +1125 -0
  142. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification.py +674 -0
  143. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +444 -0
  144. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +1469 -0
  145. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +1142 -0
  146. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +634 -0
  147. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +804 -0
  148. package/standard-skills/translate-native/integrations/website_localization_deepl_baseline.py +922 -0
  149. package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +482 -0
  150. package/standard-skills/translate-native/integrations/website_localization_health.py +1541 -0
  151. package/standard-skills/translate-native/integrations/website_localization_health_http.py +372 -0
  152. package/standard-skills/translate-native/integrations/website_localization_http_provider.py +297 -0
  153. package/standard-skills/translate-native/integrations/website_localization_native_reference_http.py +479 -0
  154. package/standard-skills/translate-native/integrations/website_localization_native_reference_intake.py +363 -0
  155. package/standard-skills/translate-native/integrations/website_localization_native_reference_queue.py +1449 -0
  156. package/standard-skills/translate-native/integrations/website_localization_native_reference_store.py +420 -0
  157. package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +235 -0
  158. package/standard-skills/translate-native/integrations/website_localization_queue.py +671 -0
  159. package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +516 -0
  160. package/standard-skills/translate-native/integrations/website_localization_release.py +928 -0
  161. package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +1008 -0
  162. package/standard-skills/translate-native/integrations/website_localization_runner.py +276 -0
  163. package/standard-skills/translate-native/integrations/website_localization_runtime.py +862 -0
  164. package/standard-skills/translate-native/integrations/website_localization_service.py +350 -0
  165. package/standard-skills/translate-native/integrations/website_localization_supervisor.py +511 -0
  166. package/standard-skills/translate-native/integrations/website_localization_worker.py +663 -0
  167. package/standard-skills/translate-native/provenance.json +3 -4
  168. package/standard-skills/translate-native/references/commercial-localization.md +177 -0
  169. package/standard-skills/translate-native/scripts/blun_language_guard.py +7 -1
  170. package/standard-skills/translate-native/scripts/check_commercial_review.py +80 -0
  171. package/standard-skills/translate-native/scripts/commercial_localization_profile.py +333 -0
  172. package/standard-tools/language-guard/LICENSE +21 -0
  173. package/standard-tools/language-guard/VERSION +1 -0
  174. package/standard-tools/language-guard/blun_language_guard.py +7 -1
  175. package/standard-tools/language-guard/check_commercial_review.py +80 -0
  176. package/standard-tools/language-guard/commercial_localization_profile.py +333 -0
  177. package/standard-tools/language-guard/language_gateway.py +62 -0
  178. package/standard-tools/language-guard/pre_output_guard.py +64 -0
  179. package/standard-tools/language-guard/provenance.json +4 -11
  180. package/standard-tools/manifest.json +34 -11
  181. package/telegram-plugin/commands/access.md +2 -10
  182. package/telegram-plugin/dist/bridge.mjs +64041 -687
  183. package/telegram-plugin/dist/mcp-server.mjs +72810 -9027
  184. package/telegram-plugin/dist/noise.mjs +28 -63511
  185. package/agent-spine-plugin/CONTRIBUTING.md +0 -52
  186. package/agent-spine-plugin/SECURITY.md +0 -47
  187. package/agent-spine-plugin/docs/assignment-continuation.md +0 -48
  188. package/agent-spine-plugin/docs/releasing.md +0 -85
  189. package/agent-spine-plugin/docs/structured-completion.md +0 -67
  190. package/bin/abort-listener-policy.cjs +0 -43
  191. package/bin/active-steer-priority-policy.cjs +0 -24
  192. package/bin/agent-api-http-adapter.mjs +0 -446
  193. package/bin/agent-api-private-http-server.mjs +0 -288
  194. package/bin/agent-api-runtime.mjs +0 -252
  195. package/bin/agent-api-service-environment.mjs +0 -236
  196. package/bin/agent-api-service-host.mjs +0 -209
  197. package/bin/agent-api-service-process.mjs +0 -171
  198. package/bin/agent-api-session-registry.mjs +0 -428
  199. package/bin/agent-api-tool-broker.cjs +0 -248
  200. package/bin/agent-api-turn-controller.mjs +0 -461
  201. package/bin/agent-api-usage-journal.cjs +0 -259
  202. package/bin/agent-resume-snapshot.cjs +0 -241
  203. package/bin/agentspine-king-goal-inbox.mjs +0 -111
  204. package/bin/agentspine-king-goal-intake.mjs +0 -106
  205. package/bin/approval-rejection-stop.cjs +0 -15
  206. package/bin/assistant-message-offload-policy.cjs +0 -284
  207. package/bin/baseline-skill-performance-policy.cjs +0 -39
  208. package/bin/bash-search-scope-policy.cjs +0 -49
  209. package/bin/codebase-search-runtime.cjs +0 -23
  210. package/bin/cognitive-action-checkpoint.cjs +0 -1104
  211. package/bin/cognitive-attention-delivery.cjs +0 -76
  212. package/bin/cognitive-attention-policy.cjs +0 -143
  213. package/bin/cognitive-attention-runtime.cjs +0 -91
  214. package/bin/cognitive-context-projection.cjs +0 -73
  215. package/bin/cognitive-cross-portal-acceptance.cjs +0 -443
  216. package/bin/cognitive-effective-view.cjs +0 -77
  217. package/bin/cognitive-focus-projection.cjs +0 -206
  218. package/bin/cognitive-focus-scope.cjs +0 -37
  219. package/bin/cognitive-goal-autostart-policy.cjs +0 -72
  220. package/bin/cognitive-goal-time-trigger-controller.cjs +0 -146
  221. package/bin/cognitive-memory-adapter.cjs +0 -282
  222. package/bin/cognitive-memory-command.cjs +0 -293
  223. package/bin/cognitive-memory-provider.cjs +0 -92
  224. package/bin/cognitive-salience-policy.cjs +0 -159
  225. package/bin/cognitive-state-store.cjs +0 -508
  226. package/bin/cognitive-turn-lifecycle.cjs +0 -624
  227. package/bin/cognitive-work-focus.cjs +0 -180
  228. package/bin/compaction-history-archive.cjs +0 -166
  229. package/bin/compaction-history-startup.cjs +0 -50
  230. package/bin/compaction-model-policy.cjs +0 -31
  231. package/bin/compaction-stage-policy.cjs +0 -21
  232. package/bin/compaction-transaction-policy.cjs +0 -122
  233. package/bin/config-write-dedup-policy.cjs +0 -27
  234. package/bin/context-budget-ledger.cjs +0 -31
  235. package/bin/context-doctor-policy.cjs +0 -70
  236. package/bin/context-insight-policy.cjs +0 -36
  237. package/bin/context-performance-policy.cjs +0 -19
  238. package/bin/context-pressure-policy.cjs +0 -20
  239. package/bin/cron-run-output.cjs +0 -45
  240. package/bin/cron-run-store.cjs +0 -145
  241. package/bin/curiosity-scout-policy.cjs +0 -49
  242. package/bin/default-model-output-budget-policy.cjs +0 -28
  243. package/bin/durable-task-resume-policy.cjs +0 -130
  244. package/bin/durable-task-resume-runtime.cjs +0 -117
  245. package/bin/durable-task-resume-store.cjs +0 -88
  246. package/bin/editable-tool-approval-policy.cjs +0 -540
  247. package/bin/editable-tool-approval-runtime.cjs +0 -99
  248. package/bin/effective-system-prompt-cache-policy.cjs +0 -33
  249. package/bin/error-memory-performance-policy.cjs +0 -113
  250. package/bin/file-observation-policy.cjs +0 -133
  251. package/bin/foreground-output-capture-policy.cjs +0 -41
  252. package/bin/generated-source-health.cjs +0 -142
  253. package/bin/glob-pattern-policy.cjs +0 -13
  254. package/bin/goal-completion-evidence-policy.cjs +0 -120
  255. package/bin/grep-output-limit-policy.cjs +0 -39
  256. package/bin/historical-media-projection-policy.cjs +0 -48
  257. package/bin/history-offload-pressure-policy.cjs +0 -33
  258. package/bin/html-to-research-markdown.cjs +0 -147
  259. package/bin/identity-context-policy.cjs +0 -764
  260. package/bin/identity-journal-policy.cjs +0 -107
  261. package/bin/input-draft-persistence.cjs +0 -77
  262. package/bin/king-tui-function-contract.json +0 -33
  263. package/bin/launcher-restart-policy.cjs +0 -150
  264. package/bin/live-response-repetition-guard.cjs +0 -196
  265. package/bin/llm-config-log-dedup-policy.cjs +0 -76
  266. package/bin/loop-event-record-policy.cjs +0 -174
  267. package/bin/managed-context-startup-policy.cjs +0 -27
  268. package/bin/media-activity-layout-policy.cjs +0 -34
  269. package/bin/media-auto-retrieval-policy.cjs +0 -90
  270. package/bin/media-result-policy.cjs +0 -59
  271. package/bin/micro-compaction-policy.cjs +0 -145
  272. package/bin/mistake-relevance-policy.cjs +0 -319
  273. package/bin/model-retry-progress-policy.cjs +0 -46
  274. package/bin/native-large-file-io.cjs +0 -42
  275. package/bin/native-runtime-cache.cjs +0 -76
  276. package/bin/natural-presence-policy.cjs +0 -28
  277. package/bin/noninteractive-shell-env-policy.cjs +0 -19
  278. package/bin/observer-hooks.cjs +0 -14
  279. package/bin/outbound-claim-provenance.cjs +0 -150
  280. package/bin/oversized-context-offload-policy.cjs +0 -86
  281. package/bin/pending-media-policy.cjs +0 -182
  282. package/bin/pending-token-estimate-policy.cjs +0 -41
  283. package/bin/personal-memory-consent-policy.cjs +0 -72
  284. package/bin/personal-memory-performance-policy.cjs +0 -12
  285. package/bin/personality-choice-policy.cjs +0 -101
  286. package/bin/personality-memory-adapter.cjs +0 -379
  287. package/bin/personality-mode.cjs +0 -46
  288. package/bin/personality-setup-policy.cjs +0 -197
  289. package/bin/proactive-compaction-policy.cjs +0 -25
  290. package/bin/profile-identity-resolution.cjs +0 -136
  291. package/bin/profile-runtime.cjs +0 -318
  292. package/bin/profile-tool-exclusion-policy.cjs +0 -37
  293. package/bin/programmatic-context-isolation.cjs +0 -25
  294. package/bin/programmatic-tool-runtime.mjs +0 -627
  295. package/bin/provider-idle-timeout-policy.cjs +0 -14
  296. package/bin/provider-model-refresh-deadline.cjs +0 -53
  297. package/bin/provider-model-refresh-policy.cjs +0 -107
  298. package/bin/rate-limit-recovery-policy.cjs +0 -47
  299. package/bin/read-batch-policy.cjs +0 -32
  300. package/bin/read-continuation-policy.cjs +0 -59
  301. package/bin/recurring-cron-history-policy.cjs +0 -124
  302. package/bin/relationship-continuity-policy.cjs +0 -143
  303. package/bin/relationship-curiosity-policy.cjs +0 -107
  304. package/bin/relationship-learning-policy.cjs +0 -168
  305. package/bin/release-artifact-freeze-policy.cjs +0 -30
  306. package/bin/reload-plugin-bootstrap.cjs +0 -18
  307. package/bin/reload-queue-policy.cjs +0 -38
  308. package/bin/repeated-assistant-response-policy.cjs +0 -232
  309. package/bin/repeated-injection-projection.cjs +0 -107
  310. package/bin/repeated-user-message-projection.cjs +0 -8
  311. package/bin/research-page-result.cjs +0 -74
  312. package/bin/retry-checkpoint-policy.cjs +0 -13
  313. package/bin/runtime-exit-ledger.cjs +0 -144
  314. package/bin/scoped-cron-run-policy.cjs +0 -358
  315. package/bin/session-checkpoint-policy.cjs +0 -25
  316. package/bin/session-compaction-policy.cjs +0 -84
  317. package/bin/session-replay-policy.cjs +0 -20
  318. package/bin/session-replay-window-policy.cjs +0 -40
  319. package/bin/session-resume-checkpoint.cjs +0 -254
  320. package/bin/session-scrollback-archive.cjs +0 -229
  321. package/bin/skill-activation-performance-policy.cjs +0 -69
  322. package/bin/skill-listing-performance-policy.cjs +0 -92
  323. package/bin/soul-organization-policy.cjs +0 -78
  324. package/bin/soul-preservation-policy.cjs +0 -20
  325. package/bin/startup-preferences.cjs +0 -131
  326. package/bin/streaming-flush-performance-policy.cjs +0 -28
  327. package/bin/structured-agent-swarm-output.cjs +0 -325
  328. package/bin/structured-subagent-output.cjs +0 -252
  329. package/bin/subagent-context-fork-policy.cjs +0 -155
  330. package/bin/subagent-max-tokens-handoff-policy.cjs +0 -69
  331. package/bin/subagent-parent-responsiveness.cjs +0 -19
  332. package/bin/subagent-skill-policy.cjs +0 -206
  333. package/bin/subagent-timeout-policy.cjs +0 -182
  334. package/bin/subagent-tool-policy.cjs +0 -60
  335. package/bin/subagent-usage-rollup-policy.cjs +0 -29
  336. package/bin/system-prompt-context-policy.cjs +0 -124
  337. package/bin/system-prompt-token-cache-policy.cjs +0 -60
  338. package/bin/telegram-addressed-focus.cjs +0 -55
  339. package/bin/telegram-addressed-priority.cjs +0 -12
  340. package/bin/telegram-approval-relay.cjs +0 -290
  341. package/bin/telegram-bot-priority.cjs +0 -17
  342. package/bin/telegram-console-status-policy.cjs +0 -174
  343. package/bin/telegram-context-projection-policy.cjs +0 -141
  344. package/bin/telegram-delivery-lifecycle.cjs +0 -125
  345. package/bin/telegram-direct-focus-policy.cjs +0 -273
  346. package/bin/telegram-mcp-compatibility.cjs +0 -49
  347. package/bin/telegram-media-delivery-policy.cjs +0 -42
  348. package/bin/telegram-private-conversation-policy.cjs +0 -185
  349. package/bin/telegram-queue-handoff-policy.cjs +0 -73
  350. package/bin/telegram-remote-status-policy.cjs +0 -120
  351. package/bin/telegram-session-queue-runtime.mjs +0 -306
  352. package/bin/telegram-text-chunk-policy.cjs +0 -63
  353. package/bin/telegram-truncated-reply-policy.cjs +0 -37
  354. package/bin/telegram-urgent-policy.cjs +0 -45
  355. package/bin/telemetry-spool-policy.cjs +0 -57
  356. package/bin/thinking-activity-status-policy.cjs +0 -132
  357. package/bin/thinking-only-guard.cjs +0 -80
  358. package/bin/todo-list-turn-policy.cjs +0 -131
  359. package/bin/tool-call-loop-policy.cjs +0 -51
  360. package/bin/tool-file-persistence.cjs +0 -141
  361. package/bin/tool-result-offload-policy.cjs +0 -359
  362. package/bin/tool-result-offload-telemetry.cjs +0 -12
  363. package/bin/tool-schema-token-cache-policy.cjs +0 -41
  364. package/bin/tool-stream-preview-policy.cjs +0 -9
  365. package/bin/tui-functional-contract.cjs +0 -55
  366. package/bin/turn-tool-performance-policy.cjs +0 -486
  367. package/bin/usage-cache-efficiency-policy.cjs +0 -26
  368. package/bin/user-home-path-policy.cjs +0 -13
  369. package/bin/user-message-offload-policy.cjs +0 -103
  370. package/bin/user-prompt-hook-origin-policy.cjs +0 -34
  371. package/bin/user-tool-record-policy.cjs +0 -7
  372. package/bin/validated-learning-insight-policy.cjs +0 -58
  373. package/bin/validated-learning-outcome-trace.cjs +0 -107
  374. package/bin/validated-learning-performance-policy.cjs +0 -53
  375. package/bin/validated-learning-signal.cjs +0 -463
  376. package/bin/windows-bash-dialect-policy.cjs +0 -25
  377. package/bin/windows-node-crash-dump.cjs +0 -110
  378. package/bin/write-continuation-policy.cjs +0 -69
  379. package/codebase-index/README.md +0 -82
  380. package/codebase-index/codebase_index.py +0 -470
  381. package/standard-skills/agent-browser/SKILL.md +0 -19
  382. package/standard-skills/agent-browser/references/runtime.md +0 -8
  383. package/standard-skills/blun-session-inspector/SKILL.md +0 -41
  384. package/standard-skills/blun-session-inspector/scripts/inspect-session.cjs +0 -437
  385. package/standard-skills/design-taste-frontend/SKILL.md +0 -1206
  386. package/standard-skills/full-output-enforcement/SKILL.md +0 -49
  387. package/standard-skills/high-end-visual-design/SKILL.md +0 -98
  388. package/standard-skills/image-to-code/SKILL.md +0 -1228
  389. package/standard-skills/industrial-brutalist-ui/SKILL.md +0 -92
  390. package/standard-skills/minimalist-ui/SKILL.md +0 -85
  391. package/standard-skills/motion-design-taste/SKILL.md +0 -74
  392. package/standard-skills/playwright-testing/SKILL.md +0 -19
  393. package/standard-skills/playwright-testing/references/runtime.md +0 -7
  394. package/standard-skills/premortem/SKILL.md +0 -148
  395. package/standard-skills/redesign-existing-projects/SKILL.md +0 -178
  396. package/standard-skills/research-evidence/SKILL.md +0 -39
  397. package/standard-skills/research-evidence/references/evidence-format.md +0 -104
  398. package/standard-skills/research-evidence/scripts/evidence-collection.cjs +0 -260
  399. package/standard-skills/research-evidence/scripts/score-report.cjs +0 -130
  400. package/standard-skills/screenshot-lesen/SKILL.md +0 -52
  401. package/standard-skills/stitch-design-taste/DESIGN.md +0 -121
  402. package/standard-skills/stitch-design-taste/SKILL.md +0 -184
  403. package/standard-skills/telegram-channel/SKILL.md +0 -18
  404. package/standard-skills/telegram-channel/references/runtime.md +0 -7
  405. package/standard-skills/venture-flywheel/SKILL.md +0 -32
  406. package/standard-skills/venture-flywheel/identity/project-identity.cjs +0 -146
  407. package/standard-skills/venture-flywheel/policy/capability-engine.cjs +0 -114
  408. package/standard-skills/venture-flywheel/policy/repository-trust.cjs +0 -229
  409. package/standard-skills/venture-flywheel/references/BEISPIELE-phase0.md +0 -146
  410. package/standard-skills/venture-flywheel/references/CAPABILITY-MAP.md +0 -34
  411. package/standard-skills/venture-flywheel/references/SPEC-phase0-identity-trust.md +0 -77
  412. package/standard-skills/venture-flywheel/references/SPEC-phase0-state-events.md +0 -93
  413. package/standard-skills/venture-flywheel/schemas/capability-decision.schema.json +0 -13
  414. package/standard-skills/venture-flywheel/schemas/execution-event.schema.json +0 -44
  415. package/standard-skills/venture-flywheel/schemas/project-identity.schema.json +0 -32
  416. package/standard-skills/venture-flywheel/schemas/repository-trust.schema.json +0 -57
  417. package/standard-skills/venture-flywheel/schemas/run-transition.schema.json +0 -59
  418. package/standard-skills/venture-flywheel/state/execution-event.cjs +0 -191
  419. package/standard-skills/venture-flywheel/state/task-state-machine.cjs +0 -190
  420. package/standard-skills/web-lesen/SKILL.md +0 -73
  421. package/standard-skills/web-lesen/scripts/crawl_public.py +0 -379
  422. package/standard-skills/windows-mcp/SKILL.md +0 -19
  423. package/standard-skills/windows-mcp/references/runtime.md +0 -9
  424. package/telegram-plugin/DELIVERY.md +0 -36
  425. package/telegram-plugin/bin/telegram-approval-relay.cjs +0 -290
  426. package/telegram-plugin/bin/telegram-console-status-policy.cjs +0 -175
  427. package/telegram-plugin/bin/telegram-delivery-lifecycle.cjs +0 -125
  428. package/telegram-plugin/bin/telegram-direct-reply-policy.cjs +0 -48
  429. package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +0 -122
  430. package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +0 -186
  431. package/telegram-plugin/bin/telegram-remote-status-policy.cjs +0 -121
  432. package/telegram-plugin/bin/telegram-reply-parts.cjs +0 -149
  433. package/telegram-plugin/bin/telegram-text-chunk-policy.cjs +0 -63
  434. package/telegram-plugin/bin/telegram-typing-keepalive.cjs +0 -89
  435. package/telegram-plugin/compat/mcp-server-fa511cd1.mjs +0 -73825
  436. /package/{bin → scripts}/fix-node-pty-perms.js +0 -0
@@ -0,0 +1,583 @@
1
+ #!/usr/bin/env python3
2
+ """Contract-pinned HTTPS client for the durable source-CMS ingress.
3
+
4
+ Website backends use this adapter to enqueue one immutable source change or
5
+ removal and to inspect only content-free operational state. Every operation
6
+ first verifies the live public contract, performs one bounded request against
7
+ one fixed origin, and binds the response to the request and contract digest.
8
+ Retry scheduling remains the caller's responsibility.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import hashlib
14
+ import importlib.util
15
+ import json
16
+ import math
17
+ import re
18
+ import socket
19
+ import sys
20
+ import unicodedata
21
+ import urllib.error
22
+ import urllib.parse
23
+ import urllib.request
24
+ from dataclasses import dataclass
25
+ from pathlib import Path
26
+ from typing import Any, Callable, Mapping, Protocol
27
+
28
+
29
+ MAX_ENDPOINT_LENGTH = 2_048
30
+ MAX_HEADER_VALUE_LENGTH = 4_096
31
+ # Leave six slots for Host, Content-Length, Accept, Content-Type, idempotency,
32
+ # and the exact request-body binding header at the WSGI boundary.
33
+ MAX_AUTHENTICATION_HEADERS = 58
34
+ SHA256 = re.compile(r"^[a-f0-9]{64}$")
35
+ TOKEN = re.compile(r"^[A-Za-z0-9_.:-]{1,256}$")
36
+ ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
37
+ RESERVED_HEADERS = {
38
+ "accept", "connection", "content-length", "content-type", "host",
39
+ "idempotency-key", "transfer-encoding",
40
+ "x-localization-source-payload-sha256",
41
+ }
42
+
43
+
44
+ def _load_module(name: str, path: Path):
45
+ spec = importlib.util.spec_from_file_location(name, path)
46
+ if spec is None or spec.loader is None:
47
+ raise RuntimeError(f"cannot load source client dependency: {path.name}")
48
+ module = importlib.util.module_from_spec(spec)
49
+ sys.modules[spec.name] = module
50
+ spec.loader.exec_module(module)
51
+ return module
52
+
53
+
54
+ _ROOT = Path(__file__).resolve().parents[1]
55
+ _HTTP = _load_module(
56
+ "blun_website_localization_cms_source_client_http",
57
+ _ROOT / "integrations" / "website_localization_cms_source_http.py",
58
+ )
59
+ _CMS = _load_module(
60
+ "blun_website_localization_cms_source_client_cms",
61
+ _ROOT / "integrations" / "website_localization_cms.py",
62
+ )
63
+
64
+
65
+ class CMSSourceClientBlocked(RuntimeError):
66
+ """Stable, content-free client failure with an explicit retry decision."""
67
+
68
+ cms_source_client_failure = True
69
+
70
+ def __init__(self, code: str, *, retryable: bool):
71
+ if ERROR_CODE.fullmatch(code) is None or not isinstance(retryable, bool):
72
+ raise ValueError("source client failure is invalid")
73
+ super().__init__(code)
74
+ self.code = code
75
+ self.retryable = retryable
76
+
77
+
78
+ @dataclass(frozen=True)
79
+ class HTTPResult:
80
+ status: int
81
+ headers: tuple[tuple[str, str], ...]
82
+ body: bytes
83
+
84
+
85
+ class HTTPTransport(Protocol):
86
+ def request(
87
+ self,
88
+ method: str,
89
+ url: str,
90
+ headers: Mapping[str, str],
91
+ body: bytes | None,
92
+ *,
93
+ timeout: float,
94
+ ) -> HTTPResult: ...
95
+
96
+
97
+ class _NoRedirect(urllib.request.HTTPRedirectHandler):
98
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
99
+ return None
100
+
101
+
102
+ class URLTransport:
103
+ """Perform one bounded HTTPS request without following redirects."""
104
+
105
+ def __init__(self):
106
+ self._opener = urllib.request.build_opener(_NoRedirect)
107
+
108
+ def request(self, method, url, headers, body, *, timeout):
109
+ request = urllib.request.Request(
110
+ url, data=body, headers=dict(headers), method=method,
111
+ )
112
+ try:
113
+ response = self._opener.open(request, timeout=timeout)
114
+ except urllib.error.HTTPError as error:
115
+ response = error
116
+ except (urllib.error.URLError, TimeoutError, socket.timeout, OSError):
117
+ _fail("network", retryable=True)
118
+ try:
119
+ raw = response.read(_HTTP.MAX_BODY_BYTES + 1)
120
+ return HTTPResult(
121
+ int(response.status), tuple(response.headers.items()), raw,
122
+ )
123
+ except (TimeoutError, socket.timeout, OSError):
124
+ _fail("network", retryable=True)
125
+ finally:
126
+ response.close()
127
+
128
+
129
+ def _fail(code: str, *, retryable: bool = False) -> None:
130
+ raise CMSSourceClientBlocked(
131
+ "source_client." + code, retryable=retryable,
132
+ )
133
+
134
+
135
+ def _canonical(value: Any) -> bytes:
136
+ try:
137
+ raw = json.dumps(
138
+ value, ensure_ascii=False, allow_nan=False, sort_keys=True,
139
+ separators=(",", ":"),
140
+ ).encode("utf-8")
141
+ except (TypeError, ValueError, RecursionError):
142
+ _fail("request_invalid")
143
+ if not raw or len(raw) > _HTTP.MAX_BODY_BYTES:
144
+ _fail("request_invalid")
145
+ return raw
146
+
147
+
148
+ def _pairs(items: list[tuple[str, Any]]) -> dict[str, Any]:
149
+ result: dict[str, Any] = {}
150
+ for key, value in items:
151
+ if key in result:
152
+ raise ValueError("duplicate key")
153
+ result[key] = value
154
+ return result
155
+
156
+
157
+ def _constant(_value: str) -> None:
158
+ raise ValueError("non-finite number")
159
+
160
+
161
+ def _token(value: Any) -> bool:
162
+ return (
163
+ isinstance(value, str)
164
+ and TOKEN.fullmatch(value) is not None
165
+ and unicodedata.is_normalized("NFC", value)
166
+ )
167
+
168
+
169
+ def _count(value: Any, *, maximum: int = 1_000_000) -> bool:
170
+ return (
171
+ isinstance(value, int)
172
+ and not isinstance(value, bool)
173
+ and 0 <= value <= maximum
174
+ )
175
+
176
+
177
+ def _endpoint(value: Any, allow_loopback_http: bool) -> str:
178
+ if (
179
+ not isinstance(value, str)
180
+ or value != value.strip()
181
+ or not value
182
+ or not value.isascii()
183
+ or len(value) > MAX_ENDPOINT_LENGTH
184
+ or any(ord(character) <= 32 or ord(character) == 127 for character in value)
185
+ ):
186
+ raise ValueError("origin is invalid")
187
+ try:
188
+ parsed = urllib.parse.urlsplit(value)
189
+ hostname = parsed.hostname
190
+ port = parsed.port
191
+ except ValueError:
192
+ raise ValueError("origin is invalid") from None
193
+ secure = parsed.scheme == "https"
194
+ loopback = (
195
+ parsed.scheme == "http"
196
+ and allow_loopback_http
197
+ and isinstance(hostname, str)
198
+ and hostname.lower() in {"localhost", "127.0.0.1", "::1"}
199
+ )
200
+ if (
201
+ not (secure or loopback)
202
+ or not hostname
203
+ or parsed.username is not None
204
+ or parsed.password is not None
205
+ or parsed.path
206
+ or parsed.query
207
+ or parsed.fragment
208
+ or port is not None and not 1 <= port <= 65_535
209
+ or value != f"{parsed.scheme}://{parsed.netloc}"
210
+ ):
211
+ raise ValueError("origin must be one exact HTTPS origin")
212
+ return value
213
+
214
+
215
+ def _authentication_headers(provider, context) -> dict[str, str]:
216
+ try:
217
+ supplied = provider(dict(context))
218
+ if not isinstance(supplied, Mapping):
219
+ raise TypeError
220
+ items = tuple(supplied.items())
221
+ except Exception:
222
+ _fail("authentication")
223
+ if len(items) > MAX_AUTHENTICATION_HEADERS:
224
+ _fail("authentication")
225
+ result: dict[str, str] = {}
226
+ names: set[str] = set()
227
+ for name, value in items:
228
+ normalized = name.lower() if isinstance(name, str) else ""
229
+ if (
230
+ not isinstance(name, str)
231
+ or _HTTP.HEADER_NAME.fullmatch(name) is None
232
+ or normalized in RESERVED_HEADERS
233
+ or normalized in names
234
+ or not isinstance(value, str)
235
+ or not value
236
+ or len(value) > MAX_HEADER_VALUE_LENGTH
237
+ or "\r" in value
238
+ or "\n" in value
239
+ or any(ord(character) < 32 or ord(character) == 127 for character in value)
240
+ ):
241
+ _fail("authentication")
242
+ names.add(normalized)
243
+ result[name] = value
244
+ if not result:
245
+ _fail("authentication")
246
+ return result
247
+
248
+
249
+ def _response_headers(value: Any) -> dict[str, str]:
250
+ if not isinstance(value, tuple):
251
+ _fail("transport_invalid", retryable=True)
252
+ result: dict[str, str] = {}
253
+ for item in value:
254
+ if (
255
+ not isinstance(item, tuple)
256
+ or len(item) != 2
257
+ or not all(isinstance(part, str) for part in item)
258
+ ):
259
+ _fail("transport_invalid", retryable=True)
260
+ name, content = item[0].lower(), item[1].strip()
261
+ if name in result:
262
+ _fail("response_headers")
263
+ result[name] = content
264
+ return result
265
+
266
+
267
+ def _json_response(result: Any, allowed_statuses: set[int]) -> dict[str, Any]:
268
+ if (
269
+ not isinstance(result, HTTPResult)
270
+ or isinstance(result.status, bool)
271
+ or not isinstance(result.status, int)
272
+ or not 100 <= result.status <= 599
273
+ ):
274
+ _fail("transport_invalid", retryable=True)
275
+ if result.status not in allowed_statuses:
276
+ if 300 <= result.status <= 399:
277
+ _fail("redirect")
278
+ retryable = result.status in {408, 425, 429} or result.status >= 500
279
+ _fail("http_status", retryable=retryable)
280
+ headers = _response_headers(result.headers)
281
+ content_type = headers.get("content-type", "").lower().replace(" ", "")
282
+ if content_type not in {"application/json", "application/json;charset=utf-8"}:
283
+ _fail("response_content_type")
284
+ if (
285
+ not isinstance(result.body, bytes)
286
+ or not result.body
287
+ or len(result.body) > _HTTP.MAX_BODY_BYTES
288
+ ):
289
+ _fail("response_size")
290
+ declared = headers.get("content-length")
291
+ if declared is not None and (
292
+ not declared.isascii()
293
+ or not declared.isdecimal()
294
+ or int(declared) != len(result.body)
295
+ ):
296
+ _fail("response_size")
297
+ try:
298
+ text = result.body.decode("utf-8")
299
+ if text.startswith("\ufeff"):
300
+ raise ValueError
301
+ value = json.loads(
302
+ text, object_pairs_hook=_pairs, parse_constant=_constant,
303
+ )
304
+ except (UnicodeDecodeError, json.JSONDecodeError, ValueError, RecursionError):
305
+ _fail("response_json")
306
+ if not isinstance(value, dict):
307
+ _fail("response_binding")
308
+ return value
309
+
310
+
311
+ def _copy_payload(value: Any, operation: str) -> tuple[dict[str, Any], bytes]:
312
+ if not isinstance(value, Mapping):
313
+ _fail("request_invalid")
314
+ raw = _canonical(dict(value))
315
+ try:
316
+ copied = json.loads(raw.decode("utf-8"), object_pairs_hook=_pairs)
317
+ if operation == "change":
318
+ _CMS.WebsiteLocalizationCMSBridge._validated_event(None, copied)
319
+ elif copied.get("schema") == _CMS.CANCELLATION_SCHEMA:
320
+ operation = "cancellation"
321
+ _CMS.WebsiteLocalizationCMSBridge._validated_cancellation(None, copied)
322
+ elif copied.get("schema") == _CMS.TOMBSTONE_SCHEMA:
323
+ operation = "tombstone"
324
+ _CMS.WebsiteLocalizationCMSBridge._validated_tombstone(None, copied)
325
+ else:
326
+ raise ValueError
327
+ except Exception:
328
+ _fail("request_invalid")
329
+ return copied, raw
330
+
331
+
332
+ class _PayloadView:
333
+ def __init__(self, value: Mapping[str, Any]):
334
+ self.value = value
335
+
336
+ def as_payload(self) -> Mapping[str, Any]:
337
+ return self.value
338
+
339
+
340
+ class CMSLocalizationSourceHTTPClient:
341
+ """Operate one source runtime only through its freshly pinned contract."""
342
+
343
+ def __init__(
344
+ self,
345
+ origin: str,
346
+ expected_capabilities_sha256: str,
347
+ authentication_headers: Callable[[Mapping[str, Any]], Mapping[str, str]],
348
+ *,
349
+ transport: HTTPTransport | None = None,
350
+ timeout: float | int = 30,
351
+ allow_loopback_http: bool = False,
352
+ ):
353
+ if not isinstance(allow_loopback_http, bool):
354
+ raise TypeError("allow_loopback_http must be boolean")
355
+ self.origin = _endpoint(origin, allow_loopback_http)
356
+ if (
357
+ not isinstance(expected_capabilities_sha256, str)
358
+ or SHA256.fullmatch(expected_capabilities_sha256) is None
359
+ ):
360
+ raise ValueError("expected capability digest is invalid")
361
+ if not callable(authentication_headers):
362
+ raise TypeError("authentication_headers must be callable")
363
+ if (
364
+ isinstance(timeout, bool)
365
+ or not isinstance(timeout, (int, float))
366
+ or not math.isfinite(float(timeout))
367
+ or not 0 < float(timeout) <= 300
368
+ ):
369
+ raise ValueError("timeout is outside the supported range")
370
+ self.expected_capabilities_sha256 = expected_capabilities_sha256
371
+ self.authentication_headers = authentication_headers
372
+ self.transport = URLTransport() if transport is None else transport
373
+ if not callable(getattr(self.transport, "request", None)):
374
+ raise TypeError("transport must provide request")
375
+ self.timeout = float(timeout)
376
+
377
+ def __repr__(self) -> str:
378
+ return "CMSLocalizationSourceHTTPClient(configured=True)"
379
+
380
+ def _request(self, method, path, body, allowed_statuses, context, headers=None):
381
+ body_sha256 = hashlib.sha256(body or b"").hexdigest()
382
+ authentication = {
383
+ "schema": _HTTP.AUTH_REQUEST_SCHEMA,
384
+ "method": method,
385
+ "origin": self.origin,
386
+ "path": path,
387
+ "scope": _HTTP.SCOPES[path],
388
+ "body_sha256": body_sha256,
389
+ **context,
390
+ }
391
+ request_headers = _authentication_headers(
392
+ self.authentication_headers, authentication,
393
+ )
394
+ request_headers["Accept"] = "application/json"
395
+ if body is not None:
396
+ request_headers["Content-Type"] = "application/json; charset=utf-8"
397
+ request_headers["X-Localization-Source-Payload-Sha256"] = body_sha256
398
+ if headers:
399
+ request_headers.update(headers)
400
+ try:
401
+ result = self.transport.request(
402
+ method, self.origin + path, request_headers, body,
403
+ timeout=self.timeout,
404
+ )
405
+ except CMSSourceClientBlocked:
406
+ raise
407
+ except Exception:
408
+ _fail("network", retryable=True)
409
+ return result, _json_response(result, allowed_statuses)
410
+
411
+ def capabilities(self) -> Mapping[str, Any]:
412
+ _result, response = self._request(
413
+ "GET", _HTTP.CAPABILITIES_PATH, None, {200}, {},
414
+ )
415
+ try:
416
+ expected = _HTTP._capabilities_payload()
417
+ except Exception:
418
+ _fail("local_contract_invalid")
419
+ if (
420
+ set(response) != {"schema", "capabilities"}
421
+ or response.get("schema") != _HTTP.CAPABILITIES_RESPONSE_SCHEMA
422
+ or response.get("capabilities") != expected
423
+ or expected.get("sha256") != self.expected_capabilities_sha256
424
+ ):
425
+ _fail("capabilities_binding")
426
+ return response
427
+
428
+ def _contract(self, operation: str) -> Mapping[str, Any]:
429
+ capabilities = self.capabilities()["capabilities"]
430
+ return capabilities["operations"][operation]
431
+
432
+ def submit_change(
433
+ self, change: Mapping[str, Any], *, max_attempts: int = 5,
434
+ ) -> Mapping[str, Any]:
435
+ payload, payload_body = _copy_payload(change, "change")
436
+ return self._enqueue(
437
+ "change", payload, payload_body, payload["event_id"],
438
+ payload["event_id"], max_attempts,
439
+ )
440
+
441
+ def submit_removal(
442
+ self, removal: Mapping[str, Any], *, max_attempts: int = 5,
443
+ ) -> Mapping[str, Any]:
444
+ payload, payload_body = _copy_payload(removal, "removal")
445
+ if payload["schema"] == _CMS.CANCELLATION_SCHEMA:
446
+ operation, identity = "cancellation", "cancellation_id"
447
+ else:
448
+ operation, identity = "tombstone", "tombstone_id"
449
+ return self._enqueue(
450
+ operation, payload, payload_body, payload[identity],
451
+ payload["event_id"], max_attempts,
452
+ )
453
+
454
+ def _enqueue(
455
+ self, operation, payload, payload_body, request_id, event_id,
456
+ max_attempts,
457
+ ) -> Mapping[str, Any]:
458
+ if (
459
+ isinstance(max_attempts, bool)
460
+ or not isinstance(max_attempts, int)
461
+ or not 1 <= max_attempts <= 20
462
+ ):
463
+ _fail("request_invalid")
464
+ contract_name = "change" if operation == "change" else "removal"
465
+ contract = self._contract(contract_name)
466
+ envelope_key = "change" if operation == "change" else "removal"
467
+ request = {
468
+ "schema": contract["request_schema"],
469
+ envelope_key: payload,
470
+ "max_attempts": max_attempts,
471
+ }
472
+ body = _canonical(request)
473
+ _result, response = self._request(
474
+ contract["method"], contract["path"], body,
475
+ {contract["success_status"]},
476
+ {"event_id": event_id, "request_id": request_id},
477
+ {
478
+ "Idempotency-Key": request_id,
479
+ "X-Localization-Source-Payload-Sha256": (
480
+ hashlib.sha256(body).hexdigest()
481
+ ),
482
+ },
483
+ )
484
+ expected_fields = set(contract["response_fields"])
485
+ payload_sha256 = hashlib.sha256(payload_body).hexdigest()
486
+ if (
487
+ set(response) != expected_fields
488
+ or response.get("schema") != contract["response_schema"]
489
+ or response.get("operation") != operation
490
+ or response.get("request_id") != request_id
491
+ or response.get("event_id") != event_id
492
+ or response.get("payload_sha256") != payload_sha256
493
+ or response.get("status") not in _HTTP.STATUSES
494
+ or not _count(response.get("attempts"), maximum=20)
495
+ or response.get("max_attempts") != max_attempts
496
+ or response.get("attempts") > max_attempts
497
+ or response.get("capabilities_sha256")
498
+ != self.expected_capabilities_sha256
499
+ ):
500
+ _fail("enqueue_binding")
501
+ return response
502
+
503
+ def status(self, event_id: str, site_id: str) -> Mapping[str, Any]:
504
+ if not _token(event_id) or not _token(site_id):
505
+ _fail("request_invalid")
506
+ contract = self._contract("status")
507
+ request = {
508
+ "schema": contract["request_schema"],
509
+ "event_id": event_id,
510
+ "site_id": site_id,
511
+ }
512
+ body = _canonical(request)
513
+ _result, response = self._request(
514
+ contract["method"], contract["path"], body,
515
+ {contract["success_status"]},
516
+ {"event_id": event_id, "site_id": site_id},
517
+ )
518
+ if (
519
+ set(response) != set(contract["response_fields"])
520
+ or response.get("schema") != contract["response_schema"]
521
+ or response.get("capabilities_sha256")
522
+ != self.expected_capabilities_sha256
523
+ ):
524
+ _fail("status_binding")
525
+ try:
526
+ normalized = _HTTP._source_status_payload(
527
+ _PayloadView(response["status"]),
528
+ expected_event_id=event_id,
529
+ expected_site_id=site_id,
530
+ )
531
+ except Exception:
532
+ _fail("status_binding")
533
+ if normalized != response["status"]:
534
+ _fail("status_binding")
535
+ return response
536
+
537
+ def health(self) -> Mapping[str, Any]:
538
+ contract = self._contract("health")
539
+ result, response = self._request(
540
+ contract["method"], contract["path"], None,
541
+ {200, 503}, {},
542
+ )
543
+ if (
544
+ set(response) != set(contract["response_fields"])
545
+ or response.get("schema") != contract["response_schema"]
546
+ or response.get("capabilities_sha256")
547
+ != self.expected_capabilities_sha256
548
+ ):
549
+ _fail("health_binding")
550
+ try:
551
+ normalized = _HTTP._health_payload(_PayloadView(response["health"]))
552
+ except Exception:
553
+ _fail("health_binding")
554
+ if (
555
+ normalized != response["health"]
556
+ or (result.status == 503) != (normalized["status"] == "blocked")
557
+ ):
558
+ _fail("health_binding")
559
+ return response
560
+
561
+ def readiness(self) -> Mapping[str, Any]:
562
+ contract = self._contract("readiness")
563
+ result, response = self._request(
564
+ contract["method"], contract["path"], None,
565
+ {200, 503}, {},
566
+ )
567
+ if (
568
+ set(response) != set(contract["response_fields"])
569
+ or response.get("schema") != contract["response_schema"]
570
+ or response.get("capabilities_sha256")
571
+ != self.expected_capabilities_sha256
572
+ ):
573
+ _fail("readiness_binding")
574
+ try:
575
+ normalized = _HTTP._readiness_payload(response["readiness"])
576
+ except Exception:
577
+ _fail("readiness_binding")
578
+ if (
579
+ normalized != response["readiness"]
580
+ or (result.status == 200) != (normalized["status"] == "ready")
581
+ ):
582
+ _fail("readiness_binding")
583
+ return response