diff --git a/.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml b/.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml
index 6b8dc5e1c0..07e39db02d 100644
--- a/.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml
+++ b/.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml
@@ -18,8 +18,8 @@
en: a6d7884e4359af3a
zh: e72588705942000a
/agent-note-the-approval-seam-one-shot-permission-decisions-over-a-waterfall-of-answerers/decision/design-detail/the-seam-mechanism-and-policy-split:
- en: 0aa6f3a90921d1ea
- zh: c4a734f84800dae8
+ en: 53da7800d8744d9e
+ zh: 316fef884853ca5d
/agent-note-the-approval-seam-one-shot-permission-decisions-over-a-waterfall-of-answerers/decision/design-detail/ask-routing-in-dsh-tools:
en: 1d4478059f608fd2
zh: 4a1d12e4ccb766b5
diff --git a/.agents/notes/implemented/feature/2026-07-06-approval-seam.md b/.agents/notes/implemented/feature/2026-07-06-approval-seam.md
index 03a4269dd7..bb44957b6d 100644
--- a/.agents/notes/implemented/feature/2026-07-06-approval-seam.md
+++ b/.agents/notes/implemented/feature/2026-07-06-approval-seam.md
@@ -55,7 +55,7 @@ After validation and a successful `approval/asked` append, the service resolves
Answerers are `approval/request` waterfall listeners. Zero listeners fall through to `unavailable`; a recognizing listener occupies the first-wins decision slot, while an unrecognized agent must delegate with `next()`. Listeners dispose with their fibers, so an unloaded channel fails closed. Because sibling registration order is not deterministic, a deployment composes one terminal answerer and reserves `prepend` for decide-or-delegate gates.
-`ApprovalRequest` carries the asking `agent`, `toolName`, optional exact `callId`, human-readable `reason`, and optional `signal`. It uses the `ToolCallId` brand without importing `dsh-tools`, which depends on this seam. Channel adapters correlate any richer call state by `callId`; the approval request does not duplicate tool arguments.
+`ApprovalRequest` carries the asking `agent`, `toolName`, optional exact `callId`, human-readable `reason`, optional localized `displayReason`, and optional `signal`. It uses the `ToolCallId` brand without importing `dsh-tools`, which depends on this seam. Channel adapters correlate any richer call state by `callId`; the approval request does not duplicate tool arguments.
#### Ask routing in dsh-tools
diff --git a/.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md b/.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md
index f11e0956c9..b7e07a376c 100644
--- a/.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md
+++ b/.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md
@@ -55,7 +55,7 @@ tool/result "escalated" — this one call ran under the wider mode; the gra
应答者是 `approval/request` waterfall 监听器。零监听器会直接落到 `unavailable`;识别该 agent 的监听器占用先到先得的决策槽,而不识别的监听器必须调用 `next()` 委派。监听器会随其 fiber 一同 dispose(资源释放),因此卸载通道后,请求会在故障时默认被拒绝。由于兄弟插件的注册顺序不确定,部署应组合一个终端应答者,并保留 `prepend` 给「决策或委派」门禁。
-`ApprovalRequest` 携带发起请求的 `agent`、`toolName`、可选的精确 `callId`、人类可读的 `reason` 和可选的 `signal`。它使用 `ToolCallId` brand 而不导入依赖本 seam 的 `dsh-tools`。通道适配器可按 `callId` 关联任何更丰富的调用状态;审批请求本身不重复携带工具参数。
+`ApprovalRequest` 携带发起请求的 `agent`、`toolName`、可选的精确 `callId`、人类可读的 `reason`、可选的本地化 `displayReason` 和可选的 `signal`。它使用 `ToolCallId` brand 而不导入依赖本 seam 的 `dsh-tools`。通道适配器可按 `callId` 关联任何更丰富的调用状态;审批请求本身不重复携带工具参数。
#### dsh-tools 中的 Ask 路由
diff --git a/docs/event-producer-consumer.md b/docs/event-producer-consumer.md
index bafab73675..5312354d60 100644
--- a/docs/event-producer-consumer.md
+++ b/docs/event-producer-consumer.md
@@ -28,7 +28,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
| `api-session/removed` | `emit` | [`packages/api/session-controller/src/types.ts:597`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:604`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
| `app-boot/config-reload` | `emit` | [`packages/boot/app-boot/src/index.ts:52`](../packages/boot/app-boot/src/index.ts) | [`app-boot`](../packages/boot/app-boot) (`emit`) | [`settings`](../packages/settings/settings) |
-| `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/types.ts:85`](../packages/interaction/user-approval/src/types.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `remotes` |
+| `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/types.ts:87`](../packages/interaction/user-approval/src/types.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `remotes` |
| `authorization/settled` | `emit` | [`packages/credentials/authorization/src/index.ts:57`](../packages/credentials/authorization/src/index.ts) | [`authorization`](../packages/credentials/authorization) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization) |
| `commands/change` | `emit` | [`packages/interaction/commands/src/types.ts:89`](../packages/interaction/commands/src/types.ts) | [`commands`](../packages/interaction/commands) (`events.dispatch`) | `remotes` |
| `compaction/summary-error` | `waterfall` | [`packages/compaction/compaction/src/index.ts:106`](../packages/compaction/compaction/src/index.ts) | [`compaction-basic`](../packages/compaction/compaction-basic) (`waterfall`) | [`compaction-image-offload`](../packages/compaction/compaction-image-offload) |
diff --git a/docs/event-producer-consumer.zh.md b/docs/event-producer-consumer.zh.md
index faa7c6b3b6..6baa07d2d2 100644
--- a/docs/event-producer-consumer.zh.md
+++ b/docs/event-producer-consumer.zh.md
@@ -30,7 +30,7 @@
| `api-session/removed` | `emit` | [`packages/api/session-controller/src/types.ts:597`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:604`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
| `app-boot/config-reload` | `emit` | [`packages/boot/app-boot/src/index.ts:52`](../packages/boot/app-boot/src/index.ts) | [`app-boot`](../packages/boot/app-boot) (`emit`) | [`settings`](../packages/settings/settings) |
-| `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/types.ts:85`](../packages/interaction/user-approval/src/types.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `remotes` |
+| `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/types.ts:87`](../packages/interaction/user-approval/src/types.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `remotes` |
| `authorization/settled` | `emit` | [`packages/credentials/authorization/src/index.ts:57`](../packages/credentials/authorization/src/index.ts) | [`authorization`](../packages/credentials/authorization) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization) |
| `commands/change` | `emit` | [`packages/interaction/commands/src/types.ts:89`](../packages/interaction/commands/src/types.ts) | [`commands`](../packages/interaction/commands) (`events.dispatch`) | `remotes` |
| `compaction/summary-error` | `waterfall` | [`packages/compaction/compaction/src/index.ts:106`](../packages/compaction/compaction/src/index.ts) | [`compaction-basic`](../packages/compaction/compaction-basic) (`waterfall`) | [`compaction-image-offload`](../packages/compaction/compaction-image-offload) |
diff --git a/docs/subsystems/approval.i18n.yaml b/docs/subsystems/approval.i18n.yaml
index d11fac4c66..ebdb2ead96 100644
--- a/docs/subsystems/approval.i18n.yaml
+++ b/docs/subsystems/approval.i18n.yaml
@@ -12,8 +12,8 @@
en: 5e51c6e37c5e30c3
zh: 84bad36357332539
/user-approval/approval-request:
- en: dc3647525133ff2f
- zh: 8365b809a93ec81d
+ en: 044ddfc382eb745c
+ zh: c0010b23c94ab3af
/user-approval/dispatch-and-audit:
en: bd2c2cc1eaaaf2d6
zh: 67bfbed1b7499ffb
diff --git a/docs/subsystems/approval.md b/docs/subsystems/approval.md
index 656325aa44..5a2513775a 100644
--- a/docs/subsystems/approval.md
+++ b/docs/subsystems/approval.md
@@ -50,7 +50,7 @@ Both policies contribute their complete current meaning to the cache-safe runtim
## Approval request
-`ApprovalRequest` identifies the agent and tool action closely enough to route and audit the question. It deliberately omits tool arguments: an answerer attaches the prompt to the already-streamed tool call through `callId` instead of rendering a second copy that could drift.
+`ApprovalRequest` identifies the agent and tool action closely enough to route and audit the question. It deliberately omits tool arguments: an answerer attaches the prompt to the already-streamed tool call through `callId` instead of rendering a second copy that could drift. Optional `displayReason` carries requester-owned locale strings to presentation; `reason` remains the audit text.
```ts type-equiv
/**
diff --git a/docs/subsystems/approval.zh.md b/docs/subsystems/approval.zh.md
index a22aec2ef2..74aa7fbfc1 100644
--- a/docs/subsystems/approval.zh.md
+++ b/docs/subsystems/approval.zh.md
@@ -50,7 +50,7 @@ type ApprovalPolicy = 'ask' | 'never'
## 审批请求
-`ApprovalRequest` 以足够精确的方式标识 agent 和工具操作,以便路由和审计该问题。它有意省略工具参数:应答者通过 `callId` 将提示附加到已流式输出的工具调用上,而非渲染另一份可能漂移的副本。
+`ApprovalRequest` 以足够精确的方式标识 agent 和工具操作,以便路由和审计该问题。它有意省略工具参数:应答者通过 `callId` 将提示附加到已流式输出的工具调用上,而非渲染另一份可能漂移的副本。可选的 `displayReason` 向界面传递请求方提供的本地化字符串;`reason` 仍是审计文本。
```ts type-equiv
/**
diff --git a/docs/tool-catalog.md b/docs/tool-catalog.md
index ba5cf0f276..d92c8d583f 100644
--- a/docs/tool-catalog.md
+++ b/docs/tool-catalog.md
@@ -551,7 +551,7 @@ Execute a TypeScript program against the available tools. Takes two required arg
},
"justification": {
"type": "string",
- "description": "Reason this complete program needs wider access, shown to the user for approval."
+ "description": "Reason this complete program needs wider access, shown to the user for approval. Use the language of the user’s current request."
}
},
"required": [
diff --git a/docs/tool-catalog.zh.md b/docs/tool-catalog.zh.md
index b0b7f2944f..9c05b6f477 100644
--- a/docs/tool-catalog.zh.md
+++ b/docs/tool-catalog.zh.md
@@ -555,7 +555,7 @@ ask_user_question 会暂停工具调用,直到当前 UI 提供方返回人类
},
"justification": {
"type": "string",
- "description": "Reason this complete program needs wider access, shown to the user for approval."
+ "description": "Reason this complete program needs wider access, shown to the user for approval. Use the language of the user’s current request."
}
},
"required": [
diff --git a/packages/client/ui-approval/README.i18n.yaml b/packages/client/ui-approval/README.i18n.yaml
index efbfdf2cb6..7fef3ae2d8 100644
--- a/packages/client/ui-approval/README.i18n.yaml
+++ b/packages/client/ui-approval/README.i18n.yaml
@@ -21,8 +21,8 @@
en: adf7112e0691b89e
zh: 14eeddcff985119f
/deepseek-ai-dsh-client-ui-approval/known-limitations-and-deferred-work:
- en: 158f435625e41ca9
- zh: 9d58169aaf6c7ed7
+ en: ae644102ed52f7ee
+ zh: e109de1d517a3a94
/deepseek-ai-dsh-client-ui-approval/known-limitations-and-deferred-work/dev-note:
en: 240c92ce5e544116
zh: 5bfae598cc20a3af
diff --git a/packages/client/ui-approval/README.md b/packages/client/ui-approval/README.md
index ce2ccdbbec..4986683615 100644
--- a/packages/client/ui-approval/README.md
+++ b/packages/client/ui-approval/README.md
@@ -33,7 +33,7 @@ None; approval request and response rendering does not alter a model request.
-- **The panel exposes transient decisions only** — it supports allow-once and reject; persistent permission policy remains owned by Host-side approval packages.
+- **The panel exposes transient decisions only** — it supports allow-once and reject; persistent permission policy remains owned by Host-side approval packages. Requester-supplied localized presentation copy follows the UI language without changing the audit reason or translating model-generated text.
diff --git a/packages/client/ui-approval/README.zh.md b/packages/client/ui-approval/README.zh.md
index d7a94ae915..7015ba5f44 100644
--- a/packages/client/ui-approval/README.zh.md
+++ b/packages/client/ui-approval/README.zh.md
@@ -33,7 +33,7 @@ kind: "package-reference"
-- **面板只提供临时决定**——它支持仅本次允许和拒绝;持久权限策略仍由 Host 侧审批包拥有。
+- **面板只提供临时决定**——它支持仅本次允许和拒绝;持久权限策略仍由 Host 侧审批包拥有。请求方提供的本地化展示文案跟随界面语言,不改写审计原因,也不翻译模型生成的文本。
diff --git a/packages/client/ui-approval/src/client/ApprovalPanel.tsx b/packages/client/ui-approval/src/client/ApprovalPanel.tsx
index 9dce13573c..bdfcba3f02 100644
--- a/packages/client/ui-approval/src/client/ApprovalPanel.tsx
+++ b/packages/client/ui-approval/src/client/ApprovalPanel.tsx
@@ -14,11 +14,13 @@ export function ApprovalPanel(props: ApprovalComposerProps) {
const detail = approval.callId === undefined
? null
: props.renderSlot('conversation.approval.detail', { callId: approval.callId })
- return