Add Codex-owned in-process Token Miser - #16
Open
Harold Hunt (huntharo) wants to merge 2 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
[features.code_mode.token_miser]codex exectools.read_token_miser_outputandtools.search_token_miser_outputturn.completed.usageJSON eventArchitecture and threat model
Activation is explicit:
The raw terminal result is admitted once as an opaque
token_miser_outputrollout item and flushed before Luna or a receipt runs. It retains the structuredFunctionCallOutputContentItemvalues exactly. The in-memory rollout representation usesArc<TokenMiserOutput>, and the wire serializer borrows that payload, avoiding a second deep clone for admission or serialization.Admission is capped at 1,024 content items and 8 MiB across variable metadata and content sources. The 8 MiB cap is
codex_code_mode::host::MAX_FRAME_BYTES / 8, derived from the host's authoritative 64 MiB serialized IPC-frame limit; the factor of eight covers worst-case JSON escaping before disk persistence. Injected/future providers receive the same lower bound. Outputs beyond it are withheld without autonomous chunking or unbounded allocation by Token Miser.Raw records and decision records are excluded from model context, app-server thread history, forked history, rollout search/metadata projections, and ordinary exec JSON events. Legacy rollouts remain readable. Resume restores the opaque catalog directly from the owning thread store; a raw record lacking a committed decision is retained but never reduced a second time.
Object IDs are UUIDv4 values. Lookup also requires the current session's internal
ThreadId; authorization is not carried by the model-visible ID alone. Reads are capped at 8 KiB withnext_offset; searches cap the query at 256 bytes, results at 20, snippets at 512 bytes, and the complete serialized result at 8 KiB. Failed lookup/search does not authorize terminal passthrough.Direct terminal results are persisted and reduced immediately. Yielded cells expose only bounded actionable running state; the exact terminal result is reduced once when
waitcompletes. Terminal resolution runs in a detached Tokio task so parent cancellation cannot discard a result or its usage. Per-cell persistence and decisionOnceCellvalues make terminal delivery, replay, acceptance, and accounting idempotent.Luna runs through
run_codex_thread_one_shot, which is available in the core session used by one-shotcodex exec; it does not require app-server or ACP. The child omits parent user/developer instructions and history, uses custom reducer instructions, disables Code Mode, shell, apps, plugins, collaboration, MCP, web search, image access, planning, and user-input tools, and sends an empty tools array.The entire raw-bearing
ContextualUserFragment, including markers, is capped at 896 UTF-8 bytes. Deterministic head/tail selection omits the middle and never starts an autonomous summarization loop. Because a byte contributes at most one tokenizer token, the complete framed item stays below the repository's 1K-token manual-review threshold and far below the 10K hard limit, including token-dense Unicode and control bytes.Two explicit model-visible surfaces can exceed 1K tokens and therefore need P0/manual context review: a requested retrieval result is at most 8 KiB plus fixed framing, and a Luna replacement is at most 8 KiB plus fixed fences. Both remain below the 10K-token hard cap; ordinary receipts are fixed, short, and actionable.
Luna may select exact passthrough, a bounded replacement, or hide. Reducer startup, timeout, malformed output, and persistence failures do not fail the outer tool/turn; execution continues while raw content remains withheld behind a neutral receipt. This is operationally fail-open and content fail-closed.
Usage and Harbor
The Luna child's complete provider
TokenUsageis stored on the decision and added exactly once to the root absolute token total. Input, cached input, cache-write input, output, reasoning output, total tokens, and rollout budget units are preserved where represented. The decision and resulting absoluteTokenCountare persisted as one ordered batch before the standard root event is delivered.codex exec --jsonnow includestotal_tokensalongside the existing detailed fields on its standard rootturn.completed.usageevent. The core integration tests prove Luna usage is included once in the root total; the subprocess test proves the Harbor-shaped CLI stdout and persisted rollout carry that authoritative total. Child-only events are not required.Harbor's external rollout-to-ATIF adapter is outside this repository. It must map the standard root
turn.completed.usageevent fields:total_tokensinput_tokenscached_input_tokenscache_write_input_tokensoutput_tokensreasoning_output_tokensNo synthetic "tokens saved" telemetry is added.
Compatibility
Test evidence
Focused Token Miser suite:
just test -p codex-core token_miser: 14 passed, 3961 skippedimmediate_replacement_takes_precedence_over_managed_reducer_without_reasoning_leakage— direct terminal replacement, no narration/reasoning/raw leak, resume retrieval, exact root usagedirect_small_large_passthrough_and_failure_outputs_remain_exact— small/large output, passthrough, replacement/receipt, malformed reducer result, exact persistenceyielded_exec_is_reduced_once_only_after_terminal_wait— yielded actionable state and terminalwaitparallel_terminals_have_unique_objects_and_exact_once_usage— parallel calls, unique objects, exact-once usagecancellation_does_not_drop_or_repeat_reducer_accounting— parent cancellation and durable completion/accountingreducer_input_is_hard_bounded_and_omits_the_middle_of_large_text— 896-byte complete frame, dense Unicode/control data, deterministic head/tailretrieval_is_exact_bounded_and_thread_scoped— scoped read/search, continuations, adversarial escaped snippetsrestored_decision_is_reused_without_an_uncommitted_cell— resume/replay idempotencerestored_raw_output_without_a_decision_is_not_reduced_again— crash-window fail-closed replaystructured_output_storage_bound_rejects_adversarial_oversize_without_serializing— item/source bounds and 64 MiB upstream relationshipfork_filters_token_miser_internal_objects_in_every_history_mode— fork denialin_process_token_miser_precedence_tracks_runtime_config_refreshes— managed/external precedenceload_config_resolves_explicit_nested_token_miser_settings— activation syntax/default/clampingtoken_miser_requires_explicit_enabled_true— disabled compatibilityjust test -p codex-history token_miser: 1 passed, 14 skippedtoken_miser_output_round_trips_exact_structured_content_without_clone_amplification— exact text/image/encrypted semantics andArcidentityjust test -p codex-app-server-protocol token_miser: 1 passed, 297 skippedtoken_miser_records_are_not_admitted_to_thread_history— rollout-to-history exclusionjust test -p codex-thread-store token_miser: 1 passed, 235 skippedexact_token_miser_output_is_retained_but_excluded_from_model_context— persistence plus model-context exclusionjust test -p codex-exec harbor_shaped: 2 passed, 150 skippedharbor_shaped_root_turn_completed_usage_includes_all_token_miser_cost_once— exact root JSON usage shapeharbor_shaped_exec_json_and_rollout_preserve_authoritative_usage— real subprocess stdout event set and persisted rollout total; internal rollout records are not stdout conversational itemsFull changed-package suites:
codex-features: 40/40codex-history: 15/15codex-rollout: 126/126codex-state: 188/188codex-app-server-protocol: 297/297, 1 skippedcodex-exec: 152/152, 1 slowcodex-external-agent-migration: 168/168codex-memories-write: 43/43codex-thread-store: 236/236Generation and hygiene:
just write-config-schema: passjust write-app-server-schema: passjust fix -p ...for all changed crates: passjust fmt: passThe full
codex-corepackage suite was attempted once and was not usable as a green signal in this checkout: 3950 run; 3724 passed (2 slow, 17 flaky, 1 leaky), 222 failed, 4 timed out, 24 skipped. Failures were dominated by unavailable shared test infrastructure (target/debug/test_stdio_server), wiremock panics, realtime handshake timeouts, Code Mode host startup, and MCP lifecycle deadlines. The focused Token Miser suite subsequently passed 14/14. It was not rerun, and the workspace-wide suite was not run, per operator instruction.The standalone Code Mode host build is also blocked on this Apple Silicon checkout because the published
v8 150.4.0build script receives HTTP 404 forlibrusty_v8_ptrcomp_sandbox_release_aarch64-apple-darwin.a.gz. Core integration coverage uses the injectable session provider and exercises the same parent/reducer lifecycle without app-server or ACP.