fix(store): record which agent a decline was made for - #774
Merged
Conversation
passthrough_events carried the command, the bytes and the reason, and no agent, so the table could say what OMNI handed back and never what share of it was handed back to a model rather than to a shell. The obvious proxy is wrong, and this repository's own data disproves it: host output cap only fires for claude_code, so every one of its rows is a hook row, and 20 of its 39 carry no session id. An empty session is not a door test. This is what makes #608 unsizeable. Its case rests on 12.33 MB of structured payload with no downstream reader, and only the part that entered a model's context was ever the ledger's to take. Today that share is somewhere between 337 KB and 12.33 MB, and nothing in the store can narrow it. Old rows read unknown. The door cannot be recovered after the fact, so any query about the split windows itself, which is the same rule the reason column already needs. Closes #773
…test did not Break-testing found it: blanking the agent at the post_tool call sites left the first test green, because it passed the agent to record_passthrough by hand. The column is only worth having if the hook writes it. Driven through process_payload now. Third toothless test this session, all three found by the break step rather than by review.
…s shape Greptile on #774. Codex sends a Claude-Code-shaped payload, which is why stats_agent_id exists and why distillation already books under it. The decline sites were using normalized.agent_id, so a Codex decline would have been filed under Claude Code: a column added for attribution, attributing wrongly. The test gained the arm that catches it, in Codex's own payload shape.
Break-testing it showed the arm stays green when the decline sites go back to the payload's own id, and the reason is worth writing down rather than papering over: for a Codex-shaped payload both ids agree. They diverge when a Claude-Code-shaped payload arrives under an environment naming another host, which is resolve_agent_id's own rule and needs a process-wide variable no test here may set. The rule is tested on the pure function where it can be. The arm holds the weaker property, and now says so.
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.
passthrough_eventsrecorded the command, the byte count and the reason, and no agent, soOMNI could say what it handed back and never what share of it was handed back to a model
rather than to a shell. The ledger and the distillers exist to serve one of those two.
The obvious proxy is wrong, and this repository's own data disproves it.
host output capfires only whenagent_id == "claude_code"(post_tool.rs:366), so every one of itsrows is a hook row, and 20 of its 39 carry no session id. An empty session is not a
door test.
What that was costing. #608 proposes changing the format-safety gate on the strength of
structured payload with no downstream reader. Re-measured today that pool is 12.33 MB over
576 calls, and splitting it by session id gives 11.99 MB with none against 0.34 MB with
one. If the session-less rows are pipe, the proposal is 36 times smaller than it reads. If
they are not, it is not. Nothing in the store could tell, so a gate change was queued
behind a number nobody could attribute, which is #760's shape exactly.
agent_idis written fromnormalized.agent_idon the hook path and from the resolvedagent on the pipe path, the same value
distillationsalready stores.passthrough_bytes_by_agent(days)reports the split. Rows written before the column readunknownrather than being backfilled: the door cannot be recovered after the fact, andguessing it is inventing the number this exists to stop inventing.
The first test I wrote was toothless, and the break step found it. It called
record_passthroughwith the agent passed in by hand, so blanking the agent at everypost_toolcall site left it green. The test runs throughprocess_payloadnow, and thesame break is red:
That is the third test this session that passed for the wrong reason and was caught by
breaking it rather than by reading it.
Verification:
make cigreen,smoke_test.sh70/70.Closes #773
Greptile Summary
The PR adds durable agent attribution to passthrough events and exposes per-agent byte aggregation.
agent_idcolumn whose legacy rows remainunknown.Confidence Score: 5/5
The PR appears safe to merge.
No blocking failure remains; the previously reported decline-attribution defect is fixed across the current hook recording paths.
Important Files Changed
Reviews (2): Last reviewed commit: "test(hooks): say what the Codex arm does..." | Re-trigger Greptile
Context used (3)