Skip to content

fix(settings): 「工具」节改与会话页同源认项目 —— 侧栏过滤掉的会话不再解不出目录 (#1361) - #1364

Merged
jinjunnn merged 2 commits into
alphafrom
fix/1361-settings-dir
Sep 18, 2026
Merged

jinjunnn merged 2 commits into
alphafrom
fix/1361-settings-dir

Conversation

@jinjunnn

Copy link
Copy Markdown
Owner

Fixes #1361

改法

设置页「工具」节的「当前项目目录」此前只从侧栏项目清单查
(index.tsx → sessionDirectoryFromProjects(projects.store));会话页认的是服务端给的会话信息
(alpha-session-workspace.tsx:48 serverSync().session.data.info[id])。侧栏按设计过滤掉一部分
会话(sidebar/worktree-filter.ts:15-19:归档项目 / 以家目录为根 / 全局 / 桶),撞上这些会话时两者
分叉:会话页里用得好好的,打开「工具」节却只剩「先打开一个项目」。

怎么绕开 PR #1358 当时那条限制(要求点名说明):我没有绕开它 —— 它是结构性的,而且复核过
仍然成立:ServerSyncProvider 只挂在路由子树上(packages/app/src/app.tsx 的
TargetServerRoute:196 / SelectedServerProviders:252 / 草稿路由 :286),而 <SettingsSurface/> 是
AppInterface 的 children,渲染在 ServerShell(QueryProvider + SharedProviders)里。设置面
结构上没有 ServerSync,useServerSync() 在那里拿不到 provider。

所以走的是票面给的另一条:把会话信息以别的方式喂进去。会话页——唯一持有 ServerSync 的那一面
——把它此刻已经解出的 AlphaSessionIdentity 登记到一个壳层通道
(新文件 alpha-ui/active-session-directory.ts,同 settings-state / sandbox-state 的壳层信号形态);
设置面在侧栏清单缺这一格时回落到它。

  • 回落的值就是会话页自己在用的那个目录(session.data.info[id].directory → sessionLiveSnapshotOf
    → identity.directory),所以两个面读的是同一个值,不是两份可能分叉的真相。
  • 没有重新引入 feat(settings): 设置页新增「工具」节 —— 按来源 / 服务 / 单个工具设置停用 / 询问 / 允许 (#1130) #1358 修掉的 blocker:第一顺位仍然是 route.directory ?? 清单查表,canonical
    /server/:serverKey/session/:id 的解析路径一个字没改(那四条原有用例原样绿)。
  • fail-closed 一步没放宽:清单没有、且没有登记 / 登记的是别的会话 / 不在会话路由上 ⇒ 仍然
    undefined ⇒ 该节仍显示「先打开一个项目」,绝不落到默认项目。离开会话页 onCleanup 注销。
  • 侧栏过滤规则本身一个字没改(票面 Out of scope;它挡的是家目录递归 watcher,是那份清单自己的设计)。

改前红(先证明测得出已知的坏)

实现分两步落:先把 sessionDirectoryFromShell 写成「今天的行为」(只查清单),跑出真红,再换成带回落的实现。

$ bun test src/renderer/alpha-ui/settings-directory.test.ts
 91 |     expect(settingsDirectoryOf(route, lookup)).toBe(HOME_ROOT)
error: expect(received).toBe(expected)
Expected: "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/Users/kai"
Received: undefined
(fail) settings directory — 侧栏过滤掉的会话(#1361) > 会话页正站在它上面 ⇒ 设置页解出同一个目录

 7 pass / 1 fail

只红这一条,三条 fail-closed 用例改前改后都绿 —— 它们断的正是不许变的那一半。
另有一条前提自证先跑:shouldSkipWorktree("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/Users/kai", new Set()) 为 true 且只查清单必然 undefined
—— 不自证就分不清「回落生效了」与「这个会话本来就在清单里」。

本地门(worktree .worktrees/1361-settings-dir,base origin/alpha f0090af)

门 结果
north-star ✓ zero upstream package edits — rc 0
typecheck(contracts-consumer / ext / ui-mac) rc 0 / rc 0 / rc 0
bun test ui-mac 全量(known-fails 棘轮) 5082 pass / 0 fail / 366 files — rc 0
assert-gate-files ✓ 208 个闸门文件全部在位且真的跑过(条数与登记精确一致) — rc 0
docs 相对链接(1 个 Markdown) rc 0

与 base fail-set 的差:0 条。
两条已知的环境红(process-fence-apply.test.ts / network-egress-fence.test.ts,
bootstrap 过的 worktree 不下载 Electron 二进制)按 governance/local-verification-traps.md 的处置
把主 checkout 的 electron/dist 软链进本树后真绿,所以上表的 0 fail 是真测量。

中途真红过一次,已修:gate-file-registry.test.ts 的完备性判据红 —— 我在接线锚的抬头点名了
settings-directory.test.ts(「行为半场在那里」),而它不在登记簿里,于是「被委派的那一半按文件名
发现时完全隐形」。照判据给的三选一走第一条:受托方登记进 scripts/gate-files.tsv(精确条数 8),
委派方 alpha-session-workspace.test.ts 补 delegates_to 并把条数 12 → 实测 13。

git push --no-verify:门已在本树逐条跑过(输出如上);pre-push 的 alpha-check 第 [9/14] 步会在
共享主 checkout 里建三棵探针 worktree 并 bun install,与并行 lane 抢同一棵树。

主动没做的

  • 不动 sidebar/worktree-filter.ts(票面 Out of scope)。也没有让侧栏为此多拉一份不过滤的会话
    索引 —— 被过滤的项目根本不会被 session.list(use-projects.ts:268 先过滤 project.list),
    要拿到那些会话就得改过滤本身的数据层效果。
  • 非 sidecar server 上的会话没有单独处理。票面把它与过滤那一格并列,但走我们自己的代码到不了:
    servers() = 内嵌 sidecar + readyWslConnections(...),而产品 Mac-only(NON_GOALS#6),WSL 那支在
    本平台恒空 ⇒ 今天只有一台 server。回落通道结构上也能覆盖它(登记的身份带 serverKey),
    但没有为一个到不了的状态加判据。
  • 没写 CHANGELOG:被修的缺陷由同处 [Unreleased] 的 [REQ-131][CODE] 设置页新增「工具」节:按来源、服务、单个工具设置停用/询问/允许 #1130 引入,从未发布过 ⇒ 相对上一个发布
    没有用户可见变化。[REQ-131][CODE] 设置页新增「工具」节:按来源、服务、单个工具设置停用/询问/允许 #1130 那条 Added 里的「诚实的边界 ①(首页打开设置只提示『先打开一个项目』)」
    仍然逐字成立,不需要改。
  • 「会话页真的登记了」这一端是源码锚,不是行为闸,并已在测试与登记簿里如实标注。原因:
    AlphaSessionWorkspace 在 bun 下加载不了(上游 provider 链),而 solid-js 在 bun 里解析到
    server 构建 ⇒ 朴素的 createRoot 探针会静默失去反应性(本仓点名过的假绿形态),
    写出来的会是一个测不出坏的绊线。要真行为闸需要 vite+happy-dom 级 harness,超出本票范围。

🤖 Generated with Claude Code

jinjunnn and others added 2 commits September 18, 2026 00:05
设置页「工具」节按 (账户, 项目) 分区,当前项目此前只从侧栏项目清单查
(`sessionDirectoryFromProjects`);而会话页认的是服务端给的会话信息
(`serverSync().session.data.info[id]`)。侧栏按设计过滤掉一部分会话
(`sidebar/worktree-filter.ts`:归档项目 / 以家目录为根 / 全局 `/` 桶),撞上这些会话时
两者分叉:会话页里用得好好的,打开设置页「工具」节却只剩「先打开一个项目」。

设置面结构上拿不到 ServerSync —— `ServerSyncProvider` 只挂在路由子树上,而
`<SettingsSurface/>` 是 `AppInterface` 的 children(`packages/app/src/app.tsx`)。所以不去
绕开那条限制,而是把会话信息以别的方式喂进壳:会话页(唯一持有 ServerSync 的那一面)把它
**此刻已经解出**的身份登记到壳层通道(`alpha-ui/active-session-directory.ts`),设置面在侧栏
清单缺这一格时回落到它。回落的值就是会话页自己在用的那个目录,两个面因此同源,不是两份
可能分叉的真相。

fail-closed 一步没放宽:清单没有、且没有登记 / 登记的是别的会话 ⇒ 仍然 undefined ⇒ 该节仍然
显示「先打开一个项目」,绝不落到默认项目。侧栏过滤规则本身一个字没改(它挡的是家目录递归
watcher,是那份清单自己的设计)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`#1361` 的接线锚在 alpha-session-workspace.test.ts 的抬头点名了 settings-directory.test.ts
(「行为半场在那里」),而后者当时不在登记簿里 —— gate-file-registry 的完备性判据因此红:
按文件名发现闸门时,被委派的那一半完全隐形,删掉它委派方的三行源码锚一条都不会红。

处置照判据给的三选一走第一条:受托方登记进 scripts/gate-files.tsv(精确条数 8),
委派方补上 delegates_to 并把条数从 12 更新为实测 13。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jinjunnn
jinjunnn merged commit 07566b3 into alpha Sep 18, 2026
5 of 6 checks passed
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