Repository navigation
Conversation
roborev: Combined Review (
|
|
fancy! |
3666802 to
0a4ed41
Compare
roborev: Combined Review (
|
roborev: Combined Review (
|
531f536 to
d86e574
Compare
roborev: Combined Review (
|
roborev: Combined Review (
|
This comment has been minimized.
This comment has been minimized.
roborev: Combined Review (
|
roborev: Combined Review (
|
f661d2a to
14367cc
Compare
roborev: Combined Review (
|
80e18ce to
ae98abd
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
roborev: Combined Review (
|
4535b4a to
933aee2
Compare
roborev: Combined Review (
|
roborev: Combined Review (
|
This comment has been minimized.
This comment has been minimized.
cc1a39e to
798468c
Compare
This comment has been minimized.
This comment has been minimized.
roborev: Combined Review (
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
09ea292 to
0eeb45c
Compare
roborev: Combined Review (
|
0eeb45c to
8c42170
Compare
…irror Two gaps after a mirror file is lost, both found in review: - A refetched mirror with new messages but no token records replaced the archived chat, dropping its usage events, token totals, and capture coverage. Sync now imports the new messages and copies those from the archive, plus the plan usage row when the rebuilt file has none. Turns that ran while the mirror was missing are not counted as uncaptured. - A plan usage or live-token write that rebuilt a lost mirror reset the resume point but did not queue the chat. An idle, finished chat with an unchanged listing was never fetched again, so its mirror stayed metadata-only. The write now marks the chat to check again; the mark clears once a pass finds nothing new. The saved-copy log line now says "local copy" and names what replaces it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The goal read ran after the last 5-minute recency check, and a call can take up to 2 minutes. A chat updated just under 5 minutes ago could pass the check, then get resumed after the window closed, which is the cold resume the window exists to prevent. The recheck now runs after the goal reply, right before the resume. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The opt-in edits left long lines in three docs the format hook skips. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A read-only probe sent thread/goal/get for the newest chats on a real
login. Both returned {"goal": null}, so the goal check before a resume
reaches a method the hosted server supports.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…an figures Review found four gaps after a mirror file is lost: - A rebuilt file with no plan records parses as "plan usage not checked yet", and that empty row replaced the chat's saved plan figures. A chat with only plan usage lost them the same way. The archived figures now stay until newer plan usage arrives. - The rule that kept the whole saved chat when a refetch had the same messages and no token counts also dropped newer plan usage from the rebuilt file. The token carry-over already keeps the counts, so the rule is gone and the write goes through. - After the first new live record, peak context came only from the records left in the file. The larger of the archived and new peak now stays when the archived row is current. - A hosted hub projecting raw captures had none of these rules, so a rebuilt file uploaded before its history was refetched replaced the hub's transcript and usage. The rules now live in internal/ingest/codex_cloud_history.go. Sync calls them with the archive's session, usage events, and plan row; the hub calls them with the previous raw projection, which counts as current at the same processing version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ial loss Review found more ways a damaged mirror could drop saved usage: - A file cut short after its newest token record still parses with token counts, just fewer, so it replaced the saved events and totals. Records only accumulate, so a parse whose output total is below a current saved copy now keeps the saved counts. - A rebuilt file holding only a plan usage outcome, such as "left out", replaced the saved report figures. The saved figures now stay under the new outcome, as the parser does for a whole file. "Counted under" still clears them. - The check-again mark for a rebuilt mirror lived only in the caller's account state until the caller saved it, after the rebuilt file and its offset were already saved. A crash or a later failure lost it. The mark is now saved first on every path. - The 5-minute join check now runs before the goal read as well as before the resume, so a stale chat gets no goal read. The sync log lines say where the counts come from. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A turn that shows no progress for a day is marked stalled, and a stalled chat is fetched again only when its listing changes. When a live-token or plan usage write found the mirror file of such a chat missing, it marked the chat to check again but left the stall mark in place. Selection skips check-again chats that are stalled, so the rebuilt file held only the listing and the usage record until the chat happened to change on the server, and sync kept the archived copy the whole time. The write now clears the stall mark along with setting the check-again mark, in the saved account state and in the caller's copy, as a pass already does before it commits a thread. If the turn still shows no progress, the next pass marks it stalled again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A mirror file can lose its newest frames and still hold older token and plan usage records. The carry rules caught this only when the output total came out smaller. A cut after a record that added only input or cache tokens left the output total unchanged, so the parse replaced the saved token counts with fewer usage events. A cut after the newer of two plan reports left an older report in the file, and the parse replaced the saved, newer figures with it. A current saved copy now also wins when the parse holds only some of its usage events. The check matches events by their dedup key, because a file rebuilt after a loss starts a new running total under new keys; a plain event count would keep the saved counts after every rebuild and never take the new total. For plan usage, a parse whose report is older than the saved one keeps the saved figures. Two copies share no file, so the check compares report and outcome times where the parser compares places in the file. A parse's outcome still applies when it is newer than both the saved report and the saved outcome. The hub now records that the previous projection contributed when it keeps the saved transcript or carries anything from it, as other providers already do, so the provenance rows say where the data came from. The log lines now name the mirror file and the saved copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The refused-join lease test ended by turning the server's draining flag back off and checking that a second join succeeds. The server only ever turns that flag on, at shutdown, so the step tested a path production cannot take. The rest of the test already shows that the refused join holds no lease and closes its connection. The direct test of the plan usage date formatter repeated the year case that the new-year usage pass test already covers through a full pass, which also checks that no new request goes out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… is lost A sub-agent chat counts toward the chat that started it, and plan usage asks OpenAI about the parent with the child listed as a descendant. A parent counted as known only while its mirror file existed. If that file went missing and the child then changed, the child became its own root: the usage step asked about the child alone and wrote that report to the child's file. When the parent's file came back, the child was already in the parent's descendants list, so no new "counted under" record was written. The child kept its own figures for good, and the parent's report counted it again. A thread with saved state now stays known while its mirror file is missing. Only a fetch's commit creates that state, so a thread that was never mirrored still waits as before. A plan usage write to the parent during the gap takes the existing lost-mirror path, which rebuilds the file and fetches the parent's history again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…me report When plan usage settles a chat, it writes the newest report again marked final, with the same report time, and can add a left_out outcome after it. A file cut short before those records still holds the first copy of the report. The previous rule kept the saved figures only when the saved report was strictly newer, so at equal times the parse won, and sync and the hosted hub dropped the final mark and the outcome. Session details then showed the figures as still open and lost the left_out warning. At equal report times the parse now keeps the final mark of either copy and the newer outcome. Equal times also cover a whole file that has just gained its final copy, so the parse's own mark still applies. The rule reports the saved copy as contributing only when it changed the row; otherwise every resync of a settled chat would log a carry and mark the hub's provenance row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84fbde6 to
0a435f1
Compare
The usage step writes left_out when OpenAI's answer leaves a chat out. A later answer can bring the chat back with the same report time, when OpenAI has not refreshed its figures. Its row follows the outcome in the mirror file, so the parse correctly shows no outcome. The equal-time rule added for cut files took any newer saved outcome, so sync and the hub put the stale left_out warning back on every resync of an intact file. The saved outcome now returns at equal times only when the saved copy is final and the parse is not. That is the pair settling writes: the report again marked final, then its outcome. A file cut after a left_out written while the chat was still pending loses the warning until the next usage answer; telling that apart from a repeated report would need the time each row was written, which the archive does not keep. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The equal-totals test checked that a second connection's record with the same running total as the first connection's still counts after a drop. The baselines test already runs that sequence and checks every event it produces, so the extra test could not fail on its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
roborev: Combined Review (
|
Three rounds of rules tried to keep newer saved plan figures when a mirror file was cut short after a newer report. Each rule compared the report times OpenAI sends, and each round found an intact file the rule overrode: an answer that repeats a report time after a left_out outcome, a chat that resumes after settling before OpenAI refreshes its figures, and an outcome-only parse taking an outcome older than the saved report. Report times repeat across answers, so they cannot tell a cut file from a whole one, and the cost of guessing wrong landed on ordinary resyncs. A parse that has a plan report now keeps its own figures. A file cut short after a newer report shows the older one until the next usage answer replaces it. Files lose whole records only through outside damage, so that window is rare and closes on its own. The rules that do not depend on report times stay: a file with no plan records keeps the saved figures, and the token counts still use the event-key check. An outcome-only parse keeps the saved figures and takes its outcome only when that outcome is newer than the saved report, as the parser does for a whole file. The sync log line for a carry now names no cause, since a carry can come from token counts, peak context, or plan figures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…build When account.json is lost, AgentsView rebuilds the plan usage queue from the thread files. A thread with saved state now counts as known even without its mirror file, so the rebuild can reach a root whose mirror file is also missing. If that root's newest plan record was final or an outcome, the rebuild read the mirror file to place it, failed to open it, logged an error, and left the root out until its chat changed. A missing mirror file now reads as holding no plan records. The root goes back to pending, and its next plan usage write takes the lost-mirror path, which rebuilds the file and fetches the history. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both the pass's own commit and the lost-mirror write mark a thread to check again, and both must clear its stall mark, because selection skips stalled threads. Each kept its own copy of that rule, so a change to one could miss the other and leave a stalled chat that never gets fetched again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
Live capture never joins a sub-agent chat, so every Codex cloud sub-agent has no token records and no capture coverage row. The combined usage of a chat and its sub-agents added coverage only from rows that exist. A captured parent with a finished sub-agent therefore reported zero missed turns and complete totals, while the sub-agent's tokens were missing from them. Once the combined result has coverage, from the parent or any sub-agent, each Codex cloud sub-agent without a coverage row now adds its user messages as missed turns. One user message stands for one turn, so the count is close, but the "partly captured" warning is what the reader needs. Giving tokenless chats parser coverage would be exact, but it would change how every tokenless chat counts in the plan usage totals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n home A status message for a signed-out home tells the user to run `codex login`. The message printed the plain command for the first Codex home the daemon reads, on the assumption that it is ~/.codex. A daemon started with its own CODEX_HOME reads that home first, so the user was told to run a plain `codex login` in a terminal that signs in ~/.codex, and imports stayed paused. The plain command now appears only for ~/.codex itself. Every other home, the daemon's own CODEX_HOME included, gets the command that sets CODEX_HOME for the login. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The second parse read the same file with fresh parser state and checked the same value, so it could fail only when the first check already had. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
roborev: Combined Review (
|
For a mirror file that holds a plan usage outcome but no report, the carry kept the saved report figures and took the new outcome only when the outcome's time was later than the saved report's data_as_of. The outcome's time comes from the local clock and data_as_of from OpenAI's, so a local clock running behind dropped a real new outcome, such as account_unavailable written just after a fresh report. The check only served a file cut short after an older outcome, a case the carry no longer tries to recover. The outcome now always applies over the saved figures, as before. A file cut after an older outcome shows it until the next usage answer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
The plan-only flags test seeds a Codex cloud sub-agent with no coverage row. Combined usage now counts such a sub-agent's user messages as missed turns, so the combined path reports the root's two missed turns plus the sub-agent's two. The per-session path still reports two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Home discovery cleans each path, which turns /srv/codex into \srv\codex on Windows, so the test's literal path never matched there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hub computed a session's signals in Finalize, then carried saved token counts and peak context onto a parse of a rebuilt mirror. The context signals read the peak, so a rebuilt mirror with new messages but no token records was stored as having no context data, which also feeds the health score. Sync carries before it computes signals and was not affected. The hub now derives the signals again whenever the carry changed the session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When account.json is lost, AgentsView rebuilds what to fetch again from the thread files. A chat whose mirror file went missing too was marked only if it had changed recently. An idle chat's listing never changes, so its history waited for its next change, which might never come. The rebuild now marks any chat whose mirror file is missing to check again. A file that is still there but damaged is left to the pass that next selects the chat, so one damaged file does not pause imports for the whole account on every rebuild. The design doc also names a known limit: a mirror rebuilt after a token counter reset starts below the saved total, and the archive cannot tell a new counter from a continuation of the old one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
roborev: Combined Review (
|
TL;DR
ChatGPT dot, Codex web, and Codex cloud task chats live only on OpenAI's servers, so AgentsView never showed them or their cost. A new opt-in
codex-cloudsource imports them with a local Codex home's ChatGPT login, listens in on running chats to record token usage, and uses OpenAI's plan usage report for chats it did not hear.Users get these chats as searchable sessions, with their cost in usage totals where AgentsView has token counts.
How
sources/codex-cloud/, and parses it like any other provider.live_tokens = true.session_plan_usagetable. The DuckDB mirror rebuilds once. Session export moves to schema 7, wheremodel_usageisnullwhen token counts are unknown. Artifact folder sync writes plan usage and capture coverage into a v7 manifest, only for sessions that have them.agentsview serve statusshow each account's import, live tokens, and plan usage state, with a next step for every failure.Fragile parts and tradeoffs
thread/resumerequest, and the usage report. When OpenAI changes a reply shape, import or capture for that account stops with "OpenAI's service answered in a way this version of AgentsView can't read". Imported sessions stay. Expect a follow-up release each time OpenAI changes one.auth.jsononly. A home that keeps its login in the system keyring needscli_auth_credentials_store = "file", which leaves the token in a plain file, and the status names that cost when it suggests the setting. AgentsView accepts endpoint overrides only for OpenAI hosts and loopback, and neither client follows redirects.Reviewer notes
internal/codexcloud/monitor.go. Plan usage scheduling and settling live inusage_step.go. Import and status text live inpass.goandstatus.go. The parser isinternal/parser/codex_cloud*.go. The rules that keep a saved chat after its mirror file is lost live ininternal/ingest/codex_cloud_history.go, shared by sync and the hosted hub.SELECTonsession_plan_usage. Consumers ofagentsview export sessionsmust accept anullmodel_usage. Artifact importers must be upgraded to read v7 manifests; older ones hold them.docs/internal/codex-cloud-source.mdexplains how sync, live capture, and plan usage work, what was rejected, and which probes are still open.internal/zstdframe, so DeepSeek parsing goes through new code.🤖 Generated with Claude Code