* 'main' of https://github.com/vitorpamplona/amethyst:
New Crowdin translations by GitHub Action
New Crowdin translations by GitHub Action
feat: implement NIP-45 HyperLogLog for probabilistic event counting
Add client-side HyperLogLog support as specified by NIP-45:
- HyperLogLog object with merge, estimate, encode/decode, and
computeOffset for deterministic filter-based offset calculation
- Add hll ByteArray field to CountResult for relay HLL data
- Update CountResultKSerializer to serialize/deserialize hll hex field
- Add queryCountMergedHll extension for multi-relay HLL merging
- 20 unit tests covering HLL operations and serialization round-trips
https://claude.ai/code/session_01CQzygEkwckLCiXzSRPMpBa
ChaCha20Core.chaCha20Xor:
- Parse key/nonce once into initial state, reuse across blocks
- XOR at word level (4 bytes at a time) instead of byte-by-byte
- Reuse working IntArray across blocks instead of allocating per block
XChaCha20Poly1305:
- Add hChaCha20FromNonce24 to avoid nonce copyOfRange(0,16) allocation
- Add chaCha20PolyKey to generate only 32 bytes instead of full 64-byte block
- Use single result array instead of ciphertext + tag concatenation
Benchmark (98-byte padded message, JVM):
Before: encrypt 2286 ns/op, decrypt 2062 ns/op
After: encrypt 1544 ns/op, decrypt 341 ns/op
https://claude.ai/code/session_01YHBwqnb3Z7Q7PX31tJ2G3i
Tests the StringIndexOutOfBoundsException fix in Url.getPart() by directly
constructing Url objects with UrlMarker indices that exceed the trimmed
originalUrl length — the exact scenario that occurs when readEnd() strips
a trailing character (e.g. ':') while the PORT/QUERY marker still points
to the original buffer position.
https://claude.ai/code/session_013rJ9iYndYVJgpYK2VazxL2
Tests cover the StringIndexOutOfBoundsException in Url.getPart() that
occurred when readEnd() trimmed trailing characters (e.g. ':') from a
detected URL but urlMarker indices remained pointing past the trimmed
string's end.
- UrlMarkerTest: three cases testing PORT/QUERY index at or beyond
string length (the boundary conditions fixed by minOf clamping and
the startIndex >= length guard)
- UrlsDetectorTest: regression for "今北産業" (no crash, 0 URLs) and
for a bare "example.com:" host
- UrlParserTest: end-to-end regression for "今北産業" and "example.com:"
https://claude.ai/code/session_013rJ9iYndYVJgpYK2VazxL2
When UrlDetector.readEnd() trims the last character from URLs ending
with characters like '.', ',', etc., the urlMarker indices remain
based on the original buffer length. This caused getPart() to call
substring() with an end index beyond the trimmed URL's length.
Fix by clamping the end index to originalUrl.length and guarding
against an out-of-bounds start index.
https://claude.ai/code/session_014Q2SvTE5vKgUm1w8dPVjYo
JesterContent fields version, fen, and history were omitted from
serialized JSON because kotlinx.serialization skips default values.
Jester's isStartGameEvent checks arrayEquals(json.history, []) which
fails when the field is absent (undefined !== []).
Added @EncodeDefault to version, fen, and history so they are always
included in the JSON output regardless of value.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ChessEngine.makeMove() now normalizes SAN notation before passing to
chesslib, fixing games against jester.nyo.dev and other clients that
use different notation:
- Castling: 0-0 → O-O, 0-0-0 → O-O-O (zeros to letters)
- Annotations: strips !, ?, !!, ??, !?, ?! suffixes
Previously, chesslib rejected 0-0/0-0-0 causing ChessStateReconstructor
to mark games as desynced and skip remaining moves. Games appeared
permanently stuck, even after app restart.
Also fixes discoverUserGames() silently dropping games classified as
spectator — now adds them to spectatingGames instead.
23 new interop tests covering SAN variants, reconstruction, spectator
detection, and missing start event handling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>