Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
e224224
fix(bonanza): enforce 45-minute limit (00-preamble.js)
maghuro Oct 10, 2026
5cc0d51
fix(bonanza): enforce 45-minute limit (01-global-constants.js)
maghuro Oct 10, 2026
ea98ca7
fix(bonanza): enforce 45-minute limit (04-ui-template.js)
maghuro Oct 10, 2026
e62a42b
fix(bonanza): enforce 45-minute limit (05-initialization.js)
maghuro Oct 10, 2026
3bd347b
fix(bonanza): enforce 45-minute limit (06-lifecycle.js)
maghuro Oct 10, 2026
0463922
fix(bonanza): enforce 45-minute limit (10-command-handling.js)
maghuro Oct 10, 2026
db7db56
fix(bonanza): enforce 45-minute limit (12-utilities.js)
maghuro Oct 10, 2026
2a6ea83
fix(bonanza): enforce 45-minute limit (bonanza-review-hardening.test.…
maghuro Oct 10, 2026
7e9358c
fix(bonanza): enforce 45-minute limit (bonanza-operations.md)
maghuro Oct 10, 2026
46afa44
test(bonanza): cover 45-minute start, extension, and restore limits
maghuro Oct 10, 2026
54d3e12
build(bonanza): regenerate 1.5.15 userscript with 45-minute cap
maghuro Oct 10, 2026
02ff6a0
fix(bonanza): keep stale snapshot grace after duration cap
maghuro Oct 10, 2026
7adcbc1
test(bonanza): prevent stale legacy snapshot settlement after duratio…
maghuro Oct 10, 2026
4d8f4e0
build(bonanza): synchronize compiled script with corrected recovery g…
maghuro Oct 10, 2026
8617954
docs: add repo-level agent instructions for generated BONanza script
maghuro Oct 10, 2026
4a65f53
docs(bonanza): explain source-of-truth build and Gist publishing work…
maghuro Oct 10, 2026
53a2338
fix(bonanza): rebuild reminder schedule when capping a restored giveaway
maghuro Oct 10, 2026
e0a2e88
test(bonanza): exercise restored capped reminder schedules
maghuro Oct 10, 2026
c4d8849
build(bonanza): regenerate tracked userscript from corrected reminder…
maghuro Oct 10, 2026
9c90d84
fix(bonanza): restore reminder count to UI for later time adjustments
maghuro Oct 10, 2026
c318a6d
test(bonanza): ensure restored reminder count survives subsequent tim…
maghuro Oct 10, 2026
609d7d5
build(bonanza): synchronize generated userscript with reminder recove…
maghuro Oct 10, 2026
7ddc4a3
fix(bonanza): anchor 45-minute deadline before asynchronous opening send
maghuro Oct 10, 2026
1238176
test(bonanza): enforce 45-minute wall clock despite delayed opening POST
maghuro Oct 10, 2026
9a905c1
build(bonanza): regenerate userscript from pre-send opening timestamp…
maghuro Oct 10, 2026
c82b7b3
fix(bonanza): announce rejected over-limit chat time commands publicly
maghuro Oct 10, 2026
6f1af32
test(bonanza): assert public chat notice for exceeding 45 minutes
maghuro Oct 10, 2026
88dfd03
docs(bonanza): explain public chat warning for over-limit time commands
maghuro Oct 10, 2026
145824b
build(bonanza): regenerate release with public time-limit chat warning
maghuro Oct 10, 2026
fe325ed
test(bonanza): confirm time-limit warnings stay private in rehearsal …
maghuro Oct 10, 2026
f920a2f
test(bonanza): extract async sendMessage correctly in rehearsal regre…
maghuro Oct 10, 2026
b6905cb
fix(bonanza): honor Silent Mode for all host/staff command replies
maghuro Oct 10, 2026
efd0b63
test(bonanza): assert Silent Mode private time-command responses for …
maghuro Oct 10, 2026
2726909
docs(bonanza): document private Silent Mode limit warnings
maghuro Oct 10, 2026
e75b27d
build(bonanza): regenerate userscript with Silent Mode command replies
maghuro Oct 10, 2026
c9660d7
fix(bonanza): route winners and addbon command announcements through …
maghuro Oct 10, 2026
f24d8d4
fix(bonanza): preserve exclusive ownership when routing private comma…
maghuro Oct 10, 2026
175729c
fix(bonanza): persist and verify public opening before accepting spon…
maghuro Oct 10, 2026
066675d
fix(bonanza): retain and reconcile pending opening snapshots before r…
maghuro Oct 10, 2026
d4c60be
fix(bonanza): avoid duplicate opening posts on ambiguous API timeouts
maghuro Oct 10, 2026
e75cfe2
fix(bonanza): apply Silent Mode to panel and chat pot announcements
maghuro Oct 10, 2026
4ab8763
test(bonanza): update deadline assertions for durable opening checkpo…
maghuro Oct 10, 2026
4fb4169
test(bonanza): verify durable opening, sponsor boundary, timeout and …
maghuro Oct 10, 2026
3951a20
test(bonanza): keep overdue ambiguous opening checkpoints recoverable
maghuro Oct 10, 2026
7261fde
build(bonanza): regenerate bundle for durable opening recovery and co…
maghuro Oct 10, 2026
cb2bfde
test(bonanza): account for opening replay cursor in hardening invariants
maghuro Oct 10, 2026
c12052e
fix(bonanza): send manually requested reminders via command reply rou…
maghuro Oct 10, 2026
a38fb3a
fix(bonanza): preserve public automatic reminders but private Silent …
maghuro Oct 10, 2026
ba2eadf
fix(bonanza): block new giveaways while uncertain opening is recoverable
maghuro Oct 10, 2026
a107db1
test(bonanza): protect uncertain recovery from restart and route manu…
maghuro Oct 10, 2026
c4494fd
build(bonanza): sync generated userscript after opening and Silent Mo…
maghuro Oct 10, 2026
86687c8
docs(bonanza): record fail-closed opening, sponsor and Silent Mode in…
maghuro Oct 10, 2026
e1a9fd9
docs(bonanza): explain checkpoint recovery and distinct sponsor boundary
maghuro Oct 10, 2026
a4b9d7a
docs(bonanza): annotate verified opening and sponsor safety in versio…
maghuro Oct 10, 2026
eab133f
fix(bonanza): re-enable verified sponsorship after confirmed public o…
maghuro Oct 10, 2026
1e96ec3
test(bonanza): assert sponsor verification gates on freshly confirmed…
maghuro Oct 10, 2026
91f7366
build(bonanza): regenerate bundle after verified opening sponsor reco…
maghuro Oct 10, 2026
6370f47
fix(bonanza): keep explicit !reminder announcements in Main Chat
maghuro Oct 10, 2026
8c4c5a4
fix(bonanza): broadcast manual reminders even in Silent Mode
maghuro Oct 10, 2026
feaaf1e
fix(bonanza): require trustworthy Main Chat cursor before opening post
maghuro Oct 10, 2026
8a0f54c
test(bonanza): verify manual reminder is public in Silent Mode and sa…
maghuro Oct 10, 2026
b6f58a1
docs(bonanza): record public !reminder exception and mandatory openin…
maghuro Oct 10, 2026
828f6bc
docs(bonanza): clarify reminder broadcasts and fail-closed opening cu…
maghuro Oct 10, 2026
4975b8e
docs(bonanza): explain manual reminders and cursor safety in version …
maghuro Oct 10, 2026
602e6bf
build(bonanza): regenerate userscript with public manual reminders an…
maghuro Oct 10, 2026
ee010b4
fix(bonanza): bind opening reconciliation to complete timestamp bucke…
maghuro Oct 10, 2026
c453d44
test(bonanza): reject same-second and late matching opening posts out…
maghuro Oct 10, 2026
d8a9318
docs(bonanza): document bounded opening publication and ambiguous tim…
maghuro Oct 10, 2026
74081e2
docs(bonanza): record strict timestamp window for opening verification
maghuro Oct 10, 2026
e44add6
docs(bonanza): describe bounded posting window and safer reconciliation
maghuro Oct 10, 2026
e467aa0
build(bonanza): sync bundle with bounded public-opening timestamp ver…
maghuro Oct 10, 2026
255e4b5
fix(bonanza): exclude ambiguous pre-opening Gift History timestamp bu…
maghuro Oct 10, 2026
f440145
fix(bonanza): never chatbox-retry opening after non-OK API response
maghuro Oct 10, 2026
4c8727c
fix(bonanza): prevent every chatbox fallback for opening, including d…
maghuro Oct 10, 2026
5e5a6bf
test(bonanza): execute sponsor timestamp and non-OK opening fallback …
maghuro Oct 10, 2026
1ed223b
docs(bonanza): record safe sponsor bucket and failed opening POST rules
maghuro Oct 10, 2026
e922889
docs(bonanza): explain precise sponsor boundary and no-duplicate opening
maghuro Oct 10, 2026
4854170
docs(bonanza): note fail-closed sponsor and non-OK API safeguards
maghuro Oct 10, 2026
fe6d749
build(bonanza): regenerate from fail-closed sponsor and opening retry…
maghuro Oct 10, 2026
3660db6
fix(bonanza): quarantine legacy snapshots without verified public ope…
maghuro Oct 10, 2026
cad3582
fix(bonanza): protect unverified legacy recovery before starting new …
maghuro Oct 10, 2026
6f36878
fix(bonanza): propagate calibrated clock uncertainty into sponsor eli…
maghuro Oct 10, 2026
86471cf
fix(bonanza): persist sponsor clock uncertainty across crash recovery
maghuro Oct 10, 2026
117b4f6
test(bonanza): quarantine legacy saves without public-opening proof e…
maghuro Oct 10, 2026
27f4037
test(bonanza): validate calibrated clock error cannot inflate the spo…
maghuro Oct 10, 2026
504aeed
docs(bonanza): mandate manual legacy recovery and calibration uncerta…
maghuro Oct 10, 2026
44edb6d
docs(bonanza): clarify immutable legacy snapshots and calibrated gift…
maghuro Oct 10, 2026
e0a32b6
docs(bonanza): describe fail-closed legacy and sponsor calibration fixes
maghuro Oct 10, 2026
82c7716
build(bonanza): regenerate legacy quarantine and sponsor calibration …
maghuro Oct 10, 2026
9843ed7
test(bonanza): keep calibration regression fixture within sponsor clo…
maghuro Oct 10, 2026
23565f3
test(bonanza): compare cross-realm VM sponsor result with native array
maghuro Oct 10, 2026
9ca2e44
fix(bonanza): recheck saved giveaway under exclusive lock before new …
maghuro Oct 10, 2026
6b30033
fix(bonanza): verify original confirmed opening message ID on reload
maghuro Oct 10, 2026
e77049c
fix(bonanza): revalidate confirmed public openings before restore or …
maghuro Oct 10, 2026
6cab76b
fix(bonanza): fail closed on uncalibrated Gift History timestamps
maghuro Oct 10, 2026
4fdb3d9
test(bonanza): cover post-lock races, confirmed recovery and uncalibr…
maghuro Oct 10, 2026
a697a36
docs(bonanza): require post-lock recovery and safe uncalibrated gift …
maghuro Oct 10, 2026
c5cae06
docs(bonanza): document strict concurrency, replay proof and clock gates
maghuro Oct 10, 2026
5a4af4e
docs(bonanza): record three newest review safety corrections
maghuro Oct 10, 2026
56d948f
build(bonanza): regenerate userscript for secure lock, recovery and t…
maghuro Oct 10, 2026
06c67b8
fix(bonanza): distinguish failed storage reads and never snapshot pre…
maghuro Oct 10, 2026
ed1b884
fix(bonanza): fail closed on uncertain recovery reads and quarantined…
maghuro Oct 10, 2026
5b27654
test(bonanza): exercise recovery read failures and preflight snapshot…
maghuro Oct 10, 2026
960dc96
fix(bonanza): preserve unreadable or malformed recovery snapshots ins…
maghuro Oct 10, 2026
b013c98
docs(bonanza): define fail-closed storage reads and unsnapshotted pre…
maghuro Oct 10, 2026
321955b
docs(bonanza): document browser interruption and recovery preservation
maghuro Oct 10, 2026
af86b7e
docs(bonanza): record storage safety regression safeguards
maghuro Oct 10, 2026
2bd854d
test(bonanza): preserve corrupt recovery data and distinguish failed …
maghuro Oct 10, 2026
df012b7
build(bonanza): regenerate from complete fail-closed storage/prefligh…
maghuro Oct 10, 2026
7ca4658
fix(bonanza): treat empty-but-present recovery keys as occupied unsaf…
maghuro Oct 10, 2026
d8b7cd4
fix(bonanza): reject occupied recovery slots even when stored text is…
maghuro Oct 10, 2026
506decf
test(bonanza): protect empty corrupt recovery keys from overwrite
maghuro Oct 10, 2026
dbd16dc
fix(bonanza): keep pre-lock recovery checks read-only and serialize l…
maghuro Oct 10, 2026
5c300d6
docs(bonanza): clarify occupied recovery keys and serialized migration
maghuro Oct 10, 2026
e8b32b7
docs(bonanza): explain pre-lock read-only recovery invariant
maghuro Oct 10, 2026
25a70fb
docs(bonanza): mention empty corrupt state and migration safety
maghuro Oct 10, 2026
01d62cd
build(bonanza): synchronize full bundle after recovery storage audit
maghuro Oct 10, 2026
1a01d40
fix(bonanza): reload recovery under restore lock and reject empty leg…
maghuro Oct 10, 2026
48f80f9
test(bonanza): cover locked restore freshness, empty legacy key and r…
maghuro Oct 10, 2026
4131d34
fix(bonanza): keep pre-lock recovery loading read-only, quarantine ex…
maghuro Oct 10, 2026
5b4d670
test(bonanza): ensure expired snapshots remain read-only before resto…
maghuro Oct 10, 2026
b4bc589
docs(bonanza): document locked restore refresh and read-only recovery…
maghuro Oct 10, 2026
4dde6ca
docs(bonanza): document locked restore refresh and read-only recovery…
maghuro Oct 10, 2026
c998a34
build(bonanza): synchronize generated script after locked recovery ha…
maghuro Oct 10, 2026
fcb68b8
fix(bonanza): fail closed on hostless legacy state and restore under …
maghuro Oct 10, 2026
34ce04d
test(bonanza): update locked recovery safety assertions and diagnostic
maghuro Oct 10, 2026
906fcfc
fix(bonanza): reject nonstring legacy recovery host identities
maghuro Oct 10, 2026
4286104
fix(bonanza): reconcile legacy and namespaced recovery before settlement
maghuro Oct 10, 2026
0ed1335
fix(bonanza): retire verified duplicate legacy state before checkpoin…
maghuro Oct 11, 2026
f8831d4
fix(bonanza): verify legacy removal after single-slot recovery migration
maghuro Oct 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Repository instructions for coding agents

These instructions apply to the whole repository. Read them before editing code.
Keep changes focused on the affected component; this repository contains
multiple userscripts, not just BONanza.

## DarkPeers BONanza Giveaway (important)

- **Single source of truth:** `userscripts/giveaway/src/*.js` (15 ordered
fragments). Never edit
`userscripts/giveaway/DarkPeers_BONanza_Giveaway.user.js` directly.
That file is **generated and committed** to Git for Tampermonkey.
- To modify the script, edit the relevant fragment. The file
`scripts/build-bonanza.mjs` defines the **exact concatenation order**.
Fragments are not independent JavaScript modules and must keep the
existing single-IIFE runtime intact.
- Update metadata, version notes and `@version` in
`userscripts/giveaway/src/00-preamble.js`, not in the generated file.
When bumping the version, adjust tests that assert the precise version.
Do not change `@namespace` or the update/download URLs unintentionally.
- From the repository root, **after every source change**, run:

```bash
node scripts/build-bonanza.mjs
node scripts/build-bonanza.mjs --check
node --check userscripts/giveaway/DarkPeers_BONanza_Giveaway.user.js
node --test tests/bonanza-*.test.mjs
git diff --check
```

- Commit both the changed fragments and the regenerated
`DarkPeers_BONanza_Giveaway.user.js` (plus any tests/docs) in the same PR.
A source-only commit will fail CI because the generated file is stale.
Do not patch the generated file by hand, even to repair a review finding:
fix the source, then rebuild.
- The **Validate BONanza** GitHub Action verifies the tracked bundle, checks
syntax and runs tests on PRs and relevant pushes to `main`. It does not
commit the generated file for you.
- On relevant pushes to `main`, **Publish BONanza to Gist** rebuilds,
fails if the committed bundle differs, and then publishes the userscript
plus a generated `.meta.js` update manifest. No deployment occurs merely
from opening a PR. Do not manually publish or maintain the Gist.
- The script can transfer real BON. Preserve safety gates around ownership,
recovery, gift history, settlement and transfers. Add regression tests for
affected behavior, and use rehearsal mode for validation that would
otherwise post public chat messages or move real currency/points. Never
initiate a live payout for a routine code test.

## Opening / sponsor accounting invariants

- Before posting a LIVE opening, require a trustworthy positive Main Chat
message cursor. If it is unavailable, abort BEFORE posting (otherwise an
identical old announcement might falsely verify the new opening).
- Before posting the public giveaway opening, persist and read back a
**pending opening checkpoint** with the exact prepared announcement,
pre-send timestamp, Main Chat cursor and a bounded publication window.
When the send resolves, persist its completion timestamp to further
narrow that window. Reconciliation must prove the **entire** server-side
timestamp-resolution bucket lies inside the original opening attempt:
same-second overlap or later identical announcements are NOT sufficient.
ANY opening API failure, including non-OK HTTP responses, must never
trigger the chatbox fallback: the server may already have published
the opening, so reconcile the original checkpoint instead.
A timeout/ownership loss is ambiguous: do not erase the checkpoint,
re-post blindly, or settle BON.
Restore must verify the exact own-user announcement in authoritative
Main Chat history before enabling entries or any sponsor/payout action.
- The 45-minute absolute deadline is anchored to the conservative
**pre-send** time, so server response latency cannot extend the event.
**Sponsor eligibility must NOT use that time.** It begins strictly after
the independently verified publication timestamp bucket. Each Gift
History timestamp bucket must START at/after `sponsorStartTs`, not
merely overlap it; uncalibrated history must be deferred altogether.
Omit ambiguous boundary gifts rather than risking inflation of a real
BON payout. Persist `sponsorStartTs` and
use it for both live Gift History polling and reload reconciliation.
- After acquiring the exclusive Web Lock, read saved recovery storage AGAIN
before mutating state or posting. Another tab may have saved an uncertain
opening while waiting for the lock; do not overwrite any such state.
**Restores must also re-read and revalidate the COMPLETE latest snapshot
under that lock**, discarding the pre-lock in-memory object: another tab
could have persisted payout/settlement progress while ownership was queued.
Pre-lock `__expiredBeyondGrace`, `__legacyOpeningUnverified`, proof and
host data are stale hints, NEVER grounds for rejecting before the lock.
Classify only the latest post-lock snapshot.
Never replace a newer committed settlement with stale recovery data.
The recovery reader reports `readOk` separately from `raw`: a denied
localStorage read, corrupt legacy JSON or migration failure MUST block the
start, never appear as empty storage. An empty STRING in an existing
recovery slot is still an occupied (corrupt) record. Keep pre-lock reads
read-only, performing any legacy migration under exclusive ownership.
A legacy key containing an empty string is PRESENT, not absent: test
`getItem() === null` to prove absence. Even valid JSON without an
identifiable host (such as `{}` or `{"giveawayData":{}}`) remains an
occupied, unidentified record. Fail closed and preserve it for manual
review: ONLY a positively identified foreign host may be ignored.
ALWAYS inspect the old legacy slot even when namespaced recovery exists.
Corrupt, unidentified or different SAME-HOST snapshots must block automatic
recovery/settlement; identical same-host records are safe to read, as is
a positively identified different host. On post-lock recovery, first
verify byte-identical same-host snapshots, then retire their duplicate
legacy slot with before/after read-back checks BEFORE writing a new
confirmed opening checkpoint. If cleanup fails, abort without payout;
pre-lock discovery must remain read-only. Also verify legacy removal
succeeded after migrating a single old-format record: a successful
namespaced write does not prove the old key was deleted. Abort restore
if deletion is denied or silently ignored, before a pending opening
is confirmed. Never delete a legacy record until its namespaced copy
has been verified durably.
`loadGiveawaySnapshot()` must never
delete, migrate, or alter recovery storage before acquiring the Web Lock;
stale/expired data needs manual review, not speculative cleanup.
- **Preflight is not an opening.** Before a durable `openingCheckpoint`
exists, the in-memory configuration MUST NOT be snapshotted by pagehide,
beforeunload or other background persistence. A BFCache handoff during
balance/history/cursor awaits must not generate a false legacy giveaway
or allow the abandoned tab to post.
- Malformed, unreadable or incomplete recovery data may contain settlement
evidence. Preserve its raw storage for manual investigation; a parse error
is not permission to delete it or start a replacement.
- Reverify every locally **confirmed** LIVE opening during restore against
the exact original Main Chat message ID, authenticated author, full
announcement text, bounded send window and sponsor boundary. If that
authoritative evidence is unavailable, preserve the snapshot without
enabling entries or BON transfers.
- With no calibrated Gift History offset, neither UTC nor browser-local
timestamps are trustworthy: defer ALL gifts as retryable and block
final canonical settlement until calibration succeeds.
- Leave unresolved opening checkpoints intact for later recovery; never
overwrite them with a new giveaway or auto-settle a recovered ancient
opening beyond the one-hour expiry grace. **Pre-checkpoint legacy snapshots
without proven publication and a conservative pre-send opening time are
quarantined unchanged for MANUAL review**, including already-expired or
committed settlement state. Never cap their deadlines using a post-send
`startTime` or automatically resume entries and BON settlement. Never
overwrite such a preserved snapshot with a new start.
- A Gift History clock offset calibrated against precise notification/chat
events and second-precision history rows has **fractional calibration
uncertainty**. Persist an upper error bound with the inferred offset and
subtract it from the calibrated bucket start BEFORE checking
`sponsorStartTs`. This also applies to the boundary-evidence path and
across reloads. Keep all BON-moving operations blocked while publication
or sponsor timing remains unverified.
- In **Silent Mode**, ordinary command replies (staff responses, errors,
`!winners`, `!addbon` etc.) use private messages. **`!reminder` is NOT
an ordinary reply:** it explicitly requests an announcement for everyone.
Both manual `!reminder` and scheduled automatic reminders MUST broadcast
to Main Chat even in Silent Mode. Rehearsal Mode still redirects both
reminder types privately to the host and never transfers real BON.

Full source layout and examples:
[`userscripts/giveaway/src/README.md`](userscripts/giveaway/src/README.md).

If repository conventions or workflows change, update **both** this file
and the component's README in the same PR so future agents get accurate
instructions.
4 changes: 3 additions & 1 deletion docs/runbooks/bonanza-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This is the operational reference for hosting, rehearsing and recovering a DarkP

## If the pot or sponsor accounting looks wrong

1. Extend the giveaway time if entries are still open.
1. Extend the giveaway time if entries are still open, without exceeding 45 minutes in total from public opening.
2. Do not settle while the accounting warning is visible.
3. Do not manually resend winner gifts or BON Pool contributions unless the persisted settlement state explicitly says they were never attempted.
4. Reload Main Chat. The userscript restores the giveaway and reconciles sponsor accounting against persistent DarkPeers Gift History.
Expand All @@ -25,6 +25,8 @@ DarkPeers staff may use operational recovery controls:
- rig / unrig
- time add / remove
- addtime / removetime

The 45-minute maximum applies to the initial form duration, saved presets and every host/staff extension. An extension cannot push the deadline beyond 45 minutes after the original public opening, even after a reload.
- naughty

Every non-host staff action is identified publicly in the command output with the staff username.
Expand Down
Loading
Loading