throughline 0.3.24 → 0.4.0

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 (116) hide show
  1. package/.claude/commands/tl.md +6 -21
  2. package/.codex-sidecar.yml +62 -0
  3. package/CHANGELOG.md +632 -0
  4. package/README.ja.md +71 -46
  5. package/README.md +420 -76
  6. package/bin/throughline.mjs +169 -7
  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 +159 -0
  10. package/docs/L1_L2_L3_REDESIGN.md +415 -0
  11. package/docs/PUBLIC_RELEASE_PLAN.md +185 -0
  12. package/docs/THROUGHLINE_CLEAR_AUTO_HANDOFF_PLAN.md +286 -0
  13. package/docs/THROUGHLINE_CODEX_DUAL_SUPPORT.md +249 -0
  14. package/docs/THROUGHLINE_CODEX_FIRST_ROADMAP.md +555 -0
  15. package/docs/THROUGHLINE_CODEX_MONITOR_IMPLEMENTATION_PLAN.md +220 -0
  16. package/docs/THROUGHLINE_CODEX_TRIM_IMPLEMENTATION_PLAN.md +528 -0
  17. package/docs/THROUGHLINE_CODEX_TRIM_ROLLBACK_FIX_PLAN.md +672 -0
  18. package/docs/archive/CONCEPT.md +476 -0
  19. package/docs/archive/EXPERIMENT.md +371 -0
  20. package/docs/archive/README.md +22 -0
  21. package/docs/archive/SESSION_LINKING_DESIGN.md +231 -0
  22. package/docs/archive/THROUGHLINE_NEXT_STEPS.md +134 -0
  23. package/docs/throughline-codex-trim-rollback-incident-report.md +306 -0
  24. package/docs/throughline-handoff-context.example.json +57 -0
  25. package/docs/throughline-rollback-context-trim-insight.md +455 -0
  26. package/package.json +6 -2
  27. package/src/baton.mjs +17 -45
  28. package/src/baton.test.mjs +4 -41
  29. package/src/cli/codex-capture.mjs +95 -0
  30. package/src/cli/codex-handoff-model-smoke.mjs +292 -0
  31. package/src/cli/codex-handoff-model-smoke.test.mjs +262 -0
  32. package/src/cli/codex-handoff-smoke.mjs +163 -0
  33. package/src/cli/codex-handoff-smoke.test.mjs +149 -0
  34. package/src/cli/codex-handoff-start.mjs +291 -0
  35. package/src/cli/codex-handoff-start.test.mjs +194 -0
  36. package/src/cli/codex-hook.mjs +276 -0
  37. package/src/cli/codex-hook.test.mjs +293 -0
  38. package/src/cli/codex-host-primitive-audit.mjs +110 -0
  39. package/src/cli/codex-host-primitive-audit.test.mjs +75 -0
  40. package/src/cli/codex-restore-smoke.mjs +357 -0
  41. package/src/cli/codex-restore-source-audit.mjs +304 -0
  42. package/src/cli/codex-resume.mjs +138 -0
  43. package/src/cli/codex-rollback-model-visible-smoke.mjs +373 -0
  44. package/src/cli/codex-rollback-model-visible-smoke.test.mjs +255 -0
  45. package/src/cli/codex-sidecar-diagnostics.mjs +48 -0
  46. package/src/cli/codex-sidecar-dry-run.mjs +85 -0
  47. package/src/cli/codex-summarize.mjs +224 -0
  48. package/src/cli/codex-threads.mjs +89 -0
  49. package/src/cli/codex-visibility-smoke.mjs +196 -0
  50. package/src/cli/codex-vscode-restore-smoke.mjs +226 -0
  51. package/src/cli/codex-vscode-rollback-smoke.mjs +114 -0
  52. package/src/cli/doctor.mjs +503 -1
  53. package/src/cli/doctor.test.mjs +542 -3
  54. package/src/cli/handoff-preview.mjs +78 -0
  55. package/src/cli/help.test.mjs +64 -0
  56. package/src/cli/install.mjs +226 -3
  57. package/src/cli/install.test.mjs +205 -4
  58. package/src/cli/trim.mjs +564 -0
  59. package/src/codex-app-server.mjs +1816 -0
  60. package/src/codex-app-server.test.mjs +512 -0
  61. package/src/codex-auto-refresh.mjs +194 -0
  62. package/src/codex-auto-refresh.test.mjs +182 -0
  63. package/src/codex-capture.mjs +235 -0
  64. package/src/codex-capture.test.mjs +393 -0
  65. package/src/codex-handoff-model-smoke.mjs +114 -0
  66. package/src/codex-handoff-model-smoke.test.mjs +89 -0
  67. package/src/codex-handoff-smoke.mjs +124 -0
  68. package/src/codex-handoff-smoke.test.mjs +103 -0
  69. package/src/codex-handoff.mjs +331 -0
  70. package/src/codex-handoff.test.mjs +220 -0
  71. package/src/codex-host-primitive-audit.mjs +374 -0
  72. package/src/codex-host-primitive-audit.test.mjs +208 -0
  73. package/src/codex-restore-smoke.test.mjs +639 -0
  74. package/src/codex-restore-source-audit.mjs +1348 -0
  75. package/src/codex-restore-source-audit.test.mjs +623 -0
  76. package/src/codex-resume.test.mjs +242 -0
  77. package/src/codex-rollout-memory.mjs +711 -0
  78. package/src/codex-rollout-memory.test.mjs +610 -0
  79. package/src/codex-sidecar-cli.test.mjs +75 -0
  80. package/src/codex-sidecar.mjs +246 -0
  81. package/src/codex-sidecar.test.mjs +172 -0
  82. package/src/codex-summarize.test.mjs +143 -0
  83. package/src/codex-thread-identity.mjs +23 -0
  84. package/src/codex-thread-index.mjs +173 -0
  85. package/src/codex-thread-index.test.mjs +164 -0
  86. package/src/codex-usage.mjs +110 -0
  87. package/src/codex-usage.test.mjs +140 -0
  88. package/src/codex-visibility-smoke.test.mjs +222 -0
  89. package/src/codex-vscode-restore-smoke.mjs +206 -0
  90. package/src/codex-vscode-restore-smoke.test.mjs +325 -0
  91. package/src/codex-vscode-rollback-smoke.mjs +90 -0
  92. package/src/codex-vscode-rollback-smoke.test.mjs +290 -0
  93. package/src/db-schema.test.mjs +96 -0
  94. package/src/db.mjs +14 -1
  95. package/src/haiku-summarizer.mjs +267 -26
  96. package/src/haiku-summarizer.test.mjs +282 -0
  97. package/src/handoff-preview.test.mjs +108 -0
  98. package/src/handoff-record.mjs +294 -0
  99. package/src/handoff-record.test.mjs +226 -0
  100. package/src/hook-entrypoints.test.mjs +286 -0
  101. package/src/package-files.test.mjs +19 -0
  102. package/src/prompt-submit.mjs +9 -6
  103. package/src/resume-context.mjs +58 -171
  104. package/src/resume-context.test.mjs +177 -0
  105. package/src/session-start.mjs +85 -26
  106. package/src/state-file.mjs +50 -6
  107. package/src/state-file.test.mjs +50 -0
  108. package/src/token-monitor.mjs +14 -10
  109. package/src/token-monitor.test.mjs +27 -0
  110. package/src/trim-cli.test.mjs +1584 -0
  111. package/src/trim-model.mjs +584 -0
  112. package/src/trim-model.test.mjs +568 -0
  113. package/src/turn-processor.mjs +17 -10
  114. package/src/vscode-task.mjs +33 -10
  115. package/src/vscode-task.test.mjs +19 -9
  116. package/src/cli/save-inflight.mjs +0 -81
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  ```bash
20
20
  npm install -g throughline
21
- throughline install # registers hooks in ~/.claude/settings.json
21
+ throughline install # registers Claude hooks, Codex Stop hook, and Codex skill
22
22
  ```
