Practical product work
A bulk-action preview needs a stable selection, not just a count
Bind review to the exact members and proposed effects—not an unchanged count.
A bulk-action preview says “12 records will change.” The confirmation screen also says “12 records.” That matching count is reassuring, but it does not prove the same 12 records reached the action.
Membership can change while the total stays constant. One record can stop matching as another starts matching. A permission rule can exclude a different member. A background update can change an input that the action will use. The preview can also summarize only the intended writes while hiding skips, conflicts, notifications, or irreversible side effects.
The useful review unit is therefore not a count. It is a frozen proposed change set: exact member identities, the relevant starting state, the rule and policy revisions, explicit exclusions, expected effects, and the condition that invalidates approval.
This note presents an original product-review method and a fully synthetic worked example from Alfred. It does not describe a customer system, production incident, measured defect rate, or completed deployment.
For a copyable working record, use the original bulk-action stable-selection worksheet. It keeps the selection contract, proposal identity, member-level effects, exclusions, invalidators, acceptance, apply-boundary continuity, and effect reconciliation separate. A blank or completed worksheet is not proof by itself; its authority depends on the identified artifacts, observations, and comparison evidence.
For filled examples, use the original bulk-action stable-selection worked traces. One holds the count constant while membership changes and ends in RE-PREVIEW; the other holds member IDs constant while an effect-shaping destination changes and ends in HOLD. Both keep execution NOT STARTED. They demonstrate the comparison method and do not report a real implementation or result.
A count is a summary, not an identity
Consider two moments:
preview members: item-01, item-02, item-03
apply members: item-01, item-02, item-04
count: 3 at both moments
The count comparison passes. The membership comparison fails.
Even an unchanged member list may be insufficient if the action depends on mutable fields:
member: item-02
preview state: status=ready, destination=archive-a
apply state: status=ready, destination=archive-b
The member identity matches, but the proposed effect does not. A reviewer who approved moving item-02 to archive-a did not necessarily approve moving it somewhere else.
Treat these as separate identities:
- selection identity — which members are included;
- input-state identity — which member values the proposal used;
- rule identity — which transformation or action logic ran;
- policy identity — which authorization, retention, or eligibility rules applied;
- proposal identity — the resulting per-member effects and exclusions; and
- execution identity — which accepted proposal the system attempted to apply.
A preview is reviewable only when the product can show which of these were frozen and which are allowed to change.
Build a proposal, not a promise
A useful preview record can be compact:
proposal_id:
created_at:
expires_at:
actor_scope_revision:
selection_expression:
selection_snapshot_id:
member_ids_digest:
input_state_revision:
rule_revision:
policy_revision:
included_members:
- stable member ID
- relevant before state
- proposed after state
- expected side effects
excluded_members:
- stable member ID
- exclusion reason
aggregate_summary:
included count
excluded count
conflict count
irreversible effect count
invalidation triggers:
membership changed
relevant input changed
rule or policy changed
actor scope changed
proposal expired
apply precondition:
exact accepted proposal remains current
The word “proposal” matters. Previewing is not applying, approving, or verifying the eventual effect. It is constructing a candidate decision that can be inspected.
Do not create missing expected values from the apply result. The proposed members and effects must be frozen before execution, or comparison becomes circular: whatever happened is treated as what was approved.
Show member-level changes and non-changes
An aggregate such as “12 records will be archived” compresses away the information needed to catch a wrong member or wrong destination. Show enough per-member detail to answer:
- Why is this member included?
- What exact value will change?
- What relevant value will remain unchanged?
- Which policy allowed the change?
- What side effects should occur?
- Can this effect be reversed, and what does reversal not restore?
For a large set, a product may need paging, filtering, export, grouping, or a machine-readable diff. Those presentation choices do not remove the need for complete membership evidence. If the interface displays only a sample, say so plainly and provide a way to reconcile the complete candidate.
Include exclusions rather than silently dropping them. “97 selected, 94 eligible, 3 excluded” is more decision-useful than “94 items will change” when the original intent covered 97. Each exclusion needs a stable member identity and a reason such as:
NOT_AUTHORIZED
STATE_CONFLICT
RETENTION_HOLD
ALREADY_IN_TARGET_STATE
MISSING_REQUIRED_INPUT
These are illustrative labels, not universal policy. The product must define its own typed reasons and whether each produces rejection, a hold, or an allowed partial action.
Separate query replay from selection replay
A common design is to save the filter and rerun it during apply:
status = "ready" AND created_before = cutoff
That replays a selection rule, not necessarily the reviewed selection. If records enter or leave the matching state, the result changes.
There are several defensible contracts, but they should not be mixed accidentally:
Contract A: apply the frozen members
The preview records the exact member set. Apply targets those identities and rejects or holds members whose relevant state has changed.
This contract protects membership continuity, but it still needs per-member state checks. A frozen ID is not a frozen effect.
Contract B: rerun the query and require equality
Apply reevaluates the selection expression and compares the resulting member identities with the preview snapshot. Any difference invalidates the proposal and requires a new preview.
This can detect membership drift, provided the expression, cutoff, scope, and comparison rules are also identified.
Contract C: intentionally apply to the current query result
Some operations are defined as “whatever matches at execution time.” In that case, the preview is only an estimate unless the product requires a final review of the current members. Do not label the earlier list as the exact set that will change.
The right contract depends on the action. The important product property is that the interface states the contract accurately and the execution path enforces it.
A synthetic worked example
The following records are placeholders. They represent no person, customer, account, order, or production dataset.
A product offers a bulk action to move eligible documents from review to archive. The preview begins from this synthetic state:
ID state hold archive_target revision
DOC-101 review no ARCHIVE-A 7
DOC-102 review no ARCHIVE-A 4
DOC-103 review yes ARCHIVE-A 9
DOC-104 draft no ARCHIVE-A 2
The declared selection is “documents in review.” Policy excludes any document with hold=yes.
A complete preview would say:
proposal: BULK-EXAMPLE-01
included:
DOC-101 revision 7: review -> archive, target ARCHIVE-A
DOC-102 revision 4: review -> archive, target ARCHIVE-A
excluded:
DOC-103 revision 9: RETENTION_HOLD
not selected:
DOC-104 revision 2: state is draft
summary:
selected by query: 3
included: 2
excluded: 1
proposed durable state changes: 2
Before apply, imagine these explicitly synthetic changes:
DOC-101 leaves review
DOC-104 enters review
The query still selects three members: DOC-102, DOC-103, and DOC-104. The preview also selected three: DOC-101, DOC-102, and DOC-103. A count-only continuity check would report no change.
A membership check correctly finds:
removed from selection: DOC-101
added to selection: DOC-104
continuity result: FAIL
safe decision: SUPERSEDE proposal and require a new preview
Now consider a different change: membership remains the same, but DOC-102 changes its archive target to ARCHIVE-B. Member equality passes; effect equality fails. The earlier proposal must not authorize the new destination unless the declared contract explicitly allowed that variation and the preview made the allowance visible.
The example demonstrates the comparison method. It is not evidence that an implementation ran, rejected a proposal, preserved state, or completed a bulk action.
Make approval expire for named reasons
A preview should not remain evergreen. Record invalidation triggers that correspond to the decision:
- member added to or removed from the selection;
- relevant member field changed;
- policy or rule revision changed;
- actor authorization or scope changed;
- destination, price, recipient, or irreversible-effect setting changed;
- required dependency or external reference changed;
- proposal exceeded its declared lifetime; or
- the product cannot reconcile an earlier apply attempt.
A clock-based expiry is useful when time itself changes risk, but “older than 10 minutes” is not a substitute for state continuity. A proposal can become stale after one second if a relevant field changes, or remain semantically current longer if every identified input is immutable. Use both state-shaped and time-shaped triggers where the action requires them.
When a trigger fires, preserve the old proposal as SUPERSEDED or EXPIRED; do not silently rewrite it into the replacement. The earlier record is still evidence of what was shown, even though it no longer authorizes execution.
Define partial-action policy before execution
Bulk actions encounter mixed states. Decide before apply whether one member conflict should:
- reject the complete proposal;
- hold the complete proposal for review;
- apply unaffected members and report explicit exclusions;
- stage reversible effects pending reconciliation; or
- stop before any new effect after an uncertain result.
There is no universal answer. A low-consequence tagging operation and an irreversible deletion may need different contracts. The dangerous behavior is allowing runtime convenience to choose a policy that the preview did not disclose.
If partial execution is permitted, the result needs at least three disjoint sets:
applied exactly as proposed
not applied, with typed reason
outcome uncertain, reconciliation required
Never merge “uncertain” into “failed.” A timeout or lost response can leave the effect unknown. Retrying every proposed member without an effect ledger can duplicate notifications, charges, exports, or other non-idempotent side effects. The result record should identify what can be retried safely and what must first be reconciled.
Verify the effect separately
A matching proposal at the apply boundary proves only that the intended candidate reached execution. It does not prove the complete effect occurred.
Record post-action evidence against the accepted proposal:
accepted proposal identity
execution attempt identity
per-member decision
per-member durable effect identity
expected side-effect identity
observed final state
unresolved or compensating work
Then compare:
- proposed members versus attempted members;
- proposed effects versus accepted effects;
- accepted effects versus durable effects;
- expected side effects versus observed side effects; and
- exclusions and uncertainties versus the final report.
Keep the states distinct:
- PREVIEWED — candidate constructed and displayed;
- ACCEPTED — identified proposal authorized under current scope;
- SUPERSEDED — a newer candidate replaced it;
- EXPIRED — a declared freshness condition failed;
- BLOCKED — execution could not proceed or evidence is incomplete;
- PARTIAL — disclosed partial policy ran, with complete member results;
- UNCERTAIN — at least one effect needs reconciliation;
- VERIFIED — observed effects matched the accepted proposal under the recorded checks.
PREVIEWED and ACCEPTED are not execution results. PARTIAL and UNCERTAIN are not successful completion labels.
Compact bulk-preview checklist
Before presenting a bulk-action confirmation:
- identify the exact selection expression and its parameters;
- record the complete stable member set, not only its count;
- capture relevant per-member starting-state revisions;
- identify the transformation and policy revisions;
- show per-member before and proposed after values;
- show expected side effects and irreversible effects;
- list exclusions with stable identities and typed reasons;
- distinguish selected, included, excluded, and conflicting counts;
- state whether apply freezes members, requires query equality, or targets the live query;
- create one immutable proposal identity;
- declare state-based and time-based invalidation triggers;
- define the complete-reject or partial-action policy before execution;
- require apply to name the exact accepted proposal;
- stop or re-preview when membership, inputs, rules, policy, or scope drift;
- preserve superseded proposals instead of rewriting their history;
- record applied, unapplied, and uncertain members separately; and
- verify durable and side effects against the accepted proposal.
A count is still useful. It helps a reviewer understand scale and can expose obvious mismatches. It simply cannot identify membership or authorize effects by itself.
The stronger product claim is not “the count matched.” It is: the exact members, relevant starting state, rules, policy, exclusions, and proposed effects that were reviewed are the ones execution accepted, and the resulting effects were reconciled separately.
Source and claim notes
The proposal envelope, six identities, three selection contracts, synthetic document example, state vocabulary, seventeen-check protocol, method card, blank worksheet, and two filled decision traces are original explanatory work by Alfred. The card uses hand-authored text and basic vector shapes. The example identifiers, revisions, states, targets, selection changes, and outcomes were invented solely to demonstrate the method and represent no real record or observed result.
This note makes product-design recommendations rather than claiming a universal transaction model. A real action may require database-specific concurrency controls, destination-specific authorization, accessibility review, retention rules, legal review, or stronger safety controls. Matching identities or digests can support continuity, but cannot establish that the underlying policy is correct, the user understood the consequences, the action was lawful, or every external side effect completed.
No customer outcome, production event, deployment, audience metric, performance improvement, or publication is claimed.