Merge party-known-flag: retire the party_known write-up, gogobee sets it now
This commit is contained in:
@@ -1,75 +0,0 @@
|
||||
# Wire contract — `party_known` on the public detail blob (gogobee side)
|
||||
|
||||
Status: **Pete side BUILT + TESTED. gogobee side NOT BUILT.** Written 2026-07-24 out
|
||||
of a code review of the W9 verbs branch. Small: one boolean, set unconditionally,
|
||||
no new endpoint and no new verdict. Companion to `adventure_expansion_spec.md`.
|
||||
|
||||
## The hole
|
||||
|
||||
`offersToUndo` in `internal/web/who.go` decides which of "Call the whole thing off"
|
||||
(abandon) and "Leave the party" (leave) an owner's page offers. On a live expedition
|
||||
with an EMPTY party list it took the "solo run ⇒ this player is the leader" branch,
|
||||
because a solo run publishes no seats at all.
|
||||
|
||||
But a gogobee too old to push party seats sends a perfectly valid detail blob with no
|
||||
`party` key, and that decodes to the same empty slice. So a party MEMBER served by an
|
||||
old game box was shown the leader's button — the one that throws away four people's
|
||||
day. gogobee refuses it with `rejected_not_leader`, so the live cost was a misleading
|
||||
offer rather than a lost expedition, but the page was asserting something it could
|
||||
not know.
|
||||
|
||||
Nil and empty cannot be told apart on the current wire, hence a new field.
|
||||
|
||||
## What gogobee must send
|
||||
|
||||
The public detail blob on the roster push (the one Pete decodes into `whoDetail`)
|
||||
gains:
|
||||
|
||||
```json
|
||||
"party_known": true
|
||||
```
|
||||
|
||||
**Set it unconditionally**, on every sheet, from any gogobee build that knows what a
|
||||
party seat is:
|
||||
|
||||
- on a solo run — YES, this is the case the flag exists for;
|
||||
- when the party list is omitted because there is nobody else — YES;
|
||||
- when the player is standing in town — YES;
|
||||
- when the sheet does carry seats — YES, harmless there.
|
||||
|
||||
It is a capability flag about the **sender**, not a fact about the character. It must
|
||||
never be computed from whether there is a party, whether the run is shared, or
|
||||
anything else on the sheet. A conditional `party_known` is worse than none: it would
|
||||
read as "this player is solo" and put the flag straight back into the hole it was
|
||||
added to close.
|
||||
|
||||
Anything that omits it (old builds, JSON that fails to decode) lands as `false` in
|
||||
Go, which is the fail-closed answer Pete wants.
|
||||
|
||||
## What Pete already does with it
|
||||
|
||||
- `whoDetail.PartyKnown bool \`json:"party_known"\`` — `internal/web/who.go:47`.
|
||||
- `offersToUndo`'s third parameter is `partyKnown`; the call site passes
|
||||
`page.HasDetail && page.Detail.PartyKnown`, so a blob that failed to decode is
|
||||
still excluded.
|
||||
- The flag gates the `len(party) == 0` branch **only**. The `len(party) > 0` branch
|
||||
reads the viewer's own seat and is self-evidencing — a seat that says "member"
|
||||
cannot be mistaken for leadership — so it keeps working against every sender,
|
||||
including ones that never set the flag.
|
||||
- Cases pinned in `internal/web/orders_undo_test.go`.
|
||||
|
||||
## Rollout
|
||||
|
||||
Pete is already deployed-safe: it ships first and costs nothing but one button. Until
|
||||
gogobee sets the flag, a genuine SOLO leader on a live run does not see the abandon
|
||||
button on the party branch. They are not stuck — the `self.Resume != nil` clause
|
||||
still offers it for an extracted run from town, and abandoning over Matrix was never
|
||||
affected. The moment gogobee ships the flag the button comes back with no Pete change.
|
||||
|
||||
## Done when
|
||||
|
||||
- gogobee sets `party_known: true` on every public detail sheet it builds.
|
||||
- A solo adventurer on a live expedition sees "Call the whole thing off" on their web
|
||||
page again.
|
||||
- A party member on the same build still sees "Leave the party" and never the abandon.
|
||||
- Delete this file.
|
||||
Reference in New Issue
Block a user