docs: add pre-implementation spikes section to design spec
Three spikes gating the implementation plan: - Spike 1: pane mode capability (tmux split + cleanup) - Spike 2: data source stability (SQLite fields + JSONL event names) - Spike 3: inline fallback safety (scroll region + terminal cleanup) Each spike has goal, verification method, pass criteria, and fallback decisions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -356,7 +356,128 @@ inline 初始化失败 --> 自动降级到 passthrough mode
|
|||||||
- install 必须可逆(one command uninstall)
|
- install 必须可逆(one command uninstall)
|
||||||
- shell rc 修改使用标记块,安装幂等
|
- shell rc 修改使用标记块,安装幂等
|
||||||
|
|
||||||
## 10. Confidence & Risk Assessment
|
## 10. Pre-Implementation Spikes
|
||||||
|
|
||||||
|
> 这三个 spike 必须在写 implementation plan 之前完成。每个 spike 是独立的小脚本或手工验证,目标是锁定架构假设,不是实现功能。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Spike 1: Pane Mode Capability
|
||||||
|
|
||||||
|
**目标:** 确认 tmux/zellij 下可靠分屏、在主 pane 跑真实 codex、退出后自动清理 HUD pane。
|
||||||
|
|
||||||
|
**验证方法:**
|
||||||
|
```bash
|
||||||
|
# 在 tmux session 内运行:
|
||||||
|
# 1. 用 display-message 探测 session 可操作性
|
||||||
|
tmux display-message -p '#{session_id}'
|
||||||
|
|
||||||
|
# 2. split 出 4 行底部 pane,在里面跑 watch 模拟 HUD
|
||||||
|
tmux split-window -v -l 4 'watch -n 0.5 date'
|
||||||
|
|
||||||
|
# 3. 在主 pane 跑真实 codex(或任意 full-screen TUI,如 vim)
|
||||||
|
codex
|
||||||
|
|
||||||
|
# 4. 退出 codex,验证 HUD pane 是否自动关闭
|
||||||
|
# 用 tmux kill-pane -t <pane_id> 从代码层面关闭
|
||||||
|
```
|
||||||
|
|
||||||
|
**通过标准:**
|
||||||
|
- `display-message` 在正常 session 下返回有效 session_id,在嵌套/只读 session 下可检测失败
|
||||||
|
- split pane 成功,HUD pane 内容独立于主 pane,主 pane codex TUI 不受干扰
|
||||||
|
- codex 退出后,`tmux kill-pane` 能可靠关闭 HUD pane,不留残留
|
||||||
|
|
||||||
|
**失败后的降级决策:**
|
||||||
|
- 探测不可靠 → pane mode 进入条件收紧,宁可误降级到 inline 也不误进 pane
|
||||||
|
- kill-pane 不可靠 → pane 生命周期改为"codex 退出时发送信号给 HUD 子进程,HUD 进程自行退出"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Spike 2: Data Source Stability
|
||||||
|
|
||||||
|
**目标:** 确认 `state_5.sqlite` 和 `sessions/*.jsonl` 哪些字段在活动会话里稳定更新,哪些不可依赖。
|
||||||
|
|
||||||
|
**验证方法:**
|
||||||
|
```bash
|
||||||
|
# 1. 跑一个真实 codex session,同时在另一窗口执行:
|
||||||
|
|
||||||
|
# SQLite:每 2 秒看 threads 表最新行
|
||||||
|
watch -n 2 'sqlite3 ~/.codex/state_5.sqlite \
|
||||||
|
"SELECT model, cwd, git_branch, tokens_used, updated_at \
|
||||||
|
FROM threads ORDER BY updated_at DESC LIMIT 3"'
|
||||||
|
|
||||||
|
# SQLite:看 jobs/agent_jobs 表是否有更新
|
||||||
|
sqlite3 ~/.codex/state_5.sqlite ".tables"
|
||||||
|
sqlite3 ~/.codex/state_5.sqlite "SELECT * FROM jobs LIMIT 5"
|
||||||
|
|
||||||
|
# JSONL:tail 最新 session 文件,观察 type 字段分布
|
||||||
|
tail -f ~/.codex/sessions/$(date +%Y/%m/%d)/rollout-*.jsonl | \
|
||||||
|
python3 -c 'import sys,json; [print(json.loads(l).get("type","?")) for l in sys.stdin]'
|
||||||
|
```
|
||||||
|
|
||||||
|
**通过标准(按字段逐一确认):**
|
||||||
|
|
||||||
|
| 字段 | 预期来源 | 通过标准 |
|
||||||
|
|------|----------|----------|
|
||||||
|
| `threads.model` | SQLite | session 开始时写入,不频繁变化 |
|
||||||
|
| `threads.cwd` | SQLite | 准确反映当前工作目录 |
|
||||||
|
| `threads.git_branch` | SQLite | 与 `git branch --show-current` 一致 |
|
||||||
|
| `threads.tokens_used` | SQLite | 随对话进行递增 |
|
||||||
|
| `threads.updated_at` | SQLite | 每轮对话后更新 |
|
||||||
|
| JSONL `type` 字段 | JSONL | 每个事件都有 type,且值稳定可枚举 |
|
||||||
|
| JSONL tool/task 事件 | JSONL | 至少能识别 tool 调用开始/结束、task 进度 |
|
||||||
|
|
||||||
|
**失败后的降级决策:**
|
||||||
|
- `tokens_used` 不更新 → HUD 不显示 tokens,标 n/a
|
||||||
|
- JSONL 事件名不稳定 → normalize 层对所有未知 type 返回 null,HUD 对应字段降为 n/a
|
||||||
|
- `git_branch` 不准确 → 改为本地 `git branch --show-current` 补充
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Spike 3: Inline Fallback Safety
|
||||||
|
|
||||||
|
**目标:** 确认 `codex --no-alt-screen` 下能预留底部区域,且 wrapper crash/exit 后不会弄脏终端。
|
||||||
|
|
||||||
|
**验证方法:**
|
||||||
|
```bash
|
||||||
|
# 1. 确认 --no-alt-screen 模式下 codex 以滚动方式输出
|
||||||
|
codex --no-alt-screen
|
||||||
|
|
||||||
|
# 2. 用小脚本模拟 scroll region + 底部 HUD,然后正常退出和异常退出各跑一次
|
||||||
|
node -e "
|
||||||
|
process.stdout.write('\x1b[s'); // save cursor
|
||||||
|
process.stdout.write('\x1b[1;' + (process.stdout.rows - 4) + 'r'); // scroll region
|
||||||
|
process.stdout.write('\x1b[' + (process.stdout.rows - 3) + ';1H'); // move to HUD area
|
||||||
|
process.stdout.write('=== HUD TEST LINE ===');
|
||||||
|
process.stdout.write('\x1b[u'); // restore cursor
|
||||||
|
setTimeout(() => {
|
||||||
|
// cleanup
|
||||||
|
process.stdout.write('\x1b[r'); // reset scroll region
|
||||||
|
process.stdout.write('\x1b[' + process.stdout.rows + ';1H\x1b[2K'); // clear HUD
|
||||||
|
console.log('cleaned up');
|
||||||
|
}, 3000);
|
||||||
|
"
|
||||||
|
|
||||||
|
# 3. 验证 Ctrl-C 后终端是否正常(光标可见,滚动恢复)
|
||||||
|
# 4. 在不同终端宽度下测试(80, 120, 200 列)
|
||||||
|
```
|
||||||
|
|
||||||
|
**通过标准:**
|
||||||
|
- scroll region 设置后,主内容区域可滚动,底部 4 行固定不动
|
||||||
|
- 正常退出后终端恢复原始状态(光标可见,scroll region 清除)
|
||||||
|
- Ctrl-C / kill 后终端不残留 HUD 内容,不留隐藏光标
|
||||||
|
- macOS Terminal.app + iTerm2 + Ghostty 下行为一致(至少两种实测)
|
||||||
|
|
||||||
|
**失败后的降级决策:**
|
||||||
|
- scroll region 在任一目标终端不稳定 → inline mode 标记为"实验性",默认不启用,需 `--inline` flag 显式开启
|
||||||
|
- cleanup 不可靠 → cleanup 逻辑改为双重保险:正常路径 + `process.on('exit')` 兜底
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**三个 spike 全部通过后,才进入 implementation plan。**
|
||||||
|
每个 spike 的结论(通过 / 部分通过 + 条件 / 失败 + 降级)应记录在 implementation plan 的前置说明中。
|
||||||
|
|
||||||
|
## 11. Confidence & Risk Assessment
|
||||||
|
|
||||||
### 10.1 已确认(可直接依赖)
|
### 10.1 已确认(可直接依赖)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user