[codex-analytics] rework thread_source for thread analytics (#20949)

## Summary
- make `thread_source` an explicit optional thread-level field on
`thread/start`, `thread/fork`, and returned thread payloads
- persist `thread_source` in rollout/session metadata so resumed live
threads retain the original value
- replace the old best-effort `session_source` -> `thread_source`
mapping with an explicit caller-supplied analytics classification

## Why
Before this change, analytics `thread_source` was populated by a
best-effort mapping from `session_source`. `session_source` describes
the runtime/client surface, not the actual thread-level origin, so that
projection was not accurate enough to distinguish cases such as `user`,
`subagent`, `memory_consolidation`, and future thread origins reliably.

Making `thread_source` explicit keeps one thread-level analytics field
while letting callers provide the real classification directly instead
of recovering it indirectly from `session_source`.

## Impact
For new analytics events, `thread_source` now reflects the explicit
thread-level classification supplied by the caller rather than an
inferred value derived from `session_source`. Existing protocol fields
remain optional; callers that omit `threadSource` now produce `null`
instead of a best-effort inferred value.

## Validation
- `just write-app-server-schema`
- `cargo test -p codex-analytics -p codex-core -p
codex-app-server-protocol --no-run`
- `cargo test -p codex-app-server-protocol
generated_ts_optional_nullable_fields_only_in_params`
- `cargo test -p codex-analytics
thread_initialized_event_serializes_expected_shape`
- `cargo test -p codex-core
resume_stopped_thread_from_rollout_preserves_thread_source`
This commit is contained in:
rhan-oai
2026-05-06 02:12:31 +00:00
committed by GitHub
parent 94db03d5af
commit b3d4f1a9f0
98 changed files with 896 additions and 90 deletions
+1
View File
@@ -1134,6 +1134,7 @@ fn session_configured_from_thread_response(
Ok(SessionConfiguredEvent {
session_id,
forked_from_id: None,
thread_source: None,
thread_name,
model,
model_provider_id,
+2
View File
@@ -255,6 +255,7 @@ fn turn_items_for_thread_returns_matching_turn_items() {
cwd: test_path_buf("/tmp/project").abs(),
cli_version: "0.0.0-test".to_string(),
source: codex_app_server_protocol::SessionSource::Exec,
thread_source: None,
agent_nickname: None,
agent_role: None,
git_info: None,
@@ -477,6 +478,7 @@ fn sample_thread_start_response() -> ThreadStartResponse {
cwd: test_path_buf("/tmp").abs(),
cli_version: "0.0.0".to_string(),
source: codex_app_server_protocol::SessionSource::Cli,
thread_source: None,
agent_nickname: None,
agent_role: None,
git_info: None,