throughline 0.3.23 → 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 +400 -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 +94 -6
  111. package/src/vscode-task.test.mjs +186 -6
@@ -0,0 +1,415 @@
1
+ # 新 L1/L2/L3 設計(再定義)
2
+
3
+ > **Status**: 実装完了(2026-04-16 時点)。この文書は **L1/L2/L3 再定義の設計記録**であり、schema v4-v5 相当の変更までを扱う。以後の `handoff_batons` (v6)・`memo_text` (v7)・state.usage スナップショット・VSCode 自動起動・monitor 診断機能は本仕様と独立で、[CLAUDE.md](../CLAUDE.md) と [PUBLIC_RELEASE_PLAN.md](PUBLIC_RELEASE_PLAN.md) に索引あり。
4
+ > 全ステップ (1〜8) 実装済み。L1/L2/L3 すべて書き込みパスが稼働。schema v5 で details に `kind` / `source_id` 列追加済み。
5
+ > 進捗の詳細は「実装順序」セクション末尾の進捗表を参照。
6
+
7
+ ## Context
8
+
9
+ 現行実装は [docs/archive/CONCEPT.md](archive/CONCEPT.md) の原義から乖離しており、L1/L2 ともに段落先頭の機械的な切り詰めになっている。その結果:
10
+
11
+ - L1 の末尾(=結論)が常に失われ、文脈理解できない
12
+ - L1 と L2 が「同じ本文の別切り方」になっており質的階層になっていない
13
+ - L3 は SQLite にあるが `/sc-detail` 未実装で取り出せない「墓場」
14
+ - 完了済み ISSUE が L2 に溜まり続ける
15
+
16
+ ユーザーとの対話で、現行設計を捨てて新しい層定義を採用することに合意した。
17
+
18
+ ## 新 L1/L2/L3 定義
19
+
20
+ 3 層は **差分の関係**。L2 と L3 は補完関係にあり、重複しない。
21
+
22
+ | 層 | 役割 | 中身 | コンテキスト |
23
+ |---|---|---|---|
24
+ | **L1** 見出し | L2 を要約した 1 行索引 | Haiku 4.5 による要約(目標圧縮率 1/5) | 常駐(古いターンのみ、新しいターンは L2 があるので不要) |
25
+ | **L2** 本文 | 会話の自然言語部分 | ユーザー発言 + Claude のユーザー向け返答 | 常駐 |
26
+ | **L3** 裏方 | L2 に入れなかったもの | ツール入力、ツール出力、システムメッセージ、画像 | SQLite 退避、`/sc-detail <時刻>` でオンデマンド参照 |
27
+
28
+ ### ノイズ除去ルール(全層共通)
29
+
30
+ 以下は意味ゼロのノイズなので、L2 にも L3 にも保存しない:
31
+
32
+ - 空行・連続空白・インデント装飾だけの行
33
+ - 進捗表示(プログレスバー、パーセント、`████░░`)
34
+ - ANSI エスケープシーケンス
35
+ - 繰り返しの定型ヘッダ/フッタ(毎ターン同じ内容のリマインダ等)
36
+
37
+ ### L2 に残すもの(明示)
38
+
39
+ - ユーザーが貼り付けた長大な生ログ(stacktrace、ビルドログ、JSON ダンプ等)
40
+ - Claude の返答に含まれるコードブロック
41
+ - TODO リスト構造化ブロック
42
+
43
+ これらは「会話の一部」として扱い、切り落とさない。
44
+
45
+ ### L2 = L3 から何を引くか
46
+
47
+ L3(ノイズ除去後の全文)から以下を除いて L2 を作る:
48
+
49
+ 1. ツールの入力(Bash コマンド、Read/Edit/Grep の引数)
50
+ 2. ツールの出力(stdout/stderr、ファイル内容、検索結果)
51
+ 3. システムメッセージ(フック注入、リマインダ、`<system-reminder>` 等)
52
+ 4. 画像データ
53
+
54
+ これら 4 項目が L3 に入る。
55
+
56
+ **思考ブロック(extended thinking)は L2 にも L3 にも保存しない**。素の Claude Code のコンテキストでも思考ブロックはターン境界で削除されているため、比較対象と揃える意味で保存しない。signature 付きブロックの再注入問題も同時に解消。
57
+
58
+ ### 比較の基準
59
+
60
+ 新設計の評価は「`/clear` しなかった場合の素の Claude Code のコンテキスト」と比較する。引き算にしかならない設計なので、デフォルトより重くなる状況は原理的に存在しない。
61
+
62
+ ---
63
+
64
+ ## L1 生成方針
65
+
66
+ ### モデル
67
+
68
+ **Haiku 4.5(`claude-haiku-4-5-20251001`)固定**。
69
+
70
+ ### 呼び出し経路
71
+
72
+ **Claude Max 契約前提**。Anthropic API キーは使わず、`claude -p --model claude-haiku-4-5-20251001` を `child_process.spawn` で子プロセス起動する。認証は Claude Code CLI が管理している Max 契約の枠を使う。実機で 3 回成功を確認済み(Throughline ベンチマーク中)。
73
+
74
+ Windows 環境では `claude.cmd` ラッパー解決のため `shell: true` または `claude.cmd` を明示する。
75
+
76
+ ### タイミング
77
+
78
+ **ターン終了時(Stop フック内)で実行**。Haiku 呼び出しと DB 書き込みは同じ process-turn 実行内で順次走り、完了してから確定する。
79
+
80
+ **v0.3.22 からは Stop フック自体を `"async": true` で登録する**。Claude 本体のターン完了 → ユーザー表示を Haiku 要約の数秒〜数十秒で待たせていた問題を解消するため、process-turn は Claude Code から fire-and-forget で起動される。L1 要約は**次** SessionStart 注入用なので今ターンをブロックする理由が無い。
81
+
82
+ > 旧設計文(2025 年時点): 「Claude 本体の返答時間に比べて要約呼び出しの数秒は誤差。非同期化の実装複雑性を払う価値がない」 — 実運用で Bell + Spotter の 84 ターン長尺セッションにおいて体感悪化が観測されたため、2026-04-19 時点で撤回。Claude Code hooks schema の `async: true` フィールドがこの切替を 1 行で実現できるため、実装複雑性の負担も無い。
83
+
84
+ ### 圧縮率
85
+
86
+ **目標 1/5**。Haiku 4.5 の実測ベンチマークに基づく。
87
+
88
+ 実測結果(2 サンプル、原文 1,400〜1,850 文字):
89
+
90
+ | 圧縮率 | 新聞記事(並列トピック 4 本) | 技術論文(直列論旨) |
91
+ |---|---|---|
92
+ | 1/5 | 論点・固有名詞・数値・因果すべて保持 | 同左 |
93
+ | 1/10 | ホルムズ海峡の話が消失(論点 1/4 脱落) | 1/5 とほぼ同品質 |
94
+ | 1/20 | 1 論点のみ残存、不合格 | 未測定 |
95
+
96
+ 並列トピック耐性を考慮して **1/5 を下限・デフォルト** とする。コーディング会話は通常単一トピックなので 1/10 でも成立するが、Claude の長文返答が並列議論になるケースに備えて保守側を採る。
97
+
98
+ ### 失敗時のポリシー
99
+
100
+ 1. Haiku 呼び出しを **2 回リトライ**
101
+ 2. それでも失敗したら **L2 の全文をそのまま L1 として保存**
102
+
103
+ 理由:情報欠損ゼロ、データ構造に穴が空かない、後工程の分岐不要、後から再要約可能。
104
+
105
+ ---
106
+
107
+ ## スキーマ変更(schema v4)
108
+
109
+ ```sql
110
+ -- skeletons: L1 = 1 行要約(意味変更、列は据え置き)
111
+ -- summary 列に Haiku 要約 or フォールバック時の L2 全文が入る
112
+
113
+ -- 新テーブル: bodies(L2 = 会話の自然言語本文)
114
+ CREATE TABLE bodies (
115
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
116
+ session_id TEXT NOT NULL,
117
+ origin_session_id TEXT NOT NULL,
118
+ turn_number INTEGER NOT NULL,
119
+ role TEXT NOT NULL, -- user | assistant
120
+ text TEXT NOT NULL,
121
+ token_count INTEGER,
122
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
123
+ UNIQUE(session_id, origin_session_id, turn_number, role)
124
+ );
125
+
126
+ -- details: L3 = ツール入出力・思考・システムメッセージ・画像
127
+ -- 現行の details テーブルを拡張し、tool_name 以外のカテゴリも受け入れる
128
+ -- もしくは kind 列を追加して区別する
129
+
130
+ -- judgments: 廃止。v4 で DROP
131
+ -- 理由: 素の Claude Code のコンテキストには「判断ラベル付き抽出リスト」は存在しない。
132
+ -- Throughline が勝手に作り出した余計な層であり、新設計の原則「比較対象は素の Claude、
133
+ -- そこからの引き算」に反する(引き算ではなく足し算)。
134
+ -- L2 ロスレスで 20 ターン保持しているので、制約・決定・未解決事項は会話本文内に自然な
135
+ -- 文として残る。素の Claude と同じく、会話本文を読めば十分。
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 生成パイプライン(Stop フック)
141
+
142
+ ```
143
+ Stop フック受信
144
+
145
+ transcript から当該ターンを取得
146
+
147
+ ブロック分類(ノイズ除去を先に実行)
148
+ ├→ ユーザー発言 / Claude 本文 → L2 (bodies) に INSERT
149
+ └→ ツール I/O / 思考 / システム / 画像 → L3 (details) に INSERT
150
+
151
+ Haiku 4.5 で L2 を約 1/5 に要約(同期、2 回リトライ)
152
+ ├→ 成功 → skeletons に要約を INSERT
153
+ └→ 失敗 → skeletons に L2 全文を INSERT(フォールバック)
154
+ ```
155
+
156
+ ---
157
+
158
+ ## 注入パイプライン(SessionStart フック)
159
+
160
+ > **変更履歴**: 当初は UserPromptSubmit で毎ターン注入していたが、SessionStart と完全に重複するため廃止。注入は SessionStart の 1 回のみ。
161
+
162
+ 注入対象は **前任チェーンの過去ターンのみ**。現セッション内のターンは Claude Code 本体のコンテキストに既に全文入っているので注入不要。
163
+
164
+ ```
165
+ merge chain をたどり前任セッションのターンを時系列順に取得
166
+
167
+ 前任の直近 20 ターン → bodies から L2 全文を注入
168
+ 前任のそれ以前のターン → skeletons から L1 要約のみ注入
169
+
170
+ 末尾に "/sc-detail <id> で退避データ復元可" のガイドを追記
171
+ ```
172
+
173
+ ### 注入テキストの新フォーマット
174
+
175
+ 各行頭に **現セッション視点のローカル連番 ID**(`#1`, `#2`, ...)を付ける。Claude はこの ID をそのまま `/sc-detail` に渡せる。
176
+
177
+ ```
178
+ ## Throughline: セッション記憶
179
+
180
+ ### 直近のターン履歴
181
+ [14:23:05] [user]: 〜〜
182
+ [14:23:05] [assistant]: 〜〜
183
+ ...
184
+ [15:47:12] [assistant]: 〜〜
185
+
186
+ ### それ以前の要約
187
+ [13:02:11] 要約1行...
188
+ [13:05:34] 要約1行...
189
+
190
+ ---
191
+ 過去ターンの詳細は `/sc-detail <時刻>` で取得可能(例: /sc-detail 14:23:05、/sc-detail 14:23-14:30)
192
+ ```
193
+
194
+ ### Claude に気づかせる仕組み
195
+
196
+ 1. **注入テキスト末尾に案内文**(上記例の末尾行)
197
+ 2. **各行頭の ID 表示**(Claude が自然に参照できる形で)
198
+
199
+ CLAUDE.md への記載は **しない**。配布時、新規プロジェクトで Throughline を導入したユーザーが手動で CLAUDE.md を編集する必要が出ると利便性の障害になる。注入テキスト自体で完結させる。
200
+
201
+ ### `/sc-detail` コマンド仕様
202
+
203
+ - **ID は bodies テーブルの `created_at`(時刻ベース、DB 永続)を使う**
204
+ - 注入テキストの行頭に `[14:23:05]` の形式で時刻を表示
205
+ - `/sc-detail 14:23:05` → 指定時刻のターンの L2 + L3 をまとめて返す
206
+ - `/sc-detail 14:23-14:30` → 時刻範囲指定、複数ターンまとめて取得
207
+ - L2 と L3 を別コマンドに分けない(「このターンの詳細が欲しい」という Claude の意図に一発で答える)
208
+
209
+ ### なぜ時刻ベースか
210
+
211
+ 当初案の「ローカル連番 `#1, #2, ...`」は注入時に動的に採番されるだけで DB に保存されず、次ターンで連番がずれる問題があった。`created_at` は DB に永続保存されているので安定した ID になる。時刻は人間にも可読で範囲指定も自然。同一秒に複数ターンが終わる可能性はほぼ無い(Claude Code の 1 ターンには数秒以上かかる)。
212
+
213
+ **N=20 固定**。
214
+
215
+ 根拠 1(原理): 比較対象は「`/clear` せずに会話を続けた場合の素の Claude Code」であり、新設計はそこからツール入出力等を引き算したものなので、原理的にデフォルトより重くなる状況は存在しない。トークン予算制にする必要はない。
216
+
217
+ 根拠 2(実測): ユーザーの Claude Code 全トランスクリプト(`~/.claude/projects/` 配下、1,739 ファイル、Throughline プロジェクトは除外)から実作業セッション(3 ターン以上)86 件を抽出して分布を測った:
218
+
219
+ | 指標 | ターン数 |
220
+ |---|---|
221
+ | 中央値 (p50) | 13 |
222
+ | p25 | 5 |
223
+ | p75 | 34 |
224
+ | p90 | 71 |
225
+ | p95 | 108 |
226
+ | 最大 | 331 |
227
+
228
+ N=20 は中央値の約 1.5 倍、p75 の少し下。典型的なセッションは丸ごと L2 全文注入でき、長めのセッション(p75 以上)は超過分が L1 要約に格下げされる、という設計が自然に成立する。
229
+
230
+ ---
231
+
232
+ ## 影響ファイル
233
+
234
+ - [src/turn-processor.mjs](../src/turn-processor.mjs) — Stop フック本体。ブロック分類 + Haiku 呼び出し + 3 テーブル書き込み
235
+ - `src/classifier.mjs` — **廃止**(judgments 廃止に伴い役割消滅)
236
+ - ~~src/context-injector.mjs~~ — **廃止**(SessionStart との重複注入解消。注入は SessionStart に一本化)
237
+ - [src/session-start.mjs](../src/session-start.mjs) — 引き継ぎ注入を新構造に(注入の唯一のエントリポイント)
238
+ - [src/resume-context.mjs](../src/resume-context.mjs) — レンダラ差し替え
239
+ - [src/db.mjs](../src/db.mjs) — schema v4 migration、bodies テーブル追加
240
+ - [src/session-merger.mjs](../src/session-merger.mjs) — **bodies テーブルも merge 追従対象に追加**、judgments 張り替えロジックは削除(skeletons/details/bodies の 3 テーブルで session_id 張り替え)
241
+ - `src/detail-capture.mjs` — **削除**(Stop フックに統合)
242
+ - `.claude-plugin/hooks.json` — detail-capture の PostToolUse 登録を削除
243
+ - [.claude/settings.json](../.claude/settings.json) — classifier / detail-capture 関連 hook があれば削除
244
+ - [docs/archive/CONCEPT.md](archive/CONCEPT.md) — 再定義の反映
245
+ - **新規**: `commands/sc-detail.md` — L3 オンデマンド参照コマンド。bodies 設計と同時実装必須
246
+
247
+ ---
248
+
249
+ ## 既存データの扱い
250
+
251
+ **新データのみ新構造**。v3 以前のセッションはマイグレーションしない。
252
+
253
+ - v3 データの skeletons/details はそのまま読み取り可能(judgments は読まない)
254
+ - v3 セッションを引き継いだ場合、bodies テーブルは空。L2 全文が無い状態
255
+ - SessionStart 注入は「bodies がなければ skeletons のみ注入」にフォールバック
256
+ - 二系統分岐の恒久化は避けたいので、v3 セッションは **read-only 扱い、書き込みは新構造のみ** と明示
257
+
258
+ ---
259
+
260
+ ## 追加で必須の作業
261
+
262
+ 1. **`/sc-detail <turn>` コマンドの先行実装**
263
+ L3 退避先を読み出す手段がないと、参照マーカーがデッドリンクになる。本文ロスレス化と同時にリリースする必要あり
264
+
265
+ 2. **session-merger の bodies 対応**
266
+ 現行トランザクションから judgments の UPDATE 行を削除し、bodies の UPDATE 行を 1 行追加する。張り替え対象は skeletons/details/bodies の 3 テーブル + sessions.merged_into。既存の `BEGIN IMMEDIATE` ... `COMMIT` トランザクションに全部収める(途中失敗で中途半端な状態が残らないよう原子性を保証)
267
+
268
+ 3. **judgments テーブルと classifier の廃止**
269
+ DB migration で judgments を DROP、classifier.mjs は削除。注入テキストから「未解決事項」セクションを除去
270
+
271
+ ---
272
+
273
+ ## 実装順序
274
+
275
+ 依存関係に沿って以下の順で実装する。**judgments 参照の全削除を schema migration より先にやる** のがポイント(migration 後の中途半端な動作状態で crash するのを防ぐ)。
276
+
277
+ 1. **judgments 参照の全削除**(先行クリーンアップ)
278
+ - [src/turn-processor.mjs](../src/turn-processor.mjs) から judgments 書き込みを削除
279
+ - ~~src/context-injector.mjs~~ から judgments 読み出しを削除(ファイル自体が廃止済み)
280
+ - [src/session-merger.mjs](../src/session-merger.mjs) から judgments の UPDATE を削除
281
+ - `src/classifier.mjs` 削除
282
+ - [.claude/settings.json](../.claude/settings.json) / `.claude-plugin/hooks.json` から classifier 関連 hook があれば削除
283
+ - この段階では judgments テーブルは DB に残したまま。参照が消えただけ
284
+
285
+ 2. **schema v4 migration** — [src/db.mjs](../src/db.mjs)
286
+ - bodies テーブル追加
287
+ - judgments テーブル DROP(関連インデックスも DROP)
288
+ - v3 データはマイグレーションせず read-only で共存
289
+ - `user_version` を 4 に更新
290
+
291
+ 3. **`/sc-detail` コマンド** — 新規 `commands/sc-detail.md` + ロジック実装
292
+ - bodies と details を時刻指定で読み出す
293
+ - 単一時刻と時刻範囲の両方サポート
294
+ - 後段の動作確認に使えるので先に作る
295
+
296
+ 4. **Stop フック改修** — [src/turn-processor.mjs](../src/turn-processor.mjs)
297
+ - transcript のブロック分類:
298
+ - `type === 'text'` の user メッセージ → L2(ユーザー発言)
299
+ - `type === 'text'` の assistant メッセージ → L2(Claude 本文)
300
+ - `type === 'tool_use'` → L3(ツール入力)
301
+ - user メッセージ内の `type === 'tool_result'` → L3(ツール出力)
302
+ - `type === 'thinking'` → **破棄**(保存しない。素の Claude も削除しているため)
303
+ - `type === 'image'` → L3(プレースホルダ化)
304
+ - ノイズ除去(空白・進捗表示・ANSI・`<system-reminder>` タグ)
305
+ - **実装着手時に transcript JSONL サンプル 1 件を実データで検証してから実装**
306
+ - Haiku 4.5 同期呼び出しで L1 要約生成(2 回リトライ、失敗時は L2 全文を L1 に)
307
+ - bodies/skeletons/details の 3 テーブルへ分離書き込み
308
+
309
+ 5. **detail-capture.mjs 削除** — `src/detail-capture.mjs`
310
+ - Stop フックに統合済みなので不要
311
+ - `.claude-plugin/hooks.json` の PostToolUse 登録も同時に削除
312
+
313
+ 6. **注入パイプライン改修** — [src/session-start.mjs](../src/session-start.mjs)、[src/resume-context.mjs](../src/resume-context.mjs)
314
+ - 新フォーマット(`[HH:MM:SS]` 時刻プレフィックス)
315
+ - 直近 20 ターンは bodies から L2 全文、それ以前は skeletons から L1 要約
316
+ - 末尾に `/sc-detail` 案内文を追加
317
+ - v3 セッションのフォールバック経路(bodies が空なら skeletons のみ)
318
+ - ~~context-injector.mjs~~ は廃止(SessionStart に一本化)
319
+
320
+ 7. **session-merger の bodies 対応** — [src/session-merger.mjs](../src/session-merger.mjs)
321
+ - BEGIN IMMEDIATE トランザクションに bodies の UPDATE を追加
322
+ - 張り替え対象: skeletons / details / bodies / sessions.merged_into
323
+
324
+ 8. **SessionStart 改修** — [src/session-start.mjs](../src/session-start.mjs)
325
+ - 引き継ぎ注入を新フォーマットで
326
+
327
+ 9. **検証** — 各段階で smoke test を走らせ、ユーザーに動作確認してもらう
328
+
329
+ ---
330
+
331
+ ## 進捗(2026-04-16 時点)
332
+
333
+ | # | タスク | 状態 | 備考 |
334
+ |---|---|---|---|
335
+ | 1 | judgments 参照の全削除 | ✅ | |
336
+ | 2 | schema v4 migration (bodies 追加 / judgments DROP) | ✅ | |
337
+ | 3 | /sc-detail コマンド | ✅ | kind 別グループ化表示対応(tool / system / image / legacy) |
338
+ | 4 | **Stop フックのブロック分類 → bodies/skeletons/details 3 テーブル分離書き込み** | ✅ | schema v5 で details に `kind` / `source_id` 追加。`extractDetailBlocks()` で分類 |
339
+ | 5 | detail-capture.mjs 削除 | ✅ | |
340
+ | 6 | 注入パイプライン改修(新フォーマット) | ✅ | |
341
+ | 7 | session-merger の bodies 対応 | ✅ | |
342
+ | 8 | SessionStart 改修 | ✅ | |
343
+
344
+ ### ステップ 4 の実装メモ
345
+
346
+ - **schema v5**: `details.kind TEXT NOT NULL DEFAULT 'tool_input'`, `details.source_id TEXT`。`UNIQUE(session_id, origin_session_id, source_id) WHERE source_id IS NOT NULL` で冪等再処理を保証
347
+ - **transcript-reader 拡張**:
348
+ - `readRawEntries()` — 全エントリを生で返す(user/assistant だけでなく attachment/system も含む)
349
+ - `sliceCurrentTurnEntries()` — 最後の user text から 最後の assistant text までを 1 論理ターンとして切り出す
350
+ - `extractDetailBlocks()` — ブロック分類してレコード配列を返す
351
+ - `stripAnsi()` / `normalizeToolResultContent()` — ノイズ除去ヘルパ
352
+ - **ブロック分類ルール(実装で確定)**:
353
+ | 入力 | 出力 |
354
+ |---|---|
355
+ | assistant の `tool_use` | L3 kind=`tool_input`、source_id=`toolu_xxx`、input_text に JSON.stringify した input |
356
+ | user の `tool_result` | L3 kind=`tool_output`、source_id=`toolu_xxx:result`、output_text (ANSI 剥離済み) |
357
+ | attachment の `hook_success` | L3 kind=`system`、source_id=`attachment.uuid`、tool_name=`hook:<event>`、input_text=`command`、output_text=`content` |
358
+ | `text` (user/assistant) | L2 bodies(L3 には入れない) |
359
+ | `thinking` | 破棄(L2/L3 どちらにも入れない) |
360
+ | `image` | L3 kind=`image`、プレースホルダ `[image]` |
361
+ | `system` エントリ (`stop_hook_summary`) / `queue-operation` / `file-history-snapshot` | skip |
362
+ - **`<system-reminder>` タグ**: 実データ調査の結果、user text ブロックには **含まれない**(129 件すべて assistant の quote 内)。実体は attachment entry の hook_success として保存されるため、kind='system' として L3 に入る。したがって user text からの剥離は不要だった
363
+ - **実データ検証済み**: 現セッション (2292 entries) の最終ターンを slice すると 295 entries、そこから 20 tool_input + 20 tool_output + 173 system が抽出される
364
+
365
+ ---
366
+
367
+ ## 追加で発覚した課題(実装中に判明)
368
+
369
+ ### turn_number ペアリングの食い違い(2026-04-16 修正済み)
370
+
371
+ bodies に user と assistant を別 turn_number で保存してしまい、「1 往復 = 2 ターン」として数えていた。修正で「1 往復 = 1 ターン(= assistant 側の turn_number)」に統一。
372
+
373
+ 詳細: user と assistant を同じ turn_number でペアリングして bodies に書くよう [turn-processor.mjs](../src/turn-processor.mjs) を変更済み。
374
+
375
+ ### 遅延 Haiku 要約(2026-04-16 追加)
376
+
377
+ 20 ターン以内で終わる作業では Haiku 要約コストをゼロにするため、「21 ターン目以降、bodies ターン数が WINDOW(=20) を超えた時点で、最古の未要約ターンを 1 件要約する」という遅延方式に変更。
378
+
379
+ 制約: 1 Stop につき最大 1 件しか要約しないので、merge で複数ターン一気に流入するとバックログが溜まる。現状は時間が経てば追いつく設計で放置。
380
+
381
+ ---
382
+
383
+ ## 検証方法
384
+
385
+ 1. schema migration が v3 → v4 で壊れない(既存 DB で smoke test)
386
+ 2. 新 Stop フックが bodies/skeletons/details に正しく分離書き込み
387
+ 3. Haiku 同期呼び出しの平均レイテンシ計測(想定 2〜5 秒)
388
+ 4. 要約失敗時のフォールバックが動作(Haiku 側を強制エラーにして確認)
389
+ 5. SessionStart 注入が「直近は L2 全文、それ以前は L1 要約」で注入
390
+ 6. `/clear` → SessionStart 引き継ぎが新構造で動く
391
+ 7. `/sc-detail <turn>` で L3 が取れる
392
+ 8. session-merger が bodies を正しく張り替える
393
+ 9. 実セッションで 1 ターン 1/5 要約が品質を保っていることを確認(Haiku ベンチと同等)
394
+
395
+ ---
396
+
397
+ ## Haiku ベンチマーク実測記録(設計根拠)
398
+
399
+ 対話の中で 2 サンプルを実機で Haiku 4.5 に投げた結果:
400
+
401
+ ### サンプル 1: 新聞記事(約 1,850 文字)
402
+ - 内容: 米イラン再協議、対伊不和、ホルムズ海峡の 3 つの並列トピック
403
+ - **1/5**: 3 トピックすべて + 固有名詞 + 数値 20/5/10 年 + 因果関係保持。**合格**
404
+ - **1/10**: ホルムズ海峡が完全消失。3/4 トピックのみ。**ボーダー**
405
+ - **1/20**: 濃縮期間交渉のみ残存。**不合格**
406
+
407
+ ### サンプル 2: 技術論文(約 1,430 文字)
408
+ - 内容: 光空間並列伝送 + MIMO 処理の研究
409
+ - **1/5**: 背景・手法・結果の 3 本柱すべて保持。**合格**
410
+ - **1/10**: 1/5 とほぼ同品質。**合格**
411
+
412
+ ### 結論
413
+ - 単一トピック構造(論文・コーディング会話): 1/10 でも OK
414
+ - 並列トピック構造(新聞・長文議論): 1/5 が下限
415
+ - 保守的にデフォルト 1/5 を採用
@@ -0,0 +1,184 @@
1
+ # Throughline 公開配布化プラン
2
+
3
+ ## §0 プロジェクト不変ルール
4
+
5
+ **フォールバック / 逃げ道のコードを書かない。** バグを隠してデバッグを困難にするため、想定外の状態・契約違反・依存関係の不在などに遭遇した場合は **エラーを吐いて停止** する。該当箇所を後で直すのが正しい対応。
6
+
7
+ 具体的には以下のパターンを禁止する:
8
+
9
+ - `try { ... } catch { /* ignore */ }`(例外を黙って握り潰す)
10
+ - `catch (err) { stderr.write(...); process.exit(0); }`(エラーを記録しつつ成功コードで終わる)
11
+ - 「A がダメなら B」という暗黙の切り替え(明示的な設定フラグなしでの挙動分岐)
12
+ - 未検証の契約に対する「とりあえず動く」実装
13
+
14
+ 例外は以下のみ:
15
+ - 外部入力のバリデーション失敗 → 明確な `throw new Error(...)` で拒否
16
+ - hook 実行での I/O エラー → stderr + 非ゼロ終了コード(Claude Code 側で可視化される)
17
+ - 既に値が NULL であることが設計上許容されている場合の `?.` アクセス
18
+
19
+ ---
20
+
21
+ ## ゴール
22
+
23
+ Throughline を GitHub + npm で公開し、世界中の Claude Code ユーザーに使ってもらう。満たすべき条件:
24
+
25
+ 1. **導入が簡単** — 1〜2 コマンドで完了
26
+ 2. **複数プロジェクトで動く** — 導入後は全プロジェクトで自動的に働く
27
+ 3. **配布物の絶対パス依存を避ける** — npm tarball に開発環境の path を焼き込まず、install 時に必要な実行 path だけをユーザー環境で解決する
28
+
29
+ ---
30
+
31
+ ## 採用方式: npm グローバル + bin エントリ
32
+
33
+ ### 導入フロー(ユーザー視点)
34
+
35
+ ```bash
36
+ npm install -g throughline # CLI を PATH に配置
37
+ throughline install # ~/.claude/settings.json、Codex hook、Codex skill を追記
38
+ ```
39
+
40
+ Claude hook コマンドは **`throughline <subcommand>` の PATH 解決型**。node のインストール先や OS が変わっても PATH さえ通っていれば動く。Codex Stop hook は Codex App Server / VSCode host の PATH 差分を避けるため、絶対 node + installed `bin/throughline.mjs` で登録する。Codex 手動 UX は `~/.codex/skills/throughline` の `$throughline` skill で自然言語から呼ぶ。
41
+
42
+ ### hook 登録後の `~/.claude/settings.json`(抜粋)
43
+
44
+ ```json
45
+ {
46
+ "hooks": {
47
+ "SessionStart": [{ "hooks": [{ "command": "throughline session-start" }] }],
48
+ "Stop": [{ "hooks": [{ "command": "throughline process-turn" }] }]
49
+ }
50
+ }
51
+ ```
52
+
53
+ schema v4 で PostToolUse (`capture-tool`) は廃止、L2/L3 は Stop 内で一括処理。schema v6 で UserPromptSubmit (`prompt-submit`) を `/tl` バトン書き込み専用として再導入(注入は一切行わない、SessionStart 側との重複注入は発生しない)。schema v7 で `handoff_batons.memo_text` を追加(`/tl` 直後に in-flight メモを保存)。
54
+
55
+ ### 却下した代替案
56
+
57
+ - **npx (`npx -y throughline <subcommand>`)**: hook 発火ごとに npx のオーバーヘッドが乗り、UX が悪化する
58
+ - **Claude hook を開発リポジトリの絶対パスで登録** (`node C:\Users\...\src\...`): リポジトリを移動すると壊れる。Codex Stop hook だけは App Server / VSCode host の PATH 差分を避けるため、install 時点の installed CLI script path を絶対 node で登録する
59
+ - **Claude Code プラグインマーケットプレース形式**: まず npm で出してから将来 ECC 等に登録する
60
+
61
+ ---
62
+
63
+ ## 実装ステータス
64
+
65
+ ### ✅ 実装済み
66
+
67
+ | 項目 | 実体 |
68
+ |---|---|
69
+ | CLI エントリポイント | [bin/throughline.mjs](../bin/throughline.mjs) |
70
+ | package.json(`bin`, `files`, `engines`, `keywords`, `repository`, `license`) | [package.json](../package.json) |
71
+ | install / uninstall コマンド(デフォルト global、`--project` でローカル) | [src/cli/install.mjs](../src/cli/install.mjs) |
72
+ | doctor サブコマンド | [src/cli/doctor.mjs](../src/cli/doctor.mjs) |
73
+ | status サブコマンド(sessions / skeletons / bodies / details 件数) | [src/cli/status.mjs](../src/cli/status.mjs) |
74
+ | monitor サブコマンド(マルチセッション対応) | [src/token-monitor.mjs](../src/token-monitor.mjs) |
75
+ | 状態ファイルをセッション単位に分割 | [src/state-file.mjs](../src/state-file.mjs) |
76
+ | transcript JSONL から実測 usage 抽出、1M context 検出 | [src/transcript-usage.mjs](../src/transcript-usage.mjs) |
77
+ | 記憶張り替え方式(merged_into + origin_session_id, schema v3) | [src/session-merger.mjs](../src/session-merger.mjs) |
78
+ | schema v4 migration(bodies 追加、judgments DROP) | [src/db.mjs](../src/db.mjs) |
79
+ | schema v5 migration(details に kind / source_id 追加、L3 分離書き込み対応) | [src/db.mjs](../src/db.mjs) |
80
+ | schema v6 migration(handoff_batons テーブル追加、`/tl` バトン引き継ぎ方式) | [src/db.mjs](../src/db.mjs), [src/baton.mjs](../src/baton.mjs) |
81
+ | schema v7 migration(`handoff_batons.memo_text` カラム追加、in-flight メモ保存) | [src/db.mjs](../src/db.mjs), [src/baton.mjs](../src/baton.mjs), [src/cli/save-inflight.mjs](../src/cli/save-inflight.mjs) |
82
+ | VSCode `.vscode/tasks.json` の自動プロビジョニング(token-monitor の folderOpen 自動起動) | [src/vscode-task.mjs](../src/vscode-task.mjs) |
83
+ | Stop フック時の state.usage スナップショット(monitor の「止まって見える」問題の切り分け用) | [src/state-file.mjs](../src/state-file.mjs), [src/turn-processor.mjs](../src/turn-processor.mjs) |
84
+ | `throughline doctor --session <id-prefix>` セッション診断(state/transcript ズレ検出) | [src/cli/doctor.mjs](../src/cli/doctor.mjs) |
85
+ | token-monitor の `(Nm ago)` 表示 + columns polling による resize 検知 | [src/token-monitor.mjs](../src/token-monitor.mjs) |
86
+ | token-monitor の OSC 18t による端末実幅取得 (Windows ConPTY + VSCode task の resize 追従) | [src/terminal-size.mjs](../src/terminal-size.mjs), [src/token-monitor.mjs](../src/token-monitor.mjs) |
87
+ | token-monitor の `--diag` サブモード (TTY/columns/env の実測出力、`~/.throughline/last-diag.txt` にも保存) | [src/token-monitor.mjs](../src/token-monitor.mjs) |
88
+ | `/tl` スラッシュコマンド + UserPromptSubmit hook でバトン書き込み | [.claude/commands/tl.md](../.claude/commands/tl.md), [src/prompt-submit.mjs](../src/prompt-submit.mjs) |
89
+ | SessionStart でバトン消費 → 指名 merge(自動推測の引き継ぎは撤去) | [src/session-start.mjs](../src/session-start.mjs), [src/session-merger.mjs](../src/session-merger.mjs) |
90
+ | L3 ブロック分類抽出(tool_use / tool_result / attachment hook / thinking 破棄) | [src/transcript-reader.mjs](../src/transcript-reader.mjs) |
91
+ | L3 書き込み(Stop フック内で bodies/skeletons と同時に details に INSERT OR IGNORE) | [src/turn-processor.mjs](../src/turn-processor.mjs) |
92
+ | /sc-detail コマンドの kind 別グループ表示 | [src/sc-detail.mjs](../src/sc-detail.mjs) |
93
+ | Haiku 4.5 同期要約(subprocess 再帰ガードつき) | [src/haiku-summarizer.mjs](../src/haiku-summarizer.mjs) |
94
+ | L1/L2 書き込み(Stop フック内で一括処理) | [src/turn-processor.mjs](../src/turn-processor.mjs) |
95
+ | 遅延 Haiku 要約(20 ターン以内はコストゼロ) | [src/turn-processor.mjs](../src/turn-processor.mjs) |
96
+ | README(schema v7 対応版、VSCode 自動起動・モニター診断機能を記載) | [../README.md](../README.md) |
97
+ | LICENSE | [../LICENSE](../LICENSE) (MIT) |
98
+ | token-monitor 折り返し対策(ANSI 幅切り詰め) | [src/token-monitor.mjs](../src/token-monitor.mjs) |
99
+ | § 0 ルール適用(silent try/catch 掃除) | 主要ファイルすべて |
100
+ | **`npm pack --dry-run` 検証** | 2026-04-17 確認、23 ファイル / 38.3 KB、秘密情報なし |
101
+ | **npm 公開 (v0.1.0)** | 2026-04-17 https://www.npmjs.com/package/throughline に publish 済み |
102
+ | **npm 公開 (v0.2.0)** | 2026-04-18 バトン方式引き継ぎ (schema v6) を publish |
103
+ | **npm 公開 (v0.3.0)** | 2026-04-18 in-flight メモ + thinking L3 + resume reframing (schema v7) を publish |
104
+ | **npm 公開 (v0.3.1 〜 v0.3.2)** | 2026-04-18 monitor の描画・クラッシュ耐性・1M context 検出の精度向上、色覚配慮マーカー |
105
+ | **npm 公開 (v0.3.3)** | 2026-04-18 `.vscode/tasks.json` 自動プロビジョニングを publish(2 段階マージ方式、JSONC 検出) |
106
+ | **npm 公開 (v0.3.4 〜 v0.3.5)** | 2026-04-18 Stop 時 state.usage 固定、`doctor --session` 診断、`(Nm ago)` 表示、columns polling で resize 検知 |
107
+ | **npm 公開 (v0.3.6 〜 v0.3.12)** | 2026-04-18 monitor 描画の「行が積み上がる」バグ対策の連続試行 (columns フォールバック、isTTY 切分け、clearScreen、alt screen、type:shell 等)。いずれも憶測ベースで的外れ。`--diag` モードを 0.3.11 で追加して実測に切替 |
108
+ | **npm 公開 (v0.3.13)** | 2026-04-18 真因修正: resolveColumns の `>= 40` 閾値撤廃。実在する 30 セル panel を「狂った値」と誤判定して 200 にフォールバックし wrap → CUU under-count → 積み上がり、という連鎖を解消 |
109
+ | **npm 公開 (v0.3.14 〜 v0.3.15)** | 2026-04-18 追加の診断出力 (起動ヘッダ、per-frame cols 表示)。panel resize に Node の `process.stdout.columns` が追従しないことを実機で確定 |
110
+ | **npm 公開 (v0.3.16)** | 2026-04-18 OSC 18t (`\x1b[18t`) クエリで端末から実幅を直接取得。Windows ConPTY + VSCode task terminal の resize 不追従を回避。[src/terminal-size.mjs](../src/terminal-size.mjs) 新設 |
111
+ | **npm 公開 (v0.3.17)** | 2026-04-18 resize 検知時の強制再描画で `ANSI.clearScreen` を明示発行するよう修正(前フレームが残って新フレームが下に積まれる最後のバグを潰した)|
112
+ | **npm 公開 (v0.3.18)** | 2026-04-18 `ensureMonitorTaskFile` を Stop に加え **SessionStart / UserPromptSubmit でも呼ぶ** ように変更。別プロジェクトで Stop hook が発火しなかった実機例で tasks.json が生成されない問題に対応。どれか 1 つの hook が発火すれば tasks.json が作られる冗長化 |
113
+ | **npm 公開 (v0.3.19)** | 2026-04-18 tasks.json を新規作成/マージした瞬間に `<system-reminder>` を stdout へ出力し、Claude 経由で「Reload Window が必要」をユーザーへ即時通知。`already_present` では沈黙(1 プロジェクト 1 回だけ) |
114
+ | **npm 公開 (v0.3.20)** | 2026-04-19 monitor の context 枯渇警告を `/clear` ではなく `/tl` 推奨に修正(引き継ぎを壊さない案内へ統一) |
115
+ | **npm 公開 (v0.3.21)** | 2026-04-19 `throughline install` が `/tl` と `/sc-detail` スラッシュコマンド定義 (`~/.claude/commands/*.md`) をグローバル配置するように変更。プロジェクト個別の `.claude/commands/` 依存を廃止 |
116
+ | **npm 公開 (v0.3.22)** | 2026-04-19 Stop hook を `"async": true` で登録。`throughline process-turn`(内部で Haiku subprocess 起動)がターン完了 → ユーザー表示をブロックしていた症状を解消。L1 要約は次 SessionStart 注入用なので今ターンをブロックする理由が無い。既存ユーザーは `throughline uninstall && throughline install` で再登録が必要(dedup が command 一致で skip するため async フラグ昇格は起きない)。Claude Code 公式 hooks schema の正式フィールドであることを docs で確認済み |
117
+ | **npm 公開 (v0.3.23)** | 2026-05-02 クロス環境ユーザビリティの 2 件: (1) `.vscode/tasks.json` の **絶対パス自動修復** — Windows ↔ WSL2 / Linux ↔ macOS 間でリポジトリを共有したとき、別環境の絶対パスが焼き込まれた既存タスクを検出して `command` / `args` だけを差し替え、`label` / `presentation` 等のユーザーカスタマイズは保持。`isMonitorTaskBroken` (絶対パス + 非存在で判定) と `findMonitorTaskIndex` を [src/vscode-task.mjs](../src/vscode-task.mjs) に新設。`action: 'repaired'` を追加して Reload Window 通知を 1 回出す。(2) `throughline install` 完了時に **PATH 解決チェック** — `resolveThroughlineOnPath` が PATH を走査して `throughline` が見つからない場合、stderr に修復手順 (npm prefix → `~/.bashrc` 編集 → `doctor` 確認) を出力。`~/.npm-global/bin` を `.profile` だけに書いて `.bashrc` に書き忘れる sudoless prefix 派の silent fail を防ぐ。あわせて [README.md](../README.md) Troubleshooting に WSL2 ↔ Windows 交差 / OS 別 DB / tasks.json 自動修復の各節を追加 |
118
+ | **npm 公開 (v0.3.24)** | 2026-05-02 v0.3.23 の補完: `.vscode/tasks.json` には現環境の絶対パスが書き込まれるため、**そもそも commit すべきではない**。`shouldRecommendGitignore` を [src/vscode-task.mjs](../src/vscode-task.mjs) に追加し、`ensureMonitorTaskFile` が created / merged / repaired を返すタイミングで「git リポジトリ内かつ `.gitignore` に `.vscode/tasks.json` 系エントリが無い」を判定。該当時に `<system-reminder>` で `.gitignore` 追加推奨を 1 度だけ stdout 通知 (`.throughline-gitignore-noted` marker で抑止)。否定パターン (`!.vscode/tasks.json`) はスキップ判定 = 推奨を出す。README Troubleshooting にも明示。配布物 (npm tarball) には絶対パスは入っていない (`files` フィールドが `.vscode/` を含まない、ソースに hard-coded path 無し) ことを再確認 |
119
+ | **npm 公開 (v0.3.25): Claude-primary / Codex-sidecar groundwork** | `HandoffRecord` projection、`throughline handoff-preview`、`throughline_handoff` example、`codex-sidecar-diagnostics` / `codex-sidecar-dry-run` を追加。Claude Code hooks / slash command / transcript / baton / resume behavior は正本として維持し、Codex 対応は adapter / projection として足す |
120
+ | **npm 公開 (v0.3.25): optional Codex-sidecar L1 summarization** | Claude primary の L2→L1 要約は、`codex-sidecar` が `summarize-l1` preset で configured の場合だけ sidecar を使う。disabled / unavailable / run failure では、ユーザー許可済み互換経路として既存 Claude Haiku 要約を維持する。Codex primary の L2→L1 backend は次フェーズ計画で Codex CLI 本線として扱う。Claude CLI smoke / test で Claude を呼ぶ場合は Haiku を使う |
121
+ | **npm 公開 (v0.3.25): `/tl-trim` dry-run** | `throughline trim --dry-run`、`--preflight`、guarded `--execute`、`--host`、`--keep-recent`、`--all`、`--memo-stdin`、`--preview-max-chars`、`--codex-thread-id`、`THROUGHLINE_CODEX_THREAD_ID` / `CODEX_THREAD_ID`、`throughline codex-threads`、`throughline doctor --trim`、Claude slash command `/tl-trim` を追加。Codex app-server の rollback / inject primitive は live app-server 上で実測済み。2026-05-06 incident 後は一時 blocked としたが、2026-05-08 の controlled rollback model-visible smoke が app-server restart 境界と VS Code reload/reconnect 境界の両方で `not-reproduced` だったため、過剰 blocker は解除済み。`trim --execute --host codex` は明示実行で current-thread rollback + Throughline DB memory inject を送り、Codex Stop hook auto-refresh は verified usage 90% 以上で同じ guarded path を試行する。DB memory 不在、Codex thread identity 不在、rollout/app-server turn-count 不一致は mutation 前に拒否する。restore-safety / planned restore-safety / host primitive audit は diagnostics として表示する |
122
+ | **npm 公開 (v0.3.25): Codex primary capture** | `throughline codex-capture --codex-thread-id <id>` を追加。Codex rollout JSONL の active turns を `codex:<thread_id>` session として DB `bodies` に保存し、`function_call` / `function_call_output` を DB `details` の L3 tool input / output として保存する。`thread_rolled_back` 適用後の active thread だけを再構成し、rollback 済み tail は current L2/L3 に残さない。Codex thread id は明示指定または env 指定のみで、自動推測しない |
123
+ | **npm 公開 (v0.3.25): Codex-primary L1 backend** | `summarizeToL1` に `hostMode` 分岐を追加。Claude primary は既存の `codex-sidecar` / Claude Haiku 互換経路を維持し、Codex primary は Codex CLI backend を使う。Codex CLI failure は `source = codex-cli` / `reason` 付き explicit error とし、Claude Haiku / `raw_l2` に silent fallback しない |
124
+ | **npm 公開 (v0.3.25): Codex-primary L1 CLI** | `throughline codex-summarize --session codex:<thread_id>` を追加。captured Codex L2 が L2 window を超えた場合、最古の未要約 turn を Codex CLI backend で L1 skeleton に書く。Codex CLI failure は explicit error |
125
+ | **npm 公開 (v0.3.25): Codex primary resume renderer** | `throughline codex-resume --session codex:<thread_id>` を追加。保存済み `codex:<thread_id>` memory を Active Work Thread / Reading Contract / Continuation Instruction 付きの Codex active-work context として描画する。`--format handoff` は新規 Codex thread に貼るための短い handoff prompt を返し、L2 件数 / 本文長 / detail refs を cap する。`throughline codex-handoff-smoke --session codex:<thread_id>` はその handoff prompt を read-only に検査し、fresh-thread header / current-task contract / source session / start instruction / mutation boundary / prompt size / detail command dedupe を確認する。`throughline codex-handoff-model-smoke --session codex:<thread_id>` は `--dry-run` で env なしに readiness / command boundary を監査でき、`--print-prompt` で結合 prompt を出せる。`throughline codex-handoff-start --session codex:<thread_id>` は structural smoke / model dry-run / render command / optional live smoke / `--print-prompt` を一つの guided read-only start plan として表示する。`--memo-stdin` は Codex-primary の in-flight memo を handoff prompt に含め、handoff-start は replay 用個別 command にも `--memo-stdin` を伝播する。live smoke は `THROUGHLINE_EXPERIMENTAL_CODEX_HANDOFF_MODEL_SMOKE=1` がある場合だけ structural smoke 後に `codex exec --ephemeral --ignore-user-config --ignore-rules --sandbox read-only` で marker model smoke を行う。`--format item-json` は developer message item JSON を返す。renderer は DB / Codex thread を mutate しない |
126
+ | **npm 公開 (v0.3.25): Codex model-visible smoke** | `throughline codex-visibility-smoke --session codex:<thread_id>` を追加。`codex-resume` 相当の active-work developer message に marker 指示を加えて app-server `thread/inject_items` へ送り、`turn/start` の agent delta に marker が出るか確認する。`--memo-stdin` で同じ in-flight memo surface を実注入できる。`--resume-after-inject` で inject 後に再度 `thread/resume` してから marker turn を開始できる。実 model turn を開始するため `THROUGHLINE_EXPERIMENTAL_CODEX_MODEL_VISIBLE_SMOKE=1` が必須。実 Codex host で marker `TL_CODEX_VISIBLE_REAL_20260506_C` と post-inject resume marker `TL_CODEX_RESUME_AFTER_INJECT_REAL_20260506` が `item/agentMessage/delta` に出ることを確認済みで、長い model turn 用に `--request-timeout-ms` / `--timeout-ms` を持つ |
127
+ | **npm 公開 (v0.3.25): Codex app-server restore smoke** | `throughline codex-restore-smoke --codex-thread-id <id>` を追加。fresh Codex app-server process を複数回起動し、`thread/read` / `thread/resume` / paginated `thread/turns/list` の turn count が rollout active turn count と一致し続けるかを read-only で確認する。`THROUGHLINE_EXPERIMENTAL_CODEX_RESTORE_SMOKE=1` 必須。proof scope は `app_server_process_restart_only` で、VS Code restart / reconnect 越しの rollback / inject durability 証明ではない |
128
+ | **npm 公開 (v0.3.25): Codex restore source audit** | `throughline codex-restore-source-audit --codex-thread-id <id>` を追加。Codex rollout、`session_index.jsonl`、`state_*.sqlite`、VS Code globalStorage / workspaceStorage 候補、VS Code settings / logs、installed OpenAI/Codex VS Code extension bundle を read-only で棚卸しし、thread id、retained rollback text、`thread/read` / `thread/resume` / `thread/turns/list` / reconnect `needs_resume` / persisted webview atoms / follow-up queue などの restore-path signal を確認する。proof scope は `local_restore_source_inventory_only` で、VS Code restart / reconnect 越しの rollback / inject durability 証明ではない |
129
+ | **npm 公開 (v0.3.25): Codex host primitive audit** | `throughline codex-host-primitive-audit` を追加。installed Codex CLI の app-server JSON schema を read-only 生成し、rollback 済み user text を同じ thread の model-visible input に復活させない deletion / isolation / projection primitive があるか機械判定する。実 `codex-cli 0.128.0-alpha.1` では `thread/rollback` / `thread/inject_items` / `thread/compact/start` / `thread/start` / `thread/fork` / `thread/resume` は存在したが、current-thread rollback non-resurrection primitive は無く、`thread/resume(history)` も unstable do-not-use かつ thread_id ignored なので採用しない。結果は diagnostic-only で、Codex trim execute / auto-refresh の blocker にはしない |
130
+ | **npm 公開 (v0.3.25): Codex VS Code restore smoke protocol** | `throughline codex-vscode-restore-smoke --prepare/--verify --codex-thread-id <id>` を追加。`--prepare` は hidden active-work marker memory を app-server へ注入し、VS Code reload / reconnect 後に marker を含まない prompt を送る二段階手順を出す。`--verify` は rollout を読み、prepare 後の marker-free smoke prompt、assistant の marker-only answer、user prompt への marker leak 不在を確認する。prepare は `THROUGHLINE_EXPERIMENTAL_CODEX_VSCODE_RESTORE_SMOKE=1` 必須。実 VS Code reload / reconnect marker proof は `TL_CODEX_VSCODE_RESTORE_46888202` で成功済み。ただしこれは hidden developer memory visibility 証明であり、rollback 済み user turn の非復活証明ではない |
131
+ | **npm 公開 (v0.3.25): Codex VS Code rollback smoke verifier** | `throughline codex-vscode-rollback-smoke --verify --codex-thread-id <id>` を追加。rollout を read-only で読み、rollback event、rollback 済み user text、rollback 後 user turn、`restoreSafety.status = ok` を必須条件にする。`--after-vscode-restart` がある場合だけ `restartSafe: true` を返す。実 incident-shaped live rollback run では `thread_rolled_back` と injected memory は記録されたが、rollback 対象 user text が `compacted.replacement_history` に残り、後続 verifier では rollback 済み user text の再出現も観測した。後続分類で app-server response 上の retained text は `aggregatedOutput` に限定され、controlled rollback model-visible smoke は再現しなかったため、これは現在は diagnostic evidence として扱う |
132
+ | **npm 公開 (v0.3.25): Codex primary doctor** | `throughline doctor --codex` を追加。現在 project の Codex thread env identity、rollout candidates、captured `codex:<thread_id>` DB sessions、context-refresh memory contract、new-thread handoff readiness、safe continuation status、host primitive audit status、次に使う capture / handoff / resume / audit command を表示する。doctor 自体は read-only で、Codex thread / DB / Claude settings を変更しない。`doctor --trim --host codex` も host primitive audit status を表示する |
133
+ | **npm 公開 (v0.3.25): Codex global Stop hook / skill install** | `throughline install` が Claude hooks / slash commands に加えて `~/.codex/hooks.json` に絶対 node + installed `bin/throughline.mjs codex-hook stop` を `async: false` で登録し、`~/.codex/config.toml` の `[features].codex_hooks = true` を有効化し、`~/.codex/skills/throughline` に `$throughline` skill を配置する。Codex App Server / VSCode host の PATH 差分で bare `throughline` が見えない可能性があるため、hook は Caveat と同じ絶対パス型に寄せる。既存 Caveat / Spotter などの Codex hooks は保持し、`throughline uninstall` は Throughline 管理の Codex hook / skill だけを削除する。既に bare command または `async: true` で登録済みの Throughline Codex Stop hook は次回 install で更新する。実環境では `codex exec --json` child thread `019dfd4f-93ff-7522-8f89-bd1e1996c8d7` が Stop hook で自然 capture され、`doctor --codex` の latest DB session が `codex:019dfd4f-93ff-7522-8f89-bd1e1996c8d7` に進むことを確認した。さらに絶対パス型へ更新後、child thread `019dfd5e-1248-7c11-8ddc-97e1b0701e10` でも latest DB session が `codex:019dfd5e-1248-7c11-8ddc-97e1b0701e10` に進むことを確認した。hook shape 変更後に新規開始した VSCode-origin thread `019dfd62-9a9d-7211-bf91-89d8e3fc908e` でも `doctor --codex` の current thread と latest DB session が一致し、自然 Stop hook capture を確認済み。hook shape 変更前から開いていた VSCode-origin parent thread は、変更後の自然 Stop smoke としては扱わない。Caveat 側にも `async: false` Stop hook が動く実測があるため、Codex 側は Caveat と同じ同期 hook 方針に寄せる。`codex-capture` / `codex-summarize` / `codex-resume --memo-stdin` は診断・明示操作 surface として維持し、model-visible smoke は明示 opt-in。2026-05-08 以降、Stop hook auto-refresh は verified usage 90% 以上で guarded rollback / inject を試行し、estimate usage では mutation しない |
134
+ | **npm 公開 (v0.3.25): Codex-first roadmap** | [THROUGHLINE_CODEX_FIRST_ROADMAP.md](THROUGHLINE_CODEX_FIRST_ROADMAP.md) を追加。次フェーズは Codex primary 実用化、Codex Rewind 互換、Claude 側 finalization の順で進める。Codex primary の L2→L1 backend は Codex CLI を本線とし、`codex-sidecar` は Claude primary からの review / risk-check / second opinion / 互換 L2→L1 経路として整理する |
135
+ | **npm 公開 (v0.3.25): npm docs packaging** | README から参照する `docs/` と `CHANGELOG.md` を npm `files` に追加。`docs/throughline-handoff-context.example.json` を含め、README の sidecar dry-run 例が tarball 内でも成立するようにする |
136
+ | **グローバル E2E 検証** | 2026-04-17 別ディレクトリから `throughline doctor` 全緑を確認 |
137
+
138
+ ### ❌ 未完タスク
139
+
140
+ | 項目 | 備考 |
141
+ |---|---|
142
+ | **awesome-claude-code 登録申請** | 初回 public commit から 1 週間経過(2026-04-21 以降)に Web UI 経由で提出 |
143
+ | **外部環境での実運用検証** | 別 PC / OS での install、並行 `/clear` 時の merge chain 挙動、1M context 検出のロバストさ、VSCode 系以外のエディタでの token-monitor 挙動、macOS / Linux で OSC 18t がフォールバック経路と実幅取得の両方で正しく動くかの確認 |
144
+ | **GitHub Actions 自動 publish** | `release` タグ push をトリガー(Phase 3+、Trusted Publishing 使用) |
145
+ | **Claude Code プラグインマーケットプレース登録** | npm 公開の後継ステップ(Phase 3+) |
146
+ | **turn-processor.test.mjs の 10 秒タイムアウト解消** | `main()` が stdin を待ち続けるためテストファイルがハングする既存の問題。実装動作は無影響、テスト個別 9/9 は pass |
147
+ | **automatic context rollback / inject** | Codex Stop hook auto-refresh は verified usage 90% 以上で guarded rollback + Throughline DB memory inject を試行する。controlled rollback model-visible smoke で復活が未再現となったため、2026-05-06 incident 後の overbroad blocker は解除済み。estimate usage では実行しない |
148
+
149
+ ---
150
+
151
+ ## 検証方法(End-to-End)
152
+
153
+ 初回 publish(v0.1.0 / 2026-04-17)は以下の実行で確認済み:
154
+
155
+ 1. `npm pack --dry-run` で tarball 内容を確認(23 ファイル、秘密情報なし)
156
+ 2. `npm publish` 実行 → `+ throughline@0.1.0`
157
+ 3. `npm view throughline` でレジストリに反映されていることを確認
158
+ 4. 別ディレクトリで `npm install -g throughline` → `throughline install` → `throughline doctor` 全緑
159
+ 5. `~/.claude/settings.json` の hook が global スコープに登録されていることを確認
160
+
161
+ 次バージョン以降は次の手順で:
162
+
163
+ ```bash
164
+ # 版上げ(例: patch)
165
+ npm version patch
166
+
167
+ # publish(granular access token with bypass 2FA を使う場合は OTP 不要)
168
+ npm publish
169
+
170
+ # 反映確認
171
+ npm view throughline
172
+ npm install -g throughline
173
+ throughline doctor
174
+ ```
175
+
176
+ さらに別環境(macOS / Linux / 別 PC)での claude 起動・並行 `/clear` 挙動・1M context 検出のロバストさは未検証。
177
+
178
+ ---
179
+
180
+ ## スコープ外(別 Phase)
181
+
182
+ - GitHub Actions による自動リリース(Trusted Publishing 推奨)
183
+ - `injection_log` 効果測定
184
+ - Claude Code プラグインマーケットプレース登録(Phase 3+)