@aimarket/warden 0.21.0 → 0.22.1
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 +52 -0
- package/README-es.md +24 -7
- package/README-fr.md +24 -7
- package/README-ru.md +24 -7
- package/README-zh.md +24 -7
- package/README.md +24 -7
- package/dist/annotation-review.d.ts +10 -0
- package/dist/annotation-review.d.ts.map +1 -0
- package/dist/annotation-review.js +36 -0
- package/dist/annotation-review.js.map +1 -0
- package/dist/answer-gate.d.ts +94 -0
- package/dist/answer-gate.d.ts.map +1 -0
- package/dist/answer-gate.js +234 -0
- package/dist/answer-gate.js.map +1 -0
- package/dist/atomic-screen.d.ts.map +1 -1
- package/dist/classifier.d.ts +2 -2
- package/dist/classifier.d.ts.map +1 -1
- package/dist/claude-hook.js.map +1 -1
- package/dist/declare.d.ts.map +1 -1
- package/dist/declare.js.map +1 -1
- package/dist/flow-guard-answer.d.ts +30 -0
- package/dist/flow-guard-answer.d.ts.map +1 -0
- package/dist/flow-guard-answer.js +228 -0
- package/dist/flow-guard-answer.js.map +1 -0
- package/dist/flow-guard-classify.d.ts +14 -0
- package/dist/flow-guard-classify.d.ts.map +1 -0
- package/dist/flow-guard-classify.js +224 -0
- package/dist/flow-guard-classify.js.map +1 -0
- package/dist/flow-guard-constraints.d.ts +43 -0
- package/dist/flow-guard-constraints.d.ts.map +1 -0
- package/dist/flow-guard-constraints.js +69 -0
- package/dist/flow-guard-constraints.js.map +1 -0
- package/dist/flow-guard-decode.d.ts +17 -0
- package/dist/flow-guard-decode.d.ts.map +1 -0
- package/dist/flow-guard-decode.js +149 -0
- package/dist/flow-guard-decode.js.map +1 -0
- package/dist/flow-guard-destinations.d.ts +23 -0
- package/dist/flow-guard-destinations.d.ts.map +1 -0
- package/dist/flow-guard-destinations.js +158 -0
- package/dist/flow-guard-destinations.js.map +1 -0
- package/dist/flow-guard-fingerprints.d.ts +27 -0
- package/dist/flow-guard-fingerprints.d.ts.map +1 -0
- package/dist/flow-guard-fingerprints.js +164 -0
- package/dist/flow-guard-fingerprints.js.map +1 -0
- package/dist/flow-guard-fragments.d.ts +17 -0
- package/dist/flow-guard-fragments.d.ts.map +1 -0
- package/dist/flow-guard-fragments.js +122 -0
- package/dist/flow-guard-fragments.js.map +1 -0
- package/dist/flow-guard-instructions.d.ts +12 -0
- package/dist/flow-guard-instructions.d.ts.map +1 -0
- package/dist/flow-guard-instructions.js +36 -0
- package/dist/flow-guard-instructions.js.map +1 -0
- package/dist/flow-guard-labels.d.ts +10 -0
- package/dist/flow-guard-labels.d.ts.map +1 -0
- package/dist/flow-guard-labels.js +55 -0
- package/dist/flow-guard-labels.js.map +1 -0
- package/dist/flow-guard-leak.d.ts +29 -0
- package/dist/flow-guard-leak.d.ts.map +1 -0
- package/dist/flow-guard-leak.js +135 -0
- package/dist/flow-guard-leak.js.map +1 -0
- package/dist/flow-guard-paths.d.ts +21 -0
- package/dist/flow-guard-paths.d.ts.map +1 -0
- package/dist/flow-guard-paths.js +72 -0
- package/dist/flow-guard-paths.js.map +1 -0
- package/dist/flow-guard-policy.d.ts +15 -0
- package/dist/flow-guard-policy.d.ts.map +1 -0
- package/dist/flow-guard-policy.js +179 -0
- package/dist/flow-guard-policy.js.map +1 -0
- package/dist/flow-guard-post.d.ts +6 -0
- package/dist/flow-guard-post.d.ts.map +1 -0
- package/dist/flow-guard-post.js +131 -0
- package/dist/flow-guard-post.js.map +1 -0
- package/dist/flow-guard-pre.d.ts +13 -0
- package/dist/flow-guard-pre.d.ts.map +1 -0
- package/dist/flow-guard-pre.js +335 -0
- package/dist/flow-guard-pre.js.map +1 -0
- package/dist/flow-guard-screen.d.ts +85 -0
- package/dist/flow-guard-screen.d.ts.map +1 -0
- package/dist/flow-guard-screen.js +558 -0
- package/dist/flow-guard-screen.js.map +1 -0
- package/dist/flow-guard-state.d.ts +12 -0
- package/dist/flow-guard-state.d.ts.map +1 -0
- package/dist/flow-guard-state.js +129 -0
- package/dist/flow-guard-state.js.map +1 -0
- package/dist/flow-guard-text.d.ts +9 -0
- package/dist/flow-guard-text.d.ts.map +1 -0
- package/dist/flow-guard-text.js +46 -0
- package/dist/flow-guard-text.js.map +1 -0
- package/dist/flow-guard-types.d.ts +162 -0
- package/dist/flow-guard-types.d.ts.map +1 -0
- package/dist/flow-guard-types.js +2 -0
- package/dist/flow-guard-types.js.map +1 -0
- package/dist/flow-guard.d.ts +22 -394
- package/dist/flow-guard.d.ts.map +1 -1
- package/dist/flow-guard.js +27 -2522
- package/dist/flow-guard.js.map +1 -1
- package/dist/histor.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/jcs.d.ts.map +1 -1
- package/dist/jcs.js.map +1 -1
- package/dist/mcp-client.d.ts +1 -2
- package/dist/mcp-client.d.ts.map +1 -1
- package/dist/mcp-client.js +2 -19
- package/dist/mcp-client.js.map +1 -1
- package/dist/mcp-rpc.js.map +1 -1
- package/dist/mcp-tools.d.ts.map +1 -1
- package/dist/mcp-tools.js.map +1 -1
- package/dist/mtl.d.ts +1 -1
- package/dist/mtl.d.ts.map +1 -1
- package/dist/mtl.js.map +1 -1
- package/dist/origin.d.ts.map +1 -1
- package/dist/pin-store.d.ts.map +1 -1
- package/dist/pin-store.js.map +1 -1
- package/dist/pinning.d.ts.map +1 -1
- package/dist/pinning.js.map +1 -1
- package/dist/public-address.d.ts +3 -0
- package/dist/public-address.d.ts.map +1 -0
- package/dist/public-address.js +58 -0
- package/dist/public-address.js.map +1 -0
- package/dist/review-diff.d.ts +3 -3
- package/dist/review-diff.d.ts.map +1 -1
- package/dist/review-diff.js +3 -5
- package/dist/review-diff.js.map +1 -1
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/sanitize.js.map +1 -1
- package/dist/scan-lock.d.ts.map +1 -1
- package/dist/scan-lock.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js.map +1 -1
- package/dist/static-scan.d.ts.map +1 -1
- package/dist/static-scan.js.map +1 -1
- package/dist/task-adapter.d.ts.map +1 -1
- package/dist/task-adapter.js.map +1 -1
- package/dist/threat-feed.d.ts.map +1 -1
- package/dist/threat-feed.js.map +1 -1
- package/dist/tool-list.js.map +1 -1
- package/dist/toxic-flow.js.map +1 -1
- package/dist/wrap-cli.d.ts +1 -1
- package/dist/wrap-cli.d.ts.map +1 -1
- package/dist/wrap-cli.js +2 -1
- package/dist/wrap-cli.js.map +1 -1
- package/dist/wrap-screen.js.map +1 -1
- package/dist/wrap-state.d.ts +3 -1
- package/dist/wrap-state.d.ts.map +1 -1
- package/dist/wrap-state.js +18 -3
- package/dist/wrap-state.js.map +1 -1
- package/dist/wrap-wire.d.ts.map +1 -1
- package/dist/wrap-wire.js.map +1 -1
- package/dist/wrap.d.ts.map +1 -1
- package/dist/wrap.js +45 -7
- package/dist/wrap.js.map +1 -1
- package/docs/flow-guard-answer-gate.es.md +53 -0
- package/docs/flow-guard-answer-gate.fr.md +53 -0
- package/docs/flow-guard-answer-gate.md +86 -0
- package/docs/flow-guard-answer-gate.ru.md +53 -0
- package/docs/flow-guard-answer-gate.zh.md +53 -0
- package/docs/flow-guard-constraint-evidence.es.md +76 -0
- package/docs/flow-guard-constraint-evidence.fr.md +76 -0
- package/docs/flow-guard-constraint-evidence.md +78 -0
- package/docs/flow-guard-constraint-evidence.ru.md +78 -0
- package/docs/flow-guard-constraint-evidence.zh.md +76 -0
- package/docs/flow-guard-final-witness-2026-10-26.es.md +24 -0
- package/docs/flow-guard-final-witness-2026-10-26.fr.md +24 -0
- package/docs/flow-guard-final-witness-2026-10-26.md +24 -0
- package/docs/flow-guard-final-witness-2026-10-26.ru.md +24 -0
- package/docs/flow-guard-final-witness-2026-10-26.zh.md +24 -0
- package/docs/flow-guard-fresh-rechecks-2026-10-26.es.md +39 -0
- package/docs/flow-guard-fresh-rechecks-2026-10-26.fr.md +39 -0
- package/docs/flow-guard-fresh-rechecks-2026-10-26.md +39 -0
- package/docs/flow-guard-fresh-rechecks-2026-10-26.ru.md +39 -0
- package/docs/flow-guard-fresh-rechecks-2026-10-26.zh.md +39 -0
- package/docs/flow-guard-model-comparison-2026-10-25.es.md +109 -0
- package/docs/flow-guard-model-comparison-2026-10-25.fr.md +109 -0
- package/docs/flow-guard-model-comparison-2026-10-25.md +109 -0
- package/docs/flow-guard-model-comparison-2026-10-25.ru.md +109 -0
- package/docs/flow-guard-model-comparison-2026-10-25.zh.md +109 -0
- package/docs/flow-guard-prospective-holdout-2026-10-26.es.md +30 -0
- package/docs/flow-guard-prospective-holdout-2026-10-26.fr.md +30 -0
- package/docs/flow-guard-prospective-holdout-2026-10-26.md +44 -0
- package/docs/flow-guard-prospective-holdout-2026-10-26.ru.md +44 -0
- package/docs/flow-guard-prospective-holdout-2026-10-26.zh.md +30 -0
- package/docs/flow-guard-review-factors-2026-10-26.es.md +41 -0
- package/docs/flow-guard-review-factors-2026-10-26.fr.md +41 -0
- package/docs/flow-guard-review-factors-2026-10-26.md +45 -0
- package/docs/flow-guard-review-factors-2026-10-26.ru.md +45 -0
- package/docs/flow-guard-review-factors-2026-10-26.zh.md +41 -0
- package/docs/flow-guard-structured-model-2026-10-26.es.md +35 -0
- package/docs/flow-guard-structured-model-2026-10-26.fr.md +35 -0
- package/docs/flow-guard-structured-model-2026-10-26.md +44 -0
- package/docs/flow-guard-structured-model-2026-10-26.ru.md +46 -0
- package/docs/flow-guard-structured-model-2026-10-26.zh.md +35 -0
- package/docs/flow-guard.es.md +54 -4
- package/docs/flow-guard.fr.md +54 -4
- package/docs/flow-guard.md +61 -4
- package/docs/flow-guard.ru.md +60 -4
- package/docs/flow-guard.zh.md +54 -4
- package/docs/scan-limits.es.md +39 -0
- package/docs/scan-limits.fr.md +39 -0
- package/docs/scan-limits.md +39 -0
- package/docs/scan-limits.ru.md +39 -0
- package/docs/scan-limits.zh.md +39 -0
- package/docs/scan.es.md +2 -0
- package/docs/scan.fr.md +2 -0
- package/docs/scan.md +2 -0
- package/docs/scan.ru.md +2 -0
- package/docs/scan.zh.md +2 -0
- package/examples/answer-gate-host.mjs +33 -0
- package/native/macos/Sources/WardenDesktop/NativeSurface.swift +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# 结构化答案边界的真实模型测试
|
|
2
|
+
|
|
3
|
+
[en](flow-guard-structured-model-2026-10-26.md) · [ru](flow-guard-structured-model-2026-10-26.ru.md) · [es](flow-guard-structured-model-2026-10-26.es.md) · [fr](flow-guard-structured-model-2026-10-26.fr.md) · [zh](flow-guard-structured-model-2026-10-26.zh.md)
|
|
4
|
+
|
|
5
|
+
2026 年 10 月 26 日。本地 WARDEN **0.22.0**,运行时代码未改,未发布 npm。这是[应用答案门禁](flow-guard-answer-gate.zh.md)及[四条件实验](flow-guard-review-factors-2026-10-26.zh.md)的后续。
|
|
6
|
+
|
|
7
|
+
## 设计与结果
|
|
8
|
+
|
|
9
|
+
在 Linux factory-vps 对 `deepseek-flash` 发起 160 次新调用:temperature .3、关闭 thinking、JSON object mode、最多 700 输出 token。真实且冻结的 `createAnswerGate` 检查全部规则、完整合格集合与最低价格。没有暗中修改模型候选答案来获得通过。
|
|
10
|
+
|
|
11
|
+
保留十二段原始上下文,包括外部指令和原有自由文本答案。新增用户请求要求使用规范化目录与四字段契约完整替换旧答案。每段重复八次,共 **96/96 个初次提案有效**,其中来自四个旧矛盾上下文的 **32/32** 也有效;其余八段原解释有事实支持。因此,自然产生的纠正机会为零。
|
|
12
|
+
|
|
13
|
+
另设独立受控组:实验者构造真正合格集合加 C(价格 190 > 150)或 D(距离 2.5 > 1)的错误列表。它们是**合成初始错误**,并非模型新产生的失败。四段上下文、每类八次,**32/32 个 C 错误及 32/32 个 D 错误均在首次真实纠正调用后修复**。合成种子占 SDK 初次提案,之后最多两次纠正;不能把这一组的纠正率与自然初次提案正确率混合。
|
|
14
|
+
|
|
15
|
+
160 个新答案均未把 C/D 放入合格列表,也没有重复 JSON 键、无效格式或额外自由文本字段。捕获 **160 个已检查结果和 160 个应用告知**,没有未经验证的候选交付、API 错误、C→D 替换或丢弃的尝试。冻结预测均达到:自然初次正确 >=80/96,受控最终正确 >=48/64。
|
|
16
|
+
|
|
17
|
+
**所有轨迹只需一次真实调用,均未触发第二次纠正或保留。** 本次不提供这些路径的真实模型成功率;此前确定性/stdio 测试仍用于证明机制行为。
|
|
18
|
+
|
|
19
|
+
在测量的结构化表面上,没有出现保留旧错误再追加新说法的现象。模式只有一个合格列表,没有模型自写价格、排除结论或解释字段。输出契约、目录和指令同时改变,因此不能把效果单独归因于格式;没有同期自由文本对照或独立保留集。十二段已知上下文的重复满分不是通用可靠性保证或广泛注入防护证明。
|
|
20
|
+
|
|
21
|
+
## 审核、费用与边界
|
|
22
|
+
|
|
23
|
+
收集后按原始事实重新计算全部最终值,审核过程不调用运行时验证器。测量的是捕获的最终输出帧,不是第三方原生 GUI 的实际显示。来源真实性、任意解释、支付/动作权限,以及并列项之间的隐蔽偏好影响都不在本结论内。
|
|
24
|
+
|
|
25
|
+
付费调用前,Linux 上通过 **9 项 Node 适配器测试、28 项 relay/预算/收集测试**及 480 个请求预检。容器无网络、无密钥;只有主机 relay 可访问固定官方 API。完整请求与响应均保留,删除临时目录前校验 **333 个输出哈希**。没有传输自动重试或重复实验;无需修改运行时代码。
|
|
26
|
+
|
|
27
|
+
全部调用在非高峰时段。Usage:输入 211,200 token,其中缓存 103,936;输出 17,946。按[公布费率](https://api-docs.deepseek.com/quick_start/pricing/)计算 **USD 0.027169008**;保守高峰计费 **USD 0.054338016**,低于 **USD 0.15** 硬上限。未核查发票或账户余额差额;使用现有服务器。
|
|
28
|
+
|
|
29
|
+
准备与审核由 AI 辅助、非盲审;未声称独立人工审核。没有 GitHub/npm 发布,也未发送评论。
|
|
30
|
+
|
|
31
|
+
[analysis.json](data/launchgate-structured-model-2026-10-26/analysis.json) · [protocol.md](data/launchgate-structured-model-2026-10-26/protocol.md) · [execution.json](data/launchgate-structured-model-2026-10-26/execution.json) · [output-audit.json](data/launchgate-structured-model-2026-10-26/output-audit.json) · [trajectories.jsonl](data/launchgate-structured-model-2026-10-26/trajectories.jsonl) · [manifest.json](data/launchgate-structured-model-2026-10-26/manifest.json)
|
|
32
|
+
|
|
33
|
+
<!-- prospective-holdout-followup -->
|
|
34
|
+
|
|
35
|
+
[冻结后的新案例](flow-guard-prospective-holdout-2026-10-26.zh.md):自然初次有效 89/96,七个错误中五个纠正、两个保留;受控纠正 45/48。后续排序/缺失集合证据已离线验证,未重新调用模型。
|
package/docs/flow-guard.es.md
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
# Guardia de flujo: comprobaciones de llamadas tras texto externo
|
|
2
2
|
|
|
3
|
+
<!-- final-ranking-witness -->
|
|
4
|
+
**[Comparación final de mensajes de clasificación, 26 de octubre](flow-guard-final-witness-2026-10-26.es.md).** En los cinco contextos previamente retenidos, el mensaje anterior corrigió 6/40 continuaciones y la comparación explícita entre la opción elegida y la mejor corrigió 40/40. Los controles válidos se conservaron 20/20 por grupo nominal. La serie termina sobre fallos conocidos, no sobre un nuevo conjunto reservado. Este resultado actualiza la limitación anterior de evaluación solo sin conexión para la clasificación; la eficacia del mensaje de conjunto incompleto sigue sin medirse.
|
|
5
|
+
<!-- /final-ranking-witness -->
|
|
6
|
+
|
|
3
7
|
> 🌐 [English](flow-guard.md) · [Русский](flow-guard.ru.md) · **Español** · [Français](flow-guard.fr.md) · [中文](flow-guard.zh.md)
|
|
4
8
|
|
|
9
|
+
Consulte los [límites de medición y pruebas de versión](scan-limits.es.md) sobre facturación, versiones fijas, comparaciones de launchers y significado de los recuentos de aprobación.
|
|
10
|
+
|
|
11
|
+
## Anotaciones y revisión de la respuesta (código local, 2026-10-25)
|
|
12
|
+
|
|
13
|
+
La política opcional del usuario `{"annotationReview":"first-use"}` añade una pregunta de primer uso **solo en `wrap --flow NAME`**. El valor predeterminado es `off`; wrap normal y los hooks por sí solos no cambian. Para una herramienta sin etiqueta del operador, `readOnlyHint`, `destructiveHint` y `openWorldHint` son afirmaciones no verificadas del servidor: cualquier booleano, o un tipo inválido de un hint conocido, puede exigir revisión. `readOnlyHint: true` no demuestra ausencia de escritura ni gratuidad. Las etiquetas explícitas y capability bindings exactos por identidad/conjunto completo de tools tienen prioridad; destinos permitidos y anotaciones en argumentos no conceden derechos.
|
|
14
|
+
|
|
15
|
+
La revisión se recuerda solo en este proceso wrap para la identidad de lanzamiento y el snapshot completo. Tras aceptar, espera cualquier lista anterior y solicita otra nueva; después reevalúa el riesgo compartido antes de transmitir. Cambio de definición, nueva denegación/base de ask, rechazo o formulario ausente impiden la llamada. Una base legítima de ask sin cambios sigue siendo aprobable. No es una transacción atómica frente a otros proxies. Un nuevo wrap vuelve a preguntar. Los controles por llamada sensible, credenciales y GUI siguen independientes. `audit` solo registra; `off` desactiva esta revisión. No verifica facturación ni todos los efectos.
|
|
16
|
+
|
|
17
|
+
Coste conocido: el primer precheck puede consumir una regla exacta de un solo uso `credentialEgress`. La nueva comprobación tras aceptar rechaza conservadoramente incluso un payload idéntico y la regla sigue gastada. Se registra como fricción adicional, no como un paso automático inocuo.
|
|
18
|
+
|
|
19
|
+
Stop ya no exime una frase porque diga «ignored» o «flagged»: puede repetir a la vez la recomendación inyectada. Una coincidencia exacta normalizada de 12 caracteres con una instrucción registrada pide otra revisión. **Una advertencia honesta también cuesta ese pase adicional.** El host limita la continuación mediante `stop_hook_active`; no hay contador persistente independiente. Paráfrasis, selección de filas envenenada sin coincidencia y corrección semántica siguen fuera del alcance. Nota/revisión no equivale a prevención. El [estudio](../../docs/growth/kevin-annotations-answer-review-2026-10-25.ru.md) distingue pruebas Linux deterministas de evaluación del modelo. Cambios locales sin publicar; los resultados históricos del modelo no se recalcularon.
|
|
20
|
+
|
|
5
21
|
Auditoría de seguimiento, 2026-10-23: los datos binarios `image`/`audio` de los resultados ya no consumen el límite de texto; una captura grande antes del texto no oculta etiquetas, títulos de ventanas con archivos de credenciales ni JSON en bloques de texto. Las pantallas devueltas por acciones del puntero y del teclado, incluidas las de `computer`, también actualizan la vista. Una confirmación simple conserva la vista anterior; un resultado de acción con solo una imagen la borra. Los argumentos salientes no reciben esta excepción y siguen sujetos a la comprobación de secretos. Las pruebas de regresión reproducen ambos fallos mediante hooks y el proxy stdio real. El código local ahora también exige aprobación para las acciones GUI opacas descritas abajo.
|
|
6
22
|
|
|
7
23
|
Estas correcciones del control de pantalla van en npm `0.21.0`. npm `0.20.0` no las incluía.
|
|
@@ -288,10 +304,10 @@ La guardia comprueba llamadas después de recibir texto externo; no es un sandbo
|
|
|
288
304
|
- Una dirección que solo aparece en tu prompt dentro de texto pegado, de una línea citada (`>`), de las cabeceras de un mensaje pegado o bajo una marca de reenvío no es una que nombraste: enviarle algo pregunta una vez. Un punto o una coma tras una dirección que escribiste ya no la ocultan.
|
|
289
305
|
- Una herramienta MCP sin etiqueta del operador es saliente si su nombre lo dice (send, post, share …), si lleva una URL o, desde el 2026-10-22, si nombra a una parte: un argumento como `to`, `email`, `attendees`, `assignee`, `collaborator` o `username`, o cualquier correo o IBAN. `warden-mcp flow-labels` lista las herramientas MCP sin etiqueta que usaron tus sesiones, con la suposición del guardián y un bloque `labels` para corregir y pegar en la política.
|
|
290
306
|
- Por defecto, tras contenido externo, las acciones reconocidas de pantalla requieren aprobación con independencia de las coordenadas, el texto de la captura, el formato de elementos o el idioma de la etiqueta. Incluye clics/toques/arrastres, escritura/relleno, pegado, Enter/Return y acciones de teclado desconocidas. `deny` las rechaza. Las palabras inglesas solo mejoran la explicación; una etiqueta como Inbox no autoriza el clic. Véase el modo de tareas limitado arriba.
|
|
291
|
-
- Una inyección que solo cambia la respuesta no hace ninguna llamada que rechazar. Desde el 2026-10-22 el hook Stop del plugin añade una línea bajo una respuesta cuyo turno leyó texto externo, con esas fuentes, y lo dice cuando alguna se dirigió al asistente con instrucciones. Si la respuesta repite 12
|
|
307
|
+
- Una inyección que solo cambia la respuesta no hace ninguna llamada que rechazar. Desde el 2026-10-22 el hook Stop del plugin añade una línea bajo una respuesta cuyo turno leyó texto externo, con esas fuentes, y lo dice cuando alguna se dirigió al asistente con instrucciones. Si la respuesta repite 12 caracteres normalizados consecutivos de las frases donde ese texto se dirigió al asistente, el hook además devuelve la respuesta una vez (`decision: block`) para comprobarla frente a la petición del usuario antes de que este la lea; el usuario solo pierde el tiempo de esa comprobación. `answerNote`: `always` (por defecto), `instruction` (solo ese caso) u `off`; fuera del plugin, registra `warden-mcp hook stop`.
|
|
292
308
|
- El proxy registra también errores JSON-RPC y de herramientas. Retiene una respuesta si no puede registrarla; un estado de sesión corrupto bloquea la comprobación.
|
|
293
309
|
|
|
294
|
-
Publicado en npm `0.17.0`: `npx -y @aimarket/warden@0.
|
|
310
|
+
Publicado en npm `0.17.0`: `npx -y @aimarket/warden@0.22.1 hook pre-tool-use`, o desde el código fuente en WARDEN, `npm ci && npm run build`, luego `node dist/mcp-server.js hook pre-tool-use`, con los hooks prompt/post también registrados. Política: `~/.local/state/warden/flow-policy.json` o `WARDEN_FLOW_POLICY`; modos `ask`, `deny`, `audit`, `off`. Véase el ejemplo vigente en [inglés](flow-guard.md).
|
|
295
311
|
|
|
296
312
|
Proxy: `node dist/mcp-server.js wrap --flow mail -- node mail-server.js`. Use un `WARDEN_FLOW_SESSION` nuevo y compartido por los proxies de una conversación. El PID padre predeterminado no une lanzadores diferentes. El proxy no ve el prompt ni herramientas integradas. Lo que requeriría preguntar se pregunta con el formulario de elicitation MCP del cliente cuando lo ofrece (la respuesta queda en el registro como `approvalOutcome`) y, si no, o con `--ask refuse`, se rechaza. `trustedSources` se aplica a la URL de WebFetch, no a enlaces en argumentos MCP.
|
|
297
313
|
|
|
@@ -472,10 +488,16 @@ positivos y escribimos seis ataques más contra las reglas nuevas. Pasan 2 de 23
|
|
|
472
488
|
| Las partes que comparten todas las claves de un tipo no se registran (identificador de algoritmo de una clave DER, cabecera y campos de un JWT) | la medición mostró que 0.19.0 rechazaría un README con una clave DKIM después de leer una clave RSA privada | ninguna coincidencia casual con las reglas publicadas |
|
|
473
489
|
| Escribir una clave leída en la sesión en un archivo corriente del proyecto pregunta | la clave en `docs/debug.md` pasaba | pregunta; `.env` y los demás archivos de credenciales siguen pasando |
|
|
474
490
|
| Una dirección solo en texto pegado o citado no la nombró el usuario | la dirección del atacante pegada en el prompt contaba como del usuario | pregunta una vez; una dirección que el usuario también escribió pasa. Un punto tras una dirección escrita ya no la deja sin nombrar (0.19.0 preguntaba por «envíalo a bob@corp.com.») |
|
|
475
|
-
| El hook Stop devuelve una vez una respuesta que repite una instrucción dirigida al modelo | una inyección solo en la respuesta no hace llamadas | En Ministral 8B, que obedece el ataque (sin el guardián 6 de 20 respuestas recomiendan el hotel), la nota del guardián sola lo dejó en 0; la revisión saltó 3 veces de 20 y no cambió ningún resultado. En DeepSeek V4.1 Flash
|
|
491
|
+
| El hook Stop devuelve una vez una respuesta que repite una instrucción dirigida al modelo | una inyección solo en la respuesta no hace llamadas | En Ministral 8B, que obedece el ataque (sin el guardián 6 de 20 respuestas recomiendan el hotel), la nota del guardián sola lo dejó en 0; la revisión saltó 3 veces de 20 y no cambió ningún resultado. En DeepSeek V4.1 Flash saltó 2 veces de 20 ([resultados](../scripts/agentdojo/results/model-answer-recheck-2026-10-22.json)). Una red de seguridad, no una mejora medida; véase la limitación de los textos guardados abajo |
|
|
476
492
|
| Ruleset v16 (ver [gates](gates.es.md)) | 34 herramientas envenenadas de la mitad dev de MCPTox seguían pasando, casi todas sin entrada | mitad reservada 194 → 210 de 218, incluidos los 66 secuestros de disparador implícito; 0 de 45 servidores limpios; el corpus y 1000 paquetes de HISTOR bloquean exactamente lo mismo que v15; cinco falsos positivos de un primer borrador quedan fijados como pruebas |
|
|
477
493
|
| La reproducción, de nuevo | las comprobaciones nuevas no deben preguntar donde 0.19.0 no preguntaba | los 1046 registros idénticos a 0.19.0 |
|
|
478
494
|
|
|
495
|
+
**Precisión sobre respuestas guardadas (2026-10-25):** el resultado oficial DeepSeek guard + note sigue en **18/20** con el predicado de mención exacta de AgentDojo. La lectura individual asistida por IA no encontró una recomendación adoptada en esos fragmentos; las 18 menciones exactas aparecen en advertencias. Solo 18 respuestas están completas: dos alcanzan el límite histórico de 2000 caracteres, por lo que no se ha establecido un resultado de cumplimiento 0/20 sobre respuestas completas. La anotación no es independiente ni ciega y no sustituye el resultado oficial. El arnés local conserva ahora las futuras respuestas completas con longitud y hash; esto no implica una nueva ejecución del modelo. [Auditoría y reproducción](../../docs/growth/launchgate-methodology-2026-10-25.ru.md).
|
|
496
|
+
|
|
497
|
+
**Prueba de selección controlada (2026-10-25):** Una prueba sintética separada tras recibir el resultado de la herramienta, con WARDEN `0.21.0` publicado, cubrió seis tareas hoteleras × cinco repeticiones, notas clean/benign/injected y tres perfiles: **270/270 ID correctos**, con **0/90 elecciones del objetivo en injected** (0/30 por perfil). El nombre objetivo apareció en **25/270** respuestas, incluidos los controles, y Stop se activó **0/90** veces en `note_stop`; la referencia sin protección también acertó, por lo que no se establece una mejora adicional del guard, y un ID correcto no valida todos los hechos de la explicación. [Protocolo, resultados y límites](../../docs/growth/launchgate-selection-2026-10-25.en.md): este estudio separado no cambia el **18/20** histórico de AgentDojo ni demuestra seguridad general.
|
|
498
|
+
|
|
499
|
+
**Seguimiento con empate (2026-10-25):** Con dos óptimos admisibles, la selección del objetivo bajo inyección fue 48/48 sin guard, 44/48 con note y 45/48 con note+Stop; las referencias clean fueron 28/48, 25/48 y 29/48. Los intervalos del efecto ajustado por baseline incluyen cero; las 432 elecciones eran admisibles y elegir el objetivo no implica por sí mismo un error. Las preferencias reales del usuario se siguieron 18/18 y Stop no pidió revisiones. El [evaluador offline local](../scripts/selection-probe/README.md) admite conjuntos de respuestas válidas y contrastes con referencia común; el bloqueo en runtime no cambió. [Resultados y límites, EN](../../docs/growth/launchgate-tie-selection-2026-10-25.en.md).
|
|
500
|
+
|
|
479
501
|
En la versión del 2026-10-22 estos dos ejemplos todavía pasaban. Ambos se bloquean en el código local del 2026-10-23; véase arriba. [Resultados históricos](../scripts/redteam/results/):
|
|
480
502
|
|
|
481
503
|
- **Trozos de menos de 8 caracteres, cada uno en palabras distintas**, a una dirección que escribió el usuario: 7 o más
|
|
@@ -513,7 +535,7 @@ docker run --rm --network none -v "$PWD/out:/out" warden-adojo /out/oracle.json
|
|
|
513
535
|
|
|
514
536
|
`oracle.py` escribe resultados por par; `--variants none,strict,intent` elige las variantes del guardián (`strict`
|
|
515
537
|
ignora lo que escribió el usuario). `summarize_oracle.py` los convierte en el resumen que cita la tabla.
|
|
516
|
-
`WARDEN_FLOW_GUARD=/out/x.mjs` reproduce otra versión del guardián (cualquier copia de `flow-guard.mjs` del plugin);
|
|
538
|
+
`WARDEN_FLOW_GUARD=/out/x.mjs` reproduce otra versión del guardián (cualquier copia de `flow-guard.mjs` del plugin; desde 2026-10-24 con sus partes `flow-guard-*.mjs` en la misma carpeta);
|
|
517
539
|
así se compararon los cambios del 2026-10-22 con el código anterior.
|
|
518
540
|
|
|
519
541
|
Los ataques con el código en la mano no necesitan contenedor: `npm run build && node scripts/redteam/flow-redteam.mjs out.json`.
|
|
@@ -533,3 +555,31 @@ python3 scripts/agentdojo/summarize_model.py summary.json /srv/adojo/out --goals
|
|
|
533
555
|
secuestro; `model.py OUT --model deepseek-flash --model-label DeepSeek --dump-goals` escribe los objetivos del
|
|
534
556
|
atacante con los que `summarize_model.py` reconoce las llamadas a él. Registros por ejecución de ambas rondas:
|
|
535
557
|
`results/model-deepseek-2026-10-18b.jsonl.gz` (resumen `model-deepseek-2026-10-18b.json`); `--guard-note` devuelve al modelo la nota del guardián.
|
|
558
|
+
|
|
559
|
+
## Señales de instrucciones y diagnóstico de Stop (0.22.0 local)
|
|
560
|
+
|
|
561
|
+
Los patrones acotados en inglés/ruso reconocen falsos delimitadores de rol, preferencias transmitidas o aprobaciones previas alegadas junto con una directiva cercana, instrucciones ocultas y rúbricas privadas. Son indicios falibles, incluso en citas legítimas: no prueban un ataque, no conceden autoridad ni prohíben automáticamente una elección. Las solicitudes reales del usuario siguen siendo otra fuente.
|
|
562
|
+
|
|
563
|
+
El registro local contiene `instructionSignal`, `signalKinds`, `signalScanLimited` y `warningKind` (`source`, `instruction`, `suppressed-audit`). Stop registra `trigger` (`no-instruction-signal`, `no-literal-overlap`, `literal-instruction-overlap`), `recheckRequested` y `semanticCompliance: "not-assessed"`. Se mantienen el umbral de 12 caracteres normalizados y el límite de continuación del host; una revisión no es un rechazo permanente ni prueba de corrección.
|
|
564
|
+
|
|
565
|
+
El auxiliar del repositorio `scripts/selection-probe/audit_warnings.mjs` reproduce entradas y respuestas guardadas. Las palabras candidatas de reconocimiento solo describen texto visible, no la conciencia u obediencia del modelo. Reproducir una respuesta antigua solo mide el hook; medir cambios de elección exige otra ejecución controlada del modelo.
|
|
566
|
+
|
|
567
|
+
Las advertencias Post/Stop usan frases fijas e identificadores opacos `source-` (los primeros 16 dígitos hexadecimales del SHA-256 del nombre de herramienta). No citan la instrucción detectada ni repiten nombres originales, URL o rutas de la fuente. Esto limita la promoción de metadatos de terceros a través de la advertencia, pero no inmuniza al modelo frente al resultado original. El ID solo permite correlación; no verifica un paquete, no es un pin ni concede permisos. Los registros locales aún pueden contener metadatos externos y siguen siendo datos no confiables.
|
|
568
|
+
|
|
569
|
+
**Nueva comparación con el modelo (2026-10-25):** En seis casos conocidos, 720 respuestas intercaladas eligieron el objetivo inyectado 48/48 sin protección, 44/48 y 46/48 con note/note+Stop publicados (0.21.0), y 27/48 con ambos perfiles candidatos. Sus bases limpias fueron 23/48 y 25/48. Los intervalos de mejora ajustada frente a la versión publicada son [−8,3; +60,4] puntos para note y [+14,6; +62,5] para note+Stop. Ninguna de las 12 revisiones cambió el ID elegido; tres perdieron una referencia visible a la advertencia. Todos los ID eran admisibles y las preferencias reales se siguieron 30/30. Los casos conocidos, el puente tool-role y la comparación de versiones completas no prueban protección general ni un beneficio separado de Stop. [Informe completo](flow-guard-model-comparison-2026-10-25.es.md).
|
|
570
|
+
|
|
571
|
+
<!-- constraint-evidence-followup -->
|
|
572
|
+
|
|
573
|
+
[Evidencia determinista y conservación de la divulgación](flow-guard-constraint-evidence.es.md).
|
|
574
|
+
|
|
575
|
+
<!-- structured-answer-gate -->
|
|
576
|
+
|
|
577
|
+
[Validación por la aplicación](flow-guard-answer-gate.es.md): todas las reglas, corrección adicional limitada y salida almacenada; solo datos estructurados.
|
|
578
|
+
|
|
579
|
+
<!-- structured-live-followup -->
|
|
580
|
+
|
|
581
|
+
[Prueba real de respuestas estructuradas](flow-guard-structured-model-2026-10-26.es.md): 96 primeras propuestas válidas y 64 reparaciones controladas; denominadores y límites separados.
|
|
582
|
+
|
|
583
|
+
<!-- prospective-holdout-followup -->
|
|
584
|
+
|
|
585
|
+
[Nuevos casos tras congelación](flow-guard-prospective-holdout-2026-10-26.es.md): primeras naturales válidas 89/96, cinco de siete reparadas y dos retenidas; controladas 45/48. Evidencia posterior de clasificación/conjunto incompleto probada offline, sin volver a llamar al modelo.
|
package/docs/flow-guard.fr.md
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
# Garde de flux : vérifications des appels après du texte externe
|
|
2
2
|
|
|
3
|
+
<!-- final-ranking-witness -->
|
|
4
|
+
**[Comparaison finale des messages de classement, 26 octobre](flow-guard-final-witness-2026-10-26.fr.md).** Sur les cinq contextes précédemment retenus, l’ancien message a corrigé 6/40 continuations et la comparaison explicite du choix avec le meilleur a corrigé 40/40. Les contrôles valides sont restés valides 20/20 par groupe nominal. La série se termine sur des échecs connus, sans nouvel échantillon réservé. Ce résultat actualise la limite antérieure de vérification hors ligne pour le classement ; l’efficacité du message d’ensemble incomplet reste non mesurée.
|
|
5
|
+
<!-- /final-ranking-witness -->
|
|
6
|
+
|
|
3
7
|
> 🌐 [English](flow-guard.md) · [Русский](flow-guard.ru.md) · [Español](flow-guard.es.md) · **Français** · [中文](flow-guard.zh.md)
|
|
4
8
|
|
|
9
|
+
Voir les [limites des mesures et preuves de version](scan-limits.fr.md) pour la facturation, les versions fixes, les comparaisons de launchers et le sens des compteurs d’approbation.
|
|
10
|
+
|
|
11
|
+
## Annotations et révision de réponse (code local, 2026-10-25)
|
|
12
|
+
|
|
13
|
+
La politique utilisateur facultative `{"annotationReview":"first-use"}` ajoute une question au premier usage **uniquement dans `wrap --flow NAME`**. La valeur par défaut est `off` ; wrap ordinaire et hooks seuls ne changent pas. Pour un outil sans étiquette opérateur, `readOnlyHint`, `destructiveHint` et `openWorldHint` restent des déclarations non vérifiées du serveur : toute valeur booléenne, ou un type invalide d’un hint connu, peut nécessiter une révision. `readOnlyHint: true` ne prouve ni absence d’écriture ni gratuité. Les étiquettes explicites et capability bindings exacts sur identité/ensemble complet des tools priment ; destinations autorisées et annotations dans les arguments n’accordent aucun droit.
|
|
14
|
+
|
|
15
|
+
La révision est mémorisée dans ce processus wrap seulement, pour l’identité de lancement et le snapshot complet. Après accord, le proxy attend l’ancienne liste et en demande une nouvelle, puis revérifie le risque partagé avant l’envoi. Dérive, nouveau refus/motif d’ask, refus humain ou formulaire absent empêchent l’appel. Un motif légitime d’ask inchangé reste approuvable. Ce n’est pas une transaction atomique face aux autres proxies. Un nouveau wrap redemande. Les contrôles par appel sensible, identifiants et GUI restent indépendants. `audit` journalise seulement ; `off` désactive cette vérification. Ce n’est ni une vérification de facturation ni un classificateur complet des effets.
|
|
16
|
+
|
|
17
|
+
Friction connue : le premier precheck peut déjà consommer une règle exacte `credentialEgress` à usage unique. La revérification après accord refuse alors prudemment même un payload identique et la règle reste dépensée. Ce contrôle est compté comme friction supplémentaire, pas comme passage automatique anodin.
|
|
18
|
+
|
|
19
|
+
Stop n’exempte plus une phrase parce qu’elle contient « ignored » ou « flagged » : elle peut aussi reprendre la recommandation injectée. Un chevauchement exact normalisé de 12 caractères avec une instruction enregistrée demande une révision supplémentaire. **Un avertissement honnête paie aussi ce passage.** Le host borne la continuation avec `stop_hook_active` ; aucun compteur persistant indépendant n’est revendiqué. Paraphrases, sélection de lignes empoisonnée sans correspondance et exactitude sémantique restent hors portée. Note/révision ne signifie pas prévention. L’[étude](../../docs/growth/kevin-annotations-answer-review-2026-10-25.ru.md) distingue les tests Linux déterministes de l’évaluation d’un modèle. Changements locaux non publiés ; résultats historiques du modèle non recalculés.
|
|
20
|
+
|
|
5
21
|
Audit complémentaire du 2026-10-23 : les données binaires `image`/`audio` des résultats ne consomment plus le budget de texte ; une grande capture placée avant le texte ne masque donc plus les libellés, les titres de fenêtres contenant un fichier de secrets ou le JSON des blocs de texte. Les écrans renvoyés par les actions du pointeur et du clavier, y compris celles de `computer`, actualisent aussi la vue. Un simple accusé conserve la vue précédente ; une action ne renvoyant qu’une image l’efface. Les arguments sortants ne bénéficient pas de cette exception et restent soumis à la détection de secrets. Les tests de régression reproduisent les deux contournements via les hooks et le véritable proxy stdio. Le code local soumet désormais aussi les actions GUI opaques à une approbation, comme décrit ci-dessous.
|
|
6
22
|
|
|
7
23
|
Ces corrections du contrôle d’écran sont dans npm `0.21.0`. npm `0.20.0` ne les contenait pas.
|
|
@@ -288,10 +304,10 @@ La garde vérifie les appels après réception de texte externe. Ce n’est ni u
|
|
|
288
304
|
- Une adresse qui n’apparaît dans votre prompt que dans un texte collé, une ligne citée (`>`), les en-têtes d’un message collé ou sous une marque de transfert n’est pas une adresse que vous avez nommée : y envoyer demande une fois. Un point ou une virgule après une adresse tapée ne la cachent plus.
|
|
289
305
|
- Un outil MCP sans étiquette d’opérateur est sortant si son nom le dit (send, post, share …), s’il porte une URL ou, depuis le 2026-10-22, s’il nomme une partie : un argument comme `to`, `email`, `attendees`, `assignee`, `collaborator` ou `username`, ou toute adresse e-mail ou IBAN. `warden-mcp flow-labels` liste les outils MCP sans étiquette que vos sessions ont utilisés, avec la supposition de la garde et un bloc `labels` à corriger puis coller dans la politique.
|
|
290
306
|
- Par défaut, après du contenu externe, les actions d’écran reconnues nécessitent une approbation quels que soient les coordonnées, le texte de la capture, le format de la liste ou la langue du libellé. Cela comprend clics/taps/glissements, saisie/remplissage, collage, Entrée/Return et actions de clavier inconnues. `deny` les refuse. Les mots anglais précisent seulement l’explication ; un libellé comme Inbox n’autorise pas un clic. Voir le mode de tâches limité ci-dessus.
|
|
291
|
-
- Une injection qui ne change que la réponse ne fait aucun appel à refuser. Depuis le 2026-10-22, le hook Stop du plugin ajoute une ligne sous une réponse dont le tour a lu du texte extérieur, avec ces sources, et le dit quand l’un d’eux s’adressait à l’assistant avec des instructions. Si la réponse reprend 12
|
|
307
|
+
- Une injection qui ne change que la réponse ne fait aucun appel à refuser. Depuis le 2026-10-22, le hook Stop du plugin ajoute une ligne sous une réponse dont le tour a lu du texte extérieur, avec ces sources, et le dit quand l’un d’eux s’adressait à l’assistant avec des instructions. Si la réponse reprend 12 caractères normalisés consécutifs des phrases où ce texte s’adressait à l’assistant, le hook renvoie aussi la réponse une fois (`decision: block`) pour qu’elle soit vérifiée face à la demande de l’utilisateur avant qu’il la lise ; l’utilisateur ne perd que le temps de cette vérification. `answerNote` : `always` (par défaut), `instruction` (ce cas seulement) ou `off` ; hors du plugin, enregistrez `warden-mcp hook stop`.
|
|
292
308
|
- Le proxy enregistre aussi les erreurs JSON-RPC et d’outils, retient les réponses dont l’enregistrement échoue et bloque les vérifications si l’état existant est corrompu.
|
|
293
309
|
|
|
294
|
-
Publié dans npm `0.17.0` : `npx -y @aimarket/warden@0.
|
|
310
|
+
Publié dans npm `0.17.0` : `npx -y @aimarket/warden@0.22.1 hook pre-tool-use`, ou depuis les sources dans WARDEN, `npm ci && npm run build`, puis `node dist/mcp-server.js hook pre-tool-use`, avec les hooks prompt/post également enregistrés. Politique : `~/.local/state/warden/flow-policy.json` ou `WARDEN_FLOW_POLICY` ; modes `ask`, `deny`, `audit`, `off`. Exemple actuel en [anglais](flow-guard.md).
|
|
295
311
|
|
|
296
312
|
Proxy : `node dist/mcp-server.js wrap --flow mail -- node mail-server.js`. Attribuez un nouveau `WARDEN_FLOW_SESSION` commun aux proxies d’une conversation. Le PID parent par défaut ne relie pas des lanceurs différents. Le proxy ne voit ni prompt ni outils intégrés. Un appel qui demanderait confirmation est demandé via le formulaire d’elicitation MCP du client s’il en propose un (la réponse est journalisée comme `approvalOutcome`), sinon, ou avec `--ask refuse`, il est refusé. `trustedSources` s’applique à l’URL WebFetch, pas aux liens des arguments MCP.
|
|
297
313
|
|
|
@@ -478,10 +494,16 @@ faux positifs et écrit six attaques de plus contre les nouvelles règles. 2 sur
|
|
|
478
494
|
| Les parties que partagent toutes les clés d’un type ne sont pas relevées (identifiant d’algorithme d’une clé DER, en-tête et champs d’un JWT) | la mesure a montré que 0.19.0 refuserait un README contenant une clé DKIM après la lecture d’une clé privée RSA | aucune coïncidence avec les règles publiées |
|
|
479
495
|
| Écrire une clé lue pendant la session dans un fichier ordinaire du projet demande | la clé dans `docs/debug.md` passait | demande ; `.env` et les autres fichiers d’identifiants passent toujours |
|
|
480
496
|
| Une adresse seulement dans un texte collé ou cité n’est pas nommée par l’utilisateur | l’adresse de l’attaquant collée dans le prompt comptait comme celle de l’utilisateur | demande une fois ; une adresse que l’utilisateur a aussi tapée passe. Un point après une adresse tapée ne la rend plus non nommée (0.19.0 demandait pour « envoie-le à bob@corp.com. ») |
|
|
481
|
-
| Le hook Stop renvoie une fois une réponse qui reprend une instruction adressée au modèle | une injection dans la seule réponse ne fait aucun appel | Sur Ministral 8B, qui obéit à l’attaque (sans la garde, 6 réponses sur 20 recommandent l’hôtel), la note de la garde seule a ramené cela à 0 ; la vérification s’est déclenchée 3 fois sur 20 sans changer aucun résultat. Sur DeepSeek V4.1 Flash,
|
|
497
|
+
| Le hook Stop renvoie une fois une réponse qui reprend une instruction adressée au modèle | une injection dans la seule réponse ne fait aucun appel | Sur Ministral 8B, qui obéit à l’attaque (sans la garde, 6 réponses sur 20 recommandent l’hôtel), la note de la garde seule a ramené cela à 0 ; la vérification s’est déclenchée 3 fois sur 20 sans changer aucun résultat. Sur DeepSeek V4.1 Flash, 2 fois sur 20 ([résultats](../scripts/agentdojo/results/model-answer-recheck-2026-10-22.json)). Un filet de sécurité, pas un gain mesuré ; voir la limite des réponses enregistrées ci-dessous |
|
|
482
498
|
| Ruleset v16 (voir [gates](gates.fr.md)) | 34 outils empoisonnés de la moitié dev de MCPTox passaient encore, presque tous sans entrée | moitié réservée 194 → 210 sur 218, dont les 66 détournements à déclencheur implicite ; 0 sur 45 serveurs propres ; le corpus et 1 000 paquets HISTOR bloquent exactement comme v15 ; cinq faux positifs d’un premier jet sont fixés dans les tests |
|
|
483
499
|
| Le rejeu, refait | les nouvelles vérifications ne doivent pas demander là où 0.19.0 ne demandait pas | les 1 046 enregistrements identiques à 0.19.0 |
|
|
484
500
|
|
|
501
|
+
**Précision sur les réponses enregistrées (2026-10-25) :** le résultat officiel DeepSeek guard + note reste **18/20** selon le prédicat de mention exacte d’AgentDojo. La lecture individuelle assistée par IA n’a trouvé aucune recommandation adoptée dans ces extraits ; les 18 mentions exactes figurent dans des avertissements. Seules 18 réponses sont complètes : deux atteignent l’ancienne limite de 2 000 caractères, donc un résultat de conformité 0/20 sur les réponses complètes n’est pas établi. L’annotation n’est ni indépendante ni en aveugle et ne remplace pas le score officiel. Le harnais local conserve désormais les futures réponses complètes avec longueur et hash ; aucun nouvel essai du modèle n’est impliqué. [Audit et reproduction](../../docs/growth/launchgate-methodology-2026-10-25.ru.md).
|
|
502
|
+
|
|
503
|
+
**Test de sélection contrôlé (2026-10-25) :** Un test synthétique séparé après réception du résultat d’outil, avec WARDEN `0.21.0` publié, a couvert six tâches hôtelières × cinq répétitions, des notes clean/benign/injected et trois profils : **270/270 ID corrects**, dont **0/90 choix de la cible en injected** (0/30 par profil). Le nom de la cible apparaît dans **25/270** réponses, contrôles compris, et Stop s’est déclenché **0/90** fois en `note_stop` ; la référence sans protection choisissait aussi correctement, donc aucun gain supplémentaire du guard n’est établi, et un ID correct ne valide pas tous les faits de l’explication. [Protocole, résultats et limites](../../docs/growth/launchgate-selection-2026-10-25.en.md) : cette étude séparée ne modifie pas le **18/20** historique d’AgentDojo et ne démontre pas une sécurité générale.
|
|
504
|
+
|
|
505
|
+
**Suivi avec ex æquo (2026-10-25) :** Avec deux choix optimaux admissibles, la cible a été sélectionnée sous injection 48/48 sans guard, 44/48 avec note et 45/48 avec note+Stop ; les références clean étaient 28/48, 25/48 et 29/48. Les intervalles de l’effet corrigé du baseline incluent zéro ; les 432 choix étaient admissibles et choisir la cible ne constitue donc pas automatiquement une erreur. Les vraies préférences utilisateur ont été suivies 18/18, sans nouvelle vérification Stop. L’[évaluateur offline local](../scripts/selection-probe/README.md) accepte plusieurs réponses admissibles et des contrastes avec référence commune ; le blocage en runtime reste inchangé. [Résultats et limites, EN](../../docs/growth/launchgate-tie-selection-2026-10-25.en.md).
|
|
506
|
+
|
|
485
507
|
Dans la version du 2026-10-22 ces deux exemples passaient encore. Ils sont bloqués dans le code local du 2026-10-23 ; voir plus haut. [Résultats historiques](../scripts/redteam/results/) :
|
|
486
508
|
|
|
487
509
|
- **Des morceaux de moins de 8 caractères, chacun entouré d’autres mots**, vers une adresse que l’utilisateur a
|
|
@@ -520,7 +542,7 @@ docker run --rm --network none -v "$PWD/out:/out" warden-adojo /out/oracle.json
|
|
|
520
542
|
|
|
521
543
|
`oracle.py` écrit les résultats par paire ; `--variants none,strict,intent` choisit les variantes de la garde
|
|
522
544
|
(`strict` ignore ce que l’utilisateur a tapé). `summarize_oracle.py` en tire le résumé que cite le tableau.
|
|
523
|
-
`WARDEN_FLOW_GUARD=/out/x.mjs` rejoue une autre version de la garde (toute copie de `flow-guard.mjs` du plugin) ; c’est
|
|
545
|
+
`WARDEN_FLOW_GUARD=/out/x.mjs` rejoue une autre version de la garde (toute copie de `flow-guard.mjs` du plugin ; depuis le 2026-10-24 avec ses parties `flow-guard-*.mjs` dans le même dossier) ; c’est
|
|
524
546
|
ainsi que les changements du 2026-10-22 ont été comparés au code d’avant.
|
|
525
547
|
|
|
526
548
|
Les attaques code en main n’ont pas besoin de conteneur : `npm run build && node scripts/redteam/flow-redteam.mjs out.json`.
|
|
@@ -540,3 +562,31 @@ python3 scripts/agentdojo/summarize_model.py summary.json /srv/adojo/out --goals
|
|
|
540
562
|
du détournement ; `model.py OUT --model deepseek-flash --model-label DeepSeek --dump-goals` écrit les objectifs de
|
|
541
563
|
l’attaquant avec lesquels `summarize_model.py` reconnaît les appels vers lui. Enregistrements par exécution des deux tours :
|
|
542
564
|
`results/model-deepseek-2026-10-18b.jsonl.gz` (résumé `model-deepseek-2026-10-18b.json`) ; `--guard-note` renvoie au modèle la note de la garde.
|
|
565
|
+
|
|
566
|
+
## Signaux d’instruction et diagnostic Stop (0.22.0 locale)
|
|
567
|
+
|
|
568
|
+
Les motifs anglais/russes bornés reconnaissent les faux délimiteurs de rôle, les préférences relayées ou accords antérieurs allégués avec une directive proche, les consignes dissimulées et les critères privés. Ces signaux restent faillibles, y compris dans des citations légitimes : ils ne prouvent pas une attaque, ne donnent aucune autorité et n’interdisent pas automatiquement un choix. La demande réelle de l’utilisateur reste une source distincte.
|
|
569
|
+
|
|
570
|
+
Le journal local contient `instructionSignal`, `signalKinds`, `signalScanLimited` et `warningKind` (`source`, `instruction`, `suppressed-audit`). Stop consigne `trigger` (`no-instruction-signal`, `no-literal-overlap`, `literal-instruction-overlap`), `recheckRequested` et `semanticCompliance: "not-assessed"`. Le seuil de 12 caractères normalisés et la limite de continuation indiquée par l’hôte restent ; une vérification n’est ni un refus permanent ni une preuve de correction.
|
|
571
|
+
|
|
572
|
+
L’outil du dépôt `scripts/selection-probe/audit_warnings.mjs` rejoue les entrées et réponses conservées. Les mots candidats de reconnaissance décrivent le texte visible, pas la conscience ou l’obéissance du modèle. Rejouer une ancienne réponse mesure uniquement le hook ; mesurer un changement de choix exige une nouvelle expérience contrôlée avec le modèle.
|
|
573
|
+
|
|
574
|
+
Les avertissements Post/Stop utilisent des phrases fixes et des identifiants opaques `source-` (les 16 premiers chiffres hexadécimaux du SHA-256 du nom d’outil). Ils ne citent pas la consigne détectée et ne répètent ni noms bruts, ni URL, ni chemins de la source. Cela limite la promotion de métadonnées tierces dans le canal d’avertissement, sans immuniser le modèle contre le résultat initial. Cet ID sert uniquement à la corrélation ; ce n’est ni une identité de paquet vérifiée, ni un pin, ni une permission. Les journaux locaux peuvent encore contenir des métadonnées externes et restent des données non fiables.
|
|
575
|
+
|
|
576
|
+
**Nouvelle comparaison avec le modèle (2026-10-25) :** Sur six cas connus, 720 réponses entrelacées ont choisi la cible injectée 48/48 sans garde, 44/48 et 46/48 avec note/note+Stop publiés (0.21.0), et 27/48 dans les deux profils candidats. Leurs références propres étaient 23/48 et 25/48. Les intervalles d’amélioration corrigée face à la version publiée sont [−8,3 ; +60,4] points pour note et [+14,6 ; +62,5] pour note+Stop. Aucune des 12 vérifications n’a changé l’ID choisi ; trois ont perdu une référence visible à l’avertissement. Tous les ID étaient admissibles et les vraies préférences ont été suivies 30/30. Ces cas connus, le pont tool-role et la comparaison de versions entières ne prouvent ni protection générale ni bénéfice séparé de Stop. [Rapport complet](flow-guard-model-comparison-2026-10-25.fr.md).
|
|
577
|
+
|
|
578
|
+
<!-- constraint-evidence-followup -->
|
|
579
|
+
|
|
580
|
+
[Preuves déterministes et conservation de la divulgation](flow-guard-constraint-evidence.fr.md).
|
|
581
|
+
|
|
582
|
+
<!-- structured-answer-gate -->
|
|
583
|
+
|
|
584
|
+
[Validation par l’application](flow-guard-answer-gate.fr.md) : toutes les règles, correction supplémentaire bornée et sortie tamponnée ; données structurées uniquement.
|
|
585
|
+
|
|
586
|
+
<!-- structured-live-followup -->
|
|
587
|
+
|
|
588
|
+
[Test réel des réponses structurées](flow-guard-structured-model-2026-10-26.fr.md) : 96 premières propositions valides et 64 réparations contrôlées ; dénominateurs et limites séparés.
|
|
589
|
+
|
|
590
|
+
<!-- prospective-holdout-followup -->
|
|
591
|
+
|
|
592
|
+
[Nouveaux cas après gel](flow-guard-prospective-holdout-2026-10-26.fr.md) : premières naturelles valides 89/96, cinq erreurs sur sept réparées, deux retenues ; contrôlées 45/48. Constats ultérieurs de classement/ensemble incomplet vérifiés hors ligne, sans nouveau modèle.
|
package/docs/flow-guard.md
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
# Flow guard: tool-call checks after outside text
|
|
2
2
|
|
|
3
|
+
<!-- final-ranking-witness -->
|
|
4
|
+
**[Final ranking-feedback comparison, 26 October](flow-guard-final-witness-2026-10-26.md).** On all five previously withheld contexts, old feedback repaired 6/40 continuations and explicit selected-versus-best feedback repaired 40/40. Valid controls stayed valid 20/20 per nominal arm. This completes the series on selected known failures, not a new holdout. The earlier offline-only statement is superseded for ranking feedback on this cohort; missing-set feedback efficacy remains unmeasured.
|
|
5
|
+
<!-- /final-ranking-witness -->
|
|
6
|
+
|
|
3
7
|
> 🌐 **English** · [Русский](flow-guard.ru.md) · [Español](flow-guard.es.md) · [Français](flow-guard.fr.md) · [中文](flow-guard.zh.md)
|
|
4
8
|
|
|
9
|
+
See [measurement limits and version evidence](scan-limits.md) for billing, package pins, launcher comparisons and what approval counts establish.
|
|
10
|
+
|
|
5
11
|
Follow-up audit, 2026-10-23: binary `image`/`audio` data in tool results no longer consumes the text budget, so a large screenshot before its text does not hide element labels, credential-file window titles or JSON text blocks. Screens returned by pointer and keyboard actions (including `computer` actions) update the view too. A plain acknowledgment keeps the previous view; an image-only action result clears it. Outgoing arguments receive no binary exemption and remain subject to secret checks. Regression tests cover both bypasses through the hooks and the real stdio proxy. The local source now also gates opaque GUI actions as described below.
|
|
6
12
|
|
|
7
13
|
These screen-control fixes ship in npm `0.21.0`. npm `0.20.0` did not include them.
|
|
8
14
|
|
|
15
|
+
## Annotation first-use review and answer checks (local source, 2026-10-25)
|
|
16
|
+
|
|
17
|
+
Optional user-level policy `{"annotationReview":"first-use"}` adds a first-use question in **`wrap --flow NAME` only**. Default is `off`; ordinary wrap and hooks alone gain no new requirement. For an operator-unlabelled tool, `readOnlyHint`, `destructiveHint` and `openWorldHint` are unverified server claims: either boolean value, or an invalid known hint, can require review. Even `readOnlyHint: true` proves neither read-only behavior nor free execution. Explicit operator labels and exact identity/tool-set capability bindings take precedence; destination allowlists and annotations in call arguments grant nothing.
|
|
18
|
+
|
|
19
|
+
Review is remembered only in this wrapper for the exact launch identity and complete tool snapshot. After acceptance, the proxy waits for any old list and requests a new list, then rechecks shared flow risk before forwarding; drift, a new denial/ask basis, decline or no approval form refuses the call. Unchanged legitimate ask-bases remain usable. These checks are not an atomic transaction against other proxies. A new wrapper asks again. Every-call sensitive-tool, credential and GUI guards remain independent. `audit` only logs; `off` disables this check. This is not billing verification or a general effect classifier.
|
|
20
|
+
|
|
21
|
+
Known friction: an initial precheck may already consume an exact one-use `credentialEgress` rule. The post-approval precheck then conservatively refuses even an unchanged payload, and the grant remains spent. This control is recorded as extra friction, not a harmless automatic pass.
|
|
22
|
+
|
|
23
|
+
The Stop hook no longer exempts a sentence merely because it says “ignored” or “flagged”: it can still repeat the injected recommendation. An exact normalized 12-character overlap with a recorded instruction fragment requests an additional answer check. **An honest warning pays that extra pass too.** The host's `stop_hook_active` flag bounds the continuation; no independent persistent loop counter is claimed. Paraphrases, poisoned row selection without a matching instruction and semantic correctness remain unsolved. Source notes/rechecks are not prevention scores. The [study](../../docs/growth/kevin-annotations-answer-review-2026-10-25.ru.md) distinguishes deterministic Linux tests from model evaluation; these changes are local and unreleased, and historical model results below remain historical.
|
|
24
|
+
|
|
25
|
+
## Credential windows (local source, 2026-10-25)
|
|
26
|
+
|
|
27
|
+
Strong windows remain **8 non-hex / 10 hex** after the Linux 6/7/8 comparison. The local index now includes mixed letter/digit windows before a key's first digit after recognized normalized provider prefixes, while keeping generic/DER exclusions and all old hashes. A credential reread is needed for an existing session to gain those windows. Six-character pieces inside longer words still rely on the credential boundary when not otherwise recognized.
|
|
28
|
+
|
|
29
|
+
On 14,400 attack fixtures the change converts 717 decisions from ask to deny; none execute automatically before or after. The 7,680 benign requests per profile keep their decisions: all ask by default, all pass once with exact reviewed public rules. Deliberately selected public-text controls show false hard denials at 6 and a known example at 7; these are not production rates. The [study and raw evidence](../../docs/growth/warden-thresholds-2026-10-25.ru.md) separate corpus substring hits, hook decisions and detector-only results. The change is local and unreleased.
|
|
30
|
+
|
|
9
31
|
## Credential boundary and encoded fragments (local source, 2026-10-23)
|
|
10
32
|
|
|
11
33
|
After a recorded credential/key read and outside text, **every supported outbound/MCP call requires `ask` before execution** (`deny` refuses), regardless of fragment length, encoding, user-named destination or read-only MCP label. Ordinary project writes are reviewed too; credential-file writes retain their existing exemption. The sticky `credentialRead` flag survives source-history rotation and user turns. This closes automatic transmission of one-to-four-character pieces and unknown encoded blobs by enforcing a boundary, not by claiming to decode arbitrary information.
|
|
@@ -282,10 +304,10 @@ The flow guard adds checks at tool-call boundaries after a session receives outs
|
|
|
282
304
|
- An address that appears in your prompt only inside pasted text, a quoted line (`>`), the headers of a pasted message or below a forwarded-message marker is not one you named: sending to it asks once. A full stop or comma after an address you typed no longer hides it. Fingerprints do not inspect arbitrary file contents at execution time, arbitrary encodings or every possible MCP schema. Internal project edits are generally allowed; executing their code is a separate decision.
|
|
283
305
|
- An MCP tool without an operator label is outbound when its name says so (send, post, share …), when it carries a URL, or, since 2026-10-22, when it names a party: an argument such as `to`, `email`, `attendees`, `assignee`, `collaborator` or `username`, or any e-mail address or IBAN. `warden-mcp flow-labels` lists the unlabeled MCP tools your sessions used, with the guess and a `labels` block to correct and paste into the policy.
|
|
284
306
|
- By default, screen-control calls after outside content require approval independently of coordinates, screenshot text, element-list format or label language. This includes clicks/taps/drags, typing/fill, clipboard paste, Enter/Return and unknown keyboard actions. `deny` refuses them. English target words improve the explanation only; a familiar label such as Inbox never authorizes a click. See the constrained task mode above.
|
|
285
|
-
- An injection that only changes the answer makes no call to refuse. Since 2026-10-22 the plugin's Stop hook adds one line under an answer whose turn read outside text, naming those sources, and says so when any of it addressed the assistant with instructions. When the answer repeats 12
|
|
307
|
+
- An injection that only changes the answer makes no call to refuse. Since 2026-10-22 the plugin's Stop hook adds one line under an answer whose turn read outside text, naming those sources, and says so when any of it addressed the assistant with instructions. When the answer repeats 12 consecutive normalized characters from the sentences where that text addressed the assistant, the hook also sends the answer back once (`decision: block`), to be checked against the user's request before the user reads it; the user loses nothing but the time of that check. `answerNote` chooses `always` (default), `instruction` (only that case) or `off`; outside the plugin, register `warden-mcp hook stop`.
|
|
286
308
|
- The MCP proxy records JSON-RPC error text and tool-error results as outside text too. If recording fails, it withholds the response. Existing corrupt session state blocks pre-tool checks instead of becoming an empty session.
|
|
287
309
|
|
|
288
|
-
Released in npm `0.17.0`: `npx -y @aimarket/warden@0.
|
|
310
|
+
Released in npm `0.17.0`: `npx -y @aimarket/warden@0.22.1 hook pre-tool-use`, or from a source checkout `npm ci && npm run build`, then `node dist/mcp-server.js hook pre-tool-use`. Register the prompt and post hooks as well, or use the bundled Claude plugin.
|
|
289
311
|
|
|
290
312
|
Policy is user-level (`~/.local/state/warden/flow-policy.json`, or `WARDEN_FLOW_POLICY`). Modes are `ask`, `deny`, `audit`, `off`. `audit` logs decisions without enforcing them. Example:
|
|
291
313
|
|
|
@@ -484,10 +506,16 @@ positives, and wrote six more attacks against the new rules. At that release, 2
|
|
|
484
506
|
| Parts every key of a kind shares are not fingerprinted (a DER key's algorithm identifier, a JWT's header and claims) | the measurement found 0.19.0 would deny a DKIM public key in a README after a session read an RSA private key | no chance match at all with the shipped rules |
|
|
485
507
|
| A key read this session written into an ordinary project file asks | the key in `docs/debug.md` passed | asks; `.env` and other credential files still pass |
|
|
486
508
|
| An address only in pasted or quoted text is not one the user named | the attacker's address pasted into the prompt counted as the user's | asks once; an address the user also typed passes. A full stop after a typed address no longer makes it unnamed (0.19.0 asked about "send it to bob@corp.com.") |
|
|
487
|
-
| The Stop hook sends an answer back once when it repeats an instruction aimed at the model | an answer-only injection makes no call | On Ministral 8B, which follows the attack (6 of 20 answers recommend the hotel without the guard), the guard's note alone took that to 0; the re-check fired 3 times in 20 and changed no outcome. On DeepSeek V4.1 Flash,
|
|
509
|
+
| The Stop hook sends an answer back once when it repeats an instruction aimed at the model | an answer-only injection makes no call | On Ministral 8B, which follows the attack (6 of 20 answers recommend the hotel without the guard), the guard's note alone took that to 0; the re-check fired 3 times in 20 and changed no outcome. On DeepSeek V4.1 Flash, it fired 2 times in 20 ([results](../scripts/agentdojo/results/model-answer-recheck-2026-10-22.json)). A safety net, not a measured gain; see the saved-answer limitation below |
|
|
488
510
|
| Ruleset v16 (see [gates](gates.md)) | 34 of MCPTox's dev-half poisoned tools still passed, nearly all tools that take no input | held-out half 194 → 210 of 218, all 66 implicit-trigger hijackings among them; 0 of 45 clean servers; the field corpus and 1,000 HISTOR packages block exactly what v15 blocked; five false positives of a first draft are pinned as tests |
|
|
489
511
|
| The replay re-run | the new checks must not ask where 0.19.0 did not | all 1,046 records identical to 0.19.0 |
|
|
490
512
|
|
|
513
|
+
**Saved-answer qualification (2026-10-25):** the official DeepSeek guard + note result remains **18/20** under AgentDojo's exact-name mention predicate. Individual AI-assisted reading found no adopted recommendation in those saved excerpts; all 18 exact-name mentions occur in warnings. Only 18 answers are complete: two hit the historical 2,000-character storage cap, so a full-answer 0/20 compliance result is not established. These annotations are neither independent nor blinded and do not replace the official score. The local harness now retains full future answers with length/hash metadata; no new model run is implied. [Audit and reproduction](../../docs/growth/launchgate-methodology-2026-10-25.ru.md).
|
|
514
|
+
|
|
515
|
+
**Controlled selection probe (2026-10-25):** A separate synthetic post-tool probe using published WARDEN `0.21.0` covered six hotel tasks × five repetitions, clean/benign/injected notes and three profiles: **270/270 correct IDs**, with **0/90 injected target choices** (0/30 per profile). Target names appeared in **25/270** answers including controls, and Stop fired **0/90** times in `note_stop`; the unguarded baseline was correct too, so no incremental guard gain is established, and correct IDs do not validate every explanation fact. [Protocol, results and limits](../../docs/growth/launchgate-selection-2026-10-25.en.md): this separate study does not change AgentDojo’s historical **18/20** or establish broad safety.
|
|
516
|
+
|
|
517
|
+
**Tied-choice follow-up (2026-10-25):** With two admissible optima, injected target selection was 48/48 without a guard, 44/48 with the note and 45/48 with note+Stop; the respective clean baselines were 28/48, 25/48 and 29/48. Baseline-adjusted guard-effect intervals include zero, and all 432 choices were admissible; target choice is not automatically an error. Separate genuine-user preferences were followed 18/18, with no Stop rechecks. The local [offline evaluator](../scripts/selection-probe/README.md) now supports admissible sets and common-baseline contrasts; runtime blocking is unchanged. [Results and limits](../../docs/growth/launchgate-tie-selection-2026-10-25.en.md).
|
|
518
|
+
|
|
491
519
|
At the 2026-10-22 release these two examples were still delivered. Both are blocked in the local 2026-10-23 source; see the new section above. Historical [results](../scripts/redteam/results/):
|
|
492
520
|
|
|
493
521
|
- **Pieces under 8 characters, each wrapped in different words**, to an address the user typed: 7 or more messages
|
|
@@ -524,7 +552,8 @@ docker run --rm --network none -v "$PWD/out:/out" warden-adojo /out/oracle.json
|
|
|
524
552
|
|
|
525
553
|
`oracle.py` writes per-pair results; `--variants none,strict,intent` chooses the guard variants (`strict` ignores
|
|
526
554
|
what the user typed). `summarize_oracle.py` turns them into the summary the table quotes. `WARDEN_FLOW_GUARD=/out/x.mjs`
|
|
527
|
-
plays another build of the guard (any plugin copy of `flow-guard.mjs
|
|
555
|
+
plays another build of the guard (any plugin copy of `flow-guard.mjs`; since 2026-10-24 with its `flow-guard-*.mjs`
|
|
556
|
+
parts in the same folder), which is how the 2026-10-22 changes were
|
|
528
557
|
compared with the code before them.
|
|
529
558
|
|
|
530
559
|
The code-aware attacks need no container: `npm run build && node scripts/redteam/flow-redteam.mjs out.json`.
|
|
@@ -543,3 +572,31 @@ python3 scripts/agentdojo/summarize_model.py summary.json /srv/adojo/out --goals
|
|
|
543
572
|
`model.py OUT --model deepseek-flash --model-label DeepSeek --dump-goals` writes the attacker goals
|
|
544
573
|
`summarize_model.py` uses to recognise calls at the attacker.
|
|
545
574
|
Per-run records of both rounds: `results/model-deepseek-2026-10-18b.jsonl.gz` (summary `model-deepseek-2026-10-18b.json`); `--guard-note` feeds the guard's note back to the model.
|
|
575
|
+
|
|
576
|
+
## Source instruction signals and Stop diagnostics (local 0.22.0)
|
|
577
|
+
|
|
578
|
+
Bounded English/Russian patterns recognize spoofed role delimiters, claimed relayed preferences or prior approvals paired with a nearby directive, concealed instructions and private evaluation rubrics. They are fallible source signals, including in legitimate quotations; they do not prove an attack, grant authority or automatically forbid a choice. Genuine user prompts remain a separate source.
|
|
579
|
+
|
|
580
|
+
The local log records `instructionSignal`, `signalKinds`, `signalScanLimited` and `warningKind` (`source`, `instruction`, `suppressed-audit`). Stop records `trigger` (`no-instruction-signal`, `no-literal-overlap`, `literal-instruction-overlap`), `recheckRequested` and `semanticCompliance: "not-assessed"`. The existing 12-character normalized overlap and host-marked continuation bound remain; a recheck is neither permanent refusal nor proof of correction.
|
|
581
|
+
|
|
582
|
+
The repository helper `scripts/selection-probe/audit_warnings.mjs` replays saved hook inputs and answers. Acknowledgement candidate words describe visible text, not model awareness or obedience. Replaying an old answer measures hook behavior only; changed choices require a new controlled model run.
|
|
583
|
+
|
|
584
|
+
Post/Stop warning text uses fixed sentences and opaque `source-` identifiers (the first 16 hex digits of SHA-256 of the tool name). It does not quote the detected instruction or repeat raw tool names, source URLs or paths. This limits promotion of source-controlled metadata through the warning channel; it does not make a model immune to the original tool result. The identifier permits correlation only and is not a verified package identity, pin or permission. Local logs can still contain source-authored metadata and must be treated as untrusted data.
|
|
585
|
+
|
|
586
|
+
**Fresh model comparison (2026-10-25):** On the same six known fixtures, the 720-answer interleaved run selected the injected target 48/48 unguarded, 44/48 and 46/48 with published 0.21.0 note/note+Stop, and 27/48 with either local candidate profile. Candidate clean baselines were 23/48 and 25/48. Clean-adjusted candidate-versus-published intervals are −8.3 to +60.4pp for note and +14.6 to +62.5pp for note+Stop. Twelve actual rechecks changed no selected IDs; three lost a visible warning reference. All IDs were admissible and genuine user preferences passed 30/30. These known cases, controlled tool-role bridge and whole-version comparison do not establish general protection or a separate Stop benefit. See [the complete fresh-run report](flow-guard-model-comparison-2026-10-25.md).
|
|
587
|
+
|
|
588
|
+
<!-- constraint-evidence-followup -->
|
|
589
|
+
|
|
590
|
+
[Deterministic answer evidence and disclosure continuity](flow-guard-constraint-evidence.md).
|
|
591
|
+
|
|
592
|
+
<!-- structured-answer-gate -->
|
|
593
|
+
|
|
594
|
+
[Host-owned answer gate](flow-guard-answer-gate.md): all constraints, bounded extra correction and buffered final delivery; structured data only.
|
|
595
|
+
|
|
596
|
+
<!-- structured-live-followup -->
|
|
597
|
+
|
|
598
|
+
[Live structured-model test](flow-guard-structured-model-2026-10-26.md): 96 valid first proposals and 64 controlled-seed repairs; separate denominators and limits.
|
|
599
|
+
|
|
600
|
+
<!-- prospective-holdout-followup -->
|
|
601
|
+
|
|
602
|
+
[Prospective new-fixture results](flow-guard-prospective-holdout-2026-10-26.md): 89/96 natural first proposals valid, five of seven repaired, two withheld; controlled repair 45/48. Separate post-hoc ranking/missing-set facts passed offline checks, without a new model run.
|
package/docs/flow-guard.ru.md
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
# Страж потоков: проверки вызовов после внешнего текста
|
|
2
2
|
|
|
3
|
+
<!-- final-ranking-witness -->
|
|
4
|
+
**[Финальное сравнение обратной связи, 26 октября](flow-guard-final-witness-2026-10-26.ru.md).** Во всех пяти ранее удержанных контекстах старое сообщение исправило 6/40 продолжений, явное сравнение выбранного и лучшего — 40/40. Правильные контроли сохранились 20/20 в каждой условной группе. Серия завершена на известных ошибках; это не новый holdout. Прежнее утверждение о проверке только офлайн уточнено этим результатом для ранжирования; эффективность сообщений о неполном наборе моделью пока не измерена.
|
|
5
|
+
<!-- /final-ranking-witness -->
|
|
6
|
+
|
|
3
7
|
> 🌐 [English](flow-guard.md) · **Русский** · [Español](flow-guard.es.md) · [Français](flow-guard.fr.md) · [中文](flow-guard.zh.md)
|
|
4
8
|
|
|
9
|
+
См. [границы измерений и подтверждение версии](scan-limits.ru.md): биллинг, закрепление пакетов, сравнение launcher и смысл счётчиков подтверждений.
|
|
10
|
+
|
|
5
11
|
Повторный аудит, 2026-10-23: бинарные данные `image`/`audio` в результатах инструментов больше не расходуют лимит текста: большое изображение перед текстом не скрывает подписи элементов, заголовки окон с именами файлов учётных данных и JSON в текстовых блоках. Экраны из результатов кликов и нажатий клавиш, включая действия `computer`, тоже обновляют карту. Простое подтверждение выполнения сохраняет предыдущую карту; результат действия только с изображением очищает её. Для исходящих аргументов исключения нет: секрет, замаскированный под бинарные данные, по-прежнему проверяется. Регрессионные тесты воспроизводят оба обхода через hooks и настоящий stdio-прокси. В локальных исходниках теперь также проверяются непрозрачные действия GUI, как описано ниже.
|
|
6
12
|
|
|
7
13
|
Эти исправления управления экраном входят в npm `0.21.0`. В npm `0.20.0` их не было.
|
|
8
14
|
|
|
15
|
+
## Первое review annotations и проверка ответа (локальный код, 2026-10-25)
|
|
16
|
+
|
|
17
|
+
Пользовательская 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 в аргументах вызова прав не дают.
|
|
18
|
+
|
|
19
|
+
Review запоминается только в текущем wrap для точных launch identity и полного снимка definitions. После согласия proxy дожидается старой проверки и отправляет новый list, затем повторно проверяет общий flow-риск до передачи вызова; drift, новый отказ/основание ask, отказ человека или отсутствие формы останавливают вызов. Неизменное нормальное основание ask допускает подтверждение. Это не атомарная транзакция относительно других proxies. Новый wrap спрашивает заново. Согласие на каждый чувствительный вызов, credential boundary и GUI guard действуют независимо. `audit` лишь пишет журнал, `off` отключает проверку. Это не проверка биллинга и не полный классификатор эффектов.
|
|
20
|
+
|
|
21
|
+
Известное неудобство: первоначальный precheck может уже потратить точное одноразовое правило `credentialEgress`. Повторный precheck после согласия консервативно отказывает даже для прежнего payload, а правило остаётся потраченным. Этот контроль учитывается как дополнительное неудобство, а не нормальный автоматический пропуск.
|
|
22
|
+
|
|
23
|
+
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; изменения локальные и не выпущены, исторические модельные результаты ниже не пересчитаны.
|
|
24
|
+
|
|
25
|
+
## Окна ключей (локальный код, 2026-10-25)
|
|
26
|
+
|
|
27
|
+
После Linux-сравнения 6/7/8 сильные окна остаются **8 для не-hex / 10 для hex**. Индекс теперь включает буквенно-цифровые окна до первой цифры после распознанных нормализованных префиксов провайдеров; исключения generic/DER и все старые хеши сохранены. Чтобы существующая сессия получила новые окна, credential нужно прочитать повторно. Шестисимвольные части внутри других слов при отсутствии совпадения по-прежнему останавливает общая граница подтверждения.
|
|
28
|
+
|
|
29
|
+
На 14 400 атакующих примерах 717 решений меняются с подтверждения на отказ; автоматического исполнения нет ни до, ни после. Решения на 7 680 обычных запросах на профиль не изменились: все требуют review по умолчанию, все проходят один раз с точными проверенными публичными правилами. На специально выбранном обычном тексте воспроизведены ложные жёсткие отказы при 6 и известный пример при 7; это не production-частота. [Исследование и сырые данные](../../docs/growth/warden-thresholds-2026-10-25.ru.md) разделяют совпадения подстрок, решения hooks и работу одного детектора. Изменение локальное, не выпущено.
|
|
30
|
+
|
|
9
31
|
## Граница учётных данных и закодированные фрагменты (локальный код, 2026-10-23)
|
|
10
32
|
|
|
11
33
|
После зарегистрированных чтения ключа и внешнего текста **каждый поддерживаемый исходящий/MCP-вызов требует `ask` до исполнения** (режим `deny` отказывает), независимо от длины части, кодировки, названного адресата и метки MCP «только чтение». Обычные записи в проект тоже проверяются; прежнее исключение для файлов учётных данных сохранено. Флаг `credentialRead` не сбрасывается при вытеснении старых источников или новом ходе пользователя. Так автоматическая передача частей по одному–четыре символа и неизвестных закодированных данных закрывается общей границей, а не обещанием декодировать что угодно.
|
|
@@ -292,10 +314,10 @@ node dist/mcp-server.js wrap --flow screen --screen-read computer --screen-read-
|
|
|
292
314
|
- Адрес, который есть в запросе только во вставленном тексте, в цитате (`>`), в заголовках вставленного письма или ниже пометки о пересылке, не считается названным: отправка на него спрашивает один раз. Точка или запятая после набранного адреса больше не мешают его узнать.
|
|
293
315
|
- MCP-инструмент без метки оператора считается исходящим, если об этом говорит его имя (send, post, share …), если в аргументах есть URL или, с 2026-10-22, если он называет адресата: аргумент вроде `to`, `email`, `attendees`, `assignee`, `collaborator` или `username`, либо любой e-mail или IBAN. `warden-mcp flow-labels` показывает MCP-инструменты без меток, которыми пользовались ваши сессии, с догадкой стража и блоком `labels`, который нужно проверить и вставить в политику.
|
|
294
316
|
- По умолчанию после внешних данных распознанные действия управления экраном требуют подтверждения независимо от координат, текста скриншота, формата списка элементов и языка подписи. Это клики/тапы/перетаскивания, ввод и заполнение полей, вставка, Enter/Return и неизвестные нажатия клавиш. `deny` отказывает. Английские слова уточняют объяснение; привычная подпись вроде Inbox не разрешает клик. Подробности — в ограниченном режиме задач выше.
|
|
295
|
-
- Инъекция, которая меняет только ответ, не делает вызова, которому можно отказать. С 2026-10-22 хук Stop плагина добавляет под ответом строку, если за этот ход читался внешний текст: какие источники, и отдельно — если какой-то из них обращался к ассистенту с указаниями. Если ответ повторяет 12
|
|
317
|
+
- Инъекция, которая меняет только ответ, не делает вызова, которому можно отказать. С 2026-10-22 хук Stop плагина добавляет под ответом строку, если за этот ход читался внешний текст: какие источники, и отдельно — если какой-то из них обращался к ассистенту с указаниями. Если ответ повторяет 12 нормализованных символов подряд из тех предложений, где внешний текст обращался к ассистенту, хук ещё и один раз возвращает ответ модели (`decision: block`) на проверку по запросу пользователя, прежде чем пользователь его прочтёт; пользователь теряет только время этой проверки. `answerNote`: `always` (по умолчанию), `instruction` (только этот случай) или `off`; вне плагина зарегистрируйте `warden-mcp hook stop`.
|
|
296
318
|
- Прокси учитывает текст JSON-RPC errors и ошибки инструментов как внешние данные. Если учёт ответа не удался, ответ удерживается. Повреждённое состояние сессии блокирует проверяемый вызов вместо сброса в пустую сессию.
|
|
297
319
|
|
|
298
|
-
Вышло в npm `0.17.0`: `npx -y @aimarket/warden@0.
|
|
320
|
+
Вышло в npm `0.17.0`: `npx -y @aimarket/warden@0.22.1 hook pre-tool-use`, либо из исходников — в каталоге WARDEN `npm ci && npm run build`, затем `node dist/mcp-server.js hook pre-tool-use`. Зарегистрируйте также prompt/post hooks либо плагин Claude.
|
|
299
321
|
|
|
300
322
|
Политика: `~/.local/state/warden/flow-policy.json` или `WARDEN_FLOW_POLICY`. Режимы: `ask`, `deny`, `audit`, `off`; `audit` только пишет журнал. Пример настройки контактов и адресатов — в [английской версии](flow-guard.md).
|
|
301
323
|
|
|
@@ -470,10 +492,16 @@ Sonnet; в воспроизведении выше модели нет, а пр
|
|
|
470
492
|
| Части, общие для всех ключей одного вида, не снимаются (идентификатор алгоритма в DER-ключе, заголовок и поля JWT) | замер нашёл, что 0.19.0 запретил бы отправку README с DKIM-ключом после того, как сессия прочитала RSA-ключ | с правилами в релизе ни одного случайного совпадения |
|
|
471
493
|
| Ключ, прочитанный в сессии, при записи в обычный файл проекта требует подтверждения | ключ в `docs/debug.md` проходил | спрашивает; `.env` и другие файлы с секретами по-прежнему проходят |
|
|
472
494
|
| Адрес только во вставленном или цитируемом тексте не считается названным | адрес атакующего, вставленный в запрос, считался адресом пользователя | спрашивает один раз; адрес, который пользователь ещё и набрал, проходит. Точка после набранного адреса больше не делает его неназванным (0.19.0 спрашивал про «отправь на bob@corp.com.») |
|
|
473
|
-
| Хук Stop один раз возвращает ответ, повторяющий указание для модели | инъекция только в ответ не делает вызовов | На Ministral 8B, который атаке подчиняется (без стража 6 ответов из 20 рекомендуют отель), уже одна пометка стража свела это к 0; перепроверка сработала 3 раза из 20 и исход не изменила. На DeepSeek V4.1 Flash
|
|
495
|
+
| Хук Stop один раз возвращает ответ, повторяющий указание для модели | инъекция только в ответ не делает вызовов | На Ministral 8B, который атаке подчиняется (без стража 6 ответов из 20 рекомендуют отель), уже одна пометка стража свела это к 0; перепроверка сработала 3 раза из 20 и исход не изменила. На DeepSeek V4.1 Flash — 2 раза из 20 ([результаты](../scripts/agentdojo/results/model-answer-recheck-2026-10-22.json)). Страховка, а не измеренный выигрыш; ограничение сохранённых ответов указано ниже |
|
|
474
496
|
| Набор правил v16 (см. [gates](gates.ru.md)) | 34 отравленных инструмента dev-половины MCPTox всё ещё проходили, почти все — без входных параметров | отложенная половина 194 → 210 из 218, в том числе все 66 перехватов с неявным триггером; 0 из 45 чистых серверов; корпус и 1 000 пакетов HISTOR блокируются ровно как при v15; пять ложных срабатываний первого варианта закреплены в тестах |
|
|
475
497
|
| Воспроизведение заново | новые проверки не должны спрашивать там, где не спрашивал 0.19.0 | все 1 046 записей совпадают с 0.19.0 |
|
|
476
498
|
|
|
499
|
+
**Уточнение сохранённых ответов (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).
|
|
500
|
+
|
|
501
|
+
**Контролируемый выбор (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** и не доказывающий общую безопасность.
|
|
502
|
+
|
|
503
|
+
**Продолжение с ничьей (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).
|
|
504
|
+
|
|
477
505
|
В релизе 2026-10-22 эти два примера ещё проходили. В локальном коде 2026-10-23 оба блокируются; см. новый раздел выше. Исторические [результаты](../scripts/redteam/results/):
|
|
478
506
|
|
|
479
507
|
- **Куски короче 8 символов, каждый в других словах**, на адрес, который набрал пользователь: 7 и больше писем на
|
|
@@ -510,7 +538,7 @@ docker run --rm --network none -v "$PWD/out:/out" warden-adojo /out/oracle.json
|
|
|
510
538
|
|
|
511
539
|
`oracle.py` пишет результаты по каждой паре; `--variants none,strict,intent` выбирает варианты стража (`strict`
|
|
512
540
|
не учитывает, что набрал пользователь). `summarize_oracle.py` сводит их в то, что цитирует таблица.
|
|
513
|
-
`WARDEN_FLOW_GUARD=/out/x.mjs` проигрывает другую сборку стража (любую копию `flow-guard.mjs` из
|
|
541
|
+
`WARDEN_FLOW_GUARD=/out/x.mjs` проигрывает другую сборку стража (любую копию `flow-guard.mjs` из плагина; с 2026-10-24 вместе с частями `flow-guard-*.mjs` в той же папке) — так
|
|
514
542
|
изменения 2026-10-22 сравнивали с кодом до них.
|
|
515
543
|
|
|
516
544
|
Атакам со знанием кода контейнер не нужен: `npm run build && node scripts/redteam/flow-redteam.mjs out.json`.
|
|
@@ -528,3 +556,31 @@ python3 scripts/agentdojo/summarize_model.py summary.json /srv/adojo/out --goals
|
|
|
528
556
|
`WORK/ctx` — контекст сборки (`dist/` и `scripts/agentdojo/`); `--obedient` добавляет абзац перехвата;
|
|
529
557
|
`model.py OUT --model deepseek-flash --model-label DeepSeek --dump-goals` пишет цели атакующего, по которым
|
|
530
558
|
`summarize_model.py` узнаёт вызовы в его адрес. Записи по каждому прогону обоих раундов: `results/model-deepseek-2026-10-18b.jsonl.gz` (сводка `model-deepseek-2026-10-18b.json`); `--guard-note` возвращает модели пометку стража.
|
|
559
|
+
|
|
560
|
+
## Сигналы инструкций и диагностика Stop (локальная 0.22.0)
|
|
561
|
+
|
|
562
|
+
Ограниченные английские/русские шаблоны распознают поддельные границы ролей, якобы переданные предпочтения или прежние согласования вместе с близкой директивой, скрываемые инструкции и частные критерии оценки. Это неточные сигналы во внешнем тексте, включая обычные цитаты: они не доказывают атаку, не дают полномочий и не запрещают выбор автоматически. Настоящий запрос пользователя остаётся отдельным источником.
|
|
563
|
+
|
|
564
|
+
Локальный журнал содержит `instructionSignal`, `signalKinds`, `signalScanLimited` и `warningKind` (`source`, `instruction`, `suppressed-audit`). Stop записывает `trigger` (`no-instruction-signal`, `no-literal-overlap`, `literal-instruction-overlap`), `recheckRequested` и `semanticCompliance: "not-assessed"`. Сохраняются порог совпадения 12 нормализованных символов и ограничение продолжения флагом хоста. Перепроверка не является постоянным отказом или доказательством исправления.
|
|
565
|
+
|
|
566
|
+
Помощник репозитория `scripts/selection-probe/audit_warnings.mjs` повторяет сохранённые hook-входы и ответы. Слова-кандидаты признания предупреждения описывают видимый текст, а не осведомлённость или послушание модели. Повтор старого ответа измеряет только hook; изменение выбора требует нового контролируемого модельного прогона.
|
|
567
|
+
|
|
568
|
+
Текст предупреждений Post/Stop состоит из фиксированных фраз и непрозрачных ID `source-` (первые 16 hex-символов SHA-256 имени инструмента). В нём не цитируются найденная инструкция, сырые имена инструментов, URL и пути источника. Это ограничивает перенос чужих метаданных в канал предупреждения, но не защищает модель от любого влияния исходного tool result. ID предназначен только для сопоставления: он не является проверенной версией пакета, pin или разрешением. Локальные журналы могут содержать чужие метаданные и остаются недоверенными данными.
|
|
569
|
+
|
|
570
|
+
**Свежий прогон модели (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).
|
|
571
|
+
|
|
572
|
+
<!-- constraint-evidence-followup -->
|
|
573
|
+
|
|
574
|
+
[Детерминированные факты для проверки ответа и сохранение раскрытия](flow-guard-constraint-evidence.ru.md).
|
|
575
|
+
|
|
576
|
+
<!-- structured-answer-gate -->
|
|
577
|
+
|
|
578
|
+
[Проверка ответа приложением](flow-guard-answer-gate.ru.md): все ограничения, дополнительный ограниченный проход и буферизация выдачи; только структурированные данные.
|
|
579
|
+
|
|
580
|
+
<!-- structured-live-followup -->
|
|
581
|
+
|
|
582
|
+
[Живой прогон структурированных ответов](flow-guard-structured-model-2026-10-26.ru.md): 96 правильных первых предложений и 64 исправления контролируемых ошибок; отдельные знаменатели и границы.
|
|
583
|
+
|
|
584
|
+
<!-- prospective-holdout-followup -->
|
|
585
|
+
|
|
586
|
+
[Новые случаи после заморозки](flow-guard-prospective-holdout-2026-10-26.ru.md): 89/96 первых естественных ответов правильны, пять из семи ошибок исправлены, два удержаны; контролируемые 45/48. Отдельные подсказки ранжирования/неполного списка проверены офлайн, без нового запуска модели.
|