Pre-release · phase 1 of 3

Dibs — build state

A board for dividing a treasure haul. It records what the group decides; it decides nothing.

Open the board the board

What this is

Dividing a haul is a social problem wearing an arithmetic costume

Six players come out of a dungeon with ninety-odd things and no agreed way to split them. The hard part was never the sums — it is that people want different things, value them differently, and have to end the evening believing the result was fair. Software that picks winners solves the wrong problem.

So Dibs is a shared board, not an algorithm. Everyone can see what everyone else wants, where each person stands against an equal share, and what remains unresolved. Nothing settles until the whole table agrees it should.

What it does

  • Imports a haul from a spreadsheet, an email table, or a pasted list
  • Shows every claim, every contest, and every person's position at a glance
  • Keeps a running reconciliation that cannot silently drift
  • Distinguishes unknown from worthless everywhere it matters
  • Settles a round only when nobody objects

What it isn't

  • Not a virtual tabletop, and not tied to any edition or system
  • Not a rules engine — it enforces limits you set, and has none of its own
  • Not an arbitrator; it has no opinion about who deserves what
  • Not multiplayer yet — that is phase 2
  • Not finished. This page exists to say exactly how unfinished
Nothing leaves your browser

There is no account, no server and no analytics. The board keeps its history in your browser's local storage and nowhere else, and the whole application is one HTML file you can save, read, and mail to somebody. When the shared server arrives in phase 2 that changes — and it will say so plainly when it does.

21WorkingBuilt and exercised against a real 95-line haul. One more works only partly.
10DefectsRenders but lies, does nothing, or cannot be taken back
15SpecifiedAgreed in design, absent from the build — three of them whole phases
5ParkedDeferred on purpose, or pinned pending a decision

What works today

The board draws, reconciles, and settles a round

Everything below has been run against a real haul — 95 lines, 225,614.46 gp, 23 of them unpriced — and not only against fixtures written to make it look good.

Geometry

WorksOne SVG root A single <svg> whose viewBox tracks the element's real pixel size, so one user unit is one CSS pixel and nothing is scaled twice.
WorksEqual capacity Wedges are solved so every player gets the same number of usable tile positions — not the same area. The tightest wedge sets the allowance for everyone, whatever shape the window is.
WorksSeat and block Your own wedge pins to the bottom of the ring; the four zone wedges take whichever slot lands nearest the top. Everyone keeps their order around the circle.
WorksRim names Player names curve along the arc, tinted to the wedge. Every name renders at the same size — the largest that fits the tightest wedge — because a name bigger than its neighbour's would read as a claim about the player.
WorksEmblems Ten heraldic devices on ten fields, assigned by roster position. A single bold charge carries more at 40px than a face does, and has no gaps to fall through.
WorksGauges Two arcs per player, each lying on the border of the band it reports: what you have claimed on the pool edge, what you have secured on the outer line. Both scale to the narrowest wedge, so a given length means the same quantity everywhere on the board.

Acting on it

WorksClaim Drag a tile from the pool into a player's band. The item stays in the pool; what appears in the band is a ghosted reference to it, because wanting something does not move it.
WorksWithdraw Drag that reference anywhere outside its own band. No aim needed — nothing actually moved.
WorksRelease Drag a settled item back to the pool. The only inward move on the board, and the haggling path.
WorksContest Two or more claimants turns the outline magenta. Contested items cannot settle — they are the argument still to be had.
WorksReady Per player, and fingerprinted against the board: your assent dissolves the moment what you assented to changes. When the last person flags ready, the uncontested claims settle together.
PartialSettle Works, but it is currently a driver override — available whenever anything is uncontested rather than when the table has agreed. See defects.
WorksLook Click a tile for its card; hover a wedge for that player, click to pin it open.

Data and record

WorksEvent log The board is rebuilt by replaying an append-only log of everything anyone did, through a single chokepoint. Nothing changes state anywhere else — which is what will let a shared server be added without changing how any of this behaves.
WorksEleven actions Set up · import · claim · withdraw · confirm · release · ready · settle · clear claims · portrait · reset. Every one of them carries an author and a timestamp.
WorksImport Paste tab- or comma-separated rows, or drop a .tsv, .csv or a saved Dibs export on the window. The separator is detected, a header row is dropped if there is one, and an empty value cell becomes unknown rather than zero.
WorksReconciliation Recovered, unpriced, pooled, claimed, contested, ready — plus three checks the arithmetic alone would not catch: a total that has drifted, items keyed to a place that no longer exists, and claims held by someone who has left.
WorksPortability Export the whole board, including portraits, as one file. Mail it, and the board arrives with it.

The test rig

Built into the same file, behind a shift-click on the ? button. It is how the board gets exercised, and anyone can use it to try Dibs without a haul of their own.

