Skip to content

feat(agenttui): a pane can self-report its own id, so §5.0's root rule can finally pass - #60

Open
JasonJarvan wants to merge 1 commit into
mainfrom
pane-self-report-clean
Open

feat(agenttui): a pane can self-report its own id, so §5.0's root rule can finally pass#60
JasonJarvan wants to merge 1 commit into
mainfrom
pane-self-report-clean

Conversation

@JasonJarvan

Copy link
Copy Markdown
Owner

那条根规则此前只能拒,不能过

§5.0:「凡自识别证据不足以唯一确定该 pane ⇒ 拒绝写入」。在此之前它只能拒 —— 没有任何东西产出足够强的证据,于是「正确」的路径根本不存在,只剩「被拒」和「猜」。

多路复用器把 pane id 注入每个 pane 的进程环境,产出的正是那种证据,而且按构造正确:不是推断的、不是从显示标题匹配的、也不是从一份可能指到别人 pane 的列举里挑的。

关键区别:自查询答「是哪个 pane」,这一问不因别处的歧义而失真;读列举答「有哪些 pane」,再按标题挑一个就是根规则禁止的猜 —— 标题是显示名,而真实发生过的那次,陈旧 ref 指向的是一个活着、且属于别人的 pane,id 看起来完全合理。

改了什么

  • PaneTransport.self_pane_ref() 新增,默认 None —— 新 transport 忘了实现时方向是「未知」,不是崩、也不是编一个。
  • zellij:ZELLIJ_SESSION_NAME + ZELLIJ_PANE_ID,不跑任何命令。裸整数规范化为 terminal_<n>:两种形态写路径都收(--pane-id 的帮助原文 eg. terminal_1, plugin_2 or 3 (equivalent to terminal_3)),但核验拿存的值去比 list-panes 的字符串输出 —— 存裸形态会让投递可用而核验拒绝,即一个好着的 pane 被 fail-closed。已带 kind 前缀的值原样透传(改写它就是本方法在发明 id)。
  • tmux:TMUX_PANE + display-message -p -t 的自查询 + $TMUX 的 socket 维度。
  • self_reported_pane_ref():歧义即拒。 嵌套多路复用器时两边都报 pane,挑一个就是猜,而猜错产出的 ref 会解析到别人的活 pane
  • heartbeat 无条件写入自报值,缺失时清空而非保留。 方向不对称:缺失把投递降级为 no-operational-route(可见、fail-closed);陈旧则往一个活着且属于别人的 pane 打字。实测依据:一次机器迁移后,各 leaf 携带前一台主机的 id,而同名会话在新机是活的 —— 那些 ref 每一个都解析成功了,解析到了错的 pane。由此确立的契约写在代码注释里:心跳要在 agent 自己的 pane 里跑。

一处既有门抓到我,而它的判据是枚举式的

test_the_only_property_read_is_a_self_query_without_a_target 断言 display-messageTmuxTransport 里出现恰好一次。那个计数是「每个调用点都必须是自查询」这条真属性的代理,而代理是枚举式的:我加了第二个同样合法的自查询,它就炸了,却没有违反任何东西。

1 改成 2 是错的 —— 那只是保留代理并重新调准,把枚举从一处搬到另一处。改成 AST 解析:找出每一条提到该命令的 argv,要求没有一条带 -t,并加「解析不到就算空转」的非空转保护。于是任意数量的自查询都被容许,而规则真正管的那件事(带 -t 时静默回落到当前 pane,使缺失的 pane 看起来存在)仍被拒。

读数

🤖 Generated with Claude Code

…e can finally pass

§5.0 的根规则是「凡自识别证据不足以唯一确定该 pane ⇒ 拒绝写入」。在此之前它**只能拒** ——
没有任何东西产出足够强的证据,于是「正确」的路径根本不存在,只剩「被拒」和「猜」。

多路复用器把 pane id 注入每个 pane 的进程环境,产出的正是那种证据,而且**按构造正确**:
不是推断的、不是从显示标题匹配的、也不是从一份可能指到别人 pane 的列举里挑的。

关键区别:自查询答「我是哪个 pane」,这一问不因别处的歧义而失真;读列举答「有哪些 pane」,
再按标题挑一个就是根规则禁止的猜 —— 标题是显示名,而真实发生过的那次,陈旧 ref 指向的是
一个活着、且属于别人的 pane,id 看起来完全合理。

## 改了什么

- `PaneTransport.self_pane_ref()` 新增,默认 None(新 transport 忘实现时方向是「未知」,
  不是崩、不是编一个)。
- zellij:`ZELLIJ_SESSION_NAME` + `ZELLIJ_PANE_ID`,**不跑任何命令**。裸整数规范化为
  `terminal_<n>`:两种形态写路径都收,但**核验**拿存的值去比 `list-panes` 的字符串输出 ——
  存裸形态会让投递可用而核验拒绝,即一个好着的 pane 被 fail-closed。已带 kind 前缀的值
  原样透传(改写它就是本方法在发明 id)。
- tmux:`TMUX_PANE` + `display-message -p` **无 `-t`** 的自查询 + `$TMUX` 的 socket 维度。
- `self_reported_pane_ref()`:**歧义即拒**。嵌套多路复用器时两边都报 pane,挑一个就是猜,
  而猜错产出的 ref 会解析到别人的活 pane。
- `heartbeat` 无条件写入自报值。**缺失时清空而非保留**,方向不对称:缺失把投递降级为
  no-operational-route(可见、fail-closed),陈旧则往一个活着且属于别人的 pane 打字。
  由此确立的契约已写进代码注释:**心跳要在 agent 自己的 pane 里跑。**

## 一处既有门抓到我,而它的判据是枚举式的

`test_the_only_property_read_is_a_self_query_without_a_target` 断言 `display-message` 在
TmuxTransport 里出现**恰好一次**。那个计数是「每个调用点都必须是自查询」这条真属性的**代理**,
而代理是枚举式的:我加了第二个同样合法的自查询,它就炸了,却没有违反任何东西。

**把 1 改成 2 是错的** —— 那只是保留代理并重新调准,把枚举从一处搬到另一处。改成 AST 解析:
找出每一条提到该命令的 argv,要求没有一条带 `-t`;并加「解析不到就算空转」的非空转保护。
于是任意数量的自查询都被容许,而规则真正管的那件事(带 `-t` 时静默回落到当前 pane,
使缺失的 pane 看起来存在)仍被拒。

读数:688 测试,红 6 处,与本改动前**逐个相同**(全为 macOS `/private/var` 族,另账)。
新增 12 条测试,含歧义拒绝的开火构造。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant