Skip to content

Corroborate a nonempty window instead of assuming it complete - #313

Closed
lamemustafa wants to merge 1 commit into
claude/voucher-presencefrom
claude/presence-window-corroboration
Closed

lamemustafa wants to merge 1 commit into
claude/voucher-presencefrom
claude/presence-window-corroboration

Conversation

@lamemustafa

Copy link
Copy Markdown
Owner

Stacked on #294. Do not merge before it. Sibling of #308, which is also on #294 — both touch agent_presence.rs and agent_presence_tests.rs, so whichever lands second rebases.

This is offered for judgement, not as a finished answer. It addresses the open P1 on #294 ("Withhold Complete until source cardinality is proven"), and I do not claim it closes it — see What this does not establish below. It is a separate PR precisely so its cost can be weighed on its own rather than folded into a PR that is trying to land.

Outcome and reason

WindowRead::Complete is asserted for any nonempty response. That is not something a response can be inspected for: a silently short read returns rows that are all well-formed and all inside the window, and looks exactly like a full one. The voucher it omits reads as Absent — the one verdict in this engine that puts a duplicate in a client's book.

The range is now re-read a day wider, and the two reads are compared on Tally's own identities for rows falling inside the original window. A row the wider read saw and the narrow one did not proves the narrow read short. A row carrying no GUID cannot be compared and is refused rather than assumed equal. A row appearing between the two reads makes the window uncorroborated. All fail towards Partial, which BookWindow::observed already turns into WindowIncomplete.

Provenance

The design is not mine. It was found as uncommitted work in an unowned worktree, rescued to rescue/voucher-presence-wip-20260912 by the session holding the merge queue, and handed over unreviewed. I reviewed it rather than adopting it. What is mine here is two corrections, three simulator-plan updates, and the price.

Scope, reuse, and impact

  • Scope: one corroborating read on the nonempty path, its comparison, and the tests. Excluded: the empty path (already corroborated), any change to a read profile, and the observation-size fix from the same rescued worktree, which is already in Decide which proposed vouchers are already in the book #294.
  • Existing component reused: widened_window, validate_then_filter_voucher_rows, parse_agent_rows, row_in_window and post_read — the nonempty path is the empty path's counterpart and borrows its whole shape. No new request profile, no new XML.
  • What is deleted: the WindowRead::Complete assumption, and the let mut reason = None / conditional-assignment shape it needed.
  • What breaks if this is not built: a size-truncated window keeps producing Absent, and Absent authorises an import.
  • Net LOC change: production +119/−13, tests +86/−6.
  • Migration/rollback: revert the commit. No stored state, no schema change. Callers see state: "partial" and WindowIncomplete where they previously saw a verdict — that is the intended behaviour change and it fails closed.
  • Destructive database migration: No.
  • Security impact: no new credential path, no write. One additional read per nonempty presence call against the same qualified profile.

Validation and evidence

  • Exact candidate SHA: a1fc8ff5
  • Commands (macOS, pinned 1.96.0): cargo fmt --all -- --check clean; cargo clippy --locked --workspace --all-targets -- -D warnings clean; cargo test --locked --workspace 1351 passed, 0 failed; gate compatibility_gate_passed:unknown_claims=11:evidenced_claims=0, pin set read off the base at reseal — none added, none removed.
  • Live: the twenty-invoice replay on Decide which proposed vouchers are already in the book #294 still passes with this enabled — sixteen present, four absent, unchanged.

The price, measured

On a dense corpus against a licensed TallyPrime 7.1 Silver instance (education_mode: false):

read bytes
one-day window 895,888
its corroborating read 1,744,152
1.95×

One presence call goes from ~896 KB to ~2.6 MB of Tally traffic. max_bytes is bounded at 5,000,000, so this roughly halves the widest window the tool can serve before corroboration alone fails the call.

Wall-clock is deliberately not quoted. Across runs on this lab the same work varied between six and twenty-six seconds, which measures the lab rather than the change. I reported "6.5s against 6.3s" to a peer earlier today off two runs; that was under-supported and I am withdrawing it.

Two corrections to the rescued work

  1. It did not build. The simulator cycle pins the request count; the run makes 28 against the 24 asserted. Two further simulator plans needed the extra paired read.
  2. Its own comment mis-stated the cost it was pinning — "the two extra are the wider voucher read and its paired status probe". A corroborating read in this adapter is a paired read: company, payload, status, payload, status, company. Six requests, not two. The number and its reason now say what actually happens.

What this does not establish

It catches a read that fell short because of size — the case the finding describes. A wider read is denser, so it truncates at least as hard, and a row the narrow read has and the wider one lacks proves the narrow read short.

It does not catch a voucher that both reads omit for a reason unrelated to size, because two reads that agree prove only that they agree. And it is neither a source-side count nor a complete partitioning, which is what the finding actually asked for. It raises the bar. Whether it clears the one that was set is the reviewer's judgement, and I have not resolved that thread.

  • One completed review-checklist.md line is linked here: "New or changed commands validate inputs and surface user-safe errors." — the two new outcomes are window_short_read and window_identity_unreadable, both fixed strings carrying no book content, and both resolving to WindowIncomplete rather than a verdict. See agent_tests.rs::a_nonempty_window_is_corroborated_rather_than_assumed_complete.
  • Native Windows validation — not applicable: no platform-specific code, no path handling, no packaging change.
  • Native macOS validation — the commands above ran natively on macOS, and the live read against the lab ran from it.
  • Rectify issue — not a regression fix.

Checklist

  • Security implications reviewed
  • Migration compatibility and rollback impact documented
  • Error handling paths still return actionable errors
  • No leftover debug logs with sensitive values
  • No personal/customer data, certificate output, local usernames, or developer-specific absolute paths added

🤖 Generated with Claude Code

`WindowRead::Complete` was asserted for any nonempty response, and that is not
something a response can be inspected for: a silently short read returns rows
that are all well-formed and all inside the window, and looks exactly like a
full one. The voucher it omits then reads as `Absent` -- the one verdict in
this engine that puts a duplicate in a client's book.

So the range is re-read a day wider and the two reads are compared on Tally's
own identities for the rows falling inside the original window. A row the wider
read saw and the narrow one did not means the narrow read was short. A row
carrying no `GUID` cannot be compared at all and is refused rather than assumed
equal, and a row appearing between the two reads makes the window
uncorroborated rather than absent. All of those fail towards `Partial`, which
`BookWindow::observed` turns into `WindowIncomplete`.

**The design is not mine.** It was rescued from an unowned worktree and is
reviewed here rather than adopted: two corrections and a price.

It did not build. The simulator cycle pins the request count and the run makes
twenty-eight against the twenty-four asserted -- and the comment justifying
that number said "the two extra are the wider voucher read and its paired
status probe", when a corroborating read in this adapter is a *paired* read of
six requests. The cost being pinned had been mis-estimated threefold. Two other
simulator plans needed the extra read as well.

**The price, measured against a live licensed 7.1 Silver book.** A one-day
window on a dense corpus reads 895,888 bytes; its corroborating read of the
same range widened a day either side reads 1,744,152 -- **1.95x** -- taking one
presence call from ~896 KB to ~2.6 MB of Tally traffic. `max_bytes` is bounded
at 5,000,000, so this roughly halves the widest window the tool can serve
before corroboration alone fails the call. Wall-clock is not quoted: across
runs on this lab it varied between six and twenty-six seconds for the same
work, which is not a measurement of anything.

The twenty-invoice replay still passes with it enabled -- sixteen present, four
absent, unchanged.

**What it establishes, and what it does not.** It catches a read that fell
short because of *size*, which is the case the finding describes: a wider read
is denser, so it truncates at least as hard, and a row the narrow read has and
the wider one lacks proves the narrow read short. It does **not** catch a
voucher both reads omit for a reason unrelated to size, and it is neither a
source-side count nor a complete partitioning. It raises the bar; whether it
clears the one the reviewer set is the reviewer's judgement, not mine.

Pin set read off the base branch at reseal: none added, none removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-11T23:35:06.356202Z a1fc8ff PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1fc8ff510

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src-tauri/src/agent.rs
Comment thread src-tauri/src/agent_vouchers.rs
@lamemustafa

Copy link
Copy Markdown
Owner Author

Closing this without merging. It does not do the thing it was built to do, and the two open findings on it are both correct.

It cannot establish completeness, and ADR 0017 says why in a sentence I wrote before building it. A deterministic short answer agrees with itself across a pair. If the boundary days this adds happen to be empty, both reads drop the same suffix, the identity multisets match, and agreement becomes indistinguishable from correctness. The mechanism converts some false Completes into Partial and licenses none — a detector offered against a finding that asks for a prover.

It is expensive. Measured on a licensed TallyPrime 7.1 Silver book: a one-day window reads 895,888 bytes, its widened corroboration reads 1,744,152 — 1.95× — taking one presence call from ~896 KB to ~2.6 MB. Against a max_bytes bounded at 5,000,000 that roughly halves the widest window the tool can serve before the corroboration alone fails the call.

And the widening introduces a hazard of its own. On Education-mode Tally an accepted boundary can widen into a date Tally silently reinterprets as the whole book, so a mechanism added to make a verdict safer would either reject a valid request or compare evidence from the wrong period.

A detector with that price and that hazard is not worth shipping for the cases it does catch.

What survives, and where

9cc3b0a9 on #294 writes the reasoning into the section of ADR 0017 it concerns: that a widened re-read was built and measured, what it detects, why agreement cannot license Complete, the 1.95× figure, and the Education-mode hazard. The next attempt starts past this rather than at it.

The source-side control total remains the only thing that would close the finding, and it is still a separate read contract needing its own live evidence. #294's corresponding P1 stays open — this PR does not narrow it.

Provenance

The design was not mine. It was rescued from an unowned worktree, and what I added was two corrections, three simulator-plan updates and the price. Closing it is not a judgement on the person who wrote it — the idea was worth trying, and the reason it fails is only visible once you measure it and re-read the ADR.

The branch claude/presence-window-corroboration is left in place so the work is recoverable if someone revives it with boundary-safe widening and a different view of the cost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant