Skip to content

Stage 6b: estates (death guild, vehicles, replay guard, upkeep pause) - #163

Merged
ryanbarlow97 merged 7 commits into
mainfrom
stage6b/estates
Oct 13, 2026
Merged

ryanbarlow97 merged 7 commits into
mainfrom
stage6b/estates

Conversation

@ryanbarlow97

@ryanbarlow97 ryanbarlow97 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Stage 6b (estates and wills) for SimpleFactions 4.2.0, on the TLibs 2.6.0 estate API. SimpleFactions answers which guild a character died in, hands dead owners' personal vehicles to the estate recipient, stops its death journal from acting on a revived or re-dead character, and pauses upkeep while vehicles wait for an estate. Design: stage 6b v2.3, rules E10 and E12, the SimpleFactions participant section and review items M1, M5, M11, N2, N3 and P2–P4.

Death realm. Death capture records a new optional journal field, lockGuildRealm: the incarnation of the death guild's realm's ruling guild, taken from the same ungated lookup and civil-war mapping as lockGuildIncarnation (a moved rebel follows its origin guild in the host realm). Journal validation accepts it and closedBy.

Replay guard. Before an incomplete journal replays, the character is read. If it is still DEAD with that death ID, the journal replays as before. If it is ALIVE, or dead with another death ID, the journal is closed: remaining steps are marked done unapplied, complete=true and closedBy: revive|redeath. Claims whose cleanup step never applied are cancelled in the same durable write by setting paid = cents, because their wage bucket and dividend eligibility were never cleared, so nothing is paid twice. An unreadable or MISSING character is skipped for now (staff decide MISSING characters). Older jars read a closed journal as complete and its cancelled claims as paid, and their Gson ignores the new fields. A succession step never displaces a living seat holder but still fills a blank seat.

