docs: record spike 2 results, add spike 1/3 manual scripts
Spike 2 (data source) completed: - All SQLite threads fields verified stable (model, cwd, git_branch, tokens_used) - JSONL event names stable across 2 sessions (function_call, task_started, token_count, etc.) - Bonus: token_count event has rate_limits.primary/secondary.used_percent and plan_type - HudState updated with rateLimitPrimary, rateLimitSecondary, planType fields Spike 1 (pane mode): pending - tmux not installed, manual steps documented Spike 3 (inline): pending - needs real TTY, test script provided Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -140,6 +140,11 @@ type HudState = {
|
|||||||
toolCounts: Record<string, number>
|
toolCounts: Record<string, number>
|
||||||
taskProgress: { done: number; total: number } | null
|
taskProgress: { done: number; total: number } | null
|
||||||
|
|
||||||
|
// from JSONL token_count event (bonus: rate limit data)
|
||||||
|
rateLimitPrimary: { usedPercent: number; windowMinutes: number; resetsAt: number } | null
|
||||||
|
rateLimitSecondary: { usedPercent: number; windowMinutes: number; resetsAt: number } | null
|
||||||
|
planType: string | null // "plus" | "pro" | "team" | ...
|
||||||
|
|
||||||
// from timer
|
// from timer
|
||||||
elapsedSec: number
|
elapsedSec: number
|
||||||
|
|
||||||
@@ -360,6 +365,14 @@ inline 初始化失败 --> 自动降级到 passthrough mode
|
|||||||
|
|
||||||
> 这三个 spike 必须在写 implementation plan 之前完成。每个 spike 是独立的小脚本或手工验证,目标是锁定架构假设,不是实现功能。
|
> 这三个 spike 必须在写 implementation plan 之前完成。每个 spike 是独立的小脚本或手工验证,目标是锁定架构假设,不是实现功能。
|
||||||
|
|
||||||
|
**Spike 状态总览(2026-03-22):**
|
||||||
|
|
||||||
|
| Spike | 状态 | 结论 |
|
||||||
|
|-------|------|------|
|
||||||
|
| Spike 1: Pane Mode Capability | 待手工验证 | tmux 未安装,需先安装再测 |
|
||||||
|
| Spike 2: Data Source Stability | **已完成** | SQLite + JSONL 均稳定可依赖,有额外 rate limit 发现 |
|
||||||
|
| Spike 3: Inline Fallback Safety | 待手工验证 | 需在真实 TTY 中运行测试脚本 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Spike 1: Pane Mode Capability
|
### Spike 1: Pane Mode Capability
|
||||||
@@ -391,6 +404,9 @@ codex
|
|||||||
- 探测不可靠 → pane mode 进入条件收紧,宁可误降级到 inline 也不误进 pane
|
- 探测不可靠 → pane mode 进入条件收紧,宁可误降级到 inline 也不误进 pane
|
||||||
- kill-pane 不可靠 → pane 生命周期改为"codex 退出时发送信号给 HUD 子进程,HUD 进程自行退出"
|
- kill-pane 不可靠 → pane 生命周期改为"codex 退出时发送信号给 HUD 子进程,HUD 进程自行退出"
|
||||||
|
|
||||||
|
**当前状态(2026-03-22):tmux 未安装,待手工验证。**
|
||||||
|
手工步骤:`brew install tmux` → 在 tmux session 内运行上述验证命令 → 记录结论。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Spike 2: Data Source Stability
|
### Spike 2: Data Source Stability
|
||||||
@@ -434,6 +450,54 @@ tail -f ~/.codex/sessions/$(date +%Y/%m/%d)/rollout-*.jsonl | \
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Spike 2 结论(已完成,2026-03-22)
|
||||||
|
|
||||||
|
**SQLite `threads` 表 — 全部字段已验证稳定:**
|
||||||
|
|
||||||
|
| 字段 | 实测值样本 | 结论 |
|
||||||
|
|------|-----------|------|
|
||||||
|
| `model` | `gpt-5.4` | 稳定,session 开始时写入 |
|
||||||
|
| `cwd` | `/Users/manpengan/pro/nas-infra` | 稳定,准确 |
|
||||||
|
| `git_branch` | `main` / 空字符串(非 git 目录) | 稳定,非 git 目录为空字符串 |
|
||||||
|
| `tokens_used` | `710865`, `6413335` | 稳定递增,线程累计值 |
|
||||||
|
| `updated_at` | Unix timestamp(秒) | 每轮对话更新 |
|
||||||
|
|
||||||
|
**JSONL 事件 — 跨 2 个 session 验证,事件名稳定:**
|
||||||
|
|
||||||
|
| event 类型 | payload.type | 关键字段 | HUD 用途 |
|
||||||
|
|-----------|--------------|----------|----------|
|
||||||
|
| `session_meta` | — | `cwd`, `cli_version`, `model_provider` | session 初始化 |
|
||||||
|
| `event_msg` | `task_started` | `turn_id`, `model_context_window: 258400` | turn 开始,context window 大小 |
|
||||||
|
| `event_msg` | `task_complete` | `turn_id`, `last_agent_message` | turn 结束 |
|
||||||
|
| `event_msg` | `token_count` | `rate_limits.primary.used_percent`, `secondary.used_percent`, `plan_type` | **rate limit 显示** |
|
||||||
|
| `event_msg` | `agent_message` | `message`, `phase` | agent 回复内容 |
|
||||||
|
| `response_item` | `function_call` | `name`(工具名), `call_id` | tool 开始 |
|
||||||
|
| `response_item` | `function_call_output` | `call_id`(匹配) | tool 结束 |
|
||||||
|
| `response_item` | `reasoning` | 内部推理 | 可忽略 |
|
||||||
|
| `turn_context` | — | `cwd`, `timezone`, `approval_policy` | 每轮上下文 |
|
||||||
|
|
||||||
|
**额外发现(超出原预期):**
|
||||||
|
- `token_count.rate_limits` 直接给出 `primary.used_percent`(5分钟窗口)和 `secondary.used_percent`(周窗口)
|
||||||
|
- 这是 claude-hud 需要单独调用 OAuth API 才能拿到的数据,Codex 直接写在 JSONL 里
|
||||||
|
- `model_context_window: 258400` 给出每个 turn 的 context 窗口大小
|
||||||
|
|
||||||
|
**结论对 HudState 的影响:**
|
||||||
|
- `tokensUsedTotal`:来自 SQLite `threads.tokens_used`,可信
|
||||||
|
- `rateLimitPrimary` / `rateLimitSecondary`:来自 `token_count` JSONL 事件,可信(**新增字段**)
|
||||||
|
- `activeTool`:来自 `function_call` / `function_call_output` 配对,可信
|
||||||
|
- `taskProgress`:无直接字段,需从 `task_started`/`task_complete` 事件计数推断
|
||||||
|
- context window usage:`model_context_window` 大小已知,但当前 turn 的 input token 数暂未找到来源
|
||||||
|
|
||||||
|
**更新后的 HudState(在 Section 4.2 中同步):**
|
||||||
|
```typescript
|
||||||
|
// 新增字段(来自 token_count 事件)
|
||||||
|
rateLimitPrimary: { usedPercent: number; windowMinutes: number; resetsAt: number } | null
|
||||||
|
rateLimitSecondary: { usedPercent: number; windowMinutes: number; resetsAt: number } | null
|
||||||
|
planType: string | null // "plus" | "pro" | ...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Spike 3: Inline Fallback Safety
|
### Spike 3: Inline Fallback Safety
|
||||||
|
|
||||||
**目标:** 确认 `codex --no-alt-screen` 下能预留底部区域,且 wrapper crash/exit 后不会弄脏终端。
|
**目标:** 确认 `codex --no-alt-screen` 下能预留底部区域,且 wrapper crash/exit 后不会弄脏终端。
|
||||||
@@ -472,6 +536,36 @@ setTimeout(() => {
|
|||||||
- scroll region 在任一目标终端不稳定 → inline mode 标记为"实验性",默认不启用,需 `--inline` flag 显式开启
|
- scroll region 在任一目标终端不稳定 → inline mode 标记为"实验性",默认不启用,需 `--inline` flag 显式开启
|
||||||
- cleanup 不可靠 → cleanup 逻辑改为双重保险:正常路径 + `process.on('exit')` 兜底
|
- cleanup 不可靠 → cleanup 逻辑改为双重保险:正常路径 + `process.on('exit')` 兜底
|
||||||
|
|
||||||
|
**当前状态(2026-03-22):需在真实 TTY 中手工验证。**
|
||||||
|
在真实终端(非 Claude Code 子 shell)中运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 保存到 /tmp/spike3.mjs 后执行:node /tmp/spike3.mjs
|
||||||
|
const rows = process.stdout.rows;
|
||||||
|
const cols = process.stdout.columns;
|
||||||
|
if (!rows) { console.error('Not a TTY'); process.exit(1); }
|
||||||
|
console.log(`Terminal: ${cols}x${rows}`);
|
||||||
|
process.stdout.write('\x1b[s');
|
||||||
|
process.stdout.write(`\x1b[1;${rows - 4}r`);
|
||||||
|
process.stdout.write(`\x1b[${rows - 3};1H\x1b[2K=== HUD 1: model | cwd | main* | 2m ===`);
|
||||||
|
process.stdout.write(`\x1b[${rows - 2};1H\x1b[2K=== HUD 2: tokens 12,340 | Write 3s ===`);
|
||||||
|
process.stdout.write(`\x1b[${rows - 1};1H\x1b[2K=== HUD 3: shell(3) read(7) ===`);
|
||||||
|
process.stdout.write(`\x1b[${rows};1H\x1b[2K=== HUD 4: task 3/5 ===`);
|
||||||
|
process.stdout.write('\x1b[u');
|
||||||
|
setTimeout(() => {
|
||||||
|
process.stdout.write('\x1b[r');
|
||||||
|
for (let i = rows - 3; i <= rows; i++)
|
||||||
|
process.stdout.write(`\x1b[${i};1H\x1b[2K`);
|
||||||
|
process.stdout.write(`\x1b[${rows};1H`);
|
||||||
|
console.log('\nCLEANUP OK');
|
||||||
|
}, 3000);
|
||||||
|
```
|
||||||
|
|
||||||
|
通过标准:
|
||||||
|
- HUD 4 行固定在底部,主区域可自由滚动
|
||||||
|
- 3 秒后自动清除,光标恢复,终端无残留
|
||||||
|
- 在 macOS Terminal.app / iTerm2 / Ghostty 中各测一次
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**三个 spike 全部通过后,才进入 implementation plan。**
|
**三个 spike 全部通过后,才进入 implementation plan。**
|
||||||
|
|||||||
Reference in New Issue
Block a user