23
23
 
24
24
  That's it. Open any Claude Code session and your turns flow into
@@ -27,6 +27,15 @@ That's it. Open any Claude Code session and your turns flow into
27
27
  session to inherit the memory — the new session resumes mid-thought instead
28
28
  of starting from zero.
29
29
 
30
+ Global install also registers a Codex Stop hook in `~/.codex/hooks.json` and
31
+ enables `[features].codex_hooks = true` in `~/.codex/config.toml`. The Codex
32
+ hook invokes the installed `bin/throughline.mjs` through an absolute Node path,
33
+ so Codex App Server PATH differences do not hide the command. It is registered
34
+ synchronously (`async: false`), matching the Codex hook behavior verified in
35
+ Caveat. Existing non-Throughline Codex hooks are preserved. It also installs a
36
+ global `$throughline` Codex skill, so in Codex you can ask for Throughline
37
+ status, resume, summarize, or trim without typing the full guarded command.
38
+
30
39
  ## How it compares
31
40
 
32
41
  | | Throughline | MemGPT / SummaryBufferMemory | Plain Claude Code |
@@ -36,7 +45,7 @@ of starting from zero.
36
45
  | **`/clear` survival** | ✅ via SQLite + `/tl` baton | depends on host | ❌ |
37
46
  | **Auto-inheritance risk** | zero (explicit `/tl`) | high | — |
38
47
  | **Runtime deps** | **zero** (Node 22.5+ built-in `node:sqlite`) | many | — |
39
- | **Multi-session token monitor** | ✅ real `message.usage`, no `len/4` | — | — |
48
+ | **Multi-session token monitor** | ✅ Claude real `message.usage`; Codex rollout `token_count` when available | — | — |
40
49
 
41
50
  <details>
42
51
  <summary><b>Why this matters — the 80% tool-I/O problem</b></summary>
@@ -100,7 +109,7 @@ flowchart LR
100
109
 
101
110
  | Layer | Name | Where it lives | Content | Cost per turn |
102
111
  | ----- | ---------- | --------------------- | --------------------------------------------------------------------- | ------------- |
103
- | **L1** | Skeleton | injected when old | one-line Haiku-generated summary of the turn | ~10 tok |
112
+ | **L1** | Skeleton | injected when old | one-line summary of the turn (current Claude-primary path: Claude Haiku, optional Codex sidecar) | ~10 tok |
104
113
  | **L2** | Body | injected when recent | user text + assistant reply, verbatim | full natural |
105
114
  | **L3** | Detail | SQLite only | tool I/O, system messages, images, **extended thinking** (on-demand) | heavy, retired |
106
115
 
@@ -118,10 +127,13 @@ injects it as plain text:
118
127
  - **Older turns** are injected as L1 (`skeletons`) one-liners
119
128
  - L3 stays in SQLite and is retrieved on demand via `/sc-detail <time>`
120
129
 
121
- L1 summaries are generated by **Claude Haiku 4.5** via a subprocess
122
- (`claude -p --model claude-haiku-4-5-*`), reusing your Claude Max login no API
123
- key required. Summarization is lazy: for sessions that stay under 20 turns,
124
- Haiku is never invoked, so short tasks cost zero summarization time.
130
+ L1 summaries are generated lazily: for sessions that stay under 20 turns, no
131
+ external summarizer is invoked. In the current Claude-primary path, Throughline uses **Claude Haiku 4.5**
132
+ via a subprocess (`claude -p --model claude-haiku-4-5-*`), reusing your Claude
133
+ Max login no API key required. When `codex-sidecar` is explicitly configured
134
+ for the `summarize-l1` preset, Throughline can use that instead.
135
+ For Codex-primary capture, the L1 backend is the Codex CLI; failures are explicit
136
+ and do not fall back to Claude Haiku or raw L2.
125
137
 
126
138
  All three layers (L1/L2/L3) have working write paths as of schema v5.
127
139
  `/sc-detail HH:MM:SS` returns user/assistant text (L2) plus a kind-grouped view
@@ -129,65 +141,341 @@ of tool inputs, tool outputs, and hook output captured at L3 for that turn.
129
141
 
130
142
  ---
131
143
 
