@aimarket/warden 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README-es.md +27 -11
  3. package/README-fr.md +27 -11
  4. package/README-ru.md +27 -11
  5. package/README-zh.md +27 -11
  6. package/README.md +27 -11
  7. package/dist/annotation-review.d.ts +10 -0
  8. package/dist/annotation-review.d.ts.map +1 -0
  9. package/dist/annotation-review.js +36 -0
  10. package/dist/annotation-review.js.map +1 -0
  11. package/dist/atomic-screen.d.ts +61 -0
  12. package/dist/atomic-screen.d.ts.map +1 -0
  13. package/dist/atomic-screen.js +165 -0
  14. package/dist/atomic-screen.js.map +1 -0
  15. package/dist/flow-guard-answer.d.ts +29 -0
  16. package/dist/flow-guard-answer.d.ts.map +1 -0
  17. package/dist/flow-guard-answer.js +201 -0
  18. package/dist/flow-guard-answer.js.map +1 -0
  19. package/dist/flow-guard-classify.d.ts +14 -0
  20. package/dist/flow-guard-classify.d.ts.map +1 -0
  21. package/dist/flow-guard-classify.js +224 -0
  22. package/dist/flow-guard-classify.js.map +1 -0
  23. package/dist/flow-guard-decode.d.ts +17 -0
  24. package/dist/flow-guard-decode.d.ts.map +1 -0
  25. package/dist/flow-guard-decode.js +149 -0
  26. package/dist/flow-guard-decode.js.map +1 -0
  27. package/dist/flow-guard-destinations.d.ts +23 -0
  28. package/dist/flow-guard-destinations.d.ts.map +1 -0
  29. package/dist/flow-guard-destinations.js +158 -0
  30. package/dist/flow-guard-destinations.js.map +1 -0
  31. package/dist/flow-guard-fingerprints.d.ts +27 -0
  32. package/dist/flow-guard-fingerprints.d.ts.map +1 -0
  33. package/dist/flow-guard-fingerprints.js +164 -0
  34. package/dist/flow-guard-fingerprints.js.map +1 -0
  35. package/dist/flow-guard-fragments.d.ts +17 -0
  36. package/dist/flow-guard-fragments.d.ts.map +1 -0
  37. package/dist/flow-guard-fragments.js +122 -0
  38. package/dist/flow-guard-fragments.js.map +1 -0
  39. package/dist/flow-guard-instructions.d.ts +12 -0
  40. package/dist/flow-guard-instructions.d.ts.map +1 -0
  41. package/dist/flow-guard-instructions.js +36 -0
  42. package/dist/flow-guard-instructions.js.map +1 -0
  43. package/dist/flow-guard-labels.d.ts +10 -0
  44. package/dist/flow-guard-labels.d.ts.map +1 -0
  45. package/dist/flow-guard-labels.js +55 -0
  46. package/dist/flow-guard-labels.js.map +1 -0
  47. package/dist/flow-guard-leak.d.ts +29 -0
  48. package/dist/flow-guard-leak.d.ts.map +1 -0
  49. package/dist/flow-guard-leak.js +135 -0
  50. package/dist/flow-guard-leak.js.map +1 -0
  51. package/dist/flow-guard-paths.d.ts +21 -0
  52. package/dist/flow-guard-paths.d.ts.map +1 -0
  53. package/dist/flow-guard-paths.js +72 -0
  54. package/dist/flow-guard-paths.js.map +1 -0
  55. package/dist/flow-guard-policy.d.ts +15 -0
  56. package/dist/flow-guard-policy.d.ts.map +1 -0
  57. package/dist/flow-guard-policy.js +179 -0
  58. package/dist/flow-guard-policy.js.map +1 -0
  59. package/dist/flow-guard-post.d.ts +6 -0
  60. package/dist/flow-guard-post.d.ts.map +1 -0
  61. package/dist/flow-guard-post.js +131 -0
  62. package/dist/flow-guard-post.js.map +1 -0
  63. package/dist/flow-guard-pre.d.ts +13 -0
  64. package/dist/flow-guard-pre.d.ts.map +1 -0
  65. package/dist/flow-guard-pre.js +335 -0
  66. package/dist/flow-guard-pre.js.map +1 -0
  67. package/dist/flow-guard-screen.d.ts +85 -0
  68. package/dist/flow-guard-screen.d.ts.map +1 -0
  69. package/dist/flow-guard-screen.js +558 -0
  70. package/dist/flow-guard-screen.js.map +1 -0
  71. package/dist/flow-guard-state.d.ts +12 -0
  72. package/dist/flow-guard-state.d.ts.map +1 -0
  73. package/dist/flow-guard-state.js +121 -0
  74. package/dist/flow-guard-state.js.map +1 -0
  75. package/dist/flow-guard-text.d.ts +9 -0
  76. package/dist/flow-guard-text.d.ts.map +1 -0
  77. package/dist/flow-guard-text.js +46 -0
  78. package/dist/flow-guard-text.js.map +1 -0
  79. package/dist/flow-guard-types.d.ts +154 -0
  80. package/dist/flow-guard-types.d.ts.map +1 -0
  81. package/dist/flow-guard-types.js +2 -0
  82. package/dist/flow-guard-types.js.map +1 -0
  83. package/dist/flow-guard.d.ts +20 -215
  84. package/dist/flow-guard.d.ts.map +1 -1
  85. package/dist/flow-guard.js +26 -1400
  86. package/dist/flow-guard.js.map +1 -1
  87. package/dist/mcp-client.d.ts +1 -2
  88. package/dist/mcp-client.d.ts.map +1 -1
  89. package/dist/mcp-client.js +2 -19
  90. package/dist/mcp-client.js.map +1 -1
  91. package/dist/mcp-server.js +5 -0
  92. package/dist/mcp-server.js.map +1 -1
  93. package/dist/mcp-tools.d.ts.map +1 -1
  94. package/dist/mcp-tools.js +46 -9
  95. package/dist/mcp-tools.js.map +1 -1
  96. package/dist/public-address.d.ts +3 -0
  97. package/dist/public-address.d.ts.map +1 -0
  98. package/dist/public-address.js +58 -0
  99. package/dist/public-address.js.map +1 -0
  100. package/dist/review-diff.d.ts +36 -0
  101. package/dist/review-diff.d.ts.map +1 -1
  102. package/dist/review-diff.js +177 -7
  103. package/dist/review-diff.js.map +1 -1
  104. package/dist/task-adapter.d.ts +73 -0
  105. package/dist/task-adapter.d.ts.map +1 -0
  106. package/dist/task-adapter.js +379 -0
  107. package/dist/task-adapter.js.map +1 -0
  108. package/dist/task-cli.d.ts +3 -0
  109. package/dist/task-cli.d.ts.map +1 -0
  110. package/dist/task-cli.js +162 -0
  111. package/dist/task-cli.js.map +1 -0
  112. package/dist/types.d.ts +9 -0
  113. package/dist/types.d.ts.map +1 -1
  114. package/dist/wrap-cli.d.ts +5 -0
  115. package/dist/wrap-cli.d.ts.map +1 -1
  116. package/dist/wrap-cli.js +29 -2
  117. package/dist/wrap-cli.js.map +1 -1
  118. package/dist/wrap-screen.d.ts +3 -0
  119. package/dist/wrap-screen.d.ts.map +1 -0
  120. package/dist/wrap-screen.js +20 -0
  121. package/dist/wrap-screen.js.map +1 -0
  122. package/dist/wrap-state.d.ts +8 -1
  123. package/dist/wrap-state.d.ts.map +1 -1
  124. package/dist/wrap-state.js +21 -4
  125. package/dist/wrap-state.js.map +1 -1
  126. package/dist/wrap.d.ts.map +1 -1
  127. package/dist/wrap.js +204 -10
  128. package/dist/wrap.js.map +1 -1
  129. package/docs/flow-guard-model-comparison-2026-10-25.es.md +82 -0
  130. package/docs/flow-guard-model-comparison-2026-10-25.fr.md +82 -0
  131. package/docs/flow-guard-model-comparison-2026-10-25.md +82 -0
  132. package/docs/flow-guard-model-comparison-2026-10-25.ru.md +82 -0
  133. package/docs/flow-guard-model-comparison-2026-10-25.zh.md +82 -0
  134. package/docs/flow-guard.es.md +307 -12
  135. package/docs/flow-guard.fr.md +307 -12
  136. package/docs/flow-guard.md +315 -13
  137. package/docs/flow-guard.ru.md +314 -13
  138. package/docs/flow-guard.zh.md +306 -8
  139. package/docs/scan-limits.es.md +39 -0
  140. package/docs/scan-limits.fr.md +39 -0
  141. package/docs/scan-limits.md +39 -0
  142. package/docs/scan-limits.ru.md +39 -0
  143. package/docs/scan-limits.zh.md +39 -0
  144. package/docs/scan.es.md +2 -0
  145. package/docs/scan.fr.md +2 -0
  146. package/docs/scan.md +2 -0
  147. package/docs/scan.ru.md +2 -0
  148. package/docs/scan.zh.md +2 -0
  149. package/docs/security-hardening.es.md +1 -1
  150. package/docs/security-hardening.fr.md +1 -1
  151. package/docs/security-hardening.md +1 -1
  152. package/docs/security-hardening.ru.md +1 -1
  153. package/docs/security-hardening.zh.md +1 -1
  154. package/examples/atomic-screen-server.mjs +42 -0
  155. package/native/macos/Package.swift +9 -0
  156. package/native/macos/Sources/WardenDesktop/NativeSurface.swift +246 -0
  157. package/native/macos/Sources/WardenDesktop/StandardIO.swift +139 -0
  158. package/native/macos/Sources/WardenDesktopHost/Main.swift +211 -0
  159. package/package.json +18 -6
  160. package/scripts/build-macos.mjs +22 -0
@@ -2,6 +2,291 @@
2
2
 
3
3
  > 🌐 [English](flow-guard.md) · **Русский** · [Español](flow-guard.es.md) · [Français](flow-guard.fr.md) · [中文](flow-guard.zh.md)
