# 诊断与限制

[返回 README](../README.md) · [传输原理](notifications.md) · [配置](configuration.md)

## 从哪里开始？

```text
/pi-notify status
/pi-notify test             # 仅 bell + terminal，不发 webhook
/pi-notify test bell
/pi-notify test terminal
/pi-notify test webhook     # 显式外发，必须配置并启用
/pi-notify test all         # 显式允许所有已启用通道
```

这些是用户命令，不是模型工具。测试不会越过 enabled 或 TUI/TTY 限制。status 显示配置来源、隐私开关、通道状态、已解析请求头数量、队列和计数，不显示 URL、请求头值或 JSON 模板。

### 常见结果

| 结果 | 含义 / 下一步 |
| --- | --- |
| `disabled` | 通道未开启，或因配置错误而关闭 |
| `outside-tmux` | BEL 仅在 tmux 中发送；其他通道不受影响 |
| `protocol-off-or-unknown` | terminal 关闭、protocol=off，或 auto 无法识别终端 |
| `passthrough-needs-all` | 当前 pane 不可见，而有效透传设置只有 on |
| `passthrough-off-or-unknown` | tmux 不允许透传或不支持该选项 |
| `tmux-query-failed` | tmux 命令失败，检查 PATH、版本、来源 pane 是否仍存在 |
| `http-401` | webhook 拒绝身份验证；检查请求头引用的环境变量和服务端权限 |
| `timeout` | 请求超时，不能排除服务端已接收 |
| `stale` | 来源 run、prompt 或 session 已失效，主动丢弃 |
| `queue-full` | 队列已满，丢弃最旧待发项 |
| `tty-backpressure` | 终端写入积压，为避免阻塞而跳过 |
| `written` / `http-2xx` | 已写出 / 服务端接受，不是用户已看到的回执 |

如果显示 inactive，先 `/reload`。配置文件修改可 reload；环境变量修改需重启 Pi。

## 不使用 tmux

支持直接在本地终端或 SSH 远程 shell 中运行 Pi，tmux 不是必需条件。需要满足以下条件：

- Pi 以 TUI 模式运行，标准输出是交互式 TTY；管道、重定向、后台无终端运行不启用通知运行时。
- terminal 通道将 OSC 777 直接写到当前终端。远程运行时，控制序列经 SSH 到达本地终端，因此需要本地终端支持 OSC 777 并具有系统通知权限。
- webhook 的发送链路不依赖 tmux、终端控制序列或持续的 SSH 连接；但插件仍只在 TUI/TTY 模式初始化，而且 Pi 进程必须保持运行。
- bell 只用于 tmux 窗口标记；`outside-tmux` 是预期跳过，不影响 terminal 或 webhook。通知正文也会省略 tmux 位置。

先运行 `/pi-notify test terminal` 验证桌面通道；需要同时检查已启用通道时运行 `/pi-notify test all`。

## tmux：窗口标记和桌面通知是两回事

本包不安装 tmux 配置。需要后台 window 桌面通知及 bell flag 时，自行检查用户配置：

```tmux
set -g allow-passthrough all
setw -g monitor-bell on

# 可选：独立于任何主题的 bell 标记样式。
setw -g window-status-bell-style "fg=red,bold"
```

请通过自己的配置加载流程应用。插件不自动 source tmux.conf。

- 原生 BEL 不包透传；OSC 才包 tmux DCS。
- `allow-passthrough on` 只允许可见 pane；后台窗口需要 `all`。`all` 扩大了不可见 pane 程序对本地终端的影响面，只对可信程序开启。
- 插件使用 `show-options -A -p -v` 检查继承后的有效值。off 或查询失败只影响 terminal 通道。`on` 的可见性检查复用同次通知查询的窗口 ID，避免重复创建查询进程；权限和客户端列表每次重新读取，不做跨事件缓存。
- `bell-action` / `visual-bell` 决定声音与提示；插件不会修改。可自行使用 `bell-action none` 保留 flag 而不响铃。
- tmux 的 flag 是窗口级，不是 pane 级。同一已附着窗口中的另一 pane 不一定获得 bell flag，插件不伪造高亮；切回来源窗口后由 tmux 清除。
- 多层 tmux 不支持。不要用当前真实会话测试未经确认的透传控制序列。

## 桌面没有弹窗，但显示 written

1. 确认本地终端支持 OSC 777 notify：WezTerm / Ghostty；后者还需允许 `desktop-notifications`。
2. 检查操作系统通知权限、勿扰模式及终端自己的通知策略。
3. 在 tmux 中，检查 `allow-passthrough` 是否对来源 pane 生效；on 在窗口不可见或 pane 被 zoom 隐藏时不够。
4. 确认 SSH 未断开且当前仍有 TTY 接收字节；若在 tmux 中，还需有 attached client。没有终端接收这些字节时，桌面通道不可靠，可使用独立的 webhook 通道。

不支持 Kitty OSC 99、iTerm2 OSC 9、foot 专用协议或 Windows toast。显式 osc777 不会自动回退。OSC 没有桌面显示回执，所以 written 不能进一步判断通知被谁拦截。

插件不判断桌面焦点，也不会把 tmux active pane 当成“你正在看”。当前版本总是按事件尝试通知，多个客户端可能各显示一份。

## 队列和日志

webhook 并发最多 2、等待最多 16；bell/terminal 各自并发 1、等待最多 16。队列满时丢最旧待发项，不持久化、不自动 retry。新 run、prompt 关闭或 session 切换会使相应通知失效；已发送的通知不能撤回。弹窗打断 settled 的发送准备时，关闭后可以恢复未尝试的通道，这不是对失败发送的重试。通道相互隔离，网络请求不会挡住终端写入。

`debug: true` 时写入 `${XDG_CACHE_HOME:-~/.cache}/pi-notify/debug-<pid>.log`：

- 只有时间、channel、status 和固定错误代码。
- 每会话最多 256 行，同一 channel/status/code 至少间隔 30 秒。
- 每进程文件约 64KiB 封顶，无常驻日志定时器；可手动删除旧日志。
- 默认不会因普通网络失败反复弹窗。

## 手工验收清单

自动测试不等于实际桌面验收。以下场景仍需在你的终端与服务环境验证：

1. **完成/停止**：Pi 在窗口 A 工作，切 B，结束后检查 A bell flag 与桌面通知；回 A 检查清除。通知不代表任务成功。
2. **等待操作**：让第三方扩展弹出问题，切 B，确认收到“Pi 需要你的操作”；默认不应包含标题。
3. **tmux 外**：直接从 TTY 启动 Pi，`test all`，bell 跳过，其余按配置工作。
4. **webhook 异常**：仅使用测试服务验证错误凭据、模板、超时和终端通道隔离，不修改生产服务权限。
5. **终端策略**：检查 off/on/all、系统权限与勿扰模式。
6. **生命周期**：retry、compaction retry、queued follow-up 期间不提前报等待输入；同标题不同问题可分别通知，嵌套为一个外层区间。
7. **清理**：有待发任务时 `/reload`、`/new`、`/resume`、`/fork`、退出，确认没有旧会话通知或重复实例。
8. **并发与隐私**：多个 Pi 可根据项目/位置或可选详细信息区分；确认默认内容和日志无秘密。

已自动覆盖的范围见 [开发与测试](development.md)，不要把缺少环境而跳过的测试算作通过。
