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,514 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const os = require("node:os");
5
+ const path = require("node:path");
6
+ const {
7
+ LanguageGuardBlocked,
8
+ routeHostContext,
9
+ verifyForDelivery,
10
+ } = require("./node-language-guard");
11
+
12
+ const SERVER_NAME = "blun-language-guard";
13
+ const MAX_SERVICE_TOKEN_BYTES = 64 * 1024;
14
+ const MAX_BLUN_MCP_CONFIG_BYTES = 1024 * 1024;
15
+
16
+ function protectedFileIdentity(stats) {
17
+ return {
18
+ dev: stats.dev,
19
+ ino: stats.ino,
20
+ size: stats.size,
21
+ ctimeMs: stats.ctimeMs,
22
+ mtimeMs: stats.mtimeMs,
23
+ };
24
+ }
25
+
26
+ function sameProtectedFile(stats, expected) {
27
+ return stats.dev === expected.dev && stats.ino === expected.ino
28
+ && stats.size === expected.size && stats.ctimeMs === expected.ctimeMs
29
+ && stats.mtimeMs === expected.mtimeMs;
30
+ }
31
+
32
+ function validateServiceTokenStats(stats) {
33
+ if (!stats.isFile() || stats.isSymbolicLink()) throw new Error("service token must be a regular file");
34
+ if (stats.nlink !== 1) throw new Error("service token must not have additional hard links");
35
+ if (stats.size < 32 || stats.size > MAX_SERVICE_TOKEN_BYTES) throw new Error("service token has an invalid size");
36
+ if (process.platform !== "win32" && (stats.mode & 0o077) !== 0) throw new Error("service token permissions are too broad");
37
+ if (typeof process.getuid === "function" && stats.uid !== process.getuid()) throw new Error("service token has the wrong owner");
38
+ }
39
+
40
+ function protectedDirectoryIdentity(stats) {
41
+ return {
42
+ dev: stats.dev,
43
+ ino: stats.ino,
44
+ mode: stats.mode,
45
+ uid: stats.uid,
46
+ gid: stats.gid,
47
+ };
48
+ }
49
+
50
+ function sameProtectedDirectory(stats, expected) {
51
+ return stats.dev === expected.dev && stats.ino === expected.ino
52
+ && stats.mode === expected.mode && stats.uid === expected.uid
53
+ && stats.gid === expected.gid;
54
+ }
55
+
56
+ function validateProtectedDirectoryStats(stats, directory, label) {
57
+ if (!stats.isDirectory() || stats.isSymbolicLink()) {
58
+ throw new Error(`${label} directory must be a directory: ${directory}`);
59
+ }
60
+ if (process.platform !== "win32" && (stats.mode & 0o022) !== 0) {
61
+ throw new Error(`${label} directory is writable outside its owner: ${directory}`);
62
+ }
63
+ if (typeof process.getuid === "function" && stats.uid !== process.getuid()) {
64
+ throw new Error(`${label} directory has the wrong owner: ${directory}`);
65
+ }
66
+ }
67
+
68
+ function existingProtectedDirectoryAnchor(directory, label) {
69
+ let candidate = directory;
70
+ while (true) {
71
+ try {
72
+ fs.lstatSync(candidate);
73
+ return candidate;
74
+ } catch (error) {
75
+ if (!error || error.code !== "ENOENT") throw error;
76
+ const parent = path.dirname(candidate);
77
+ if (parent === candidate) {
78
+ throw new Error(`${label} directory has no existing anchor: ${directory}`);
79
+ }
80
+ candidate = parent;
81
+ }
82
+ }
83
+ }
84
+
85
+ function openProtectedDirectory(destination, label, { allowMissing = false } = {}) {
86
+ const absoluteFile = path.resolve(destination);
87
+ const directory = path.dirname(absoluteFile);
88
+ if (process.platform === "win32") {
89
+ let details;
90
+ try {
91
+ details = fs.lstatSync(directory);
92
+ } catch (error) {
93
+ if (allowMissing && error && error.code === "ENOENT") return null;
94
+ throw error;
95
+ }
96
+ validateProtectedDirectoryStats(details, directory, label);
97
+ return {
98
+ accessPath: absoluteFile,
99
+ descriptor: null,
100
+ directory,
101
+ identity: protectedDirectoryIdentity(details),
102
+ };
103
+ }
104
+ const home = path.resolve(os.homedir());
105
+ const underHome = directory === home || directory.startsWith(`${home}${path.sep}`);
106
+ const anchor = underHome ? home : existingProtectedDirectoryAnchor(directory, label);
107
+ const relative = path.relative(anchor, directory);
108
+ const components = relative ? relative.split(path.sep) : [];
109
+ const noFollow = typeof fs.constants.O_NOFOLLOW === "number" ? fs.constants.O_NOFOLLOW : 0;
110
+ const directoryOnly = typeof fs.constants.O_DIRECTORY === "number" ? fs.constants.O_DIRECTORY : 0;
111
+ const flags = fs.constants.O_RDONLY | noFollow | directoryOnly;
112
+ const descriptorRoot = process.platform === "linux" ? "/proc/self/fd" : "/dev/fd";
113
+ let descriptor = null;
114
+ let current = anchor;
115
+ try {
116
+ descriptor = fs.openSync(anchor, flags);
117
+ validateProtectedDirectoryStats(fs.fstatSync(descriptor), anchor, label);
118
+ for (const component of components) {
119
+ current = path.join(current, component);
120
+ let child;
121
+ try {
122
+ child = fs.openSync(path.join(descriptorRoot, String(descriptor), component), flags);
123
+ } catch (error) {
124
+ if (allowMissing && error && error.code === "ENOENT") {
125
+ fs.closeSync(descriptor);
126
+ descriptor = null;
127
+ return null;
128
+ }
129
+ throw error;
130
+ }
131
+ try {
132
+ validateProtectedDirectoryStats(fs.fstatSync(child), current, label);
133
+ } catch (error) {
134
+ fs.closeSync(child);
135
+ throw error;
136
+ }
137
+ fs.closeSync(descriptor);
138
+ descriptor = child;
139
+ }
140
+ const identity = protectedDirectoryIdentity(fs.fstatSync(descriptor));
141
+ const accessPath = path.join(descriptorRoot, String(descriptor), path.basename(absoluteFile));
142
+ return { accessPath, descriptor, directory, identity };
143
+ } catch (error) {
144
+ if (descriptor !== null) fs.closeSync(descriptor);
145
+ if (error && String(error.message || "").startsWith(`${label} directory`)) throw error;
146
+ throw new Error(`${label} directory cannot be opened safely: ${current}`);
147
+ }
148
+ }
149
+
150
+ function closeProtectedDirectory(protectedDirectory, label) {
151
+ if (protectedDirectory.descriptor === null) {
152
+ const current = fs.lstatSync(protectedDirectory.directory);
153
+ validateProtectedDirectoryStats(current, protectedDirectory.directory, label);
154
+ if (!sameProtectedDirectory(current, protectedDirectory.identity)) {
155
+ throw new Error(`${label} directory changed while reading: ${protectedDirectory.directory}`);
156
+ }
157
+ return;
158
+ }
159
+ try {
160
+ const held = fs.fstatSync(protectedDirectory.descriptor);
161
+ const current = fs.lstatSync(protectedDirectory.directory);
162
+ validateProtectedDirectoryStats(current, protectedDirectory.directory, label);
163
+ if (!sameProtectedDirectory(held, protectedDirectory.identity)
164
+ || !sameProtectedDirectory(current, protectedDirectory.identity)) {
165
+ throw new Error(`${label} directory changed while reading: ${protectedDirectory.directory}`);
166
+ }
167
+ } finally {
168
+ fs.closeSync(protectedDirectory.descriptor);
169
+ }
170
+ }
171
+
172
+ function readProtectedServiceToken(destination) {
173
+ const protectedDirectory = openProtectedDirectory(destination, "service token");
174
+ const tokenFile = protectedDirectory.accessPath;
175
+ try {
176
+ const before = fs.lstatSync(tokenFile);
177
+ validateServiceTokenStats(before);
178
+ const noFollow = typeof fs.constants.O_NOFOLLOW === "number" ? fs.constants.O_NOFOLLOW : 0;
179
+ const descriptor = fs.openSync(tokenFile, fs.constants.O_RDONLY | noFollow);
180
+ try {
181
+ const opened = fs.fstatSync(descriptor);
182
+ validateServiceTokenStats(opened);
183
+ if (!sameProtectedFile(opened, protectedFileIdentity(before)) || opened.nlink !== before.nlink) {
184
+ throw new Error("service token changed while opening");
185
+ }
186
+ const buffer = Buffer.alloc(MAX_SERVICE_TOKEN_BYTES + 1);
187
+ let size = 0;
188
+ while (size < buffer.length) {
189
+ const count = fs.readSync(descriptor, buffer, size, buffer.length - size, null);
190
+ if (count === 0) break;
191
+ size += count;
192
+ }
193
+ const after = fs.fstatSync(descriptor);
194
+ const afterPath = fs.lstatSync(tokenFile);
195
+ if (!sameProtectedFile(after, protectedFileIdentity(opened)) || after.nlink !== opened.nlink
196
+ || !sameProtectedFile(afterPath, protectedFileIdentity(opened)) || afterPath.nlink !== opened.nlink) {
197
+ throw new Error("service token changed while reading");
198
+ }
199
+ if (size > MAX_SERVICE_TOKEN_BYTES) throw new Error("service token has an invalid size");
200
+ const token = new TextDecoder("utf-8", { fatal: true }).decode(buffer.subarray(0, size)).replace(/^\uFEFF/, "").trim();
201
+ if (token.length < 32) throw new Error("service token is invalid");
202
+ return token;
203
+ } finally {
204
+ fs.closeSync(descriptor);
205
+ }
206
+ } finally {
207
+ closeProtectedDirectory(protectedDirectory, "service token");
208
+ }
209
+ }
210
+
211
+ function validateLegacyConfigStats(stats) {
212
+ if (!stats.isFile() || stats.isSymbolicLink()) throw new Error("BLUN MCP configuration must be a regular file");
213
+ if (stats.nlink !== 1) throw new Error("BLUN MCP configuration must not have additional hard links");
214
+ if (stats.size > MAX_BLUN_MCP_CONFIG_BYTES) throw new Error("BLUN MCP configuration exceeds the size limit");
215
+ if (process.platform !== "win32" && (stats.mode & 0o022) !== 0) {
216
+ throw new Error("BLUN MCP configuration is writable outside its owner");
217
+ }
218
+ if (typeof process.getuid === "function" && stats.uid !== process.getuid()) {
219
+ throw new Error("BLUN MCP configuration has the wrong owner");
220
+ }
221
+ }
222
+
223
+ function readProtectedLegacyConfig(destination) {
224
+ const protectedDirectory = openProtectedDirectory(
225
+ destination,
226
+ "BLUN MCP configuration",
227
+ { allowMissing: true },
228
+ );
229
+ if (protectedDirectory === null) return null;
230
+ const configFile = protectedDirectory.accessPath;
231
+ try {
232
+ let before;
233
+ try { before = fs.lstatSync(configFile); }
234
+ catch (error) {
235
+ if (error?.code === "ENOENT") return null;
236
+ throw error;
237
+ }
238
+ validateLegacyConfigStats(before);
239
+ const expected = protectedFileIdentity(before);
240
+ const noFollow = typeof fs.constants.O_NOFOLLOW === "number" ? fs.constants.O_NOFOLLOW : 0;
241
+ const descriptor = fs.openSync(configFile, fs.constants.O_RDONLY | noFollow);
242
+ try {
243
+ const opened = fs.fstatSync(descriptor);
244
+ validateLegacyConfigStats(opened);
245
+ if (!sameProtectedFile(opened, expected) || opened.nlink !== before.nlink) {
246
+ throw new Error("BLUN MCP configuration changed while opening");
247
+ }
248
+ const buffer = Buffer.alloc(MAX_BLUN_MCP_CONFIG_BYTES + 1);
249
+ let size = 0;
250
+ while (size < buffer.length) {
251
+ const count = fs.readSync(descriptor, buffer, size, buffer.length - size, null);
252
+ if (count === 0) break;
253
+ size += count;
254
+ }
255
+ const after = fs.fstatSync(descriptor);
256
+ const afterPath = fs.lstatSync(configFile);
257
+ if (
258
+ !sameProtectedFile(after, expected) || after.nlink !== before.nlink
259
+ || !sameProtectedFile(afterPath, expected) || afterPath.nlink !== before.nlink
260
+ ) throw new Error("BLUN MCP configuration changed while reading");
261
+ if (size > MAX_BLUN_MCP_CONFIG_BYTES) throw new Error("BLUN MCP configuration exceeds the size limit");
262
+ return new TextDecoder("utf-8", { fatal: true })
263
+ .decode(buffer.subarray(0, size)).replace(/^\uFEFF/, "");
264
+ } finally {
265
+ fs.closeSync(descriptor);
266
+ }
267
+ } finally {
268
+ closeProtectedDirectory(protectedDirectory, "BLUN MCP configuration");
269
+ }
270
+ }
271
+
272
+ function loadLegacyGuardConfig(userHome) {
273
+ const file = path.join(userHome, ".blun", "mcp.json");
274
+ const raw = readProtectedLegacyConfig(file);
275
+ if (raw === null) return null;
276
+ let parsed;
277
+ try {
278
+ parsed = JSON.parse(raw);
279
+ } catch {
280
+ throw new Error("BLUN MCP configuration is not valid JSON");
281
+ }
282
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
283
+ throw new Error("BLUN MCP configuration root must be an object");
284
+ }
285
+ if (parsed.mcpServers !== undefined && (
286
+ !parsed.mcpServers || typeof parsed.mcpServers !== "object" || Array.isArray(parsed.mcpServers)
287
+ )) throw new Error("BLUN mcpServers must be an object");
288
+ const server = parsed?.mcpServers?.[SERVER_NAME];
289
+ if (server === undefined) return null;
290
+ if (!server || typeof server !== "object" || Array.isArray(server)) {
291
+ throw new Error("BLUN language-guard MCP entry must be an object");
292
+ }
293
+ if (server.env !== undefined && (
294
+ !server.env || typeof server.env !== "object" || Array.isArray(server.env)
295
+ )) throw new Error("BLUN language-guard MCP environment must be an object");
296
+ if (server.args !== undefined && !Array.isArray(server.args)) {
297
+ throw new Error("BLUN language-guard MCP arguments must be an array");
298
+ }
299
+ const env = server.env || {};
300
+ const values = {
301
+ command: String(server.command || ""),
302
+ args: Array.isArray(server.args) ? server.args.map(String) : [],
303
+ cwd: String(server.cwd || ""),
304
+ endpoint: String(env.BLUN_LANGUAGE_GUARD_SERVICE_ENDPOINT || ""),
305
+ tokenFile: String(env.BLUN_LANGUAGE_GUARD_SERVICE_TOKEN_FILE || ""),
306
+ };
307
+ if (
308
+ !values.command || !values.endpoint || !values.tokenFile
309
+ || values.command.length > 4096 || values.cwd.length > 4096
310
+ || values.endpoint.length > 4096 || values.tokenFile.length > 4096
311
+ || values.args.length > 128 || values.args.some(value => value.length > 4096)
312
+ ) throw new Error("BLUN language-guard MCP entry is invalid");
313
+ return {
314
+ name: SERVER_NAME,
315
+ ...values,
316
+ };
317
+ }
318
+
319
+ function bootstrapLanguageGuardMcp({ userHome, store }) {
320
+ const current = store.getAllInternal().find(item => String(item.name || "").toLowerCase() === SERVER_NAME);
321
+ if (current) return { installed: false, id: current.id, reason: "already-installed" };
322
+ let legacy;
323
+ try { legacy = loadLegacyGuardConfig(userHome); }
324
+ catch {
325
+ throw new LanguageGuardBlocked("legacy BLUN MCP configuration is unsafe", "guard_unavailable");
326
+ }
327
+ if (!legacy?.command || !legacy.endpoint || !legacy.tokenFile) {
328
+ return { installed: false, reason: "legacy-config-missing" };
329
+ }
330
+ const saved = store.save({
331
+ name: SERVER_NAME,
332
+ transport: "stdio",
333
+ command: legacy.command,
334
+ args: legacy.args,
335
+ cwd: legacy.cwd,
336
+ enabled: true,
337
+ secretText: [
338
+ `BLUN_LANGUAGE_GUARD_SERVICE_ENDPOINT=${legacy.endpoint}`,
339
+ `BLUN_LANGUAGE_GUARD_SERVICE_TOKEN_FILE=${legacy.tokenFile}`,
340
+ ].join("\n"),
341
+ });
342
+ if (!saved?.ok || !saved.savedId) throw new LanguageGuardBlocked("language guard MCP bootstrap failed", "guard_unavailable");
343
+ return { installed: true, id: saved.savedId };
344
+ }
345
+
346
+ function resolveGuardConnection({ store, environment = process.env }) {
347
+ const server = store.getAllInternal().find(item => String(item.name || "").toLowerCase() === SERVER_NAME);
348
+ let secrets = {};
349
+ if (server) {
350
+ try { secrets = store.getSecrets(server.id) || {}; }
351
+ catch { secrets = {}; }
352
+ }
353
+ const endpoint = String(
354
+ environment.BLUN_LANGUAGE_GUARD_SERVICE_ENDPOINT
355
+ || secrets.BLUN_LANGUAGE_GUARD_SERVICE_ENDPOINT
356
+ || "",
357
+ ).trim();
358
+ const tokenFile = String(
359
+ environment.BLUN_LANGUAGE_GUARD_SERVICE_TOKEN_FILE
360
+ || secrets.BLUN_LANGUAGE_GUARD_SERVICE_TOKEN_FILE
361
+ || "",
362
+ ).trim();
363
+ if (!server || server.enabled === false || !endpoint || !tokenFile) {
364
+ throw new LanguageGuardBlocked("mandatory language guard is not configured", "guard_unavailable");
365
+ }
366
+ let serviceToken;
367
+ try { serviceToken = readProtectedServiceToken(tokenFile); }
368
+ catch { throw new LanguageGuardBlocked("mandatory language guard token is unavailable", "guard_unavailable"); }
369
+ if (serviceToken.length < 32) {
370
+ throw new LanguageGuardBlocked("mandatory language guard token is invalid", "guard_unavailable");
371
+ }
372
+ return { endpoint, serviceToken };
373
+ }
374
+
375
+ function resolveLanguage(meta, config) {
376
+ const candidates = [
377
+ [meta?.languageGuardLanguage, "meta.languageGuardLanguage"],
378
+ [config?.languageGuardLanguage, "config.languageGuardLanguage"],
379
+ [config?.responseLanguage, "config.responseLanguage"],
380
+ [config?.language, "config.language"],
381
+ [meta?.telegram?.conversationLanguage, "meta.telegram.conversationLanguage"],
382
+ // Telegram's senderLanguageCode describes the sender's client/interface
383
+ // language. It is not reliable evidence for the language of this message,
384
+ // so retain it only as a backwards-compatible last resort.
385
+ [meta?.telegram?.senderLanguageCode, "meta.telegram.senderLanguageCode"],
386
+ ];
387
+ for (const [value, source] of candidates) {
388
+ const language = String(value || "").trim();
389
+ if (language) return { language, source };
390
+ }
391
+ return { language: "", source: "missing" };
392
+ }
393
+
394
+ function languageFromMeta(meta, config) {
395
+ return resolveLanguage(meta, config).language;
396
+ }
397
+
398
+ function createBlunLanguageGuard({ store, getConfig, environment = process.env }) {
399
+ function context({ messages, meta = {}, channel = "desktop" }) {
400
+ const prompt = String(messages?.[messages.length - 1]?.content || "");
401
+ const languageResolution = resolveLanguage(meta, getConfig?.() || {});
402
+ const language = languageResolution.language;
403
+ const route = routeHostContext({
404
+ // Keep host evidence and types intact. The shared router infers a
405
+ // translation from source text and rejects an explicit downgrade.
406
+ task_kind: meta.languageGuardTaskKind,
407
+ source_text: meta.languageGuardSourceText,
408
+ target_language: language,
409
+ response_language: language,
410
+ content_type: meta.languageGuardContentType || "prose",
411
+ });
412
+ const connection = resolveGuardConnection({ store, environment });
413
+ return {
414
+ hostContext: {
415
+ task_kind: route.taskKind,
416
+ operation: route.taskKind === "translation" ? "translation" : "chat",
417
+ source_text: route.sourceText,
418
+ target_language: route.taskKind === "translation" ? route.language : undefined,
419
+ response_language: route.taskKind === "response" ? route.language : undefined,
420
+ content_type: route.contentType,
421
+ },
422
+ endpoint: connection.endpoint,
423
+ serviceToken: connection.serviceToken,
424
+ agentId: String(meta.agentName || meta.agentId || "blun-code"),
425
+ channel: String(channel || "desktop"),
426
+ prompt,
427
+ route,
428
+ languageSource: languageResolution.source,
429
+ };
430
+ }
431
+
432
+ function mandatoryInstruction(guardContext) {
433
+ const tool = guardContext.route.taskKind === "translation" ? "release_translation" : "release_response";
434
+ const translationRule = guardContext.route.taskKind === "translation"
435
+ ? "Load and apply the installed translate-native skill/plugin before drafting. Use the complete trusted source supplied by the host."
436
+ : "If the request is actually a translation but the host did not mark it as translation, do not translate; explain that trusted translation routing is required.";
437
+ return [
438
+ "[BLUN LANGUAGE GUARD — MANDATORY]",
439
+ `The host classified this output as ${guardContext.route.taskKind} in ${guardContext.route.language}.`,
440
+ `Pass language exactly as ${JSON.stringify(guardContext.route.language)} to ${tool}; do not substitute a base language or another locale.`,
441
+ translationRule,
442
+ `Before final output, call ${tool} for the complete final candidate with truthful attestations.`,
443
+ "Final output must be exactly one JSON object with only target_text and release_token.",
444
+ "Do not stream, print, or send the candidate through another channel.",
445
+ "[/BLUN LANGUAGE GUARD]",
446
+ ].join("\n");
447
+ }
448
+
449
+ function decorateMessages(messages, guardContext) {
450
+ const copy = Array.isArray(messages) ? messages.map(item => ({ ...item })) : [];
451
+ if (!copy.length) return copy;
452
+ const index = copy.length - 1;
453
+ copy[index].content = `${String(copy[index].content || "")}\n\n${mandatoryInstruction(guardContext)}`;
454
+ return copy;
455
+ }
456
+
457
+ function bufferedEmitter(emit) {
458
+ if (typeof emit !== "function") return undefined;
459
+ return event => {
460
+ if (event?.type === "text-delta" || event?.type === "done") return;
461
+ emit(event);
462
+ };
463
+ }
464
+
465
+ async function releaseResult(result, guardContext, emit) {
466
+ if (result?.error || result?.cancelled) return result;
467
+ const rawEnvelope = result?.answer || result?.reply || "";
468
+ const verified = await verifyForDelivery({
469
+ rawEnvelope,
470
+ hostContext: guardContext.hostContext,
471
+ endpoint: guardContext.endpoint,
472
+ serviceToken: guardContext.serviceToken,
473
+ agentId: guardContext.agentId,
474
+ channel: guardContext.channel,
475
+ });
476
+ if (typeof emit === "function") {
477
+ emit({ type: "text-delta", delta: verified.text, languageGuardVerified: true });
478
+ emit({ type: "done", answer: verified.text, languageGuardVerified: true });
479
+ }
480
+ return {
481
+ ...result,
482
+ answer: verified.text,
483
+ reply: verified.text,
484
+ languageGuardVerified: true,
485
+ languageGuard: {
486
+ taskKind: verified.route.taskKind,
487
+ language: verified.route.language,
488
+ languageSource: guardContext.languageSource,
489
+ version: verified.verification?.version || "",
490
+ },
491
+ };
492
+ }
493
+
494
+ return {
495
+ mandatory: true,
496
+ context,
497
+ mandatoryInstruction,
498
+ decorateMessages,
499
+ bufferedEmitter,
500
+ releaseResult,
501
+ };
502
+ }
503
+
504
+ module.exports = {
505
+ SERVER_NAME,
506
+ loadLegacyGuardConfig,
507
+ readProtectedLegacyConfig,
508
+ readProtectedServiceToken,
509
+ bootstrapLanguageGuardMcp,
510
+ resolveGuardConnection,
511
+ resolveLanguage,
512
+ languageFromMeta,
513
+ createBlunLanguageGuard,
514
+ };