132
- ## Explicit handoff via `/tl` (with in-flight memo)
133
-
134
- Inheritance is **opt-in**, not automatic. When you want the next session to
135
- pick up where this one left off, type `/tl` in the current session before you
136
- `/clear` or open a new chat. Without `/tl`, new sessions start fresh — no
137
- memory is carried over.
138
-
139
- The `/tl` slash command does two things:
140
-
141
- 1. **Writes a handoff baton** (the current `session_id`) into the
142
- `handoff_batons` table via the `UserPromptSubmit` hook.
143
- 2. **Asks the current Claude to write an in-flight memo.** `/tl` instructs
144
- Claude to summarize *what it was about to do next, its current hypothesis,
145
- open questions, and in-progress TODOs*, then pipe that Markdown into
146
- `throughline save-inflight`, which attaches it to the baton's `memo_text`
147
- column. This captures the "currently thinking" state that plain transcript
148
- replay cannot preserve.
149
-
150
- On the next `SessionStart`, the hook reads the baton, and if it is less than
151
- **1 hour old**, merges that session's memory into the new session using a
152
- deterministic `UPDATE session_id = ?` inside a `BEGIN IMMEDIATE` transaction.
153
- The baton is consumed (deleted) atomically with the merge, so it cannot fire
154
- twice. The injected resume context is reframed as **"resuming an interrupted
155
- task"** rather than *"reading past logs"*, and the in-flight memo plus the
156
- final turn's extended thinking appear at the top so the new Claude picks up
157
- mid-thought.
144
+ ## Inheritance: auto via `/clear`, opt-out via env, opt-in via `/tl`
145
+
146
+ Throughline 0.4.0+ supports two inheritance paths:
147
+
148
+ ### auto path (default): `/clear` automatic inheritance
149
+
150
+ Since Claude Code 2.1.128, the SessionStart hook receives `source='clear'`
151
+ reliably after `/clear`. Throughline detects this and automatically merges the
152
+ previous session's memory into the new one. **No user action required** —
153
+ just type `/clear` and the new chat resumes mid-thought.
154
+
155
+ Set `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` in your environment to opt out.
156
+
157
+ ### baton path (`/tl`): explicit inheritance signal
158
+
159
+ For users who:
160
+
161
+ - have `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` set, **or**
162
+ - want to inherit across a non-`/clear` boundary (new chat / VSCode restart),
163
+
164
+ type `/tl` before opening the new session. The `UserPromptSubmit` hook writes
165
+ a handoff baton; the next `SessionStart` (within 1 hour) consumes the baton
166
+ and merges the previous session's memory, regardless of the `source` value.
158
167
 
159
168
  ```
160
- Session A (type /tl) -----------> baton written
161
- |
162
- /clear |
163
- | ▼
164
- Session B ---- reads baton, merges A into B, deletes baton ---->
165
- |
166
- (type /tl again to hand off further)
169
+ auto path: Session A /clear Session B (auto-merges A)
170
+ baton path: Session A → /tl → (new chat / restart) → Session B (consumes baton, merges A)
167
171
  ```
168
172
 
169
- Why explicit baton instead of auto-inherit:
173
+ ### What gets injected
174
+
175
+ Both paths inject the **same** curated memory:
170
176
 
