Branch Eligibility Readback / 分支资格回读
Branch Eligibility Readback is the rite that opens when a material branch has become locked, suppressed, downgraded, or recovery-only and the player can still act on the reason.
The rite is not a tutorial, hint overlay, or debug screen. It is a desk readback: the producer asks the route table to name the missing live state before the branch disappears into clean absence.
Entry state
entry_state:
trigger_kind: state_pressure
source_option_set_present: true
candidate_branch_present: true
candidate_branch_material_to_future_play: true
eligibility_state_any:
- locked
- suppressed
- downgraded
- hidden_by_claimant
- recovery_only
- explicit_absence
blocking_surface_visible_or_explicit_absence: true
missing_or_contested_requirement_visible_or_explicit_absence: true
harmed_reader_if_silent_visible_or_explicit_absence: true
future_reader_or_route_consumes_lock_state: true
player_can_fulfill_assign_downgrade_publish_accept_suppress_or_default: true
no_fixed_turn_trigger: true
no_fixed_day_or_week_trigger: true
no_raw_choice_count_trigger: true
no_dashboard_or_lens_health_trigger: trueThe rite must fail if it opens because of chronology, chapter quota, raw branch count, generic tutorial prompt, dashboard state, or lens health.
Required assignment
The player may not resolve the readback until the receipt has concrete assignments.
assignment_required:
receipt: storyteller.card.branch_eligibility_receipt.v1
source_option_set_id: <choice set, rite, docket, or route surface>
candidate_branch_id: <branch id>
eligibility_state_before: locked | suppressed | downgraded | hidden_by_claimant | recovery_only | explicit_absence
blocking_surface: capacity | callback | notice | proof | carrier | handler | witness | sponsor | public | lawful | archive | route_asset | producer_license | management_compression | broadcast_reality | equivalent
blocking_row_id_or_absence: <row id or explicit_absence>
missing_requirement_or_absence: <requirement or explicit_absence>
contested_requirement_or_absence: <requirement or explicit_absence>
lock_beneficiary: <reader or actor>
harmed_reader_if_silent: <reader or actor>
proof_bridge_or_absence: <proof or explicit_absence>
future_reader: <reader route package proof window ending scar or explicit_absence>Exact nine-slot runtime assignment
| Slot | Accepted card |
|---|---|
receipt | storyteller.card.branch_eligibility_receipt.v1 |
source_option_set | storyteller.card.branch_eligibility_source_option_set.v1 |
candidate_branch | storyteller.card.branch_eligibility_candidate_branch.v1 |
blocker_row | storyteller.card.branch_eligibility_blocker_row.v1 |
missing_requirement | storyteller.card.branch_eligibility_missing_requirement.v1 |
lock_beneficiary | storyteller.card.branch_eligibility_lock_beneficiary.v1 |
harmed_reader | storyteller.card.branch_eligibility_harmed_reader.v1 |
proof_bridge | storyteller.card.branch_eligibility_proof_bridge.v1 |
future_reader | storyteller.card.branch_eligibility_future_reader.v1 |
All nine slots are required, exact-accept enforced, and backed by cards in the player’s hand. Resolution also requires a selected option. A generic any card, missing evidence, mismatched ID, or metadata-only assignment must fail. The additional receipt fields in the design assignment above are card rows, not additional runtime slots.
Branch families
| Branch | Relief | Cost | Future effect |
|---|---|---|---|
| Fulfill requirement | locked branch becomes selectable with cost | spends capacity, proof, carrier protection, bond, or public notice | branch_eligible_with_named_cost |
| Assign carrier | branch remains unavailable until a named carrier accepts burden | carrier leverage, capture risk, handler exhaustion | eligibility_carrier_required |
| Downgrade branch | lower-intensity option becomes playable | clean branch lost; harmed reader still named | downgraded_branch_only |
| Pay bond | temporary eligibility is restored | bond debt, sponsor pressure, producer-license pressure | eligibility_bond_required |
| Publish absence | lock reason becomes public/lawful/route-asset evidence | public confusion, sponsor retaliation, inspection heat | public_absence_receipt_required |
| Accept recovery-only | false clean branch is blocked | route narrows permanently | branch_recovery_only |
| Suppress lock | immediate pressure drops through recorded suppression | future challenge remains armed | suppressed_branch_challenge_armed |
| Default silent | prior silent disappearance is receipted | harmed reader and missing requirement harden against player | silent_branch_suppression_pending |
No branch may make the unavailable option cleanly irrelevant to every reader.
Exact branch/state/future mapping
| Stable branch ID | branch_eligibility.state.* | future_route.* |
|---|---|---|
fulfill_requirement | eligibility_restored_with_cost | branch_eligible_with_named_cost |
assign_carrier | carrier_assigned | eligibility_carrier_required |
downgrade_branch | branch_downgraded | downgraded_branch_only |
pay_bond | bond_posted | eligibility_bond_required |
publish_absence | absence_published | public_absence_receipt_required |
accept_recovery_only | recovery_only_accepted | branch_recovery_only |
suppress_lock | lock_suppressed | suppressed_branch_challenge_armed |
default_silent | silent_default_pending | silent_branch_suppression_pending |
Each option sets exactly one branch_eligibility.branch.<branch> flag, exactly one matching state flag, and exactly one matching future flag after clearing the other seven mappings. Every option records its exact state/future strings and durable counter deltas.
Only default_silent sets branch_eligibility.silent_default_pending, event.silent_branch_suppression.armed, future_route.silent_branch_suppression_pending, and broadcast_reality.branch_falsely_absent. All other branch outcomes clear that set. suppress_lock is therefore an exposed, challenge-armed local posture; it is not an alias for the silent default.
Default-only terminal handoff
storyteller.event.silent_branch_suppression.v1 is reachable only after default_silent. Its three option IDs and exclusive results are:
| Event option | State after | Future effect |
|---|---|---|
reconstruct_eligibility_receipt | eligibility_receipt_reconstruction_required | future_routes_require_eligibility_receipt |
publish_hidden_beneficiary | hidden_lock_beneficiary_exposed | public_or_lawful_challenge_required |
freeze_false_unavailable_route | false_unavailable_route_frozen | recovery_only_until_blocker_served |
Every terminal clears the four pending flags and the pending state. The target replay is lens/replays/branch-eligibility-receipts.replay.json; it resolves this rite with all nine real assignments through default_silent, then resolves reconstruct_eligibility_receipt. lens/storyteller-branch-eligibility-receipts.runtime.test.ts supplies exhaustive coverage for all eight branches and all three event terminals.
Successful rite resolution sets branch_eligibility.readback_resolved. Event resolution sets branch_eligibility.default_resolved and preserves branch_eligibility.silent_suppression_scar; neither flag is an extra branch, state, or future result.
Local authority boundary
Readback is a local eligibility disposition, not a judgment on the source branch’s truth or merit. It cannot fabricate that a branch was offered, automatically satisfy a named requirement, override claimant or proof custody, or grant consent, waiver, settlement, route clearance, archive release, proof truth, sponsor/fan/inspector/editor authority, or universal broadcast authority.
Branch payload
Every readback result must record:
readback_result:
selected_posture: fulfill_requirement | assign_carrier | downgrade_branch | pay_bond | publish_absence | accept_recovery_only | suppress_lock | default_silent
eligibility_state_after: eligibility_restored_with_cost | carrier_assigned | branch_downgraded | bond_posted | absence_published | recovery_only_accepted | lock_suppressed | silent_default_pending
recovery_surface_after_or_absence: <surface or explicit_absence>
harmed_reader_state_after: protected | delayed | hostile | excluded | public_counter | lawful_challenge | sponsor_capture | recovery_only | explicit_absence
lock_beneficiary_state_after: satisfied | pressured | exposed | captured | challenged | explicit_absence
future_route_effect: branch_eligible_with_named_cost | eligibility_carrier_required | downgraded_branch_only | eligibility_bond_required | public_absence_receipt_required | branch_recovery_only | suppressed_branch_challenge_armed | silent_branch_suppression_pending
counter_deltas:
relief: []
cost: []
future: []Failure contract
The rite fails if the implementation can:
- hide a material branch without a receipt;
- show a locked option with only generic text;
- unlock a branch without naming what state was changed;
- suppress a lock without future scar;
- treat missing proof, missing carrier, exhausted capacity, or claimant pressure as UI-only;
- use a fixed turn, fixed day/week, raw count, dashboard state, or lens-health state as the reason.