Repository navigation
fix(purchase): carry the no_submission proof to the root of an all-refused fan-out - #1881
Conversation
The fan-out tests for carrying the no_submission proof to the root row need accounts that behave differently: a credential failure, a row-save failure, a provider factory failure and a refused account followed by a cancelled run. The fixture keys each hook by account ID and runs two accounts through executeMultiAccount. A table-driven smoke test, one case per hook, asserts only today's per-account rows and the returned error. Part of #1844 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…fused fan-out When no account of a multi-account run committed and every account was refused before submission, never started, or finished with nothing bought, the root error now carries the before-submission class, so the root row is stamped no_submission and releases its suppressions. The decision reads the in-memory per-account results, not saved rows. A failed account-row save strips the class so a lost audit row never counts as proof. Part of #1844 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 8 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
APPROVE @ 16284b5 by claude-nibblets Adversarial review of #1881 (Part of #1844, S0 and S1, +413/-5, money path). It matters beyond the fan-out: since #1870, a root stamped Read (internal/purchase/refusal_tally.go, execution.go): `fanOutNotSubmitted` runs only when no account committed and reads the in-memory per-account results, not saved rows. It returns true only if the result list is non-empty and every account either bought nothing without error (the nothing-selected case of #339), was refused before submission (`refusedBeforeSubmission`: the class and not `ErrOutcomeUnknown`), or never started (no entry in `started`, so the run context ended first). Any panic, plain error from an account that started, unknown outcome, or bought rec keeps today's unproven failure. A failed account-row save re-joins the cause as text (`errors.New(cause.Error())`), so a lost audit row cannot carry the class into the proof, and `failedPurchasesError` only wraps when `allRefused`. The root error keeps its `%w` chain (`errAllAccountsFailed`). `skippedAccountNote` now uses `RetryRefusalReason`, matching #1870. Scoped probes (go test -run FanOut|Refusal|RootProof|Tally|MultiAccount|Skipped|Fan in internal/purchase, scratch worktree at this head, baseline ok), each killed: committed account ignored (TestFanOutNotSubmitted_GuardsAreSafeOnTheirOwn); a started account with a plain error counted as unsent (TestExecuteMultiAccount_RootProof, _FanOutFixtureHooks); empty results counted as unsent (_GuardsAreSafeOnTheirOwn); root not wrapped (TestExecuteMultiAccount_AllRefusedRedshiftRootIsNeverSubmitted and two more); lost audit row keeping the class (TestExecuteMultiAccount_RootProof); unknown outcome counted as refused (TestExecuteMultiAccount_RootProof, TestMultiAccount_MixedOutcomesAreNotNoSubmission; my first run of this one did not compile and was redone); an account that bought nothing without error blocking the proof (_GuardsAreSafeOnTheirOwn). Residual trust, not new here: an account that ends with no purchased rec and no error is read as "bought nothing"; that is the existing #339 meaning of `committed == false` and I did not audit every way a provider call could return without recording an error. The S2 credential and pin failures are a follow-up, as the PR says. CI at this head: Lint Code and Integration Tests (purchase) pass; Unit Tests and others were still running (26 pass, 11 pending). |
|
CHANGES REQUESTED 16284b5 by claude-nibblets I am withdrawing my APPROVE at this head. I posted it while Unit Tests was still pending; it has since failed (run 42670342582, CI Success fails as a result), and the failure is in this PR's own new test file. Failure:
Fix: take the mock into a local first (for example Everything else in my earlier review stands (the analysis of |
… assertions The mock assertion guard cannot check a call on a nested selector, so the root proof test copies the store into a local before asserting on it. Part of #1844 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
APPROVE @ 51810d2 by claude-nibblets Delta 16284b5..51810d2 is test-only: one commit in internal/purchase/fanout_root_proof_test.go (+3/-2) that takes the mock into a local ( CI at this head: Unit Tests, Lint Code and Run pre-commit hooks pass (12 pass, 3 pending, 2 skipping when I looked). My CHANGES REQUESTED at 16284b5 is superseded by this approval. |
Summary
no_submissionand releases its suppressions. The decision reads the in-memory per-account results (fanOutNotSubmitted), not saved rows, so a panicked or lost-row account never reads as "nothing submitted".Verification
Success=false, mixed) through the realexecuteMultiAccount.started, drop ther.Valueguard, drop the empty-results guard, drop the nil-error branch, drop the class strip, drop the wrap, count refused as started) are each killed by a test. Unit and golangci-lint pass locally on macOS; CI covers Linux and the integration suites.execution_id, so a root's release never touches another attempt's rows.Part of #1844
🤖 Generated with Claude Code