The artifact/dialect/chapter/translation-version events packed several
independent attributes into single positional tags
(["artifact", url, visibility, license], ["dialect", name, country,
language], etc.). Positional packing made every field mandatory (a
missing or malformed field nulled the whole metadata blob), blocked
extension, and forced ArtifactMetadataTag and
TranslationArtifactVersionMetadataTag to share TAG_NAME "artifact" with
field 1 meaning url vs name.
Replace the four compound tags with seven shared single-field tags
(NameTag, UrlTag, VisibilityTag, LicenseTag, CountryTag, LanguageTag,
OriginalTextTag), following the NIP-23 one-tag-per-field convention.
Event accessors now read each field independently and build()/toXEvent()
emit one tag per field; from...Event() readers let-chain the per-field
accessors. This also removes the duplicate "artifact" tag-name collision.
Note: breaking wire-format change for kinds 30300/30302/30304/30306;
safe now since these events are not published yet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WordStatisticsTag.parse used has(3) but the tag has only 3 elements
(indices 0-2), so the guard never passed and parse always returned null
— silently breaking all Chapter and Chunk event parsing. Correct to
has(2).
Also replace unsafe tag[n].toInt() with toIntOrNull() in WordStatisticsTag
and IndexTag so a malformed numeric field from a relay returns null
instead of throwing NumberFormatException up through the parse loop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>