# Readiness gates and bounded bulk-decision review

Use during independent acceptance review when a preview exposes coverage/readiness metrics, grouped decisions, or a separate confirm endpoint.

## Server-side readiness probe

A disabled Confirm button is not a write gate. Trace the exact backend confirm path and verify that it rejects a fingerprint-bound preview whenever `business_ready_for_confirm` is false. Do not accept a check of a weaker technical field such as `confirmable` when the UI promises “confirmation remains locked.”

Review this without writing productive data:

1. Locate the computation of technical confirmability and business readiness.
2. Trace both fields into the public preview response and frontend state.
3. Inspect the backend confirm guard before the first transaction/write.
4. Require a focused synthetic regression where technical readiness is true, business readiness is false, and confirm is rejected with zero DB changes.

## Bounded grouped decisions

For every cluster/bulk decision, compare four sets:

- all rows the decision will mutate;
- rows disclosed to the user;
- rows the user can individually exclude;
- rows bound into the preview fingerprint.

The mutation set must be a subset of the disclosed and excludable set. A UI that shows `examples[:3]` but applies the category to every cluster member is a financial-correctness blocker, even when the displayed cluster count is accurate.

Use a synthetic preview-only counterprobe with more rows than the UI example cap. Record only aggregate results such as:

```text
cluster_count=5 displayed_examples=3 categorized_rows=5
```

Do not execute Confirm merely to prove this defect; the preview result and source trace are sufficient.

## Readiness-denominator integrity

Treat readiness arithmetic as a financial contract, not presentation metadata. Define a disjoint row partition before calculating coverage: ordinary monetary rows, safe transfer legs, explicit neutral user decisions, receipt details, duplicates, pending rows, and genuine ambiguity. Then require invariants that prove:

- every candidate belongs to exactly one partition;
- the coverage numerator is a subset of the declared ordinary-monetary denominator;
- receipt details and both legs of safe transfers are not double-counted as ordinary expenses;
- workflow artifacts that are already safely actionable do not inflate unresolved review;
- changing a label such as “ordinary” cannot silently remove hard cases from the denominator.

Add focused tests for the partition sums and boundary cases. In the private old/new report, publish the denominator, numerator, ratio, individual-review count/ratio, grouped-cluster count, and the exact failed threshold independently. If any target is missed, keep `business_ready_for_confirm=false`; do not reinterpret the metric or broaden rules merely to reach the number.

## Private iterative preview loop

For real financial sources, iterate only through owner-local, read-only previews:

1. Open the production database read-only or bracket the run with a logical/material digest.
2. Keep source files and aggregate reports outside Git; enforce mode `0600`.
3. First partition the backlog into repeated resolvable families, one-off insufficient-evidence rows, genuine ambiguity, and workflow artifacts.
4. Fix the largest safely resolvable families using active category IDs, controlled normalization, source/account semantics, and confirmed consistent history.
5. Rerun the exact same aggregate report and verify database/source digests are unchanged.
6. Stop adding automatic rules when the residual set requires private business meaning or a user category choice. Surface bounded group decisions and preserve an honest not-ready state instead of overclassifying.

An architecture/root-cause analysis against the base commit is advisory only. The release-gating review must inspect the actual final HEAD after all fixes. Do not treat a late-arriving base analysis as the final independent verdict.

## Detecting weakened acceptance tests

Diff tests as contracts, not only as executable files. Search specifically for tests that were renamed from a negative invariant to a positive opposite, for example:

- “history does not leak across sources” becoming “history reuses across sources”;
- “only receipts above threshold are linked” becoming “all receipts are linked.”

Reconcile each inversion against the version-bound inventory/ADR. A green replacement test does not authorize a product-contract change. For financial classification, source/account-role leakage is P0; a documented enrichment threshold mismatch is at least a release-blocking acceptance finding unless the governing contract was explicitly amended.

## Privacy scan for embedded business data

Do not limit the privacy review to added files. Scan changed product code and fixtures for exact employer, merchant, counterparty, account, or person-specific mappings. A hard-coded employer mapped to a named person’s salary category is private business context embedded in Git even when no raw CSV or database was added. Prefer generic public taxonomy plus private audited rule data.

## Evidence discipline

- Keep all probes synthetic and preview-only when productive Confirm is excluded.
- Prove preview non-persistence with a before/after logical DB dump or protected digest.
- Separate “the calculation returns false when targets are missed” from “the real private preview was independently reproduced.” If private sources are out of scope and no sanitized aggregate report exists, state that limitation rather than accessing them.
- Refresh exact HEAD and clean status after review because the verdict is snapshot-bound.
