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,42 @@
1
+ """Compatibility import for the portable, skill-bundled commercial validator.
2
+
3
+ The production website runtime and skill-only CLI deliberately execute the same
4
+ implementation. This module is not a service and does not install or start one.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import importlib.util
10
+ from pathlib import Path
11
+
12
+
13
+ _PATH = (
14
+ Path(__file__).resolve().parents[1]
15
+ / "translate-native"
16
+ / "scripts"
17
+ / "commercial_localization_profile.py"
18
+ )
19
+ _SPEC = importlib.util.spec_from_file_location(
20
+ "translate_native_portable_commercial",
21
+ _PATH,
22
+ )
23
+ if _SPEC is None or _SPEC.loader is None:
24
+ raise ImportError("commercial profile implementation unavailable")
25
+ _IMPL = importlib.util.module_from_spec(_SPEC)
26
+ _SPEC.loader.exec_module(_IMPL)
27
+
28
+ hashlib = _IMPL.hashlib
29
+ PUBLIC_PROFILE_SCHEMA = _IMPL.PUBLIC_PROFILE_SCHEMA
30
+ REVIEW_SUMMARY_CAPABILITIES_SCHEMA = _IMPL.REVIEW_SUMMARY_CAPABILITIES_SCHEMA
31
+ REVIEW_SUMMARY_SCHEMA = _IMPL.REVIEW_SUMMARY_SCHEMA
32
+ DIMENSIONS = _IMPL.DIMENSIONS
33
+ _canonical_json = _IMPL._canonical_json
34
+ public_review_summary_contract = _IMPL.public_review_summary_contract
35
+ public_profile = _IMPL.public_profile
36
+ CREATION_GUIDANCE = _IMPL.CREATION_GUIDANCE
37
+ NATIVE_GUIDANCE = _IMPL.NATIVE_GUIDANCE
38
+ FIDELITY_GUIDANCE = _IMPL.FIDELITY_GUIDANCE
39
+ CommercialReviewBlocked = _IMPL.CommercialReviewBlocked
40
+ review_contract = _IMPL.review_contract
41
+ validate_review = _IMPL.validate_review
42
+ validate_summary = _IMPL.validate_summary
@@ -0,0 +1,28 @@
1
+ {
2
+ "mandatory": true,
3
+ "fail_closed": true,
4
+ "host_owns": [
5
+ "task_kind",
6
+ "language",
7
+ "source_text",
8
+ "content_type",
9
+ "delivery_channel"
10
+ ],
11
+ "agent_envelope_fields": [
12
+ "target_text",
13
+ "release_token"
14
+ ],
15
+ "isolated_service": {
16
+ "required": true,
17
+ "endpoint": "platform installer supplies a loopback socket",
18
+ "token_file": "owner-only host path",
19
+ "audit_file": "content-free JSONL"
20
+ },
21
+ "routes": {
22
+ "response": "release_response",
23
+ "translation": "translate-native + release_translation"
24
+ },
25
+ "direct_delivery_allowed": false,
26
+ "raw_streaming_allowed": false,
27
+ "on_guard_error": "block"
28
+ }
@@ -0,0 +1,543 @@
1
+ #!/usr/bin/env python3
2
+ """Host-owned, fail-closed delivery boundary for agent output.
3
+
4
+ The untrusted agent must return one JSON envelope on stdout:
5
+
6
+ {"target_text": "...", "release_token": "blg6...."}
7
+
8
+ The trusted host supplies task kind, locale, source text, and signing-key
9
+ location as command-line policy. Only the exact text covered by the receipt is
10
+ written to stdout. Diagnostics and rejected candidates are never written to
11
+ stdout.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import contextlib
18
+ import hashlib
19
+ import importlib.util
20
+ import json
21
+ import os
22
+ import re
23
+ import stat
24
+ import subprocess
25
+ import sys
26
+ from dataclasses import dataclass
27
+ from pathlib import Path
28
+ from typing import Any, Awaitable, Callable, Iterator, Sequence, TypeVar
29
+
30
+
31
+ ROOT = Path(__file__).resolve().parents[1]
32
+ QUALITY_PATH = ROOT / "translate-native" / "scripts" / "language_quality.py"
33
+ CLIENT_PATH = ROOT / "translate-native" / "scripts" / "guard_service_client.py"
34
+ SPEC = importlib.util.spec_from_file_location("blun_delivery_quality", QUALITY_PATH)
35
+ assert SPEC and SPEC.loader
36
+ QUALITY = importlib.util.module_from_spec(SPEC)
37
+ SPEC.loader.exec_module(QUALITY)
38
+
39
+ CLIENT_SPEC = importlib.util.spec_from_file_location("blun_delivery_service_client", CLIENT_PATH)
40
+ assert CLIENT_SPEC and CLIENT_SPEC.loader
41
+ SERVICE_CLIENT = importlib.util.module_from_spec(CLIENT_SPEC)
42
+ CLIENT_SPEC.loader.exec_module(SERVICE_CLIENT)
43
+
44
+ DEFAULT_KEY_PATH = Path.home() / ".config" / "blun-language-guard" / "signing.key"
45
+ DEFAULT_POLICY_PATH = Path.home() / ".config" / "blun-language-guard" / "delivery-policy.json"
46
+ DEFAULT_MAX_BYTES = 4 * 1024 * 1024
47
+ MAX_POLICY_BYTES = 64 * 1024
48
+ FORBIDDEN_AGENT_FIELDS = {
49
+ "task_kind", "language", "source_text", "content_type",
50
+ "short_text_reviewed", "key_path", "delivery_channel",
51
+ }
52
+
53
+
54
+ @dataclass(frozen=True)
55
+ class HostPolicy:
56
+ task_kind: str
57
+ language: str
58
+ source_text: str = ""
59
+ content_type: str = "prose"
60
+ short_text_reviewed: bool = False
61
+
62
+
63
+ class DeliveryBlocked(ValueError):
64
+ """Raised when an untrusted candidate is not eligible for delivery."""
65
+
66
+
67
+ def _exact_language(language: str) -> bool:
68
+ return (
69
+ isinstance(language, str)
70
+ and language.casefold() not in {"auto", "all"}
71
+ and re.fullmatch(r"(?:[A-Za-z]{2,8}|x)(?:-[A-Za-z0-9]{1,8})*", language)
72
+ is not None
73
+ )
74
+
75
+
76
+ def validate_policy(policy: HostPolicy) -> None:
77
+ if policy.task_kind not in {"response", "translation"}:
78
+ raise DeliveryBlocked("host policy has an invalid task kind")
79
+ if not _exact_language(policy.language):
80
+ raise DeliveryBlocked("host policy requires an exact language or locale tag")
81
+ if policy.task_kind == "translation" and not policy.source_text.strip():
82
+ raise DeliveryBlocked("translation policy requires the complete source text")
83
+ if policy.task_kind == "response" and policy.source_text:
84
+ raise DeliveryBlocked("response policy cannot contain translation source text")
85
+
86
+
87
+ def parse_envelope(raw: str, max_bytes: int = DEFAULT_MAX_BYTES) -> dict[str, Any]:
88
+ if len(raw.encode("utf-8")) > max_bytes:
89
+ raise DeliveryBlocked("agent envelope exceeds the configured size limit")
90
+ try:
91
+ envelope = json.loads(raw.lstrip("\ufeff"))
92
+ except json.JSONDecodeError as error:
93
+ raise DeliveryBlocked("agent output is not one valid JSON release envelope") from error
94
+ if not isinstance(envelope, dict):
95
+ raise DeliveryBlocked("agent release envelope must be a JSON object")
96
+ forbidden = sorted(FORBIDDEN_AGENT_FIELDS.intersection(envelope))
97
+ if forbidden:
98
+ raise DeliveryBlocked(
99
+ "agent envelope attempts to override host-owned fields: " + ", ".join(forbidden)
100
+ )
101
+ if set(envelope) - {"target_text", "release_token"}:
102
+ raise DeliveryBlocked("agent release envelope contains unsupported fields")
103
+ if not isinstance(envelope.get("target_text"), str) or not envelope["target_text"].strip():
104
+ raise DeliveryBlocked("agent release envelope has no non-empty target_text")
105
+ if not isinstance(envelope.get("release_token"), str) or not envelope["release_token"].strip():
106
+ raise DeliveryBlocked("agent release envelope has no release_token")
107
+ return envelope
108
+
109
+
110
+ def verify_envelope(envelope: dict[str, Any], policy: HostPolicy, key: bytes) -> str:
111
+ validate_policy(policy)
112
+ target = envelope["target_text"]
113
+ verification = QUALITY.verify_receipt(
114
+ envelope["release_token"],
115
+ policy.source_text,
116
+ target,
117
+ policy.language,
118
+ key,
119
+ policy.content_type,
120
+ policy.short_text_reviewed,
121
+ purpose=policy.task_kind,
122
+ )
123
+ if not verification.get("valid"):
124
+ failed = [name for name, passed in verification.get("checks", {}).items() if not passed]
125
+ detail = ", ".join(failed) if failed else "invalid receipt"
126
+ raise DeliveryBlocked("release receipt rejected: " + detail)
127
+ return target
128
+
129
+
130
+ def verify_envelope_with_service(
131
+ envelope: dict[str, Any],
132
+ policy: HostPolicy,
133
+ endpoint: str,
134
+ *,
135
+ service_token: str = "",
136
+ timeout: float = 10.0,
137
+ ) -> str:
138
+ validate_policy(policy)
139
+ target = envelope["target_text"]
140
+ result = SERVICE_CLIENT.call_guard_service(
141
+ endpoint,
142
+ {
143
+ "operation": "verify",
144
+ "task_kind": policy.task_kind,
145
+ "source_text": policy.source_text,
146
+ "target_text": target,
147
+ "language": policy.language,
148
+ "release_token": envelope["release_token"],
149
+ "content_type": policy.content_type,
150
+ "short_text_reviewed": policy.short_text_reviewed,
151
+ },
152
+ auth_token=service_token,
153
+ timeout=timeout,
154
+ )
155
+ if not result.get("valid"):
156
+ failed = [name for name, passed in result.get("checks", {}).items() if not passed]
157
+ detail = ", ".join(failed) if failed else "invalid receipt"
158
+ raise DeliveryBlocked("isolated guard rejected the receipt: " + detail)
159
+ return target
160
+
161
+
162
+ def load_verification_key(path: Path) -> bytes:
163
+ """Load an existing verifier key without silently creating a new trust root."""
164
+ environment_key = os.environ.get("BLUN_LANGUAGE_GUARD_KEY")
165
+ if environment_key:
166
+ return hashlib.sha256(environment_key.encode("utf-8")).digest()
167
+ try:
168
+ return QUALITY.load_existing_key(path)
169
+ except FileNotFoundError as error:
170
+ raise DeliveryBlocked("signing key is missing; delivery fails closed") from error
171
+ except OSError as error:
172
+ raise DeliveryBlocked("signing key cannot be read") from error
173
+ except ValueError as error:
174
+ if "permissions" in str(error):
175
+ raise DeliveryBlocked("signing key permissions are broader than owner-only") from error
176
+ raise DeliveryBlocked("signing key is invalid") from error
177
+
178
+
179
+ def _policy_identity(details: os.stat_result) -> tuple[int, int, int, int, int, int]:
180
+ return (
181
+ details.st_dev,
182
+ details.st_ino,
183
+ details.st_nlink,
184
+ details.st_size,
185
+ details.st_ctime_ns,
186
+ details.st_mtime_ns,
187
+ )
188
+
189
+
190
+ def _policy_directory_identity(
191
+ details: os.stat_result,
192
+ ) -> tuple[int, int, int, int, int]:
193
+ return (
194
+ details.st_dev,
195
+ details.st_ino,
196
+ details.st_mode,
197
+ details.st_uid,
198
+ details.st_gid,
199
+ )
200
+
201
+
202
+ def _validate_policy_directory(path: Path, details: os.stat_result) -> None:
203
+ if not stat.S_ISDIR(details.st_mode) or stat.S_ISLNK(details.st_mode):
204
+ raise DeliveryBlocked(f"installed delivery policy directory is invalid: {path}")
205
+ if os.name != "nt" and stat.S_IMODE(details.st_mode) & 0o022:
206
+ raise DeliveryBlocked(
207
+ f"installed delivery policy directory is writable outside its owner: {path}"
208
+ )
209
+ if hasattr(os, "getuid") and details.st_uid != os.getuid():
210
+ raise DeliveryBlocked(
211
+ f"installed delivery policy directory has the wrong owner: {path}"
212
+ )
213
+
214
+
215
+ def _existing_policy_directory_anchor(path: Path) -> Path:
216
+ candidate = path
217
+ while True:
218
+ try:
219
+ candidate.lstat()
220
+ return candidate
221
+ except FileNotFoundError:
222
+ parent = candidate.parent
223
+ if parent == candidate:
224
+ raise DeliveryBlocked(
225
+ f"installed delivery policy directory has no existing anchor: {path}"
226
+ )
227
+ candidate = parent
228
+
229
+
230
+ def _assert_policy_directory_unchanged(
231
+ path: Path,
232
+ expected: tuple[int, int, int, int, int],
233
+ ) -> None:
234
+ try:
235
+ current = path.lstat()
236
+ except OSError as error:
237
+ raise DeliveryBlocked(
238
+ f"installed delivery policy directory cannot be rechecked: {path}"
239
+ ) from error
240
+ _validate_policy_directory(path, current)
241
+ if _policy_directory_identity(current) != expected:
242
+ raise DeliveryBlocked(
243
+ f"installed delivery policy directory changed while reading: {path}"
244
+ )
245
+
246
+
247
+ @contextlib.contextmanager
248
+ def _open_policy_directory(path: Path) -> Iterator[int | None]:
249
+ if os.name == "nt":
250
+ yield None
251
+ return
252
+ anchor = Path.home()
253
+ try:
254
+ relative = path.parent.relative_to(anchor)
255
+ except ValueError:
256
+ anchor = _existing_policy_directory_anchor(path.parent)
257
+ relative = path.parent.relative_to(anchor)
258
+ flags = (
259
+ os.O_RDONLY
260
+ | getattr(os, "O_BINARY", 0)
261
+ | getattr(os, "O_DIRECTORY", 0)
262
+ | getattr(os, "O_NOFOLLOW", 0)
263
+ )
264
+ descriptor = None
265
+ current_path = anchor
266
+ try:
267
+ try:
268
+ descriptor = os.open(anchor, flags)
269
+ _validate_policy_directory(anchor, os.fstat(descriptor))
270
+ for component in relative.parts:
271
+ current_path = current_path / component
272
+ try:
273
+ child = os.open(component, flags, dir_fd=descriptor)
274
+ except FileNotFoundError:
275
+ yield None
276
+ return
277
+ try:
278
+ _validate_policy_directory(current_path, os.fstat(child))
279
+ except Exception:
280
+ os.close(child)
281
+ raise
282
+ os.close(descriptor)
283
+ descriptor = child
284
+ expected = _policy_directory_identity(os.fstat(descriptor))
285
+ except DeliveryBlocked:
286
+ raise
287
+ except OSError as error:
288
+ raise DeliveryBlocked(
289
+ f"installed delivery policy directory cannot be opened safely: {current_path}"
290
+ ) from error
291
+ try:
292
+ yield descriptor
293
+ finally:
294
+ _assert_policy_directory_unchanged(path.parent, expected)
295
+ finally:
296
+ if descriptor is not None:
297
+ os.close(descriptor)
298
+
299
+
300
+ def _policy_lstat(path: Path, directory: int | None) -> os.stat_result:
301
+ if directory is None:
302
+ return path.lstat()
303
+ return os.stat(path.name, dir_fd=directory, follow_symlinks=False)
304
+
305
+
306
+ def _open_policy_file(path: Path, directory: int | None, flags: int) -> int:
307
+ if directory is None:
308
+ return os.open(path, flags)
309
+ return os.open(path.name, flags, dir_fd=directory)
310
+
311
+
312
+ def _policy_fstat(descriptor: int) -> os.stat_result:
313
+ return os.fstat(descriptor)
314
+
315
+
316
+ def _read_protected_policy_at(
317
+ path: Path,
318
+ directory: int | None,
319
+ ) -> dict[str, Any] | None:
320
+ try:
321
+ before = _policy_lstat(path, directory)
322
+ except FileNotFoundError:
323
+ return None
324
+ except OSError as error:
325
+ raise DeliveryBlocked("installed delivery policy is unreadable") from error
326
+ if not stat.S_ISREG(before.st_mode) or stat.S_ISLNK(before.st_mode):
327
+ raise DeliveryBlocked("installed delivery policy must be a regular file")
328
+ if before.st_nlink != 1:
329
+ raise DeliveryBlocked("installed delivery policy must not have additional hard links")
330
+ if before.st_size > MAX_POLICY_BYTES:
331
+ raise DeliveryBlocked("installed delivery policy exceeds the size limit")
332
+ if os.name != "nt" and stat.S_IMODE(before.st_mode) & 0o077:
333
+ raise DeliveryBlocked("installed delivery policy permissions are broader than owner-only")
334
+ if hasattr(os, "getuid") and before.st_uid != os.getuid():
335
+ raise DeliveryBlocked("installed delivery policy owner is invalid")
336
+
337
+ flags = os.O_RDONLY | getattr(os, "O_BINARY", 0) | getattr(os, "O_NOFOLLOW", 0)
338
+ try:
339
+ descriptor = _open_policy_file(path, directory, flags)
340
+ with os.fdopen(descriptor, "rb") as handle:
341
+ opened = _policy_fstat(handle.fileno())
342
+ if not stat.S_ISREG(opened.st_mode) or _policy_identity(opened) != _policy_identity(before):
343
+ raise DeliveryBlocked("installed delivery policy changed while opening")
344
+ raw = handle.read(MAX_POLICY_BYTES + 1)
345
+ after_read = _policy_fstat(handle.fileno())
346
+ after_path = _policy_lstat(path, directory)
347
+ except DeliveryBlocked:
348
+ raise
349
+ except OSError as error:
350
+ raise DeliveryBlocked("installed delivery policy is unreadable") from error
351
+ if len(raw) > MAX_POLICY_BYTES:
352
+ raise DeliveryBlocked("installed delivery policy exceeds the size limit")
353
+ if (
354
+ _policy_identity(after_read) != _policy_identity(opened)
355
+ or _policy_identity(after_path) != _policy_identity(opened)
356
+ ):
357
+ raise DeliveryBlocked("installed delivery policy changed while reading")
358
+ try:
359
+ policy = json.loads(raw.decode("utf-8-sig"))
360
+ except (UnicodeError, json.JSONDecodeError) as error:
361
+ raise DeliveryBlocked("installed delivery policy is unreadable") from error
362
+ if not isinstance(policy, dict):
363
+ raise DeliveryBlocked("installed delivery policy is invalid")
364
+ return policy
365
+
366
+
367
+ def _read_protected_policy(path: Path) -> dict[str, Any] | None:
368
+ with _open_policy_directory(path) as directory:
369
+ if os.name != "nt" and directory is None:
370
+ return None
371
+ return _read_protected_policy_at(path, directory)
372
+
373
+
374
+ def load_installed_service_policy(path: Path = DEFAULT_POLICY_PATH) -> dict[str, Any]:
375
+ policy = _read_protected_policy(path)
376
+ if policy is None:
377
+ return {}
378
+ isolated = policy.get("isolated_service")
379
+ if (
380
+ policy.get("mandatory") is not True
381
+ or not isinstance(isolated, dict)
382
+ or isolated.get("required") is not True
383
+ or not isinstance(isolated.get("endpoint"), str)
384
+ or not isolated["endpoint"].strip()
385
+ or len(isolated["endpoint"]) > 4096
386
+ or not isinstance(isolated.get("token_file"), str)
387
+ or not isolated["token_file"].strip()
388
+ or len(isolated["token_file"]) > 4096
389
+ or ("fail_closed" in policy and policy["fail_closed"] is not True)
390
+ or ("direct_delivery_allowed" in policy and policy["direct_delivery_allowed"] is not False)
391
+ or ("raw_streaming_allowed" in policy and policy["raw_streaming_allowed"] is not False)
392
+ or ("on_guard_error" in policy and policy["on_guard_error"] != "block")
393
+ ):
394
+ raise DeliveryBlocked("installed delivery policy is invalid")
395
+ return isolated
396
+
397
+
398
+ ResultT = TypeVar("ResultT")
399
+
400
+
401
+ def guarded_send(
402
+ raw_envelope: str,
403
+ policy: HostPolicy,
404
+ key: bytes,
405
+ send: Callable[[str], ResultT],
406
+ *,
407
+ max_bytes: int = DEFAULT_MAX_BYTES,
408
+ ) -> ResultT:
409
+ """Verify first, then invoke a synchronous delivery function exactly once."""
410
+ target = verify_envelope(parse_envelope(raw_envelope, max_bytes), policy, key)
411
+ return send(target)
412
+
413
+
414
+ async def guarded_send_async(
415
+ raw_envelope: str,
416
+ policy: HostPolicy,
417
+ key: bytes,
418
+ send: Callable[[str], Awaitable[ResultT]],
419
+ *,
420
+ max_bytes: int = DEFAULT_MAX_BYTES,
421
+ ) -> ResultT:
422
+ """Verify first, then invoke an asynchronous API/Telegram sender exactly once."""
423
+ target = verify_envelope(parse_envelope(raw_envelope, max_bytes), policy, key)
424
+ return await send(target)
425
+
426
+
427
+ def _read_source(path: Path | None, task_kind: str) -> str:
428
+ if path is None:
429
+ return ""
430
+ if task_kind != "translation":
431
+ raise DeliveryBlocked("--source-file is valid only for translation tasks")
432
+ try:
433
+ return path.read_text(encoding="utf-8-sig")
434
+ except OSError as error:
435
+ raise DeliveryBlocked("cannot read the trusted translation source") from error
436
+
437
+
438
+ def _untrusted_environment(policy: HostPolicy) -> dict[str, str]:
439
+ environment = dict(os.environ)
440
+ environment.pop("BLUN_LANGUAGE_GUARD_KEY", None)
441
+ environment.pop("BLUN_LANGUAGE_GUARD_KEY_FILE", None)
442
+ environment.pop("BLUN_LANGUAGE_GUARD_SERVICE_TOKEN", None)
443
+ environment.pop("BLUN_LANGUAGE_GUARD_SERVICE_TOKEN_FILE", None)
444
+ environment["BLUN_LANGUAGE_GUARD_MANDATORY"] = "1"
445
+ environment["BLUN_LANGUAGE_GUARD_TASK_KIND"] = policy.task_kind
446
+ environment["BLUN_LANGUAGE_GUARD_LANGUAGE"] = policy.language
447
+ environment["BLUN_LANGUAGE_GUARD_CONTENT_TYPE"] = policy.content_type
448
+ return environment
449
+
450
+
451
+ def _run_agent(command: Sequence[str], timeout: float, max_bytes: int, policy: HostPolicy) -> str:
452
+ if not command:
453
+ return sys.stdin.read(max_bytes + 1)
454
+ actual = list(command)
455
+ if actual and actual[0] == "--":
456
+ actual = actual[1:]
457
+ if not actual:
458
+ raise DeliveryBlocked("missing agent command after --")
459
+ try:
460
+ completed = subprocess.run(
461
+ actual,
462
+ text=True,
463
+ encoding="utf-8",
464
+ errors="strict",
465
+ capture_output=True,
466
+ check=False,
467
+ timeout=timeout,
468
+ env=_untrusted_environment(policy),
469
+ )
470
+ except (OSError, subprocess.SubprocessError, UnicodeError) as error:
471
+ raise DeliveryBlocked("agent process failed before guarded delivery") from error
472
+ if completed.returncode != 0:
473
+ raise DeliveryBlocked(f"agent process exited with status {completed.returncode}")
474
+ if len(completed.stdout.encode("utf-8")) > max_bytes:
475
+ raise DeliveryBlocked("agent envelope exceeds the configured size limit")
476
+ return completed.stdout
477
+
478
+
479
+ def build_parser() -> argparse.ArgumentParser:
480
+ parser = argparse.ArgumentParser(description="Deliver only language-guarded agent output")
481
+ parser.add_argument("--task-kind", required=True, choices=("response", "translation"))
482
+ parser.add_argument("--language", required=True, help="Trusted exact BCP-47 language tag")
483
+ parser.add_argument("--source-file", type=Path, help="Trusted complete source for translations")
484
+ parser.add_argument("--content-type", default="prose")
485
+ parser.add_argument("--short-text-reviewed", action="store_true")
486
+ parser.add_argument("--key-file", type=Path, default=DEFAULT_KEY_PATH)
487
+ parser.add_argument("--service-endpoint", default=os.environ.get("BLUN_LANGUAGE_GUARD_SERVICE_ENDPOINT", ""))
488
+ parser.add_argument("--service-token-file", type=Path)
489
+ parser.add_argument("--require-service", action="store_true", help="Disable same-user key verification")
490
+ parser.add_argument("--policy-file", type=Path, default=DEFAULT_POLICY_PATH)
491
+ parser.add_argument("--timeout", type=float, default=300.0)
492
+ parser.add_argument("--max-bytes", type=int, default=DEFAULT_MAX_BYTES)
493
+ parser.add_argument("command", nargs=argparse.REMAINDER)
494
+ return parser
495
+
496
+
497
+ def main(argv: Sequence[str] | None = None) -> int:
498
+ args = build_parser().parse_args(argv)
499
+ try:
500
+ if args.timeout <= 0 or args.max_bytes <= 0:
501
+ raise DeliveryBlocked("timeout and max-bytes must be positive")
502
+ source = _read_source(args.source_file, args.task_kind)
503
+ policy = HostPolicy(
504
+ task_kind=args.task_kind,
505
+ language=args.language,
506
+ source_text=source,
507
+ content_type=args.content_type,
508
+ short_text_reviewed=args.short_text_reviewed,
509
+ )
510
+ validate_policy(policy)
511
+ raw = _run_agent(args.command, args.timeout, args.max_bytes, policy)
512
+ envelope = parse_envelope(raw, args.max_bytes)
513
+ installed_service = load_installed_service_policy(args.policy_file)
514
+ service_endpoint = args.service_endpoint or str(installed_service.get("endpoint", ""))
515
+ token_file = args.service_token_file
516
+ if token_file is None and installed_service.get("token_file"):
517
+ token_file = Path(str(installed_service["token_file"]))
518
+ require_service = args.require_service or installed_service.get("required") is True
519
+ if service_endpoint:
520
+ service_token = ""
521
+ if token_file:
522
+ service_token = SERVICE_CLIENT.load_service_token(token_file)
523
+ target = verify_envelope_with_service(
524
+ envelope,
525
+ policy,
526
+ service_endpoint,
527
+ service_token=service_token,
528
+ timeout=min(args.timeout, 30.0),
529
+ )
530
+ else:
531
+ if require_service:
532
+ raise DeliveryBlocked("isolated guard service is required")
533
+ key = load_verification_key(args.key_file)
534
+ target = verify_envelope(envelope, policy, key)
535
+ except (DeliveryBlocked, SERVICE_CLIENT.GuardServiceError, OSError) as error:
536
+ print(f"BLOCK: {error}", file=sys.stderr)
537
+ return 1
538
+ sys.stdout.write(target)
539
+ return 0
540
+
541
+
542
+ if __name__ == "__main__":
543
+ raise SystemExit(main())