blun-king-cli 9.1.587 → 9.1.588
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -185
- package/LIESMICH.txt +51 -13
- package/README.md +44 -47
- package/agent-spine-plugin/.codex-plugin/plugin.json +16 -4
- package/agent-spine-plugin/CHANGELOG.md +37 -5
- package/agent-spine-plugin/README.md +3 -3
- package/agent-spine-plugin/blun.plugin.json +45 -10
- package/agent-spine-plugin/docs/artifact-evaluation.md +93 -0
- package/agent-spine-plugin/docs/host-integration.md +42 -27
- package/agent-spine-plugin/docs/preflight-recall.md +4 -2
- package/agent-spine-plugin/docs/session-timeline.md +97 -236
- package/agent-spine-plugin/docs/world-model.md +25 -0
- package/agent-spine-plugin/hooks/codex.json +1 -1
- package/agent-spine-plugin/hooks/hooks.json +1 -1
- package/agent-spine-plugin/package.json +1 -3
- package/agent-spine-plugin/scripts/check-hosts.js +3 -3
- package/agent-spine-plugin/scripts/release-check.js +10 -5
- package/agent-spine-plugin/scripts/run-checks.js +4 -1
- package/agent-spine-plugin/scripts/run-tests-hermetic.js +32 -6
- package/agent-spine-plugin/src/cli-learning.js +15 -0
- package/agent-spine-plugin/src/cli.js +2 -0
- package/agent-spine-plugin/src/hook.js +32 -32
- package/agent-spine-plugin/src/lib/action-lesson-recall.js +73 -8
- package/agent-spine-plugin/src/lib/briefing.js +146 -36
- package/agent-spine-plugin/src/lib/channel-continuity.js +19 -0
- package/agent-spine-plugin/src/lib/delivery-agent-usage.js +14 -7
- package/agent-spine-plugin/src/lib/gateway-group-response.js +128 -0
- package/agent-spine-plugin/src/lib/gateway-runs.js +24 -15
- package/agent-spine-plugin/src/lib/hook-briefing-use.js +13 -3
- package/agent-spine-plugin/src/lib/hook-context.js +16 -3
- package/agent-spine-plugin/src/lib/hook-output.js +129 -5
- package/agent-spine-plugin/src/lib/hook-timeline.js +5 -3
- package/agent-spine-plugin/src/lib/indexed-memory.js +2 -2
- package/agent-spine-plugin/src/lib/learning-artifact-evaluator.js +114 -0
- package/agent-spine-plugin/src/lib/learning-context.js +11 -4
- package/agent-spine-plugin/src/lib/learning-measurements.js +2 -2
- package/agent-spine-plugin/src/lib/mcp-runtime.js +89 -3
- package/agent-spine-plugin/src/lib/mcp-source-context.js +12 -2
- package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +91 -8
- package/agent-spine-plugin/src/lib/mcp-world-tools.js +2 -2
- package/agent-spine-plugin/src/lib/owned-file-lock.js +20 -1
- package/agent-spine-plugin/src/lib/persona-runtime.js +2 -2
- package/agent-spine-plugin/src/lib/preflight-delivery-id.js +27 -0
- package/agent-spine-plugin/src/lib/preflight.js +4 -4
- package/agent-spine-plugin/src/lib/session-timeline-codex.js +15 -0
- package/agent-spine-plugin/src/lib/session-timeline-contract.js +12 -4
- package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +36 -7
- package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +13 -10
- package/agent-spine-plugin/src/lib/session-timeline-invocation.js +1 -1
- package/agent-spine-plugin/src/lib/session-timeline-king.js +14 -0
- package/agent-spine-plugin/src/lib/session-timeline-prior.js +18 -12
- package/agent-spine-plugin/src/lib/session-timeline-provider.js +5 -0
- package/agent-spine-plugin/src/lib/session-timeline-query.js +2 -0
- package/agent-spine-plugin/src/lib/session-timeline-results.js +35 -10
- package/agent-spine-plugin/src/lib/session-timeline-source-open.js +30 -0
- package/agent-spine-plugin/src/lib/session-timeline.js +122 -75
- package/agent-spine-plugin/src/lib/source-roots.js +3 -2
- package/agent-spine-plugin/src/lib/task-knowledge-context.js +22 -1
- package/agent-spine-plugin/src/lib/timeline-continuation-update.js +100 -0
- package/agent-spine-plugin/src/lib/timeline-tool-guard.js +30 -7
- package/agent-spine-plugin/src/lib/timeline-user-feedback.js +217 -0
- package/agent-spine-plugin/src/lib/timeline-world-capture.js +233 -0
- package/agent-spine-plugin/src/lib/world-knowledge.js +59 -2
- package/agent-spine-plugin/src/lib/world-model.js +64 -9
- package/agent-spine-plugin/src/worker.js +13 -1
- package/bin/blun.js +43 -28
- package/bin/core-bootstrap.js +5 -4
- package/bin/king.js +43 -28
- package/bin/launcher-mode.js +1 -10
- package/bin/launcher-runtime.js +128 -295
- package/bin/managed-node.js +0 -0
- package/bin/managed-plugin-selection.cjs +0 -1
- package/bin/native-module-repair.js +0 -0
- package/bin/node-runtime.js +0 -0
- package/bin/node-version.js +0 -0
- package/bin/plugin-bootstrap.js +56 -120
- package/bin/private-paths.js +11 -34
- package/bin/standard-tools-bootstrap.js +34 -114
- package/bin/turn-thinking-policy.cjs +3 -11
- package/bin/update-copy.js +200 -0
- package/bin/update-lease.js +0 -0
- package/bin/update-notice.js +136 -289
- package/bin/verify-agent-behavior.cjs +122 -0
- package/bin/verify-agent-components.cjs +104 -0
- package/bin/verify-bundled-agent-sources.cjs +57 -0
- package/blun.mjs +143076 -135288
- package/bundled-agent-sources.json +701 -0
- package/package.json +12 -15
- package/standard-skills/translate-native/README.md +1293 -0
- package/standard-skills/translate-native/SKILL.md +172 -22
- package/standard-skills/translate-native/VERSION +1 -1
- package/standard-skills/translate-native/agents/openai.yaml +18 -0
- package/standard-skills/translate-native/assets/icon.svg +8 -0
- package/standard-skills/translate-native/docs/BLUN_CODE_INTEGRATION.md +76 -0
- package/standard-skills/translate-native/docs/PREMORTEM.md +489 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +2035 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1302 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +136 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HEALTH_HTTP.md +130 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +175 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +86 -0
- package/standard-skills/translate-native/integrations/AGENT_RULES.md +32 -0
- package/standard-skills/translate-native/integrations/adapters/blun-code-language-guard.js +514 -0
- package/standard-skills/translate-native/integrations/adapters/node-language-guard.js +230 -0
- package/standard-skills/translate-native/integrations/audit_log.py +327 -0
- package/standard-skills/translate-native/integrations/claude_language_hook.js +1536 -0
- package/standard-skills/translate-native/integrations/commercial_localization_profile.py +42 -0
- package/standard-skills/translate-native/integrations/delivery-policy.example.json +28 -0
- package/standard-skills/translate-native/integrations/enforced_delivery.py +543 -0
- package/standard-skills/translate-native/integrations/guard_service.py +435 -0
- package/standard-skills/translate-native/integrations/language_gateway.py +67 -0
- package/standard-skills/translate-native/integrations/mcp_auth_headers.py +198 -0
- package/standard-skills/translate-native/integrations/mcp_http_gateway.py +429 -0
- package/standard-skills/translate-native/integrations/non_language_html_entities.js +1485 -0
- package/standard-skills/translate-native/integrations/pre_output_guard.py +65 -0
- package/standard-skills/translate-native/integrations/task_router.py +101 -0
- package/standard-skills/translate-native/integrations/website_localization.py +401 -0
- package/standard-skills/translate-native/integrations/website_localization_api.py +581 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark.py +1885 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_campaign.py +1772 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_candidate.py +506 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_http.py +400 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_review_store.py +781 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_reviewer_http.py +500 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_runtime.py +1107 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_suite.py +463 -0
- package/standard-skills/translate-native/integrations/website_localization_cms.py +2835 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_client.py +875 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_dispatch.py +805 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_http.py +588 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_lifecycle_monitor.py +991 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +1441 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +414 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +1073 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_removal_dispatch.py +865 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +583 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +964 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +665 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +1153 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +675 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +1125 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification.py +674 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +444 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +1469 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +1142 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +634 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +804 -0
- package/standard-skills/translate-native/integrations/website_localization_deepl_baseline.py +922 -0
- package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +482 -0
- package/standard-skills/translate-native/integrations/website_localization_health.py +1541 -0
- package/standard-skills/translate-native/integrations/website_localization_health_http.py +372 -0
- package/standard-skills/translate-native/integrations/website_localization_http_provider.py +297 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_http.py +479 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_intake.py +363 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_queue.py +1449 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_store.py +420 -0
- package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +235 -0
- package/standard-skills/translate-native/integrations/website_localization_queue.py +671 -0
- package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +516 -0
- package/standard-skills/translate-native/integrations/website_localization_release.py +928 -0
- package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +1008 -0
- package/standard-skills/translate-native/integrations/website_localization_runner.py +276 -0
- package/standard-skills/translate-native/integrations/website_localization_runtime.py +862 -0
- package/standard-skills/translate-native/integrations/website_localization_service.py +350 -0
- package/standard-skills/translate-native/integrations/website_localization_supervisor.py +511 -0
- package/standard-skills/translate-native/integrations/website_localization_worker.py +663 -0
- package/standard-skills/translate-native/provenance.json +3 -4
- package/standard-skills/translate-native/references/commercial-localization.md +177 -0
- package/standard-skills/translate-native/scripts/blun_language_guard.py +7 -1
- package/standard-skills/translate-native/scripts/check_commercial_review.py +80 -0
- package/standard-skills/translate-native/scripts/commercial_localization_profile.py +333 -0
- package/standard-tools/language-guard/LICENSE +21 -0
- package/standard-tools/language-guard/VERSION +1 -0
- package/standard-tools/language-guard/blun_language_guard.py +7 -1
- package/standard-tools/language-guard/check_commercial_review.py +80 -0
- package/standard-tools/language-guard/commercial_localization_profile.py +333 -0
- package/standard-tools/language-guard/language_gateway.py +62 -0
- package/standard-tools/language-guard/pre_output_guard.py +64 -0
- package/standard-tools/language-guard/provenance.json +4 -11
- package/standard-tools/manifest.json +34 -11
- package/telegram-plugin/commands/access.md +2 -10
- package/telegram-plugin/dist/bridge.mjs +64041 -687
- package/telegram-plugin/dist/mcp-server.mjs +72810 -9027
- package/telegram-plugin/dist/noise.mjs +28 -63511
- package/agent-spine-plugin/CONTRIBUTING.md +0 -52
- package/agent-spine-plugin/SECURITY.md +0 -47
- package/agent-spine-plugin/docs/assignment-continuation.md +0 -48
- package/agent-spine-plugin/docs/releasing.md +0 -85
- package/agent-spine-plugin/docs/structured-completion.md +0 -67
- package/bin/abort-listener-policy.cjs +0 -43
- package/bin/active-steer-priority-policy.cjs +0 -24
- package/bin/agent-api-http-adapter.mjs +0 -446
- package/bin/agent-api-private-http-server.mjs +0 -288
- package/bin/agent-api-runtime.mjs +0 -252
- package/bin/agent-api-service-environment.mjs +0 -236
- package/bin/agent-api-service-host.mjs +0 -209
- package/bin/agent-api-service-process.mjs +0 -171
- package/bin/agent-api-session-registry.mjs +0 -428
- package/bin/agent-api-tool-broker.cjs +0 -248
- package/bin/agent-api-turn-controller.mjs +0 -461
- package/bin/agent-api-usage-journal.cjs +0 -259
- package/bin/agent-resume-snapshot.cjs +0 -241
- package/bin/agentspine-king-goal-inbox.mjs +0 -111
- package/bin/agentspine-king-goal-intake.mjs +0 -106
- package/bin/approval-rejection-stop.cjs +0 -15
- package/bin/assistant-message-offload-policy.cjs +0 -284
- package/bin/baseline-skill-performance-policy.cjs +0 -39
- package/bin/bash-search-scope-policy.cjs +0 -49
- package/bin/codebase-search-runtime.cjs +0 -23
- package/bin/cognitive-action-checkpoint.cjs +0 -1104
- package/bin/cognitive-attention-delivery.cjs +0 -76
- package/bin/cognitive-attention-policy.cjs +0 -143
- package/bin/cognitive-attention-runtime.cjs +0 -91
- package/bin/cognitive-context-projection.cjs +0 -73
- package/bin/cognitive-cross-portal-acceptance.cjs +0 -443
- package/bin/cognitive-effective-view.cjs +0 -77
- package/bin/cognitive-focus-projection.cjs +0 -206
- package/bin/cognitive-focus-scope.cjs +0 -37
- package/bin/cognitive-goal-autostart-policy.cjs +0 -72
- package/bin/cognitive-goal-time-trigger-controller.cjs +0 -146
- package/bin/cognitive-memory-adapter.cjs +0 -282
- package/bin/cognitive-memory-command.cjs +0 -293
- package/bin/cognitive-memory-provider.cjs +0 -92
- package/bin/cognitive-salience-policy.cjs +0 -159
- package/bin/cognitive-state-store.cjs +0 -508
- package/bin/cognitive-turn-lifecycle.cjs +0 -624
- package/bin/cognitive-work-focus.cjs +0 -180
- package/bin/compaction-history-archive.cjs +0 -166
- package/bin/compaction-history-startup.cjs +0 -50
- package/bin/compaction-model-policy.cjs +0 -31
- package/bin/compaction-stage-policy.cjs +0 -21
- package/bin/compaction-transaction-policy.cjs +0 -122
- package/bin/config-write-dedup-policy.cjs +0 -27
- package/bin/context-budget-ledger.cjs +0 -31
- package/bin/context-doctor-policy.cjs +0 -70
- package/bin/context-insight-policy.cjs +0 -36
- package/bin/context-performance-policy.cjs +0 -19
- package/bin/context-pressure-policy.cjs +0 -20
- package/bin/cron-run-output.cjs +0 -45
- package/bin/cron-run-store.cjs +0 -145
- package/bin/curiosity-scout-policy.cjs +0 -49
- package/bin/default-model-output-budget-policy.cjs +0 -28
- package/bin/durable-task-resume-policy.cjs +0 -130
- package/bin/durable-task-resume-runtime.cjs +0 -117
- package/bin/durable-task-resume-store.cjs +0 -88
- package/bin/editable-tool-approval-policy.cjs +0 -540
- package/bin/editable-tool-approval-runtime.cjs +0 -99
- package/bin/effective-system-prompt-cache-policy.cjs +0 -33
- package/bin/error-memory-performance-policy.cjs +0 -113
- package/bin/file-observation-policy.cjs +0 -133
- package/bin/foreground-output-capture-policy.cjs +0 -41
- package/bin/generated-source-health.cjs +0 -142
- package/bin/glob-pattern-policy.cjs +0 -13
- package/bin/goal-completion-evidence-policy.cjs +0 -120
- package/bin/grep-output-limit-policy.cjs +0 -39
- package/bin/historical-media-projection-policy.cjs +0 -48
- package/bin/history-offload-pressure-policy.cjs +0 -33
- package/bin/html-to-research-markdown.cjs +0 -147
- package/bin/identity-context-policy.cjs +0 -764
- package/bin/identity-journal-policy.cjs +0 -107
- package/bin/input-draft-persistence.cjs +0 -77
- package/bin/king-tui-function-contract.json +0 -33
- package/bin/launcher-restart-policy.cjs +0 -150
- package/bin/live-response-repetition-guard.cjs +0 -196
- package/bin/llm-config-log-dedup-policy.cjs +0 -76
- package/bin/loop-event-record-policy.cjs +0 -174
- package/bin/managed-context-startup-policy.cjs +0 -27
- package/bin/media-activity-layout-policy.cjs +0 -34
- package/bin/media-auto-retrieval-policy.cjs +0 -90
- package/bin/media-result-policy.cjs +0 -59
- package/bin/micro-compaction-policy.cjs +0 -145
- package/bin/mistake-relevance-policy.cjs +0 -319
- package/bin/model-retry-progress-policy.cjs +0 -46
- package/bin/native-large-file-io.cjs +0 -42
- package/bin/native-runtime-cache.cjs +0 -76
- package/bin/natural-presence-policy.cjs +0 -28
- package/bin/noninteractive-shell-env-policy.cjs +0 -19
- package/bin/observer-hooks.cjs +0 -14
- package/bin/outbound-claim-provenance.cjs +0 -150
- package/bin/oversized-context-offload-policy.cjs +0 -86
- package/bin/pending-media-policy.cjs +0 -182
- package/bin/pending-token-estimate-policy.cjs +0 -41
- package/bin/personal-memory-consent-policy.cjs +0 -72
- package/bin/personal-memory-performance-policy.cjs +0 -12
- package/bin/personality-choice-policy.cjs +0 -101
- package/bin/personality-memory-adapter.cjs +0 -379
- package/bin/personality-mode.cjs +0 -46
- package/bin/personality-setup-policy.cjs +0 -197
- package/bin/proactive-compaction-policy.cjs +0 -25
- package/bin/profile-identity-resolution.cjs +0 -136
- package/bin/profile-runtime.cjs +0 -318
- package/bin/profile-tool-exclusion-policy.cjs +0 -37
- package/bin/programmatic-context-isolation.cjs +0 -25
- package/bin/programmatic-tool-runtime.mjs +0 -627
- package/bin/provider-idle-timeout-policy.cjs +0 -14
- package/bin/provider-model-refresh-deadline.cjs +0 -53
- package/bin/provider-model-refresh-policy.cjs +0 -107
- package/bin/rate-limit-recovery-policy.cjs +0 -47
- package/bin/read-batch-policy.cjs +0 -32
- package/bin/read-continuation-policy.cjs +0 -59
- package/bin/recurring-cron-history-policy.cjs +0 -124
- package/bin/relationship-continuity-policy.cjs +0 -143
- package/bin/relationship-curiosity-policy.cjs +0 -107
- package/bin/relationship-learning-policy.cjs +0 -168
- package/bin/release-artifact-freeze-policy.cjs +0 -30
- package/bin/reload-plugin-bootstrap.cjs +0 -18
- package/bin/reload-queue-policy.cjs +0 -38
- package/bin/repeated-assistant-response-policy.cjs +0 -232
- package/bin/repeated-injection-projection.cjs +0 -107
- package/bin/repeated-user-message-projection.cjs +0 -8
- package/bin/research-page-result.cjs +0 -74
- package/bin/retry-checkpoint-policy.cjs +0 -13
- package/bin/runtime-exit-ledger.cjs +0 -144
- package/bin/scoped-cron-run-policy.cjs +0 -358
- package/bin/session-checkpoint-policy.cjs +0 -25
- package/bin/session-compaction-policy.cjs +0 -84
- package/bin/session-replay-policy.cjs +0 -20
- package/bin/session-replay-window-policy.cjs +0 -40
- package/bin/session-resume-checkpoint.cjs +0 -254
- package/bin/session-scrollback-archive.cjs +0 -229
- package/bin/skill-activation-performance-policy.cjs +0 -69
- package/bin/skill-listing-performance-policy.cjs +0 -92
- package/bin/soul-organization-policy.cjs +0 -78
- package/bin/soul-preservation-policy.cjs +0 -20
- package/bin/startup-preferences.cjs +0 -131
- package/bin/streaming-flush-performance-policy.cjs +0 -28
- package/bin/structured-agent-swarm-output.cjs +0 -325
- package/bin/structured-subagent-output.cjs +0 -252
- package/bin/subagent-context-fork-policy.cjs +0 -155
- package/bin/subagent-max-tokens-handoff-policy.cjs +0 -69
- package/bin/subagent-parent-responsiveness.cjs +0 -19
- package/bin/subagent-skill-policy.cjs +0 -206
- package/bin/subagent-timeout-policy.cjs +0 -182
- package/bin/subagent-tool-policy.cjs +0 -60
- package/bin/subagent-usage-rollup-policy.cjs +0 -29
- package/bin/system-prompt-context-policy.cjs +0 -124
- package/bin/system-prompt-token-cache-policy.cjs +0 -60
- package/bin/telegram-addressed-focus.cjs +0 -55
- package/bin/telegram-addressed-priority.cjs +0 -12
- package/bin/telegram-approval-relay.cjs +0 -290
- package/bin/telegram-bot-priority.cjs +0 -17
- package/bin/telegram-console-status-policy.cjs +0 -174
- package/bin/telegram-context-projection-policy.cjs +0 -141
- package/bin/telegram-delivery-lifecycle.cjs +0 -125
- package/bin/telegram-direct-focus-policy.cjs +0 -273
- package/bin/telegram-mcp-compatibility.cjs +0 -49
- package/bin/telegram-media-delivery-policy.cjs +0 -42
- package/bin/telegram-private-conversation-policy.cjs +0 -185
- package/bin/telegram-queue-handoff-policy.cjs +0 -73
- package/bin/telegram-remote-status-policy.cjs +0 -120
- package/bin/telegram-session-queue-runtime.mjs +0 -306
- package/bin/telegram-text-chunk-policy.cjs +0 -63
- package/bin/telegram-truncated-reply-policy.cjs +0 -37
- package/bin/telegram-urgent-policy.cjs +0 -45
- package/bin/telemetry-spool-policy.cjs +0 -57
- package/bin/thinking-activity-status-policy.cjs +0 -132
- package/bin/thinking-only-guard.cjs +0 -80
- package/bin/todo-list-turn-policy.cjs +0 -131
- package/bin/tool-call-loop-policy.cjs +0 -51
- package/bin/tool-file-persistence.cjs +0 -141
- package/bin/tool-result-offload-policy.cjs +0 -359
- package/bin/tool-result-offload-telemetry.cjs +0 -12
- package/bin/tool-schema-token-cache-policy.cjs +0 -41
- package/bin/tool-stream-preview-policy.cjs +0 -9
- package/bin/tui-functional-contract.cjs +0 -55
- package/bin/turn-tool-performance-policy.cjs +0 -486
- package/bin/usage-cache-efficiency-policy.cjs +0 -26
- package/bin/user-home-path-policy.cjs +0 -13
- package/bin/user-message-offload-policy.cjs +0 -103
- package/bin/user-prompt-hook-origin-policy.cjs +0 -34
- package/bin/user-tool-record-policy.cjs +0 -7
- package/bin/validated-learning-insight-policy.cjs +0 -58
- package/bin/validated-learning-outcome-trace.cjs +0 -107
- package/bin/validated-learning-performance-policy.cjs +0 -53
- package/bin/validated-learning-signal.cjs +0 -463
- package/bin/windows-bash-dialect-policy.cjs +0 -25
- package/bin/windows-node-crash-dump.cjs +0 -110
- package/bin/write-continuation-policy.cjs +0 -69
- package/codebase-index/README.md +0 -82
- package/codebase-index/codebase_index.py +0 -470
- package/standard-skills/agent-browser/SKILL.md +0 -19
- package/standard-skills/agent-browser/references/runtime.md +0 -8
- package/standard-skills/blun-session-inspector/SKILL.md +0 -41
- package/standard-skills/blun-session-inspector/scripts/inspect-session.cjs +0 -437
- package/standard-skills/design-taste-frontend/SKILL.md +0 -1206
- package/standard-skills/full-output-enforcement/SKILL.md +0 -49
- package/standard-skills/high-end-visual-design/SKILL.md +0 -98
- package/standard-skills/image-to-code/SKILL.md +0 -1228
- package/standard-skills/industrial-brutalist-ui/SKILL.md +0 -92
- package/standard-skills/minimalist-ui/SKILL.md +0 -85
- package/standard-skills/motion-design-taste/SKILL.md +0 -74
- package/standard-skills/playwright-testing/SKILL.md +0 -19
- package/standard-skills/playwright-testing/references/runtime.md +0 -7
- package/standard-skills/premortem/SKILL.md +0 -148
- package/standard-skills/redesign-existing-projects/SKILL.md +0 -178
- package/standard-skills/research-evidence/SKILL.md +0 -39
- package/standard-skills/research-evidence/references/evidence-format.md +0 -104
- package/standard-skills/research-evidence/scripts/evidence-collection.cjs +0 -260
- package/standard-skills/research-evidence/scripts/score-report.cjs +0 -130
- package/standard-skills/screenshot-lesen/SKILL.md +0 -52
- package/standard-skills/stitch-design-taste/DESIGN.md +0 -121
- package/standard-skills/stitch-design-taste/SKILL.md +0 -184
- package/standard-skills/telegram-channel/SKILL.md +0 -18
- package/standard-skills/telegram-channel/references/runtime.md +0 -7
- package/standard-skills/venture-flywheel/SKILL.md +0 -32
- package/standard-skills/venture-flywheel/identity/project-identity.cjs +0 -146
- package/standard-skills/venture-flywheel/policy/capability-engine.cjs +0 -114
- package/standard-skills/venture-flywheel/policy/repository-trust.cjs +0 -229
- package/standard-skills/venture-flywheel/references/BEISPIELE-phase0.md +0 -146
- package/standard-skills/venture-flywheel/references/CAPABILITY-MAP.md +0 -34
- package/standard-skills/venture-flywheel/references/SPEC-phase0-identity-trust.md +0 -77
- package/standard-skills/venture-flywheel/references/SPEC-phase0-state-events.md +0 -93
- package/standard-skills/venture-flywheel/schemas/capability-decision.schema.json +0 -13
- package/standard-skills/venture-flywheel/schemas/execution-event.schema.json +0 -44
- package/standard-skills/venture-flywheel/schemas/project-identity.schema.json +0 -32
- package/standard-skills/venture-flywheel/schemas/repository-trust.schema.json +0 -57
- package/standard-skills/venture-flywheel/schemas/run-transition.schema.json +0 -59
- package/standard-skills/venture-flywheel/state/execution-event.cjs +0 -191
- package/standard-skills/venture-flywheel/state/task-state-machine.cjs +0 -190
- package/standard-skills/web-lesen/SKILL.md +0 -73
- package/standard-skills/web-lesen/scripts/crawl_public.py +0 -379
- package/standard-skills/windows-mcp/SKILL.md +0 -19
- package/standard-skills/windows-mcp/references/runtime.md +0 -9
- package/telegram-plugin/DELIVERY.md +0 -36
- package/telegram-plugin/bin/telegram-approval-relay.cjs +0 -290
- package/telegram-plugin/bin/telegram-console-status-policy.cjs +0 -175
- package/telegram-plugin/bin/telegram-delivery-lifecycle.cjs +0 -125
- package/telegram-plugin/bin/telegram-direct-reply-policy.cjs +0 -48
- package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +0 -122
- package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +0 -186
- package/telegram-plugin/bin/telegram-remote-status-policy.cjs +0 -121
- package/telegram-plugin/bin/telegram-reply-parts.cjs +0 -149
- package/telegram-plugin/bin/telegram-text-chunk-policy.cjs +0 -63
- package/telegram-plugin/bin/telegram-typing-keepalive.cjs +0 -89
- package/telegram-plugin/compat/mcp-server-fa511cd1.mjs +0 -73825
- /package/{bin → scripts}/fix-node-pty-perms.js +0 -0
|
@@ -0,0 +1,1293 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src=".github/social-preview.png" alt="Translate Native — Meaning in. Native language out." width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<div align="center">
|
|
6
|
+
|
|
7
|
+
<pre>
|
|
8
|
+
____ _ _ _ _ _
|
|
9
|
+
| __ )| | | | | | \ | |
|
|
10
|
+
| _ \| | | | | | \| |
|
|
11
|
+
| |_) | |___| |_| | |\ |
|
|
12
|
+
|____/|_____|\___/|_| \_|
|
|
13
|
+
</pre>
|
|
14
|
+
|
|
15
|
+
# Translate Native
|
|
16
|
+
|
|
17
|
+
### Meaning in. Native language out. Release only after proof.
|
|
18
|
+
|
|
19
|
+
One universal agent skill for translations that sound written—not translated—and preserve every language's native script.
|
|
20
|
+
|
|
21
|
+
<p>
|
|
22
|
+
<img alt="Tests" src="https://github.com/Maykbiletti/translate-native/actions/workflows/test.yml/badge.svg">
|
|
23
|
+
<img alt="MIT License" src="https://img.shields.io/badge/license-MIT-7C3AED?style=flat-square">
|
|
24
|
+
<img alt="Python 3" src="https://img.shields.io/badge/python-3.10%2B-3776AB?style=flat-square">
|
|
25
|
+
<img alt="Dependencies" src="https://img.shields.io/badge/dependencies-zero-16A34A?style=flat-square">
|
|
26
|
+
<img alt="Languages" src="https://img.shields.io/badge/languages-all-E11D48?style=flat-square">
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
**Built by BLUN · Skill + MCP + enforced release gate.**
|
|
30
|
+
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
> **Stop translating strings. Start rewriting meaning in the target language.**
|
|
36
|
+
|
|
37
|
+
Agents can speak beautifully with users in their own language and still produce stiff, literal copy as soon as the task is called “translation” or arrives inside an i18n file. Translate Native prevents that mode switch.
|
|
38
|
+
|
|
39
|
+
It reconstructs the meaning, discards the source sentence structure, and writes the message again with native syntax, rhythm, idiom, register, script, punctuation, and locale conventions—without changing the facts.
|
|
40
|
+
|
|
41
|
+
## One skill. Every human language.
|
|
42
|
+
|
|
43
|
+
The skill has no language allowlist. It applies equally to:
|
|
44
|
+
|
|
45
|
+
- Swedish, German, Czech, Spanish, Catalan, Basque, and every other Latin-script language;
|
|
46
|
+
- Chinese, Japanese, and Korean;
|
|
47
|
+
- Arabic, Persian, Urdu, and Hebrew;
|
|
48
|
+
- Greek, Cyrillic, Armenian, and Georgian writing systems;
|
|
49
|
+
- Indic, Southeast Asian, Indigenous, minority, endangered, and low-resource languages;
|
|
50
|
+
- regional standards, scripts, dialects, honorific systems, and specialist registers.
|
|
51
|
+
|
|
52
|
+
For uncertain and low-resource varieties, the rule is honesty: verify with community and authoritative sources, or request native review. Never fake fluency.
|
|
53
|
+
|
|
54
|
+
## What changes
|
|
55
|
+
|
|
56
|
+
| Ordinary translation mode | Translate Native |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| Mirrors source word order | Rebuilds native information flow |
|
|
59
|
+
| Chooses dictionary equivalents | Chooses native collocations |
|
|
60
|
+
| Produces generic “i18n language” | Writes for the real audience and medium |
|
|
61
|
+
| Flattens locale and script choices | Resolves locale, script, dialect, and register |
|
|
62
|
+
| Drops accents or romanizes native text | Preserves native spelling, diacritics, alphabets, scripts, and punctuation |
|
|
63
|
+
| Silently changes emphasis | Preserves claims, modality, negation, and uncertainty |
|
|
64
|
+
| Breaks variables during rewriting | Protects keys, placeholders, URLs, markup, and code |
|
|
65
|
+
|
|
66
|
+
## Two jobs. One mandatory skill.
|
|
67
|
+
|
|
68
|
+
Agents no longer need to activate a second orthography skill after translating. `translate-native` now owns both jobs in one self-contained release gate:
|
|
69
|
+
|
|
70
|
+
1. rewrite the meaning as natural original target-language prose;
|
|
71
|
+
2. enforce native spelling, diacritics, alphabets, scripts, punctuation, spacing, and Unicode.
|
|
72
|
+
|
|
73
|
+
The separate `native-diacritics` skill can still protect ordinary writing outside translation tasks. Inside a translation, its activation is optional because the full orthography contract is built directly into `translate-native`.
|
|
74
|
+
|
|
75
|
+
The root [`AGENTS.md`](AGENTS.md) tells repository-aware agents to load the combined workflow and treat every model-generated translation as an untrusted draft.
|
|
76
|
+
|
|
77
|
+
## Version 6: mandatory native output for every agent answer
|
|
78
|
+
|
|
79
|
+
Version 6 extends the gateway beyond translations. Every user-visible natural-language answer now has a release path:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
Agent candidate
|
|
83
|
+
↓ trusted host classifies the task and supplies the expected locale
|
|
84
|
+
├── response → release_response
|
|
85
|
+
└── translation → translate-native skill/plugin → release_translation
|
|
86
|
+
↓
|
|
87
|
+
PASS + purpose-bound receipt → deliver
|
|
88
|
+
BLOCK → revise or stop
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`release_response` validates the agent's own answer for Unicode integrity, expected script, native spelling and measurable ASCII folding. It rejects `auto` and `all`: the trusted host must supply the exact language or locale rather than letting the agent choose a convenient label. A German answer such as `Haendler pruefen taeglich die Qualitaet im Buero` blocks; the correctly written `Händler prüfen täglich die Qualität im Büro` can pass.
|
|
92
|
+
|
|
93
|
+
Translations always take the separate, stricter path. The MCP initialization response tells compatible agents to load the installed `translate-native` skill/plugin before drafting, exposes the same workflow as the MCP prompt `translate-native`, and requires `release_translation` for the complete source-target pair. Translation and response receipts are purpose-bound, so a response receipt cannot authorize a translation.
|
|
94
|
+
|
|
95
|
+
The portable gateway requires a host-owned `task_kind`:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"task_kind": "response",
|
|
100
|
+
"target_text": "Natürlich können wir das zuverlässig prüfen.",
|
|
101
|
+
"language": "de-DE",
|
|
102
|
+
"attestations": {"nativeness": true, "orthography": true}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For a translation, use `"task_kind": "translation"`, include the complete `source_text`, and supply all seven translation attestations. The gateway blocks ambiguous task kinds, a translation without source, and any attempt to carry a source through the response route.
|
|
107
|
+
|
|
108
|
+
This covers every human language and writing system, not only German umlauts. The same contract protects Swedish `å/ä/ö`, Czech `č/ř/š/ž`, Spanish accents and punctuation, Vietnamese tone marks, Greek, Cyrillic, Arabic, Hebrew, Indic scripts, Chinese, Japanese, Korean, and languages not named here. Deterministic checks are intentionally conservative and cannot prove perfect native wording; the native-language workflow and human review remain necessary where consequences are material.
|
|
109
|
+
|
|
110
|
+
### Version 6.64.0: hosted website-source delivery runtime
|
|
111
|
+
|
|
112
|
+
Version 6.64.0 turns the durable website outbox into an owned production
|
|
113
|
+
runtime. Configuration and lease safety are proven in memory before one
|
|
114
|
+
private SQLite file is created. Every later operation rechecks the database
|
|
115
|
+
path and inode, rejects links or weakened permissions, serializes threads, and
|
|
116
|
+
blocks an inherited pre-fork runtime before it can enter a lock or call the
|
|
117
|
+
source client.
|
|
118
|
+
|
|
119
|
+
The hosted factory starts one supervised non-daemon worker and gates new
|
|
120
|
+
managed intake on its live state. Readiness combines worker liveness with the
|
|
121
|
+
outbox's fail-closed health without exposing website content. Shutdown signals
|
|
122
|
+
the worker before joining it; if a provider call exceeds the bound, the
|
|
123
|
+
database remains open until the worker has safely returned.
|
|
124
|
+
|
|
125
|
+
### Version 6.63.0: durable website-source delivery
|
|
126
|
+
|
|
127
|
+
Version 6.63.0 gives website and CMS backends a durable handoff to the
|
|
128
|
+
contract-pinned source client. The new SQLite outbox persists each immutable
|
|
129
|
+
change, cancellation, or tombstone before network access, leases exactly one
|
|
130
|
+
attempt to one worker, and safely replays the same idempotency identity after
|
|
131
|
+
an ambiguous response or process crash.
|
|
132
|
+
|
|
133
|
+
Delivery retries and source-service retries have separate bounded ceilings.
|
|
134
|
+
Removal work takes priority over ordinary changes; exponential backoff remains
|
|
135
|
+
durable across restarts. Exact payload hashes, request identities, source retry
|
|
136
|
+
policy, and the trusted capability digest are fixed at enqueue time. Altered
|
|
137
|
+
rows, stale leases, exhausted work, invalid acknowledgements, and contract
|
|
138
|
+
changes remain content-free and fail closed through explicit status and health
|
|
139
|
+
snapshots.
|
|
140
|
+
|
|
141
|
+
### Version 6.62.0: contract-pinned source-CMS client
|
|
142
|
+
|
|
143
|
+
Version 6.62.0 completes the public source-ingress path for website and CMS
|
|
144
|
+
backends. The new provider-neutral HTTPS client discovers the live contract
|
|
145
|
+
before every operation, verifies it against a trusted deployment pin, and uses
|
|
146
|
+
only the freshly verified method and path for source changes, cancellations,
|
|
147
|
+
tombstones, site-bound status, health, and readiness.
|
|
148
|
+
|
|
149
|
+
Every write uses one canonical body, one transport attempt, an immutable
|
|
150
|
+
idempotency identity, and exact request and payload hashes. All operational
|
|
151
|
+
responses now carry the capability digest that authorized their schema; the
|
|
152
|
+
client rejects endpoint changes, stale responses, cross-site status, altered
|
|
153
|
+
payload hashes, malformed state, redirects, and private transport failures
|
|
154
|
+
fail-closed. Stable retryability lets the website host schedule bounded replay
|
|
155
|
+
without introducing a hidden retry loop in the adapter.
|
|
156
|
+
|
|
157
|
+
### Version 6.61.0: durable terminal-processing reconciliation
|
|
158
|
+
|
|
159
|
+
Version 6.61.0 closes the gap between receiver acceptance and actual CMS-side
|
|
160
|
+
processing. When the configured terminal notifier also exposes the pinned
|
|
161
|
+
`status(event_id, site_id)` operation, the source service creates an independent
|
|
162
|
+
durable processing-observation record after the exact notification
|
|
163
|
+
acknowledgement commits. Later ticks poll only that bound event and site.
|
|
164
|
+
|
|
165
|
+
The observation ledger has its own leases, crash recovery, bounded transport
|
|
166
|
+
failures, and polling cadence. It accepts a receiver state only when the
|
|
167
|
+
notification ID, event, site, terminal outcome, and payload SHA-256 all match
|
|
168
|
+
the delivered record. Pending and leased receiver work stays visible without
|
|
169
|
+
being called complete; a remote terminal failure, malformed response, exhausted
|
|
170
|
+
status access, expired local lease, or altered ledger blocks health fail-closed.
|
|
171
|
+
The authenticated source status and health APIs now expose this content-free
|
|
172
|
+
state through their V3 schemas, including stable local and receiver error codes.
|
|
173
|
+
|
|
174
|
+
### Version 6.60.0: contract-pinned terminal delivery
|
|
175
|
+
|
|
176
|
+
Version 6.60.0 makes the terminal-receiver client directly usable as the
|
|
177
|
+
source service's durable terminal notifier. Before each delivery it validates
|
|
178
|
+
the complete immutable notification locally, fetches and verifies the live
|
|
179
|
+
receiver contract against the trusted deployment pin, and takes the active
|
|
180
|
+
notification path from that verified contract. This supports custom receiver
|
|
181
|
+
paths without maintaining a second unpinned delivery configuration.
|
|
182
|
+
|
|
183
|
+
The write authenticates the exact method, origin, verified path, body SHA-256,
|
|
184
|
+
notification, event, and site. Reserved idempotency and binding headers cannot
|
|
185
|
+
be supplied by credential code. Only an exact acknowledgement for the same
|
|
186
|
+
payload is accepted, and the client exposes stable retryability metadata to the
|
|
187
|
+
durable outbox so it alone controls replay. Invalid payloads and contract drift
|
|
188
|
+
block before the notification write; redirects, cross-site acknowledgements,
|
|
189
|
+
and private transport failures remain fail-closed and content-free.
|
|
190
|
+
|
|
191
|
+
### Version 6.59.0: response-bound terminal-receiver contract
|
|
192
|
+
|
|
193
|
+
Version 6.59.0 binds every health, readiness, and site-specific status response
|
|
194
|
+
to the exact current terminal-receiver capability SHA-256. The server derives
|
|
195
|
+
that binding from its live configured intake path and complete semantic
|
|
196
|
+
contract when it creates each response; the operator client requires it to
|
|
197
|
+
equal the trusted deployment pin.
|
|
198
|
+
|
|
199
|
+
This closes the interval between the client's discovery request and its
|
|
200
|
+
operational request. A switched endpoint, stale replay, changed custom intake
|
|
201
|
+
path, missing binding, or response from another compatible-looking deployment
|
|
202
|
+
cannot pass merely because discovery succeeded immediately beforehand. The new
|
|
203
|
+
field is part of the canonical advertised response schemas, so old clients and
|
|
204
|
+
servers fail closed until upgraded together.
|
|
205
|
+
|
|
206
|
+
### Version 6.58.0: contract-pinned terminal-receiver operator client
|
|
207
|
+
|
|
208
|
+
Version 6.58.0 adds a provider-neutral HTTPS client for the terminal receiver's
|
|
209
|
+
capability, health, readiness, and site-bound status routes. Deployment code
|
|
210
|
+
supplies an expected capability SHA-256 through trusted configuration. Before
|
|
211
|
+
every operational read, the client fetches the live contract, verifies its
|
|
212
|
+
canonical digest and complete semantics, and requires it to equal that pin.
|
|
213
|
+
|
|
214
|
+
Each request uses fresh method-, origin-, path-, body-hash-, event-, and
|
|
215
|
+
site-bound authentication. The client follows no redirect, makes one bounded
|
|
216
|
+
transport attempt per request, accepts only exact UTF-8 JSON schemas and field
|
|
217
|
+
sets, and checks cross-field state invariants. A changed route, reused scope,
|
|
218
|
+
rehashed semantic downgrade, tenant mismatch, partial health evidence, private
|
|
219
|
+
transport exception, or unexpected status blocks with a stable content-free
|
|
220
|
+
error before operational data can be trusted. Valid `503` health and readiness
|
|
221
|
+
snapshots remain observable as blocked state rather than being mislabeled as a
|
|
222
|
+
network failure.
|
|
223
|
+
|
|
224
|
+
### Version 6.57.0: terminal-receiver operational health API
|
|
225
|
+
|
|
226
|
+
Version 6.57.0 adds a separately authenticated, body-free health route for
|
|
227
|
+
the hosted terminal receiver. It combines runtime ownership, managed-worker
|
|
228
|
+
state, verified SQLite inbox integrity, processing counts, due work, expired
|
|
229
|
+
leases, and terminal failures in one content-free operational snapshot. HTTP
|
|
230
|
+
`200` requires an open runtime, a running or deliberately unmanaged worker,
|
|
231
|
+
and an `ok` inbox; every worker or storage failure returns `503` with a stable
|
|
232
|
+
error code.
|
|
233
|
+
|
|
234
|
+
The route authenticates before reading health, never claims work or invokes the
|
|
235
|
+
CMS handler, and uses a fifth distinct scope. Aggregate counts contain no site,
|
|
236
|
+
event, notification, website text, credential, provider response, or private
|
|
237
|
+
exception detail. The discoverable receiver contract now hashes this fifth
|
|
238
|
+
operation, its exact schema, fields, path, method, scope, and success status;
|
|
239
|
+
path collisions or scope reuse block before SQLite is opened.
|
|
240
|
+
|
|
241
|
+
### Version 6.56.0: discoverable terminal-receiver contract
|
|
242
|
+
|
|
243
|
+
Version 6.56.0 adds a separately authenticated, body-free capability route for
|
|
244
|
+
the hosted terminal receiver. It publishes the exact active notification,
|
|
245
|
+
status, health, readiness, and discovery operations with their methods, paths, scopes,
|
|
246
|
+
schemas, required fields, success statuses, transport limits, processing
|
|
247
|
+
states, and terminal outcomes. One canonical SHA-256 covers the complete
|
|
248
|
+
content-free contract, including a configured custom notification intake path.
|
|
249
|
+
|
|
250
|
+
The contract is generated from the same constants used by the receiver and
|
|
251
|
+
never reads SQLite, claims work, calls the CMS handler, or exposes a site,
|
|
252
|
+
notification, website text, credential, or deployment endpoint. A reused
|
|
253
|
+
write/read scope, colliding custom intake path, altered notification schema,
|
|
254
|
+
non-empty discovery request, malformed transport, or private authentication
|
|
255
|
+
failure blocks the complete response instead of advertising a partial or stale
|
|
256
|
+
interface.
|
|
257
|
+
|
|
258
|
+
### Version 6.55.0: terminal-receiver status and readiness API
|
|
259
|
+
|
|
260
|
+
Version 6.55.0 exposes the hosted terminal receiver's durable processing state
|
|
261
|
+
without requiring deployment code to query SQLite. A canonical, authenticated
|
|
262
|
+
status request is bound to one event and site and returns only notification
|
|
263
|
+
identity, hashes, terminal state, attempts, lease timing, stable error code,
|
|
264
|
+
and completion time. A foreign site's event is indistinguishable from a
|
|
265
|
+
missing event.
|
|
266
|
+
|
|
267
|
+
A separate body-free readiness route reports the managed worker and verified
|
|
268
|
+
inbox state. Status and readiness use distinct read scopes from notification
|
|
269
|
+
delivery, never advance processing, and remain available for diagnosis after
|
|
270
|
+
the worker stops or blocks. Plain HTTP, queries, ambiguous framing, invalid
|
|
271
|
+
methods, noncanonical bodies, wrong body hashes, scope reuse, storage damage,
|
|
272
|
+
and private authenticator failures all produce content-free fail-closed
|
|
273
|
+
responses.
|
|
274
|
+
|
|
275
|
+
### Version 6.54.0: supervised terminal-receiver host
|
|
276
|
+
|
|
277
|
+
Version 6.54.0 closes the deployment gap between durable terminal receipt and
|
|
278
|
+
CMS-side processing. `open_hosted_durable_terminal_notification_receiver`
|
|
279
|
+
starts one process-owned, non-daemon background worker that claims and handles
|
|
280
|
+
one due notification at a time. State-specific waits are interruptible, so an
|
|
281
|
+
idle worker stops promptly without waiting through its configured poll delay.
|
|
282
|
+
|
|
283
|
+
Once the runtime enters managed mode, HTTP intake succeeds only while the
|
|
284
|
+
worker is running and inbox health is `ok`. Startup, stop, callback-loop
|
|
285
|
+
failure, terminal processing failure, damaged storage, and inherited pre-fork
|
|
286
|
+
instances therefore fail closed before another notification is acknowledged.
|
|
287
|
+
`worker_readiness()` exposes only worker state, inbox state, and stable error
|
|
288
|
+
codes. `close()` signals and joins the worker before closing SQLite; a bounded
|
|
289
|
+
join timeout leaves the database open for an explicit supervisor decision
|
|
290
|
+
instead of racing a still-running host callback.
|
|
291
|
+
|
|
292
|
+
### Version 6.53.0: durable terminal-notification processing
|
|
293
|
+
|
|
294
|
+
Version 6.53.0 closes the CMS-side callback loop after durable receipt. The
|
|
295
|
+
receiver now creates one processing record in the same transaction that stores
|
|
296
|
+
and acknowledges a terminal notification. A host worker claims one due record
|
|
297
|
+
at a time and receives the exact content-free notification only after the
|
|
298
|
+
claim's owner, random token, attempt, deadline, and immutable payload binding
|
|
299
|
+
have been committed.
|
|
300
|
+
|
|
301
|
+
The host returns a bound `processed` acknowledgement. Retryable failures use a
|
|
302
|
+
persisted bounded exponential delay; permanent failures and exhausted attempts
|
|
303
|
+
remain visible and block health. Expired leases recover after restart, while a
|
|
304
|
+
stale worker cannot complete a replacement claim. Unknown callback exceptions
|
|
305
|
+
become one stable content-free failure code instead of stored private prose.
|
|
306
|
+
|
|
307
|
+
Existing V6.51/V6.52 databases migrate transactionally from schema V1 to V2.
|
|
308
|
+
Every old receipt is validated before one pending processing record is
|
|
309
|
+
backfilled; any altered table or stored binding rolls the whole migration back.
|
|
310
|
+
CMS handlers must apply their own side effect idempotently by
|
|
311
|
+
`notification_id`, because a crash after that side effect but before the local
|
|
312
|
+
completion commit intentionally causes a safe replay.
|
|
313
|
+
|
|
314
|
+
### Version 6.52.0: protected terminal-receiver runtime
|
|
315
|
+
|
|
316
|
+
Version 6.52.0 gives the reference terminal receiver a production-oriented
|
|
317
|
+
composition root. It validates authentication, origin, route, and HTTPS policy
|
|
318
|
+
before opening SQLite, creates a missing database exclusively with mode `0600`,
|
|
319
|
+
and rejects symlinks, hard links, special files, shared writable parents,
|
|
320
|
+
permission drift, and path replacement. The exact file identity is rechecked
|
|
321
|
+
under the runtime lock before every request, status read, and health inspection.
|
|
322
|
+
|
|
323
|
+
One runtime belongs to one WSGI worker process and owns its connection until an
|
|
324
|
+
idempotent close. Inherited pre-fork instances, requests racing shutdown, closed
|
|
325
|
+
runtimes, damaged schemas, failed integrity checks, and semantically altered
|
|
326
|
+
rows remain fail closed. Restarted workers recover the durable inbox, while a
|
|
327
|
+
content-free health result reports only runtime state and received-record count.
|
|
328
|
+
|
|
329
|
+
### Version 6.51.0: durable terminal-notification receiver
|
|
330
|
+
|
|
331
|
+
Version 6.51.0 completes the remote terminal callback with a provider-neutral
|
|
332
|
+
reference receiver. Its HTTPS-only WSGI boundary validates canonical UTF-8 JSON,
|
|
333
|
+
the three reserved identity headers, exact site authorization, and the same
|
|
334
|
+
content-free authentication context used by the sending adapter. Authentication
|
|
335
|
+
remains host supplied, so bearer tokens, HMAC, mTLS gateways, and other policies
|
|
336
|
+
can be integrated without coupling the service to one vendor.
|
|
337
|
+
|
|
338
|
+
The receiver commits each exact notification to a serialized, process-bound
|
|
339
|
+
SQLite inbox before returning the acknowledgement. Replays after a lost response
|
|
340
|
+
return the same acknowledgement without changing the original receipt time;
|
|
341
|
+
changed data under an existing event, notification, or payload identity conflicts.
|
|
342
|
+
Restart recovery, parallel requests, altered storage, malformed framing, wrong-site
|
|
343
|
+
credentials, and private verifier failures are covered fail closed without exposing
|
|
344
|
+
website content or secret-bearing error detail.
|
|
345
|
+
|
|
346
|
+
### Version 6.50.0: secure terminal-notification HTTPS adapter
|
|
347
|
+
|
|
348
|
+
Version 6.50.0 makes the durable terminal outbox deployable across a real CMS
|
|
349
|
+
boundary. The provider-neutral callback adapter posts one canonical,
|
|
350
|
+
content-free terminal notification to one fixed HTTPS endpoint, never follows
|
|
351
|
+
redirects, and never retries inside the transport. A host-supplied
|
|
352
|
+
authentication function receives the exact body hash and routing identity, so
|
|
353
|
+
deployments may apply their own token, signature, or gateway policy without a
|
|
354
|
+
hard-coded provider.
|
|
355
|
+
|
|
356
|
+
The notification ID and body hash are repeated in reserved idempotency and
|
|
357
|
+
binding headers. Only an exact JSON acknowledgement for the same notification,
|
|
358
|
+
event, site, and body hash succeeds. Redirects, altered requests, header
|
|
359
|
+
injection, duplicate JSON keys, incorrect content types, malformed or oversized
|
|
360
|
+
bodies, cross-bound acknowledgements, and private transport exceptions fail
|
|
361
|
+
closed. Retryable status and network failures return only stable public codes
|
|
362
|
+
to the durable outbox, which remains the sole owner of bounded retries.
|
|
363
|
+
|
|
364
|
+
### Version 6.49.0: durable terminal notifications
|
|
365
|
+
|
|
366
|
+
Version 6.49.0 closes the callback gap after lifecycle monitoring reaches a
|
|
367
|
+
verified terminal result. Deployments may supply a provider-neutral terminal
|
|
368
|
+
notifier; the source service then registers one content-free notification in
|
|
369
|
+
the lifecycle database before invoking host code. Event, site, plan, website
|
|
370
|
+
version, source sequence, job count, change hash, lifecycle binding, terminal
|
|
371
|
+
status, and available lifecycle evidence are bound to one deterministic
|
|
372
|
+
notification ID.
|
|
373
|
+
|
|
374
|
+
The notifier is optional so polling-only integrations remain compatible. When
|
|
375
|
+
enabled, each callback attempt uses a durable lease, bounded exponential
|
|
376
|
+
backoff, and an explicit attempt ceiling. Only an exact acknowledgement bound
|
|
377
|
+
to the notification, event, site, and payload hash completes delivery. Lost
|
|
378
|
+
responses replay the same identity; altered evidence, invalid acknowledgements,
|
|
379
|
+
expired leases, exhausted attempts, and damaged state block health without
|
|
380
|
+
exposing website content or private callback errors.
|
|
381
|
+
|
|
382
|
+
### Version 6.48.0: supervised source-CMS host lifecycle
|
|
383
|
+
|
|
384
|
+
Version 6.48.0 closes the operational gap between the durable source-CMS
|
|
385
|
+
runtime and a production WSGI host. `open_hosted_cms_source` starts one owned,
|
|
386
|
+
non-daemon worker before returning the HTTP application. Its interruptible
|
|
387
|
+
sleep allows bounded shutdown without waiting through the idle interval, while
|
|
388
|
+
`close` joins the worker before any SQLite connection is closed.
|
|
389
|
+
|
|
390
|
+
The separately authenticated readiness route reports only worker and service
|
|
391
|
+
state. It stays unavailable before startup, after shutdown, on worker failure,
|
|
392
|
+
or when durable service health blocks. Once a runtime has entered managed mode,
|
|
393
|
+
HTTP change and removal writes fail closed whenever that worker is not running;
|
|
394
|
+
no accepted work can silently remain without an active dispatcher. Private
|
|
395
|
+
exceptions are reduced to stable codes, and a failed worker cannot be restarted
|
|
396
|
+
against potentially inconsistent in-memory state.
|
|
397
|
+
|
|
398
|
+
### Version 6.47.0: discoverable source-CMS contract
|
|
399
|
+
|
|
400
|
+
Version 6.47.0 exposes the complete source-CMS HTTP surface through one
|
|
401
|
+
authenticated, content-free capabilities route. Integrators receive the exact
|
|
402
|
+
active paths, methods, route-specific scopes, principal schemas, request and
|
|
403
|
+
response schemas, required top-level fields, success statuses, retry bounds,
|
|
404
|
+
and transport limits. A canonical SHA-256 binds the complete advertised
|
|
405
|
+
contract for deployment checks and generated clients.
|
|
406
|
+
|
|
407
|
+
The capability object is derived from the same constants used by WSGI routing
|
|
408
|
+
and authentication. It is available only through the separate
|
|
409
|
+
`source-capabilities:read` scope, accepts no body or query, touches no runtime
|
|
410
|
+
state, and performs no network call. Missing, duplicate, or inconsistent route
|
|
411
|
+
metadata blocks the complete response instead of advertising a partial or
|
|
412
|
+
stale interface.
|
|
413
|
+
|
|
414
|
+
### Version 6.46.0: source-CMS lifecycle status
|
|
415
|
+
|
|
416
|
+
Version 6.46.0 closes the source-CMS request loop with an authenticated,
|
|
417
|
+
strictly read-only status route. A CMS can follow one accepted event from its
|
|
418
|
+
durable dispatch through lifecycle registration, per-locale processing,
|
|
419
|
+
approval, publication, cancellation, or failure without receiving source or
|
|
420
|
+
target prose. The response exposes only exact generation identifiers, hashes,
|
|
421
|
+
states, bounded counters, locale tags, and stable error codes.
|
|
422
|
+
|
|
423
|
+
Status credentials are bound to one `site_id` and a separate
|
|
424
|
+
`source-status:read` scope. A missing event and an event owned by another site
|
|
425
|
+
produce the same content-free response. The runtime revalidates the complete
|
|
426
|
+
stored change and lifecycle binding on every read; a corrupt database,
|
|
427
|
+
mismatched response identity, malformed principal, or private exception blocks
|
|
428
|
+
without repairing state, taking a lease, or performing a network call.
|
|
429
|
+
|
|
430
|
+
### Version 6.45.0: authenticated source-CMS HTTP ingress
|
|
431
|
+
|
|
432
|
+
Version 6.45.0 gives the durable source-CMS runtime a strict, optional WSGI
|
|
433
|
+
boundary for real CMS deployments. Separate HTTPS routes accept complete
|
|
434
|
+
change and removal envelopes or return aggregate health; each route requires
|
|
435
|
+
its own authenticated scope. The authenticator receives method, path, bounded
|
|
436
|
+
headers, and the exact body hash, but never the website body as a parsed
|
|
437
|
+
object. Valid work is persisted before the response and later processed by the
|
|
438
|
+
same crash-safe runtime.
|
|
439
|
+
|
|
440
|
+
The boundary rejects ambiguous framing, transfer encoding, queries, oversized
|
|
441
|
+
bodies, duplicate JSON keys, wrong schemas, wrong scopes, and idempotency
|
|
442
|
+
collisions. Responses contain only IDs, hashes, counters, states, and stable
|
|
443
|
+
error codes. Runtime, database, authentication, and response-shape failures
|
|
444
|
+
return fail-closed without exposing source or target text.
|
|
445
|
+
|
|
446
|
+
### Version 6.44.0: owned source-CMS runtime
|
|
447
|
+
|
|
448
|
+
Version 6.44.0 makes the coordinated source-CMS service directly deployable as
|
|
449
|
+
one owned runtime. Its composition root validates the complete client, worker,
|
|
450
|
+
lease, delay, timeout, and database configuration before creating persistent
|
|
451
|
+
state; opens three independent owner-only SQLite files; serializes threads;
|
|
452
|
+
and rejects use inherited across a process fork before lock or store access.
|
|
453
|
+
Restarts and separately constructed workers reuse the existing durable leases,
|
|
454
|
+
so accepted changes, removals, and lifecycle polls converge without duplicate
|
|
455
|
+
change dispatch. Every public failure remains content-free, and a linked,
|
|
456
|
+
hard-linked, aliased, replaced, missing, or permission-weakened database blocks
|
|
457
|
+
before the next network operation.
|
|
458
|
+
|
|
459
|
+
### Version 6.43.0: automatic source-CMS lifecycle service
|
|
460
|
+
|
|
461
|
+
Version 6.43.0 closes the source-side gap between durable webhook delivery and durable lifecycle observation. One provider-neutral service now prioritizes cancellations and tombstones, dispatches immutable website changes, registers every accepted change for monitoring, and polls verified lifecycle state. A restart after remote acceptance but before local registration reconciles the exact stored acknowledgement without sending the accepted change again. Each tick performs at most one network operation, keeps the existing token-bound outbox leases authoritative, and exposes only content-free status and health data.
|
|
462
|
+
|
|
463
|
+
### What “mandatory” really means
|
|
464
|
+
|
|
465
|
+
An MCP server cannot physically stop an agent that is still allowed to print directly to its terminal, Telegram bridge, API response, or file. Non-bypassable enforcement requires the host to capture the complete candidate output, assign `task_kind` and the expected locale outside the agent's control, call the gateway, verify the purpose-bound receipt, and withhold delivery on every failure. If the agent controls the wrapper, signing key, task classification, source, or delivery channel, the installation is advisory.
|
|
466
|
+
|
|
467
|
+
Version 6.1 therefore installs [`enforced_delivery.py`](integrations/enforced_delivery.py) as `blun-language-deliver`. In mandatory mode the untrusted agent may emit only this envelope:
|
|
468
|
+
|
|
469
|
+
```json
|
|
470
|
+
{
|
|
471
|
+
"target_text": "Natürlich können wir das zuverlässig prüfen.",
|
|
472
|
+
"release_token": "blg6.…"
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
The host—not the envelope—supplies `task_kind`, `language`, `source_text`, and content policy. Any attempt by the agent to include or override those fields blocks delivery. Raw text, invalid JSON, a missing token, an edited target, a wrong locale, an expired token, a response token used for translation, an unavailable guard, or a missing key all produce an empty stdout and a nonzero exit.
|
|
477
|
+
|
|
478
|
+
The wrapper exposes its trusted classification to the child as read-only process context through `BLUN_LANGUAGE_GUARD_MANDATORY`, `BLUN_LANGUAGE_GUARD_TASK_KIND`, `BLUN_LANGUAGE_GUARD_LANGUAGE`, and `BLUN_LANGUAGE_GUARD_CONTENT_TYPE`. This lets the agent call the correct MCP release tool with the expected locale. Changing those variables inside the child cannot change the host policy used for final verification.
|
|
479
|
+
|
|
480
|
+
Wrap a non-interactive, JSON-only agent command like this:
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
blun-language-deliver \
|
|
484
|
+
--task-kind response \
|
|
485
|
+
--language de-AT \
|
|
486
|
+
-- your-agent-command --json-only
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
For translation the trusted host captures the complete source independently and chooses the stricter route:
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
blun-language-deliver \
|
|
493
|
+
--task-kind translation \
|
|
494
|
+
--language sv-SE \
|
|
495
|
+
--source-file /trusted/job/source.txt \
|
|
496
|
+
-- your-agent-command --json-only
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
The same module exposes `guarded_send` and `guarded_send_async` for API, Telegram, queue, and web-response adapters. These functions verify before invoking the supplied sender and never invoke it on failure. The host must remove every alternate sender: an agent with direct Telegram/API credentials or an unwrapped stdout path can still bypass any guard.
|
|
500
|
+
|
|
501
|
+
For a genuine security boundary, run the MCP signer and delivery verifier under a separate OS identity, container, or remote service. The agent must be unable to read the signing key, modify the gateway, change trusted source files, administer the delivery socket, or call the final channel directly. Same-user installation is strong workflow enforcement, not protection against a hostile process with filesystem access.
|
|
502
|
+
|
|
503
|
+
### Version 6.42.18: Roman-symbol text bypass
|
|
504
|
+
|
|
505
|
+
Version 6.42.18 protects readable text written with Unicode Roman numeral symbols at Claude's complete `Stop` and `SubagentStop` boundary. Contiguous multi-symbol runs are compatibility-normalized and require an exact signed delivery grant when they cannot be parsed as a non-increasing additive/subtractive Roman number. Literal, lowercase, compound-symbol, and numeric HTML forms such as `ⅭⅠⅤⅠⅭ` now block, while genuine numeric output such as `Ⅻ`, `ⅯⅯⅩⅩⅥ`, additive forms, and isolated symbols remain compatible.
|
|
506
|
+
|
|
507
|
+
### Version 6.42.17: formatted and compact Morse boundaries
|
|
508
|
+
|
|
509
|
+
Version 6.42.17 closes the remaining formatting gaps in Claude's complete `Stop` and `SubagentStop` response check. Valid separated Morse runs now remain protected when parentheses, punctuation, or emoji immediately follow the final code, and the exact bounded compact SOS prosign `...---...` is protected in literal, HTML-encoded, and standard typographic form. Short decoration, incomplete compact signals, and longer unbounded dot-dash runs remain compatible.
|
|
510
|
+
|
|
511
|
+
### Version 6.42.16: Morse output bypass
|
|
512
|
+
|
|
513
|
+
Version 6.42.16 classifies readable Morse output as natural language at Claude's complete `Stop` and `SubagentStop` boundary. Literal ASCII, standard typographic dots and dashes, numeric HTML references, and emoji-prefixed runs now require an exact signed delivery grant when they contain at least three separated valid Morse letter codes using both signal types. Isolated marks, ellipses, and one- or two-token decorative separators remain compatible to avoid punctuation false positives.
|
|
514
|
+
|
|
515
|
+
### Version 6.42.15: exact Stop continuation state
|
|
516
|
+
|
|
517
|
+
Version 6.42.15 requires Anthropic's documented `stop_hook_active` field to be an exact boolean on both `Stop` and `SubagentStop`. Missing, string, numeric, array, object, and null values now terminate processing with `continue: false` before any protected grant state is read. The generic stop reason exposes no response text, and regression tests prove that malformed main and child inputs cannot consume the independently valid one-time grant that a subsequent schema-correct stop still uses.
|
|
518
|
+
|
|
519
|
+
### Version 6.42.14: symmetric Stop identity isolation
|
|
520
|
+
|
|
521
|
+
Version 6.42.14 rejects `agent_id` on the dedicated main-thread `Stop` route, matching Anthropic's event schema where the field is added specifically for `SubagentStop`. Together with the existing child-route requirement, neither stop boundary can address the other's grant namespace: a forged main stop carrying a child ID blocks before protected state is read, and the exact child retains its independently consumable one-time grant.
|
|
522
|
+
|
|
523
|
+
### Version 6.42.13: isolated SubagentStop identity
|
|
524
|
+
|
|
525
|
+
Version 6.42.13 routes Claude's `SubagentStop` event through a dedicated hook mode and requires its documented `agent_id` explicitly. The trusted route and the reported hook event must match before any protected state is read, so a malformed child stop cannot omit its identity, claim the main-thread route, or consume the parent's one-time grant. Ordinary `Stop` inputs retain the documented absent-`agent_id` fallback to `main` for compatibility.
|
|
526
|
+
|
|
527
|
+
### Version 6.42.12: exact Claude hook identities
|
|
528
|
+
|
|
529
|
+
Version 6.42.12 accepts Claude's documented `session_id` and optional `agent_id` only as non-empty strings. Object, array, numeric, empty, and NUL-bearing values now block before protected grant state is read, written, invalidated, or sent to the isolated verifier. This prevents JavaScript coercion from mapping a malformed identity such as `{}` onto the valid string identity `"[object Object]"`; the legitimate session or subagent retains its own one-time grant and remains independently deliverable.
|
|
530
|
+
|
|
531
|
+
### Version 6.42.11: SignWriting output bypass
|
|
532
|
+
|
|
533
|
+
Version 6.42.11 classifies two or more Unicode SignWriting symbols as natural language in Claude's complete `Stop` and `SubagentStop` output. Literal, spaced, numerically HTML-encoded, and mixed sign-language writing can no longer bypass the exact-response grant merely because Unicode categorizes its handshape, movement, and location symbols outside the letter category. One isolated SignWriting symbol and pure SignWriting punctuation remain compatible as non-language output.
|
|
534
|
+
|
|
535
|
+
### Version 6.42.10: Braille output bypass
|
|
536
|
+
|
|
537
|
+
Version 6.42.10 classifies two or more nonblank Unicode Braille cells as natural language in Claude's complete `Stop` and `SubagentStop` output. Literal, spaced, numerically HTML-encoded, and mixed Braille text can no longer bypass the exact-response grant merely because Unicode categorizes Braille patterns as symbols rather than letters. One isolated cell and the blank Braille pattern remain compatible as non-language output, avoiding false positives for individual markers and spacing.
|
|
538
|
+
|
|
539
|
+
### Version 6.42.9: regional-indicator output bypass
|
|
540
|
+
|
|
541
|
+
Version 6.42.9 classifies two or more unpaired Unicode regional indicator symbols as natural language in Claude's complete `Stop` and `SubagentStop` output. Spaced, zero-width-separated, numerically HTML-encoded, and mixed sequences such as `🇭 🇪 🇱 🇱 🇴` can no longer spell readable words outside Unicode's letter category to bypass the exact-response grant. Adjacent pairs remain compatible as ordinary flag emoji, including multiple neighboring or separated flags; one isolated indicator also remains emoji-only. Numeric references are decoded into one visible classification stream without recursively interpreting entity-like replacement text.
|
|
542
|
+
|
|
543
|
+
### Version 6.42.8: enclosed alphabetic output bypass
|
|
544
|
+
|
|
545
|
+
Version 6.42.8 classifies Unicode parenthesized, circled, squared, negative-circled, and negative-squared Latin letters as natural language in Claude's complete `Stop` and `SubagentStop` output. Readable text such as `Ⓗⓔⓛⓛⓞ` or `🅗🅔🅛🅛🅞` can no longer bypass the exact-response grant merely because Unicode categorizes the visible letters as symbols. A single enclosed character that Unicode explicitly marks as emoji, such as `Ⓜ️` or `🅰️`, remains compatible as emoji-only output; a sequence of two or more enclosed letter buttons requires verification so short words cannot use the emoji subset as a bypass.
|
|
546
|
+
|
|
547
|
+
### Version 6.42.7: complete non-language WHATWG references
|
|
548
|
+
|
|
549
|
+
Version 6.42.7 avoids false positives for every semicolon-terminated named reference in the [WHATWG HTML entity table](https://html.spec.whatwg.org/entities.json) whose complete rendered value contains neither a Unicode letter nor a linguistic combining mark. Mathematical operators, arrows, box-drawing characters, card suits, spacing, and invisible aliases can now pass `Stop` and `SubagentStop` without a translation grant when they contain no prose. Unknown references, language-bearing or linguistic combining-mark references, non-legacy names without a semicolon, and safe references followed by natural language remain fail-closed.
|
|
550
|
+
|
|
551
|
+
### Version 6.42.6: quarantined temporary Claude cleanup
|
|
552
|
+
|
|
553
|
+
Version 6.42.6 keeps the creation descriptor open while cleaning up a failed temporary Claude delivery grant or session epoch. The hook first moves the pathname to an unpredictable cleanup quarantine and then proves that the expected creation identity, open descriptor, and quarantined path still identify the same file before unlinking it. A replacement introduced at the former check-to-unlink boundary is preserved under quarantine alongside the original file, and publication blocks fail-closed.
|
|
554
|
+
|
|
555
|
+
### Version 6.42.5: non-language HTML formatting references
|
|
556
|
+
|
|
557
|
+
Version 6.42.5 avoids false positives when Claude's complete `Stop` or `SubagentStop` output consists only of standardized named HTML controls and spacing such as `	`, `​`, or `⁢`. The hook accepts only an exact, case-sensitive, semicolon-terminated set whose rendered values contain neither Unicode letters nor linguistic marks. Semicolonless forms, near misses, unknown names, language-bearing entities, and mixed prose remain fail-closed.
|
|
558
|
+
|
|
559
|
+
### Version 6.42.4: bounded Claude state reads
|
|
560
|
+
|
|
561
|
+
Version 6.42.4 bounds the bytes actually read from every Claude delivery-grant and session-epoch descriptor. A file that grows after its initial metadata check can no longer make `readFileSync` consume unbounded data before the final identity check: the hook reads at most the configured limit plus one byte, rejects growth past that limit, and decodes the complete bounded payload as strict UTF-8. Existing BOM handling and exact state validation remain unchanged.
|
|
562
|
+
|
|
563
|
+
### Version 6.42.3: quarantined Claude state removal
|
|
564
|
+
|
|
565
|
+
Version 6.42.3 removes the old direct pathname delete after identity validation of a Claude delivery grant or session epoch. The hook now moves the candidate to an unpredictable quarantine name inside the retained protected directory, proves that the open descriptor and quarantined path still identify the inspected file, and only then removes it. A replacement introduced at the former removal boundary is preserved under quarantine and the operation blocks fail-closed instead of deleting the substituted file.
|
|
566
|
+
|
|
567
|
+
### Version 6.42.2: protected first-use Claude state creation
|
|
568
|
+
|
|
569
|
+
Version 6.42.2 removes the last recursive path creation from Claude session startup. When the hook state directory does not exist yet, every missing component is now created relative to a retained, no-follow opened, owner-controlled parent-directory handle before any session epoch is registered or published. Linked and broadly writable parents block without receiving a new directory; a parent exchanged during creation receives no state, while safe nested first-use creation remains compatible.
|
|
570
|
+
|
|
571
|
+
### Version 6.42.1: HTML C1 numeric-reference parity
|
|
572
|
+
|
|
573
|
+
Version 6.42.1 closes a rendered-output gap in the Claude `Stop` and `SubagentStop` classifier. HTML parsers replace selected numeric C1 control references through the Windows-1252 compatibility table: for example, `Š` renders as `Š`, even though the raw code point is not a Unicode letter. The hook now classifies the rendered replacement, so decimal, hexadecimal, zero-padded, and semicolonless C1 references that become letters require a release grant. References that render only currency, punctuation, or symbols remain compatible without a natural-language false positive.
|
|
574
|
+
|
|
575
|
+
### Version 6.42.0: hardened Claude hooks become update-visible
|
|
576
|
+
|
|
577
|
+
Version 6.42 publishes the accumulated Stop and SubagentStop hardening under a new plugin cache key. Claude Code uses the explicit manifest version to decide whether an installed marketplace plugin needs an update; leaving the version at 6.41.1 would make existing installations report that they were current while retaining the older cached hooks.
|
|
578
|
+
|
|
579
|
+
`VERSION`, the Claude manifest, the active skill contract, and this README now identify Version 6.42.0 consistently. A repository regression prevents those active version declarations from drifting apart again; every later plugin release must still advance the explicit version with its changed bytes. See Anthropic's official [plugin version-management reference](https://code.claude.com/docs/en/plugins-reference#version-management).
|
|
580
|
+
|
|
581
|
+
### Version 6.41.1: strict Claude plugin paths
|
|
582
|
+
|
|
583
|
+
Version 6.41.1 fixes the two remaining path violations reported by Claude's strict plugin validator. The marketplace now declares its repository-root source as `./`, satisfying Claude's requirement that relative marketplace sources start with `./`. The manifest's `skills` entry now names the `./translate-native` directory that contains `SKILL.md`, rather than naming the Markdown file as if it were a skill directory.
|
|
584
|
+
|
|
585
|
+
The version is bumped because Claude uses the manifest version as the plugin cache and update key; publishing corrected bytes under Version 6.41.0 would leave existing installations unchanged. A repository regression now resolves every declared skill path to a directory containing `SKILL.md` and rejects marketplace sources that do not use Claude's strict relative-path form. Hooks, MCP configuration, delivery policy, and live processes are unchanged. See Anthropic's official [plugin path rules](https://code.claude.com/docs/en/plugins-reference#path-behavior-rules) and [marketplace source rules](https://code.claude.com/docs/en/plugin-marketplaces#relative-paths).
|
|
586
|
+
|
|
587
|
+
### Version 6.41.0: Claude blocks direct Telegram delivery
|
|
588
|
+
|
|
589
|
+
Version 6.41 enforces the existing host-owned delivery contract at Claude's tool boundary. A Claude agent can no longer call a Telegram `reply`, `send`, `send_message`, or `sendMessage` MCP tool before its actual final response reaches `Stop`. The `PreToolUse` hook denies only those delivery operations, never copies their candidate text into the denial, and remains closed even when the language service is unavailable. Read-only Telegram operations remain unaffected.
|
|
590
|
+
|
|
591
|
+
The agent returns its verified final response normally. After `Stop` consumes the fresh grant bound to the exact response, the host-owned bridge remains responsible for delivery. This prevents a direct Telegram tool call from escaping before the lifecycle gate while preserving the non-bypassable host boundary. The implementation follows Anthropic's official [hook reference](https://code.claude.com/docs/en/hooks), where `PreToolUse` can deny a tool call before execution. Regression tests cover the observed `plugin-telegram_telegram.reply` path, candidate confidentiality, and a read-only Telegram control.
|
|
592
|
+
|
|
593
|
+
### Version 6.40.0: Claude binds release calls to the host language
|
|
594
|
+
|
|
595
|
+
Version 6.40 closes the remaining Claude-side path behind delayed `language mismatch` failures. When the trusted host supplies `BLUN_LANGUAGE_GUARD_LANGUAGE` or `BLUN_LANGUAGE_GUARD_TASK_KIND`, the plugin repeats that policy at session and prompt boundaries, rewrites the release tool's `language` argument to the exact host tag in `PreToolUse`, and rejects a wrong release purpose. `PostToolUse` independently rechecks both fields before exchanging the receipt for a delivery grant, so an older client, hook race, or direct invocation cannot bypass the binding.
|
|
596
|
+
|
|
597
|
+
No locale equivalence is introduced: `de`, `de-DE`, and `de-AT` remain distinct signed values. Installations without either host variable retain the existing behavior, while an explicitly present but malformed policy fails closed. The implementation follows Anthropic's official [hook reference](https://code.claude.com/docs/en/hooks): `PreToolUse` may return `updatedInput`, and `UserPromptSubmit` may inject `additionalContext`. Regression tests cover automatic `de-DE` correction, wrong-purpose denial, invalid-policy denial, prompt reinforcement, exact post-tool enforcement, and the no-policy compatibility path.
|
|
598
|
+
|
|
599
|
+
### Version 6.39.0: authoritative reply language wins over Telegram UI language
|
|
600
|
+
|
|
601
|
+
Version 6.39 fixes a real delivery failure in which Telegram's `senderLanguageCode` could override the host's configured response locale. That Telegram field describes the sender's client/interface language and is not reliable evidence for the language of the current message. A German release such as `de-DE` could therefore be checked against `en` or another short UI tag and fail with `language mismatch` even though the text was correct.
|
|
602
|
+
|
|
603
|
+
The BLUN adapter now resolves the language in a strict trust order: explicit per-task guard language, dedicated guard or response configuration, general host language, explicit Telegram conversation language, and only then the legacy sender UI language as a compatibility fallback. The chosen tag is still preserved exactly—`de`, `de-DE`, and `de-AT` are not treated as interchangeable—and the mandatory agent instruction now names the exact release-tool argument. Rejections also identify failed receipt fields without exposing protected text. Regression tests cover configured German with an English Telegram UI, explicit Swedish routing, Catalan conversation metadata, and diagnostic failure output.
|
|
604
|
+
|
|
605
|
+
### Version 6.38.0: update verifies the checkout after repository tests
|
|
606
|
+
|
|
607
|
+
Version 6.38 closes the post-test race in forward updates. Post-update tests run without creating Python bytecode, and the updater then requires the exact completely clean tested candidate before any persistent runtime, Claude integration, health monitor, or update state can change.
|
|
608
|
+
|
|
609
|
+
If uncommitted work appears during the tests, the updater restores the previous revision only through `reset --keep` and preserves the new bytes. If another process creates a commit, it leaves that independent history untouched and does not execute it through an automatic restart. The same rule protects the failing-test path, so a failed candidate can never reset a concurrent commit. Regression tests cover passing and failing tests against both uncommitted and committed races.
|
|
610
|
+
|
|
611
|
+
### Version 6.37.0: rollback verifies the checkout after runtime probes
|
|
612
|
+
|
|
613
|
+
Version 6.37 closes the final rollback window between repository tests and updater-state publication. After installed runtimes restart and the optional Claude cache is checked, the repository must still be the exact completely clean tested target before the scheduler is removed or rollback success is recorded.
|
|
614
|
+
|
|
615
|
+
If uncommitted work appears during runtime verification, rollback safely restores both the forward revision and its runtimes without discarding the new bytes. If another process creates a commit, it leaves that independent history untouched and does not execute it through an automatic restart. Both paths preserve the updater schedule and prior state. Regression tests prove exact `HEAD`, byte preservation, bounded restart behavior, and the absence of scheduler mutation.
|
|
616
|
+
|
|
617
|
+
### Version 6.36.0: rollback verifies the checkout after repository tests
|
|
618
|
+
|
|
619
|
+
Version 6.36 closes the remaining test-time race in emergency rollback. The tested ancestor must still be the exact completely clean checkout after its post-rollback test suite finishes and before any installed runtime is restarted or the automatic-update scheduler is changed.
|
|
620
|
+
|
|
621
|
+
If the tests or another process leave uncommitted work, rollback restores the forward revision only through `reset --keep` and preserves those bytes. If another process creates a commit, the guard leaves that independent history untouched, blocks runtime activation, and requires inspection. Regression tests prove both outcomes and verify that blocked transitions perform no runtime restart or scheduler removal.
|
|
622
|
+
|
|
623
|
+
### Version 6.35.0: rollback rechecks both sides of the cutover
|
|
624
|
+
|
|
625
|
+
Version 6.35 applies the updater's complete clean-checkout contract to emergency rollback. Rollback now starts only from a valid exact `HEAD` with every tracked, staged, and untracked path clean, and rechecks that identical revision after candidate tests and Claude cache preflight immediately before changing the repository.
|
|
626
|
+
|
|
627
|
+
Immediately after `git reset --keep` selects the tested ancestor, rollback requires that exact target and a completely clean checkout before post-tests or runtime activation begin. If uncommitted work appears during cutover, it safely restores the forward revision with `reset --keep` and preserves the new bytes. If another process creates a commit, rollback never rewrites it and blocks runtime activation for manual inspection. Regression tests exercise both dirty and committed races on both sides of the cutover and prove that scheduler removal and runtime restarts never run after a blocked transition.
|
|
628
|
+
|
|
629
|
+
### Version 6.34.0: update cutover rechecks both sides of the fast-forward
|
|
630
|
+
|
|
631
|
+
Version 6.34 closes the remaining network and cutover windows in the clean-checkout contract. After the tested revision is fetched, the updater rechecks the exact pre-update `HEAD` and every tracked, staged, and untracked path before running the fast-forward. Work created while the network request is in progress therefore blocks before the repository moves.
|
|
632
|
+
|
|
633
|
+
Immediately after a successful fast-forward, the updater requires the exact tested revision and a clean checkout before post-update tests or persistent-runtime activation can begin. If uncommitted work appears during the cutover, the updater attempts `git reset --keep`: it returns to the previous revision only when Git can preserve those bytes, otherwise it leaves the state for manual inspection. If another process creates a commit, the updater never resets that independent history. Fetch-time dirty work, fetch-time commits, cutover-time dirty work, and cutover-time commits are separate regression cases.
|
|
634
|
+
|
|
635
|
+
### Version 6.33.0: automatic updates never mix with local work
|
|
636
|
+
|
|
637
|
+
Version 6.33 makes a completely clean active checkout a precondition for automatic and manual repository updates. Tracked edits, staged changes and untracked files now block before the temporary candidate is cloned or any repository-owned candidate test can execute. The updater never stashes, resets, deletes or overwrites local work.
|
|
638
|
+
|
|
639
|
+
The same clean-state and exact-`HEAD` check runs again after candidate tests and Claude plugin preflight, immediately before fetch and fast-forward. If another process edits the checkout or advances its commit during that window, activation stops while both the tested candidate and the local work remain untouched. Rollback already required a clean checkout; forward update now enforces the same fail-closed contract.
|
|
640
|
+
|
|
641
|
+
### Version 6.32.0: maintenance locks identify the process generation
|
|
642
|
+
|
|
643
|
+
Version 6.32 prevents a crashed updater's old lock from becoming immortal when the operating system later reuses the same numeric PID for an unrelated process. New locks bind their PID to an immutable process-start identity: Linux combines the kernel boot ID with the process start tick, Windows uses the process creation time through a read-only Win32 handle, and other POSIX systems hash the start timestamp reported by `ps`.
|
|
644
|
+
|
|
645
|
+
An old lock is recovered only when the PID is dead or the stored and observed process generations definitely differ. If the platform cannot prove the current generation, the lock remains fail-safe and is not removed. Locks written by Version 6.31 remain compatible: a live legacy PID without a generation field is preserved. Exact file-identity checks still protect both stale recovery and normal release from concurrent replacement.
|
|
646
|
+
|
|
647
|
+
### Version 6.31.0: live maintenance locks cannot expire underneath their owner
|
|
648
|
+
|
|
649
|
+
Version 6.31 closes a race between long update, rollback and health-monitor operations. The shared lock no longer becomes removable merely because its timestamp is older than 30 minutes. A validated lock whose process is still alive remains authoritative for its complete lifetime, so a slow test suite or plugin preflight cannot be overtaken by a repair process.
|
|
650
|
+
|
|
651
|
+
Recovery still works after a crash: only an old lock with a confirmed dead owner, or an old malformed lock with no trustworthy owner, may be replaced. Before either stale recovery or normal release deletes anything, the installer rechecks that the path still names the exact file instance it inspected. A concurrently replaced lock is therefore preserved. Lock reads are bounded, regular-file-only and no-follow where the platform supports it; process liveness is checked without sending a signal that changes process state.
|
|
652
|
+
|
|
653
|
+
### Version 6.30.0: updater policy files are fail-closed inputs
|
|
654
|
+
|
|
655
|
+
Version 6.30 treats both active and rollback-paused updater policies as security-sensitive input at every public updater path. Policy reads now reject symbolic links, directories, FIFOs and other special files before opening them; cap input at 64 KiB; and validate the stored Boolean, interval, repository and Claude-command field types. `status`, scheduled `run`, direct update, rollback, reconfiguration and the doctor therefore fail closed instead of following a redirected file, hanging on a pipe or crashing on malformed schema.
|
|
656
|
+
|
|
657
|
+
Atomic JSON writes now use an unpredictable owner-only temporary file in the destination directory, flush it before replacement and always clean it up. A pre-created legacy `updater.json.tmp` link can no longer redirect policy output into another file. Existing regular policy files remain compatible. `auto-update disable` preflights both active and rollback-paused policies before scheduler mutation, then removes only the exact file identities it inspected; unsafe or concurrently exchanged policy state blocks fail-closed.
|
|
658
|
+
|
|
659
|
+
### Version 6.29.0: reconfiguration preserves signed-update enforcement
|
|
660
|
+
|
|
661
|
+
Version 6.29 closes the remaining configuration-time downgrade path in the signed-commit policy. Re-running `auto-update enable` to change an interval or repair a scheduler now resolves the same monotonic active and rollback-paused policy before writing configuration. Omitting `--require-signed-commits` therefore cannot overwrite a stored `true`, and restoring automatic updates after rollback cannot discard the paused requirement.
|
|
662
|
+
|
|
663
|
+
If either stored policy is malformed, non-Boolean, unreadable, linked, or exchanged during reconfiguration, activation stops before scheduler installation. The active replacement and paused-policy removal are each bound to the exact identities read during monotonic policy resolution, so a concurrent replacement is preserved rather than overwritten or deleted. The deliberate escape path remains explicit and auditable: run `auto-update disable` to remove both policies, then enable again without the signature option.
|
|
664
|
+
|
|
665
|
+
Regression tests cover interval-only reconfiguration, reactivation from a paused signed policy, preservation of invalid or concurrently replaced policy bytes, linked paused state, and the explicit disable-then-enable reset control.
|
|
666
|
+
|
|
667
|
+
### Version 6.28.0: signed-update policy cannot be downgraded by omission
|
|
668
|
+
|
|
669
|
+
Version 6.28 makes the optional signed-commit policy monotonic across every updater entry point. After signature enforcement is enabled, a direct `update` call without `--require-signed-commits` can no longer silently fall back to unsigned mode. The updater resolves the effective policy by combining the caller request with both the active automatic-update policy and the policy paused after a successful rollback; any stored `true` remains authoritative.
|
|
670
|
+
|
|
671
|
+
Malformed JSON, a non-object policy, or a non-Boolean `require_signed_commits` value now blocks update and rollback fail-closed before candidate testing or active mutation. This prevents values such as the string `"false"` from being interpreted inconsistently. Disabling automatic updates still explicitly removes both stored policies, preserving the existing operator-controlled escape hatch.
|
|
672
|
+
|
|
673
|
+
Regression tests prove that an unsigned candidate cannot execute its import-time marker through a flagless direct update, that the paused rollback policy reaches the update worker as `true`, and that a type-invalid policy never invokes the worker.
|
|
674
|
+
|
|
675
|
+
### Version 6.27.0: verify trust before executing candidate code
|
|
676
|
+
|
|
677
|
+
Version 6.27 closes an updater supply-chain gap in the optional signed-commit policy. Previously, a clean clone ran its repository-owned test suite before `git verify-commit` rejected an unsigned update or rollback target. Test discovery imports Python modules, so a rejected commit could execute code even though it never became active.
|
|
678
|
+
|
|
679
|
+
When `require_signed_commits` is enabled, both forward update and rollback now resolve and verify the exact checked-out commit immediately after clone or checkout. Only a trusted signature permits test discovery, candidate metadata reads, Claude preflight, fetch, merge, or runtime work. Signature rejection leaves the active checkout and every installed runtime unchanged. The default remains compatible: installations that do not require signed commits continue to test unsigned candidates before activation.
|
|
680
|
+
|
|
681
|
+
The regression tests place an observable import-time marker inside an unsigned candidate and an unsigned rollback target. Both operations must reject the commit while the marker remains absent, proving that the result is not merely a later rollback after code execution.
|
|
682
|
+
|
|
683
|
+
### Version 6.26.0: fail-closed Claude preflight before runtime cutover
|
|
684
|
+
|
|
685
|
+
Version 6.26 closes the split-version window caused by discovering a deterministic Claude plugin failure only after the repository, signer, and MCP had already advanced. When the Claude plugin is installed, the updater now validates the clean temporary candidate with Claude's strict validator, refreshes only the trusted marketplace, and proves exact catalog-version equality while the active checkout and both persistent runtimes are still untouched.
|
|
686
|
+
|
|
687
|
+
Only a successful preflight permits the fast-forward and runtime restarts. The later plugin-cache step consumes that exact expected-version preflight instead of repeating mutation-prone discovery. Validator failure, marketplace failure, catalog drift, an unavailable Claude executable, or process loss records a degraded retry while preserving the active commit, services, and installed cache. A disappearing plugin between preflight and application also fails closed. Tests prove the preflight never invokes `plugin update`, a rejected candidate does not fetch, merge, restart, or create its new runtime file, and process loss becomes a structured failure instead of crashing the scheduler.
|
|
688
|
+
|
|
689
|
+
The unavoidable residual race is explicit: Claude's documented update command targets the latest marketplace version rather than a pinned content digest. Final enabled-state, load-error, and exact-version verification therefore remains mandatory after application; any mismatch leaves delivery degraded and fail-closed.
|
|
690
|
+
|
|
691
|
+
### Version 6.25.0: Claude-native strict validation before update
|
|
692
|
+
|
|
693
|
+
Version 6.25 closes the schema-authority gap in automatic Claude plugin maintenance. Repository tests can verify the files and the BLUN contracts, but they are not Claude Code's own parser. Before refreshing a marketplace or touching an installed cache, the updater now runs the documented `claude plugin validate <plugin-root> --strict` command against the exact repository candidate that already passed the full test suite.
|
|
694
|
+
|
|
695
|
+
Any validator error or warning treated as an error blocks before marketplace refresh and before `plugin update`; the previously installed cache remains unchanged and maintenance is reported as degraded. A valid candidate continues through the Version 6.24 trusted-marketplace refresh, exact catalog-version equality check, official user-scope update, and final installed-version, enabled-state, and load-error verification. An already exact healthy cache remains a no-op.
|
|
696
|
+
|
|
697
|
+
### Version 6.24.0: tested-version marketplace synchronization
|
|
698
|
+
|
|
699
|
+
Version 6.24 closes a stale-catalog gap in automatic Claude plugin maintenance. Anthropic documents marketplace refresh and plugin update as separate CLI operations: `plugin marketplace update` retrieves version changes, while `plugin update` installs the latest version known to that marketplace. Calling only the latter could therefore leave an old catalog and old hooks in place even though the updater had already tested a newer repository revision.
|
|
700
|
+
|
|
701
|
+
For an already-installed but stale plugin, the updater now refreshes only `blun-language-tools`, inspects the refreshed public catalog with `plugin list --available --json`, and requires its advertised version to equal the fully tested runtime version before it invokes the official user-scope plugin update. Refresh failure, invalid catalog output, a missing plugin, catalog/runtime drift, update failure, disabled state, load errors, or final version mismatch all remain degraded and fail-closed. An already exact, enabled, error-free cache stays a no-op. The updater still never installs a missing plugin or claims that an existing session has reloaded downloaded hooks.
|
|
702
|
+
|
|
703
|
+
### Version 6.23.0: service-authoritative session retirement
|
|
704
|
+
|
|
705
|
+
Version 6.23 handles Claude's `SessionEnd` lifecycle event as an authoritative cleanup boundary. Anthropic documents that this event runs when a session terminates, including `/clear` and switching sessions through interactive `/resume`, and that it is intended for cleanup rather than decision control. The plugin therefore removes the owner-only local epoch and every grant record for that exact session before it contacts the isolated service. Another concurrent session and its grants remain untouched.
|
|
706
|
+
|
|
707
|
+
The service retires the epoch only when the request names the exact epoch that is still current, then replaces it with an undisclosed random tombstone. A delayed cleanup from an older session lifecycle cannot overwrite a newer `SessionStart` epoch. Restoring a deleted marker and grant afterward remains blocked by the service; a later genuine startup or resume registers a fresh epoch and restores normal one-time delivery. The hook uses a 700 ms service deadline and a one-second command timeout so local fail-closed cleanup completes within Anthropic's documented 1.5-second overall `SessionEnd` budget. It emits no output and cannot pretend to block termination.
|
|
708
|
+
|
|
709
|
+
### Version 6.22.0: service-authoritative API-failure revocation
|
|
710
|
+
|
|
711
|
+
Version 6.22 makes `StopFailure` invalidation authoritative at the isolated service instead of relying only on deletion of local hook records. Every failed Claude turn now rotates that session's random epoch through the guard service. All earlier main-agent and subagent delivery grants are therefore invalid even if an old local grant record and its matching epoch marker are later restored. A parallel session retains its independent epoch and grants.
|
|
712
|
+
|
|
713
|
+
The rotation removes the old local epoch before asking the isolated service to register its replacement and writes the new owner-only marker only after confirmation. If the guard is unavailable, rejects the epoch, or the marker cannot be replaced, the session remains deliberately fail-closed until a later `SessionStart` repairs it. After a successful rotation, a fresh exact response or translation release works normally and remains one-time. The hook still emits nothing because Anthropic documents `StopFailure` output and exit status as ignored.
|
|
714
|
+
|
|
715
|
+
### Version 6.21.0: invalidate grants after API failure
|
|
716
|
+
|
|
717
|
+
Version 6.21 handles Claude's `StopFailure` lifecycle event, which Anthropic documents as running instead of `Stop` when a turn ends because of an API error. A rate limit, authentication failure, server error, output-limit failure, or other API failure now removes every unconsumed main-agent and subagent delivery grant belonging to that exact Claude session. A later retry must therefore obtain a fresh response or translation release; another concurrent session remains untouched.
|
|
718
|
+
|
|
719
|
+
The cleanup is deliberately silent. Anthropic documents that `StopFailure` output and exit status are ignored, so the hook does not pretend it can block or guide Claude at this event. It emits no candidate, rendered API error, or diagnostic detail. The next `UserPromptSubmit`, `Stop`, and `SubagentStop` boundaries remain fail-closed if protected state is unavailable or could not be removed.
|
|
720
|
+
|
|
721
|
+
### Version 6.20.0: safe recovery after guard-service restart
|
|
722
|
+
|
|
723
|
+
Version 6.20 lets an already running Claude session recover after the isolated guard service restarts. Anthropic's official [hooks reference](https://code.claude.com/docs/en/hooks) describes `SessionStart` as a session lifecycle event, so restarting an independent local service does not itself create a new Claude startup boundary. Version 6.19 therefore invalidated old grants safely but also left the restarted service without the active session epoch until Claude restarted or resumed.
|
|
724
|
+
|
|
725
|
+
The service may now recover a missing epoch only inside `authorize_delivery` and only after it has cryptographically verified a fresh response or translation receipt. It never recovers during grant consumption. A forged or rejected receipt cannot enroll a session; a different epoch already registered during the current service boot still blocks; every pre-restart grant remains invalid because its signed service-boot identity changed. The next successful release call restores availability without weakening fail-closed behavior or recording the raw epoch in the audit log.
|
|
726
|
+
|
|
727
|
+
### Version 6.19.0: service-authoritative session epochs
|
|
728
|
+
|
|
729
|
+
Version 6.19 closes the remaining two-file replay path in the Claude hook. Version 6.18 rejected an old local grant record after `SessionStart` rotated its epoch marker, but restoring both the record and its matching old marker could recreate the local state. The isolated guard service now registers the active epoch for each hashed Claude session and atomically requires that registered value before issuing or consuming any delivery grant.
|
|
730
|
+
|
|
731
|
+
Every startup, resume, clear, compaction, or fork therefore replaces the service-authoritative epoch as well as the owner-only local marker. Previously registered epochs cannot be registered again during the same service boot. Restoring both old files, authorizing against an obsolete epoch, replaying an earlier registration, or losing the registration response blocks; another session remains independent. The service retains only session and epoch hashes, and neither the raw epoch nor candidate text enters its audit log. Anthropic's official [hooks reference](https://code.claude.com/docs/en/hooks) documents these `SessionStart` lifecycle sources.
|
|
732
|
+
|
|
733
|
+
### Version 6.18.0: session-resume-bound delivery grants
|
|
734
|
+
|
|
735
|
+
Version 6.18 prevents an unconsumed delivery grant from surviving a Claude session restart, `--resume`, `--continue`, `/resume`, `/clear`, or context compaction. Anthropic's official [hooks reference](https://code.claude.com/docs/en/hooks) states that `SessionStart` runs for each of those lifecycle sources, including resumed sessions. The plugin now rotates a cryptographically random delivery epoch on every `SessionStart`, removes the session's outstanding main-agent and subagent records, and requires that epoch before it will authorize any new release.
|
|
736
|
+
|
|
737
|
+
The isolated service signs only the epoch's SHA-256 binding into each delivery grant and checks the live epoch again during one-time consumption. The raw epoch remains in an owner-only local marker and never enters the grant, audit log, candidate diagnostics, or skill text. A copied pre-resume record, missing marker, unsafe marker permissions, failed rotation, cross-session epoch, or old pre-6.18 record blocks; the final `Stop` and `SubagentStop` checks therefore remain fail-closed even if stale local JSON is restored after resume.
|
|
738
|
+
|
|
739
|
+
### Version 6.17.0: invalidate grants on every rejected release
|
|
740
|
+
|
|
741
|
+
Version 6.17 closes the logical-failure half of the stale-grant path. A release tool can execute successfully while returning no usable receipt, while the isolated verifier rejects that receipt, or while delivery authorization becomes unavailable. The synchronous `PostToolUse` hook now clears any earlier grant for the exact session and agent before processing every new release attempt and clears it again on every rejection path. A failed new attempt can therefore never fall back to an older authorization.
|
|
742
|
+
|
|
743
|
+
The second invalidation is deliberate: Anthropic's official [hooks reference](https://code.claude.com/docs/en/hooks) documents that `PostToolUse` hooks run concurrently for parallel tool calls. Rechecking on rejection ensures that a later failure removes a grant written by an overlapping earlier attempt, while a later successful attempt may still establish its own exact grant. Missing receipts, verifier rejection, verifier outages, protected-state deletion failures, cross-session isolation, privacy-safe diagnostics, and ordinary success all have regression coverage.
|
|
744
|
+
|
|
745
|
+
### Version 6.16.0: fail closed after release-tool failures
|
|
746
|
+
|
|
747
|
+
Version 6.16 closes the stale-grant path that appears when Claude's MCP release call fails. Anthropic's official [`PostToolUseFailure` hook contract](https://code.claude.com/docs/en/hooks) can add recovery context alongside the tool error and can return a blocking decision. The plugin now matches only failed `release_response` and `release_translation` calls, immediately removes any earlier unconsumed delivery grant for that exact Claude session and agent, and tells Claude to reconnect and repeat the correct release workflow.
|
|
748
|
+
|
|
749
|
+
The failure hook never copies the candidate, source, tool error, receipt, or token into its output. It preserves grants belonging to other agents and sessions, ignores unrelated failed tools, and blocks if protected state cannot be invalidated. `Stop` and `SubagentStop` remain the authoritative delivery boundary: a failed release call never creates a grant, and the now-stale earlier text cannot pass afterward. Regression tests prove same-agent invalidation, cross-session isolation, recovery instructions for both release paths, privacy-safe output, and unchanged exact-release success.
|
|
750
|
+
|
|
751
|
+
### Version 6.15.0: mandatory subagent startup context
|
|
752
|
+
|
|
753
|
+
Version 6.15 closes an instruction gap between the main Claude session and its subagents. Anthropic's official [hook lifecycle](https://code.claude.com/docs/en/hooks) places `SubagentStart` context before a subagent's first prompt. The plugin now uses that event to tell every subagent that native-language output requires its own fresh `release_response` or `release_translation` grant, bound to that session and agent identity. A subagent no longer has to discover the requirement only after `SubagentStop` rejects its first answer.
|
|
754
|
+
|
|
755
|
+
`SubagentStart` is guidance, not the security boundary: Anthropic does not allow it to block subagent creation. The existing service-backed `SubagentStop` verification and bounded hard stop remain authoritative. A healthy startup injects the exact release workflow; an unavailable guard injects an explicit fail-closed instruction. Tests prove the correct event-specific output, both release paths, agent-specific wording, and the unavailable-service branch.
|
|
756
|
+
|
|
757
|
+
### Version 6.14.0: turn-bound delivery grants
|
|
758
|
+
|
|
759
|
+
Version 6.14 prevents an unconsumed Claude delivery grant from surviving an interrupted turn. Anthropic's official [hook lifecycle](https://code.claude.com/docs/en/hooks) places `UserPromptSubmit` before Claude processes each new turn. The plugin now uses that trusted boundary to invalidate every outstanding main-agent and subagent grant belonging to the current session before the new prompt is processed. A generic response released in an abandoned turn therefore cannot authorize identical text in a later turn.
|
|
760
|
+
|
|
761
|
+
The added session identifier is only a SHA-256 label, never the prompt or source text. Invalidation scans only hook-state JSON records, preserves labeled concurrent sessions, tolerates unrelated or malformed foreign records, and blocks the current prompt if a matching record cannot be removed. Structurally valid pre-6.14 grant records have no session label and are discarded once during the upgrade rather than trusted across a turn boundary. Regression coverage proves cross-turn replay rejection, same-session and legacy-subagent cleanup, parallel-session isolation, and ordinary release behavior after the boundary.
|
|
762
|
+
|
|
763
|
+
### Version 6.13.0: bounded fail-closed Stop recovery
|
|
764
|
+
|
|
765
|
+
Version 6.13 closes a Claude lifecycle bypass caused by repeated Stop-hook rejection. [Anthropic documents](https://code.claude.com/docs/en/hooks) that `stop_hook_active` becomes true when Claude is already continuing because of a Stop hook, while the official [hook troubleshooting guide](https://code.claude.com/docs/en/hooks-guide) explains that Claude Code eventually overrides a hook after repeated consecutive blocks. Returning `decision: "block"` forever was therefore neither reliable enforcement nor reliable recovery.
|
|
766
|
+
|
|
767
|
+
The mandatory hook now gives Claude one protected correction cycle. A newly released exact response or translation can still pass during that cycle. If `stop_hook_active` is already true and the output remains unverified, both `Stop` and `SubagentStop` return the universal `continue: false` hard stop instead of adding another block. The user-visible stop reason is generic and contains no candidate text, receipt, source, or token. Tests cover the first correction request, the second-attempt hard stop, a successfully corrected signed answer, and the subagent path.
|
|
768
|
+
|
|
769
|
+
### Version 6.12.0: non-mutating portable verification
|
|
770
|
+
|
|
771
|
+
Version 6.12 closes a trust-root failure in the portable pre-output verifier. Earlier portable and installed-skill hooks used the signer's load-or-create helper: a missing verifier key could therefore create a new signing key before rejecting the current receipt, and a later signer restart could adopt that unrelated key. Both hooks now only read an existing key, require at least 32 bytes, enforce owner-only permissions on POSIX systems, and fail closed without creating directories or files. The explicit `BLUN_LANGUAGE_GUARD_KEY` compatibility path remains available, but no filesystem fallback may initialize or repair signing state.
|
|
772
|
+
|
|
773
|
+
Regression tests exercise both shipped hook locations, prove that a missing key remains absent, prove that broadly readable keys block on POSIX, and retain the existing exact-receipt success and edited-target rejection controls. Version 6.11's complete context-bound one-time delivery grants remain unchanged.
|
|
774
|
+
|
|
775
|
+
### Version 6.11.0: complete delivery-context binding
|
|
776
|
+
|
|
777
|
+
Version 6.11 closes the final context gap between a successful release tool call and Claude's actual `Stop` or `SubagentStop`. The isolated service now signs the canonical source hash, target hash, exact language, task purpose, content type, short-text review flag, delivery channel, Claude session, agent identity, guard version, service boot, expiry, and nonce into every one-time delivery grant. The stop hook must return that complete context when consuming the grant; any changed, missing, stale, copied, or cross-context value blocks delivery.
|
|
778
|
+
|
|
779
|
+
The Claude hook stores only the canonical source hash, never the complete translation source. The full source remains bound by the original signed release receipt and is independently verified before the delivery grant is issued. A translation grant therefore cannot be relabeled as a normal response, moved to another locale or content policy, or detached from its source context at the last delivery boundary. Version 6.10's deep health probe and existing one-time, target, session, subagent, restart, and replay protections remain unchanged.
|
|
780
|
+
|
|
781
|
+
### Version 6.10.0: deep MCP health proof
|
|
782
|
+
|
|
783
|
+
Version 6.10 closes a false-green health gap. The one-minute monitor no longer accepts a signer heartbeat plus MCP initialization and a matching tool list as proof that the language guard can actually execute tools. The isolated service's authenticated health operation now performs an audit-free response release with correct Swedish Unicode, verifies the resulting purpose-bound signature, and proves that a changed target is rejected. The HTTP probe then performs a real MCP `tools/call` using `validate_text` on `Hälsokontrollen är aktiv.` and requires an exact `PASS` result.
|
|
784
|
+
|
|
785
|
+
No customer text, token, or synthetic canary is written to the audit log. A broken release/signature path, a gateway that merely advertises tools, or a failed tool dispatcher now makes the health monitor block and enter its existing ordered repair and bounded-backoff path. The integration suite runs this complete chain through temporary TCP signer and authenticated HTTP MCP servers without touching installed services.
|
|
786
|
+
|
|
787
|
+
### Version 6.9.0: transactional safe rollback
|
|
788
|
+
|
|
789
|
+
Version 6.9 turns the updater's recorded previous revision into an explicit, fail-closed recovery command. `rollback` accepts only an exact 40-character commit recorded by the immediately preceding successful or degraded update, requires the current `HEAD` to match that update, requires a clean worktree, and proves that the target is an available ancestor. It clones the target locally, runs its complete test suite, enforces the saved signed-commit policy when enabled, and changes the active checkout only after every preflight passes. The rolled-back checkout is tested again and already-installed guard and MCP runtimes must restart and pass their live probes; otherwise the updater restores the forward revision. The final automatic-update pause is bound to the exact active and paused policy identities inspected before candidate execution; concurrent replacements are preserved and trigger forward restoration instead of being overwritten or moved.
|
|
790
|
+
|
|
791
|
+
Claude adds a necessary safety boundary. Anthropic documents `claude plugin update` as updating to the latest plugin and does not document a version-pinned downgrade. Therefore the command never guesses or edits Claude's cache: if the plugin is installed, its enabled, error-free cached version must already equal the rollback target before Git changes. After success, the operating-system scheduler is removed and its policy is preserved as `updater.rollback-paused.json`, so even an older rolled-back installer cannot immediately reinstall the rejected revision. Existing Claude sessions still require `/reload-plugins` or a restart.
|
|
792
|
+
|
|
793
|
+
### Version 6.8.0: mandatory plugin-cache health
|
|
794
|
+
|
|
795
|
+
Version 6.8 extends the one-minute health path to the installed Claude plugin cache because the mandatory `Stop` and `SubagentStop` hooks live there. Once the monitor observes an installed `translate-native@blun-language-tools` plugin, it enrolls that cache and checks its enabled state, load errors, and exact version together with the signer and MCP. A stale or unhealthy enrolled cache blocks the overall health result and receives one official `claude plugin update ... --scope user` repair attempt under the same operation lock and exponential backoff as the services.
|
|
796
|
+
|
|
797
|
+
Enrollment never installs a missing plugin and never reads or edits Claude's private cache layout. The monitor uses the owner-visible Claude executable recorded at installation or updater setup, calls only the documented `plugin list --json` and `plugin update` commands, and verifies the exact version afterward. A successful cache repair still does not claim that an existing session reloaded its hooks: run `/reload-plugins` or start a new session before relying on the new plugin code.
|
|
798
|
+
|
|
799
|
+
### Version 6.7.1: self-healing guard stack
|
|
800
|
+
|
|
801
|
+
Version 6.7 adds an independent one-minute health monitor for the two-process Claude path. It verifies both the isolated signer and the complete authenticated MCP `healthz` → `initialize` → `tools/list` path. If the signer fails, it repairs that dependency first and then rechecks the MCP; if only the MCP fails, it restarts only the MCP. Every repair is followed by a complete end-to-end probe before the state may become `recovered`.
|
|
802
|
+
|
|
803
|
+
The monitor uses systemd on Linux, a LaunchAgent on macOS, and Task Scheduler on Windows. A shared atomic operation lock prevents it from fighting the updater, and each run makes at most one dependency-ordered repair. Version 6.7.1 replaces the ineffective fixed cooldown with persistent exponential backoff: repeated failed repairs wait 1, 2, 5, 15, and then at most 60 minutes, while health probes continue every minute. A skipped probe does not increase the failure count or postpone the next eligible repair, and a successful end-to-end probe resets the backoff immediately. Its state contains only health booleans, timestamps, counters, and repair labels—never source text, target text, receipts, or credentials. Failure remains fail-closed: the monitor never substitutes a local signer or releases pending output while either process is unhealthy.
|
|
804
|
+
|
|
805
|
+
Fresh Claude installations enable the monitor automatically. Existing automatically updated installations detect the missing health state on their next scheduler wake-up and install it without waiting for the normal update interval:
|
|
806
|
+
|
|
807
|
+
```bash
|
|
808
|
+
python3 installer/blun_language_guard.py health-monitor install
|
|
809
|
+
python3 installer/blun_language_guard.py health-monitor status
|
|
810
|
+
python3 installer/blun_language_guard.py health-monitor run
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
`health-monitor remove` removes only the monitor schedule; it preserves both services, all secrets, and user configuration. Before changing the schedule or persisted opt-out, it validates the exact policy and state files and refuses linked, unsafe, malformed, or concurrently replaced state fail-closed.
|
|
814
|
+
|
|
815
|
+
### Version 6.5: service-owned one-time delivery grants
|
|
816
|
+
|
|
817
|
+
Version 6.5 removes the local Claude hook record as a trust decision. After `release_response` or `release_translation`, the `PostToolUse` hook sends the complete receipt context to the isolated service. A valid receipt is exchanged for a short-lived signed delivery grant bound to the exact target hash, Claude session, agent or subagent, guard version, service boot, purpose, locale, and expiry.
|
|
818
|
+
|
|
819
|
+
The owner-only hook file contains the opaque delivery grant, canonical source and target hashes, signed context labels, and authorization time—never the source or target prose. The grant file and service-authoritative session epoch are bounded regular files opened without following links where the platform supports it, checked for owner-only access and stable identity, and replaced through unpredictable exclusive temporary files. At `Stop` or `SubagentStop`, the hook removes the exact inspected record before asking the isolated service to consume the grant for the actual `last_assistant_message` and exact recorded context. The service accepts each nonce exactly once. Copying a consumed record, forging or relabeling local state, racing its replacement, changing the final response, moving a grant to another session or subagent, restarting the signer, or crossing a version boundary now fails closed.
|
|
820
|
+
|
|
821
|
+
This strengthens the ordinary same-user installation without overstating it. A process that can read the service authentication token, replace managed hooks, or reach the final delivery channel can still bypass workflow enforcement. Use a separate OS identity, container, remote signer, and host-owned delivery credentials for a hostile-process boundary.
|
|
822
|
+
|
|
823
|
+
### Version 6.4: Claude plugin and mandatory final-response hooks
|
|
824
|
+
|
|
825
|
+
The repository is now both a Claude Code plugin and a Claude plugin marketplace. The plugin bundles the `translate-native` skill, connects to the persistent HTTP MCP, injects mandatory policy at session start, observes successful release-tool calls, and applies `Stop` plus `SubagentStop` hooks to the actual final response.
|
|
826
|
+
|
|
827
|
+
The `PostToolUse` hook does not trust the MCP result by appearance. It sends the receipt, exact target, complete source for translations, purpose, locale, and content policy to the isolated verifier. Version 6.5 exchanges a valid result for a service-owned one-time delivery grant rather than trusting the local hook record itself. A missing, stale, replayed, wrong-purpose, or post-release-edited result prevents Claude from stopping and tells it to run the proper release path again.
|
|
828
|
+
|
|
829
|
+
Install the persistent runtime first, then the marketplace plugin:
|
|
830
|
+
|
|
831
|
+
```bash
|
|
832
|
+
python3 installer/blun_language_guard.py install --target claude
|
|
833
|
+
claude plugin marketplace add Maykbiletti/translate-native --scope user
|
|
834
|
+
claude plugin install translate-native@blun-language-tools --scope user
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
In Claude's `/plugin` interface, open **Marketplaces → blun-language-tools → Enable auto-update**. Claude then refreshes the marketplace and installed plugin at startup. A changed plugin is activated by `/reload-plugins` or the next session; the independently installed HTTP service continues running during that change.
|
|
838
|
+
|
|
839
|
+
The plugin's checked-in components are:
|
|
840
|
+
|
|
841
|
+
- [`.claude-plugin/plugin.json`](.claude-plugin/plugin.json): versioned plugin manifest;
|
|
842
|
+
- [`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json): GitHub marketplace catalog;
|
|
843
|
+
- [`.mcp.json`](.mcp.json): plugin-scoped persistent MCP connection;
|
|
844
|
+
- [`hooks/hooks.json`](hooks/hooks.json): session, release-tool, main-agent, and subagent hooks;
|
|
845
|
+
- [`claude_language_hook.js`](integrations/claude_language_hook.js): cross-platform, zero-package verification state machine.
|
|
846
|
+
|
|
847
|
+
This closes accidental omission and catches an agent that validates one draft but returns another. A forged hook-state file alone no longer passes because the isolated service must consume its signed grant. It is still not a hostile-process boundary: same-user code may be able to read service credentials or disable an unmanaged plugin. For organization-wide enforcement, force-enable the plugin and managed hooks, remove direct delivery credentials from the agent, or place a buffering BLUN host in front of rendered output.
|
|
848
|
+
|
|
849
|
+
### Version 6.3: persistent Claude MCP
|
|
850
|
+
|
|
851
|
+
Claude Code no longer needs to keep this guard alive as a child `stdio` process. The installer registers an authenticated, user-scoped Streamable HTTP server at `http://127.0.0.1:47632/mcp`. The endpoint is stateless: every tool call is a separate request, so a disconnected client pipe cannot kill the server or erase its tools. The operating system keeps the process alive and restarts it after a failure. This follows Claude Code's documented [user-scoped HTTP MCP configuration](https://code.claude.com/docs/en/mcp) and the MCP specification's [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports).
|
|
852
|
+
|
|
853
|
+
```bash
|
|
854
|
+
python3 installer/blun_language_guard.py install --target claude
|
|
855
|
+
python3 installer/blun_language_guard.py mcp-service status
|
|
856
|
+
python3 installer/blun_language_guard.py doctor
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
Installation safely updates the top-level user entry in `~/.claude.json`, preserves unrelated settings and MCP servers, creates `~/.claude.json.bak`, and removes stale same-name local entries stored under individual projects in that file. This matters because Claude's local and project scopes take precedence over user scope; an old project-specific `stdio` definition can otherwise make the repaired server appear unreliable only in certain repositories. Checked-in `.mcp.json` files remain project-owned and must not define another server with the same name. `doctor` reads each candidate through a bounded no-follow check and fails closed on symbolic links, additional hard links, special files, unsafe permissions, malformed schemas, oversized content, or exchange races instead of silently treating an unreadable configuration as shadow-free.
|
|
860
|
+
|
|
861
|
+
The exact generated shape is also available as [`claude-http.example.json`](mcp-server/claude-http.example.json) for inspection. Let the installer write the machine-specific absolute helper path instead of copying the example by hand.
|
|
862
|
+
|
|
863
|
+
The Claude entry uses [`mcp_auth_headers.py`](integrations/mcp_auth_headers.py) as `headersHelper`. Claude runs that helper again at connection time and after an authentication retry, so the bearer token remains in an owner-only file instead of being copied into configuration. The HTTP server binds only to loopback, validates browser origins, requires authentication, rejects oversized or invalid requests without exiting, accepts UTF-8 BOM input, and exposes an authenticated `/healthz` probe covering the complete path to the isolated guard service.
|
|
864
|
+
|
|
865
|
+
The persistent transport improves availability; it does not turn MCP instructions into a security boundary. The trusted host must still intercept output and fail closed. If the HTTP service or isolated signer is unavailable, delivery remains blocked rather than falling back to local signing or raw text.
|
|
866
|
+
|
|
867
|
+
### Version 6.2: isolated runtime enforcement
|
|
868
|
+
|
|
869
|
+
Version 6.2 moves signing and final verification into [`guard_service.py`](integrations/guard_service.py), a dedicated loopback service. The MCP process and host adapters receive only a service endpoint and an authentication token; the untrusted agent child receives neither the signing key nor the service token. The service accepts UTF-8 with or without a BOM, signs releases, verifies the exact envelope at delivery time, and appends a content-free audit record containing only hashes, route metadata, guard version, and finding codes.
|
|
870
|
+
|
|
871
|
+
The audit log and its interprocess lock now use protected append-only handles. They are created exclusively with mode `0600`, refuse symbolic links, additional hard links, FIFOs, non-owner files, and paths writable by another account, and verify that the named file still matches the open descriptor before and after locking or appending. A substituted or exchanged audit path therefore blocks the release without modifying its target. The authenticated health self-test inspects both paths without creating a canary record, so the monitor cannot report green while real releases would fail at the audit boundary; existing content-free `0644` logs remain readable and append-compatible because only owner write access is required.
|
|
872
|
+
|
|
873
|
+
The signing key is treated as protected trust-root state. Signer and verifier paths accept only bounded, owner-only regular files, refuse symbolic links, open without following links where supported, and compare file identity across inspection and reading. First creation reserves the final path exclusively and requests owner-only mode `0600` where POSIX permissions apply; the former predictable `.tmp` name is never touched, and a concurrent creator can neither replace an existing key nor redirect initialization through a prepared link.
|
|
874
|
+
|
|
875
|
+
The isolated service authentication token now uses the same protected-state contract everywhere it is consumed: the signer, MCP process, mandatory host delivery command, Claude hooks, BLUN Code adapter, installer probe, and doctor accept only a bounded regular file, require owner-only access where POSIX permission bits apply, and verify its identity before and after reading. Installation reserves the final token path exclusively, requests owner-only mode `0600` on POSIX systems, and never touches the former predictable `.tmp` name. A linked, oversized, broadly readable, replaced, or malformed token therefore fails closed before any request reaches the signer; direct environment-token deployments remain compatible.
|
|
876
|
+
|
|
877
|
+
The persistent HTTP MCP bearer token follows that protected-file contract independently. The gateway, Claude `headersHelper`, installer health probe, and doctor accept only a bounded owner-only regular token, open it without following links, and verify the same file identity throughout the read. Installation reserves `mcp-http.token` directly with exclusive creation and owner-only mode instead of writing through the former predictable `.tmp` path. An unsafe token therefore blocks before the loopback MCP starts or receives a health request, while an existing valid token continues to survive reinstall and rotation is picked up by the headers helper on the next reconnect.
|
|
878
|
+
|
|
879
|
+
The mandatory `delivery-policy.json` is protected at each trust decision as well. The host delivery boundary, Claude hooks, installer, and doctor accept only a bounded owner-only regular JSON file, open it without following links, compare its identity before and after reading, and validate the fail-closed delivery and isolated-service fields. A linked, oversized, broadly readable, malformed, or exchanged policy blocks before model output, command installation, key creation, or service access; an absent policy still preserves the existing first-install and explicitly configured local-verifier paths.
|
|
880
|
+
|
|
881
|
+
Health-monitor policy and backoff state use the same protected-file discipline. The installer accepts only bounded owner-only regular JSON files, opens them without following links where supported, verifies stable identity across the complete read, and validates the persisted Boolean, integer, string, and repair-list fields. Unsafe health state blocks status, repair, and update candidate execution without restarting services, resetting backoff, replacing a linked path, or changing its target. Missing files retain the existing first-run migration behavior, valid owner-only files remain compatible, and POSIX permission checks remain disabled on Windows where those mode bits are not authoritative.
|
|
882
|
+
|
|
883
|
+
Health-monitor activation is also bound to the exact policy identity inspected after its initial health probe. A policy that appears or changes before scheduler installation blocks without touching the scheduler. If an exchange races with scheduler activation, the replacement is preserved, the newly installed schedule is removed, and activation reports a fail-closed error instead of overwriting concurrent operator state.
|
|
884
|
+
|
|
885
|
+
The minutely monitor applies the same identity binding when it first observes an installed Claude plugin and automatically enrolls that cache in mandatory health checks. A policy exchanged while Claude's status command is running survives unchanged; enrollment, plugin repair, and health-state publication stop fail-closed instead of replacing the operator's newer policy.
|
|
886
|
+
|
|
887
|
+
Every minutely health-state transition is likewise bound to the exact backoff file inspected at run start. An exchange discovered after probing blocks before a service or plugin repair; an exchange during a repair preserves the replacement and prevents the stale result from being published. This keeps concurrent operator state and a newer backoff authoritative without weakening the existing one-repair-per-run limit.
|
|
888
|
+
|
|
889
|
+
The monitor also keeps its initially inspected health-policy identity authoritative for the complete run. A policy exchanged during signer, MCP, or Claude probing blocks before any repair; an exchange during a repair prevents later dependent repairs and stale health-state publication. Automatic Claude enrollment refreshes the expected identity only after its own protected policy replacement, so the compatible first-enrollment path remains available while concurrent operator changes remain authoritative.
|
|
890
|
+
|
|
891
|
+
The updater's recorded state is protected independently from its policy. `doctor`, `auto-update status`, scheduled checks, direct updates, and rollback now read `update-state.json` through a bounded owner-only regular-file path, reject links and exchanged identities, and validate commit hashes plus every security-relevant persisted type. Unsafe state blocks before Git commands or candidate code can run and is never printed or replaced through that read path. A missing state remains valid before the first successful update, while rollback continues to require a complete exact state record.
|
|
892
|
+
|
|
893
|
+
Update and rollback now retain that initially inspected state identity for the complete maintenance operation. Candidate activation stops if another process replaces the state during preflight or fetch, rollback restores the forward revision if the state changes during runtime verification, and every final status write rechecks the same identity immediately before atomic replacement. Concurrent recovery decisions therefore survive unchanged instead of being overwritten by stale success, degraded, or rolled-back reports; the absent first-run state remains compatible.
|
|
894
|
+
|
|
895
|
+
Forward updates now retain the initially inspected health-policy and backoff-state identities as well. Scheduler activation, healthy-state initialization, and automatic Claude plugin maintenance stop when either protected file is exchanged during the update. Every updater-owned health write rechecks both identities immediately before atomic replacement and refreshes only the identity produced by its own successful write. A concurrent opt-out therefore survives unchanged and removes the schedule activated by the stale updater pass; other replacement policies and newer backoff decisions remain untouched while the update records a degraded retry.
|
|
896
|
+
|
|
897
|
+
The installer now creates and starts the service automatically through systemd user services on Linux, a LaunchAgent on macOS, or Task Scheduler on Windows:
|
|
898
|
+
|
|
899
|
+
```bash
|
|
900
|
+
python3 installer/blun_language_guard.py install
|
|
901
|
+
python3 installer/blun_language_guard.py service status
|
|
902
|
+
python3 installer/blun_language_guard.py doctor
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
Linux systemd units and macOS LaunchAgent definitions are installed through a protected atomic boundary before either service manager is called. Existing definitions must be bounded single-link regular files owned by the current user and not writable by another account; symbolic links, hard links, special files, and concurrent replacements block without altering their targets or activating a service. The installer also traverses every service-directory component below the user home without following links, rejects directories writable by another account, and creates and replaces definitions relative to a held directory handle. A concurrently exchanged parent therefore cannot redirect the write or activate a detached definition. Newly written definitions use owner-only permissions. Resetting updater, health-monitor, or MCP autostart keeps the same protected directory handle from marker preflight through identity-checked removal, so linked, broadly writable, or exchanged parents cannot redirect the cleanup. The definition itself must still pass no-follow and stable-identity checks and contain service-specific BLUN markers. Windows Task Scheduler behavior is unchanged.
|
|
906
|
+
|
|
907
|
+
Use `service start` or `service stop` for explicit lifecycle control. `install --no-service-autostart` exists for packaging and tests, but a production host must not deliver model output in that state. A per-user service prevents accidental key exposure to child processes; resisting a hostile same-user agent still requires a separate service account, container, or remote signer with filesystem and channel credentials denied to the agent.
|
|
908
|
+
|
|
909
|
+
Two host adapters are included:
|
|
910
|
+
|
|
911
|
+
- [`node-language-guard.js`](integrations/adapters/node-language-guard.js) provides strict routing, envelope parsing, isolated verification, and verify-before-send Telegram delivery for Node.js hosts.
|
|
912
|
+
- [`blun-code-language-guard.js`](integrations/adapters/blun-code-language-guard.js) migrates the installed BLUN MCP entry into BLUN Code's encrypted MCP store, buffers model text so an unsigned draft cannot leak through streaming, and releases only the verified target.
|
|
913
|
+
|
|
914
|
+
The legacy BLUN MCP file is a security-relevant migration input because it selects the isolated endpoint and service-token path. Installer and BLUN Code therefore accept only a bounded, single-link regular `~/.blun/mcp.json` owned by the current user and not writable by another account. Both consumers open without following links where supported and verify stable identity across the complete read. The installer preserves unrelated servers, writes its backup and replacement atomically as owner-only files, and rechecks the original immediately before replacement. A symbolic link, hard link, special file, oversized or malformed document, unsafe permissions, or exchange race blocks before the encrypted store or configuration is changed; existing safe `0644` files remain compatible.
|
|
915
|
+
|
|
916
|
+
Claude's user-scoped `~/.claude.json` now follows the same protected migration boundary. Installation preflights the bounded owner-controlled single-link file before changing any skill or runtime, then preserves unrelated settings while atomically writing an owner-only backup and replacement. The final replacement rechecks the exact file identity, so links, special files, unsafe write permissions, excessive size, malformed JSON, and concurrent exchange all block without overwriting the substituted target or losing a concurrent Claude change. `doctor` uses the same protected reader, while existing safe `0644` configurations remain compatible.
|
|
917
|
+
|
|
918
|
+
The trusted router uses structured job metadata, never the agent's claim. A source-bearing or explicitly translated job takes `release_translation`; an ordinary reply takes `release_response`. Contradictory metadata, `auto`, `all`, missing translation source, raw prose, unknown envelope fields, an invalid receipt, an unavailable service, or a sender invocation before verification all block.
|
|
919
|
+
|
|
920
|
+
Free-form text alone cannot provide non-bypassable task classification. A host that offers translation through chat must set `languageGuardTaskKind: translation`, capture the complete source independently as `languageGuardSourceText`, and set the exact target language. If that metadata is absent, the BLUN adapter instructs the agent not to perform a translation through the response route. See [`BLUN_CODE_INTEGRATION.md`](docs/BLUN_CODE_INTEGRATION.md) for the runtime contract and residual limits.
|
|
921
|
+
|
|
922
|
+
## Version 5: BLUN Language Gateway
|
|
923
|
+
|
|
924
|
+
Version 5 makes the host—not the agent—the final authority. Skills and MCP tools can be forgotten or skipped. A mandatory gateway intercepts the candidate output and releases it only after validation produces a signed receipt for the exact source, target, and locale.
|
|
925
|
+
|
|
926
|
+
```text
|
|
927
|
+
User → Agent → intercepted candidate → BLUN Language Gateway
|
|
928
|
+
├── PASS + receipt → release
|
|
929
|
+
└── BLOCK → revise or stop
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
Use the portable gateway with JSON on stdin:
|
|
933
|
+
|
|
934
|
+
```bash
|
|
935
|
+
python3 integrations/language_gateway.py < release-request.json
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
Strong enforcement requires the gateway and signing key to run outside the agent's writable sandbox, ideally as a separate OS user, container, or remote service. If the agent can replace the gateway or read its key, the installation is advisory—not non-bypassable. CLI adapters must capture final output before it is printed; API gateways must withhold the HTTP response; CI must require the check before merge and deployment.
|
|
939
|
+
|
|
940
|
+
### Automatic safe updates
|
|
941
|
+
|
|
942
|
+
Enable the operating-system scheduler once:
|
|
943
|
+
|
|
944
|
+
```bash
|
|
945
|
+
python3 installer/blun_language_guard.py auto-update enable --interval-hours 24
|
|
946
|
+
python3 installer/blun_language_guard.py auto-update status
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
Linux uses a user-level systemd timer, macOS a LaunchAgent, and Windows Task Scheduler. Each scheduled wake-up checks whether the configured interval is due. A candidate checkout is tested before installation, the update is fast-forward-only, post-update tests run again, and the previous revision is retained for rollback. When Claude is installed, an update also installs or refreshes the persistent HTTP MCP, its dynamic-header helper, its autostart service, and the user-scoped Claude entry before marking the runtime update successful. If activation fails, cleanup is bound to the exact post-install identity of each MCP command, bearer token, and Claude configuration. A path that appeared or changed concurrently is preserved and makes rollback report failure instead of deleting operator-owned state; an existing Claude configuration is restored through an unpredictable atomic temporary file. The repository reset is likewise bound to the exact clean candidate revision: parallel edits or a new commit block reset, cleanup, and secondary restarts without moving the changed checkout. Security-sensitive deployments can require trusted Git commit signatures:
|
|
950
|
+
|
|
951
|
+
```bash
|
|
952
|
+
python3 installer/blun_language_guard.py auto-update enable --require-signed-commits
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
Version 6.6 also coordinates Claude's plugin cache. When automatic updates are enabled, the owner-visible Claude executable path is recorded so an OS scheduler with a smaller `PATH` invokes the same CLI. If `translate-native@blun-language-tools` is already installed at user scope, the updater refreshes its marketplace, requires the catalog version to equal the tested runtime, runs Claude's official non-interactive `plugin update` command, and verifies the exact installed version through `plugin list --json`. A missing plugin is never installed without consent. A plugin or marketplace failure leaves the already-tested runtime and fail-closed MCP active, records a `degraded` updater state, returns nonzero, and retries on the next scheduled wake-up instead of waiting for the normal interval. Version 6.7 uses the same degraded retry path for a health-monitor installation failure and shares an operation lock between updates and repairs. Version 6.8 enrolls an observed installed cache in the one-minute monitor, so disabling it, load errors, or later version drift can no longer leave the services green while the mandatory hooks are unhealthy. A successful cache update still requires `/reload-plugins` or a new Claude session because active sessions retain their previously loaded hook paths.
|
|
956
|
+
|
|
957
|
+
To return to the exact revision saved by the last update, synchronize an installed Claude plugin to that target version first, make sure the checkout is clean, and run:
|
|
958
|
+
|
|
959
|
+
```bash
|
|
960
|
+
python3 installer/blun_language_guard.py rollback
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
Use `--require-signed-commits` to require a trusted signature even when the saved updater policy did not. The command never selects an arbitrary revision, never downgrades a plugin through undocumented cache manipulation, and never overwrites local changes. A successful rollback pauses scheduled updates; inspect the result, then run an explicit `update` followed by `auto-update enable` when you intentionally want to resume the forward line.
|
|
964
|
+
|
|
965
|
+
The authoritative plugin version lives only in `.claude-plugin/plugin.json`; the marketplace entry deliberately omits a duplicate version field. Claude uses the manifest version as its cache key, avoiding two version declarations that can drift apart.
|
|
966
|
+
|
|
967
|
+
Third-party marketplace auto-update is disabled by default in Claude. Users may enable it in the marketplace UI as an additional startup check; the operating-system updater no longer depends on that optional setting. Other platform-native plugin stores remain controlled by their host platform.
|
|
968
|
+
|
|
969
|
+
BLUN Code is supported explicitly. Installation creates the BLUN skill symlink and safely merges `blun-language-guard` into the protected `~/.blun/mcp.json`, preserving the other MCP servers and writing `mcp.json.bak` atomically before a change. BLUN Code must be restarted once after initial installation; subsequent repository updates are visible through the symlink automatically.
|
|
970
|
+
|
|
971
|
+
### Production regressions fixed in Version 5
|
|
972
|
+
|
|
973
|
+
- Page-sized releases are covered by a regression test above 7,000 characters with a one-second local execution budget.
|
|
974
|
+
- MCP JSON input accepts the UTF-8 BOM frequently emitted by Windows tooling.
|
|
975
|
+
- Long Swedish, German, Spanish, Czech, and Catalan targets receive a language-character profile check that catches wholesale ASCII folding even when no word appears in a small substitution list.
|
|
976
|
+
- The Swedish BLUN ASCII-folding regression was found by **Angel** and is retained under her name in the permanent evaluation corpus.
|
|
977
|
+
|
|
978
|
+
### Version 5.1: short copy and transport-safe identity
|
|
979
|
+
|
|
980
|
+
Titles, meta descriptions, and UI strings below 200 characters never receive a deterministic `PASS` from character profiles or substitution lists. The gate always returns `REVIEW_REQUIRED` until an independent native review sets `short_text_reviewed: true`; that decision, together with `content_type`, is cryptographically bound into the receipt. This remains true even when the short text still contains some native characters, preventing one surviving `å`, `ä`, or `ö` from hiding another destroyed word.
|
|
981
|
+
|
|
982
|
+
Text identity now distinguishes transport differences from corruption. Canonical hashes remove a leading UTF-8 BOM, normalize CRLF and lone CR to LF, and normalize Unicode to NFC. Mojibake and actual character changes remain different and invalidate the receipt.
|
|
983
|
+
|
|
984
|
+
Both portable commands are now present inside the installable skill as well as the repository integration layer:
|
|
985
|
+
|
|
986
|
+
- `translate-native/scripts/language_gateway.py`
|
|
987
|
+
- `translate-native/scripts/pre_output_guard.py`
|
|
988
|
+
|
|
989
|
+
Symlink installations receive these files with the next automatic update; no manual copying is required.
|
|
990
|
+
|
|
991
|
+
### Version 5.2: measurable evidence beats self-attestation
|
|
992
|
+
|
|
993
|
+
Version 5.1 correctly raised a short-copy gate but incorrectly allowed the same caller to declare both `content_type` and `short_text_reviewed`. Those values are not independent evidence and are no longer a security boundary.
|
|
994
|
+
|
|
995
|
+
Version 5.2 measures conventional ASCII-folding pressure for German, Swedish, Danish, and Norwegian on every target, regardless of length or declared content type. Measurable folding findings cannot be overridden by `short_text_reviewed: true` or `content_type: prose`.
|
|
996
|
+
|
|
997
|
+
Version 5.2.1 removes German `ss` from that measurement. Unlike `ae`, `oe`, and `ue`, `ss` is frequently correct native spelling (`wissen`, `dass`, `interessiert`) and cannot be classified as a `ß` replacement without lexical and locale context. The guard deliberately leaves cases such as `Grösse` to a future `de-DE`/`de-AT`/`de-CH` dictionary-aware check instead of creating a broad false positive.
|
|
998
|
+
|
|
999
|
+
### Version 5.3: quantity is part of integrity
|
|
1000
|
+
|
|
1001
|
+
`translation_guard.py` now measures linguistic volume in addition to tags and protected tokens. It compares total Unicode letter/number volume, non-empty linguistic segment counts, and aligned segment coverage for text, JSON/ARB, HTML, XML/XLIFF/Android resources, PO, Apple strings, and subtitles. Script-aware thresholds allow naturally compact CJK translations while blocking major omissions such as a 64-unit target derived from a 224-unit source.
|
|
1002
|
+
|
|
1003
|
+
A successful deterministic guard now says exactly what it proves: measurable structure, protected tokens, linguistic volume, and Unicode integrity. It explicitly does **not** prove semantic fidelity, true completeness, or native quality. A literal translation can have the right length and still fail the native-language gate.
|
|
1004
|
+
|
|
1005
|
+
Version 5.3.1 also makes the volume check unconditional inside the mandatory MCP `release_translation` path. Format detection is derived from the source syntax rather than a caller-supplied checkbox, so truthful-looking attestations cannot release a measurably truncated target. Structured CLI validation remains required for exact tag, key, placeholder, and technical-value integrity.
|
|
1006
|
+
|
|
1007
|
+
Version 5.3.2 makes every MCP dependency resolve relative to the installed script itself. The server no longer assumes the repository's `translate-native/scripts` directory layout, and an isolated-install regression test starts the copied server from the exact flat `scripts/` layout used by installed skills.
|
|
1008
|
+
|
|
1009
|
+
Version 5.3.3 blocks substantial unchanged targets. When source and target remain identical after transport-only BOM, newline, surrounding-whitespace, and NFC normalization, a source of at least 200 characters fails both the CLI and mandatory MCP release with `source-target-identical`. Short shared terms such as `BLUN King` and `E-Mail` remain valid. The comparison covers the complete input—not only `<main>` or another convenient content subtree.
|
|
1010
|
+
|
|
1011
|
+
Version 5.3.4 closes the structured-file segment gap. Human-language values in JSON/ARB, HTML, XML/XLIFF/Android resources, PO, Apple strings, subtitles, and plain text are compared independently. An unchanged segment of at least 24 linguistic units now fails the CLI and mandatory MCP release, even when every other value was translated. JSON keys are aligned independently of property order; other structured formats use cross-target segment identity, so swapping two unchanged HTML or XML values cannot bypass the gate. Copyright and rights notices receive no automatic fixed-content exemption: an unchanged copyright-marked segment is blocked even below the normal segment threshold. Short product names such as `BLUN King` remain valid. A legitimate fixed legal line requires explicit human handling outside the automatic release gate; it is never silently passed.
|
|
1012
|
+
|
|
1013
|
+
Read the diagnostic text, not only the exit code. A blocked identity comparison must explicitly report `target is unchanged` or `linguistic segment is unchanged`; JSON findings name the exact path such as `$.hinweis`. The structural translation guard reserves exit code `1` for evaluated content that was blocked and returns `2` when an input file cannot be read. A missing path reports `cannot read file` and is not evidence that the identity detector fired. Tests assert both the expected result and the expected reason.
|
|
1014
|
+
|
|
1015
|
+
Other scripts cannot always be reconstructed from stripped ASCII without a dictionary or native model. The guard reports only what it can measure and never claims that this heuristic proves correct spelling. Strong independence still requires the external Language Gateway and reviewer to run outside the releasing agent's authority.
|
|
1016
|
+
|
|
1017
|
+
## Version 4 foundation: signed release receipts
|
|
1018
|
+
|
|
1019
|
+
Version 4 turns the executable MCP gate into a signed, independently verifiable release system. The skill remains responsible for meaning, native rewriting, locale fit, and orthography. The server blocks deterministic defects and issues a cryptographic receipt bound to the exact source, target, locale, version, issue time, and expiry.
|
|
1020
|
+
|
|
1021
|
+
```text
|
|
1022
|
+
Translation request
|
|
1023
|
+
↓
|
|
1024
|
+
translate-native skill
|
|
1025
|
+
↓
|
|
1026
|
+
Native pass → fidelity pass → integrity pass
|
|
1027
|
+
↓
|
|
1028
|
+
release_translation MCP tool
|
|
1029
|
+
↓
|
|
1030
|
+
BLOCK → revise and repeat
|
|
1031
|
+
PASS → signed receipt → verify receipt → deliver
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
The gate checks UTF-8/Unicode integrity, NFC normalization, script identity, balanced bidirectional isolates, dangerous overrides, frequent ASCII substitutions, optional terminology glossaries, and all seven mandatory attestations. Edited, expired, forged, wrong-locale, or wrong-version receipts fail verification.
|
|
1035
|
+
|
|
1036
|
+
### Install, update, and diagnose
|
|
1037
|
+
|
|
1038
|
+
```bash
|
|
1039
|
+
python3 installer/blun_language_guard.py install
|
|
1040
|
+
python3 installer/blun_language_guard.py doctor
|
|
1041
|
+
python3 installer/blun_language_guard.py update
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
Installation uses atomic symlinks for Codex and Claude Code and refuses to overwrite existing non-symlink skill folders. Each update reserves an unpredictable staging symlink exclusively, preserves legacy and colliding staging paths, rechecks the destination identity immediately before cutover, and cleans up only its own staging link. It installs `~/.local/bin/blun-language-deliver`, the isolated service command, owner-only key and service-token files, autostart configuration, a content-free audit path, and a fail-closed policy; writes a mergeable MCP snippet without overwriting unrelated host configuration; and merges the BLUN MCP entry safely. Updates are cloned and tested before the active checkout is fast-forwarded, then the service is restarted and health-checked; a failed restart rolls the checkout back. `doctor` checks the delivery command, service health, secret permissions, mandatory policy, test suite, live MCP tools, signed receipts, and updater heartbeat.
|
|
1045
|
+
|
|
1046
|
+
The portable fail-closed hook is [`pre_output_guard.py`](integrations/pre_output_guard.py). It accepts `task_kind`, target, locale, receipt, and the complete source for translations as JSON on stdin and exits nonzero when verification fails. It only reads an existing owner-only verification key and never creates or repairs signing state. Host-specific adapters must pass the candidate output into this contract; a host hook that exposes no candidate text cannot enforce output validation.
|
|
1047
|
+
|
|
1048
|
+
### Supported structured formats
|
|
1049
|
+
|
|
1050
|
+
- JSON and ARB;
|
|
1051
|
+
- HTML including linguistic metadata and JSON-LD linguistic fields while protecting schema, URLs, types, code, and placeholders;
|
|
1052
|
+
- XML, Android resources, and structurally equivalent XLIFF documents;
|
|
1053
|
+
- PO/POT catalogs;
|
|
1054
|
+
- Apple `.strings`;
|
|
1055
|
+
- SRT, VTT, and ASS subtitle timing;
|
|
1056
|
+
- ICU placeholders and plural/select contracts inside supported containers.
|
|
1057
|
+
|
|
1058
|
+
See [`PREMORTEM.md`](docs/PREMORTEM.md) for the failure modes, mitigations, and proof required before calling this system production-ready.
|
|
1059
|
+
|
|
1060
|
+
No deterministic linter can prove that prose is genuinely native. That is why the MCP server supplements the skill's native-language judgment instead of pretending to replace it.
|
|
1061
|
+
|
|
1062
|
+
### Start the MCP server
|
|
1063
|
+
|
|
1064
|
+
For Claude Code, use the persistent runtime shown in Version 6.3 together with the current Version 6.64.0 plugin. The HTTP MCP remains available in every project through user scope, while the plugin adds the mandatory lifecycle hooks and the operating-system monitor repairs its service path and enrolled plugin cache. Check the runtime at any time with:
|
|
1065
|
+
|
|
1066
|
+
```bash
|
|
1067
|
+
python3 installer/blun_language_guard.py mcp-service status
|
|
1068
|
+
claude mcp get blun-language-guard
|
|
1069
|
+
```
|
|
1070
|
+
|
|
1071
|
+
For other clients, the zero-dependency `stdio` transport remains available as a compatibility fallback:
|
|
1072
|
+
|
|
1073
|
+
```bash
|
|
1074
|
+
python3 translate-native/scripts/blun_language_guard.py serve
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
Copy [`mcp-config.example.json`](mcp-server/mcp-config.example.json), replace the absolute path, and merge the `blun-language-guard` entry into the MCP configuration used by that agent CLI. Do not use the `stdio` fallback for Claude after installing Version 6.3; a higher-precedence project or local entry with the same name can shadow the persistent user server.
|
|
1078
|
+
|
|
1079
|
+
Then copy the rules in [`AGENT_RULES.md`](integrations/AGENT_RULES.md) into the host's always-on instruction file:
|
|
1080
|
+
|
|
1081
|
+
- Codex: repository or global `AGENTS.md`;
|
|
1082
|
+
- Claude Code: `CLAUDE.md`;
|
|
1083
|
+
- another MCP-compatible agent: its equivalent persistent instruction file.
|
|
1084
|
+
|
|
1085
|
+
This combination matters. A skill can fail to trigger, and an MCP tool can remain unused. The persistent rule requires `release_response` for ordinary answers and both the `translate-native` workflow and `release_translation` for translations. The trusted host gateway remains the final enforcement boundary.
|
|
1086
|
+
|
|
1087
|
+
### Validate from the terminal
|
|
1088
|
+
|
|
1089
|
+
The same engine can be used in hooks, CI, wrappers, or pre-publication scripts:
|
|
1090
|
+
|
|
1091
|
+
```bash
|
|
1092
|
+
python3 translate-native/scripts/blun_language_guard.py validate --language sv-SE target.txt
|
|
1093
|
+
```
|
|
1094
|
+
|
|
1095
|
+
Exit code `0` means the deterministic checks passed. Exit code `1` means delivery must stop. Semantic and native-quality review remains mandatory even after exit code `0`.
|
|
1096
|
+
|
|
1097
|
+
## Native examples
|
|
1098
|
+
|
|
1099
|
+
| Target | Native result |
|
|
1100
|
+
| --- | --- |
|
|
1101
|
+
| Swedish | `Om du redan har betalat behöver du inte göra något mer.` |
|
|
1102
|
+
| Simplified Chinese | `你确认前,我们不会分享任何内容。` |
|
|
1103
|
+
| Catalan | `No es compartirà res fins que ho confirmis.` |
|
|
1104
|
+
| Basque | `Dagoeneko ordaindu baduzu, ez duzu beste ezer egin behar.` |
|
|
1105
|
+
| Czech | `Pokud jste již zaplatili, nemusíte nic dalšího dělat.` |
|
|
1106
|
+
| Spanish | `Si ya has pagado, no tienes que hacer nada más.` |
|
|
1107
|
+
|
|
1108
|
+
These are examples, not the boundary of the skill.
|
|
1109
|
+
|
|
1110
|
+
## Grammatical is not native
|
|
1111
|
+
|
|
1112
|
+
The skill now explicitly rejects agent-written copy that is grammatically correct but still sounds translated. Agents must inspect collocations, parallel structure, paragraph flow, register, unnecessary source-language borrowings, and vague AI filler—not just spelling and syntax.
|
|
1113
|
+
|
|
1114
|
+
The Swedish BLUN regression case captures the difference:
|
|
1115
|
+
|
|
1116
|
+
| Agent wording | Native review |
|
|
1117
|
+
| --- | --- |
|
|
1118
|
+
| `desktop- och mobilprogramvara` | `programvara för datorer och mobila enheter` |
|
|
1119
|
+
| `fördela uppgiften på ett smart sätt` | `fördela arbetet mellan de modeller som passar bäst för uppgiften` |
|
|
1120
|
+
| `fördela uppgiften till den modell som passar bäst` | `automatiskt välja den modell som passar bäst för uppgiften` |
|
|
1121
|
+
|
|
1122
|
+
All three agent formulations are understandable. They still fail because a native editor would recast them for publication. The complete candidates, defect analyses, native rewrites, and language-independent review procedure live in [`translationese-review.md`](translate-native/references/translationese-review.md).
|
|
1123
|
+
|
|
1124
|
+
## The translation contract
|
|
1125
|
+
|
|
1126
|
+
Every result passes seven gates:
|
|
1127
|
+
|
|
1128
|
+
1. **Meaning** — claims, relationships, conditions, and implications remain equivalent.
|
|
1129
|
+
2. **Completeness** — nothing is lost, duplicated, or invented.
|
|
1130
|
+
3. **Precision** — negation, modality, quantities, entities, and terminology remain exact.
|
|
1131
|
+
4. **Nativeness** — calques, source syntax, and translationese are removed.
|
|
1132
|
+
5. **Fit** — locale, script, register, audience, tone, and medium are right.
|
|
1133
|
+
6. **Integrity** — placeholders, keys, links, markup, code, and structure survive intact.
|
|
1134
|
+
7. **Orthography** — spelling, diacritics, punctuation, spacing, and Unicode are native.
|
|
1135
|
+
|
|
1136
|
+
Version 2 deliberately separates judgment into two passes: a target-only native edit that cannot lean on the source wording, followed by a source-aware fidelity audit that accounts for every claim and constraint. Publication-grade, long-form, and uncertain work can be routed through an independent defect review before release.
|
|
1137
|
+
|
|
1138
|
+
## i18n without i18n language
|
|
1139
|
+
|
|
1140
|
+
JSON, YAML, XML, PO, ARB, ICU MessageFormat, Android resources, Apple strings, Markdown, and HTML are containers. They do not excuse robotic prose.
|
|
1141
|
+
|
|
1142
|
+
```json
|
|
1143
|
+
{
|
|
1144
|
+
"welcome": "Ongi etorri, {name}!",
|
|
1145
|
+
"upload": "Kargatu {{count}} fitxategi <strong>{project}</strong> proiektura.",
|
|
1146
|
+
"help": "Informazio gehiago: https://example.com/help"
|
|
1147
|
+
}
|
|
1148
|
+
```
|
|
1149
|
+
|
|
1150
|
+
The key structure stays fixed. The Basque values read naturally. Every placeholder, URL, and HTML tag remains protected.
|
|
1151
|
+
|
|
1152
|
+
## Install
|
|
1153
|
+
|
|
1154
|
+
Clone the repository:
|
|
1155
|
+
|
|
1156
|
+
```bash
|
|
1157
|
+
git clone https://github.com/Maykbiletti/translate-native.git
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
Copy the `translate-native` directory into the skill directory used by your compatible agent platform, or load its [`SKILL.md`](translate-native/SKILL.md) according to that platform's skill instructions.
|
|
1161
|
+
|
|
1162
|
+
Invoke it explicitly:
|
|
1163
|
+
|
|
1164
|
+
```text
|
|
1165
|
+
$translate-native
|
|
1166
|
+
```
|
|
1167
|
+
|
|
1168
|
+
Direct skill address:
|
|
1169
|
+
|
|
1170
|
+
```text
|
|
1171
|
+
https://github.com/Maykbiletti/translate-native/tree/main/translate-native
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
## Connect a website-localization provider
|
|
1175
|
+
|
|
1176
|
+
The production-oriented website pipeline plans one job per locale, processes
|
|
1177
|
+
each through separate transcreation, source-blind native review, and
|
|
1178
|
+
source-aware fidelity review stages, and remains vendor-neutral. A host can now
|
|
1179
|
+
connect its own LLM or model gateway through the bundled request-bound HTTP
|
|
1180
|
+
adapter. The public protocol, authentication boundary, idempotency rules,
|
|
1181
|
+
response schemas, and fail-closed behavior are documented in
|
|
1182
|
+
[`docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md`](docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md).
|
|
1183
|
+
|
|
1184
|
+
The same pipeline can connect its independent quality-evidence service through
|
|
1185
|
+
the separate request-bound HTTPS adapter documented in
|
|
1186
|
+
[`docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md`](docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md).
|
|
1187
|
+
It sends exactly one complete source/candidate pair for one leased locale,
|
|
1188
|
+
binds request and worker-result hashes end to end, and leaves all retries to the
|
|
1189
|
+
durable evidence queue.
|
|
1190
|
+
|
|
1191
|
+
The adapter is public and contains no fixed provider, brand, product, price, or
|
|
1192
|
+
credential. Passing transport tests does not establish native-language quality
|
|
1193
|
+
or superiority over another translation system; those claims require the
|
|
1194
|
+
separate review and blinded benchmark evidence described in
|
|
1195
|
+
[`docs/WEBSITE_LOCALIZATION.md`](docs/WEBSITE_LOCALIZATION.md).
|
|
1196
|
+
|
|
1197
|
+
## Protect machine-readable content
|
|
1198
|
+
|
|
1199
|
+
The zero-dependency guard compares source and target files:
|
|
1200
|
+
|
|
1201
|
+
```bash
|
|
1202
|
+
python3 translate-native/scripts/translation_guard.py source.md target.md
|
|
1203
|
+
python3 translate-native/scripts/translation_guard.py source.json target.json --format json
|
|
1204
|
+
python3 translate-native/scripts/translation_guard.py source.html target.html --format html
|
|
1205
|
+
python3 translate-native/scripts/check_diacritics.py --language sv target.md
|
|
1206
|
+
```
|
|
1207
|
+
|
|
1208
|
+
It blocks delivery when it detects:
|
|
1209
|
+
|
|
1210
|
+
- missing, added, or renamed placeholders;
|
|
1211
|
+
- changed URLs, email addresses, code, HTML tags, escapes, or format tokens;
|
|
1212
|
+
- changed JSON keys, hierarchy, arrays, scalar types, or non-string values;
|
|
1213
|
+
- changed ICU argument names, formatters, selectors, or number signs;
|
|
1214
|
+
- changed HTML structure, technical attributes, comments, scripts, or styles while still allowing native translation of linguistic accessibility attributes;
|
|
1215
|
+
- target text that is not valid UTF-8 and Unicode NFC.
|
|
1216
|
+
|
|
1217
|
+
The guard protects structure. The agent's seven-pass review protects meaning and native quality.
|
|
1218
|
+
|
|
1219
|
+
The diacritics linter additionally catches frequent ASCII substitutions such as `schoen`, `forstar`, `informacion`, and `cestina` while leaving code, URLs, and other protected technical spans alone. It is a deterministic warning system, not a finite definition of any language; the built-in orthography gate remains mandatory for every script worldwide.
|
|
1220
|
+
|
|
1221
|
+
Language tags without a deterministic substitution list, such as `en`, are accepted. The linter still checks UTF-8 and Unicode NFC, prints that no language-specific diacritics rules apply, and leaves the mandatory native-orthography review in force.
|
|
1222
|
+
|
|
1223
|
+
For complete HTML pages, linguistic metadata may change: descriptions, keywords, application names, Open Graph titles/descriptions, and Twitter titles/descriptions are treated as translatable text while their placeholders remain protected. Technical metadata such as viewport settings, encodings, URLs, and unrelated `content` attributes remain fixed.
|
|
1224
|
+
|
|
1225
|
+
## Evidence, not dataset worship
|
|
1226
|
+
|
|
1227
|
+
| Source | Best use | Warning |
|
|
1228
|
+
| --- | --- | --- |
|
|
1229
|
+
| [Language communities and authorities](translate-native/references/native-translation-standard.md) | Orthography, terminology, accepted standard | Prefer the requested community's own convention |
|
|
1230
|
+
| [Unicode CLDR](https://cldr.unicode.org/) | Locale IDs, formats, plurals, exemplar characters | Locale data is not prose guidance |
|
|
1231
|
+
| [Unicode Normalization](https://unicode.org/reports/tr15/) | Canonical Unicode normalization | NFC does not prove correct spelling |
|
|
1232
|
+
| [W3C Language Enablement](https://www.w3.org/International/typography/gap-analysis/language-matrix.html) | Script layout and typography | Web support data is not a dictionary |
|
|
1233
|
+
| [IANA Language Subtag Registry](https://www.iana.org/assignments/language-subtag-registry) | Language, script, and region tags | Tags identify a target; they do not translate it |
|
|
1234
|
+
| [Leipzig Corpora Collection](https://cls.corpora.uni-leipzig.de/) | Native usage and collocations | Check domain and date |
|
|
1235
|
+
| [FLORES+](https://huggingface.co/datasets/openlanguagedata/flores_plus) | Multilingual evaluation | It is an evaluation set, not training data |
|
|
1236
|
+
| [OPUS](https://opus.nlpl.eu/) | Supporting parallel examples | Large corpora can contain literal or noisy translations |
|
|
1237
|
+
|
|
1238
|
+
Hugging Face is a useful distribution platform, not a quality certificate. Provenance, curation, locale, license, domain, and intended use still matter.
|
|
1239
|
+
|
|
1240
|
+
## Repository structure
|
|
1241
|
+
|
|
1242
|
+
```text
|
|
1243
|
+
translate-native/
|
|
1244
|
+
├── SKILL.md
|
|
1245
|
+
├── agents/
|
|
1246
|
+
│ └── openai.yaml
|
|
1247
|
+
├── assets/
|
|
1248
|
+
│ └── icon.svg
|
|
1249
|
+
├── references/
|
|
1250
|
+
│ ├── native-translation-standard.md
|
|
1251
|
+
│ ├── native-orthography.md
|
|
1252
|
+
│ ├── evaluation-protocol.md
|
|
1253
|
+
│ ├── translationese-review.md
|
|
1254
|
+
│ └── structured-content.md
|
|
1255
|
+
└── scripts/
|
|
1256
|
+
├── translation_guard.py
|
|
1257
|
+
├── check_diacritics.py
|
|
1258
|
+
└── blun_language_guard.py
|
|
1259
|
+
```
|
|
1260
|
+
|
|
1261
|
+
The MCP configuration example, persistent CLI rules, automated tests, and GitHub Actions workflow live at repository level.
|
|
1262
|
+
|
|
1263
|
+
Machine-readable failure cases live in [`evals/regressions.jsonl`](evals/regressions.jsonl). They cover Swedish translationese and model selection, German umlauts, Spanish punctuation and accents, Czech and Catalan orthography, Vietnamese tone marks, Chinese and Arabic native scripts, and Ukrainian language identity. They are regression examples, never a language allowlist.
|
|
1264
|
+
|
|
1265
|
+
## Test
|
|
1266
|
+
|
|
1267
|
+
```bash
|
|
1268
|
+
python3 -m unittest discover -s tests -v
|
|
1269
|
+
```
|
|
1270
|
+
|
|
1271
|
+
The suite covers protected text, sentence punctuation after URLs, JSON structure and types, ICU plural/select syntax, safely translatable HTML attributes, HTML/code tampering, Unicode normalization, common missing diacritics in German, Spanish, and Czech, technical-span protection, the combined language-and-orthography contract, repository agent instructions, and both Swedish agent-copy regression cases.
|
|
1272
|
+
|
|
1273
|
+
## Design principle
|
|
1274
|
+
|
|
1275
|
+
Translation is not token replacement. It is constrained re-authorship: the same meaning, rebuilt inside another language's own system.
|
|
1276
|
+
|
|
1277
|
+
That standard is universal. Confidence is not.
|
|
1278
|
+
|
|
1279
|
+
## License
|
|
1280
|
+
|
|
1281
|
+
Released under the [MIT License](LICENSE).
|
|
1282
|
+
|
|
1283
|
+
---
|
|
1284
|
+
|
|
1285
|
+
<div align="center">
|
|
1286
|
+
|
|
1287
|
+
### Built for every language that people call home.
|
|
1288
|
+
|
|
1289
|
+
**BLUN**
|
|
1290
|
+
|
|
1291
|
+
*Get it done with BLUN.*
|
|
1292
|
+
|
|
1293
|
+
</div>
|