WorksThree axes Seven hauls × seven parties × six stages. Haul says what is in the box, party says who is at the table, stage says how far along the evening is.
WorksStages Fresh · Opening · Mid-haggle · Deadlock · Lopsided · Endgame — the same haul at different moments, not different hauls.
WorksA real haul Ninety-five lines from an actual campaign, including nine kinds of coin, twenty-five stacks, and twenty-three things nobody has priced. Every other fixture was written to exercise one thing; this one was not written at all, which is the point of having it.
WorksReproducible Fixture identities are a pure function of which haul and which position, so a saved board reloads and a reported bug reproduces.

Known defects

What renders but lies, or does nothing at all

Published rather than quietly fixed later, because a build-state page that lists only successes is not a build state. Ordered by how much each one misleads — the first is not a bug in a feature, it is a feature that was drawn and never wired.

BrokenZone entry Nothing can be put into Party, Assess, Consign or Dispose by hand. The hit test recognises those bands and the drop handler has no branch for them, so every drop silently bounces. Only the test rig can place items there.
BrokenZone as claimant Worse than a no-op: a drop on a zone's inner band is treated as a claim, registering the zone itself as a player who wants the thing.
BrokenConsignment counted as a loss Value set aside to be sold is subtracted from the pot alongside things given away, so consigning a 400 gp sword makes everyone poorer by a sixth of it with nothing ever coming back. It should be pending, not spent.
LiesTile size readout The slider reports the size you asked for, not the size you got. On a 95-item haul it reads 56px while drawing at 34px — the pool quietly shrank the tiles to fit and said nothing.
LiesTwo dead figures Realized and written off are hard-coded dashes. They sit in the reconciliation panel looking exactly like the figures either side of them, which are real.
DeadThe established value state Confidence in a value has three designed states — unidentified, attributed, established. The third is styled, and named on every card, and nothing has ever produced it.
DeadAppraisals Every item carries a list of appraisals, seeded at import. Nothing reads it. The model where a value is a claim with an author and a basis is specified and absent.
DeadWho is carrying it Written in four places, read in none — and it already means two things at once: the owner in one case, whoever moved the item in another. Ownership and possession got merged into a single field, and they are not the same question.
RiskNo undo Never exactly one way to undo something is a stated principle, and the undo system does not exist. The settle override can move dozens of items on one click and nothing takes it back.
LimitLabels stop identifying things At 95 items, 86 of 95 tile labels are truncated and only 73 remain distinguishable — one wizard's fourteen possessions all render as the same six characters. The truncation is working as designed; the pool has simply outgrown what a tile can say, which is what the filtering and splitting tools are for.

Specifications currently adhered to

The rules the code actually obeys

Stated principles

  • Dibs has no opinions. No dice, no scoring, no automatic winner. People decide; the board records.
  • Every action has an author. Some authors act in advance — readiness is consent given before the moment it is spent. The board never moves anything by itself.
  • Nothing settles without everyone. One rule covers putting things in and taking them out: if you disagree, don't vote to settle.
  • Silence is not consent. Indifference is a position taken on the record, never one assumed of you because you said nothing.
  • Money settles desire, not trust. Two people wanting the same thing is a question about price. Two people disagreeing over whose hand should destroy it is not, and nothing here will treat it as one.
  • Unknown is never zero. A total that leaves rows out says so, in the footer and on every card.
  • Colour is never the only cue. Contested is an outline and a position, not just a hue.
  • Equal capacity, not equal area. Every player gets the same room to work in, whatever shape the window is.
  • Limits are the group's, and default to none. The board can enforce a rule you set. It has none of its own.

The ownership model

The division decides ownership, in the mutual opinion of the group — never possession. A fighter carrying a wizard's books because they are heavy owns nothing by carrying them. So every wedge on the board is either a character, or a state regarding ownership.

WedgeOwnership answerState
a playerthat character owns itbuilt
the poolowned by nobody yet; answerable herebuilt
Partyowned jointly, deliberately undivideddraws only
Assessundetermined — the answer is not in yetdraws only
Consignpasses to a buyer; the party owns the proceedsdraws only
Disposeownership relinquisheddraws only

Assess is the odd one: not a destination but a router. Its verdict picks one of the others — a price and back into the pool, a danger and straight to disposal, a quest item to the party, a refusal to rule on something that was never the group's to decide, or a question that outlives the session and waits for an expert.

Architectural contracts

HeldThe model is the truth Every change goes through one function. What you see is a projection of the model and never a source of it.
HeldAppend-only history The log is never rewritten. That is what lets a shared server be added later without changing the meaning of anything already recorded.
HeldDragging moves nothing A drag updates a transform. No element is ever re-parented mid-gesture, which is why a claim can be abandoned harmlessly at any point.
HeldTwo drag systems, never mixed Pointer events drive the tiles; the browser's own file drag-and-drop handles dropped files. They do not meet.
HeldMeasured truncation SVG text cannot wrap, so every label is cut against its own measured width, and the measurement is cached.
HeldTwo complete palettes Dark by default, light when your system asks for it, with every colour that carries meaning independently tuned for the ground it sits on.
Four rules learned the hard way, now load-bearing

SVG presentation attributes lose to any CSS rule, so sizes on styled text must be set inline or resizing silently does nothing. The hidden attribute loses to any author display, so hiding a panel needs an explicit override or it renders anyway. A shape filled with none hit-tests only its outline, so ghosted tiles need an explicit pointer-events rule or they are unclickable in the middle. And round line caps paint half a stroke past the end of a path, which the path's own measured length does not include — the reason three separate attempts to stop the gauges overrunning their wedges all failed.

Planned

The session, front to back

Four phases, each opening and closing deliberately. Only the second one exists.

  1. The assessment round Is it ours? Is it to be held jointly? What is it? The round sorts rather than resolves — anything waiting on an outside answer stays put, across sessions if need be, because an appraisal takes real time and the table cannot stall on the slowest one. A verdict here can be a price, but it can equally be that poison must be destroyed or we will never carry that, leave it. ends when nothing in the pool has an open question
  2. The claim rounds Claim, contest, haggle, settle. The only phase that is built. ends when the pool is empty
  3. The buyout round Things set aside to be sold come back at their resale price for one last round, so anyone who passed at full value can take them at the discount the party had already agreed to accept. Whatever nobody buys, the party keeps — held, but not valued. one repricing per item, never a descending auction by increments
  4. Close The settlement record: what each person owns, what was marked down, what was written off, and who is holding what that the party declined to rule on. not started

The value spine

Everything above depends on this, and most of it is one function split in two.

NextSplit the value One figure stays what came out of the dungeon and never changes, guarding the reconciliation. A second reads what it counts for when dividing, and that is the one prices and bids move.
NextFour real figures Recovered, marked down, realized, written off. The markdown line is signed, so a winning bid above book value reads as a premium without needing a second row bolted on later.
NextHeld but not valued One property, four reasons: something awaiting assessment, a quest item, an unsold consignment, an unbid lot. All are in the party's hands and count toward nobody's share.

Consent

SpecReadiness that covers what you saw Today your assent tracks only your own claims, so a disposal's terms or an item's price could change under you without being asked again. It should track exactly what the round view showed you.
SpecStances Three ways to give assent: plainly, I care not, or so long as those with an opinion agree — the last surviving the details being refined, and dying the moment the people who care fall out with each other.
SpecAssent lives with the round Ready and Settle reachable only where the round is on screen, so nobody approves a thing they were not looking at. It costs nothing on the ordinary path and constrains only the override — the one act that spends consent nobody gave.
SpecDisposal terms How, and by whose hand, recorded with the item, along with whether the thing still exists afterwards. Agreeing something should go is not agreeing who does it — and that disagreement is never settled by money.

Pool tools

At ninety-five items nobody reads a pool; they search it. That is a different instrument.

SpecWhat's on the table A toggle between what is in the round and what is still available. It depends on nothing else, and it is the difference between a navigable board and a wall of tiles.
SpecShared view and your own The pool inverts to the opposite palette when what you are looking at is a private lens. The inverted region is exactly the region where your view can differ from everyone else's, so the boundary itself carries the meaning.
SpecSplitting and merging A real haul shows both failures at once: nine rows of coin that are really one number, and twenty-five stacks pretending to be single things.
SpecThe top-up filter Show me what would close my gap. The most useful single tool on the list, and downstream of the value work because computing the gap needs the share arithmetic.
SpecValue confidence Undetermined, contested, established — visible on the tile. Two of the three already exist in the data; contested value is the real gap, and it cannot use the outline, because a contested claim already owns that channel and both can be true at once.

Deferred and undecided

DeferredBidding The only mechanism that answers both of the board's questions in a single act — who owns it, and what it was worth. It serves equally as a tiebreak between two people who want the same thing and as a substitute for an appraisal the group cannot afford to wait for. Sealed or open is undecided: sealed suits players in different rooms, but it forces the board to keep a secret, which it has no way to do today.
DeferredOffering something back Drag from what you hold into your own band — solid where ownership rests, ghosted in the pool where it might go. The claim gesture run backwards, and the supply side of topping up whoever came out short.
DeferredUndo · notes and IOUs · private tools · audit view · the shared server The remaining work, in roughly that order of urgency.
UndecidedThe gate An experiment in letting a player's own token act as the threshold between wanting and holding. It breaks equal capacity — only four of twenty-four test boards still deliver every player their full allowance with it on. Keep, adopt, or drop.
UndecidedZone block sizing The four zone wedges currently take a fixed share of the ring rather than as much as they actually need. Solving it properly returns about 35° to the players.