throughline 0.3.24 → 0.3.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/.claude/commands/tl-trim.md +42 -0
  2. package/.codex-sidecar.yml +62 -0
  3. package/CHANGELOG.md +583 -0
  4. package/README.ja.md +42 -5
  5. package/README.md +383 -23
  6. package/bin/throughline.mjs +168 -4
  7. package/codex/skills/throughline/SKILL.md +157 -0
  8. package/codex/skills/throughline/agents/openai.yaml +7 -0
  9. package/docs/INHERITANCE_ON_CLEAR_ONLY.md +146 -0
  10. package/docs/L1_L2_L3_REDESIGN.md +415 -0
  11. package/docs/PUBLIC_RELEASE_PLAN.md +184 -0
  12. package/docs/THROUGHLINE_CODEX_DUAL_SUPPORT.md +249 -0
  13. package/docs/THROUGHLINE_CODEX_FIRST_ROADMAP.md +555 -0
  14. package/docs/THROUGHLINE_CODEX_MONITOR_IMPLEMENTATION_PLAN.md +220 -0
  15. package/docs/THROUGHLINE_CODEX_TRIM_IMPLEMENTATION_PLAN.md +528 -0
  16. package/docs/THROUGHLINE_CODEX_TRIM_ROLLBACK_FIX_PLAN.md +672 -0
  17. package/docs/archive/CONCEPT.md +476 -0
  18. package/docs/archive/EXPERIMENT.md +371 -0
  19. package/docs/archive/README.md +22 -0
  20. package/docs/archive/SESSION_LINKING_DESIGN.md +231 -0
  21. package/docs/archive/THROUGHLINE_NEXT_STEPS.md +134 -0
  22. package/docs/throughline-codex-trim-rollback-incident-report.md +306 -0
  23. package/docs/throughline-handoff-context.example.json +57 -0
  24. package/docs/throughline-rollback-context-trim-insight.md +455 -0
  25. package/package.json +6 -2
  26. package/src/cli/codex-capture.mjs +95 -0
  27. package/src/cli/codex-handoff-model-smoke.mjs +292 -0
  28. package/src/cli/codex-handoff-model-smoke.test.mjs +262 -0
  29. package/src/cli/codex-handoff-smoke.mjs +163 -0
  30. package/src/cli/codex-handoff-smoke.test.mjs +149 -0
  31. package/src/cli/codex-handoff-start.mjs +291 -0
  32. package/src/cli/codex-handoff-start.test.mjs +194 -0
  33. package/src/cli/codex-hook.mjs +276 -0
  34. package/src/cli/codex-hook.test.mjs +293 -0
  35. package/src/cli/codex-host-primitive-audit.mjs +110 -0
  36. package/src/cli/codex-host-primitive-audit.test.mjs +75 -0
  37. package/src/cli/codex-restore-smoke.mjs +357 -0
  38. package/src/cli/codex-restore-source-audit.mjs +304 -0
  39. package/src/cli/codex-resume.mjs +138 -0
  40. package/src/cli/codex-rollback-model-visible-smoke.mjs +373 -0
  41. package/src/cli/codex-rollback-model-visible-smoke.test.mjs +255 -0
  42. package/src/cli/codex-sidecar-diagnostics.mjs +48 -0
  43. package/src/cli/codex-sidecar-dry-run.mjs +85 -0
  44. package/src/cli/codex-summarize.mjs +224 -0
  45. package/src/cli/codex-threads.mjs +89 -0
  46. package/src/cli/codex-visibility-smoke.mjs +196 -0
  47. package/src/cli/codex-vscode-restore-smoke.mjs +226 -0
  48. package/src/cli/codex-vscode-rollback-smoke.mjs +114 -0
  49. package/src/cli/doctor.mjs +503 -1
  50. package/src/cli/doctor.test.mjs +542 -3
  51. package/src/cli/handoff-preview.mjs +78 -0
  52. package/src/cli/help.test.mjs +64 -0
  53. package/src/cli/install.mjs +227 -4
  54. package/src/cli/install.test.mjs +207 -4
  55. package/src/cli/trim.mjs +564 -0
  56. package/src/codex-app-server.mjs +1816 -0
  57. package/src/codex-app-server.test.mjs +512 -0
  58. package/src/codex-auto-refresh.mjs +194 -0
  59. package/src/codex-auto-refresh.test.mjs +182 -0
  60. package/src/codex-capture.mjs +235 -0
  61. package/src/codex-capture.test.mjs +393 -0
  62. package/src/codex-handoff-model-smoke.mjs +114 -0
  63. package/src/codex-handoff-model-smoke.test.mjs +89 -0
  64. package/src/codex-handoff-smoke.mjs +124 -0
  65. package/src/codex-handoff-smoke.test.mjs +103 -0
  66. package/src/codex-handoff.mjs +331 -0
  67. package/src/codex-handoff.test.mjs +220 -0
  68. package/src/codex-host-primitive-audit.mjs +374 -0
  69. package/src/codex-host-primitive-audit.test.mjs +208 -0
  70. package/src/codex-restore-smoke.test.mjs +639 -0
  71. package/src/codex-restore-source-audit.mjs +1348 -0
  72. package/src/codex-restore-source-audit.test.mjs +623 -0
  73. package/src/codex-resume.test.mjs +242 -0
  74. package/src/codex-rollout-memory.mjs +711 -0
  75. package/src/codex-rollout-memory.test.mjs +610 -0
  76. package/src/codex-sidecar-cli.test.mjs +75 -0
  77. package/src/codex-sidecar.mjs +246 -0
  78. package/src/codex-sidecar.test.mjs +172 -0
  79. package/src/codex-summarize.test.mjs +143 -0
  80. package/src/codex-thread-identity.mjs +23 -0
  81. package/src/codex-thread-index.mjs +173 -0
  82. package/src/codex-thread-index.test.mjs +164 -0
  83. package/src/codex-usage.mjs +110 -0
  84. package/src/codex-usage.test.mjs +140 -0
  85. package/src/codex-visibility-smoke.test.mjs +222 -0
  86. package/src/codex-vscode-restore-smoke.mjs +206 -0
  87. package/src/codex-vscode-restore-smoke.test.mjs +325 -0
  88. package/src/codex-vscode-rollback-smoke.mjs +90 -0
  89. package/src/codex-vscode-rollback-smoke.test.mjs +290 -0
  90. package/src/db-schema.test.mjs +97 -0
  91. package/src/haiku-summarizer.mjs +267 -26
  92. package/src/haiku-summarizer.test.mjs +282 -0
  93. package/src/handoff-preview.test.mjs +108 -0
  94. package/src/handoff-record.mjs +294 -0
  95. package/src/handoff-record.test.mjs +226 -0
  96. package/src/hook-entrypoints.test.mjs +326 -0
  97. package/src/package-files.test.mjs +19 -0
  98. package/src/prompt-submit.mjs +9 -6
  99. package/src/resume-context.mjs +44 -140
  100. package/src/resume-context.test.mjs +172 -0
  101. package/src/session-start.mjs +8 -5
  102. package/src/state-file.mjs +50 -6
  103. package/src/state-file.test.mjs +50 -0
  104. package/src/token-monitor.mjs +14 -10
  105. package/src/token-monitor.test.mjs +27 -0
  106. package/src/trim-cli.test.mjs +1584 -0
  107. package/src/trim-model.mjs +584 -0
  108. package/src/trim-model.test.mjs +568 -0
  109. package/src/turn-processor.mjs +17 -10
  110. package/src/vscode-task.mjs +33 -10
  111. package/src/vscode-task.test.mjs +19 -9