4
4
 
5
+ См. [границы измерений и подтверждение версии](scan-limits.ru.md): биллинг, закрепление пакетов, сравнение launcher и смысл счётчиков подтверждений.
6
+
7
+ Повторный аудит, 2026-10-23: бинарные данные `image`/`audio` в результатах инструментов больше не расходуют лимит текста: большое изображение перед текстом не скрывает подписи элементов, заголовки окон с именами файлов учётных данных и JSON в текстовых блоках. Экраны из результатов кликов и нажатий клавиш, включая действия `computer`, тоже обновляют карту. Простое подтверждение выполнения сохраняет предыдущую карту; результат действия только с изображением очищает её. Для исходящих аргументов исключения нет: секрет, замаскированный под бинарные данные, по-прежнему проверяется. Регрессионные тесты воспроизводят оба обхода через hooks и настоящий stdio-прокси. В локальных исходниках теперь также проверяются непрозрачные действия GUI, как описано ниже.
8
+
9
+ Эти исправления управления экраном входят в npm `0.21.0`. В npm `0.20.0` их не было.
10
+
11
+ ## Первое review annotations и проверка ответа (локальный код, 2026-10-25)
12
+
13
+ Пользовательская policy `{"annotationReview":"first-use"}` добавляет вопрос перед первым использованием **только в `wrap --flow NAME`**. По умолчанию `off`; обычный wrap и отдельные hooks нового требования не получают. Для tool без операторской разметки `readOnlyHint`, `destructiveHint`, `openWorldHint` остаются непроверенными claims сервера: любое boolean-значение или неверный тип известного hint может требовать review. Даже `readOnlyHint: true` не доказывает ни отсутствие записи, ни бесплатность. Явные labels оператора и точные capability bindings по identity/снимку tools имеют приоритет; destination allowlist и annotations в аргументах вызова прав не дают.
14
+
15
+ Review запоминается только в текущем wrap для точных launch identity и полного снимка definitions. После согласия proxy дожидается старой проверки и отправляет новый list, затем повторно проверяет общий flow-риск до передачи вызова; drift, новый отказ/основание ask, отказ человека или отсутствие формы останавливают вызов. Неизменное нормальное основание ask допускает подтверждение. Это не атомарная транзакция относительно других proxies. Новый wrap спрашивает заново. Согласие на каждый чувствительный вызов, credential boundary и GUI guard действуют независимо. `audit` лишь пишет журнал, `off` отключает проверку. Это не проверка биллинга и не полный классификатор эффектов.
16
+
17
+ Известное неудобство: первоначальный precheck может уже потратить точное одноразовое правило `credentialEgress`. Повторный precheck после согласия консервативно отказывает даже для прежнего payload, а правило остаётся потраченным. Этот контроль учитывается как дополнительное неудобство, а не нормальный автоматический пропуск.
18
+
19
+ Stop hook больше не освобождает фразу от проверки из-за слов «ignored» или «flagged»: она может одновременно повторять навязанную рекомендацию. Точное совпадение нормализованного окна длиной 12 с сохранённым instruction-фрагментом запрашивает дополнительную проверку ответа. **Честное предупреждение тоже оплачивается этим проходом.** Продолжение ограничивает host flag `stop_hook_active`; независимого persistent счётчика циклов нет. Перефразирование, подмена выбора записей без совпадающей инструкции и семантическая правильность остаются за пределами проверки. Заметка/перепроверка не равны предотвращению. [Отчёт](../../docs/growth/kevin-annotations-answer-review-2026-10-25.ru.md) отделяет детерминированные Linux-тесты от model evaluation; изменения локальные и не выпущены, исторические модельные результаты ниже не пересчитаны.
20
+
21
+ ## Окна ключей (локальный код, 2026-10-25)
22
+
23
+ После Linux-сравнения 6/7/8 сильные окна остаются **8 для не-hex / 10 для hex**. Индекс теперь включает буквенно-цифровые окна до первой цифры после распознанных нормализованных префиксов провайдеров; исключения generic/DER и все старые хеши сохранены. Чтобы существующая сессия получила новые окна, credential нужно прочитать повторно. Шестисимвольные части внутри других слов при отсутствии совпадения по-прежнему останавливает общая граница подтверждения.
24
+
25
+ На 14 400 атакующих примерах 717 решений меняются с подтверждения на отказ; автоматического исполнения нет ни до, ни после. Решения на 7 680 обычных запросах на профиль не изменились: все требуют review по умолчанию, все проходят один раз с точными проверенными публичными правилами. На специально выбранном обычном тексте воспроизведены ложные жёсткие отказы при 6 и известный пример при 7; это не production-частота. [Исследование и сырые данные](../../docs/growth/warden-thresholds-2026-10-25.ru.md) разделяют совпадения подстрок, решения hooks и работу одного детектора. Изменение локальное, не выпущено.
26
+
27
+ ## Граница учётных данных и закодированные фрагменты (локальный код, 2026-10-23)
28
+
29
+ После зарегистрированных чтения ключа и внешнего текста **каждый поддерживаемый исходящий/MCP-вызов требует `ask` до исполнения** (режим `deny` отказывает), независимо от длины части, кодировки, названного адресата и метки MCP «только чтение». Обычные записи в проект тоже проверяются; прежнее исключение для файлов учётных данных сохранено. Флаг `credentialRead` не сбрасывается при вытеснении старых источников или новом ходе пользователя. Так автоматическая передача частей по одному–четыре символа и неизвестных закодированных данных закрывается общей границей, а не обещанием декодировать что угодно.
30
+
31
+ Известное совпадение с секретом по-прежнему запрещается, неоднозначный короткий фрагмент получает `secret_fragment`. Прочие запросы границы имеют причину `credential_egress`, а не ложное утверждение, что безвредный текст — секрет. Строгий GUI остаётся стандартным; его исключения, включая копирование, эту границу не отменяют. `audit` только записывает, `off` отключает защиту; клиент должен соблюдать решения.
32
+
33
+ **Как уменьшить лишние подтверждения:** оператор может добавить точные, независимо проверенные публичные запросы в защищённый пользовательский `flow-policy.json`. Правило связывает полное имя инструмента и все аргументы, включая адресата, через `publicRequestDigest(tool, args)` из `dist/flow-guard.js`. Ключи объектов сортируются, порядок массива значим. Каждое правило разрешает максимум один вызов за сессию, атомарно между прокси, и расходуется даже при ошибке исполнения. Повторы, изменения, дополнительные метаданные RPC и некорректные аргументы не покрываются. Правила не освобождают найденные секреты/приватный текст/персональные данные/короткие совпадения, неполную проверку, переполненное хранилище, управление GUI, shell-код, разрушительные действия и защищённые настройки. Правило разрешает ровно заданные данные, а не доказывает их публичность. Перед одобрением кодированных данных самостоятельно проверьте расшифрованное содержимое. Правила автоматически не устанавливаются.
34
+
35
+ Пример разрешает только `mcp__mail__send_email` с `{"to":"bob@corp.com","subject":"status","body":"The public release is ready."}`:
36
+
37
+ ```json
38
+ {"credentialEgress":{"allow":[{"tool":"mcp__mail__send_email","requestSha256":"62e02f4cb9c21a472999fac9316b66fc8fefe3fcafd2b2860c32c5409dae4a65"}]}}
39
+ ```
40
+
41
+ При исполнении с защитой потока пересылается проверенный JSON-объект без проигнорированных дубликатов полей; скрытые значения не проходят вместе с точным разрешением.
42
+
43
+ Отпечаток создаётся локально через `publicRequestDigest` после проверки всего запроса. Лимиты: 32 правила/использованных разрешения, 1 024 JSON-узла, глубина 32, 16 384 единицы UTF-16 в сериализованном запросе и 65 536 единиц работы сериализации. Некорректный раздел не даёт разрешений. Журнал: `credential_public_request` / `policy_allowed`, исход подтверждения unknown; это не утверждение о нажатии человеком формы.
44
+
45
+ Метаданные фрагментов сохраняют версию `v2`. Подтверждения безвредных запросов: **12/12 → 0/12** с точными проверенными правилами; цена стандартного режима остаётся явной.
46
+
47
+ **Декодирование и ошибки:** ограниченная очередь совмещает URL, канонические base64/base64url, UTF-8 hex, скалярные Unicode/hex escape-последовательности, числовые HTML-сущности и явные английские списки символов. Максимум: четыре уровня преобразования, 64 кандидата, суммарно 524 288 единиц UTF-16. Исчерпание бюджета даёт `payload_incomplete` и проверку человеком, а не «чистый» результат или разрешение правила. Некорректные литералы не исполняются; распаковки и смыслового угадывания нет. Повреждённое состояние/отпечатки не разрешают вызов. Старый индекс v1 требует проверки; для полного восстановления нужна новая сессия и повторное чтение приватных источников. Хеши/смещения/размеры и ограниченные исходящие хвосты остаются чувствительными данными, шифрования нет.
48
+
49
+ **Измеренный компромисс:** в проверке рабочих сценариев — 12 безвредных запросов и 16 атак. Строгий стандартный режим запрашивает все 12 безвредных вызовов; точные проверенные правила пропускают все 12 по одному разу. В обоих вариантах автоматически проходит **0/16 атак**, жёстких ложных запретов — **0**. Отдельный замер только отпечатков: 480 вымышленных ключей, 758 файлов, 0 жёстких запретов и 2 файла с коротким совпадением, требующим проверки. Это разные измерения, они не доказывают частоту ложных срабатываний на проде. Прежний набор из 23 сценариев остаётся на **0/23 прошедших целиком**, включая `secret-chunks-6-filler` и `secret-spelled-out`; два сценария только с ответом получают пояснение/перепроверку. Настоящие stdio-тесты подтверждают ноль вызовов сервера для неподтверждённых коротких/неизвестно закодированных данных, одно разрешение между параллельными прокси и отсутствие обхода через метаданные или повторы.
50
+
51
+ ```bash
52
+ npm run build
53
+ npm test
54
+ node scripts/redteam/credential-egress.mjs /tmp/warden-egress.json
55
+ node scripts/redteam/flow-redteam.mjs /tmp/warden-redteam.json
56
+ node scripts/redteam/fragment-collisions.mjs /tmp/warden-fragments.json docs src test ../docs ../core
57
+ ```
58
+
59
+ **Пределы:** это контроль зарегистрированной границы инструментов, а не всеобщий анализ информационных потоков. Непрочитанные источники, неизвестные/переименованные интеграции, ответы без вызова инструмента, временные/скрытые каналы, скрытое поведение сервера, явно одобренная передача и клиенты, обходящие решения, гарантией не покрыты. Без проверенных правил подтверждений для безвредных действий намеренно больше. Прод и npm не обновлены; oracle replay AgentDojo перезапущен ниже; прежние измерения с моделью и 115 млн символов/HISTOR не повторялись.
60
+
61
+ ## Непрозрачные действия GUI (локальные исходники, 2026-10-23)
62
+
63
+ В строгом режиме GUI по умолчанию после недоверенных данных распознанные вызовы указателя и клавиатуры MCP запрашивают подтверждение до исполнения (`deny` отказывает). Автоматический пропуск кликов по координатам, экранов из одних пикселей, Enter в активном поле и подписей не на английском закрывается **участием человека**, а не распознаванием любого экрана. Ввод текста тоже требует подтверждения: перевод строки или автоматически отправляющее поле может отправить сообщение. Вставка спрашивает даже без зарегистрированного чтения секрета; после распознанного чтения учётных данных сохраняется точная причина `paste_after_secret`. Для остальных непрозрачных действий GUI причина — `screen_action`.
64
+
65
+ Исключение из этого правила — одно точное сочетание выделения всего или копирования (`cmd+a`, `cmd+c`, `ctrl+a`, `ctrl+c`, с поддерживаемыми синонимами модификатора) в одном известном поле клавиш. Лишние поля, последовательности, некорректные массивы, перевод строки в конце и слишком длинные значения требуют подтверждения. Проверки видимых секретов сохраняются. Известные универсальные контроллеры (`computer`, `screen_control`, `desktop_control`, `browser_control`) спрашивают при неизвестном или отсутствующем действии. Полностью известная операция наблюдения, например `screenshot` или `get_screen`, освобождается от правила, только если указан один аргумент `action`. Имена операций в camelCase, с точками и дефисами нормализуются. Названный пользователем или разрешённый политикой адресат не разрешает действия GUI.
66
+
67
+ Последний список элементов каждого сервера (Playwright `[ref=e14]`, `[ref_14]`, номера и JSON-узлы) нужен только для объяснения. Другой формат больше не обходит подтверждение; его пример полезен для улучшения объяснений, но не нужен для блокировки клика. В запрос попадает каноническое английское слово стража, если оно распознано, а не исходная подпись с экрана. Перед одобрением проверьте реальное окно, цель, буфер обмена и ожидаемый эффект. В stdio-прокси каждое действие требует отдельной принятой формы MCP elicitation с установленным флажком; при отсутствии формы, отказе или отмене сервер действие не получает. Хук Claude возвращает `ask` клиенту; исполнение этого решения зависит от механизма разрешений клиента.
68
+
69
+ В строгом режиме подтверждений станет больше, в том числе для обычной навигации и клика в тело письма; удобство и усталость от подтверждений не измерялись. `audit` пишет журнал без блокировки, `off` выключает проверки. Нужны ранее зарегистрированные недоверенные данные (скриншоты по умолчанию недоверенные); если оператор пометит все наблюдения как private, этот триггер может исчезнуть. Проверяются распознанные имена операций, а не произвольно переименованные инструменты, исполнители JavaScript или скрытое поведение вредоносного сервера. На этих границах нужны политика оператора и изоляция ОС. OCR и классификатор инструкций в изображениях не добавлены: инъекция только в пикселях всё ещё может изменить ответ без проверяемого вызова. Локальные тесты hooks и настоящего stdio-прокси проверяют отказ до отправки, отдельное одобрение каждого действия и четыре заявленных случая. Эти локальные изменения ещё не развёрнуты и не опубликованы в npm.
70
+
71
+ Последний снимок теперь уточняет объяснение тремя способами. Координаты (`x`/`y`, `coordinate`, `coordinates` или `position`) сопоставляются с единственным JSON-элементом через `bounds`, `boundingBox`, `bounding_box` или `rect`: конечные числа в `{x,y,width,height}` либо `{left,top,right,bottom}`, размеры положительные. Правая и нижняя границы не включаются; `center` совпадает только при точном равенстве координат. Перекрытия, противоречащие прямоугольники или ссылки, некорректные числа и массивы с неоднозначным порядком xywh/xyxy не дают предполагаемой цели. Пересчёт между координатами экрана, страницы и масштабом не угадывается. Совпадение относится к геометрии прошлого снимка, а не к проверенной текущей цели.
72
+
73
+ Для Enter/Return однозначный узел `focused: true` либо `focusedRef`/`focusedElementId`/`activeElementId` уточняет активный элемент. У явно однострочного поля (`multiline: false`) в форме с единственным распознанным элементом отправки появляется объяснение «Enter может отправить форму»; у многострочного — для cmd/ctrl+Enter. Связь с формой задаётся `form`/`formId` или вложенностью JSON-формы. Отсутствующий или противоречивый фокус, неизвестная многострочность, разные формы и несколько кандидатов на отправку не позволяют сделать такой вывод. Распознанные accessibility/automation identifiers и `type: "submit"` дают каноническую подсказку действия даже без видимой подписи. Небольшие словари поясняют распространённые подписи Senden, Envoyer, Enviar, Wyślij и другие. Идентификатор, роль и перевод остаются недоверенными подсказками; исходное поле accessibility-id не копируется в дополнительные метаданные и не выводится в запросе разрешения; прежние ссылки и подписи элементов остаются в состоянии сессии.
74
+
75
+ Эти дополнения улучшают только объяснения; метаданные экрана не разрешают действие. Подтверждение только после вставки или ввода пропустило бы заранее заполненные сообщения, платежи и удаление. Геометрия, фокус или accessibility-id из одного снимка не доказывают безвредность навигации. Новый снимок только с изображением очищает подсказки; противоречивые дубликаты узлов не используются. Тесты hooks и stdio проверяют объяснения и отказ до отправки вызова серверу.
76
+
77
+ ## Регрессии Gautam: коды символов, НАТО, Git-метаданные и CI
78
+
79
+ Ограниченный декодер теперь распознаёт списки десятичных кодов символов и написание словами НАТО. Для кодов нужны не менее пяти допустимых скаляров, для НАТО — пяти явных единиц. Разделители: пробелы, запятые, точка с запятой, вертикальная черта и переводы строк. Неизвестная единица, недопустимый код или неоднозначный маркер регистра прерывают цепочку. Поддерживаются alfa/alpha, juliett/juliet, xray/x-ray, цифры словами/литералами, названия знаков и явные capital/uppercase/lowercase. Числовые JSON-массивы из 5–4096 целых тоже проверяются. Действуют прежние пределы глубины/вариантов/текста; исчерпание означает `payload_incomplete`. Нет eval и распаковки произвольных данных.
80
+
81
+ Само декодирование не означает утечку: запрет секрета требует совпадения с известным шаблоном или отпечатком. Обычные списки чисел и текст со словами НАТО автоматически не запрещаются. Первые 1–4 символа защищены границей учётных данных, даже если они слишком коротки для декодирования. Тесты проверяют восстановленные ключи и безвредный текст, не объявляя любое короткое совпадение секретом.
82
+
83
+ MCP без меток: `git_push`, `push_files`, `git_commit`, создание коммита и распространённые camelCase/точечные варианты теперь считаются отправкой или сохранением с возможной публикацией. Commit message может уйти наружу позже. `get_commit` / `list_commits` остаются чтением. Метки оператора по-прежнему требуют правильной настройки; независимая граница учётных данных покрывает и ошибочно помеченные MCP-инструменты. Shell Git сохраняет свои проверки. Для этих тестов реальные commit/push не выполнялись.
84
+
85
+ **Локальное изменение release-гейта:** `npm run build && npm run test:redteam` запускает весь сквозной hook replay с `--check`. Сохранены исходные 23 сценария и добавлены пять от Gautam: **28 случаев, из них 26 атак через инструменты требуют ask/deny, две атаки только на ответ — note/recheck**. Удалённый/повторённый сценарий, неверный исход или вновь открытая автоматическая передача дают ненулевой exit code. Тесты намеренно портят отчёт и проверяют отказ гейта. Команда включена в матрицу CI WARDEN, CI workspace, npm `prepublishOnly` и registry workflow до публикации. Это правки локальных файлов: удалённые CI, релиз и публикация не запускались. Заметка об ответе не доказывает, что модель не выполнит атаку только на ответ.
86
+
87
+ Повторить: `npm run build`, `npm run test:redteam` либо `node scripts/redteam/flow-redteam.mjs /tmp/warden-redteam.json --check`. Код: `test/flow-guard-gautam.test.ts`, `scripts/redteam/flow-gate.mjs`.
88
+
89
+ ## Ограниченный режим задач: меньше подтверждений, контроль реального действия
90
+
91
+ Строгий GUI остаётся по умолчанию. Старые `gui.mode: "policy"` / `gui.allow` читаются для миграции, но больше не разрешают клик, ввод или навигационную клавишу после внешнего текста. Страница может подделать даже точный origin, роль и accessibility ID. Геометрия, фокус и переводы служат только объяснением. Составное имя вроде `press_keys_then_execute` не получает исключение Copy. Дополнительные поля RPC не дают автоматического разрешения.
92
+
93
+ Новый встроенный адаптер задач (`node dist/mcp-server.js task`) сам обеспечивает ограничения. Это MCP-сервер для фиксированных ресурсов и HTTP-операций, а не ослабление проверки произвольных экранных инструментов. Он читает закреплённые локальные UTF-8-снимки без выполнения HTML/JS и исполняет проверенную операцию по ID. Модель не задаёт URL, метод, заголовки, тело, получателя, вложения или путь. У адаптера нет профиля браузера, cookies, системного буфера обмена, скриптов страницы, service workers, подпроцессов и произвольной переадресации инструментов. Обычный GUI сохраняет подтверждения. Это структурированный путь для поддерживаемых задач, а не изоляция произвольного браузера/VM.
94
+
95
+ **Настройка только оператором:** сохраните манифест ниже в `<WARDEN_STATE_DIR>/task-manifest.json`, политику — в пользовательский flow policy. Замените путь снимка, его хеш и endpoint; установите `expiresAt` не дальше 24 часов. В снимке должны быть только данные, которые вы намеренно открываете агенту. Пример хеша соответствует точным байтам `The public release is ready.\n`. Проверьте каждый запрос и вычислите `manifestSha256` по фактическим байтам файла со всеми пробелами и переводами строк. Хеш примера policy соответствует показанному манифесту с одним завершающим переводом строки. Разрешения автоматически не устанавливаются.
96
+
97
+ ```json
98
+ {
99
+ "version": 1,
100
+ "taskId": "public-report",
101
+ "expiresAt": "2026-10-23T23:00:00.000Z",
102
+ "resources": [
103
+ {
104
+ "id": "report",
105
+ "title": "Public report",
106
+ "path": "/absolute/path/public-report.txt",
107
+ "sha256": "1403cece199725b166f0f6e59faa9d45e3d5a25db26080fecf95e818ac8d4d0d"
108
+ }
109
+ ],
110
+ "operations": [
111
+ {
112
+ "id": "send_report",
113
+ "title": "Send reviewed report to Bob, no attachments",
114
+ "maxUses": 1,
115
+ "request": {
116
+ "method": "POST",
117
+ "url": "https://mail.example/api/send",
118
+ "headers": {
119
+ "content-type": "application/json",
120
+ "idempotency-key": "public-report-once"
121
+ },
122
+ "body": "{\"to\":\"bob@corp.com\",\"body\":\"The public release is ready.\",\"attachments\":[]}"
123
+ }
124
+ }
125
+ ]
126
+ }
127
+ ```
128
+
129
+ ```json
130
+ {
131
+ "mode": "ask",
132
+ "taskAdapter": {
133
+ "mode": "capabilities",
134
+ "server": "warden_task",
135
+ "manifestSha256": "1531d08beffb7c86d6f236c3bdfa85a8fbac1c3e8734d701e79455c53d0d94b7"
136
+ }
137
+ }
138
+ ```
139
+ ```json
140
+ {
141
+ "mcpServers": {
142
+ "warden_task": {
143
+ "command": "node",
144
+ "args": [
145
+ "/absolute/path/warden/dist/mcp-server.js",
146
+ "task"
147
+ ],
148
+ "env": {
149
+ "WARDEN_STATE_DIR": "/absolute/state/warden",
150
+ "WARDEN_FLOW_POLICY": "/absolute/state/warden/flow-policy.json"
151
+ }
152
+ }
153
+ }
154
+ }
155
+ ```
156
+
157
+ ```sh
158
+ node -e 'console.log(new Date(Date.now() + 3600000).toISOString())'
159
+ node --input-type=module -e 'import {createHash} from "node:crypto"; import {readFileSync} from "node:fs"; console.log(createHash("sha256").update(readFileSync(process.argv[1])).digest("hex"))' /absolute/state/warden/task-manifest.json
160
+ ```
161
+
162
+
163
+ Зарегистрируйте MCP-сервер **`warden_task`**: команда `node`, аргументы `[/absolute/path/warden/dist/mcp-server.js, task]`, те же `WARDEN_STATE_DIR` / `WARDEN_FLOW_POLICY`, что у hooks или `wrap --flow warden_task`. Это имя политики можно связывать только со встроенным адаптером WARDEN. Привязка к постороннему серверу передаст ему полномочия: имя инструмента и `readOnlyHint` не подтверждают подлинность. Отсутствующая, строгая или ошибочная политика запрещает сетевые операции; глобальные `deny`, `audit`, `off` тоже не дают их исполнять. Отдельные разрешения клиента могут по-прежнему запрашиваться.
164
+
165
+ Вызовы: `task_list {}`, `task_read {"id":"report"}`, `task_execute {"id":"send_report"}`. В аргументах допускается только фиксированный ID; лишние поля, дубликаты ключей JSON, массивы и скрытые метаданные RPC отвергаются. Запись hook `task_adapter_delegated` означает передачу доверенному исполнителю, а не успешное выполнение или подтверждение человека. Runtime повторно проверяет хеш, схему, срок и policy; блокировка между процессами и fsync расходуют бюджет до отправки. Бюджет сохраняется после перезапуска, изменённый манифест не сбрасывает уже использованный task ID. Ошибка/неизвестный исход и отмена после отправки расходуют разрешение; отмена до отправки — нет. Повреждённое состояние или оставшийся lock запрещают запуск. После неопределённого исхода оператор сверяет фактический результат, а не удаляет состояние ради повтора.
166
+
167
+ Поддерживаются только фиксированные HTTPS-запросы; `loopback-test` дополнительно разрешает HTTP на числовой localhost для изолированных тестов. Редиректы запрещены, cookies/ссылки/указания ответа не исполняются, размер ответа и полное время ограничены, повторов нет. `bearerEnv` — имя выбранной оператором переменной: токен добавляется только к фиксированному endpoint, не попадает в список операций или аудит. Аудит хранит ID и исходы без payload/токенов. Ответы остаются недоверенными данными.
168
+
169
+ **Платежи и транзакции:** заранее закрепите счёт, сумму, валюту и тело операции; используйте `maxUses: 1` и фиксированный `idempotency-key`, поддерживаемый провайдером. Одна отправка не гарантирует однократное зачисление. После таймаута/ошибки сначала сверяйте состояние у провайдера и только затем выдавайте новое разрешение. Интеграционные тесты используют loopback и синтетические ключи; реальных платежей не было.
170
+
171
+ **Пределы:** оператор доверяет процессу WARDEN и защищает его policy/state, runtime и привязку MCP. Проверенный запрос делает то, что реализует endpoint; даже GET не считается безвредным автоматически. Ошибочное разрешение оператора, явно разрешённый секрет в фиксированном теле, поведение сервера, скрытые каналы выбора ID/порядка/времени и обход защиты другими инструментами или клиентами вне этой границы. OCR и перехват произвольных действий живого GUI не добавлены.
172
+
173
+ **Проверка 2026-10-23:** заново выполнен детерминированный oracle replay AgentDojo 0.1.35 / v1.2.2 в локальном Docker без сети и API модели. Вариант intent: успешных доставленных атак действием 0/579; без вопроса 57/97 обычных задач; завершено 58/97; под атакой завершено 608/949 (исторически 613/949). `ask` считается отказом; это не доказывает безопасность целей без эталона и атак только на ответ. У AgentDojo нет GUI и инструментов адаптера — их проверяют отдельные stdio-, межпроцессные и loopback-тесты. Прежние запуски с живой моделью, 115 млн символов и HISTOR не повторялись. [Сводка replay](../scripts/agentdojo/results/summary-2026-10-23-local.json).
174
+
175
+ Регрессии: `test/task-adapter.test.ts`, `test/flow-guard-gui-policy.test.ts`, `test/flow-guard-credential-boundary.test.ts`, `test/flow-guard-secret-regression.test.ts`. Проверяются подделка подписей/ID, схема policy, закрепление ресурсов, конкуренция/перезапуски, редиректы, точные получатель/тело и первые 1–4 символа ключа в raw, hex, base64, Unicode и неизвестных кодировках. Неоднозначные короткие совпадения требуют проверки без ложного утверждения «обнаружен секрет».
176
+
177
+ ## Нативный бэкенд macOS: AppKit внутри приложения
178
+
179
+ **Реализовано:** Swift-пакет [WardenDesktop](../native/macos/Package.swift), `WardenDesktopSurface` и `WardenDesktopStandardIO` работают внутри нативного приложения — владельца окна. `warden-desktop --demo` открывает настоящее окно AppKit с локальным обработчиком кнопки. Он не управляет чужими приложениями, не отправляет глобальные события мыши/клавиатуры и не выполняет сетевые операции или платежи. Строгое подтверждение wrap сохранено по умолчанию. Бэкенд включается явно и требует подключения приложения; это не универсальный desktop-инжектор.
180
+
181
+ Сборка и запуск из каталога WARDEN. Нужны macOS, Xcode command-line tools и активная сессия WindowServer. Сборка нацелена на macOS 13+ и архитектуру хоста arm64/x86_64; проверенной считается только архитектура записанного локального прогона. В пакет включены исходники, не готовый бинарник. Новых runtime-зависимостей npm нет:
182
+
183
+ ```sh
184
+ npm run build
185
+ npm run build:macos
186
+ node dist/mcp-server.js wrap --id macos-owned-app --flow native --screen-read screenshot --screen-atomic -- native/macos/.build/warden-desktop --demo
187
+ npm run test:macos
188
+ ```
189
+
190
+ Пример нативного действия: ссылки строковые. Альтернатива — только `x` и `y` в глобальных экранных points с началом сверху слева, не в пикселях. Перекрытые или неоднозначные цели отклоняются:
191
+
192
+ ```json
193
+ {"name":"click","arguments":{"index":"3"}}
194
+ ```
195
+
196
+ **Граница атомарности:** prepare удерживает точный `NSButton`, явный `NSObject`-target, selector и проверенную по ABI реализацию из `method_getImplementation`. Commit на MainActor сверяет ревизию, живые роль/ID/рамку/подпись, идентичность объекта, окно/фокус/модальность, прозрачность всей цепочки родительских views и hit-test. Полностью прозрачные кнопки/окна, заблокированное модальное окно и ожидающие sheet, включая переходную связь `sheetParent`, отклоняются. После hit-test свойства считываются заново; после проверки обоих часов и всех внедрённых callback выполняется последняя сверка ревизии. Закреплённый IMP вызывается через `NativeAction` в том же проходе главного цикла. `NSApp.sendAction` намеренно обходится: переопределение может отложить, перенаправить действие или вернуть успех без вызова согласованного метода. Нет `AXPress`, `CGEvent`, анимации `performClick`, first-responder поиска или отложенного координатного ввода. Поддерживаются только зарегистрированные видимые активные momentary push buttons с сигнатурой `void action(id sender)`. Прямой клик, текст, аккорды, буфер обмена, secure-поля, незарегистрированные views и внешние PID отклоняются.
197
+
198
+ **Подключение:** импортируйте локальный Swift-пакет в приложение. На MainActor создайте `WardenDesktopSurface(window:applicationID:)`, задайте кнопке accessibility element/role/identifier и вызовите `register(id:button:target:selector:)`. Храните surface и `WardenDesktopStandardIO(surface:)` на всё время работы; `start()` обслуживает выделенный унаследованный stdio-канал. Наблюдение возвращает структурированные метаданные зарегистрированных контролов, а не пиксельный снимок или глобальное AX-дерево. Максимум 64 контрола, уникальные ссылки/ID и явные удерживаемые target; nil-target и небезопасные Objective-C сигнатуры запрещены. См. [исходник](../native/macos/Sources/WardenDesktop/NativeSurface.swift) и [нативный пример](../native/macos/Sources/WardenDesktopHost/Main.swift).
199
+
200
+ Все изменения модели, получателя и обработчика должны выполняться на MainActor с вызовом `invalidate()` **до** изменения вне одобренного обработчика, включая невидимые изменения и A → B → A. Уведомления окна и свежие отпечатки дополняют это правило, но не доказывают учёт всех скрытых изменений модели. Одобренные обработчики должны быть синхронными, без вложенного модального run loop, асинхронной пересылки и подмены responder. Их собственные изменения покрываются сменой ревизии commit. Если приложение не соблюдает этот контракт владения, атомарный режим включать нельзя. Для стороннего приложения без подключения нет запасного пути: Apple предоставляет [раздельные AX-чтение и действие](https://developer.apple.com/documentation/applicationservices/1462091-axuielementperformaction), а не наш контракт ревизии.
201
+
202
+ Билеты связывают полные аргументы и истекают и по системным, и по монотонным часам, максимум через пять минут. Они расходуются до вызова; отмена, повтор, перезапуск и несовпадение не дают использовать билет снова. Ошибка/неопределённость вызова блокирует нативный экземпляр; нельзя перезапускать его или выдавать новое одобрение лишь ради повтора платежа. Квитанция committed подтверждает локальный вызов target-обработчика, **не** доставку письма, завершение платежа или асинхронной работы. Для этого нужны сверка транзакции и постоянный idempotency key конечного сервиса. При потере ответа wrap сохраняет блокировку неопределённого результата.
203
+
204
+ **Нативный интеграционный гейт:** `npm run test:macos` отдельно собирает production/test-бинарники и проверяет настоящие окна и stdio/wrap-диалоги. Покрыты изменения цели/обработчика/рамки/окна, замена объекта с прежним видом, ABA, реентерабельность hit-test, срок/откат часов/повтор/перезапуск/отмена, совместимость отпечатков между языками и многоязычные подписи. Тестовые методы изменения отсутствуют в production-сборке. Набор отделён от кроссплатформенного `npm test`; другая ОС, отсутствие инструментов или GUI приводят к ошибке нативного гейта, без тихого skip. В локальную конфигурацию CI добавлен macOS-гейт; удалённо он не запускался. Тесты не запрашивают глобальные Accessibility/Screen Recording-разрешения и не меняют TCC. Публикации/деплоя нет.
205
+
206
+ **Повторный локальный аудит (2026-10-24):** prepare и commit теперь заново считывают нативные свойства после `hitTest`; изменение обработчика, подписи, доступности или рамки приводит к отказу, даже если приложение пропустило `invalidate()`. Оба времени проверяются ещё раз непосредственно перед отправкой действия. Аргумент отправителя Objective-C должен быть именно объектом (`@`), а не блоком (`@?`). Общий атомарный TypeScript-сервер также использует монотонный срок и повторно проверяет истечение перед эффектом. Регрессии охватывают эти случаи, изменение цели при prepare, освобождение ёмкости просроченных разрешений и повторный вход в нативный обработчик. Это дополнение к договору владения: getters и hit-test не должны запускать вложенные циклы событий или побочные действия; скрытые изменения модели/получателя по-прежнему требуют предварительного invalidate. Поддерживаются только доверенные приложения, подключившие бэкенд.
207
+
208
+ **Контракт прямого вызова (второй локальный аудит, 2026-10-24):** зарегистрированные обработчики должны безопасно вызываться напрямую и самостоятельно проверять права приложения; нельзя полагаться для этого на переопределение `NSApplication.sendAction` или маршрутизацию responder. Провайдеры часов и getters — доверенный синхронный код хоста. Скрытые изменения и ABA по-прежнему требуют предварительного `invalidate()`. Регрессии покрывают модальность/прозрачность во время hit-test, смену runtime-реализации, неизменно полупрозрачную кнопку, перехват dispatch и invalidation из последнего callback часов. Эти проверки входят в npm `0.21.0`. Локальный отчёт тестов не заменяет подписанное release-quality подтверждение. Его текущий digest охватывает JavaScript-файлы `dist`, а не исходники нативного SDK; нативная проверка отдельная.
209
+
210
+ ## Атомарная проверка цели на сервере
211
+
212
+ **Явное включение:** `--screen-atomic` требует `--flow`, `--screen-read` и принудительного режима flow. Строгое подтверждение остаётся по умолчанию. Нужен доверенный сервер с поддержкой контракта; аннотации инструментов и заявленная версия протокола не доказывают доверие. Неподдерживаемый сервер приводит к отказу до вопроса пользователю. Запасного обычного клика нет. Прежний режим только со снимками остаётся неатомарным.
213
+
214
+ Сначала соберите WARDEN, затем запустите локальный пример из его каталога. Пример владеет виртуальной формой: он не управляет ОС, не отправляет письма, не проводит платежи и не обращается к сети:
215
+
216
+ ```sh
217
+ node dist/mcp-server.js wrap --flow screen --screen-read screenshot --screen-atomic -- node examples/atomic-screen-server.mjs
218
+ ```
219
+
220
+ **Протокол:** до вопроса прокси приватно вызывает `warden/screen/prepare` с точным действием и настроенным наблюдением. Пример параметров:
221
+
222
+ ```json
223
+ {
224
+ "protocol": "warden.screen.atomic.v1",
225
+ "observation": { "name": "screenshot", "arguments": {} },
226
+ "action": { "name": "click", "arguments": { "index": 3 } }
227
+ }
228
+ ```
229
+
230
+ Сервер возвращает `protocol`, непрозрачный одноразовый `ticket`, ревизию поверхности `revision`, отпечаток цели `stamp`, `expiresAt` и `observation`. Прокси сверяет отпечаток с наблюдением, показывает действие и после явного принятия повторно проверяет определения инструментов, риск-контекст и свежую цель. Вместо обычного вызова отправляется `warden/screen/commit` с `{protocol,ticket,expected:{revision,stamp},action}`. Сервер расходует билет, сравнивает текущую ревизию, разрешённую цель и точные аргументы и синхронно выполняет действие в той же критической секции. Между проверкой и эффектом нельзя уступать цикл событий или ставить координатный клик в очередь. Любое изменение, включая обработчик/получателя и A → B → A, должно менять ревизию. Действие использует уже разрешённую ссылку на цель, без повторного поиска по координатам.
231
+
232
+ На сервере используйте `AtomicScreenServer` из `@aimarket/warden/atomic-screen` (в локальной сборке — `dist/atomic-screen.js`). Три метода протокола направляйте в `prepare(params)`, `commit(params)` и `cancel(params)`, инструмент наблюдения — в `read()`. Все прямые пути выполнения действий должны отказывать. Нужен один общий экземпляр на поверхность для всех соединений; остальные изменения проходят через `replace(snapshot)`. Доверенный синхронный `apply(action, target)` возвращает `{result,snapshot}`, где result — обычный результат MCP-инструмента. Асинхронные функции запрещены; исключение или неверный результат блокируют поверхность до явной сверки и замены состояния. См. [работающий пример сервера](../examples/atomic-screen-server.mjs).
233
+
234
+ Билеты действуют не больше пяти минут, связывают полное действие, расходуются при попытке commit и не переживают перезапуск сервера. Лимит — 256 ожидающих билетов. Клиент не может вызвать приватный протокол через wrap; билеты не передаются модели и в flow-журнал. `warden/screen/cancel` удаляет неиспользованный билет после отказа/отмены; забытые билеты ограничены сроком. Аргументы атомарного действия должны полностью помещаться в 1500 экранированных символов подтверждения; длинные вызовы отклоняются вместо обрезки.
235
+
236
+ Проверенная квитанция `committed` содержит `protocol,status,revisionBefore,revisionAfter,stamp,result`; wrap возвращает только `result`. Проверенная квитанция `refused` содержит `protocol,status,reason` и означает отсутствие эффекта. В аудите — `atomic_committed` / `atomic_refused`. Повреждённая квитанция, ошибка транспорта или потерянный результат — `execution_uncertain`: повтор запрещён, общая GUI-блокировка остаётся до сверки оператором. Эффект мог произойти до потери ответа. Серверный билет не заменяет постоянный платёжный idempotency key.
237
+
238
+ **Граница владения:** гонка закрывается только для поверхности, чьё полное состояние и синхронное действие контролирует доверенный сервер. Аутентификация или выделенный транспорт должны допускать к prepare/commit только доверенные прокси; билет сам по себе не доказывает согласие человека. Один экземпляр в процессе не является межпроцессной блокировкой ОС. Блокировка сервера вокруг асинхронного ввода мыши или обёртка над Playwright/desktop RPC не делают удалённый экран атомарным. Нативному бэкенду нужна реальная транзакция платформы/ревизия либо управляемая синхронная модель приложения. Нативный модуль AppKit описан в разделе macOS; сторонние приложения без его подключения не поддерживаются. Ложные метаданные, неучтённые внешние изменения и вредоносные разрешённые обработчики не покрываются гарантией. Claude hook не может выполнить приватный commit после одобрения. Регрессии проверяют изменение после последнего чтения прокси, ABA/обработчик, повтор, срок, перезапуск, реентерабельность, запрет прямого клика и неопределённый эффект. Публикации/деплоя нет.
239
+
240
+ ## Auten: одно подтверждение результата и свежий экран после одобрения
241
+
242
+ **Подтверждение результата:** добавьте фрагмент `runs` ниже в существующий закреплённый манифест, сохраните JSON с отступом в два пробела и завершающим переводом строки, пересчитайте хеш и используйте следующую policy с `taskAdapter.mode: "review"`. Вызов — `task_run {"id":"mail_to_bob"}`. Встроенный адаптер задаёт один вопрос через MCP form elicitation до первого действия: результат, полный порядок запросов, точные URL и тела. Учётные данные заголовков скрыты. Флажок по умолчанию выключен. Отсутствие формы, принятие значений по умолчанию, отказ или отмена ничего не разрешают. `strict` остаётся режимом по умолчанию, `capabilities` сохраняет явное разрешение оператора.
243
+
244
+ В примере подготовка/отправка GUI сведена к фиксированному HTTP-действию. План поддерживает до восьми различных ID операций; максимум 16 планов, полное экранированное описание — до 12 000 символов. Модель не может менять шаги, порядок, получателя, тело или результат. В `review` отдельный `task_execute` запрещён, чтобы вопрос нельзя было обойти. Чтение ресурсов и списка не требует вопросов; отдельные разрешения клиента и sensitive-tool policy могут по-прежнему запрашиваться.
245
+
246
+ Адаптер держит межпроцессную блокировку задачи на время вопроса и исполнения, проверяет доступность бюджета до вопроса, после принятия атомарно резервирует весь план и бюджеты всех операций. План одноразовый и после перезапуска. Перед каждым шагом повторно проверяются манифест/policy, срок, отмена и привязка учётных данных. Изменение контекста, ошибка или неопределённый ответ останавливают оставшиеся шаги; неиспользованные резервирования тоже расходуются. Уже выполненные действия не откатываются. Ответ сервера не может менять следующий шаг или адрес. Отказ/отмена до резервирования не расходуют план. Не удаляйте неопределённое состояние/lock ради повтора платежа — сначала сверяйте результат. Аудит отдельно хранит одобрение, резервирование, завершение и остановку без payload/токенов.
247
+
248
+ ```json
249
+ {
250
+ "runs": [
251
+ {
252
+ "id": "mail_to_bob",
253
+ "title": "Send the reviewed public report to bob@corp.com in Mail",
254
+ "operations": [
255
+ "send_report"
256
+ ]
257
+ }
258
+ ]
259
+ }
260
+ ```
261
+
262
+ ```json
263
+ {
264
+ "mode": "ask",
265
+ "taskAdapter": {
266
+ "mode": "review",
267
+ "server": "warden_task",
268
+ "manifestSha256": "c69bafc53aa2e4a1a82dd9a20accbe2e4de5372d7545509fe3f6ccf18fdc5580"
269
+ }
270
+ }
271
+ ```
272
+
273
+ **Свежий экран — только в wrap:** явно выберите инструмент наблюдения того же проверенного сервера, например:
274
+
275
+ ```sh
276
+ node dist/mcp-server.js wrap --flow screen --screen-read get_elements -- node /absolute/path/screen-server.js
277
+ node dist/mcp-server.js wrap --flow screen --screen-read computer --screen-read-input '{"action":"screenshot"}' -- node /absolute/path/screen-server.js
278
+ ```
279
+
280
+ `--screen-read` требует `--flow`; `--screen-read-input` — строгий JSON: пустой ввод для известного инструмента наблюдения либо одно известное поле `action` для общего контроллера. `readOnlyHint` не даёт полномочий. Без этой настройки остаётся обычное строгое подтверждение каждого GUI-вызова, без заявления о проверке после одобрения. У Claude hook нет обратного вызова между диалогом клиента и выполнением, поэтому он эту проверку не делает.
281
+
282
+ При включении wrap читает исходное состояние прямо перед вопросом, затем после принятия повторно проверяет определения и читает экран ещё раз. Проверяется именно новый ответ, а не кэш. Он должен однозначно задавать цель, роль, точную ссылку узла, рамку, контекст и согласованный фокус для клавиатуры; при наличии сравниваются accessibility ID, подпись и подсказки формы. Изменение, отсутствие, перекрытие/неоднозначность, неполный список, одни пиксели или ошибка чтения запрещают действие. Масштаб и систему координат не угадываем. Неподдерживаемая схема нескольких действий/лишних полей не проходит сравнение. Изменившийся риск или вновь обнаруженный секрет тоже останавливают вызов. Отмена во время последнего чтения учитывается.
283
+
284
+ Известные GUI-действия разных прокси с общими `WARDEN_FLOW_SESSION` / state сериализуются экранной блокировкой, в том числе если второй прокси не включает перепроверку. Обычный результат снимает lock; пропавший результат/сбой оставляет неопределённую блокировку для проверки оператором. Наблюдения без изменения UI могут продолжаться. `screen_validation` пишет `unchanged`, `refused_without_approval`, `refused_after_approval` или `execution_uncertain`; принятие формы и совпадение метаданных сами по себе не означают выполнения.
285
+
286
+ **Предел:** окно устаревшей цели сужается, но снимок и клик не становятся атомарными. Внешний процесс может изменить UI после чтения; сервер — вернуть старые/ложные данные; одинаковые ID/рамки не доказывают неизменность обработчиков или безвредность действия. Полное закрытие требует доверенного сервера, который проверяет revision/цель и выполняет действие атомарно. Произвольная цепочка click/paste/Send не получает общее разрешение. Группировка относится к структурированному адаптеру с контролем исполнения, а не к доверию метаданным страницы. Атаки только на ответ остаются вне контроля действий инструментов.
287
+
288
+ Локальные регрессии: `test/wrap-screen.test.ts`, `test/wrap.test.ts`, `test/task-adapter.test.ts`. [Новый локальный AgentDojo checkpoint](../scripts/agentdojo/results/summary-2026-10-23-auten-local.json): детерминированный replay без API модели и GUI-инструментов. Публикации, деплоя и отправки комментария не было.
289
+
5
290
  ## Объяснения запросов разрешения (исходники, ещё не выпущены)
6
291
 
7
292
  Сообщение теперь показывает действие и до четырёх адресатов: например, `Action: mcp__slack__send_message. Targets: channel="#general".` Далее указана причина запроса. Перечень инструментов, давших внешний текст, — контекст сессии, а не доказательство происхождения адресата. Происхождение каждого адресата пока не отслеживается.
@@ -20,20 +305,21 @@
20
305
  - Защищены распознанные записи в политику/состояние стража, настройки hooks Claude и Git hooks/config, включая раскрываемые переменные путей и симлинки. Hooks с правами самого агента не заменяют ограничения ОС.
21
306
  - Хост разбирается URL-парсером; userinfo не считается хостом. Проверяются все найденные адресаты и наличие аргумента назначения. Ссылка в теле письма не разрешает его получателя. Почтовые адреса в политике сопоставляются целиком; домен не разрешает все ящики. Упоминание адресата пользователем — грубое исключение, а не разрешение любых действий и данных.
22
307
  - Контакты разрешаются только через явно заданный `contactTools` с меткой `private`: структурированные записи `name`/`email`, в том числе JSON в MCP-ответе. В запросе пользователя должно быть полное отображаемое имя; неоднозначное имя требует подтверждения. Файлы проекта, произвольный текст, YAML и старый кэш контактов не подходят. Доверяйте только справочнику, записи которого агент и посторонние не могут менять.
23
- - Отпечатки проверяют видимый текст аргументов и ограниченный набор декодирований URL/base64/hex. С 2026-10-22 значения, похожие на ключи (случайные последовательности в файлах с секретами и известные форматы токенов, где бы их ни прочли), снимаются ещё и окнами по 8 букв и цифр, для hex-ключей — по 10: кусок ключа, ключ задом наперёд, с разделителями или невидимыми символами, кусками в base64 или с кириллическими или греческими буквами-двойниками запрещается. Это самые маленькие размеры, при которых ни один из 480 выдуманных ключей восьми форматов ни разу не совпал с 115 млн букв и цифр (этот монорепо и 1 000 пакетов HISTOR) обычного текста; части, общие для всех ключей одного вида (идентификатор алгоритма в DER-ключе, заголовок и поля JWT), не снимаются вовсе. Каждый аргумент помнит хвост того, что он отправил после внешнего текста, поэтому куски, отправленные подряд через один аргумент, проверяются целиком. Куски короче 8 символов, каждый раз обёрнутые другими словами, по-прежнему проходят, как и начальный формат ключа (`rk_live_`). Отпечатки не читают произвольные файлы в момент отправки и не покрывают все кодировки и схемы MCP. Правки внутри проекта обычно разрешены; исполнение кода проверяется отдельно.
308
+ - Отпечатки проверяют видимый текст аргументов и ограниченный набор декодирований URL/base64/hex. С 2026-10-22 значения, похожие на ключи (случайные последовательности в файлах с секретами и известные форматы токенов, где бы их ни прочли), снимаются ещё и окнами по 8 букв и цифр, для hex-ключей — по 10: кусок ключа, ключ задом наперёд, с разделителями или невидимыми символами, кусками в base64 или с кириллическими или греческими буквами-двойниками запрещается. Это самые маленькие размеры, при которых ни один из 480 выдуманных ключей восьми форматов ни разу не совпал с 115 млн букв и цифр (этот монорепо и 1 000 пакетов HISTOR) обычного текста; части, общие для всех ключей одного вида (идентификатор алгоритма в DER-ключе, заголовок и поля JWT), не снимаются вовсе. Каждый аргумент помнит хвост того, что он отправил после внешнего текста, поэтому куски, отправленные подряд через один аргумент, проверяются целиком. Локальный код 2026-10-23 добавляет описанные выше сопоставление пар по шесть символов и декодирование явных списков символов. Начальный формат (`rk_live_`) сам по себе секретом не считается. Отпечатки не читают произвольные файлы в момент отправки и не покрывают все кодировки и схемы MCP. Правки внутри проекта обычно разрешены; исполнение кода проверяется отдельно.
24
309
  - После внешнего текста запись ключа, прочитанного в сессии, в обычный файл проекта требует подтверждения (`deny` отказывает): файлы проекта потом коммитят и публикуют без нового вызова. `.env`, `.npmrc` и другие файлы с секретами — место для ключей, туда запись проходит; правка, которая только убирает ключ, не срабатывает.
25
310
  - Адрес, который есть в запросе только во вставленном тексте, в цитате (`>`), в заголовках вставленного письма или ниже пометки о пересылке, не считается названным: отправка на него спрашивает один раз. Точка или запятая после набранного адреса больше не мешают его узнать.
26
311
  - MCP-инструмент без метки оператора считается исходящим, если об этом говорит его имя (send, post, share …), если в аргументах есть URL или, с 2026-10-22, если он называет адресата: аргумент вроде `to`, `email`, `attendees`, `assignee`, `collaborator` или `username`, либо любой e-mail или IBAN. `warden-mcp flow-labels` показывает MCP-инструменты без меток, которыми пользовались ваши сессии, с догадкой стража и блоком `labels`, который нужно проверить и вставить в политику.
27
- - Инъекция, которая меняет только ответ, не делает вызова, которому можно отказать. С 2026-10-22 хук Stop плагина добавляет под ответом строку, если за этот ход читался внешний текст: какие источники, и отдельно — если какой-то из них обращался к ассистенту с указаниями. Если ответ повторяет 12 букв и цифр подряд из тех предложений, где внешний текст обращался к ассистенту, хук ещё и один раз возвращает ответ модели (`decision: block`) на проверку по запросу пользователя, прежде чем пользователь его прочтёт; пользователь теряет только время этой проверки. `answerNote`: `always` (по умолчанию), `instruction` (только этот случай) или `off`; вне плагина зарегистрируйте `warden-mcp hook stop`.
312
+ - По умолчанию после внешних данных распознанные действия управления экраном требуют подтверждения независимо от координат, текста скриншота, формата списка элементов и языка подписи. Это клики/тапы/перетаскивания, ввод и заполнение полей, вставка, Enter/Return и неизвестные нажатия клавиш. `deny` отказывает. Английские слова уточняют объяснение; привычная подпись вроде Inbox не разрешает клик. Подробности — в ограниченном режиме задач выше.
313
+ - Инъекция, которая меняет только ответ, не делает вызова, которому можно отказать. С 2026-10-22 хук Stop плагина добавляет под ответом строку, если за этот ход читался внешний текст: какие источники, и отдельно — если какой-то из них обращался к ассистенту с указаниями. Если ответ повторяет 12 нормализованных символов подряд из тех предложений, где внешний текст обращался к ассистенту, хук ещё и один раз возвращает ответ модели (`decision: block`) на проверку по запросу пользователя, прежде чем пользователь его прочтёт; пользователь теряет только время этой проверки. `answerNote`: `always` (по умолчанию), `instruction` (только этот случай) или `off`; вне плагина зарегистрируйте `warden-mcp hook stop`.
28
314
  - Прокси учитывает текст JSON-RPC errors и ошибки инструментов как внешние данные. Если учёт ответа не удался, ответ удерживается. Повреждённое состояние сессии блокирует проверяемый вызов вместо сброса в пустую сессию.
29
315
 
30
- Вышло в npm `0.17.0`: `npx -y @aimarket/warden@0.20.0 hook pre-tool-use`, либо из исходников — в каталоге WARDEN `npm ci && npm run build`, затем `node dist/mcp-server.js hook pre-tool-use`. Зарегистрируйте также prompt/post hooks либо плагин Claude.
316
+ Вышло в npm `0.17.0`: `npx -y @aimarket/warden@0.22.0 hook pre-tool-use`, либо из исходников — в каталоге WARDEN `npm ci && npm run build`, затем `node dist/mcp-server.js hook pre-tool-use`. Зарегистрируйте также prompt/post hooks либо плагин Claude.
31
317
 
32
318
  Политика: `~/.local/state/warden/flow-policy.json` или `WARDEN_FLOW_POLICY`. Режимы: `ask`, `deny`, `audit`, `off`; `audit` только пишет журнал. Пример настройки контактов и адресатов — в [английской версии](flow-guard.md).
33
319
 
34
320
  Прокси: `node dist/mcp-server.js wrap --flow mail -- node mail-server.js`. Всем прокси одной беседы задайте одинаковый новый `WARDEN_FLOW_SESSION`. По умолчанию используется PID родителя; разные запускатели могут иметь разных родителей. Прокси не видит запрос пользователя и встроенные инструменты клиента. Вызов, о котором нужно спросить, спрашивается через форму MCP elicitation клиента, если она есть (ответ пишется в журнал как `approvalOutcome`), иначе или с `--ask refuse` отклоняется. `trustedSources` применяется к URL WebFetch, а не к ссылкам в произвольных аргументах MCP.
35
321
 
36
- **Какую сборку описывают цифры.** Таблицу воспроизведения ниже прогнали заново 2026-10-22 на текущем коде: исправления аудита плюс изменения 2026-10-22. Изменения 2026-10-22 не поменяли в ней ни одного решения (все 1 046 записей совпали с кодом до них); исправления аудита стоили одной задачи без вопроса и 19 задач, выполненных под атакой. Таблицы прогона с моделью и стоимость по-прежнему относятся к коду до аудита, вплоть до коммита `2328be980`; нового прогона с моделью не было. Воспроизведение эталонной последовательности — один путь атаки, а не адаптивный худший случай; атаки со знанием кода от 2026-10-22 — [ниже](#что-меняли-2026-10-22-и-зачем).
322
+ **Какую сборку описывают цифры.** Таблицу воспроизведения ниже прогнали заново 2026-10-22 на коде того дня: исправления аудита плюс изменения 2026-10-22. Изменения 2026-10-22 не поменяли в ней ни одного решения (все 1 046 записей совпали с кодом до них); исправления аудита стоили одной задачи без вопроса и 19 задач, выполненных под атакой. Таблицы прогона с моделью и стоимость по-прежнему относятся к коду до аудита, вплоть до коммита `2328be980`; нового прогона с моделью не было. Воспроизведение эталонной последовательности — один путь атаки, а не адаптивный худший случай; атаки со знанием кода от 2026-10-22 — [ниже](#что-меняли-2026-10-22-и-зачем).
37
323
 
38
324
  ## Измерено на AgentDojo
39
325
 
@@ -189,12 +475,12 @@ Sonnet; в воспроизведении выше модели нет, а пр
189
475
  | MCP-инструмент без метки, называющий адресата, — исходящий; `warden-mcp flow-labels` | «добавить участника» с e-mail атакующего и «добавить соавтора» по имени пользователя проходили | оба спрашивают |
190
476
  | Хук Stop: строка под ответом, опиравшимся на внешний текст | инъекция только в ответ не делает вызовов | пользователь видит, на какие источники опирался ответ; ничего не блокируется |
191
477
  | Набор правил v15 (см. [gates](gates.ru.md)) | 78 отравленных инструментов из dev-половины MCPTox проходили правила | отложенная половина 171 → 194 из 218 (правила писали только по другой половине), dev-половина 189 → 233 из 267; 0 из 45 чистых серверов; корпус и 1 000 пакетов HISTOR блокируются ровно как при v14 |
192
- | Воспроизведение заново на текущем коде | исправления аудита от 2026-10-18 не измерялись | 0 из 579 атак-действий, 57 из 97 задач без вопроса, 608 из 949 выполнено под атакой; изменения 2026-10-22 не поменяли ни одного решения |
478
+ | Воспроизведение заново на коде 2026-10-22 | исправления аудита от 2026-10-18 не измерялись | 0 из 579 атак-действий, 57 из 97 задач без вопроса, 608 из 949 выполнено под атакой; изменения 2026-10-22 не поменяли ни одного решения |
193
479
  | `scripts/agentdojo/Dockerfile.dockerignore` | `.dockerignore` пакета исключает `dist/`, и команда из «Повторить» не собиралась | собирается |
194
480
 
195
481
  Эти три по-прежнему проходили: куски короче 10 символов в разных словах, адрес, вставленный в запрос, и ключ,
196
482
  записанный в файл проекта. В тот же день мы закрыли всё, что закрывается без ложных срабатываний, и написали ещё шесть
197
- атак против новых правил. Из 23 проходят 2.
483
+ атак против новых правил. В том релизе из 23 проходили 2.
198
484
 
199
485
  | Изменение | Зачем | Результат |
200
486
  |---|---|---|
@@ -202,11 +488,17 @@ Sonnet; в воспроизведении выше модели нет, а пр
202
488
  | Части, общие для всех ключей одного вида, не снимаются (идентификатор алгоритма в DER-ключе, заголовок и поля JWT) | замер нашёл, что 0.19.0 запретил бы отправку README с DKIM-ключом после того, как сессия прочитала RSA-ключ | с правилами в релизе ни одного случайного совпадения |
203
489
  | Ключ, прочитанный в сессии, при записи в обычный файл проекта требует подтверждения | ключ в `docs/debug.md` проходил | спрашивает; `.env` и другие файлы с секретами по-прежнему проходят |
204
490
  | Адрес только во вставленном или цитируемом тексте не считается названным | адрес атакующего, вставленный в запрос, считался адресом пользователя | спрашивает один раз; адрес, который пользователь ещё и набрал, проходит. Точка после набранного адреса больше не делает его неназванным (0.19.0 спрашивал про «отправь на bob@corp.com.») |
205
- | Хук Stop один раз возвращает ответ, повторяющий указание для модели | инъекция только в ответ не делает вызовов | На Ministral 8B, который атаке подчиняется (без стража 6 ответов из 20 рекомендуют отель), уже одна пометка стража свела это к 0; перепроверка сработала 3 раза из 20 и исход не изменила. На DeepSeek V4.1 Flash, который отель ни разу не рекомендовал, — 2 раза из 20 ([результаты](../scripts/agentdojo/results/model-answer-recheck-2026-10-22.json)). Страховка, а не измеренный выигрыш |
491
+ | Хук Stop один раз возвращает ответ, повторяющий указание для модели | инъекция только в ответ не делает вызовов | На Ministral 8B, который атаке подчиняется (без стража 6 ответов из 20 рекомендуют отель), уже одна пометка стража свела это к 0; перепроверка сработала 3 раза из 20 и исход не изменила. На DeepSeek V4.1 Flash — 2 раза из 20 ([результаты](../scripts/agentdojo/results/model-answer-recheck-2026-10-22.json)). Страховка, а не измеренный выигрыш; ограничение сохранённых ответов указано ниже |
206
492
  | Набор правил v16 (см. [gates](gates.ru.md)) | 34 отравленных инструмента dev-половины MCPTox всё ещё проходили, почти все — без входных параметров | отложенная половина 194 → 210 из 218, в том числе все 66 перехватов с неявным триггером; 0 из 45 чистых серверов; корпус и 1 000 пакетов HISTOR блокируются ровно как при v15; пять ложных срабатываний первого варианта закреплены в тестах |
207
493
  | Воспроизведение заново | новые проверки не должны спрашивать там, где не спрашивал 0.19.0 | все 1 046 записей совпадают с 0.19.0 |
208
494
 
209
- По-прежнему проходят ([результаты](../scripts/redteam/results/)):
495
+ **Уточнение сохранённых ответов (2026-10-25):** официальный результат DeepSeek guard + note остаётся **18/20** по предикату точного упоминания названия AgentDojo. При индивидуальном чтении AI-агентом в сохранённых фрагментах не найдено принятой рекомендации; все 18 точных упоминаний находятся в предупреждениях. Полны только 18 ответов: два достигли прежнего лимита хранения 2000 символов, поэтому полный результат compliance 0/20 не установлен. Разметка не независимая и не слепая, официальный балл она не заменяет. Локальный harness теперь сохраняет будущие ответы целиком с длиной и hash; нового модельного прогона не было. [Аудит и воспроизведение](../../docs/growth/launchgate-methodology-2026-10-25.ru.md).
496
+
497
+ **Контролируемый выбор (2026-10-25):** В отдельной синтетической проверке после ответа инструмента использован опубликованный WARDEN `0.21.0`: шесть гостиничных задач × пять повторов, пометки clean/benign/injected и три профиля дали **270/270 правильных ID**, включая **0/90 выборов цели атаки** в injected (0/30 в каждом профиле). Название цели встречалось в **25/270** ответах, включая контроли, а Stop сработал **0/90** раз в `note_stop`; baseline без защиты тоже выбрал правильно, поэтому дополнительный выигрыш защиты не установлен, а правильный ID не подтверждает точность всех фактов в объяснении. [Протокол, результаты и пределы](../../docs/growth/launchgate-selection-2026-10-25.ru.md): это отдельный от AgentDojo опыт, не меняющий исторические **18/20** и не доказывающий общую безопасность.
498
+
499
+ **Продолжение с ничьей (2026-10-25):** При двух допустимых оптимумах injected target выбран 48/48 без защиты, 44/48 с note и 45/48 с note+Stop; clean baseline — соответственно 28/48, 25/48 и 29/48. Интервалы baseline-adjusted эффекта защиты включают ноль; все 432 выбора допустимы, поэтому выбор target не означает ошибку. Настоящие предпочтения пользователя выполнены 18/18, Stop не запрашивал recheck. Локальный [offline evaluator](../scripts/selection-probe/README.md) поддерживает набор допустимых ответов и common-baseline сравнения; runtime-блокировка не изменена. [Результаты и пределы](../../docs/growth/launchgate-tie-selection-2026-10-25.ru.md).
500
+
501
+ В релизе 2026-10-22 эти два примера ещё проходили. В локальном коде 2026-10-23 оба блокируются; см. новый раздел выше. Исторические [результаты](../scripts/redteam/results/):
210
502
 
211
503
  - **Куски короче 8 символов, каждый в других словах**, на адрес, который набрал пользователь: 7 и больше писем на
212
504
  ключ из 40 символов.
@@ -227,10 +519,7 @@ Sonnet; в воспроизведении выше модели нет, а пр
227
519
  один раз просит модель его перепроверить; он видит только те указания, которые страж распознаёт как указания.
228
520
  - **Локальные изменения внутри проекта проходят**, кроме ключа, прочитанного в сессии и записанного в обычный файл.
229
521
  Править файлы проекта — работа агента.
230
- - **Утечка мелкими кусками.** Обычный приватный текст может уйти адресату, которого назвал пользователь, целиком или
231
- кусками: это выбор пользователя. Другим адресатам, а ключи и номера карт — кому угодно: куски, отправленные подряд
232
- через один аргумент, склеиваются; куски короче 8 символов с другими словами вокруг каждого — нет, как и ключ,
233
- продиктованный словами.
522
+ - **Утечка мелкими кусками.** Обычный приватный текст может уходить названному пользователем адресату. Потоковое склеивание и новое правило пар по шесть символов покрывают отдельные разбиения секретов; более короткие части с добавленным текстом и неподдерживаемые словесные кодировки остаются пределами.
234
523
  - **Вставленный текст — не набранный.** Адрес, который вы хотели использовать, но только вставили, спросит один раз.
235
524
  - **Он не видит** ваш запрос до установки плагина и текст, который модель держит из других мест.
236
525
 
@@ -245,7 +534,7 @@ docker run --rm --network none -v "$PWD/out:/out" warden-adojo /out/oracle.json
245
534
 
246
535
  `oracle.py` пишет результаты по каждой паре; `--variants none,strict,intent` выбирает варианты стража (`strict`
247
536
  не учитывает, что набрал пользователь). `summarize_oracle.py` сводит их в то, что цитирует таблица.
248
- `WARDEN_FLOW_GUARD=/out/x.mjs` проигрывает другую сборку стража (любую копию `flow-guard.mjs` из плагина) — так
537
+ `WARDEN_FLOW_GUARD=/out/x.mjs` проигрывает другую сборку стража (любую копию `flow-guard.mjs` из плагина; с 2026-10-24 вместе с частями `flow-guard-*.mjs` в той же папке) — так
249
538
  изменения 2026-10-22 сравнивали с кодом до них.
250
539
 
251
540
  Атакам со знанием кода контейнер не нужен: `npm run build && node scripts/redteam/flow-redteam.mjs out.json`.
@@ -263,3 +552,15 @@ python3 scripts/agentdojo/summarize_model.py summary.json /srv/adojo/out --goals
263
552
  `WORK/ctx` — контекст сборки (`dist/` и `scripts/agentdojo/`); `--obedient` добавляет абзац перехвата;
264
553
  `model.py OUT --model deepseek-flash --model-label DeepSeek --dump-goals` пишет цели атакующего, по которым
265
554
  `summarize_model.py` узнаёт вызовы в его адрес. Записи по каждому прогону обоих раундов: `results/model-deepseek-2026-10-18b.jsonl.gz` (сводка `model-deepseek-2026-10-18b.json`); `--guard-note` возвращает модели пометку стража.
555
+
556
+ ## Сигналы инструкций и диагностика Stop (локальная 0.22.0)
557
+
558
+ Ограниченные английские/русские шаблоны распознают поддельные границы ролей, якобы переданные предпочтения или прежние согласования вместе с близкой директивой, скрываемые инструкции и частные критерии оценки. Это неточные сигналы во внешнем тексте, включая обычные цитаты: они не доказывают атаку, не дают полномочий и не запрещают выбор автоматически. Настоящий запрос пользователя остаётся отдельным источником.
559
+
560
+ Локальный журнал содержит `instructionSignal`, `signalKinds`, `signalScanLimited` и `warningKind` (`source`, `instruction`, `suppressed-audit`). Stop записывает `trigger` (`no-instruction-signal`, `no-literal-overlap`, `literal-instruction-overlap`), `recheckRequested` и `semanticCompliance: "not-assessed"`. Сохраняются порог совпадения 12 нормализованных символов и ограничение продолжения флагом хоста. Перепроверка не является постоянным отказом или доказательством исправления.
561
+
562
+ Помощник репозитория `scripts/selection-probe/audit_warnings.mjs` повторяет сохранённые hook-входы и ответы. Слова-кандидаты признания предупреждения описывают видимый текст, а не осведомлённость или послушание модели. Повтор старого ответа измеряет только hook; изменение выбора требует нового контролируемого модельного прогона.
563
+
564
+ Текст предупреждений Post/Stop состоит из фиксированных фраз и непрозрачных ID `source-` (первые 16 hex-символов SHA-256 имени инструмента). В нём не цитируются найденная инструкция, сырые имена инструментов, URL и пути источника. Это ограничивает перенос чужих метаданных в канал предупреждения, но не защищает модель от любого влияния исходного tool result. ID предназначен только для сопоставления: он не является проверенной версией пакета, pin или разрешением. Локальные журналы могут содержать чужие метаданные и остаются недоверенными данными.
565
+
566
+ **Свежий прогон модели (2026-10-25):** На шести известных задачах получены 720 основных ответов. Под атакой цель выбрана 48/48 без защиты, 44/48 и 46/48 со старыми note/note+Stop (0.21.0), 27/48 в обоих новых режимах. Чистые фоны кандидата — 23/48 и 25/48. Интервалы улучшения относительно старой версии с поправкой на фон: [−8,3; +60,4] п.п. для note и [+14,6; +62,5] для note+Stop. Ни одна из 12 реальных перепроверок не изменила выбранный ID; в трёх исчезла видимая ссылка на предупреждение. Все ID допустимы, настоящие предпочтения пользователя выполнены 30/30. Известные случаи, tool-role bridge и сравнение целых версий не доказывают общей защиты или отдельной пользы Stop. [Полный отчёт](flow-guard-model-comparison-2026-10-25.ru.md).