EstateFallback, registered once factions start (before SimpleFactionsReadyEvent):

  • deathGuild(character, deathId): UNAVAILABLE while SimpleFactions is not ready or a referenced death has no journal yet; NONE for a guildless death; otherwise the death guild with its live state, current leader (Guild.getLeader(), the realm's for a ruling guild) and the realm recorded at death. For older journals the realm comes from the one stored rights plan that lists the guild; snapshot() is never re-run.
  • guild(incarnation) and guildByName(name): UNAVAILABLE, GONE, or LIVE with the treasury guild:<incarnation> and the realm as its ruling guild's incarnation. guildByName also accepts an incarnation; a name two guilds share answers UNAVAILABLE.
  • No lookup creates a guild. The reference scan behind UNAVAILABLE no longer creates a realm's main guild either.

Vehicles participant simplefactions-vehicles, registered at the end of the vehicle stage. It finds vehicles by personal payer row or VehicleFramework owner, writes vehicles/estates/<deathId>.json durably before the first change, then moves the payer row (payments.personal), the owner (VehicleOwnerWrites.write(HANDOVER)) and the last owner (fee store's durable save) as separate durable steps. The estate gate checks a known type, not faction-owned, payments ready and not blocked, and not VehicleQuarantine.held. There is no fee, slot or battle-lock check. Replay follows the observed row and tag:

Observed Action
tag neither from nor to close as superseded; never rewritten
row not to redo the row, whatever the tag says
row to, tag from redo the owner change
row to, tag to, before lastOwner record the last owner
row to, tag to, lastOwner done

NOT_FOUND or an unreadable vehicle is BLOCKED after three checks at least an hour apart, and the dead owner's row is not put back. A blocked vehicle stays blocked until the estate provider calls again (staff /estate retry), which reads it once more. An entry planned for another recipient is BLOCKED rather than reported moved. Waiting or frozen property answers DONE even while the vehicle stage is down. Other owner-change failures put the previous row back and retry. DONE carries the count and every moved vehicle ID. A boot and hourly reconcile over Estates.decided() catches vehicles that appear later, such as a build finishing for the dead payer; failures are caught per estate.

Upkeep pause. While the payer is dead and its latest estate is OPEN, HELD or DECIDED, settlement marks no new unpaid day and the hourly upkeep deals no damage. An unpaid marker set before the death stays.

Capability gate. EstateBridge probes the TLibs 2.6.0 classes once. Only EstateCalls, GuildEstateFallback and the participant touch them, and every call is caught, so on TLibs 2.5.0 SimpleFactions enables and simply takes no part in estates. No estate error can reach failFinancialState.

Docs: TF-Minecraft/Docs#219

Gate: tfmc-mvn -o -B clean verify: 7,985 tests, 0 failures, 100% line coverage. Tests cover crash and replay at each vehicle step, claim cancellation without double payment, old-jar journal compatibility, the civil-war realm, and the absent and UNAVAILABLE paths. CI may 404 on the unreleased TLibs 2.6.0.

🤖 Generated with Claude Code

ryanbarlow97 and others added 6 commits October 13, 2026 14:03
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Death capture records lockGuildRealm, the realm's ruling guild incarnation,
beside lockGuildIncarnation, using the same ungated lookup and civil-war
mapping (a moved rebel follows its origin guild in the host realm).

Replay now checks the character first: the current death replays, a
revived or re-dead character's journal is closed (remaining steps done,
complete, closedBy) and claims whose cleanup never applied are cancelled
in the same write, so wages are never paid twice. Unreadable characters
wait. Succession never displaces a living seat holder. CharacterDeaths
answers the death guild from the journal alone, with the realm from the
stored rights plan for older journals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GuildEstateFallback answers TLibs' EstateFallback from the death journals
and live guilds only: UNAVAILABLE until SimpleFactions is ready or while a
referenced death has no journal, NONE, or the death guild with its live
state, current leader and realm. Guild lookups give the treasury account
and the realm as its ruling guild's incarnation, and never create a guild.

EstateBridge probes the TLibs 2.6.0 estate classes once and keeps every
call behind EstateCalls, so an older TLibs only means no estates. The
fallback registers once factions start; the vehicles participant
registers at the end of the vehicle stage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cipient

The simplefactions-vehicles participant finds vehicles by personal payer
row or by VehicleFramework owner, writes vehicles/estates/<deathId>.json
durably before the first change, then moves the payer row, the owner tag
(HANDOVER) and the last owner as separate durable steps. Replay follows the
observed row and tag, never rewrites a vehicle handed on since, and lists
a vehicle for staff after three gone or unreadable reads without putting
the dead owner's row back. No fee; no slot or battle-lock check.

The hourly reconcile settles every decided estate again, which moves
vehicles that appear later, and reports only changed outcomes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he estate

While the payer is dead and its latest estate is OPEN, HELD or DECIDED,
settlement marks no new unpaid day for its personal vehicles and the
hourly upkeep deals them no damage. An unpaid marker set before the death
stays until the recipient pays. The estate state is read through the
probed bridge, which answers false on any failure, so no estate error can
reach the financial failure path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the size:XL 500-999 effective changed lines (tests excluded in mixed PRs). label Oct 13, 2026
…ay guard

- A MISSING character's journal waits for staff instead of replaying (E13).
- Waiting or frozen property answers DONE before the readiness checks, so a
  degraded vehicle stage never holds back a revive.
- A BLOCKED vehicle stays blocked: the participant's own reconcile leaves
  it alone and only a call from the estate provider (staff retry) reads it
  once more. Gone or unreadable reads count at most once an hour.
- An entry planned for another recipient is listed rather than reported
  as moved.
- The reconcile catches failures per estate, so one bad record does not
  hold back the rest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ryanbarlow97
ryanbarlow97 marked this pull request as ready for review October 13, 2026 18:25
@ryanbarlow97
ryanbarlow97 merged commit 6964207 into main Oct 13, 2026
3 of 4 checks passed
@ryanbarlow97
ryanbarlow97 deleted the stage6b/estates branch October 13, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 effective changed lines (tests excluded in mixed PRs).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant