{
  "shell.native_background": {
    "score": 1,
    "evidence": "codex-rs/core/src/tools/handlers/shell_spec.rs:96-113 registers exec_command as 'Runs a command in a PTY, returning output or a session ID for ongoing interaction.' codex-rs/core/src/unified_exec/process_manager.rs:673-716 returns response_process_id for a process still alive after the yield window."
  },
  "shell.timeout_cap": {
    "score": 0.5,
    "evidence": "Partial: codex-rs/core/src/tools/handlers/shell_spec.rs:30-39 exposes only yield_time_ms (default 10000 ms, effective 250-30000 ms), and codex-rs/core/src/unified_exec/mod.rs:73-77/210-217 enforces that range. There is no model-settable command kill timeout in the interactive exec_command schema; timeout_ms exists only in the one-shot spec used when unified exec is policy-disabled (codex-rs/core/src/tools/handlers/unified_exec/exec_command.rs:291-298,455-472)."
  },
  "shell.persistent": {
    "score": 1,
    "evidence": "codex-rs/core/src/unified_exec/mod.rs:149-160 keeps a ProcessStore keyed by process id; codex-rs/core/src/tools/handlers/unified_exec/write_stdin.rs:81-100 reattaches to that session, and codex-rs/core/src/unified_exec/process_manager.rs:804-895 looks it up and continues it. cwd/env live in the surviving PTY."
  },
  "shell.powershell": {
    "score": 1,
    "evidence": "codex-rs/core/src/shell.rs:26-40 builds PowerShell argv (-NoProfile, -Command) and codex-rs/core/src/shell.rs:60-69 maps environment shell name 'powershell'. codex-rs/shell-command/src/shell_detect.rs:6-10,39-47 recognizes pwsh/powershell, and codex-rs/core/src/tools/handlers/shell_spec.rs:339-345 includes Windows/PowerShell-specific guidance."
  },
  "shell.middle_out": {
    "score": 1,
    "evidence": "codex-rs/core/src/unified_exec/head_tail_buffer.rs:5-19 allocates the output cap 50/50 to a stable head and tail; :45-124 retains both and inserts an omission marker between them. codex-rs/utils/output-truncation/src/lib.rs:14-31 also uses truncate_middle_chars/truncate_middle_with_token_budget for the model-facing truncation."
  },
  "shell.full_log": {
    "score": 0,
    "evidence": "Searched core/src/tools and core/src/unified_exec for output_path/log_path/full_output_path/'written to' and found no writer. codex-rs/core/src/tools/context.rs:346-359 shows ExecCommandToolOutput carries raw_output, truncation policy, original_token_count, and output_omitted_bytes, but no file path; retained output is capped at codex-rs/core/src/unified_exec/mod.rs:80."
  },
  "shell.omitted_counts": {
    "score": 0.5,
    "evidence": "Partial: codex-rs/core/src/unified_exec/mod.rs:223-225 formats the exact marker '... N bytes omitted ...', and codex-rs/core/src/unified_exec/head_tail_buffer.rs:104-124 places it between head and tail. It reports the count but gives no recovery path or command, so the second half of the definition is missing."
  },
  "shell.signal_honesty": {
    "score": 1,
    "evidence": "codex-rs/utils/pty/src/process.rs:35-45 converts a Unix signal death to 128 + signal (so SIGKILL=137, SIGTERM=143); codex-rs/core/src/exec.rs:67,996,1038 use the same convention. codex-rs/core/src/tools/context.rs:490-505 reports the exit code as 'Process exited with code N' rather than a success stub."
  },
  "shell.benign_exit": {
    "score": 0,
    "evidence": "Searched core/src for benign/expected-exit handling and found none. codex-rs/core/src/tools/context.rs:490-505 always renders 'Process exited with code N' with no special case for grep 1, diff 1, or test-runner 1."
  },
  "shell.untrusted_fencing": {
    "score": 0,
    "evidence": "Exec output is returned as raw InputText at codex-rs/core/src/tools/context.rs:379-388. The only 'untrusted evidence' fencing found by grep is for node_repl/cua_repl in codex-rs/core/src/context/node_repl_review_evidence.rs:311; no delimiters or inert-data wrapper exists for process output."
  },
  "shell.bg_output_reader": {
    "score": 1,
    "evidence": "codex-rs/core/src/tools/handlers/shell_spec.rs:115-145 defines write_stdin with session_id and an empty chars poll; codex-rs/core/src/unified_exec/process_manager.rs:925-1005 collects and returns buffered output for that poll."
  },
  "shell.wait_modes": {
    "score": 0.5,
    "evidence": "Partial: return-now is yield_time_ms (codex-rs/core/src/tools/handlers/shell_spec.rs:30-39) and wait-for-output is the empty write_stdin poll (codex-rs/core/src/unified_exec/process_manager.rs:925-1005). There is no exit-only wait mode: codex-rs/core/src/tools/handlers/unified_exec/write_stdin.rs:22-32 has only session_id/chars/yield_time_ms/max_output_tokens, and the poll returns on either new output or exit."
  },
  "shell.cursor_reads": {
    "score": 0.5,
    "evidence": "Partial: codex-rs/core/src/unified_exec/process_manager.rs:1474 uses std::mem::take on the shared output buffer, so write_stdin returns only newly accumulated bytes and does not replay old bytes. But there is no byte-offset/cursor parameter (codex-rs/core/src/tools/handlers/unified_exec/write_stdin.rs:22-32), and the 1 MiB retained cap at codex-rs/core/src/unified_exec/mod.rs:80 can drop bytes the model can never seek back to."
  },
  "shell.list_tasks": {
    "score": 0,
    "evidence": "codex-rs/core/src/tools/spec_plan.rs:1111-1112 registers only exec_command and write_stdin for shell execution. No list/ps/tasks handler exists among the tool names in codex-rs/core/src/tools/handlers (grep of ToolName::plain yields apply_patch, exec_command, view_image, write_stdin, agent/MCP utilities only)."
  },
  "shell.kill_id": {
    "score": 0,
    "evidence": "codex-rs/core/src/tools/handlers/unified_exec/write_stdin.rs:22-32 accepts only session_id, chars, yield_time_ms, and max_output_tokens. Ctrl-C input is written as the raw 0x03 character at codex-rs/core/src/unified_exec/process_manager.rs:103,901, but there is no kill/cancel-by-id tool."
  },
  "shell.kill_pid_port": {
    "score": 0,
    "evidence": "No exec handler accepts a pid or listening port; codex-rs/core/src/tools/spec_plan.rs:1111-1112 exposes only exec_command and write_stdin, and grep for kill/stop/ps tool names in codex-rs/core/src/tools/handlers found none."
  },
  "shell.sigterm_escalation": {
    "score": 0.5,
    "evidence": "Partial: codex-rs/core/src/exec.rs:1000-1030 sends SIGTERM to the original process group, waits CANCELLATION_TERMINATION_GRACE_PERIOD=50 ms (codex-rs/core/src/exec.rs:69), then SIGKILLs. The default unified-exec path does not use it: terminate() at codex-rs/core/src/unified_exec/process.rs:227-236 goes straight to the PTY kill at codex-rs/utils/pty/src/pipe.rs:60-78. So escalation exists but not on the default exec_command kill path."
  },
  "shell.group_kill": {
    "score": 1,
    "evidence": "codex-rs/utils/pty/src/process_group.rs:1-11 documents that each spawned child is put into its own process group; :150-167 rejects pgid <= 0 before killpg. codex-rs/utils/pty/src/pipe.rs:161-163 spawns with setsid/setpgid, and :217 records that spawned group id, which is the only group signalled."
  },
  "shell.monitor": {
    "score": 0,
    "evidence": "Searched for a runtime wake path and found only UI event emitters: codex-rs/core/src/unified_exec/async_watcher.rs:52-72 starts ExecCommandOutputDelta streaming and :168-216 emits ExecCommandEnd on exit. Neither injects a model turn or tool result; the model must call write_stdin to observe progress."
  },
  "shell.sleep": {
    "score": 0.5,
    "evidence": "Partial: codex-rs/core/src/tools/handlers/sleep.rs:44-60 defines clock.sleep and :110-141 returns early on new input activity. Registration is not default: codex-rs/core/src/tools/spec_plan.rs:1201-1226 requires CurrentTimeReminder (default false, codex-rs/features/src/lib.rs:1542-1545) or a model advertising clock, and the bundled models carry empty experimental_supported_tools (e.g. codex-rs/models-manager/models.json:88,219,687)."
  },
  "shell.cron": {
    "score": 0,
    "evidence": "grep -ri 'cron|scheduled prompt' over codex-rs/core/src and codex-rs/ext returned no matches. No durable scheduler tool is registered in codex-rs/core/src/tools/spec_plan.rs:1086-1265."
  },
  "shell.bg_subagents": {
    "score": 1,
    "evidence": "codex-rs/core/src/tools/spec_plan.rs:1342-1358 registers spawn_agent, send_input, resume_agent, wait_agent, and close_agent when multi_agent is on (stable and default-true at codex-rs/features/src/lib.rs:1206-1209). Spawn returns while the child thread runs (codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs:203-224), and wait_agent blocks for activity up to timeout_ms (codex-rs/core/src/tools/handlers/multi_agents_v2/wait.rs:86-122)."
  },
  "shell.safe_classification": {
    "score": 0,
    "evidence": "The policy engine is a token-prefix allowlist, not AST classification: codex-rs/execpolicy/README.md:5-7 and codex-rs/execpolicy/src/rule.rs:211-231 implement PrefixRule matching. Shell parsing exists only to canonicalize wrappers for approval-cache keys (codex-rs/core/src/command_canonicalization.rs:11-40); grep for is_safe/command_safety found no classifier."
  },
  "shell.workspace_boundary": {
    "score": 0.5,
    "evidence": "Partial: the default workspace-write profile grants Root read but only project-roots write (codex-rs/protocol/src/permissions.rs:753-765), so writes outside the workspace fail in the sandbox and require the model-settable require_escalated approval (codex-rs/core/src/tools/handlers/shell_spec.rs:232-265). Reads outside the workspace are explicitly allowed by the Root-read entry and are not detected or gated."
  },
  "read.line_window": {
    "score": 0,
    "evidence": "There is no dedicated file-read tool. codex-rs/core/src/tools/spec_plan.rs:1086-1265 registers exec_command, write_stdin, apply_patch, view_image, and control tools only; grep for read_file found only the plugin-backed notes namespace in codex-rs/core/src/tools/handlers/extension_tools.rs:85. Shell output has a 1 MiB byte cap (codex-rs/core/src/unified_exec/mod.rs:80), not a default line window."
  },
  "read.second_ceiling": {
    "score": 0,
    "evidence": "No read tool exists (codex-rs/core/src/tools/spec_plan.rs:1086-1265). The only related ceiling is a token/byte cap on shell output, codex-rs/core/src/unified_exec/mod.rs:79-81 and codex-rs/core/src/tools/handlers/shell_spec.rs:58-62; that is not a second byte budget on a line-windowed file read."
  },
  "read.per_line_clamp": {
    "score": 0,
    "evidence": "No read tool exists, and shell truncation is whole-output head/tail rather than per-line clamping: codex-rs/core/src/unified_exec/head_tail_buffer.rs:5-19,45-124 truncates the byte stream, not individual long lines."
  },
  "read.line_prefixes": {
    "score": 0,
    "evidence": "No read tool exists (codex-rs/core/src/tools/spec_plan.rs:1086-1265). Shell output is returned as raw bytes/text at codex-rs/core/src/tools/context.rs:379-388 with no 1-indexed line prefixes."
  },
  "read.resume_offset": {
    "score": 0,
    "evidence": "No read tool exists. The only truncation note is the byte marker at codex-rs/core/src/unified_exec/mod.rs:223-225 ('... N bytes omitted ...'), which names no next offset or resume command."
  },
  "read.empty_file_note": {
    "score": 0,
    "evidence": "No read tool exists. view_image only handles decodable images and errors on everything else at codex-rs/core/src/tools/handlers/view_image.rs:184-186, and shell cat output has no empty-file-vs-broken distinction."
  },
  "read.eof_note": {
    "score": 0,
    "evidence": "No read tool and no offset parameter exists: the shell tools expose cmd/workdir/yield_time_ms/max_output_tokens (codex-rs/core/src/tools/handlers/shell_spec.rs:40-62) and write_stdin exposes session_id/chars/yield_time_ms/max_output_tokens (codex-rs/core/src/tools/handlers/unified_exec/write_stdin.rs:22-32). There is nowhere to express offset-past-EOF."
  },
  "read.streaming": {
    "score": 0,
    "evidence": "No file-read tool. Shell PTY output streams into an in-memory capped HeadTailBuffer (codex-rs/core/src/unified_exec/process.rs:75-100, codex-rs/core/src/unified_exec/head_tail_buffer.rs:5-19), but there is no streaming, memory-capped file reader."
  },
  "read.deferred_chunk": {
    "score": 0,
    "evidence": "No read tool exists, so there is no deferred chunk-boundary truncation. The only 'more remains' signal is the after-the-fact omitted-byte marker at codex-rs/core/src/unified_exec/mod.rs:223-225."
  },
  "read.dedup": {
    "score": 0,
    "evidence": "No read tool exists (codex-rs/core/src/tools/spec_plan.rs:1086-1265). grep for dedup in core/src/tools found only network-approval dedup and tool-list dedup, not a read-result stub cache; apply_patch.rs has no read cache either."
  },
  "read.ledger": {
    "score": 0,
    "evidence": "No read tool and no read-before-write ledger. codex-rs/core/src/tools/handlers/apply_patch.rs:1-220 and codex-rs/core/src/apply_patch.rs contain no record of what the model has previously read."
  },
  "read.partial_ledger": {
    "score": 0,
    "evidence": "No read tool, and apply_patch has no partial-view tracking or destructive-overwrite refusal based on prior reads: codex-rs/core/src/tools/handlers/apply_patch.rs:1-220."
  },
  "read.did_you_mean": {
    "score": 0,
    "evidence": "No read tool exists; grep -ri 'did_you_mean|did you mean' over codex-rs/core/src returned no path-suggestion logic in the tool layer."
  },
  "read.unicode_retry": {
    "score": 0,
    "evidence": "No read tool exists; grep for unicode normalization/retry in codex-rs/core/src/tools found none. Path handling in view_image resolves the supplied path directly (codex-rs/core/src/tools/handlers/view_image.rs:150-186)."
  },
  "read.confusables": {
    "score": 0,
    "evidence": "No read tool exists; grep -i 'confusable|zero.width|bidi' over codex-rs/core/src/tools and codex-rs/core/src/context found no content disclosure for zero-width or bidi characters."
  },
  "read.image_vision": {
    "score": 1,
    "evidence": "codex-rs/core/src/tools/handlers/view_image.rs:101-105 requires image input modality, and :184-198 decodes the file and returns an image_url content item. The ViewImage feature is stable and default-true at codex-rs/features/src/lib.rs:890-895, and it is registered at codex-rs/core/src/tools/spec_plan.rs:1259-1261."
  },
  "read.coord_scale": {
    "score": 0.5,
    "evidence": "Partial and off by default: when enabled, codex-rs/core/src/context/image_resize_notice.rs:56-72 discloses 'resized from WxH to WxH pixels' using source_width/source_height/prepared_width/prepared_height (codex-rs/core/src/image_preparation.rs:300-315), which gives the exact mapping. The notice is gated by Feature::ImageResizeNotice, whose default_enabled is false at codex-rs/features/src/lib.rs:1410-1414; codex-rs/core/src/session/mod.rs:3124-3136 only enables it when that flag is on."
  },
  "read.magic_bytes": {
    "score": 1,
    "evidence": "codex-rs/core/src/tools/handlers/view_image.rs:184-186 calls image::load_from_memory on the file bytes and rejects anything that is not a decodable image, independent of the filename extension. The returned data URL is fixed to application/octet-stream at :198, so the media type is not taken from the extension."
  },
  "read.notebooks": {
    "score": 0,
    "evidence": "grep -ri 'ipynb|notebook' over codex-rs returned no notebook renderer; no .ipynb handling exists in codex-rs/core/src/tools or codex-rs/core/src/context."
  },
  "read.docx": {
    "score": 0,
    "evidence": "grep -ri 'docx' over codex-rs found only plugin artifact-format metadata at codex-rs/core-plugins/src/artifact_operation.rs:29-35, not a document reader. There is no docx-to-markdown path in the tool layer."
  },
  "read.pptx": {
    "score": 0,
    "evidence": "grep -ri 'pptx' over codex-rs found only plugin artifact-format metadata at codex-rs/core-plugins/src/artifact_operation.rs:23-30. No slide or speaker-notes reader exists."
  },
  "read.xlsx": {
    "score": 0,
    "evidence": "grep -ri 'xlsx' over codex-rs found only plugin artifact-format metadata at codex-rs/core-plugins/src/artifact_operation.rs:37-41. No worksheet-to-table renderer is registered as a tool."
  },
  "read.odf": {
    "score": 0,
    "evidence": "grep -ri 'odt|ods|odp|opendocument' over codex-rs returned no matches. No ODF reader exists."
  },
  "read.rtf_epub": {
    "score": 0,
    "evidence": "grep -ri 'rtf|epub' over codex-rs returned no matches. No RTF or EPUB reader exists."
  },
  "read.pdf_text": {
    "score": 0,
    "evidence": "grep -ri 'pdf' over codex-rs found only plugin artifact metadata at codex-rs/core-plugins/src/artifact_operation.rs:44-47 and unrelated identifiers; no PDF text extractor is registered."
  },
  "read.scanned_pdf": {
    "score": 0,
    "evidence": "No PDF reader exists at all, so there is no scan detection or rendering command. The only PDF references are artifact-format markers at codex-rs/core-plugins/src/artifact_operation.rs:44-47."
  },
  "read.docs_windowed": {
    "score": 0,
    "evidence": "No document reader exists (no docx/pptx/xlsx/odf/rtf/epub/pdf handling in codex-rs), so document text cannot honour a line window."
  },
  "read.docs_bulk": {
    "score": 0,
    "evidence": "No document reader and no bulk-read tool: codex-rs/core/src/tools/spec_plan.rs:1086-1265 registers no file/document read handler."
  },
  "read.converter_on_demand": {
    "score": 0,
    "evidence": "No converter exists to fetch on first use; grep for docx/pptx/xlsx/odf/pdf in codex-rs found only plugin artifact-format metadata (codex-rs/core-plugins/src/artifact_operation.rs:23-47), not a converter invocation."
  },
  "read.many_files": {
    "score": 0,
    "evidence": "No bulk-read handler exists. codex-rs/core/src/tools/spec_plan.rs:1086-1265 registers no read tool, and the handler tool-name list contains only exec_command, write_stdin, apply_patch, view_image, MCP resource, and agent/control tools."
  },
  "read.globs": {
    "score": 0,
    "evidence": "No read tool exists, and no read handler expands globs. Shell globbing happens only because a command is passed to a shell at codex-rs/core/src/tools/handlers/unified_exec/exec_command.rs:268-277; that is command execution, not a read-tool feature."
  },
  "read.per_file_range": {
    "score": 0,
    "evidence": "No bulk read exists, so there is no per-entry line range. The only shell range control is the model composing sed/awk itself."
  },
  "read.exclusions_gitignore": {
    "score": 0,
    "evidence": "No read/glob tool is registered (codex-rs/core/src/tools/spec_plan.rs:1086-1265). codex-rs/file-search has search code for the UI, but grep of spec_plan shows it is not exposed as a model tool; no gitignore-aware read exists."
  },
  "read.aggregate_cap": {
    "score": 0,
    "evidence": "No bulk-read handler exists (codex-rs/core/src/tools/spec_plan.rs:1086-1265), so there is no aggregate budget across matched files."
  },
  "read.aliased_input": {
    "score": 0,
    "evidence": "No read tool exists. Argument parsing for the shell tools is strict Deserialize (codex-rs/core/src/tools/handlers/unified_exec/write_stdin.rs:22-32, shell_spec.rs:40-62); no file-path alias repair is implemented."
  },
  "read.negative_offset": {
    "score": 0,
    "evidence": "No read tool exists, and neither shell tool has an offset field: codex-rs/core/src/tools/handlers/unified_exec/write_stdin.rs:22-32 and codex-rs/core/src/tools/handlers/shell_spec.rs:40-62 are the complete input schemas."
  },
  "read.device_blocklist": {
    "score": 0,
    "evidence": "No read tool and no device-path blocklist. view_image resolves the supplied path and reads it at codex-rs/core/src/tools/handlers/view_image.rs:150-186 before attempting image decode, with no character-device check."
  }
}