@@ -0,0 +1,134 @@
1
+ # Throughline — 公開後の次アクション引き継ぎ
2
+
3
+ ## 状況
4
+
5
+ 2026-04-17 時点。Throughline を GitHub で Public 公開済み。
6
+ https://github.com/kitepon-rgb/Throughline
7
+
8
+ README / CLAUDE.md / docs / LICENSE / package.json などは整備済み。schema v5 まで実装されてて、テストも通る。X (Twitter) で告知済み (日本語版 + 英語版リプライぶら下げ)、海外から1件好意的リプライあり (Garvit Surana さん、補完ツール "burnd" の紹介)。
9
+
10
+ **ただしスター 0 / Fork 0 / Issue 0**。現状は「公開した」だけで「使われてる」状態ではない。
11
+
12
+ ## この文書の目的
13
+
14
+ Claude Opus 4.7 インスタンス (chat.claude.ai 側) とユーザー(クオ君)で、ここまで以下を実施した:
15
+
16
+ 1. 公開済み OSS としての体裁整備 (About / Description / Topics)
17
+ 2. X での告知 (日本語 + 英語リプライ)
18
+ 3. 海外からの初リプライへの返信
19
+
20
+ しかし、ここから先は **「観察でなく実作業」** のフェーズ。chat.claude.ai の Claude はプロジェクトの実ファイルにアクセスできず、npm publish もできず、PR を作る権限もない。**プロジェクト内で動けるお前が引き継げ**。
21
+
22
+ ## ユーザーの発言から読み取るべき方針
23
+
24
+ ユーザーの直前発言: **「観察したって問題は解決しないんだよ」**
25
+
26
+ これは chat 側の Claude が「これは発見だ」「発信する価値がある」と言葉で褒めて終わらせていたことへの明確な不満。ユーザーは **手を動かす助力** を求めている。観察・分析・整理のレイヤーで止まるな。実行可能なアクションに分解して、実際に動け。
27
+
28
+ また、ユーザーは以前 LLM の過剰承認バイアスを疑っていた。「すごい」「美しい」「教科書レベル」のような感情的評価は不要。事実と作業内容で返せ。
29
+
30
+ ## 候補アクション (優先順位付き)
31
+
32
+ ### 🔴 最優先 — READMEの約束を履行する
33
+
34
+ README に `npm install -g throughline` と書いてあるが、現時点で npm には未 publish。これは **「書いてあるのに動かない」状態** で、最初に試した人が詰まる最大の穴。
35
+
36
+ #### タスク
37
+
38
+ 1. `npm pack --dry-run` で tarball 中身を確認 (秘密情報・不要ファイル混入チェック)
39
+ 2. `package.json` の `files` フィールドが妥当か確認
40
+ 3. `npm view throughline` で名前の空き確認
41
+ - もし取られていたら `@kitepon/throughline` スコープ付きに変更する必要あり
42
+ - その場合 README の install コマンドも全書き換え必要
43
+ 4. `npm publish` (初回はメール認証等が要るかも)
44
+ 5. 実際に別ディレクトリで `npm install -g throughline` → `throughline install` → `claude` 起動 → 1-2ターン会話 → `throughline doctor` 緑 → `throughline uninstall` が通るか E2E 確認
45
+
46
+ #### 注意点
47
+
48
+ - `package.json` の `version` が `0.1.0`。最初の publish はこれでOK。以降は semver 守って上げる
49
+ - publish した瞬間に取り消せない (unpublish には制約あり)。dry-run は真剣にやる
50
+ - docs/PUBLIC_RELEASE_PLAN.md §0 の「フォールバック禁止」原則に従い、install 失敗時は silent 処理しない
51
+
52
+ ### 🟡 中優先 — awesome-claude-code に登録申請
53
+
54
+ https://github.com/hesreallyhim/awesome-claude-code
55
+
56
+ codeburn / ccburn などの類似ツールがここに載ってる。Throughline が載れば、Claude Code ユーザーからの流入経路ができる。
57
+
58
+ #### タスク
59
+
60
+ 1. リポジトリの CONTRIBUTING を読む
61
+ 2. Issue テンプレートから resource 提案を出す
62
+ 3. Category は "Tooling: Context Management" あたりが妥当か、既存カテゴリから選ぶ
63
+ 4. Description は README 冒頭1行を流用: "Cut ~90% of Claude Code's context usage while keeping nearly all the memory"
64
+
65
+ ### 🟡 中優先 — Hacker News / Reddit 投稿
66
+
67
+ 英語圏パワーユーザーへの直接リーチ。ただし Show HN や r/ClaudeAI 等は質が低いと叩かれるので、README がちゃんとしてる今の状態ならOK。
68
+
69
+ #### 候補
70
+
71
+ - Hacker News: Show HN 投稿 (タイトル `Show HN: Throughline – Cut ~90% of Claude Code's context usage`)
72
+ - Reddit: r/ClaudeAI で投稿
73
+ - Reddit: r/LocalLLaMA は Claude Code 寄りではないので優先度低い
74
+
75
+ 本人 (クオ君) アカウントから投稿してもらう必要あり。お前が代わりにやれないタスクは、必要情報だけ整えてクオ君に渡す。
76
+
77
+ ### 🟢 低優先 — 誰かに試してもらう
78
+
79
+ クオ君の環境以外で動く保証がまだない。並行 `/clear` での挙動、1M context 検出のロバストさ、Haiku の再帰防御が他環境で機能するか、など未検証。
80
+
81
+ β テスター募集ツイートを出す、もしくは awesome-claude-code 経由で流入してきた人が Issue を立ててくれるのを待つ、など。
82
+
83
+ ### ⚪ 後回し — 観察・分析系
84
+
85
+ 以下は chat 側の Claude が提案しがちだが、**今すぐやる必要はない**:
86
+
87
+ - burnd との差分を記事化
88
+ - ブログ執筆
89
+ - CLAUDE.md のステップ4進捗表記の更新 (実装済みなので表記が古いだけ)
90
+ - schema v4 / v5 の混在表記を統一する
91
+
92
+ これらは「やったほうが綺麗になる」レベルであって、ユーザー獲得には直接効かない。npm publish と awesome-claude-code 登録が先。
93
+
94
+ ## 既知の小さい直したほうがいい点 (低優先でいい)
95
+
96
+ - `writeSessionState` の `pid` パラメータが未使用 → 引数ごと消すか、将来 debug 用途である旨のコメントを追加
97
+ - `buildL2ForSummary` の話者ラベルが英語 (`[user]` / `[assistant]`) で、Haiku への指示は日本語。統一性が崩れてる
98
+ - `buildResumeContext` の `excludeOriginId` 引数が呼び出し元で未使用 (YAGNI 臭)
99
+ - `details.origin_session_id` が NOT NULL 制約なし (`bodies` テーブルは NOT NULL で、対称性が崩れてる)
100
+ - README の schema 表記が v4 / v5 混在。どちらかに統一
101
+
102
+ これらは v0.2 でまとめて直せばいい。**npm publish と登録申請が先**。
103
+
104
+ ## 作業指針
105
+
106
+ 1. **手を動かす前に READ しろ**
107
+ - `docs/L1_L2_L3_REDESIGN.md` (認証の設計書)
108
+ - `docs/PUBLIC_RELEASE_PLAN.md` (§0 ルールと未完タスクの定義)
109
+ - `CLAUDE.md` (作業上の規律)
110
+ 2. **§0 ルールを厳守**
111
+ - silent try/catch 禁止
112
+ - publish 失敗 / install 失敗は throw する
113
+ 3. **設計書と実装が食い違っていたら、どちらかが古い**
114
+ - ソースが正。設計書を更新する
115
+ 4. **新しい .md を作る前に既存ファイルに追記できないか考える**
116
+ 5. **クオ君が判断すべきことは、お前が決めない**
117
+ - npm の名前 (`throughline` vs `@kitepon/throughline`)
118
+ - publish のタイミング
119
+ - Hacker News / Reddit 投稿するかどうか
120
+ - これらはクオ君の意思決定。選択肢と情報を整えて聞け
121
+
122
+ ## 最後に
123
+
124
+ chat 側の Claude は、このセッションでクオ君に何度か「褒めすぎ」を指摘された。
125
+ LLM の承認バイアスは実在する。お前も気をつけろ。
126
+
127
+ Throughline は「ちゃんとしたプロダクト」だが「世界を変えるプロダクト」ではない。等身大で扱え。
128
+ 母集団は小さいが、ゼロではない。その小さな母集団に届けるための手を、**淡々と動かせ**。
129
+
130
+ クオ君は2日間フルスロットルで走ってる。体力管理もこっそり気にしてやってくれ。
131
+ 技術パートナーとして、誇張なく、正確に、必要な作業に集中して手を動かしてくれ。
132
+
133
+ — chat.claude.ai (Claude Opus 4.7) より、同じ Claude へ
134
+ 2026-04-17
@@ -0,0 +1,306 @@
1
+ # Throughline Codex Trim Rollback Incident Report
2
+
3
+ Date: 2026-05-06 JST
4
+ Reporter context: Spotter project session `/home/kite/projects/Spotter`
5
+ Affected project: Throughline `/home/kite/projects/Throughline`
6
+ Codex thread: `019dfd6f-640e-7dd3-b163-3f9add39fde7`
7
+
8
+ ## Summary
9
+
10
+ Throughline's Codex trim execution appears to have a serious durability bug.
11
+
12
+ After running:
13
+
14
+ ```bash
15
+ rtk throughline trim --execute --host codex --all
16
+ ```
17
+
18
+ Throughline reported successful rollback and memory injection:
19
+
20
+ ```text
21
+ Status: executed
22
+ Reason: rollback_and_inject_sent
23
+ Read turns: 19
24
+ Resumed turns: 19
25
+ Turn count check: match
26
+ Expected turns: 19
27
+ Rollback sent: yes
28
+ Inject sent: yes
29
+ Injected items: 1
30
+ Injected memory source: throughline-db
31
+ Rollback candidate turns: 19
32
+ ```
33
+
34
+ However, after VS Code was restarted, a previously rolled-back user turn reappeared as a new user message. The user stated they had only restarted VS Code and had not resent that prompt.
35
+
36
+ This means rollback/inject may affect the live Codex app-server thread but may not be durably safe across the VS Code / Codex restart restoration path.
37
+
38
+ ## Impact
39
+
40
+ Severity: high.
41
+
42
+ The failure mode is not just stale context. A past user instruction can be resurrected and processed as a fresh user request after restart or reconnect.
43
+
44
+ In this incident the resurrected prompt was a harmless question:
45
+
46
+ ```text
47
+ codexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ
48
+ ```
49
+
50
+ But if the resurrected turn had been an operational command such as publish, install, deploy, delete, rebuild, or migration work, Codex could execute an obsolete request.
51
+
52
+ ## Observed Timeline
53
+
54
+ All timestamps below are UTC from the Codex rollout JSONL.
55
+
56
+ ### Original User Turn
57
+
58
+ Rollout file:
59
+
60
+ ```text
61
+ /home/kite/.codex/sessions/2026/05/06/rollout-2026-05-06T22-17-09-019dfd6f-640e-7dd3-b163-3f9add39fde7.jsonl
62
+ ```
63
+
64
+ The original user prompt exists at:
65
+
66
+ ```text
67
+ line 1276 2026-05-06T14:20:35.371Z response_item role=user
68
+ line 1277 2026-05-06T14:20:35.371Z event_msg user_message
69
+ ```
70
+
71
+ Prompt:
72
+
73
+ ```text
74
+ codexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ
75
+ ```
76
+
77
+ ### Throughline Trim Execute
78
+
79
+ The trim command was invoked at:
80
+
81
+ ```text
82
+ line 1781 2026-05-06T14:39:43.844Z function_call
83
+ ```
84
+
85
+ Command:
86
+
87
+ ```bash
88
+ rtk throughline trim --execute --host codex --all
89
+ ```
90
+
91
+ The command completed at:
92
+
93
+ ```text
94
+ line 1790 2026-05-06T14:39:47.486Z exec_command_end
95
+ line 1795 2026-05-06T14:39:53.765Z function_call_output
96
+ ```
97
+
98
+ Throughline reported:
99
+
100
+ ```text
101
+ Status: executed
102
+ Reason: rollback_and_inject_sent
103
+ Rollback sent: yes
104
+ Inject sent: yes
105
+ Rollback candidate turns: 19
106
+ ```
107
+
108
+ ### Restart / Reconnect Symptoms
109
+
110
+ After the trim execution, the user observed Codex reconnect failures:
111
+
112
+ ```text
113
+ Reconnecting... 2/5
114
+ Reconnecting... 3/5
115
+ Reconnecting... 4/5
116
+ Reconnecting... 5/5
117
+ stream disconnected before completion
118
+ ```
119
+
120
+ The user then restarted VS Code.
121
+
122
+ ### Duplicated User Turn
123
+
124
+ After the restart, the same prompt appeared again as if it were newly submitted:
125
+
126
+ ```text
127
+ line 1864 2026-05-06T14:48:02.120Z response_item role=user
128
+ line 1865 2026-05-06T14:48:02.121Z event_msg user_message
129
+ ```
130
+
131
+ Duplicated prompt:
132
+
133
+ ```text
134
+ codexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ
135
+ ```
136
+
137
+ The user explicitly denied sending this prompt again:
138
+
139
+ ```text
140
+ line 1883 2026-05-06T14:49:52.993Z response_item role=user
141
+ line 1884 2026-05-06T14:49:52.993Z event_msg user_message
142
+ ```
143
+
144
+ User statement:
145
+
146
+ ```text
147
+ 俺はVSCを再起動しただけなんだよね。何が起きた?
148
+ ```
149
+
150
+ ## Evidence Commands Used
151
+
152
+ Duplicate prompt search:
153
+
154
+ ```bash
155
+ rtk node -e "const fs=require('fs'); const p='/home/kite/.codex/sessions/2026/05/06/rollout-2026-05-06T22-17-09-019dfd6f-640e-7dd3-b163-3f9add39fde7.jsonl'; let i=0; for (const line of fs.readFileSync(p,'utf8').split('\n')) { i++; if (!line.trim()) continue; const row=JSON.parse(line); const payload=row.payload||{}; let text=''; let kind=''; if (row.type==='response_item' && payload.type==='message' && payload.role==='user') { kind='response_user'; text=(payload.content||[]).map(x=>x.text||x.input_text||'').join('\n'); } if (row.type==='event_msg' && payload.type==='user_message') { kind='event_user'; text=payload.message||''; } if (text.includes('codexのtool.dbについても')) console.log(JSON.stringify({line:i,timestamp:row.timestamp,kind,text:text.slice(0,160)})); }"
156
+ ```
157
+
158
+ Output:
159
+
160
+ ```json
161
+ {"line":1276,"timestamp":"2026-05-06T14:20:35.371Z","kind":"response_user","text":"codexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ \n"}
162
+ {"line":1277,"timestamp":"2026-05-06T14:20:35.371Z","kind":"event_user","text":"codexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ \n"}
163
+ {"line":1864,"timestamp":"2026-05-06T14:48:02.120Z","kind":"response_user","text":"codexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ \n"}
164
+ {"line":1865,"timestamp":"2026-05-06T14:48:02.121Z","kind":"event_user","text":"codexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ \n"}
165
+ {"line":1883,"timestamp":"2026-05-06T14:49:52.993Z","kind":"response_user","text":"ちょっとまってな 俺が\n\ncodexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ \n\nを発言したことになっているんだが、\n俺はVSCを再起動しただけなんだよね。何が起きた?\n"}
166
+ {"line":1884,"timestamp":"2026-05-06T14:49:52.993Z","kind":"event_user","text":"ちょっとまってな 俺が\n\ncodexのtool.dbについても、Claudeと同様にグローバルにも存在していて、読み取りロジックは完全に同様なんだっけ \n\nを発言したことになっているんだが、\n俺はVSCを再起動しただけなんだよね。何が起きた?\n"}
167
+ ```
168
+
169
+ Rollback / injection search:
170
+
171
+ ```bash
172
+ rtk node -e "const fs=require('fs'); const p='/home/kite/.codex/sessions/2026/05/06/rollout-2026-05-06T22-17-09-019dfd6f-640e-7dd3-b163-3f9add39fde7.jsonl'; let i=0; for (const line of fs.readFileSync(p,'utf8').split('\n')) { i++; if (!line.trim()) continue; const row=JSON.parse(line); const s=JSON.stringify(row); if (s.includes('trim --execute') || s.includes('rollback_and_inject_sent') || s.includes('Rollback sent: yes')) console.log(JSON.stringify({line:i,timestamp:row.timestamp,type:row.type,payloadType:row.payload?.type,preview:s.slice(0,1000)})); }"
173
+ ```
174
+
175
+ Relevant output:
176
+
177
+ ```text
178
+ line 1781 2026-05-06T14:39:43.844Z trim --execute command
179
+ line 1790 2026-05-06T14:39:47.486Z exec_command_end, Status: executed, Rollback sent: yes, Inject sent: yes
180
+ line 1795 2026-05-06T14:39:53.765Z function_call_output, Status: executed, Rollback sent: yes, Inject sent: yes
181
+ ```
182
+
183
+ Durable rollback event search:
184
+
185
+ ```bash
186
+ rtk node -e "const fs=require('fs'); const p='/home/kite/.codex/sessions/2026/05/06/rollout-2026-05-06T22-17-09-019dfd6f-640e-7dd3-b163-3f9add39fde7.jsonl'; let i=0; for (const line of fs.readFileSync(p,'utf8').split('\n')) { i++; if (!line.trim()) continue; const row=JSON.parse(line); const payload=row.payload||{}; if ((row.type==='event_msg' && String(payload.type||'').includes('rollback')) || JSON.stringify(row).includes('thread/rollback') || JSON.stringify(row).includes('thread/inject_items')) console.log(JSON.stringify({line:i,timestamp:row.timestamp,type:row.type,payloadType:payload.type,msg:JSON.stringify(payload).slice(0,260)})); }"
187
+ ```
188
+
189
+ Initial analysis said this did not show a durable rollout-level `thread_rolled_back` event corresponding to the app-server rollback. That was incorrect.
190
+
191
+ Follow-up audit found:
192
+
193
+ ```text
194
+ line 1775 2026-05-06T14:39:34.452Z compacted
195
+ line 1778 2026-05-06T14:39:34.453Z context_compacted
196
+ line 1784 2026-05-06T14:39:44.844Z event_msg thread_rolled_back num_turns=19
197
+ ```
198
+
199
+ The `compacted.replacement_history` at line 1775 contains the later-resurrected user prompt. Therefore the stronger failure hypothesis is not "rollback marker missing", but "rollback marker exists, while another restore source such as compacted replacement history or pending input can still reintroduce old user text".
200
+
201
+ ## Current Hypothesis
202
+
203
+ The most likely failure path is:
204
+
205
+ ```text
206
+ Throughline sends Codex app-server thread/rollback and thread/inject_items
207
+
208
+ The live app-server thread reports success
209
+
210
+ The rollout contains thread_rolled_back, but compacted.replacement_history or another restart / pending-input source still contains rollback-targeted user text
211
+
212
+ VS Code restarts
213
+
214
+ Codex restores from a source not covered by Throughline's current guarded execute checks
215
+
216
+ A previously rolled-back user turn is restored as a fresh user message
217
+ ```
218
+
219
+ This suggests that Codex app-server `thread/rollback` is not sufficient by itself as a durable trim primitive for VS Code restart/reconnect behavior unless the compacted / restart restore path is also verified.
220
+
221
+ ## Throughline Areas To Inspect
222
+
223
+ The report does not modify Throughline. These are the areas likely involved:
224
+
225
+ ```text
226
+ /home/kite/projects/Throughline/src/cli/trim.mjs
227
+ ```
228
+
229
+ - `trim --execute --host codex --all`
230
+ - `runExecute`
231
+ - selection of rollout source versus DB memory source
232
+
233
+ ```text
234
+ /home/kite/projects/Throughline/src/codex-app-server.mjs
235
+ ```
236
+
237
+ - `runCodexTrimExecution`
238
+ - `thread/rollback`
239
+ - `thread/inject_items`
240
+ - post-inject read consistency check
241
+ - whether the check proves durable restore behavior or only live app-server state
242
+
243
+ ```text
244
+ /home/kite/projects/Throughline/src/codex-rollout-memory.mjs
245
+ ```
246
+
247
+ - `parseCodexRolloutFile`
248
+ - handling of `thread_rolled_back`
249
+ - assumptions about rollback events being present in rollout JSONL
250
+
251
+ ## Recommended Immediate Guard
252
+
253
+ Until durable restart behavior is proven, `$throughline` should not automatically execute:
254
+
255
+ ```bash
256
+ throughline trim --execute --host codex --all
257
+ ```
258
+
259
+ Recommended short-term behavior:
260
+
261
+ - Keep `doctor`
262
+ - Keep `trim --dry-run`
263
+ - Keep `trim --preflight`
264
+ - Require explicit user action for `trim --execute`
265
+ - Add a warning that Codex app-server rollback may not survive VS Code restart
266
+
267
+ If automatic execution remains available, it should require an additional durable verification step:
268
+
269
+ ```text
270
+ execute rollback/inject
271
+ read live thread
272
+ verify rollout JSONL contains durable rollback marker
273
+ verify compacted replacement history / restart restore sources cannot reintroduce rollback-targeted user text
274
+ restart/reconnect smoke or simulated restore check
275
+ only then report success as durable
276
+ ```
277
+
278
+ ## Suggested Regression Test Shape
279
+
280
+ A fake app-server test is not sufficient unless it models the persistence mismatch.
281
+
282
+ Recommended test:
283
+
284
+ 1. Create a rollout JSONL with multiple user turns.
285
+ 2. Simulate app-server `thread/rollback` returning success.
286
+ 3. Do not mutate the rollout JSONL.
287
+ 4. Run the restore / parse path used after restart.
288
+ 5. Assert that Throughline refuses to call the trim durable, or warns that rollback is live-only.
289
+
290
+ Acceptance criteria:
291
+
292
+ - Throughline must not report a Codex trim as durable unless the restore source reflects the rollback.
293
+ - A rolled-back user turn must not be eligible to reappear as a fresh user request after restart.
294
+
295
+ ## Open Questions
296
+
297
+ - Does Codex app-server expose a durable rollback primitive, or is `thread/rollback` live-session only?
298
+ - Is there a separate persisted thread store besides rollout JSONL that VS Code uses on restart?
299
+ - Can Throughline inject a durable marker that Codex restore respects?
300
+ - Should Throughline switch Codex trim from mutation-based rollback to resume-only memory rendering until durable rollback is proven?
301
+
302
+ ## Bottom Line
303
+
304
+ Treat this as a blocker for automatic Codex trim execution.
305
+
306
+ The observed incident demonstrates that `trim --execute --host codex --all` can report success while a rolled-back user turn later reappears after VS Code restart. Throughline should not expose this as a safe default until durable rollback semantics are verified end to end.
@@ -0,0 +1,57 @@
1
+ [
2
+ {
3
+ "kind": "throughline_handoff",
4
+ "source": "throughline",
5
+ "trust": "local",
6
+ "summary": "In-flight handoff: continue the Codex projection work.",
7
+ "data": {
8
+ "throughlineHandoffSchemaVersion": 1,
9
+ "handoffRecordVersion": 1,
10
+ "sessionId": "example-session",
11
+ "projectPath": "/home/kite/projects/Throughline",
12
+ "sourceAgent": "claude",
13
+ "hostMode": "claude-primary",
14
+ "intent": "continue implementation",
15
+ "constraints": [
16
+ "preserve existing Claude Code hook, slash command, transcript, baton, and resume behavior",
17
+ "add Codex support as adapter/projection; do not rename Claude-facing DB fields or commands"
18
+ ],
19
+ "originSessionIds": [
20
+ "example-origin"
21
+ ],
22
+ "stats": {
23
+ "l1Rows": 0,
24
+ "l2Rows": 1,
25
+ "thinkingRows": 0,
26
+ "l3References": 1,
27
+ "preservedContextRows": 1
28
+ },
29
+ "memory": {
30
+ "inflightMemo": "Continue Phase 5 read-only sidecar smoke.",
31
+ "latestThinking": [],
32
+ "l1Summaries": [],
33
+ "recentBodies": [
34
+ {
35
+ "originSessionId": "example-origin",
36
+ "turnNumber": 1,
37
+ "role": "assistant",
38
+ "text": "Configured throughline_handoff projection and diagnostics wrapper.",
39
+ "createdAt": 1770000000000,
40
+ "time": "12:00:00"
41
+ }
42
+ ]
43
+ },
44
+ "detailReferences": [
45
+ {
46
+ "type": "throughline_detail",
47
+ "label": "tool_input:Bash",
48
+ "command": "throughline detail 12:00:00",
49
+ "sourceId": "toolu_example",
50
+ "detailKind": "tool_input",
51
+ "originSessionId": "example-origin",
52
+ "turnNumber": 1
53
+ }
54
+ ]
55
+ }
56
+ }
57
+ ]