优先级:
P0:第一版能跑起来的最低要求。P1:日常工作流可用所必需。P2:核心闭环跑通之后再补。
记录约定:
- 已完成的条目不要删,改成
[x],保留实现轨迹。 - 一个实现任务暴露出阻塞、设计冲突或 bug 时,父条目继续保持开放状态,在其下用缩进的
sub-todo:记录。 - 任何非琐碎的
sub-todo:都要链接到docs/problems/里对应的记录,让上下文和决策痕迹挂在父条目上。
- 当前统计:共 178 个状态标记,其中 176 个完成、0 个开放、2 个取消不再追踪;当前待处理队列已清空。
- P0 已清空:基础设施、terminal 主渲染/history 真相源、agent 会话生命周期、浏览器位置/路由/网络代理设置均已完成第一版验收。
- P1 已清空:管理中心、workspace 体验、安全可靠性和日常工作流必需项均已完成第一版验收。
- P2 当前无开放项:M2Terminal logo 与 app icon wiring 已完成第一轮接入。
- 不再作为当前 TODO 阻塞项:完整 libghostty Metal/GPU surface 直连属于后续 renderer backend 架构升级;旧命令面板和活跃端口显示已取消追踪。
- 已完成但仍要防回归的重点模块:Rust core PTY ownership、Ghostty-backed viewport/history source、AI session management、workspace browser tabs、Git diff workspace tab、tab history/workspace restore、app-owned window style。
- 本文件下方保留完整历史 checklist;新工作优先从本队列进入,不再从旧审计段落反向推断。
| Rank | Priority | Status | Area | Item | Definition of done |
|---|---|---|---|---|---|
| 1 | P0 | None open | Release blocker | 第一版最低可运行要求 | 无剩余开放项;只做回归保护,不从历史完成项重开任务。 |
| 2 | P1 | None open | Daily workflow | 日常工作流必需项 | 无剩余开放项;只做回归保护,不从历史完成项重开任务。 |
| 3 | P2 | Done | Branding | M2Terminal logo | logo.png 与生成的 logo.icns 已接入 About、运行时 app icon 和 app bundle CFBundleIconFile,并完成视觉验收。 |
父条目,详见 docs/problems/2026-06-30-performance-scan.md(顶部 §0.0 进度表为主清单)。
- P1 性能扫描攻坚:31/43 已修复并通过 Gate 1(
cargo test全绿 /swift test875 全绿 /scripts/build_app.sh全绿);Gate 2 以 app-control 聚焦走查覆盖核心断言(text.dump=ghostty-formatter、CJK 命令往返、browser.check_connection异步不阻塞主 actor、pkill关闭)。提交逻辑组见 scan §0.0.1。- sub-todo: 12 条高风险 / Low 项带理由延后(见 scan §0.0.2),均为有界、非崩溃风险、需独立改造 + before/after 基准 + 专项验收的后续项:
- P2 T1 终端每帧全量重建可见网格
NSAttributedString→ 给 Ghostty 快照加 per-row dirty 协议(动 formatter 真相源,text.dump=ghostty-formatter回归伞风险高)。 - P2 W1 tab routing 派生属性全量重建 → 每逻辑操作算一次 layout + 在 tab mutation 上精确失效(受 maxTabs=30 有界)。
- P2 W2 / G4 Trash 视图 / Git 侧栏文件列表未虚拟化
NSStackView→ view-basedNSTableView(沿用分支列表范式;分别受 100/文件数有界)。 - P2 W4 sidebar 每按键全量
reloadData→reloadData(forRowIndexes:)行级 delta(与 W3 缓存叠加后单次成本已降)。 - P2 其余 Low(W8 / B7 / B8 / T6 / T7 / R6 / R7):边际收益,逐条理由见 scan §0.0.2。
- P2 T1 终端每帧全量重建可见网格
- sub-todo: 已知 flaky(非本轮引入):
crates/m2terminal-core/tests/rpc.rs的hooks_and_runbooks_work_via_rpc、rpc_dispatch_events_record_request_id_duration_and_error_status在全套并行高负载下偶发失败(baseline 即偶发;隔离/单跑稳定通过)。
- sub-todo: 12 条高风险 / Low 项带理由延后(见 scan §0.0.2),均为有界、非崩溃风险、需独立改造 + before/after 基准 + 专项验收的后续项:
父条目,详见 docs/EXPERIENCE_QUALITY_GOAL.md(§0.0 进度表为主清单)与 docs/problems/2026-07-01-experience-verification-gap.md(方法论缺口 = 为什么「修了还在」)。
- P0 体验缺陷攻坚:用户报告的 4 项(切回乱像素 EXP-R1/R2 / 软换行复制硬换行 EXP-S1 / 拖选闪烁 EXP-S2 / 拼音光标跳 EXP-I1/I3)全部已修复 + 双门验收(
swift test全绿 / harness PASS=7 FAIL=0)。两次 instrumentation 推翻扫描假设(EXP-R1 真因是 atlas upload identity 非 lastScene;EXP-I1 inline 本就正确、真因是 firstRect actualRange)——印证 goal §1 论点。- sub-todo: [x] 证明 app-control socket 可无授权驱动真机(
M2TERMINAL_APP_CONTROL=1+nc -U,绕过 [[gui-verification-blocked]] 的 computer-use 限制);落地 harnessscripts/experience-soak.sh(三态 PASS/FAIL/BLOCKED)。 - sub-todo: [x] 补 5 个 instrumentation:
terminal.gpu_diagnostics(渲染计数 + outcome)、terminal.capture_pixels(离屏像素回读)、terminal.present_log(per-present 事件流)、selection.drag(网格坐标真鼠标选择)、pane.set_marked_text/unmark_text/commit_text(真 IME 合成注入)。 - sub-todo: [x] 修 4 项并把 harness 场景从 BLOCKED 升级为真 PASS:EXP-R2(atlas
instanceID+ 去掉 remount 重建)、EXP-S1(on-screen 拖拽走 unwrap-aware mapper)、EXP-S2(storage swap 期间静音选区通知 + 一次性结算)、EXP-I3(firstRect actualRange 报 marked range)。各带回归单测。 - sub-todo: [x]
/simplify审查验收:4 agent(reuse/simplification/efficiency/altitude)并行复审 diff;应用 3 项清理(applier 选区赋值加等值守卫消除每帧冗余needsDisplay、删gridSelectDragForTesting死赋值、selectedTerminalText合并重复 guard);swift test全绿、harness 复跑 PASS=7。 - sub-todo: [x] EXP-P1 多行粘贴逐行执行+尾段丢失(台账闭环后用户新报告)—— 已修复 + 双门验收(2026-07-02)。根因
paste(_:)裸发字节(不查 DECSET 2004 / 不包ESC[200~/201~/\n不转\r);修复 = 绑定 dylib 现成ghostty_terminal_mode_get+ghostty_paste_encode走 mode-aware 编码(+纯 Swift fallback),「发送到 pane」链穿asPaste同走编码器并删 browser 无条件包裹(反向孪生 bug),PtySession.write部分写丢尾改 poll 重试。新 instrumentation #11(pane.paste真 pasteboard 路径 +terminal.bracketed_paste探针);harness 新增 E15(修前 FAIL"paste executed before Enter"、修后原子性+字节保真双 PASS),E13 顺手改自清理(恢复初始 workspace)。swift test895/0(+9 测)、experience-soak.sh --once= PASS=23 FAIL=0 BLOCKED=0。见 goal §4.G、docs/problems/2026-07-02-multiline-paste-fidelity.md。 - sub-todo: [x] P1/P2 体验台账全闭环 + harness 零 BLOCKED(2026-07-02 收官)。§4 每个 EXP-* 项均落地:真修 9(R1/R2、S1、S2、I1/I3、拼音频闪、B1、T1、T2、G1、S4,各带 harness 修前FAIL修后PASS + 单测)、证伪 12(T3/T4/G2·G3/G6/T6/B7/T5/S6/B4/I7 + 早期 R1/I1,instrumentation/代码追踪证据在案 + 回归守卫)、吸收 1(S5←S1)、NEEDS-HUMAN §6.5(IME 候选窗、I2、R3、B2·B3·B5、I4·I5·I6、B6·B8·B9、T7、S3、G4、G5——均写明为何 headless 不可验 + 真机验收步骤 + fix 方向)、deferred §6.6(R4 结构类专项、R5..R8 内存/部分重绘 latent)。harness 终态 PASS=21 FAIL=0 BLOCKED=0、
swift test884/0。下方各 P2 子项即逐项证据。剩余非 headless 待办 = §6.5 人工验收清单 + §6.6 后续专项(均已显式列举、非本闭环范围)。EXP-S1 深层项(屏外 scrollback 拖拽仍走 formatter 不 unwrap,待统一两个抽取器)另立 goal §4.B 显式条目跟进。- sub-todo: [x] P2 EXP-S4 选到内容下方空行带多余换行 —— 已修复 + 双门验收(
swift test883/0;harness 新增 E11 拖进空行尾随换行=0,修前 row1→row16 尾随 11、修后 0)。selectedText对齐spans(同在 lastSelectableRowOffset break + 边界)。experience-soak.sh --once=PASS=17 FAIL=0 BLOCKED=0。见 goal §4.B。 - sub-todo: [x] P2 EXP-G6 极窄 pane 列数 1↔80 抖动 —— 实测证伪(NSSplitView min-thickness + 窗口 min 内容尺寸把 viewport 宽钉在远高于 1,80×24 fallback 不可达;divider 拖 998pt 列恒 29、窗口 60pt viewport 仍 299pt)。加 harness 守卫(小窗口列 clamp 到 31 非 80)。
experience-soak.sh --once=PASS=18 FAIL=0 BLOCKED=0。见 goal §4.E。 - sub-todo: [x] P2 EXP-T6 后台 resize 后切回 grid stale —— 实测证伪(切回时 view 重布局 + viewDidAppear 的 resizePty 读到新 gridSize 正常 resize;1200w→560w 后台切回列数正确跟到新窗宽非 stale)。加 harness 守卫 E12(自比较同一 tab 前后列数)。
experience-soak.sh --once=PASS=19 FAIL=0 BLOCKED=0。见 goal §4.D。 - sub-todo: [x] P2 EXP-B7 拖入
-文件名选项注入 —— 可达性证伪(format(urls:)只喂 file URL 的绝对 path,恒以/开头,三处 caller 全走它;扫描假设的相对文件名 file URL 不产生)。无 socket 路径,单测守卫安全不变量。swift test884/0。见 goal §4.F。 - sub-todo: [x] P2 EXP-S5 pin-vs-mapper 可见选区文本分歧 —— 已被 EXP-S1 修复吸收(S1 让完全在屏选区只走 mapper 一条路径,无分歧;socket 实测含内部空格行拖选复制字节一致)。残留屏外 scrollback formatter 是 §4.B 已列 S1 深层项。可见路径一致性由 E3/E11 守卫。见 goal §4.B。
- sub-todo: [x] P2 EXP-I2 合成中途 overlay 锚 transient cursor —— → NEEDS-HUMAN(
append_output会把光标推到新行,overlay 正确跟 settled 光标非 transient;无法模型「compose 时 shell 流式输出 prompt 留底部」,transient 光标只在真 TUI 重绘出现,headless 不可忠实复现)。归 goal §6.5 人工验收清单。差点上假断言,查证 FAIL 后撤掉。 - sub-todo: [x] P2 EXP-T5 workspace 缓存子 VC 泄漏 —— 实测证伪(补
workspace.children_count探针,真机切 workspace 触发 detachForCaching,子 VC 数稳定在 3、连切 10 次恒 3 不增长)。harness 守卫 E13(8 次切换增量≤2)。swift test884/0,experience-soak.sh --once=PASS=20 FAIL=0 BLOCKED=0。见 goal §4.D。 - sub-todo: [x] P2 EXP-S6 no-move click 清选区不清 GPU mirror —— 代码追踪证伪(
gridSelectionEnd无移动分支gridSelectionClear()后紧接setSelectedRange({0,0})同步 fire onSelectedRangeChanged → metalGridView.setSelectionRange({0,0}),mirror 同一调用栈清空无残留;扫描漏了 setSelectedRange 路径)。no-move click 无 socket 原语,构造级同步保证,据代码追踪归档。见 goal §4.B。 - sub-todo: [x] P2 EXP-R3..R8 渲染簇成簇归类 —— R3(backing-scale 双读,单屏两读恒同、触发需第二屏)→ §6.5 NEEDS-HUMAN;R4(多入口每 turn 多 present)= deferred-structural(render-model 类修复,是拼音频闪深层类修复,留专门一轮,§6.6);R5(framebufferOnly readback 已被 #1 解除)+ R6..R8(内存 purge 无重建路径,harness 造不出)→ deferred-latent(§6.6)。见 goal §4.A/§6.5/§6.6。
- sub-todo: [x] P2 EXP-B2/B3/B5 浏览器/启动视觉簇 —— 均高信心真 bug 但 headless 不可验(B2 WKWebView 白闪真 compositing、B3 系统光标、B5 启动瞬间窗口跳)→ §6.5 NEEDS-HUMAN,带 fix 方向留真机验收 + 未来专项。见 goal §4.F/§6.5。
- sub-todo: [x] P2 EXP-I4/I5/I6 IME 合成视觉簇 —— 均合成期视觉 + 真焦点(I4 第二 caret、I5 predicted echo 时序、I6 真失焦提交);headless set_marked_text 只验 app 侧不变量(E5 已覆盖 block-cursor 抑制 + markedRange),真 IME 会话不可 emulate → §6.5 NEEDS-HUMAN,带 fix 方向。见 goal §4.C/§6.5。
- sub-todo: [x] P2 EXP-B4 软换行 URL 下划线断裂 —— socket 实测证伪(补
terminal.url_hover+terminal.url_underlines,窄窗跨 3 行 URL rangeCount=1 单条连续;mirror 把软换行当一条逻辑行)。harness 守卫 E14,experience-soak.sh --once=PASS=21 FAIL=0 BLOCKED=0。见 goal §4.F。 - sub-todo: [x] P2 EXP-I7 可见-未聚焦 pane 渲染抢主线程 —— 代码追踪证伪(
render()门控是正确可见性判据:detached pane 完全跳过=O(visible) + damage tracking 跳重复帧;可见 pane 渲染是对的,对标 ghostty/iTerm2;扫描"未聚焦不该渲染"前提错)。残留同步渲染争主线程是固有边界,彻底消除需 off-main-thread=§7 non-goals。见 goal §4.C。 - sub-todo: [x] P2 EXP-G1 divider 拖拽 PTY-resize 风暴 —— 已修复 + 双门验收(
swift test883/0;harness E4 divider 从 BLOCKED 毕业,11 步拖动 winsize +5→+1)。落 #8terminal.pty_resize_count+divider.step;resizePty拆同步视觉 + 子 PTY winsize 32ms 防抖合并。experience-soak.sh --once=PASS=16 FAIL=0 BLOCKED=0(harness 首次零 BLOCKED)。见docs/problems/2026-07-02-divider-drag-pty-resize-storm.md。 - sub-todo: [x] P1 EXP-B1 关内嵌 browser pane 丢焦点 —— 已修复 + 双门验收(
swift test882/0;harness 新增 E6 PASS,experience-soak.sh --once=PASS=9 FAIL=0)。落地 instrumentation #6window.first_responder+browser.open_embedded/browser.focus_embedded/pane.close_active;下沉共用closeEmbeddedBrowser()同时修 Cmd-W 与 X 按钮两条路径。见docs/problems/2026-07-01-browser-close-focus-loss.md。 - sub-todo: [x] P1 EXP-T3 切 tab 焦点落空 —— 扫描假设经 #6 证伪(终端 tab 选择焦点走两道 viewDidAppear+focusActivePane 且都 window-present,6 次切换 first responder 恒为终端);无生产代码修复,加 harness 回归守卫 E7 tab-switch-focus(现即 PASS)。见 goal §4.D。
- sub-todo: [x] P1 EXP-T1 tab.snapshot 多个 isActive —— 已修复 + 双门验收(
swift test882/0;harness 新增 E8 修前计数 2→修后 1,experience-soak.sh --once=PASS=11 FAIL=0)。窄修tabSnapshot()用选中 group 唯一全局 active id(不动被生产选择器消费的跨 grouppaneSummaries);顺手加固 E1 冷启动 baseline 竞态。见 goal §4.D。 - sub-todo: [x] P1 EXP-T2 多 pane tab 重挂载 active pane 跳 —— 已修复 + 双门验收(
swift test882/0;harness 新增 E9 修前跳→修后留,experience-soak.sh --once=PASS=12 FAIL=0)。只有 active pane 才 appear 时抢焦点(claimsFocusOnAppear逐 pane 判断,跨 TerminalViewController/chrome/group 三层接线);补pane.split/pane.focus驱动。见docs/problems/2026-07-02-active-pane-jumps-on-tab-remount.md。 - sub-todo: [x] P1 EXP-T4 mount thrash —— 「重选/风暴」经 #10 证伪(重选被 store.select guard;每次 mount 都先改选中 tab;8 类操作实测无冗余重挂载)。顺手补 mounter 幂等 defense-in-depth(单测证同视图连挂 2→1+skip)+ harness 守卫 E10 + E1 冷启动改 poll-until-atlas-built。
swift test883/0,experience-soak.sh --once=PASS=13 FAIL=0。见 goal §4.D。 - sub-todo: [x] P1 EXP-G2/G3 resize/按键丢滚动锚点 —— 扫描假设经 #7 证伪(ghostty C 引擎已保留 viewport pin,resize 不跳;输入滚到底=标准正确行为;输出跟随已正确抑制)。落 #7
terminal.viewport_top+terminal.scroll,把 E4 resize-anchor 从 BLOCKED 毕业为 2 条真断言。swift test883/0,experience-soak.sh --once=PASS=15 FAIL=0 BLOCKED=1(仅剩 G1)。见 goal §4.E。P1 全部收官:3 修 3 证。
- sub-todo: [x] P2 EXP-S4 选到内容下方空行带多余换行 —— 已修复 + 双门验收(
- sub-todo: [x] 证明 app-control socket 可无授权驱动真机(
父条目,详见 docs/problems/2026-07-14-project-audit-fixes.md(五维审查 ≥80 置信度的六项发现逐项修复,每项独立 commit + 双门验收)。
- P2 OSC 133 semantic prompt(shell integration):命令高亮的 prompt 定位目前是终结符启发式(
%/$/#/❯/>,审查修复 4 的临时方案,agent TUI 激活时跳过)。正解 = OSC 133 A/B 标记 + shell integration 脚本(Ghostty/iTerm2/kitty/WezTerm 同款机制),需要 vt shim 透出 per-row semantic prompt 状态;落地后删除启发式。
- 本地
.build/libghostty-vtruntime 已可用,SwiftPM/dev 启动默认请求 Ghostty-backed renderer;swift test --filter TerminalMVPTests全量通过。 - 普通 app pane 的 PTY ownership 已切到 Rust core 优先,active Ghostty 下的文本查询已切到 libghostty-vt formatter。
- 修复 app 首次打开 terminal pane 早于 Rust core socket ready 导致的短暂
core PTY failed闪屏,CorePtySession对启动期临时连接错误做短重试。 - 当前剩余差距不是 VT 语义接入,而是完整 libghostty Metal/GPU renderer 直连、Ghostty-backed history 真相源和真实 terminal 兼容性矩阵。(2026-05-18 复审后:Ghostty-backed history 真相源和兼容性矩阵已收口;Metal/GPU renderer 直连保留为 P0 之后架构升级。)
- 问题记录:
docs/problems/2026-05-13-architecture-optimization-audit.md;docs/problems/2026-05-13-core-pty-and-ghostty-truth-source.md。
- 当时统计:共 175 个 checkbox 条目,167 个完成,8 个开放。
- 只核对当前代码和现有测试,不做功能实现;已有未提交代码改动保持不动。
- 可以确认已落地但缺少完整 app acceptance 记录:terminal 空输入点击光标修复、terminal 宽度几何修复、app 内 browser split shell。对应条目已补状态备注;只有空输入点击这一项因问题记录已有 Resolution 且 targeted scripted validation 通过,改为完成。
- 当时仍开放:Ghostty 主渲染/scrollback 真相源收口、terminal 宽度真实 app 对照、terminal 兼容性矩阵、browser split 真实 terminal-click 验收、browser 网络/代理设置、M2Terminal logo。
- 本次验证:
swift test --filter WorkspaceExperienceTests/testTerminalWorkspaceGroupOpensBrowserInsideActiveTabSplitPane通过;swift test --filter TerminalMVPTests/testTerminalTextViewPlainClickDoesNotMoveTerminalCursor、testTerminalGeometryNeverAllocatesColumnsPastViewportWidth、testTerminalGeometryDoesNotForceTwentyColumnsInNarrowPanes、testTerminalTextViewUsesExactGridWidthWithoutFragmentPadding通过。swift test --filter TerminalMVPTests全量失败在强制 Ghostty renderer 的 3 个用例;当时测试环境libghostty-vtruntime 不可用,相关 snapshot tests 被 skip,但 controller 级 Ghostty renderer tests 没有自动 skip,需后续修正测试前置条件或补 runtime。
- 当前统计:共 161 个 checkbox 条目,112 个完成,49 个开放;开放项包含未开始、阻塞中、以及已有部分实现但未通过完整验收的任务。(2026-05-12 复审已有新统计,见上。)
- 完成:P0 基础设施、基础 PTY shell、基础 agent 生命周期、基础浏览器位置、管理中心基础能力、安全可靠性、自动化基础、agent context routing 基础能力、打包/更新等已保留为完成项。
- 未完成:libghostty 真正接入、terminal 兼容性矩阵、app 内浏览器 split pane、内置浏览器网络/代理设置、workspace/tab 垃圾箱、M2Terminal logo、App menu 完整重做、所有 app-owned window 风格统一、完整国际化、accessibility 完整走查等仍是开放项。
- 没完成好:分屏、app 内浏览器 split pane、workspace 侧栏打磨、Git 变动阅览、workspace shell dark-mode 一致性、部分窗口样式、pane 布局预设、国际化都已有部分实现,但当前状态不满足完整验收;对应父项已在本次审计中改回开放状态或补了备注。
- 已取消/不再追踪:状态栏旧辅助入口(ports、attention、quick switcher、command palette、Search Terminal Output)后续已按产品方向删除;TODO 中仅保留历史实现记录,不代表当前 UI 仍应存在。
- 确定 Swift app、Rust core、共享协议定义的仓库结构。
- 用 AppKit 搭出最小的 macOS app 外壳。
- 增加把 MVP 包成普通 macOS
.app的本地打包脚本。 - 创建 Rust core crate / 守护进程骨架。(
crates/m2terminal-core/) - 定义 Swift ↔ Rust 通讯边界。(
Sources/M2Terminal/Core/) - 选定本地协议格式:JSON-RPC over Unix domain socket 或直接 FFI。(最终走 NDJSON over UDS,路径
~/Library/Application Support/M2Terminal/core.sock。) - 给 workspaces / sessions / panes / browser_views / settings 建出最初的 SQLite schema。(迁移
0001_initial.sql。) - 定义 M2Terminal 自己拥有的 MCP / skills 配置 schema。
- 定义 Codex 与 Claude Code 配置生成的导出目标记录。
- 加上带 token 屏蔽规则的基础日志。
- 实现单个终端 pane。
- 通过 PTY 起一个 shell。
- 把 PTY 输出接入 libghostty / libghostty-vt。在仓库或构建环境里能链接到 libghostty/libghostty-vt 之前阻塞。
- sub-todo: [x] 决定 M2Terminal 怎么消费 libghostty:稳定的 C/Swift 桥接 module,配合显式可链接的 libghostty/libghostty-vt 依赖。问题记录:
docs/problems/2026-04-30-libghostty-dependency-blocker.md。 - sub-todo: [x] 加构建期依赖检查,需要 libghostty 但不可用时给出清晰错误。
- sub-todo: [x] 记录最初的依赖阻塞:本机当时没有
pkg-config,也没有可链接的libghostty/libghostty-vtheader/library/pc 文件;网上资料显示libghostty-vt已有 C/Rust/Dart/Go 生态绑定,但本项目仍需要显式可链接依赖后才能完成替换。问题记录:docs/problems/2026-04-30-libghostty-dependency-blocker.md。 - sub-todo: [x] 完成
libghostty-vt本机最小 spike:从 Ghostty 源码构建可链接 header/library,补 C 与 Swift 编译链接 smoke test,后续可在显式 feature flag 下接入 app renderer。问题记录:docs/problems/2026-05-07-libghostty-vt-spike.md。 - sub-todo: [x] 增加默认启用的
libghostty-vt实验渲染路径:packaged app 内置并签名libghostty-vtdylib,PTY 输出双写到 fallback buffer 与 libghostty-vt viewport,Codex CLI 可通过实际 app 控制验收;缺 runtime 的开发环境或显式M2TERMINAL_GHOSTTY_VT_RENDER=0才回退旧 renderer。问题记录:docs/problems/2026-05-07-libghostty-vt-spike.md。 - sub-todo: [x] 对照 Warp 的 terminal 逻辑修补临时 renderer 的 fzf/CPR/行清除/APP_CURSOR 键盘编码缺口,避免在 libghostty 接入前阻塞日常 TUI 使用。问题记录:
docs/problems/2026-05-02-terminal-logic-warp-audit.md。 - sub-todo: [x] 补 xterm SGR mouse reporting,修复 fzf-style selector 开启 mouse tracking 后无法用鼠标点选菜单的问题。问题记录:
docs/problems/2026-05-02-terminal-logic-warp-audit.md。 - sub-todo: [x] 补 truecolor / 256-color SGR 渲染和 cell-grid 背景绘制,修复 fzf-style selector 高亮、边框和面板背景显示缺失。问题记录:
docs/problems/2026-05-02-terminal-logic-warp-audit.md。 - sub-todo: [x] 修正 terminal 可用宽度计算,PTY 列数和 text container 都扣除左右 inset,避免内部内容视觉上超出 app 容器。问题记录:
docs/problems/2026-05-02-terminal-width-overflow.md。 - sub-todo: [x] 修复 terminal 输入容器可用宽度偏小的问题;例如 fzf-style selector 打开后交互区域展示宽度比正常终端少,需要重新对齐 PTY 列数、text container、inset 与 TUI 看到的 viewport。2026-05-12 代码复审:
TerminalGeometry.gridSize、fitTerminalViewToContent/fitTerminalViewToViewport已统一从扣除 inset 的 viewport 推导 PTY columns 与 text container width,且相关 targeted scripted validation 通过。2026-05-18 补terminal.geometry_snapshotapp-control 动作和scripts/terminal-width-smoke.sh;真实 app 在默认/窄/宽窗口尺寸下验证 shell$COLUMNS、PTY grid columns、text container width、Ghostty frame columns 和 alternate-screen full-width TUI ruler 全部对齐,并用 deterministic TUI width probe 完成验收。问题记录:docs/problems/2026-05-03-terminal-input-container-width.md。 - sub-todo: [x] 修复空输入状态下鼠标点击导致光标错误跳转的问题;没有输入任何内容时,点击已有展示行内不应把光标跳到点击列,点击非行内空白也不应把光标跳到最后一行末尾;只有当前命令行已有可编辑内容时,点击内容范围内才允许移动光标。2026-05-12 代码复审:
TerminalTextView在普通点击后恢复 renderer-owned terminal cursor,targeted scripted validationswift test --filter TerminalMVPTests/testTerminalTextViewPlainClickDoesNotMoveTerminalCursor通过;真实 app 边界走查并入 terminal 兼容性矩阵继续覆盖。问题记录:docs/problems/2026-05-03-terminal-empty-click-cursor.md。 - sub-todo: [x] 建立 terminal 命令兼容性验收矩阵,覆盖普通有输出命令、交互命令、自定义脚本、第三方 TUI/CLI(如
fzf、vim、less、top、claude、codex),行为必须符合正常 terminal 预期。2026-05-13 复审:已有分散单测覆盖 ANSI、mouse reporting、geometry、IME、agent TUI、Ghostty viewport,且本地libghostty-vtruntime 可用时swift test --filter TerminalMVPTests全量通过;但仍没有一份可维护矩阵和真实 app 对照验收,继续保持开放。2026-05-18 补docs/terminal/compatibility-matrix.md和scripts/terminal-compat-smoke.sh,自动覆盖 plain/color/Unicode/large scrollback/alternate screen/bracketed-paste smoke;同日扩展真实 app smoke 覆盖less/vim/nano/topopen-quit 流程,并对缺失的fzf显式 skip。2026-05-18 收口:增加必跑 fzf-style selector fixture、agent TUI fixture、真实codex --help/claude --helpTTY 输出 smoke;same-size 视觉风险由scripts/terminal-width-smoke.sh默认/窄/宽 app-control 几何与 viewport 证据覆盖;本机通过 Homebrew 安装fzf 0.72.0后,用M2TERMINAL_COMPAT_REQUIRE_REAL_FZF=1 scripts/terminal-compat-smoke.sh强制跑过真实fzfTUI 选择/返回,不再只依赖 optional skip。问题记录:docs/problems/2026-05-03-terminal-command-compatibility-matrix.md。 - sub-todo: [x] 补 agent TUI 需要的 absolute cursor positioning / alternate screen / cell erase 语义,并清理宿主
NO_COLOR环境污染,修复claude/codex这类固定位置 UI 被摊进 scrollback、颜色丢失的样式问题。问题记录:docs/problems/2026-05-02-agent-tui-rendering.md。 - sub-todo: [x] 明确记录当前 Codex 无法彻底解决的 terminal 兼容问题:
claude、codex、fzf-style scripts 等脚本交互的最终样式仍依赖真实 VT grid/alt-grid 渲染管线;在 libghostty 接入前,TerminalOutputBuffer只允许做阻塞级兼容补丁,不再把它标记为完整终端实现。问题记录:docs/problems/2026-05-02-agent-tui-rendering.md。 - sub-todo: [x] 用 libghostty 驱动的 VT 状态/渲染管线替换掉
TerminalOutputBuffer/NSTextView主渲染路径,改为 cell-grid renderer;现有 text renderer 只保留为 fallback/search/copy mirror,同时保留现有终端行为测试做回归覆盖。2026-05-13 复审:TerminalGridView和TerminalFrame已是 active Ghostty-backed viewport renderer,普通 shell/dev launch 在本地 runtime 可用时默认走libghostty-vt;NSTextView仍作为 development fallback 与 scrollback/search/copy mirror 存在。2026-05-18 收口:active Ghostty pane 的terminalOutputText()、terminalHistorySnapshotText()、text.dump、搜索、tab snapshot/runtime snapshot 均走TerminalOutputTextSnapshot(source=ghostty-formatter);新增 RIS reset 回归测试防止TerminalOutputBuffer的 stale mirror 抢回 history 真相源;text.dump暴露source/rendererBackend供真实 app 验收确认,terminal-compat-smoke.sh与terminal-width-smoke.sh也已把这些字段作为必过断言。完整 libghostty Metal/GPU surface 直连仍是 P0 之后的 renderer backend 升级,不再作为第一版 P0 阻塞项。问题记录:docs/problems/2026-05-07-terminal-grid-renderer-reference.md;docs/problems/2026-05-13-core-pty-and-ghostty-truth-source.md。 - sub-todo: [x] 将 active Ghostty 渲染下的
text.dump、搜索、复制、tab snapshot/runtime snapshot 逐步统一到 Ghostty-backed frame/history 来源,避免TerminalOutputBuffer、NSTextViewmirror 与可见 grid 各自成为真相源。2026-05-07 复审:可见 viewport 由ghostty.snapshot/TerminalFrame提供;terminalOutputText()、搜索、text.dump、tab/runtime snapshot 已恢复为完整 scrollback mirror,避免滚动到历史时丢掉底部输出。2026-05-12 代码复审:terminalOutputText()仍优先返回TerminalOutputBuffer.text,Ghostty-backed history source 尚未接入。2026-05-13 第二轮优化:active Ghostty 下terminalOutputText()优先使用 libghostty-vt formatter,搜索、text.dump、tab snapshot/runtime snapshot 随调用链切到 Ghostty-backed text;TerminalOutputBuffer只保留为 formatter/runtime 不可用时的 fallback mirror。2026-05-18 最终收口:去掉 history snapshot 的 fallback recent-lines 启发式,active Ghostty 只要 formatter 可用即以ghostty-formatter为文本真相源,fallback/text view 仅在 Ghostty formatter 不可用或非 Ghostty renderer 下返回。问题记录:docs/problems/2026-05-07-terminal-grid-renderer-reference.md;docs/problems/2026-05-13-core-pty-and-ghostty-truth-source.md。 - sub-todo: [x] 将 IME 候选框定位、marked text bounds 与 selection geometry 迁移到
TerminalGridView的 cursor/cell 坐标,不再由NSTextView文本布局推断。2026-05-07:TerminalTextView.firstRect优先使用TerminalGridView.cursorScreenRect();marked text 已按 grid cursor 绘制。问题记录:docs/problems/2026-05-07-terminal-grid-renderer-reference.md。 - sub-todo: [x] 改进
TerminalGridView的 glyph 绘制:按相同字体/颜色/样式批量绘制 cell runs,保留 wide-char spacer 跳过、背景/文本/装饰/cursor 分层,避免逐 cell 文本绘制成为长期主路径。2026-05-07:背景、文本 run、underline、marked text、cursor 分层绘制;underline cell 保持独立装饰;wide/CJK/emoji cell 会断开 text run,后续 cell 继续按 terminal column 锚定。问题记录:docs/problems/2026-05-07-terminal-grid-renderer-reference.md。 - sub-todo: [x] 将
TerminalOutputBuffer降级为非 Ghostty fallback、命令日志辅助和兼容性回归模型;active Ghostty TUI 不应依赖它决定可见语义。2026-05-07:active Ghostty 的可见输出以 Ghostty snapshot/TerminalFrame 为准;TerminalOutputBuffer继续辅助 fallback、命令日志、输入模式、回归测试,并临时作为完整 scrollback/search/tab snapshot mirror,直到 Ghostty history 来源接上。2026-05-18:active Ghostty 的 history/search/text dump/tab snapshot 已改由ghostty-formatter显式提供;TerminalOutputBuffer不再作为这些用户可见文本操作的真相源。问题记录:docs/problems/2026-05-07-terminal-grid-renderer-reference.md;docs/problems/2026-05-13-core-pty-and-ghostty-truth-source.md。
- sub-todo: [x] 决定 M2Terminal 怎么消费 libghostty:稳定的 C/Swift 桥接 module,配合显式可链接的 libghostty/libghostty-vt 依赖。问题记录:
- 在原生 view 里渲染终端内容。
- 把键盘输入回写到 PTY。
- 处理终端尺寸变更。
- 实现基本复制 / 粘贴。
- 把终端主题配置抽出来,默认采用 Technical Precision System 配色。
- 验证 macOS 上的输入法行为。
- 验证回滚(scrollback)行为。
- 定义支持的 agent 类型:Codex、Claude Code、通用命令。
- 在选中的 workspace 里启动 Codex。
- 在选中的 workspace 里启动 Claude Code。
- 跟踪进程状态。
- 跟踪 cwd、命令、启动时间、退出码。
- 显示一个会话是 running、exited 还是 waiting for attention。
- App 重启后保留会话元数据。
- 加 WKWebView pane。
- 支持把浏览器开在右侧。
- 支持把浏览器开在底部。
- 支持把浏览器开在新的 app 窗口。
- 支持用系统默认浏览器打开 URL。
- 把浏览器位置按 workspace 持久化。
- 支持在当前 workspace 内以一等 tab 打开内置浏览器;显式 New Browser Tab、app-control
browser.open、以及 WKWebViewtarget=_blank/window.open会追加新的 browser tab,不替换旧 tab,且 browser tab 不计入 terminal tab 上限。2026-05-15 验证:swift test --filter WorkspaceExperienceTests/testTerminalWorkspaceGroupOpensBrowserTabsInsideWorkspaceWithoutReplacingExistingTabs、testBrowserTabsCanOpenBeyondTerminalTabLimit、swift test --filter WorkspaceExperienceTests、git diff --check、scripts/build_app.sh通过;真实 app 以M2TERMINAL_APP_CONTROL=1启动后,browser.open https://www.google.com/返回title=Google/loading=false。2026-06-01 路由调整后,terminal URL 只有 Command-click 会打开;功能设置可选择 browser tab、browser pane 或系统默认浏览器。问题记录:docs/problems/2026-05-15-workspace-browser-tabs.md、docs/problems/2026-05-25-terminal-url-copy-and-routing.md、docs/problems/2026-06-01-terminal-url-cmd-only-browser-routing.md。 - 修复 app 内分屏打开浏览器功能未真正实现的问题;浏览器应能作为当前 workspace/tab 的 split pane 打开,并支持与 terminal pane 同屏布局。(功能设置可将 Command-click terminal URL 的默认目标设为 pane 或系统默认浏览器;browser pane 已补 URL 输入框、导航按钮、关闭按钮、转移到新 Tab 按钮和加载/失败状态。2026-05-12 代码复审:
TerminalPaneGroupViewController.openEmbeddedBrowser已把 right/bottom browser pane 放进当前 workspace tab,且swift test --filter WorkspaceExperienceTests/testTerminalWorkspaceGroupOpensBrowserInsideActiveTabSplitPane通过;2026-05-25 决策:active terminal-tab embedded split 是可配置的 terminal-origin URL open 路径;显式 New Browser Tab / app-controlbrowser.open继续使用一等 workspace browser tab。)问题记录:docs/problems/2026-05-03-browser-split-pane.md、docs/problems/2026-05-25-terminal-url-copy-and-routing.md、docs/problems/2026-06-01-terminal-url-cmd-only-browser-routing.md。- sub-todo: [x] 补内置浏览器网络/代理设置:参考 cmux、VS Code、JetBrains 和 Electron 的做法,提供 terminal link behavior host allowlist、always-open-external URL rules、WKWebView 网络模式(System / explicit HTTP CONNECT proxy / SOCKS proxy / no proxy)和 Check Connection;遇到
198.18/198.19fake-ip/TUN 场景时不要偷偷绕过用户代理策略,应让用户显式配置代理或选择系统浏览器。2026-05-18 收口:Settings/Browser 页已提供 embedded host allowlist、always-open-external rules、HTTP host allowlist、System/HTTP CONNECT/SOCKS/No Proxy 网络模式和 Check Connection;browser.settings_*、browser.route_preview、browser.check_connectionapp-control 动作覆盖真实 app 验收。脚本验证swift test、git diff --check、scripts/build_app.sh通过;真实 app 验收在.build/M2Terminal.app中确认 Browser 设置页可见、路由预览符合 allowlist/external/HTTP/system-browser 规则、https://example.com/连接检测返回 HTTP 200,且browser.snapshot显示title=Example Domain、networkMode=system。问题记录:docs/problems/2026-05-03-browser-split-pane.md。
- sub-todo: [x] 补内置浏览器网络/代理设置:参考 cmux、VS Code、JetBrains 和 Electron 的做法,提供 terminal link behavior host allowlist、always-open-external URL rules、WKWebView 网络模式(System / explicit HTTP CONNECT proxy / SOCKS proxy / no proxy)和 Check Connection;遇到
- 加 API Token 引用的设置区。
- Token 存进 macOS Keychain。
- 加 Token 校验,且不把 token 值写进日志。
Management Center 加 Tokens 页;Rust core 只保存
secret_refs元数据并提供secret_ref.upsert/list/deleteRPC,Swift 用 Keychain servicedev.m2terminal.tokens保存 token 值,校验空值和控制字符。问题记录:docs/problems/2026-05-01-api-token-keychain-management.md。 - 建 MCP server 注册表 UI。
- 加 MCP server 启动 / 停止生命周期。
- 建 skills 注册表 UI。
- 支持 per-workspace 的 MCP 启用开关。
- 支持 per-workspace 的 skills 启用开关。
- 加非密配置的导入 / 导出。
Rust core 增加
config.export/config.importRPC 和 CLIm2terminal config export/import,只导出 workspace/settings/MCP/skills/browser/export-target 等非密元数据;secret-like settings 与 MCP env 值会被跳过并返回 warnings。问题记录:docs/problems/2026-05-02-p1-reliability-data-safety.md。
- 加 workspace 侧栏。
- 加终端 split panes。(2026-05-06:保留 AppKit 默认 thin divider,不再做危险的 split divider 主题化替换;补 active pane/current tab 回归测试,并完成真实 app 分屏/拖动验收。)
- sub-todo: [x] 状态栏 split 图标补齐 hover tip;左键分别执行向右/向下分屏,右键按横向/纵向分别提供左/右、上/下选择。问题记录:
docs/problems/2026-05-02-status-bar-split-controls.md。 - sub-todo: [x] 当前 workspace tab 最多 9 个 pane,超过后提示“已达当前 tab 分屏上限”。
- sub-todo: [x] 将分屏布局改成每 tab 最多 3 列 x 3 行(最多 9 个 pane),footer 右键菜单按横/竖轴提供双向选择,并补默认快捷键。问题记录:
docs/problems/2026-05-03-terminal-split-grid.md。 - sub-todo: [x] P1 升级:分屏线颜色/样式暂时禁止做主题化定制。之前通过替换
NSSplitViewController.splitView/ 自定义NSSplitView的尝试导致真实.build/M2Terminal.app启动崩溃,后续修补又出现空白窗口;2026-05-06 已确认当前实现不替换 AppKit managed split view,真实 app 可启动、分屏和拖动默认 divider。问题记录:docs/problems/2026-05-03-themed-split-divider-crash.md。 - sub-todo: [x] 修复分屏功能当前不可用 / 逻辑错误的问题;左/右/上/下分屏必须只作用于当前 workspace 当前 tab 的 active pane。2026-05-06 补
testSplitPaneDirectionsOnlyAffectActivePaneInCurrentTab覆盖 active pane/current tab 分流,并完成真实 app 验收。问题记录:docs/problems/2026-05-03-footer-tabs-workspace-polish.md。
- sub-todo: [x] 状态栏 split 图标补齐 hover tip;左键分别执行向右/向下分屏,右键按横向/纵向分别提供左/右、上/下选择。问题记录:
- 加 tabs / workspace groups。(审计备注 2026-05-05:tab UI、关闭、重命名和 workspace-local tab 状态已做;跨 app 重启的持久化恢复另按 workspace/tab 垃圾箱与未来 core 存储跟进。)
- sub-todo: [x] 每个 workspace 的 tab 上限定为 30,⌘T 加 tab。
- sub-todo: [x] workspace tab 支持右键 Rename…,重命名后保留自定义标题。
- sub-todo: [x] workspace group tab 改成 Chrome 风格自绘 tab strip,并在末尾固定提供
+tab。问题记录:docs/problems/2026-05-02-chrome-style-workspace-tabs.md。 - sub-todo: [x] 移除 tab 标题里的 pane 数量后缀
(n)。 - sub-todo: [x] 缩窄不活跃 tab 的宽度,让 tab strip 更接近浏览器 tab 的密度。
- sub-todo: [x] 修复 workspace tabs 被所有 workspace 共享的问题;每个 workspace 独立拥有和管理自己的 tabs、选中 tab、tab 名称与 pane 状态。问题记录:
docs/problems/2026-05-03-workspace-tab-ownership.md。 - sub-todo: [x] tab hover 时在右侧显示
x关闭按钮;活跃和非活跃 tab 都支持点击关闭;多分屏 tab 关闭前需要用户确认;tab 右键菜单也提供 Close。问题记录:docs/problems/2026-05-03-workspace-tab-close-workspace-close.md。
- terminal pane 内搜索:terminal 聚焦时
Cmd+F打开浮动搜索框,支持当前 pane 内匹配高亮、上下跳转和Aa大小写完全匹配;active Ghostty renderer 下搜索真相源继续使用 Ghostty formatter history。问题记录:docs/problems/2026-05-19-terminal-pane-search.md。 - workspace 右键支持关闭整个 workspace / 关闭所有 workspaces;两种关闭都必须先让用户确认,关闭所有后右侧显示 Guide tab。问题记录:
docs/problems/2026-05-03-workspace-tab-close-workspace-close.md。- sub-todo: [x] 关闭大量 workspaces 时,sidebar footer 显示 spinner 与
Closing N workspaces...,避免批量删除期间界面看起来无响应。问题记录:docs/problems/2026-05-03-workspace-tab-close-workspace-close.md。
- sub-todo: [x] 关闭大量 workspaces 时,sidebar footer 显示 spinner 与
- 加 workspace / tab 垃圾箱与恢复机制。问题记录:
docs/problems/2026-05-03-workspace-tab-trash.md。- sub-todo: [x] 当前 workspace 的关闭 tab 历史入口:status-bar 历史图标打开 tab history,而不是 session event timeline。
- sub-todo: [x] 非最后一个 tab 关闭时,如果有 terminal input、分屏或内置浏览器活动,记录可恢复 SQLite 快照;没有任何实质操作的 tab 不进入历史。
- sub-todo: [x] tab history 行样式:左侧展示 tab name、path、closed at;右侧展示“查看日志”按钮和 pane 数量。
- sub-todo: [x] “查看日志”对话框按倒序展示最近最多 20 条交互命令、执行路径、时间和 prompt;命令日志只记录终端可见回显,避免把隐藏输入持久化。
- sub-todo: [x] 右键 Restore Tab 可恢复 tab 名称、pane 布局、cwd/git metadata、active pane;恢复后从持久化历史删除该记录。
- sub-todo: [x] tab history 持久化到 core SQLite,app 重启后仍可查看;每个 workspace 最多保留最近 100 条,core 记录/读取时清理 14 天前的记录。
- sub-todo: [x] 垃圾箱层级为 workspace 一级、其下 tab 二级;workspace 自己有 tab 垃圾箱,app 另有管理已删除 workspace 的全局垃圾箱。
- sub-todo: [x] workspace 关闭/删除时保留可恢复快照;workspace trash 只删除 M2Terminal metadata,不删除磁盘文件。
- sub-todo: [x] 从 workspace 垃圾箱恢复 tab 时,该 workspace 必须存在;如果 workspace 已删除,会先 restore workspace,并允许只恢复该 workspace 中的某一个 tab,其余 tab 转入新 workspace 的 tab history。
- sub-todo: [x] 恢复整个 workspace 时只打开删除瞬间仍打开的 tabs;删除前已经关闭的 tabs 保留在 restored workspace 的 tab history。问题记录:
docs/problems/2026-05-06-workspace-trash-restore-open-state.md。 - sub-todo: [x] 恢复 terminal scrollback 和 session runtime snapshot;原 PTY 进程不做 3 天保活/复活,恢复时启动新 PTY,并在 runtime snapshot 中标记
process_restored=false。 - sub-todo: [x] 14 天保留期支持配置化;core 通过
trash.retention_days设置对 tab/workspace trash 共用保留期,Workspace 垃圾箱与 Tab 历史会在 14 天后清理。 - sub-todo: [x] 限制 active workspaces 最多 10 个,并把已删除 workspace 垃圾箱改成与 tab history 一致的表格样式和行级操作。问题记录:
docs/problems/2026-05-19-workspace-limit-and-trash-ui.md。
- pane 元数据里显示 git 分支与 cwd。
- 加当前 tab 所处文件夹的 git 变动阅览;footer 显示 git 图标与变动数量,点击后从右侧 side panel 滑出展示当前 tab cwd 的 diff/status。(2026-05-06 重写
GitChangesSidePanelViewController:文件列表 + 结构化 diff 文档,行号 gutter,Codex 风格红绿整行底色,长行通过 documentView 水平滚动。swift test --filter testGit全部通过。)问题记录:docs/problems/2026-05-03-tab-git-changes-side-panel.md。- sub-todo: [x] 重新实现 Git diff panel:放弃旧 NSTextView 文本 dump,新实现按行渲染
DiffRowView(行号 gutter + 全行红绿底色),文件列表与 diff 区分别用独立 NSScrollView,长行靠 documentView 水平滚动;swift test --filter testGit全部通过。
- sub-todo: [x] 重新实现 Git diff panel:放弃旧 NSTextView 文本 dump,新实现按行渲染
- [~] 在能拿到的地方显示活跃端口。(2026-05-06 cancelled — 无 backend、无产品入口;状态栏旧辅助信息已按产品方向删除,此条不再追踪。问题记录:
docs/problems/2026-05-06-b-class-rebuild.md。) - 给"需要关注"的会话加通知徽标。(审计备注 2026-05-05:状态栏旧
attention辅助信息后续按产品方向删除;core hook 的session.attention事件仍可作为底层能力存在。2026-05-06 新建Sessions > Show Pending Attentionpicker 重建用户入口,filterstatus=attention;tab strip 行级徽标作为后续工作另列。问题记录:docs/problems/2026-05-06-b-class-rebuild.md。) - 加会话快速切换器。(审计备注 2026-05-05:旧 UI 入口后续按产品方向删除。2026-05-06 重建为
Sessions > Quick Switcher菜单 + 默认⌘P快捷键,picker 自动 pinned 优先。问题记录:docs/problems/2026-05-06-b-class-rebuild.md。) - [~] 加命令面板。(2026-05-06 cancelled — 旧 UI 入口已按产品方向删除,仓库内无任何残留代码;命令面板能力被新建的
Sessions一级菜单及对应 picker 覆盖,不再单独追踪。问题记录:docs/problems/2026-05-06-b-class-rebuild.md。) - 加 workspace 搜索功能;支持按名称、描述、路径过滤 workspace,并能从搜索结果直接切换到目标 workspace。问题记录:
docs/problems/2026-05-03-workspace-search.md。 - Workspace 侧栏打磨:左键 "+" 直接在
~创建,右键 "+" 弹文件夹选择菜单;行支持右键 "Rename…" 与 "Set Description…";行单元用可选的 description 替代路径展示,hover 时显示完整文本。新增和重命名都允许重复,DB 的UNIQUE(name)冲突由前端自动加后缀绕过。(2026-05-06 P1 closure:补 sidebar 隐藏恢复按钮、行右侧Workspace actions按钮、自定义color_hex左侧 border 色;脚本测试通过,真实 app 已验收隐藏恢复、行操作菜单和多色列表视觉。)- sub-todo: [x] workspace 容器被缩到完全隐藏时,tab strip 最左侧要出现列表图标;点击该图标恢复正常显示 workspace 容器。问题记录:
docs/problems/2026-05-03-workspace-sidebar-hidden-restore.md。 - sub-todo: [x] workspace 右侧区域参考浏览器/系统侧栏的“展开/打开”交互补齐,明确点击区域、hover 状态和右键行为。问题记录:
docs/problems/2026-05-03-footer-tabs-workspace-polish.md。 - sub-todo: [x] workspace 支持默认行背景,并允许用户自定义左侧 border 颜色;文字颜色只跟随行背景,不跟随 accent 色;选中 workspace 切换时,右侧 active tab 的 top border 与已置顶
pin.fill图标同步该 workspace accent 色。问题记录:docs/problems/2026-05-03-footer-tabs-workspace-polish.md。
- sub-todo: [x] workspace 容器被缩到完全隐藏时,tab strip 最左侧要出现列表图标;点击该图标恢复正常显示 workspace 容器。问题记录:
- Workspace shell dark-mode 一致性审查:sidebar、tab strip、pane header、status bar 统一走
WorkspaceChromeTheme,避免 AppKit 默认浅色背景和 terminal dark theme 打架。(2026-05-06:主 content container 改用 tab strip 的barBackgroundColor,terminal pane 外层加 1pxseparatorColor边线且不改变 terminal renderer 背景;脚本测试通过。)问题记录:docs/problems/2026-05-02-workspace-chrome-and-terminal-output-audit.md。- sub-todo: [x] app 主内容容器背景色要与 tab header 背景色一致,但不能覆盖 workspace sidebar 容器自己的样式。问题记录:
docs/problems/2026-05-03-app-container-header-background.md。 - sub-todo: [x] terminal 边线颜色要与 workspace chrome 一致,线宽 1px 即可。问题记录:
docs/problems/2026-05-03-footer-tabs-workspace-polish.md。
- sub-todo: [x] app 主内容容器背景色要与 tab header 背景色一致,但不能覆盖 workspace sidebar 容器自己的样式。问题记录:
- 主窗口首次显示按配置的启动尺寸打开。问题记录:
docs/problems/2026-05-01-window-launch-size-fitting.md。 - 修复主窗口的拖动 resize、绿色按钮 zoom、双击标题栏 → zoom。问题记录:
docs/problems/2026-05-01-window-resize-and-zoom-pinned.md。
- 从日志里屏蔽已知的密钥模式。
- 默认禁止把含密值写入生成的 agent 配置。
- 加 Rust core 的崩溃恢复。
- 加孤儿进程清理策略。
PtySession注册所有活跃 PTY 进程组;pane 关闭 / session 重启时先按终端语义发送SIGHUP,再用SIGKILL兜底,并通过proc_listchildpids递归清掉 shell 产生的后台子进程。app 退出时统一清理仍注册的 PTY 进程。2026-05-13 第二轮优化:普通 app pane 已改为 Rust corePtySupervisor优先拥有 PTY 和进程组;SwiftPtySession保留为本地 fallback/test 路径。问题记录:docs/problems/2026-05-01-orphan-process-cleanup.md;docs/problems/2026-05-13-core-pty-and-ghostty-truth-source.md。 - 加针对死掉会话的 app 重启行为。
Rust core 增加
session.recover_stale,App 启动 core 后会把无 PID 或 PID 已不存在的 running 会话标记为 exited,并记录session.recovered_stale事件。问题记录:docs/problems/2026-05-02-p1-reliability-data-safety.md。 - 加配置校验,错误信息要清晰。
workspace、MCP、skills、export targets、secret refs、settings 统一走文本/path/env/settings 校验;RPC 将校验失败映射为
invalid_params,错误里包含具体字段。问题记录:docs/problems/2026-05-02-p1-reliability-data-safety.md。 - 加 workspace 元数据的备份 / 导出路径。
config.export --path会创建父目录并写出 JSON 备份;config.import --dry-run可先预览 counts/warnings,正式导入按 workspace 名称映射并重建关联。问题记录:docs/problems/2026-05-02-p1-reliability-data-safety.md。
- 暴露本地 Unix socket API。
- 加 CLI 包装。
- 加打开 workspace 的命令。
- 加启动 agent 的命令。
- 加向 pane 发送文本的命令。
- 加按位置打开浏览器的命令。
- 加进程完成 / 需要关注事件的 hook 系统。
Core 增加
hook.upsert/list/delete/run.listRPC 与 CLIm2terminal hook ...;支持session.exited/session.attention,hook command 通过环境变量拿 session 元数据,执行记录写入hook_runs。问题记录:docs/problems/2026-05-02-automation-hooks-runbooks-packaging.md。 - 加可重复工作流的 runbook 格式。
JSON v1 runbook 支持 workspace.open / agent.start / pane.send_text / browser.open 步骤,
runbook.enqueue可 dry-run 或批量写入 automation queue;CLI 为m2terminal runbook run --path ...。文档:docs/RUNBOOKS.md。
- 把选中的终端输出路由给 agent。
Edit 菜单加 "Send Selection to Pane",默认 ⌘⇧Return(可改
Shortcut.SendSelectionToActivePane)。在任一 pane 选中文本后,触发即弹出目标 pane picker;只有一个 pane 时直接 write 到该 pane 的 PTY。无选区时菜单灰、按键 beep。(审计备注 2026-05-05:文档里的 Edit 菜单路径已过期,当前菜单重组后需要在 App menu 审计中重新确认入口归属。)- sub-todo: [x] 加目标 pane 选择器(弹出 picker 列出所有 pane 的 kind/label,让用户挑发往哪个),不再仅限于 active pane。问题记录:
docs/problems/2026-05-01-agent-context-target-pane-picker.md。
- sub-todo: [x] 加目标 pane 选择器(弹出 picker 列出所有 pane 的 kind/label,让用户挑发往哪个),不再仅限于 active pane。问题记录:
- 把浏览器 URL / 页面摘要路由给 agent。
BrowserPlacementCoordinator持有currentBrowser指向最近一次打开的BrowserViewController;BrowserViewController暴露currentURL和capturePageSummary(_:)(后者跑document.title + body.innerTextJS,主线程回调)。Edit 菜单加两条 "Send Browser URL to Pane" / "Send Browser Summary to Pane",没有内置默认快捷键,但有Shortcut.SendBrowserUrlToActivePane/Shortcut.SendBrowserSummaryToActivePane两个 UserDefaults key 可绑。无浏览器开着时菜单灰。(审计备注 2026-05-05:文档里的 Edit 菜单路径已过期,当前菜单重组后需要在 App menu 审计中重新确认入口归属。)- sub-todo: [x] 给 summary 加可配置的字符上限 / 选区裁剪策略。Management Center 的 Agent Env 页可配置
BrowserSummary.MaxChars与BrowserSummary.SelectionStrategy,支持 prefer-selection / full-page / selection-only。问题记录:docs/problems/2026-05-01-browser-summary-capture-controls.md。 - sub-todo: [x] 浏览器 url 改变时刷新 currentBrowser 元信息(目前只取 init 时记录)。
BrowserViewController观察WKWebView.url/title并回调 coordinator,standalone window 标题随当前页面刷新。问题记录:docs/problems/2026-05-01-browser-current-metadata-refresh.md。
- sub-todo: [x] 给 summary 加可配置的字符上限 / 选区裁剪策略。Management Center 的 Agent Env 页可配置
- 给 agent 会话挂文件或目录附件。
File 菜单加 "Attach Files / Folders to Pane…"(默认无快捷键,可绑
Shortcut.AttachFilesToActivePane)。点击弹NSOpenPanel,允许文件 + 目录、多选;提交后把每个 URL 的.path用BrowserWorkspaceViewController.shellQuote单引号转义、空格拼接、补尾随空格,再弹目标 pane picker 写到选中 pane 的 PTY。(审计备注 2026-05-05:文档里的 File 菜单路径已过期,当前菜单重组后需要在 App menu 审计中重新确认入口归属。)- sub-todo: [x] 终端 pane 接受 Finder drag-and-drop 文件,也走相同的格式化路径。问题记录:
docs/problems/2026-05-01-terminal-file-drag-attachments.md。
- sub-todo: [x] 终端 pane 接受 Finder drag-and-drop 文件,也走相同的格式化路径。问题记录:
- 加 per-agent 的环境模板。
Management Center 加 "Agent Env" 页,支持 Codex / Claude Code / generic 的 JSON 环境模板;CLI
env-template set与 Swift 运行时都校验 key 形状和值类型,自动以env KEY='value' ...前缀应用到 automation 启动的 agent。问题记录:docs/problems/2026-05-01-agent-env-templates.md。 - 加会话标签与置顶。
Session schema / RPC 增加
label、tags、pinned;quick switcher pinned 优先并显示标签,状态栏提供 "sessions/pinned N" 入口编辑 label、逗号分隔 tags 与 pinned 状态。(审计备注 2026-05-05:quick switcher 与sessions/pinned N旧状态栏入口后续已删除;底层 session metadata 能力保留。2026-05-06 重建为Sessions > Edit Session Label & Tags...picker→editor 流程 +Sessions > Pinned Sessionspicker;tab strip 行级 📌 / [label] 渲染作为后续工作另列。问题记录:docs/problems/2026-05-06-b-class-rebuild.md。) - 加跨会话输出搜索。
状态栏和命令面板增加 "Search Terminal Output",跨当前 workspace 的所有 tabs/panes 搜索可见终端输出,结果 picker 展示匹配片段并可跳回 pane。(审计备注 2026-05-05:Search Terminal Output 用户入口后续已按产品方向删除;底层
searchTerminalOutputhelper 仍在。2026-05-06 重建为Sessions > Search Terminal Output菜单 + 默认⌘⇧F,WorkspacePickerWindowController增加enableLiveSearch模式按 keystroke 重新调 helper。问题记录:docs/problems/2026-05-06-b-class-rebuild.md。) - 加 agent 事件时间线。
Core 增加
session_events和session.timelineRPC,自动记录 session start / status change / metadata update;状态栏和命令面板提供 "Agent Event Timeline" picker。(审计备注 2026-05-05:命令面板入口后续已删除;当前只保留 status bar / picker 路径,是否继续保留需要随新 App menu 一起验收。2026-05-06 在Sessions > Event Timeline菜单加薄 wrapper 转 status bar 的showAgentTimeline,空 events 现在显示"无事件"占位行而不再 beep 退出。问题记录:docs/problems/2026-05-06-b-class-rebuild.md。)
- 主题支持。
Management Center 增加 Appearance 页,主题配置独立存到
Terminal.Appearance.*UserDefaults;默认仍是 Technical Precision System。(审计备注 2026-05-05:terminal 主题和基础 native chrome 已做,但窗口 chrome 全量接入/验收仍开放,父项不能算完整完成。)问题记录:docs/problems/2026-05-02-terminal-polish-preferences.md。- sub-todo: [x] 把 terminal theme 扩展到 native workspace chrome,修复 dark 模式下白色 sidebar/tab/status bar。问题记录:
docs/problems/2026-05-02-workspace-chrome-and-terminal-output-audit.md。 - sub-todo: [x] 外观不再跟随系统:默认固定为深色 Technical Precision System,亮色只作为用户手动选择的
VS Code Light主题。 - sub-todo: [x] 将默认主题收口到
Resources/Themes/default.json颜色资源;字体 override 继续走Terminal.Appearance.Font*UserDefaults,workspace 单独选色继续走 workspacecolor_hexmetadata,不进入 theme。问题记录:docs/problems/2026-05-19-theme-color-resource-boundary.md。 - sub-todo: [x] Management Center / picker 窗口已部分接入
WorkspaceChromeTheme,但确认弹窗、side panel、browser 独立窗口和其他 app-owned window 尚未完成全量清单和真实 app 验收;2026-05-06 已建立 app-owned window 清单、补齐剩余 alert 样式入口,并完成真实 app 验收。问题记录:docs/problems/2026-05-06-p2-polish-completion.md。
- sub-todo: [x] 把 terminal theme 扩展到 native workspace chrome,修复 dark 模式下白色 sidebar/tab/status bar。问题记录:
- 字体配置。
Appearance 页支持 font family / font size / line height,启动时通过
TerminalTheme.current()生成终端 theme。 - 设计 M2Terminal logo:使用两个
M的简单直观图形,整体要能联想到 terminal;左边M最右侧竖线与右边M最左侧竖线共用同一笔。(2026-05-19 已接入Resources/Images/logo.png,生成logo.icns,About 使用 PNG,打包脚本通过CFBundleIconFile=logo.icns接入 app icon。)问题记录:docs/problems/2026-05-03-m2terminal-logo.md。 - App menu 优化:只保留 Settings、View、Help 三组入口,并把三组里的配置内容做完整,不允许只移动菜单或保留无效入口。2026-05-06 将 Sessions 收入
View > Sessions,补View > Pane Layout真实入口,并完成脚本测试与真实 app 验收。问题记录:docs/problems/2026-05-06-p2-polish-completion.md。- sub-todo: [x] Settings 必须只放实际可用的配置入口;普通设置、MCP、Skills、API Tokens、workspace 启用、AI 交互/通知、快捷键等入口要能打开对应配置页,缺失配置页必须补齐或从菜单移除。
- sub-todo: [x] View 必须只放视图和当前 workspace/tab 相关的可用操作;主题 Light/Dark、主题包导入/注入要有真实状态反馈和持久化配置,不能只是菜单占位。
- sub-todo: [x] Help 仅保留统一样式的 About M2Terminal,显示名称与版本号并使用 app logo。
- sub-todo: [x] 真实 app 验收:逐项打开 Settings / View / Help 下的所有菜单项,确认没有旧菜单、无效菜单、空壳窗口、错误快捷键或未接线 action。
- 所有 app 打开的窗口都要统一到当前设计风格,包括 Settings、Help、picker、side panel、确认弹窗与管理窗口;前次只接入了部分窗口,不算完成。2026-05-06 建立
AppOwnedWindowRegistry并补齐剩余 alert/window chrome 路径。问题记录:docs/problems/2026-05-06-p2-polish-completion.md。- sub-todo: [x] 建立 app-owned window 清单,覆盖主窗口之外所有由 M2Terminal 创建的窗口、面板、picker、side panel、确认弹窗、帮助窗口和管理窗口。
- sub-todo: [x] 所有 app-owned window 必须经过统一 window chrome / theme 入口创建或套样式;禁止新的散落
NSWindow/NSAlert默认样式直接出现在用户可见路径。 - sub-todo: [x] 对系统
NSOpenPanel/NSSavePanel这类不可完全定制的系统面板,触发入口、标题、按钮文案和前后承接界面要保持 M2Terminal 风格,并在验收记录里单独标注。 - sub-todo: [x] 真实 app 验收:逐个打开窗口并检查背景、字体、间距、边框、hover、按钮、空状态和错误状态是否与当前 shell 风格一致。
- sub-todo: [x] AI 会话管理面板必须是收敛的管理窗口,不能默认撑满或超出屏幕;首开时按当前屏幕可见区域钳制尺寸,并压缩侧栏、列表行、详情头部和会话气泡的固定留白。问题记录:
docs/problems/2026-05-08-ai-session-management-panel.md。
- 国际化:menu 与 app 界面上的所有用户可见文本都要提取到语言包;前次只覆盖了部分路径,不算完成。2026-05-06 补齐新增 P2 字符串,并增加语言包完整性与占位符一致性测试。问题记录:
docs/problems/2026-05-06-p2-polish-completion.md。- sub-todo: [x] 全仓扫描并列出所有用户可见硬编码文本,覆盖 menu、alerts、buttons、tooltips、status、empty states、picker、side panels、validation errors、placeholder 和 help 文案。
- sub-todo: [x] 所有用户可见文本统一通过语言包 key 读取;新增用户可见字符串必须同时补 English 与简体中文。
- sub-todo: [x] 加语言包完整性测试:缺 key、占位符不匹配、仍残留明显硬编码用户文案时测试失败。
- sub-todo: [x] 真实 app 验收:分别以 English 与简体中文启动 app,打开 main menu、Settings、View、Help、picker、side panel、确认弹窗和错误提示,确认没有混合语言或 key 泄漏。
- 快捷键编辑器。
- sub-todo: [x] ⌘T / ⌘N 快捷键通过 UserDefaults 可配置。基础已落在
Sources/M2Terminal/Shortcut.swift—— 解析cmd+shift+t这种字符串成菜单 key equivalent;用户覆盖 key 为Shortcut.NewTab与Shortcut.NewWorkspace。 - sub-todo: [x] 在同一组
UserDefaultskey 之上做编辑器 UI。
- sub-todo: [x] ⌘T / ⌘N 快捷键通过 UserDefaults 可配置。基础已落在
- Pane 布局预设。
2026-05-06 改为
View > Pane Layout用户入口,包含 Single / Two Columns / Two Rows / Focus + Stack;只重排当前 workspace group。问题记录:docs/problems/2026-05-06-p2-polish-completion.md。 - 辅助功能(accessibility)走查。
- sub-todo: [x] 所有当前图标按钮和状态图标 hover 时提供解释性 tooltip/help,包括 workspace/sidebar、status bar、Management Center 的 SwiftUI icon labels。问题记录:
docs/problems/2026-05-02-icon-tooltip-coverage.md。 - sub-todo: [x] footer 路径必须持续显示;footer 所有图标补齐 hover 提示;AI CLI session 要与 workspace 绑定,并提供 AI session 列表入口。2026-05-06 footer 增加
AI sessions图标并按当前 workspace 过滤非 shell 会话;无 active pane path 时显示 localized empty state。2026-05-08 对齐 cc-switch 的选择后启动模型:AI sessions 不再与 tab 强绑定,只列 Codex / Claude Code;列表以 Codex / Claude Code 自己的 history JSONL 和具体resume <session-id>为准,不展示Codex #4这类内部 core id;在当前 workspace 点击恢复会创建新 tab 并执行codex resume <id>或claude --resume <id>。同日把入口升级为单例「会话管理」窗口,左侧卡片列表 + provider 筛选,右侧详情展示 resume id、恢复/删除和等宽 transcript。问题记录:docs/problems/2026-05-06-p2-polish-completion.md、docs/problems/2026-05-08-ai-session-workspace-restore.md、docs/problems/2026-05-08-ai-session-management-panel.md。
- sub-todo: [x] 所有当前图标按钮和状态图标 hover 时提供解释性 tooltip/help,包括 workspace/sidebar、status bar、Management Center 的 SwiftUI icon labels。问题记录:
- 大输出量的性能基准。
增加
TerminalOutputBenchmark与scripts/benchmark_terminal_output.sh,覆盖大块 ANSI 输出、空输出和极小 chunk 边界。 - 打包与 app 签名。
保留
scripts/setup_signing_cert.sh/scripts/build_app.sh,新增scripts/package_app.sh:构建、codesign verify、zip.app、生成 sha256。文档:docs/PACKAGING_AND_UPDATES.md。 - 自动更新策略。
新增
scripts/generate_update_manifest.sh生成静态update.json(version/build/url/sha256/size/min OS);后续 in-app updater 必须先校验 SHA-256 再替换 app。文档:docs/PACKAGING_AND_UPDATES.md。
- 加 per-agent 的 MCP servers 与 skills 导出开关。
- 从 M2Terminal 配置生成 Codex 兼容的 MCP / skills 配置。
- 从 M2Terminal 配置生成 Claude Code 兼容的 MCP / skills 配置。
MCP 端:按 agent / workspace 范围筛选启用项,Codex 渲染为
config.toml风格 TOML,Claude Code 渲染为{"mcpServers": {...}}JSON,写入目标路径并附 SHA-256 checksum 入历史表。 Skills 端:把启用的 skill 在<target_dir>/skills/<name>处建符号链接指向Skill.source_path;找不到 source 的发 warning 跳过。 入口:RPCexport.run {id, workspace_id?, dry_run?}与 CLIm2terminal export run --target-id N/m2terminal export run-agent --agent-kind codex|claude-code --target-path PATH(实现:crates/m2terminal-core/src/export.rs)。- sub-todo: [x] 加 per-workspace 的导出范围,不只导全局。
- sub-todo: [x] 与 P1 "Prevent secret values from being written" 串起来:把
env_refs里的$secret:*引用替换或剔除。
- 写出生成的 agent 配置之前先做 dry-run 与 diff 预览。
- 检测生成的 Codex 或 Claude Code 配置文件被手动改动后的漂移。
- 加导出指定 agent 目标配置的命令。
- MCP CRUD 收口为“名称 + 创建后不可变唯一标识 + stdio JSON 配置”模型,Codex / Claude Code 导出使用唯一标识作为外部 key,并补 Playwright MCP 真实配置 smoke 脚本。问题记录:
docs/problems/2026-05-19-mcp-json-crud-agent-export.md。