diff --git a/skills/diagnosing-superpowers/references/claude-code-sessions.md b/skills/diagnosing-superpowers/references/claude-code-sessions.md index 7293b910e..af3f88610 100644 --- a/skills/diagnosing-superpowers/references/claude-code-sessions.md +++ b/skills/diagnosing-superpowers/references/claude-code-sessions.md @@ -39,7 +39,8 @@ Common envelope on `user`/`assistant`/`attachment`/`system` lines: | What you want | Where it is | |---|---| -| Human-typed prompt | `type=="user"`, `isMeta` absent or false, `message.content` is a string or a list whose first block is `type:"text"`. Lines whose first block is `tool_result` are tool results, not prompts. `` text inside a prompt is injected, not typed. | +| Human-typed prompt | `type=="user"`, `isMeta` absent or false, `message.content` is a string or a list whose first block is `type:"text"`. Lines whose first block is `tool_result` are tool results, not prompts. `` text inside a prompt is injected, not typed. Text beginning with ``, ``, ``, ``, or `This session is being continued from a previous conversation` is harness-injected too, even though `isMeta` is absent on those lines — exclude them or your human-turn count will be several times too high. | +| Human-typed prompt queued mid-turn | `type=="attachment"`, `attachment.type=="queued_command"`, `attachment.origin.kind=="human"`, text in `attachment.prompt`. These are typed while a turn is running and never appear as standalone `user` lines, so they are missing from the list above. Add them to the timeline. | | Assistant text / tool calls | `type=="assistant"`, `message.content[]` blocks of `type:"text"` or `type:"tool_use"` (`id`, `name`, `input`). | | Tool result | `type=="user"`, `message.content[0].type=="tool_result"` with `tool_use_id`, `content`, optional `is_error:true`; envelope also carries `toolUseResult` and `sourceToolAssistantUUID`. | | Model | `message.model` on assistant lines. | @@ -66,7 +67,11 @@ With `jq` (preferred): ```bash jq -r '.type' "$F" | sort | uniq -c # line-type census jq -r 'select(.type=="user" and .isMeta!=true and ((.message.content|type)=="string" or .message.content[0].type=="text")) + | select((.message.content|if type=="string" then . else (.[0].text // "") end) + | test("^(||||This session is being continued)") | not) | "\(input_line_number)\t\(.timestamp)\t\((.message.content|if type=="string" then . else .[0].text end)[0:160])"' "$F" # human prompts +jq -r 'select(.type=="attachment" and .attachment.type=="queued_command" and .attachment.origin.kind=="human") + | "\(input_line_number)\t\(.timestamp)\t\(.attachment.prompt[0:160])"' "$F" # human prompts queued mid-turn; merge with the list above jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | {name, id, input: (.input|tostring|.[0:120])}' "$F" # tool calls jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Skill") | .input.skill' "$F" # skill invocations diff --git a/skills/diagnosing-superpowers/references/codex-sessions.md b/skills/diagnosing-superpowers/references/codex-sessions.md index 1406ea96d..99da86099 100644 --- a/skills/diagnosing-superpowers/references/codex-sessions.md +++ b/skills/diagnosing-superpowers/references/codex-sessions.md @@ -1,8 +1,8 @@ # Codex session store -Verified against: Codex CLI 0.146.0 and 0.147.0 rollouts (`cli_version` in -`session_meta`), macOS. When a field below is missing from the file in front -of you, trust the file and say so in coverage notes. +Verified against: Codex CLI 0.146.0, 0.147.0 and 0.149.0-alpha.4.1 rollouts +(`cli_version` in `session_meta`), macOS. When a field below is missing from +the file in front of you, trust the file and say so in coverage notes. ## Where @@ -16,7 +16,10 @@ pointing at the parent thread id. Root sessions have `thread_source: "user"`. The most recently modified rollout whose `session_meta.payload.cwd` is the current working directory and whose `thread_source` is `user`. Confirm by matching the first `user_message` event to what your human partner -remembers. +remembers. Newer rollouts may carry no `user_message` event at all: when +that command returns nothing, fall back to `response_item` messages with +`role:"user"` (see Human-typed prompt below) and confirm against the first +of those instead. ## Line types @@ -28,7 +31,7 @@ Every line is `{timestamp, type, payload}` (some also carry `ordinal`). |---|---| | Session identity | `session_meta.payload`: `id`, `session_id`, `cwd`, `originator` (e.g. `Codex Desktop`), `cli_version`, `model_provider`, `thread_source`, `source`, `git` (`commit_hash`, `branch`, `repository_url`), `base_instructions.text`. | | Model per turn | `turn_context.payload`: `turn_id`, `model`, `effort`, `cwd`, `approval_policy`, `sandbox_policy`, `multi_agent_version`. Also `event_msg` `thread_settings_applied`. | -| Human-typed prompt | `event_msg` with `payload.type=="user_message"`: `payload.message`. (`response_item` messages with `role:"developer"` are injected, not typed; see Subagents below for rollouts that carry no `user_message` event at all.) | +| Human-typed prompt | `event_msg` with `payload.type=="user_message"`: `payload.message`. When that returns nothing — seen on `thread_source: "user"` Codex Desktop rollouts at `cli_version 0.149.0-alpha.4.1`, and on subagent rollouts — fall back to `response_item` messages with `payload.role=="user"`, text in `payload.content[0].text`. `role:"developer"` messages are injected boilerplate, not typed, and so is any fallback text that begins with a tag such as ``, ``, `` or ``. On a subagent rollout the fallback text is the parent agent's dispatch prompt, not your human partner's. | | Assistant text | `event_msg` `agent_message` (`payload.message`, `payload.phase`) or `response_item` `message` with `role:"assistant"`. | | Tool calls | `response_item` with `payload.type` `function_call` (`name`, `arguments`, `call_id`) or `custom_tool_call` (`name`, `input`, `call_id`); outputs are `function_call_output` / `custom_tool_call_output` matched by `call_id`. Also `event_msg` `patch_apply_end` (`success`, `changes`), `web_search_end`, `mcp_tool_call_end` (`invocation.server`, `invocation.tool`). | | Turn timing | `event_msg` `task_started` (`turn_id`, `started_at`, `model_context_window`) and `task_complete` (`duration_ms`, `time_to_first_token_ms`, `last_agent_message`); `turn_aborted` (`reason`, `duration_ms`). | @@ -55,6 +58,8 @@ With `jq`: head -1 "$F" | jq '.payload | {id, cwd, originator, cli_version, model_provider, thread_source, git}' # identity jq -r '.type + "/" + (.payload.type // "")' "$F" | sort | uniq -c # census jq -r 'select(.type=="event_msg" and .payload.type=="user_message") | "\(input_line_number)\t\(.timestamp)\t\(.payload.message[0:160])"' "$F" # human prompts +jq -r 'select(.type=="response_item" and .payload.type=="message" and .payload.role=="user") + | "\(input_line_number)\t\(.timestamp)\t\((.payload.content[0].text // "")[0:160])"' "$F" # human prompts, fallback when the line above returns nothing; skip rows whose text starts with a `` jq -r 'select(.type=="turn_context") | "\(.timestamp)\t\(.payload.model)\t\(.payload.effort)"' "$F" # model per turn jq -c 'select(.type=="response_item" and (.payload.type=="function_call" or .payload.type=="custom_tool_call")) | {line:input_line_number, name:.payload.name, args:((.payload.arguments // .payload.input)|tostring|.[0:120])}' "$F" # tool calls