Distinguish forked sessions in session-start hooks (#44349)

## Why

Forked threads reported `startup`, causing startup hooks to run again even when their context was inherited from the parent. Resuming with supplied history also reported `startup` instead of `resume`.

## What changed

- Add `fork` as a `SessionStart` source and expose it in the hook input schema.
- Report `fork` for histories with a fork parent and `resume` for supplied histories without one.
- Continue dispatching `SubagentStart` for spawned subagents with either fresh or forked context.

## Testing

Add regression coverage for fork hook matching without duplicate startup context, resume hooks with supplied history, and `SubagentStart` context injection for fresh and forked subagents.

GitOrigin-RevId: 5ac1ae4ab8adcbbbceb8cb0ffb9b32b6402c585b
This commit is contained in:
Abhinav authored and copyberry committed 2026-09-10 00:26:30 +00:00
1 parent c6a59ef923
commit e444aa99d7
7 files changed
+197 -16

No files matched your search

+8 -3
View File
@@ -1682,10 +1682,15 @@ impl Session {
sess.schedule_startup_prewarm(sess.get_prompt_base_instructions().await.text)
.await;
let session_start_source = match &initial_history {
InitialHistory::Resumed(_) => codex_hooks::SessionStartSource::Resume,
InitialHistory::New | InitialHistory::Forked(_) => {
codex_hooks::SessionStartSource::Startup
InitialHistory::Forked(_) if forked_from_id.is_some() => {
codex_hooks::SessionStartSource::Fork
}
// `thread/resume` with supplied history uses `Forked` internally
// without a fork parent, so it should still report `resume`.
InitialHistory::Resumed(_) | InitialHistory::Forked(_) => {
codex_hooks::SessionStartSource::Resume
}
InitialHistory::New => codex_hooks::SessionStartSource::Startup,
InitialHistory::Cleared => codex_hooks::SessionStartSource::Clear,
};