171
- - **Zero false positives.** A parallel window, a VSCode restart, or a genuine
172
- new task in the same repo won't accidentally inherit the previous session's
173
- memory. Only an explicit `/tl` triggers inheritance.
174
- - **VSCode extension compatibility.** The `SessionStart` hook's `source` field
175
- is rewritten to `"startup"` by the Claude Code VSCode extension even after
176
- `/clear` (see [issue #49937](https://github.com/anthropics/claude-code/issues/49937)),
177
- so source-based detection is unreliable. A user-driven baton sidesteps this.
178
- - **Deterministic.** No time-window heuristic, no PID guessing, no ancestor
179
- walking. The user declares intent; the hook carries it out.
177
+ - L1 summaries (older turns, one-line)
178
+ - L2 verbatim (most recent 20 turns, full text)
179
+ - L3 references (`throughline detail <time>` retrieval commands; bodies stay in SQLite)
180
180
 
181
- Each merged row keeps its `origin_session_id`, so repeated `/tl` handoffs
181
+ The injection is reframed as **"resuming an interrupted task"** rather than
182
+ "reading past logs". The L2 verbatim already contains the last assistant
183
+ turn — what Claude was about to do next — so no separate memo or extended
184
+ thinking section is injected.
185
+
186
+ Each merged row keeps its `origin_session_id`, so repeated handoffs
182
187
  accumulate memory through chains:
183
188
 
184
189
  ```
185
- S1 (4 turns) --/tl,/clear--> S2 (merges S1, adds 3 turns) --/tl,/clear--> S3 (merges S2, adds 5 turns)
186
- origin=S1×4 origin=S1×4, S2×3, S3×5
190
+ S1 (4 turns) --/clear--> S2 (auto-merges S1, adds 3 turns) --/clear--> S3 (auto-merges S2, adds 5 turns)
191
+ origin=S1×4 origin=S1×4, S2×3, S3×5
187
192
  ```
188
193
 
189
194
  ---
190
195
 
196
+ ## Codex sidecar and Codex trim
197
+
198
+ Throughline is still **Claude Code first**. Codex support is an adapter layer:
199
+ it can project the same `HandoffRecord` into a `throughline_handoff` JSON block,
200
+ and it can optionally use `codex-sidecar` for read-only review / risk-check
201
+ work when that tool is installed and configured. It does not replace Claude
202
+ hooks, slash commands, transcript parsing, or `/tl` baton handoff behavior.
203
+
204
+ Useful inspection commands:
205
+
206
+ ```bash
207
+ throughline handoff-preview --session <id>
208
+ throughline codex-summarize --session codex:<thread-id> --json
209
+ throughline codex-resume --session codex:<thread-id>
210
+ throughline codex-resume --session codex:<thread-id> --format handoff
211
+ throughline codex-handoff-start --session codex:<thread-id>
212
+ throughline codex-handoff-smoke --session codex:<thread-id>
213
+ throughline codex-handoff-model-smoke --session codex:<thread-id> --dry-run --json
214
+ THROUGHLINE_EXPERIMENTAL_CODEX_HANDOFF_MODEL_SMOKE=1 \
215
+ throughline codex-handoff-model-smoke --session codex:<thread-id> --json
216
+ throughline codex-resume --session codex:<thread-id> --format item-json
217
+ printf '**Next move**: continue the Codex implementation\n' \
218
+ | throughline codex-resume --session codex:<thread-id> --memo-stdin
219
+ printf '**Next move**: continue the Codex implementation\n' \
220
+ | THROUGHLINE_EXPERIMENTAL_CODEX_MODEL_VISIBLE_SMOKE=1 \
221
+ throughline codex-visibility-smoke --session codex:<thread-id> --memo-stdin \
222
+ --request-timeout-ms 150000 --json
223
+ THROUGHLINE_EXPERIMENTAL_CODEX_MODEL_VISIBLE_SMOKE=1 \
224
+ throughline codex-visibility-smoke --session codex:<thread-id> \
225
+ --resume-after-inject --request-timeout-ms 180000 --json
226
+ throughline codex-threads --limit 5
227
+ throughline codex-sidecar-diagnostics --project . --preset review
228
+ throughline codex-sidecar-dry-run --project . --preset risk-check \
229
+ --context-file docs/throughline-handoff-context.example.json
230
+ ```
231
+
232
+ The only existing external model call in core Throughline is L2→L1
233
+ summarization. When `codex-sidecar` is configured for `summarize-l1`,
234
+ Throughline can use it for that step; otherwise it keeps the existing Claude
235
+ Haiku path. This is an explicit compatibility mode, not silent auto-detection.
236
+
237
+ **Codex rollback / inject is enabled.** The 2026-05-06 incident initially
238
+ looked like a rolled-back user prompt could reappear after VS Code restart /
239
+ reconnect, but controlled model-visible rollback smokes did not reproduce that
240
+ path. `throughline trim --execute --host codex` now sends the guarded
241
+ rollback + Throughline DB memory injection when app-server turn-count guards and
242
+ injectable DB memory are available. Codex Stop hook auto-refresh also attempts
243
+ the same live refresh when verified usage reaches the 90% threshold.
244
+
245
+ `throughline codex-host-primitive-audit` can inspect the installed Codex
246
+ app-server schema read-only. On the current tested Codex CLI, it finds
247
+ `thread/rollback`, `thread/inject_items`, and new-thread primitives, but no
248
+ current-thread primitive that either clears/rewrites retained rollback sources
249
+ or isolates/projects them away from model-visible input. This is now diagnostic
250
+ evidence only, not an execute blocker. The audit also emits a host-agnostic same-thread repair contract:
251
+ a passing design needs a current-thread non-resurrection primitive, rollback
252
+ non-resurrection guarantee, memory reinjection, post-repair read verification,
253
+ and a restart / reconnect non-resurrection smoke. VS Code evidence can inform
254
+ that contract, but it is not itself the repair primitive.
255
+
256
+ Dry-run and preflight also inspect planned rollback risk. If the user text that
257
+ would be removed is already present in Codex `compacted.replacement_history`,
258
+ Throughline reports `Planned rollback restore safety: risk` as diagnostic
259
+ context, but it no longer refuses preflight or execute on that basis.
260
+
261
+ The intended memory contract remains:
262
+ older turns come back as L1 summaries, the latest 20 turns come back as full L2
263
+ conversation bodies, and L3 remains detail references instead of inline tool
264
+ payloads. Throughline never guesses the active Codex thread: use
265
+ `throughline codex-threads` to inspect read-only rollout candidates, then pass
266
+ the chosen id explicitly. If a wrapper or host exports
267
+ `THROUGHLINE_CODEX_THREAD_ID` or `CODEX_THREAD_ID`, `throughline trim --host
268
+ codex` treats that as a current-thread identity signal; the CLI flag still wins
269
+ when both are present. Throughline does not fall back to "latest rollout"
270
+ guessing. When the chosen Codex thread has a current-project rollout,
271
+ `throughline trim` can use the rollout as the trim source even if the
272
+ Throughline DB has no captured Codex turn bodies; rollback events in the rollout
273
+ are applied before the rollback plan is built. When DB memory exists, the
274
+ injected memory is built from the Throughline DB rather than from the rollout
275
+ preview; guarded execute refuses instead of injecting a rollout preview when
276
+ Throughline DB memory is absent. During Codex
277
+ preflight, Throughline also compares the rollout active-turn count with
278
+ app-server `thread/read` / `thread/resume` counts. The separate read-only
279
+ `codex-restore-smoke` also checks paginated `thread/turns/list` counts across
280
+ fresh app-server processes. These are live app-server guards only; they are not
281
+ by themselves a durable restart-safe proof. The guarded
282
+ execute path is enabled by explicit `--execute`; it may still report
283
+ `execute-sent-live-only` or `execute-unverified` if durable rollout evidence is
284
+ not observed. Throughline reports `execute-durable-verified` when the rollout
285
+ records a new rollback marker and records the injected active-work memory.
286
+ Developer memory injection is item-level on current Codex hosts and may not add a
287
+ host-visible turn during the immediate post-inject read; Throughline therefore
288
+ uses the `thread/inject_items` response shape to decide whether a turn-count
289
+ increase should be expected.
290
+ `doctor --codex` also reports this context-refresh readiness explicitly:
291
+ rollback source, inject memory source, the L1/L2/L3 memory contract, current
292
+ L1/L2/L3 counts, the heuristic reduction estimate when rollout text is
293
+ available, and the host primitive audit status as diagnostic context. L3 is
294
+ reported as references-only; L3 bodies and tool payloads are not injected.
295
+
296
+ Codex trim dry-run reports a context reduction estimate when rollout text is
297
+ available: rollback-candidate estimated tokens, injected-memory estimated
298
+ tokens, and net estimated reduction. This is a `chars / 4` heuristic from the
299
+ rollout text, not an exact host tokenizer measurement. If rollback candidate
300
+ turns are `0`, there is no current trim saving under the active keep-recent
301
+ setting.
302
+
303
+ Claude-side rewind UI itself is not driven by Throughline. The auto-handoff
304
+ flow is `/clear` → new SessionStart → automatic injection of curated memory.
305
+ Throughline does not invoke `/rewind` or any Claude Code internal command.
306
+
307
+ Codex-primary setup has an installed Stop hook after global
308
+ `throughline install`. In real sessions, verify capture rather than assuming it:
309
+ `doctor --codex` compares the current Codex thread with the latest captured DB
310
+ session, and makes any missing Throughline DB advance visible. A Codex VSCode
311
+ session that was already open before hook shape changes may not be a clean
312
+ natural Stop smoke; use a newly started session or `codex exec` smoke for that
313
+ check. A newly started VSCode-origin Codex session has been verified with
314
+ matching `current Codex thread` and `latest DB session` in `doctor --codex`.
315
+ The following commands are the explicit diagnostic, resume, smoke, and
316
+ guarded trim surfaces:
317
+
318
+ ```bash
319
+ throughline doctor --trim --host claude
320
+ throughline doctor --trim --host codex
321
+ throughline doctor --codex
322
+ throughline codex-capture --codex-thread-id <id> --json
323
+ throughline codex-summarize --session codex:<id> --json
324
+ throughline codex-resume --session codex:<id> --format handoff
325
+ throughline codex-handoff-start --session codex:<id>
326
+ throughline codex-handoff-smoke --session codex:<id> --json
327
+ throughline codex-handoff-model-smoke --session codex:<id> --dry-run --json
328
+ # optional model smoke; uses codex exec --ephemeral --sandbox read-only:
329
+ # THROUGHLINE_EXPERIMENTAL_CODEX_HANDOFF_MODEL_SMOKE=1 throughline codex-handoff-model-smoke --session codex:<id> --json
330
+ printf '**Next move**: continue the current Codex task\n' \
331
+ | throughline codex-resume --session codex:<id> --memo-stdin
332
+ printf '**Next move**: continue the current implementation\n' \
333
+ | throughline trim --dry-run --host claude --memo-stdin
334
+ throughline codex-threads --json --limit 5
335
+ throughline trim --dry-run --host codex --codex-thread-id <id>
336
+ throughline trim --dry-run --host codex --codex-thread-id <id> --preview-max-chars 4000
337
+ throughline trim --preflight --host codex --codex-thread-id <id>
338
+ CODEX_THREAD_ID=<id> throughline trim --preflight --host codex
339
+ # read-only app-server process restart smoke; not full VS Code restart-safe proof:
340
+ # THROUGHLINE_EXPERIMENTAL_CODEX_RESTORE_SMOKE=1 throughline codex-restore-smoke --codex-thread-id <id> --json
341
+ # read-only local restore source inventory; not full VS Code restart-safe proof:
342
+ # throughline codex-restore-source-audit --codex-thread-id <id> --json
343
+ # manual two-phase VS Code reload/reconnect smoke:
344
+ # THROUGHLINE_EXPERIMENTAL_CODEX_VSCODE_RESTORE_SMOKE=1 throughline codex-vscode-restore-smoke --prepare --codex-thread-id <id> --json
345
+ # after reloading/reconnecting VS Code and sending the printed prompt:
346
+ # throughline codex-vscode-restore-smoke --verify --codex-thread-id <id> --marker <marker> --prepared-at <iso> --after-vscode-restart --json
347
+ # explicit current-thread trim:
348
+ throughline trim --execute --host codex --all --codex-thread-id <id>
349
+ ```
350
+
351
+ That current-work framing matters: the original `/tl` design learned that L1/L2
352
+ memory alone can read like past logs rather than "the work in progress". The
353
+ memo is one strong signal, but the broader mechanism is explicit structure:
354
+ recent L2 is labeled as an active work thread, older hypotheses may be
355
+ superseded by later entries, and the continuation instruction appears at the
356
+ top and bottom of the injected memory.
357
+
358
+ For Codex-primary sessions, `throughline codex-capture --codex-thread-id <id>`
359
+ stores active rollout turns under `codex:<thread_id>`, and `throughline
360
+ codex-summarize --session codex:<thread_id>` can write older captured L2 turns
361
+ to L1 with the Codex CLI backend. `throughline codex-resume --session
362
+ codex:<thread_id>` renders that memory as an active-work context. `--format
363
+ handoff` renders a shorter prompt for starting a new Codex thread without
364
+ mutating the old one; it caps recent L2 entries, long body text, and detail
365
+ references while pointing back to the full `codex-resume` context. `--format
366
+ item-json` returns a Codex developer-message item for hosts that accept
367
+ structured item injection; it is a rendering surface only and does not mutate
368
+ the Codex thread by itself. `--memo-stdin` prepends an explicit Codex-primary
369
+ current-work memo to that rendered context; this is a Codex-side opt-in for
370
+ "what was I about to do next" signal, independent from the Claude `/tl` baton.
371
+ `throughline codex-visibility-smoke` is the experimental mutation check for
372
+ that rendered memory: it injects the active-work developer message and starts a
373
+ marker-check model turn through the Codex app-server, so it requires the
374
+ `THROUGHLINE_EXPERIMENTAL_CODEX_MODEL_VISIBLE_SMOKE=1` opt-in. In local real-host
375
+ smoke testing, the marker appeared in `item/agentMessage/delta`; use
376
+ `--resume-after-inject` to verify injected memory still survives a second
377
+ `thread/resume` before `turn/start`, and use `--request-timeout-ms` /
378
+ `--timeout-ms` when the model turn may take longer than the default wait.
379
+ `throughline codex-restore-smoke` is the read-only restart diagnostic for the
380
+ same boundary: it starts fresh Codex app-server processes and compares
381
+ `thread/read` / `thread/resume` / paginated `thread/turns/list` turn counts with
382
+ the rollout active turn count. Its proof scope is
383
+ `app_server_process_restart_only`; even a passing result is not VS Code
384
+ restart-safe proof for rollback / inject. With `--inspect-risky-rollout`, it can
385
+ inspect a risky rollout read-only; if retained rollback text appears in
386
+ app-server responses, the status becomes `app-server-restore-text-retained`
387
+ when it appears in blocking candidates such as direct turn text or
388
+ `replacement_history`, or `app-server-restore-text-quoted` when it appears only
389
+ inside quoted/tool-output fields such as `aggregatedOutput`. The text-match
390
+ report includes sample JSON paths, location kinds, risk classes, and
391
+ `blocking-candidates` so quoted old output is not confused with resurrected user
392
+ message fields.
393
+ `throughline codex-restore-source-audit` is the local inventory companion: it
394
+ checks the Codex rollout, `session_index.jsonl`, `state_*.sqlite`, and VS Code
395
+ globalStorage / workspaceStorage candidates, VS Code `settings.json`, and VS
396
+ Code logs for the chosen thread id and retained rollback text. SQLite-backed VS
397
+ Code storage candidates such as `.vscdb`, `.sqlite`, `.sqlite3`, and `.db` are
398
+ opened read-only and summarized by table / column / needle matches. It also
399
+ scans installed OpenAI/Codex VS Code extension bundles for restore-path signals
400
+ such as `thread/read`, `thread/resume`, `thread/turns/list`, reconnect
401
+ `needs_resume`, persisted webview atoms, follow-up queue signals, and explicit
402
+ rollback non-resurrection projection candidates such as `replacement_history`
403
+ filter / tombstone paths. A match here is static evidence only; current tested storage roots can still report
404
+ `VS Code storage matches: 0` for the selected thread and retained rollback text.
405
+ VS Code log matches are also classified into thread-id hits, retained rollback
406
+ text hits, patch-apply failures, thread stream broadcasts, and
407
+ `replacement_history` signals so incidental log mentions can be separated from
408
+ restore-path evidence.
409
+ Its proof scope is `local_restore_source_inventory_only`; it can narrow the
410
+ restore-source hypothesis, but it still does not prove VS Code restart safety.
411
+ These VS Code scans are diagnostics only. The product repair path remains the
412
+ host-agnostic same-thread contract reported by `codex-host-primitive-audit`, not
413
+ a VS Code-only implementation path.
414
+ `throughline codex-vscode-restore-smoke` is the manual full-boundary protocol:
415
+ `--prepare` injects a hidden active-work developer-memory marker, then VS Code
416
+ must be reloaded or reconnected and asked a prompt that does not contain the
417
+ marker. `--verify` scans the rollout for a marker answer after the prepare
418
+ timestamp and rejects the proof if the marker leaked through the user prompt.
419
+ Only a marker-free smoke prompt followed by an assistant answer whose trimmed
420
+ text exactly equals the marker, plus `--after-vscode-restart`, is treated as
421
+ `restartSafe: true`; prepare remains an explicit experiment gated by
422
+ `THROUGHLINE_EXPERIMENTAL_CODEX_VSCODE_RESTORE_SMOKE=1`. A real VS Code
423
+ reload/reconnect run has passed this marker proof, showing hidden developer
424
+ memory can remain model-visible after reconnect. That is not the same as
425
+ proving rollback-targeted user turns cannot resurrect, so rollback-specific
426
+ smokes remain the stronger diagnostic boundary.
427
+ `throughline codex-vscode-rollback-smoke --verify --after-vscode-restart` is
428
+ the read-only verifier for that next proof: it requires a rollback event,
429
+ rolled-back user text, a later user turn, and `restoreSafety: ok` before it
430
+ will report `restartSafe: true`.
431
+ `throughline codex-rollback-model-visible-smoke` is a stricter controlled
432
+ experiment for the current thread: `--prepare` creates a unique user marker and
433
+ rolls that turn back, while `--verify` later starts a model turn that contains
434
+ only the marker prefix, not the full marker. It reports `reproduced` only if the
435
+ model returns the hidden full marker. This mutates the thread and is gated by
436
+ `THROUGHLINE_EXPERIMENTAL_CODEX_ROLLBACK_MODEL_VISIBLE_SMOKE=1`. Use
437
+ `--marker-file <path>` for live runs so the full marker is stored locally instead
438
+ of being printed into the same conversation being tested. Verify output reports
439
+ `rolledBackMarkerModelVisible` separately from `restartSafe`. In a controlled
440
+ 2026-05-08 current-thread run, both the immediate fresh app-server verify and
441
+ the post VS Code reload/reconnect verify returned `not-reproduced` with no full
442
+ marker in the prompt or observed assistant output.
443
+
444
+ A 2026-05-07 incident-shaped live rollback run produced useful risk evidence:
445
+ `thread_rolled_back` and injected active-work memory were recorded in the
446
+ rollout, but rollback-targeted user text remained in
447
+ `compacted.replacement_history`, and the verifier later observed rolled-back
448
+ user text reappearing in rollout/app-server diagnostics (`restoreSafety:
449
+ risk`). A later risky restore inspection found those retained matches only
450
+ inside `aggregatedOutput`, so this is not yet proof that the text is sent as a
451
+ fresh user message or model-visible input. Because the controlled reproduction
452
+ smoke stayed clean across app-server restart and VS Code reload/reconnect,
453
+ Throughline no longer blocks Codex trim solely on this diagnostic risk.
454
+
455
+ For Codex, fresh-thread handoff remains an explicit continuation path in trim
456
+ plans and trim diagnostics, but it is not a replacement for current-thread
457
+ trim. The guided entrypoint is
458
+ `throughline codex-handoff-start --session codex:<thread-id>`; it shows the
459
+ structural smoke, model-smoke dry-run boundary, handoff render command, optional
460
+ live model smoke, and can include the prompt with `--print-prompt`. With
461
+ `--memo-stdin`, it also propagates `--memo-stdin` into the replay commands and
462
+ reminds you to pipe the same memo when using them separately. The
463
+ individual commands remain available: validate the fresh-thread handoff with
464
+ `throughline codex-handoff-smoke --session codex:<thread-id>`, optionally audit
465
+ the model-smoke boundary with
466
+ `throughline codex-handoff-model-smoke --session codex:<thread-id> --dry-run --json`,
467
+ render it with `throughline codex-resume --session codex:<thread-id> --format handoff`,
468
+ then start a new Codex thread with that context. This does not mutate the current
469
+ thread. `trim --execute --host codex` is the current-thread mutation path and
470
+ still requires explicit execution, injectable Throughline DB memory, and
471
+ rollout/app-server turn-count agreement.
472
+ Human-readable dry-run output truncates the inline memory preview for scanability;
473
+ the full text remains in `--json` as `memoryPreview.text`, and for Codex the
474
+ fresh-thread continuation can be guided with `codex-handoff-start` or rendered
475
+ directly with the `codex-resume` command shown in the fresh-thread continuation path.
476
+
477
+ ---
478
+
191
479
  ## Multi-session token monitor
192
480
 
193
481
  Run:
@@ -198,24 +486,38 @@ throughline monitor --all # every project, every session
198
486
  throughline monitor --session <id-prefix>
199
487
  ```
200
488
 
201
- Example output (real values from a running 1M-context Opus session):
489
+ Example output:
202
490
 
203
491
  ```
204
492
  [Throughline] 1 セッション
205
- ▶ Throughline 2ed5039c ████░░░░░░░░░░░░░░░░ 205.1k / 21% 残 794.9k claude-opus-4-6
493
+ ▶ Throughline Claude 2ed5039c just now ██░░░░░░░░ 205.1k / 1.0M claude-opus-4-6
494
+ Throughline Codex codex:01 just now ██████░░░░ 151.9k / 258.4k gpt-5.5
206
495
  ```
207
496
 
208
- - **Token counts are accurate.** Read straight from the latest `message.usage`
209
- field in the session transcript JSONL, which is what Anthropic's API actually
210
- reported (`input_tokens + cache_creation_input_tokens + cache_read_input_tokens`).
497
+ - **Claude token counts are accurate.** Read straight from the latest
498
+ `message.usage` field in the session transcript JSONL, which is what
499
+ Anthropic's API actually reported
500
+ (`input_tokens + cache_creation_input_tokens + cache_read_input_tokens`).
211
501
  No `length / 4` approximation.
502
+ - **Codex token counts use the rollout `token_count` event when present.** The
503
+ Codex Stop hook writes `codex:<thread_id>` monitor state and snapshots the
504
+ latest verified rollout `token_count` sample. If a Codex rollout has no
505
+ token-count event, Throughline can store an explicit estimate with
506
+ `estimated: true` and the monitor marks it with `est`; it is not presented as
507
+ exact usage.
508
+ - **Codex auto-refresh mutates at the verified 90% threshold.** The Codex Stop
509
+ hook captures DB memory, writes monitor state, and when verified usage reaches
510
+ the threshold it attempts rollback + Throughline DB memory injection for the
511
+ current thread.
212
512
  - **1M-context detection** is automatic. It checks the `[1m]` suffix in the
213
513
  transcript, falls back to string matching on `1M context`, and finally
214
514
  promotes to 1M if observed usage exceeds 200k.
215
- - **Multi-session view.** Each Claude Code session writes its own state file
216
- (`~/.throughline/state/<session_id>.json`). The monitor scans the directory
217
- every second and displays one row per live session, sorted by last activity.
218
- The most recent one is highlighted with `▶`.
515
+ - **Multi-session view.** Each Claude Code or Codex session writes its own
516
+ state file (`~/.throughline/state/<session_id>.json`). Codex session ids are
517
+ stored as `codex:<thread_id>` in the JSON payload; filenames are URL-encoded
518
+ so the state directory remains portable. The monitor scans the directory every
519
+ second and displays one row per live session, sorted by last activity. The
520
+ most recent one is highlighted with `▶`.
219
521
  - **Stale hiding.** Sessions that haven't been touched in 15 minutes drop out of
220
522
  the default view; files older than 24 hours are deleted entirely. This is the
221
523
  only time threshold in the system and is used solely for display hygiene — no
@@ -246,7 +548,11 @@ Example output (real values from a running 1M-context Opus session):
246
548
  file. The monitor prefers this snapshot over re-reading the JSONL, which
247
549
  removes a source of flicker when the transcript path in state drifts from
248
550
  the one Claude Code is currently appending to.
249
- - **Non-blocking Stop hook (v0.3.22+).** The Stop hook is registered with
551
+ - **Host-aware state.** Missing `host` means an older Claude state file.
552
+ Codex states use `host: "codex"`, keep `transcriptPath: null`, and store the
553
+ Codex rollout path separately as `rolloutPath` so the Claude transcript parser
554
+ is never pointed at a Codex rollout.
555
+ - **Non-blocking Claude Stop hook (v0.3.22+).** The Claude Stop hook is registered with
250
556
  `"async": true` so `throughline process-turn` runs in the background and
251
557
  does not delay Claude's reply from reaching you. L1 Haiku summarization
252
558
  (`claude -p` subprocess + inference, seconds to tens of seconds) would
@@ -279,6 +585,10 @@ Once per project it inspects `.vscode/tasks.json`:
279
585
  - **Already contains a Throughline Monitor task** → does nothing (idempotent;
280
586
  this is the common path on every subsequent turn; notice is silent).
281
587
 
588
+ For Codex-primary projects, hook stdout is not always surfaced in the chat.
589
+ `throughline doctor --codex` therefore reports the VS Code monitor task status,
590
+ its `runOn` value, and the same Reload Window note in a visible diagnostic.
591
+
282
592
  The generated task uses `type: 'shell'` with the absolute path to Node and
283
593
  `bin/throughline.mjs`. VS Code wraps shell tasks in a PTY (xterm.js) so the
284
594
  monitor sees `isTTY=true`, real `columns`, and resize events. Windows `.cmd`
@@ -320,15 +630,36 @@ entry to the `tasks` array yourself:
320
630
 
321
631
  | Command | What it does |
322
632
  | ---------------------------------------------- | ------------------------------------------------------------ |
323
- | `throughline install` | Register hooks in `~/.claude/settings.json` (user scope) |
324
- | `throughline install --project` | Register hooks in `.claude/settings.json` for this repo only |
325
- | `throughline uninstall` | Remove Throughline hooks from the settings file |
633
+ | `throughline install` | Register Claude user hooks/slash commands, the global Codex Stop hook, and the global `$throughline` Codex skill |
634
+ | `throughline install --project` | Register Claude hooks/slash commands in this repo only |
635
+ | `throughline uninstall` | Remove Throughline-managed Claude hooks/slash commands, only the Throughline-managed Codex hook, and the `$throughline` Codex skill |
326
636
  | `throughline monitor [--all] [--session <id>]` | Run the multi-session token monitor |
327
637
  | `throughline monitor --diag` | Dump TTY/columns/env diagnostics (for debugging monitor render bugs) |
328
638
  | `throughline detail <time>` | Retrieve L2 body text and L3 tool I/O for a turn (see below) |
329
- | `throughline save-inflight` | Called by `/tl` to attach an in-flight memo (stdin) to the current baton |
330
639
  | `throughline doctor` | Check Node version, hook registration, DB writability, PATH |
331
640
  | `throughline doctor --session <id-prefix>` | Diagnose a specific session — detect state/transcript drift, idle vs. stuck |
641
+ | `throughline doctor --trim --host claude\|codex` | Diagnose trim host boundaries, manual procedure, and Codex host primitive blockage |
642
+ | `throughline doctor --codex` | Diagnose Codex primary entry state, captured DB sessions, context-refresh memory contract, new-thread handoff readiness, safe continuation status, and host primitive audit |
643
+ | `throughline handoff-preview --session <id>` | Print a Codex-facing `throughline_handoff` JSON projection |
644
+ | `throughline codex-capture --codex-thread-id <id>` | Capture active Codex rollout turns into a `codex:<thread_id>` DB session |
645
+ | `throughline codex-summarize --session codex:<id>` | Summarize captured Codex L2 into L1 with the Codex CLI backend |
646
+ | `throughline codex-resume --session codex:<id>` | Render Codex active-work context from a captured Codex session |
647
+ | `throughline codex-resume --session codex:<id> --format handoff` | Render a concise fresh-thread handoff prompt without mutating the current thread |
648
+ | `throughline codex-handoff-start --session codex:<id>` | Guided read-only start plan for moving the handoff prompt into a new Codex thread; use `--print-prompt` to include the prompt and `--memo-stdin` to carry a current-work memo |
649
+ | `throughline codex-handoff-smoke --session codex:<id>` | Read-only validation that the fresh-thread handoff prompt is pasteable before starting a new thread |
650
+ | `throughline codex-handoff-model-smoke --session codex:<id>` | Experimental marker smoke for the handoff prompt. `--dry-run` checks readiness / command boundary without starting Codex exec; `--memo-stdin` carries a current-work memo; live `codex exec --ephemeral --sandbox read-only` requires explicit env opt-in |
651
+ | `throughline codex-visibility-smoke --session codex:<id>` | Experimental Codex app-server marker smoke; injects memory and starts a model turn |
652
+ | `throughline codex-restore-smoke --codex-thread-id <id>` | Experimental read-only app-server restart restore smoke; `--inspect-risky-rollout` classifies retained rollback text as blocking retained text or quoted/tool-output text; does not prove VS Code restart safety |
653
+ | `throughline codex-restore-source-audit --codex-thread-id <id>` | Read-only local restore-source inventory, including VS Code projection-candidate facts; does not prove VS Code restart safety |
654
+ | `throughline codex-host-primitive-audit` | Read-only Codex app-server schema audit for same-thread rollback non-resurrection primitives and the host-agnostic repair contract |
655
+ | `throughline codex-vscode-restore-smoke --prepare/--verify --codex-thread-id <id>` | Manual VS Code reload/reconnect marker proof protocol |
656
+ | `throughline codex-vscode-rollback-smoke --verify --codex-thread-id <id>` | Manual VS Code rollback non-resurrection verifier |
657
+ | `throughline codex-threads` | List read-only Codex thread id candidates for the current project |
658
+ | `throughline codex-sidecar-diagnostics` | Check `codex-sidecar` diagnostics status for this project |
659
+ | `throughline codex-sidecar-dry-run` | Print a normalized read-only sidecar request without running the app server |
660
+ | `throughline trim --dry-run --host codex` | Preview Codex same-thread context trim memory and host boundary; does not rollback automatically |
661
+ | `throughline trim --preflight --host codex` | Read/resume the explicit Codex thread and verify turn-count guards without rollback/inject |
662
+ | `throughline trim --execute --host codex` | Explicit Codex rollback-inject path; requires Codex thread identity, injectable DB memory, and rollout/app-server turn-count agreement |
332
663
  | `throughline status` | Print DB statistics (sessions, skeletons, bodies, details) |
333
664
  | `throughline --version` | Print the installed version |
334
665
 
@@ -336,13 +667,13 @@ Slash commands (invoked by the user in Claude Code):
336
667
 
337
668
  | Command | What it does |
338
669
  | ------------- | ----------------------------------------------------------------- |
339
- | `/tl` | Write a handoff baton + ask Claude to save an in-flight memo for the next session |
670
+ | `/tl` | Write a handoff baton (used as opt-in inheritance signal when `/clear` auto path is OFF or you skip `/clear`) |
340
671
  | `/sc-detail <time>` | Retrieve L2 body text and L3 tool I/O for a past turn |
341
672
 
342
- > When `/tl` triggers, Claude will call `throughline save-inflight` via its
343
- > Bash tool. Claude Code will prompt for permission the first time; add
344
- > `Bash(throughline save-inflight:*)` to your allowlist to skip the prompt on
345
- > subsequent `/tl` invocations.
673
+ > Auto-handoff is ON by default since v0.4.0: just type `/clear` and the new
674
+ > chat resumes mid-thought. Set `THROUGHLINE_DISABLE_AUTO_HANDOFF=1` in your
675
+ > environment to opt out. `/tl` is for users who opt out, or who want to
676
+ > inherit across non-`/clear` boundaries (new chat / VSCode restart).
346
677
 
347
678
  Hook subcommands (invoked by Claude Code, not by humans):
348
679
  `session-start` (SessionStart), `process-turn` (Stop),
@@ -396,7 +727,7 @@ Schema v7:
396
727
  - `skeletons` — L1 one-liners, keyed by `(session_id, origin_session_id, turn, role)`
397
728
  - `bodies` — L2 verbatim text (user + assistant), same key shape
398
729
  - `details` — L3 records with `kind` column (`tool_input` / `tool_output` / `system` / `image` / `thinking`) and `source_id` for idempotent re-processing
399
- - `handoff_batons` — one row per `project_path`, with `session_id`, `created_at`, and `memo_text` (the in-flight memo written by `save-inflight` after `/tl`). Consumed and deleted by the next `SessionStart` if within the 1-hour TTL.
730
+ - `handoff_batons` — one row per `project_path`, with `session_id` and `created_at`. Consumed and deleted by the next `SessionStart` if within the 1-hour TTL. (v8 dropped the `memo_text` column when memo was retired in v0.4.0.)
400
731
  - `injection_log` — audit trail of injection events
401
732
 
402
733
  All memory tables carry an `origin_session_id` so rebonded rows keep their
@@ -429,9 +760,10 @@ rule.
429
760
 
430
761
  ## Haiku recursion defense
431
762
 
432
- L1 summarization spawns `claude -p --model claude-haiku-4-5-*` as a subprocess.
433
- Without precautions this would recursively fire the same Stop hook on the
434
- subprocess and infinite-loop. Two defenses stack:
763
+ The default L1 summarization path spawns
764
+ `claude -p --model claude-haiku-4-5-*` as a subprocess. Without precautions this
765
+ would recursively fire the same Stop hook on the subprocess and infinite-loop.
766
+ Two defenses stack:
435
767
 
436
768
  1. **Isolated cwd.** The subprocess runs in `~/.throughline/haiku-workdir/`, a
437
769
  directory that contains no `.claude/settings.json`, so project-local hooks
@@ -583,6 +915,18 @@ the folder in VS Code.
583
915
  - [`docs/INHERITANCE_ON_CLEAR_ONLY.md`](docs/INHERITANCE_ON_CLEAR_ONLY.md) —
584
916
  design record for the `/tl` baton handoff system (schema v6–v7). Explains
585
917
  why the current inheritance is opt-in rather than heuristic.
918
+ - [`docs/THROUGHLINE_CODEX_DUAL_SUPPORT.md`](docs/THROUGHLINE_CODEX_DUAL_SUPPORT.md) —
919
+ architecture brief for adding Codex support without replacing the Claude
920
+ Code hook/slash-command path.
921
+ - [`docs/throughline-rollback-context-trim-insight.md`](docs/throughline-rollback-context-trim-insight.md) —
922
+ design insight for context rollback/trim, including why restored memory must
923
+ be framed as current work rather than passive history.
924
+ - [`docs/THROUGHLINE_CODEX_FIRST_ROADMAP.md`](docs/THROUGHLINE_CODEX_FIRST_ROADMAP.md) —
925
+ current next-phase TODO plan: Codex primary first, Codex rewind-compatible
926
+ trim next, Claude rewind finalization after that.
927
+ - [`docs/THROUGHLINE_CODEX_TRIM_IMPLEMENTATION_PLAN.md`](docs/THROUGHLINE_CODEX_TRIM_IMPLEMENTATION_PLAN.md) —
928
+ historical integrated TODO plan and implementation record for Claude/Codex
929
+ dual support and rollback trim.
586
930
  - [`docs/PUBLIC_RELEASE_PLAN.md`](docs/PUBLIC_RELEASE_PLAN.md) — public
587
931
  release plan, implementation status by version, § 0 fallback rule, and
588
932
  remaining tasks.