{
  "name": "edgegoat",
  "version": "0.1.1",
  "total": 284,
  "generators": [
    {
      "name": "dates()",
      "title": "Dates",
      "count": 46
    },
    {
      "name": "timeZones()",
      "title": "Time zones",
      "count": 18
    },
    {
      "name": "strings()",
      "title": "Strings",
      "count": 49
    },
    {
      "name": "numbers()",
      "title": "Numbers",
      "count": 26
    },
    {
      "name": "numericStrings()",
      "title": "Numeric strings",
      "count": 17
    },
    {
      "name": "bigints()",
      "title": "BigInts",
      "count": 8
    },
    {
      "name": "urls()",
      "title": "URLs",
      "count": 28
    },
    {
      "name": "emails()",
      "title": "Emails",
      "count": 26
    },
    {
      "name": "paths()",
      "title": "Paths",
      "count": 30
    },
    {
      "name": "json()",
      "title": "JSON",
      "count": 22
    },
    {
      "name": "arrays()",
      "title": "Arrays",
      "count": 14
    }
  ],
  "cases": [
    {
      "generator": "dates",
      "label": "unix epoch 1970-01-01T00:00:00.000Z",
      "value": "1970-01-01T00:00:00.000Z",
      "why": "Timestamp 0 is falsy, so `if (!time)` treats a valid date as missing, and west of UTC it is still 1969 locally.",
      "tags": [
        "epoch",
        "falsy"
      ]
    },
    {
      "generator": "dates",
      "label": "1 ms before the epoch",
      "value": "1969-12-31T23:59:59.999Z",
      "why": "Negative timestamps: `ms % 1000` is -1, not 999, so splitting seconds and milliseconds with % and Math.floor disagree.",
      "tags": [
        "epoch",
        "pre-1970",
        "negative"
      ]
    },
    {
      "generator": "dates",
      "label": "before 1970 with fractional seconds (1969-12-31T23:59:58.500Z)",
      "value": "1969-12-31T23:59:58.500Z",
      "why": "Truncating -1.5 s toward zero gives 23:59:59 instead of 23:59:58; Math.trunc vs Math.floor and integer division bugs live here.",
      "tags": [
        "pre-1970",
        "fractional",
        "negative"
      ]
    },
    {
      "generator": "dates",
      "label": "moon landing 1969-07-20T20:17:40.123Z",
      "value": "1969-07-20T20:17:40.123Z",
      "why": "Negative timestamp with milliseconds: serializers that build \"seconds.millis\" from a negative value print a wrong or doubly negative fraction.",
      "tags": [
        "pre-1970",
        "fractional",
        "negative"
      ]
    },
    {
      "generator": "dates",
      "label": "local mean time era 1850-01-01T00:00:00Z",
      "value": "1850-01-01T00:00:00.000Z",
      "why": "Before standard time, zones used local mean time with second level offsets (Sao Paulo was -03:06:28); getTimezoneOffset() reports whole minutes, so local arithmetic drifts by seconds.",
      "tags": [
        "pre-1970",
        "lmt",
        "timezone"
      ]
    },
    {
      "generator": "dates",
      "label": "year 0 (0000-01-01T00:00:00Z)",
      "value": "0000-01-01T00:00:00.000Z",
      "why": "Date.UTC(0, 0, 1) and new Date(0, 0, 1) map years 0 to 99 to 1900 to 1999, and toISOString() yields \"0000\", which \"1 BC\" formatting must handle.",
      "tags": [
        "far-past",
        "two-digit-year"
      ]
    },
    {
      "generator": "dates",
      "label": "negative year (-000001-01-01T00:00:00Z)",
      "value": "-000001-01-01T00:00:00.000Z",
      "why": "toISOString() produces an expanded, signed year \"-000001\"; regexes that expect four digits reject it.",
      "tags": [
        "far-past",
        "iso-format"
      ]
    },
    {
      "generator": "dates",
      "label": "year 2038 limit 2038-01-19T03:14:07Z",
      "value": "2038-01-19T03:14:07.000Z",
      "why": "Last second representable as a signed 32 bit Unix time; anything that stores seconds in an int32 (or uses `| 0`) is fine here.",
      "tags": [
        "y2038"
      ]
    },
    {
      "generator": "dates",
      "label": "year 2038 overflow 2038-01-19T03:14:08Z",
      "value": "2038-01-19T03:14:08.000Z",
      "why": "One second past the int32 limit: `(ms / 1000) | 0` wraps to 1901-12-13, and so do 32 bit database columns.",
      "tags": [
        "y2038",
        "overflow"
      ]
    },
    {
      "generator": "dates",
      "label": "last instant of year 9999",
      "value": "9999-12-31T23:59:59.999Z",
      "why": "Largest instant with a four digit year; one millisecond later toISOString() switches to \"+010000\".",
      "tags": [
        "far-future",
        "iso-format"
      ]
    },
    {
      "generator": "dates",
      "label": "year 10000 (+010000-01-01T00:00:00.000Z)",
      "value": "+010000-01-01T00:00:00.000Z",
      "why": "toISOString() returns a six digit signed year; parsers, databases and YYYY format strings break.",
      "tags": [
        "far-future",
        "iso-format"
      ]
    },
    {
      "generator": "dates",
      "label": "maximum Date (+275760-09-13T00:00:00.000Z)",
      "value": "+275760-09-13T00:00:00.000Z",
      "why": "Largest valid Date. Adding 1 ms produces Invalid Date, so \"end of time\" sentinels overflow.",
      "tags": [
        "far-future",
        "limit"
      ]
    },
    {
      "generator": "dates",
      "label": "minimum Date (-271821-04-20T00:00:00.000Z)",
      "value": "-271821-04-20T00:00:00.000Z",
      "why": "Smallest valid Date. Subtracting anything produces Invalid Date, and local offsets west of UTC push the local wall clock out of range.",
      "tags": [
        "far-past",
        "limit"
      ]
    },
    {
      "generator": "dates",
      "label": "invalid date",
      "value": "Invalid Date",
      "why": "getTime() is NaN, toISOString() throws RangeError, JSON.stringify gives null and every comparison is false.",
      "tags": [
        "invalid"
      ]
    },
    {
      "generator": "dates",
      "label": "date-only string parsed as UTC (new Date(\"2026-03-01\"))",
      "value": "2026-03-01T00:00:00.000Z",
      "why": "Date-only ISO strings are UTC midnight, while date-time strings without Z are local; west of UTC this date displays as February 28.",
      "tags": [
        "parsing",
        "timezone"
      ]
    },
    {
      "generator": "dates",
      "label": "leap day 2024-02-29",
      "value": "2024-02-29T12:00:00.000Z",
      "why": "Adding a year with setFullYear(y + 1) lands on 2025-03-01 because Feb 29 2025 does not exist; birthdays and anniversaries drift.",
      "tags": [
        "leap",
        "arithmetic"
      ]
    },
    {
      "generator": "dates",
      "label": "leap day 2000-02-29 (400 year rule)",
      "value": "2000-02-29T12:00:00.000Z",
      "why": "2000 is a leap year because it is divisible by 400, unlike 1900 and 2100; a \"divisible by 100 means not leap\" rule rejects it.",
      "tags": [
        "leap"
      ]
    },
    {
      "generator": "dates",
      "label": "not a leap year 2100-02-28",
      "value": "2100-02-28T12:00:00.000Z",
      "why": "2100 is not a leap year; `year % 4 === 0` claims Feb 29 2100 exists and the day after this is computed wrong.",
      "tags": [
        "leap"
      ]
    },
    {
      "generator": "dates",
      "label": "month end 2026-01-31",
      "value": "2026-01-31T12:00:00.000Z",
      "why": "setMonth(month + 1) on January 31 overflows to March 3, because February 31 does not exist.",
      "tags": [
        "month-end",
        "arithmetic"
      ]
    },
    {
      "generator": "dates",
      "label": "month end 2026-03-31",
      "value": "2026-03-31T12:00:00.000Z",
      "why": "Adding one month to March 31 gives May 1, since April has 30 days; \"same day next month\" needs clamping.",
      "tags": [
        "month-end",
        "arithmetic"
      ]
    },
    {
      "generator": "dates",
      "label": "last millisecond of 2026 (UTC)",
      "value": "2026-12-31T23:59:59.999Z",
      "why": "Range queries ending at 23:59:59 miss this millisecond; month index 11 plus one must roll over into the next year.",
      "tags": [
        "month-end",
        "year-boundary"
      ]
    },
    {
      "generator": "dates",
      "label": "2027-01-01 is in ISO week 53 of 2026",
      "value": "2027-01-01T12:00:00.000Z",
      "why": "ISO week years differ from calendar years: this Friday belongs to week 53 of 2026, so `getFullYear()` plus week number is wrong.",
      "tags": [
        "week"
      ]
    },
    {
      "generator": "dates",
      "label": "2024-12-30 is in ISO week 1 of 2025",
      "value": "2024-12-30T12:00:00.000Z",
      "why": "A Monday in December that belongs to week 1 of the next ISO year; \"yyyy-ww\" built from the calendar year shows 2024-01.",
      "tags": [
        "week"
      ]
    },
    {
      "generator": "dates",
      "label": "2023-01-01 is a Sunday in ISO week 52 of 2022",
      "value": "2023-01-01T12:00:00.000Z",
      "why": "ISO weeks start on Monday, US weeks on Sunday: this day is week 52 of 2022 in ISO but week 1 of 2023 in US numbering.",
      "tags": [
        "week"
      ]
    },
    {
      "generator": "dates",
      "label": "America/New_York 2026: 1 ms before spring forward (2026-03-08 01:59 local)",
      "value": "2026-03-08T06:59:59.999Z",
      "why": "Last instant before clocks jump from 02:00 to 03:00 (UTC-05:00 to UTC-04:00); adding 60 minutes of wall time here is not 60 minutes of real time.",
      "tags": [
        "dst",
        "gap",
        "timezone"
      ],
      "zone": "America/New_York"
    },
    {
      "generator": "dates",
      "label": "America/New_York 2026: spring forward (2026-03-08 03:00 local)",
      "value": "2026-03-08T07:00:00.000Z",
      "why": "Clocks jump from 02:00 to 03:00; local times in between do not exist, so building a Date from local fields shifts it and that local day is 23 hours long.",
      "tags": [
        "dst",
        "gap",
        "timezone"
      ],
      "zone": "America/New_York"
    },
    {
      "generator": "dates",
      "label": "America/New_York 2026: fall back, first 01:30 (2026-11-01)",
      "value": "2026-11-01T05:30:00.000Z",
      "why": "Clocks fall back from 02:00 to 01:00, so 01:30 happens twice; this is the first one (UTC-04:00). Parsing the local time picks one of the two.",
      "tags": [
        "dst",
        "overlap",
        "ambiguous",
        "timezone"
      ],
      "zone": "America/New_York"
    },
    {
      "generator": "dates",
      "label": "America/New_York 2026: fall back, second 01:30 (2026-11-01)",
      "value": "2026-11-01T06:30:00.000Z",
      "why": "Same wall clock reading as the first 01:30, 60 minutes later (UTC-05:00); sorting or deduplicating by local time breaks and that local day is 25 hours long.",
      "tags": [
        "dst",
        "overlap",
        "ambiguous",
        "timezone"
      ],
      "zone": "America/New_York"
    },
    {
      "generator": "dates",
      "label": "America/New_York: last instant of 2025 local time",
      "value": "2026-01-01T04:59:59.999Z",
      "why": "Local time is 2025-12-31 23:59:59.999 (UTC-05:00) but the UTC year is already 2026; a year check with getUTCFullYear() is off by one.",
      "tags": [
        "year-boundary",
        "timezone"
      ],
      "zone": "America/New_York",
      "ref": "https://github.com/github/relative-time-element/pull/384"
    },
    {
      "generator": "dates",
      "label": "America/Sao_Paulo 2018: fall back, first 23:30 (2018-02-17)",
      "value": "2018-02-18T01:30:00.000Z",
      "why": "Clocks fall back from 00:00 to 23:00, so 23:30 happens twice; this is the first one (UTC-02:00). Parsing the local time picks one of the two.",
      "tags": [
        "dst",
        "overlap",
        "ambiguous",
        "timezone"
      ],
      "zone": "America/Sao_Paulo"
    },
    {
      "generator": "dates",
      "label": "America/Sao_Paulo 2018: fall back, second 23:30 (2018-02-17)",
      "value": "2018-02-18T02:30:00.000Z",
      "why": "Same wall clock reading as the first 23:30, 60 minutes later (UTC-03:00); sorting or deduplicating by local time breaks and that local day is 25 hours long.",
      "tags": [
        "dst",
        "overlap",
        "ambiguous",
        "timezone"
      ],
      "zone": "America/Sao_Paulo"
    },
    {
      "generator": "dates",
      "label": "America/Sao_Paulo 2018: 1 ms before spring forward (2018-11-03 23:59 local)",
      "value": "2018-11-04T02:59:59.999Z",
      "why": "Last instant before clocks jump from 00:00 to 01:00 (UTC-03:00 to UTC-02:00); adding 60 minutes of wall time here is not 60 minutes of real time.",
      "tags": [
        "dst",
        "gap",
        "timezone"
      ],
      "zone": "America/Sao_Paulo"
    },
    {
      "generator": "dates",
      "label": "America/Sao_Paulo 2018: spring forward (2018-11-04 01:00 local)",
      "value": "2018-11-04T03:00:00.000Z",
      "why": "Clocks jump from 00:00 to 01:00; local times in between do not exist, so building a Date from local fields shifts it and that local day is 23 hours long. Midnight does not exist that day, so new Date(2018, 10, 4) returns 01:00.",
      "tags": [
        "dst",
        "gap",
        "timezone"
      ],
      "zone": "America/Sao_Paulo"
    },
    {
      "generator": "dates",
      "label": "America/Sao_Paulo: last instant of 2017 local time",
      "value": "2018-01-01T01:59:59.999Z",
      "why": "Local time is 2017-12-31 23:59:59.999 (UTC-02:00) but the UTC year is already 2018; a year check with getUTCFullYear() is off by one.",
      "tags": [
        "year-boundary",
        "timezone"
      ],
      "zone": "America/Sao_Paulo",
      "ref": "https://github.com/github/relative-time-element/pull/384"
    },
    {
      "generator": "dates",
      "label": "Europe/London 2026: 1 ms before spring forward (2026-03-29 00:59 local)",
      "value": "2026-03-29T00:59:59.999Z",
      "why": "Last instant before clocks jump from 01:00 to 02:00 (UTC+00:00 to UTC+01:00); adding 60 minutes of wall time here is not 60 minutes of real time.",
      "tags": [
        "dst",
        "gap",
        "timezone"
      ],
      "zone": "Europe/London"
    },
    {
      "generator": "dates",
      "label": "Europe/London 2026: spring forward (2026-03-29 02:00 local)",
      "value": "2026-03-29T01:00:00.000Z",
      "why": "Clocks jump from 01:00 to 02:00; local times in between do not exist, so building a Date from local fields shifts it and that local day is 23 hours long.",
      "tags": [
        "dst",
        "gap",
        "timezone"
      ],
      "zone": "Europe/London"
    },
    {
      "generator": "dates",
      "label": "Europe/London 2026: fall back, first 01:30 (2026-10-25)",
      "value": "2026-10-25T00:30:00.000Z",
      "why": "Clocks fall back from 02:00 to 01:00, so 01:30 happens twice; this is the first one (UTC+01:00). Parsing the local time picks one of the two.",
      "tags": [
        "dst",
        "overlap",
        "ambiguous",
        "timezone"
      ],
      "zone": "Europe/London"
    },
    {
      "generator": "dates",
      "label": "Europe/London 2026: fall back, second 01:30 (2026-10-25)",
      "value": "2026-10-25T01:30:00.000Z",
      "why": "Same wall clock reading as the first 01:30, 60 minutes later (UTC+00:00); sorting or deduplicating by local time breaks and that local day is 25 hours long.",
      "tags": [
        "dst",
        "overlap",
        "ambiguous",
        "timezone"
      ],
      "zone": "Europe/London"
    },
    {
      "generator": "dates",
      "label": "Australia/Lord_Howe 2026: fall back, first 01:45 (2026-04-05)",
      "value": "2026-04-04T14:45:00.000Z",
      "why": "Clocks fall back from 02:00 to 01:30, so 01:45 happens twice; this is the first one (UTC+11:00). Parsing the local time picks one of the two.",
      "tags": [
        "dst",
        "overlap",
        "ambiguous",
        "timezone",
        "unusual-dst"
      ],
      "zone": "Australia/Lord_Howe"
    },
    {
      "generator": "dates",
      "label": "Australia/Lord_Howe 2026: fall back, second 01:45 (2026-04-05)",
      "value": "2026-04-04T15:15:00.000Z",
      "why": "Same wall clock reading as the first 01:45, 30 minutes later (UTC+10:30); sorting or deduplicating by local time breaks and that local day is 24.5 hours long.",
      "tags": [
        "dst",
        "overlap",
        "ambiguous",
        "timezone",
        "unusual-dst"
      ],
      "zone": "Australia/Lord_Howe"
    },
    {
      "generator": "dates",
      "label": "Australia/Lord_Howe 2026: 1 ms before spring forward (2026-10-04 01:59 local)",
      "value": "2026-10-03T15:29:59.999Z",
      "why": "Last instant before clocks jump from 02:00 to 02:30 (UTC+10:30 to UTC+11:00); adding 30 minutes of wall time here is not 30 minutes of real time.",
      "tags": [
        "dst",
        "gap",
        "timezone",
        "unusual-dst"
      ],
      "zone": "Australia/Lord_Howe"
    },
    {
      "generator": "dates",
      "label": "Australia/Lord_Howe 2026: spring forward (2026-10-04 02:30 local)",
      "value": "2026-10-03T15:30:00.000Z",
      "why": "Clocks jump from 02:00 to 02:30; local times in between do not exist, so building a Date from local fields shifts it and that local day is 23.5 hours long.",
      "tags": [
        "dst",
        "gap",
        "timezone",
        "unusual-dst"
      ],
      "zone": "Australia/Lord_Howe"
    },
    {
      "generator": "dates",
      "label": "Australia/Lord_Howe: first instant of 2026 local time",
      "value": "2025-12-31T13:00:00.000Z",
      "why": "Local time is 2026-01-01 00:00 (UTC+11:00) but the UTC year is still 2025; a year check with getUTCFullYear() is off by one.",
      "tags": [
        "year-boundary",
        "timezone"
      ],
      "zone": "Australia/Lord_Howe",
      "ref": "https://github.com/github/relative-time-element/pull/384"
    },
    {
      "generator": "dates",
      "label": "Asia/Kathmandu: first instant of 2026 local time",
      "value": "2025-12-31T18:15:00.000Z",
      "why": "Local time is 2026-01-01 00:00 (UTC+05:45) but the UTC year is still 2025; a year check with getUTCFullYear() is off by one.",
      "tags": [
        "year-boundary",
        "timezone",
        "fractional-offset"
      ],
      "zone": "Asia/Kathmandu",
      "ref": "https://github.com/github/relative-time-element/pull/384"
    },
    {
      "generator": "dates",
      "label": "Pacific/Kiritimati: first instant of 2026 local time",
      "value": "2025-12-31T10:00:00.000Z",
      "why": "Local time is 2026-01-01 00:00 (UTC+14:00) but the UTC year is still 2025; a year check with getUTCFullYear() is off by one. This zone is among the first places on Earth to enter the new year.",
      "tags": [
        "year-boundary",
        "timezone"
      ],
      "zone": "Pacific/Kiritimati",
      "ref": "https://github.com/github/relative-time-element/pull/384"
    },
    {
      "generator": "dates",
      "label": "Pacific/Pago_Pago: last instant of 2025 local time",
      "value": "2026-01-01T10:59:59.999Z",
      "why": "Local time is 2025-12-31 23:59:59.999 (UTC-11:00) but the UTC year is already 2026; a year check with getUTCFullYear() is off by one. This zone is among the last places on Earth to leave the old year.",
      "tags": [
        "year-boundary",
        "timezone"
      ],
      "zone": "Pacific/Pago_Pago",
      "ref": "https://github.com/github/relative-time-element/pull/384"
    },
    {
      "generator": "timeZones",
      "label": "UTC",
      "value": "\"UTC\"",
      "why": "The control zone: offset 0 all year. Bugs that only show up away from UTC hide here, which is why CI should not run only in UTC.",
      "tags": [
        "utc",
        "control"
      ]
    },
    {
      "generator": "timeZones",
      "label": "America/New_York",
      "value": "\"America/New_York\"",
      "why": "UTC-05:00 with US DST rules: the classic negative offset where UTC midnight is the previous local day.",
      "tags": [
        "negative",
        "dst"
      ]
    },
    {
      "generator": "timeZones",
      "label": "America/Los_Angeles",
      "value": "\"America/Los_Angeles\"",
      "why": "UTC-08:00: late enough that evening events land on the next UTC day.",
      "tags": [
        "negative",
        "dst"
      ]
    },
    {
      "generator": "timeZones",
      "label": "America/Sao_Paulo",
      "value": "\"America/Sao_Paulo\"",
      "why": "UTC-03:00; used DST with midnight transitions until 2019, so historical dates have days without 00:00.",
      "tags": [
        "negative",
        "historical-dst",
        "midnight-dst"
      ]
    },
    {
      "generator": "timeZones",
      "label": "America/St_Johns",
      "value": "\"America/St_Johns\"",
      "why": "UTC-03:30: a half hour offset with DST in the Americas; code that assumes whole hours breaks.",
      "tags": [
        "negative",
        "fractional-offset",
        "dst"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Europe/London",
      "value": "\"Europe/London\"",
      "why": "UTC+00:00 in winter but +01:00 in summer: tests that pass in January fail in July.",
      "tags": [
        "dst",
        "zero-offset"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Europe/Dublin",
      "value": "\"Europe/Dublin\"",
      "why": "The tz database models Irish time with a negative DST save (standard time in summer), which trips code that reads the isDST flag of tz libraries.",
      "tags": [
        "dst",
        "zero-offset"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Africa/Casablanca",
      "value": "\"Africa/Casablanca\"",
      "why": "UTC+01:00 that drops to +00:00 during Ramadan each year, so transitions move with the lunar calendar.",
      "tags": [
        "dst",
        "irregular"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Asia/Kolkata",
      "value": "\"Asia/Kolkata\"",
      "why": "UTC+05:30, no DST: the most populous half hour offset.",
      "tags": [
        "positive",
        "fractional-offset"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Asia/Kathmandu",
      "value": "\"Asia/Kathmandu\"",
      "why": "UTC+05:45: a quarter hour offset that breaks `offset / 60` rounding and hour only offset pickers.",
      "tags": [
        "positive",
        "fractional-offset"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Asia/Tehran",
      "value": "\"Asia/Tehran\"",
      "why": "UTC+03:30; abolished DST in 2022, so historical and current rules differ.",
      "tags": [
        "positive",
        "fractional-offset",
        "historical-dst"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Australia/Adelaide",
      "value": "\"Australia/Adelaide\"",
      "why": "UTC+09:30 / +10:30: southern hemisphere DST plus a half hour offset.",
      "tags": [
        "positive",
        "fractional-offset",
        "dst",
        "southern"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Australia/Lord_Howe",
      "value": "\"Australia/Lord_Howe\"",
      "why": "UTC+10:30 / +11:00: DST shifts by only 30 minutes, so \"DST adds one hour\" is false.",
      "tags": [
        "positive",
        "fractional-offset",
        "dst",
        "unusual-dst",
        "southern"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Pacific/Chatham",
      "value": "\"Pacific/Chatham\"",
      "why": "UTC+12:45 / +13:45: quarter hour offset with DST, far east of the date line.",
      "tags": [
        "positive",
        "fractional-offset",
        "dst",
        "southern"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Pacific/Kiritimati",
      "value": "\"Pacific/Kiritimati\"",
      "why": "UTC+14:00, the largest offset: local dates are a full day ahead of most of the Americas and the first to reach New Year.",
      "tags": [
        "positive",
        "extreme"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Pacific/Apia",
      "value": "\"Pacific/Apia\"",
      "why": "Samoa skipped 2011-12-30 entirely when it moved across the date line; day counting across that date is off by one.",
      "tags": [
        "positive",
        "historical",
        "skipped-day"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Pacific/Pago_Pago",
      "value": "\"Pacific/Pago_Pago\"",
      "why": "UTC-11:00, among the last places to leave a year; local dates lag a day behind most of Asia.",
      "tags": [
        "negative",
        "extreme"
      ]
    },
    {
      "generator": "timeZones",
      "label": "Antarctica/Troll",
      "value": "\"Antarctica/Troll\"",
      "why": "UTC+00:00 in winter and +02:00 in summer: a two hour DST jump.",
      "tags": [
        "dst",
        "unusual-dst"
      ]
    },
    {
      "generator": "strings",
      "label": "empty string",
      "value": "\"\"",
      "why": "Falsy, length 0: `if (!name)` and `str[0].toUpperCase()` both misbehave.",
      "tags": [
        "empty",
        "falsy"
      ]
    },
    {
      "generator": "strings",
      "label": "single space",
      "value": "\" \"",
      "why": "Truthy but blank: passes `if (str)` checks and fails after trim().",
      "tags": [
        "whitespace",
        "blank"
      ]
    },
    {
      "generator": "strings",
      "label": "mixed ASCII whitespace",
      "value": "\" \\t\\n\\r\\u000B\\u000C \"",
      "why": "Every ASCII whitespace character; trim() returns an empty string but `str.length > 0` validators accept it.",
      "tags": [
        "whitespace",
        "blank"
      ]
    },
    {
      "generator": "strings",
      "label": "no-break space (U+00A0)",
      "value": "\"a\\u00A0b\"",
      "why": "Arrives from HTML &nbsp; and copy paste; \\s and trim() treat it as whitespace but split(\" \") and many tokenizers do not.",
      "tags": [
        "whitespace",
        "invisible"
      ]
    },
    {
      "generator": "strings",
      "label": "ideographic space (U+3000)",
      "value": "\"\\u3000\\u65E5\\u672C\\u3000\"",
      "why": "Full width space used in CJK text; trim() removes it, byte based or ASCII only trimming does not.",
      "tags": [
        "whitespace",
        "cjk"
      ]
    },
    {
      "generator": "strings",
      "label": "zero width space (U+200B)",
      "value": "\"foo\\u200Bbar\"",
      "why": "Invisible and not whitespace for trim() or \\s, so it looks identical to \"foobar\" but is not equal to it.",
      "tags": [
        "invisible",
        "zero-width"
      ]
    },
    {
      "generator": "strings",
      "label": "byte order mark prefix (U+FEFF)",
      "value": "\"\\uFEFFid\"",
      "why": "Left by Windows editors at the start of files: CSV headers become \"\\uFEFFid\" and JSON.parse of BOM prefixed text throws.",
      "tags": [
        "invisible",
        "bom"
      ]
    },
    {
      "generator": "strings",
      "label": "soft hyphen (U+00AD)",
      "value": "\"co\\u00ADoperate\"",
      "why": "Invisible unless a line breaks there, so search and equality fail on text that looks the same.",
      "tags": [
        "invisible"
      ]
    },
    {
      "generator": "strings",
      "label": "very long string (100000 chars)",
      "value": "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...\" (100000 chars)",
      "why": "Exceeds column and header limits, overflows layouts and exposes quadratic algorithms and backtracking regexes.",
      "tags": [
        "long"
      ]
    },
    {
      "generator": "strings",
      "label": "emoji outside the BMP (U+1F600)",
      "value": "\"\\u{1F600}\"",
      "why": "One visible character but length 2 (a surrogate pair); charAt(0) and str[0] return half of it.",
      "tags": [
        "emoji",
        "surrogate",
        "grapheme"
      ]
    },
    {
      "generator": "strings",
      "label": "ZWJ family emoji (man, woman, girl, boy)",
      "value": "\"\\u{1F468}\\u200D\\u{1F469}\\u200D\\u{1F467}\\u200D\\u{1F466}\"",
      "why": "Seven code points joined by zero width joiners render as one glyph with length 11; splitting by code point shows four people.",
      "tags": [
        "emoji",
        "zwj",
        "grapheme",
        "surrogate"
      ]
    },
    {
      "generator": "strings",
      "label": "flag emoji (regional indicators B and R)",
      "value": "\"\\u{1F1E7}\\u{1F1F7}\"",
      "why": "A flag is two regional indicator letters; cutting between them leaves letters and reversing them names another country or none.",
      "tags": [
        "emoji",
        "grapheme",
        "surrogate"
      ]
    },
    {
      "generator": "strings",
      "label": "skin tone modifier (thumbs up, medium)",
      "value": "\"\\u{1F44D}\\u{1F3FD}\"",
      "why": "Base emoji plus a modifier: one grapheme, two code points, four code units; truncating after the base drops the tone.",
      "tags": [
        "emoji",
        "grapheme",
        "surrogate"
      ]
    },
    {
      "generator": "strings",
      "label": "emoji with variation selector (red heart)",
      "value": "\"\\u2764\\uFE0F\"",
      "why": "U+2764 plus U+FE0F: removing \"invisible\" characters changes emoji presentation, and the base alone is in the BMP.",
      "tags": [
        "emoji",
        "variation-selector",
        "grapheme"
      ]
    },
    {
      "generator": "strings",
      "label": "keycap sequence (digit one)",
      "value": "\"1\\uFE0F\\u20E3\"",
      "why": "Starts with an ASCII digit, so /^\\d/ matches what renders as a single keycap symbol.",
      "tags": [
        "emoji",
        "grapheme",
        "digits"
      ]
    },
    {
      "generator": "strings",
      "label": "surrogate pair cut by slice(0, 10)",
      "value": "\"abcdefghi\\u{1F600}\"",
      "why": "The emoji starts at index 9, so slice(0, 10) keeps only its high surrogate and produces malformed UTF-16.",
      "tags": [
        "surrogate",
        "truncation",
        "emoji"
      ],
      "ref": "https://github.com/google/budoux/pull/1411"
    },
    {
      "generator": "strings",
      "label": "surrogate pair at the end for trimEnd style truncation",
      "value": "\"Done \\u{1F389}\"",
      "why": "Truncating \"to N code units\" from the end lands inside the pair; output ends in a lone surrogate that renders as U+FFFD.",
      "tags": [
        "surrogate",
        "truncation",
        "emoji"
      ],
      "ref": "https://github.com/microsoft/vscode-js-debug/pull/2423"
    },
    {
      "generator": "strings",
      "label": "lone high surrogate",
      "value": "\"a\\uD83Db\"",
      "why": "Malformed UTF-16: encodeURIComponent throws URIError, TextEncoder writes U+FFFD and isWellFormed() is false.",
      "tags": [
        "surrogate",
        "malformed"
      ]
    },
    {
      "generator": "strings",
      "label": "lone low surrogate",
      "value": "\"\\uDE00\"",
      "why": "A trailing surrogate with no lead: string comparison works but encoding, hashing and JSON round trips through UTF-8 change it.",
      "tags": [
        "surrogate",
        "malformed"
      ]
    },
    {
      "generator": "strings",
      "label": "precomposed e acute (NFC)",
      "value": "\"caf\\u00E9\"",
      "why": "Length 4. Compare with the decomposed form: same rendering, different code points.",
      "tags": [
        "normalization",
        "combining"
      ]
    },
    {
      "generator": "strings",
      "label": "decomposed e acute (NFD)",
      "value": "\"cafe\\u0301\"",
      "why": "Length 5 and !== the NFC form; macOS file names and some keyboards produce this form. Use normalize() before comparing.",
      "tags": [
        "normalization",
        "combining"
      ]
    },
    {
      "generator": "strings",
      "label": "stacked combining marks",
      "value": "\"Z\\u0351\\u036B\\u0343\\u036A\\u0302\\u036B\\u033D\\u034F\\u0334\\u0319\"",
      "why": "One base letter with ten combining marks: one grapheme, eleven code units, and rendering that escapes its line box.",
      "tags": [
        "combining",
        "grapheme"
      ]
    },
    {
      "generator": "strings",
      "label": "leading combining mark",
      "value": "\"\\u0301abc\"",
      "why": "A combining mark with nothing to attach to; it combines with whatever precedes the string after concatenation.",
      "tags": [
        "combining"
      ]
    },
    {
      "generator": "strings",
      "label": "Hangul syllables (precomposed)",
      "value": "\"\\uD55C\\uAD6D\\uC5B4\"",
      "why": "Korean syllable blocks. NFD splits each into two or three jamo, so lengths change after normalization.",
      "tags": [
        "script",
        "normalization",
        "cjk"
      ]
    },
    {
      "generator": "strings",
      "label": "Hangul jamo (decomposed)",
      "value": "\"\\u1112\\u1161\\u11AB\"",
      "why": "Three jamo that render as one syllable and equal the first syllable of the previous case only after NFC normalization.",
      "tags": [
        "script",
        "normalization",
        "combining"
      ]
    },
    {
      "generator": "strings",
      "label": "right to left text mixed with Latin and digits",
      "value": "\"abc \\u05E9\\u05DC\\u05D5\\u05DD 123\"",
      "why": "Hebrew mixed with Latin and numbers: visual order differs from memory order, which breaks cursor math and naive truncation with ellipsis.",
      "tags": [
        "rtl",
        "bidi",
        "script"
      ]
    },
    {
      "generator": "strings",
      "label": "Arabic text",
      "value": "\"\\u0645\\u0631\\u062D\\u0628\\u0627\"",
      "why": "Right to left script with contextual letter shapes; per code point styling or splitting breaks the joining.",
      "tags": [
        "rtl",
        "script"
      ]
    },
    {
      "generator": "strings",
      "label": "right to left override (U+202E)",
      "value": "\"invoice\\u202Etxt.exe\"",
      "why": "Displays as \"invoiceexe.txt\": the Trojan Source trick (CVE-2021-42574) for file names and code review.",
      "tags": [
        "bidi",
        "security",
        "invisible"
      ]
    },
    {
      "generator": "strings",
      "label": "bidi isolate controls (U+2067, U+2069)",
      "value": "\"user\\u2067admin\\u2069\"",
      "why": "Invisible directional isolates change display order; strip or escape them in identifiers and logs.",
      "tags": [
        "bidi",
        "invisible",
        "security"
      ]
    },
    {
      "generator": "strings",
      "label": "Turkish dotted and dotless i",
      "value": "\"I\\u0130\\u0131i\"",
      "why": "Capital dotted I lowercases to i plus U+0307 (length grows), and toLocaleLowerCase(\"tr\") maps I to dotless i; case insensitive keys break.",
      "tags": [
        "casing",
        "locale"
      ]
    },
    {
      "generator": "strings",
      "label": "German sharp s",
      "value": "\"stra\\u00DFe\"",
      "why": "toUpperCase() gives \"STRASSE\" (length 6 to 7), so upper and lower case comparisons disagree and length based layouts shift.",
      "tags": [
        "casing",
        "locale"
      ]
    },
    {
      "generator": "strings",
      "label": "Greek final sigma",
      "value": "\"\\u039F\\u0394\\u039F\\u03A3\"",
      "why": "Lowercasing the whole word yields a final sigma at the end; lowercasing letter by letter does not, so results differ.",
      "tags": [
        "casing",
        "script"
      ]
    },
    {
      "generator": "strings",
      "label": "null character",
      "value": "\"a\\u0000b\"",
      "why": "Terminates C strings, is rejected by PostgreSQL text columns and disappears in some loggers.",
      "tags": [
        "control",
        "null"
      ]
    },
    {
      "generator": "strings",
      "label": "CRLF newline",
      "value": "\"line1\\r\\nline2\"",
      "why": "split(\"\\n\") leaves a trailing \"\\r\" on each line; Windows files and HTTP headers use this form.",
      "tags": [
        "newline"
      ]
    },
    {
      "generator": "strings",
      "label": "CR only newline",
      "value": "\"line1\\rline2\"",
      "why": "Classic Mac line ending: code that only looks for \\n sees one line.",
      "tags": [
        "newline"
      ]
    },
    {
      "generator": "strings",
      "label": "line separator (U+2028)",
      "value": "\"a\\u2028b\"",
      "why": "A JavaScript line terminator: `.` in a regex does not match it, and it broke inline scripts and JSONP before ES2019.",
      "tags": [
        "newline",
        "invisible"
      ]
    },
    {
      "generator": "strings",
      "label": "paragraph separator (U+2029)",
      "value": "\"a\\u2029b\"",
      "why": "Another JavaScript line terminator that most text editors render as nothing; line counting tools disagree about it.",
      "tags": [
        "newline",
        "invisible"
      ]
    },
    {
      "generator": "strings",
      "label": "vertical tab and form feed",
      "value": "\"a\\u000Bb\\u000Cc\"",
      "why": "Rarely seen whitespace that XML 1.0 forbids and some JSON encoders escape inconsistently.",
      "tags": [
        "control",
        "whitespace"
      ]
    },
    {
      "generator": "strings",
      "label": "HTML markup as text",
      "value": "\"<script>alert(\\\"x\\\")</script>\"",
      "why": "Must render as literal text; any innerHTML or template without escaping executes it.",
      "tags": [
        "injection",
        "html"
      ]
    },
    {
      "generator": "strings",
      "label": "already escaped HTML",
      "value": "\"&lt;b&gt; &amp;amp;\"",
      "why": "Escaping twice shows \"&amp;lt;\" to users; unescaping on input then escaping on output corrupts it.",
      "tags": [
        "injection",
        "html"
      ]
    },
    {
      "generator": "strings",
      "label": "SQL quote and comment",
      "value": "\"Robert'); DROP TABLE Students;--\"",
      "why": "A quote ends a string literal in hand built SQL; also tests that names with apostrophes survive a round trip.",
      "tags": [
        "injection",
        "sql"
      ]
    },
    {
      "generator": "strings",
      "label": "regex metacharacters",
      "value": "\".*+?^${}()|[]\\\\\"",
      "why": "Passing user text to new RegExp() throws on \"(\" or matches everything with \".*\"; escape it first.",
      "tags": [
        "injection",
        "regex"
      ]
    },
    {
      "generator": "strings",
      "label": "template placeholders",
      "value": "\"${7*7} {{7*7}} %s %d\"",
      "why": "Text that looks like template or printf syntax; any second pass through a formatter changes it.",
      "tags": [
        "injection",
        "template"
      ]
    },
    {
      "generator": "strings",
      "label": "__proto__ as a key",
      "value": "\"__proto__\"",
      "why": "Used as an object key it sets the prototype instead of a property; use Map or Object.create(null) for user keys.",
      "tags": [
        "injection",
        "prototype"
      ]
    },
    {
      "generator": "strings",
      "label": "the word null",
      "value": "\"null\"",
      "why": "A real surname and a common placeholder: systems that treat \"null\" as missing lose data.",
      "tags": [
        "falsy-text"
      ]
    },
    {
      "generator": "strings",
      "label": "Arabic-Indic digits",
      "value": "\"\\u0663\\u0664\"",
      "why": "Unicode digits: Number() and parseInt return NaN and \\d only matches ASCII 0 to 9, yet users type these.",
      "tags": [
        "digits",
        "rtl"
      ]
    },
    {
      "generator": "strings",
      "label": "full width digits",
      "value": "\"\\uFF11\\uFF12\\uFF13\"",
      "why": "Typed by CJK input methods; look like 123 but fail /^\\d+$/ and Number().",
      "tags": [
        "digits",
        "cjk"
      ]
    },
    {
      "generator": "strings",
      "label": "Thai without spaces",
      "value": "\"\\u0E20\\u0E32\\u0E29\\u0E32\\u0E44\\u0E17\\u0E22\"",
      "why": "Thai writes words without spaces and uses combining vowels; word wrapping and counting need Intl.Segmenter.",
      "tags": [
        "script",
        "combining"
      ]
    },
    {
      "generator": "strings",
      "label": "wide CJK characters",
      "value": "\"\\u4F60\\u597D\\uFF01\"",
      "why": "Each character takes two terminal columns, so padEnd based tables and fixed width output misalign.",
      "tags": [
        "cjk",
        "script"
      ]
    },
    {
      "generator": "numbers",
      "label": "zero",
      "value": "0",
      "why": "Falsy: `if (!count)` and `value || defaultValue` replace a legitimate 0.",
      "tags": [
        "zero",
        "falsy"
      ]
    },
    {
      "generator": "numbers",
      "label": "negative zero",
      "value": "-0",
      "why": "-0 === 0 is true, but Object.is(-0, 0) is false, 1 / -0 is -Infinity and String(-0) is \"0\", so the sign silently disappears.",
      "tags": [
        "zero",
        "negative",
        "sign"
      ]
    },
    {
      "generator": "numbers",
      "label": "NaN",
      "value": "NaN",
      "why": "NaN !== NaN, indexOf cannot find it, JSON.stringify writes null and every comparison is false, so sorting with it is unstable.",
      "tags": [
        "nan",
        "falsy"
      ]
    },
    {
      "generator": "numbers",
      "label": "Infinity",
      "value": "Infinity",
      "why": "JSON.stringify writes null, toFixed returns \"Infinity\" and a max-age or timeout of Infinity can mean \"never\" or overflow a timer.",
      "tags": [
        "infinity"
      ],
      "ref": "https://github.com/salesforce/tough-cookie/pull/644"
    },
    {
      "generator": "numbers",
      "label": "-Infinity",
      "value": "-Infinity",
      "why": "Math.max() of an empty list; a common reducer seed that leaks into output as \"-Infinity\".",
      "tags": [
        "infinity",
        "negative"
      ]
    },
    {
      "generator": "numbers",
      "label": "MAX_SAFE_INTEGER",
      "value": "9007199254740991",
      "why": "2^53 - 1, the largest integer where n + 1 is exact; IDs and counters past it stop being unique.",
      "tags": [
        "integer",
        "limit"
      ]
    },
    {
      "generator": "numbers",
      "label": "MAX_SAFE_INTEGER + 1",
      "value": "9007199254740992",
      "why": "2^53: here n + 1 === n, so loops never advance and 64 bit IDs from JSON collide.",
      "tags": [
        "integer",
        "limit",
        "precision"
      ]
    },
    {
      "generator": "numbers",
      "label": "MAX_SAFE_INTEGER + 2",
      "value": "9007199254740992",
      "why": "Is not representable: the literal 9007199254740993 rounds to 9007199254740992 before your code ever sees it.",
      "tags": [
        "integer",
        "limit",
        "precision"
      ]
    },
    {
      "generator": "numbers",
      "label": "MIN_SAFE_INTEGER",
      "value": "-9007199254740991",
      "why": "-(2^53 - 1), the negative safe integer limit; mirrors the positive overflow bugs.",
      "tags": [
        "integer",
        "limit",
        "negative"
      ]
    },
    {
      "generator": "numbers",
      "label": "MIN_SAFE_INTEGER - 1",
      "value": "-9007199254740992",
      "why": "First unsafe negative integer: Number.isSafeInteger is false and decrementing it is not exact.",
      "tags": [
        "integer",
        "limit",
        "negative",
        "precision"
      ]
    },
    {
      "generator": "numbers",
      "label": "MAX_VALUE",
      "value": "1.7976931348623157e+308",
      "why": "Largest finite double; doubling it or adding a large value gives Infinity.",
      "tags": [
        "limit",
        "overflow"
      ]
    },
    {
      "generator": "numbers",
      "label": "MIN_VALUE",
      "value": "5e-324",
      "why": "Smallest positive double (5e-324), not the most negative number; code that uses it as \"minus infinity\" is wrong.",
      "tags": [
        "limit",
        "subnormal"
      ]
    },
    {
      "generator": "numbers",
      "label": "EPSILON",
      "value": "2.220446049250313e-16",
      "why": "Gap between 1 and the next double; only meaningful as a tolerance near 1, not for large or tiny values.",
      "tags": [
        "limit",
        "precision"
      ]
    },
    {
      "generator": "numbers",
      "label": "2^32",
      "value": "4294967296",
      "why": "Breaks `x | 0` and `x >>> 0` truncation, array index limits and 32 bit counters.",
      "tags": [
        "integer",
        "overflow"
      ]
    },
    {
      "generator": "numbers",
      "label": "2^31",
      "value": "2147483648",
      "why": "Overflows signed 32 bit math: `(2 ** 31) | 0` is -2147483648.",
      "tags": [
        "integer",
        "overflow"
      ]
    },
    {
      "generator": "numbers",
      "label": "-0.5",
      "value": "-0.5",
      "why": "Between -1 and 0: Math.trunc gives -0, Math.round gives -0, and code that formats the integer part then the fraction drops the minus sign.",
      "tags": [
        "negative",
        "sign",
        "fraction"
      ],
      "ref": "https://github.com/mozilla/pdf.js/pull/22017"
    },
    {
      "generator": "numbers",
      "label": "-0.0001",
      "value": "-0.0001",
      "why": "A small negative between -1 and 0: formatting with toFixed(2) gives \"-0.00\", and splitting into integer and fraction parts loses the sign.",
      "tags": [
        "negative",
        "sign",
        "fraction"
      ],
      "ref": "https://github.com/mozilla/pdf.js/pull/22017"
    },
    {
      "generator": "numbers",
      "label": "-1e-7",
      "value": "-1e-7",
      "why": "Very small negative: String() gives \"-1e-7\", so string based number formatting and regexes for digits fail.",
      "tags": [
        "negative",
        "exponent",
        "fraction"
      ]
    },
    {
      "generator": "numbers",
      "label": "1e-7",
      "value": "1e-7",
      "why": "Smallest magnitude where String() switches to exponent notation (\"1e-7\"), while 0.000001 still prints in full.",
      "tags": [
        "exponent",
        "fraction"
      ]
    },
    {
      "generator": "numbers",
      "label": "0.1 + 0.2",
      "value": "0.30000000000000004",
      "why": "0.30000000000000004, not 0.3: exact equality on money and percentages fails; compare with a tolerance or use integers.",
      "tags": [
        "float",
        "precision"
      ]
    },
    {
      "generator": "numbers",
      "label": "1.005",
      "value": "1.005",
      "why": "Stored as 1.00499999999999989..., so (1.005).toFixed(2) is \"1.00\" and Math.round(1.005 * 100) / 100 is 1.",
      "tags": [
        "float",
        "rounding"
      ]
    },
    {
      "generator": "numbers",
      "label": "0.5 (round half)",
      "value": "0.5",
      "why": "Math.round(0.5) is 1 but Math.round(-0.5) is -0 and toFixed uses a different rule: half rounding is not symmetric.",
      "tags": [
        "float",
        "rounding"
      ]
    },
    {
      "generator": "numbers",
      "label": "1e21",
      "value": "1e+21",
      "why": "First integer where String() uses exponent notation (\"1e+21\"); toFixed also falls back to exponent form, breaking digit only checks.",
      "tags": [
        "exponent",
        "integer"
      ]
    },
    {
      "generator": "numbers",
      "label": "999999999999999900000",
      "value": "999999999999999900000",
      "why": "Largest round number below 1e21 that still prints all its digits; one step up the format changes.",
      "tags": [
        "exponent",
        "integer"
      ]
    },
    {
      "generator": "numbers",
      "label": "negative integer",
      "value": "-42",
      "why": "Modulo keeps the sign (-42 % 5 is -2), so \"positive modulo\" wraparound for indexes and calendars is wrong.",
      "tags": [
        "negative",
        "integer"
      ]
    },
    {
      "generator": "numbers",
      "label": "non-integer array index",
      "value": "1.5",
      "why": "arr[1.5] is undefined and creates a string property on write; Number.isInteger guards are often missing.",
      "tags": [
        "fraction"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "empty string",
      "value": "\"\"",
      "why": "Number(\"\") is 0, not NaN, so empty form fields become zero.",
      "tags": [
        "empty",
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "whitespace only",
      "value": "\"  \\n\\t \"",
      "why": "Number(\"  \") is 0 as well; parseFloat returns NaN, so the two parsers disagree.",
      "tags": [
        "whitespace",
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "padded number",
      "value": "\"  42  \"",
      "why": "Number trims whitespace and accepts it; strict validators and parseInt with a regex may not.",
      "tags": [
        "whitespace"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "negative zero string",
      "value": "\"-0\"",
      "why": "Number(\"-0\") is -0, which then prints as \"0\"; round trips lose the sign.",
      "tags": [
        "sign",
        "zero"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "leading zeros",
      "value": "\"007\"",
      "why": "Decimal 7 for Number and parseInt, but octal in some legacy parsers and a string ID that must keep its zeros.",
      "tags": [
        "leading-zero"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "hex string",
      "value": "\"0x1A\"",
      "why": "Number(\"0x1A\") is 26 and parseInt(\"0x1A\") is 26, but parseFloat(\"0x1A\") is 0.",
      "tags": [
        "radix",
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "binary and octal prefixes",
      "value": "\"0b101\"",
      "why": "Number(\"0b101\") is 5 while parseInt(\"0b101\") is 0; prefixes are accepted by one parser only.",
      "tags": [
        "radix",
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "exponent notation",
      "value": "\"1e3\"",
      "why": "Number gives 1000 but parseInt gives 1, so \"digits only\" assumptions break.",
      "tags": [
        "exponent",
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "trailing garbage",
      "value": "\"12px\"",
      "why": "parseInt and parseFloat return 12, Number returns NaN; lenient parsing hides bad input.",
      "tags": [
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "comma decimal separator",
      "value": "\"1,5\"",
      "why": "Decimal comma used in most of Europe and Brazil: parseFloat gives 1 and Number gives NaN.",
      "tags": [
        "locale"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "thousands separators",
      "value": "\"1,234,567.89\"",
      "why": "Grouped digits from formatted output; parseFloat stops at the first comma and returns 1.",
      "tags": [
        "locale"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "numeric separator literal",
      "value": "\"1_000\"",
      "why": "Valid in JavaScript source but Number(\"1_000\") is NaN.",
      "tags": [
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "Infinity string",
      "value": "\"Infinity\"",
      "why": "Number(\"Infinity\") is Infinity, so numeric validation accepts a word; JSON cannot represent it.",
      "tags": [
        "infinity",
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "NaN string",
      "value": "\"NaN\"",
      "why": "Number(\"NaN\") is NaN, which passes typeof === \"number\" checks after conversion.",
      "tags": [
        "nan",
        "coercion"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "unsafe integer string",
      "value": "\"9007199254740993\"",
      "why": "Parses to 9007199254740992: IDs from JSON or databases silently change; parse as BigInt or keep as string.",
      "tags": [
        "precision",
        "integer"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "plus sign",
      "value": "\"+5\"",
      "why": "Accepted by Number but rejected by many /^\\d+$/ validators, and vice versa for UI masks.",
      "tags": [
        "sign"
      ]
    },
    {
      "generator": "numericStrings",
      "label": "Arabic-Indic digits",
      "value": "\"\\u0664\\u0662\"",
      "why": "Real digits for many users, but Number returns NaN; normalize with Intl or a digit map first.",
      "tags": [
        "unicode",
        "digits"
      ]
    },
    {
      "generator": "bigints",
      "label": "0n",
      "value": "0n",
      "why": "Falsy like 0, and -0n is just 0n (BigInt has no negative zero), so sign preserving code paths diverge from Number.",
      "tags": [
        "zero",
        "falsy"
      ]
    },
    {
      "generator": "bigints",
      "label": "-1n",
      "value": "-1n",
      "why": "BigInt division truncates toward zero (-1n / 2n is 0n) and % keeps the sign.",
      "tags": [
        "negative"
      ]
    },
    {
      "generator": "bigints",
      "label": "2^53 + 1 (first integer Number cannot hold)",
      "value": "9007199254740993n",
      "why": "Number(2n ** 53n + 1n) rounds to 2^53; converting back to Number for math or JSON loses it.",
      "tags": [
        "precision",
        "number-boundary"
      ]
    },
    {
      "generator": "bigints",
      "label": "int64 max",
      "value": "9223372036854775807n",
      "why": "Largest signed 64 bit integer (PostgreSQL bigint, Java long); one more overflows the column.",
      "tags": [
        "int64",
        "limit"
      ]
    },
    {
      "generator": "bigints",
      "label": "int64 min",
      "value": "-9223372036854775808n",
      "why": "Smallest signed 64 bit integer; its absolute value does not fit in int64.",
      "tags": [
        "int64",
        "limit",
        "negative"
      ]
    },
    {
      "generator": "bigints",
      "label": "uint64 max",
      "value": "18446744073709551615n",
      "why": "Largest unsigned 64 bit integer; BigInt.asIntN(64, n) turns it into -1n.",
      "tags": [
        "uint64",
        "limit"
      ]
    },
    {
      "generator": "bigints",
      "label": "2^64 (overflows uint64)",
      "value": "18446744073709551616n",
      "why": "Wraps to 0n with BigInt.asUintN(64, n); database drivers reject it.",
      "tags": [
        "uint64",
        "overflow"
      ]
    },
    {
      "generator": "bigints",
      "label": "1e30 as BigInt",
      "value": "1000000000000000000000000000000n",
      "why": "Far beyond any Number integer: JSON.stringify throws TypeError for any BigInt, and mixing with Number in + throws.",
      "tags": [
        "large",
        "json"
      ]
    },
    {
      "generator": "urls",
      "label": "localhost with port",
      "value": "\"http://localhost:3000/\"",
      "why": "No dot in the host: \"must contain a TLD\" validators reject development URLs.",
      "tags": [
        "valid",
        "host"
      ]
    },
    {
      "generator": "urls",
      "label": "credentials in URL",
      "value": "\"https://user:p%40ss@example.com/\"",
      "why": "Userinfo with an encoded @; naive parsers split on the first @ and leak or mangle the password.",
      "tags": [
        "valid",
        "userinfo",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "IPv6 host with port",
      "value": "\"http://[::1]:8080/\"",
      "why": "hostname is \"[::1]\" with brackets; splitting host and port on \":\" breaks.",
      "tags": [
        "valid",
        "ip",
        "host"
      ]
    },
    {
      "generator": "urls",
      "label": "shorthand IPv4 (127.1)",
      "value": "\"http://127.1/\"",
      "why": "The parser normalizes it to 127.0.0.1, so SSRF block lists that compare strings miss it.",
      "tags": [
        "valid",
        "ip",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "hex IPv4 (0x7f.0.0.1)",
      "value": "\"http://0x7f.0.0.1/\"",
      "why": "Also loopback after normalization; another SSRF filter bypass.",
      "tags": [
        "valid",
        "ip",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "internationalized domain",
      "value": "\"https://\\u4F8B\\u3048.jp/\"",
      "why": "hostname becomes punycode (\"xn--r8jz45g.jp\"), so comparing the input string with url.hostname fails.",
      "tags": [
        "valid",
        "idn",
        "unicode",
        "host"
      ]
    },
    {
      "generator": "urls",
      "label": "trailing dot in host",
      "value": "\"https://example.com./\"",
      "why": "A fully qualified name that is a different origin from example.com for cookies, CORS and allow lists.",
      "tags": [
        "valid",
        "host"
      ]
    },
    {
      "generator": "urls",
      "label": "uppercase scheme and host",
      "value": "\"HTTPS://EXAMPLE.COM/Path\"",
      "why": "Scheme and host are lowercased but the path keeps its case; string compares of URLs disagree with the parser.",
      "tags": [
        "valid",
        "case"
      ]
    },
    {
      "generator": "urls",
      "label": "explicit default port",
      "value": "\"https://example.com:443/\"",
      "why": "url.port is \"\" because the default port is dropped; code expecting \"443\" breaks.",
      "tags": [
        "valid",
        "port"
      ]
    },
    {
      "generator": "urls",
      "label": "port out of range",
      "value": "\"http://example.com:65536/\"",
      "why": "Ports above 65535 make the URL invalid; regex validators accept any digits.",
      "tags": [
        "invalid",
        "port"
      ]
    },
    {
      "generator": "urls",
      "label": "encoded slash in path",
      "value": "\"https://example.com/a%2Fb\"",
      "why": "Servers and routers disagree on whether %2F is a path separator; decode once at the right layer.",
      "tags": [
        "valid",
        "encoding",
        "path"
      ]
    },
    {
      "generator": "urls",
      "label": "plus and space in query",
      "value": "\"https://example.com/?q=a+b&q=%20c\"",
      "why": "URLSearchParams decodes \"+\" as a space but decodeURIComponent does not; the key also repeats.",
      "tags": [
        "valid",
        "encoding",
        "query"
      ]
    },
    {
      "generator": "urls",
      "label": "double encoded space",
      "value": "\"https://example.com/file%2520name\"",
      "why": "Decoding twice turns %2520 into a space; decoding once gives \"%20\" literally.",
      "tags": [
        "valid",
        "encoding"
      ]
    },
    {
      "generator": "urls",
      "label": "empty fragment",
      "value": "\"https://example.com/#\"",
      "why": "url.hash is \"\" even though href ends with \"#\", so hash based checks see no fragment.",
      "tags": [
        "valid",
        "fragment"
      ]
    },
    {
      "generator": "urls",
      "label": "dot segments in path",
      "value": "\"http://example.com/public/../secret\"",
      "why": "Normalized to /secret by the parser; checks done on the raw string allow traversal.",
      "tags": [
        "valid",
        "path",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "non ASCII path and query",
      "value": "\"https://example.com/\\u{1F600}?q=caf\\u00E9\"",
      "why": "The parser percent encodes both as UTF-8, so href no longer equals the input.",
      "tags": [
        "valid",
        "unicode",
        "encoding"
      ]
    },
    {
      "generator": "urls",
      "label": "very long URL (8000 char path)",
      "value": "\"https://example.com/aaaaaaaaaaaaaaaaaaaa...\" (8020 chars)",
      "why": "Exceeds common 2048 character limits and 8 KB request line limits in proxies and servers.",
      "tags": [
        "valid",
        "long"
      ]
    },
    {
      "generator": "urls",
      "label": "javascript: scheme",
      "value": "\"javascript:alert(1)\"",
      "why": "A valid URL that runs code when used as an href; allow list schemes instead of block listing.",
      "tags": [
        "valid",
        "scheme",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "javascript: with a newline inside",
      "value": "\"java\\nscript:alert(1)\"",
      "why": "The parser removes tabs and newlines, so this is javascript:alert(1); block lists that match the raw string miss it.",
      "tags": [
        "valid",
        "scheme",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "data: URL with HTML",
      "value": "\"data:text/html,<script>alert(1)</script>\"",
      "why": "Valid and executable in some contexts; never forward user supplied data URLs to href or src.",
      "tags": [
        "valid",
        "scheme",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "file URL with Windows drive",
      "value": "\"file:///C:/Windows/win.ini\"",
      "why": "host is empty and pathname is \"/C:/Windows/win.ini\" with a leading slash before the drive letter.",
      "tags": [
        "valid",
        "scheme",
        "windows"
      ]
    },
    {
      "generator": "urls",
      "label": "mailto URL",
      "value": "\"mailto:user@example.com\"",
      "why": "No host at all: url.host is \"\" and url.origin is \"null\".",
      "tags": [
        "valid",
        "scheme"
      ]
    },
    {
      "generator": "urls",
      "label": "surrounding spaces",
      "value": "\"  https://example.com/  \"",
      "why": "The parser strips leading and trailing spaces, so it is valid, but the stored string is not.",
      "tags": [
        "valid",
        "whitespace"
      ]
    },
    {
      "generator": "urls",
      "label": "protocol relative",
      "value": "\"//example.com/path\"",
      "why": "Invalid without a base, but resolves to another host with one: \"starts with /\" open redirect checks pass it.",
      "tags": [
        "invalid",
        "relative",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "backslash relative",
      "value": "\"/\\\\example.com\"",
      "why": "Browsers treat \"\\\" as \"/\" in http URLs, so this resolves to //example.com: a classic open redirect.",
      "tags": [
        "invalid",
        "relative",
        "security"
      ]
    },
    {
      "generator": "urls",
      "label": "bare domain without scheme",
      "value": "\"example.com\"",
      "why": "What users type, but not a URL: new URL throws and links become relative paths.",
      "tags": [
        "invalid",
        "relative"
      ]
    },
    {
      "generator": "urls",
      "label": "space in host",
      "value": "\"http://exa mple.com/\"",
      "why": "Forbidden host code point; new URL throws.",
      "tags": [
        "invalid",
        "host"
      ]
    },
    {
      "generator": "urls",
      "label": "empty string",
      "value": "\"\"",
      "why": "new URL(\"\") throws; optional URL fields must be checked before parsing.",
      "tags": [
        "invalid",
        "empty"
      ]
    },
    {
      "generator": "emails",
      "label": "plus addressing",
      "value": "\"user+tag@example.com\"",
      "why": "Gmail and others deliver it to \"user\"; validators that reject \"+\" lose real users.",
      "tags": [
        "valid",
        "local-part"
      ]
    },
    {
      "generator": "emails",
      "label": "dots in local part",
      "value": "\"first.last@example.com\"",
      "why": "Valid and common; some providers ignore the dots, so deduplication by string misses duplicates.",
      "tags": [
        "valid",
        "local-part"
      ]
    },
    {
      "generator": "emails",
      "label": "apostrophe in local part",
      "value": "\"o'brien@example.com\"",
      "why": "Valid; breaks SQL built by concatenation and regexes limited to [a-z0-9._].",
      "tags": [
        "valid",
        "local-part"
      ]
    },
    {
      "generator": "emails",
      "label": "quoted local part with space",
      "value": "\"\\\"john doe\\\"@example.com\"",
      "why": "A quoted string may contain spaces; nearly every regex rejects it and naive splitting on spaces breaks.",
      "tags": [
        "valid",
        "quoted"
      ]
    },
    {
      "generator": "emails",
      "label": "quoted local part with @",
      "value": "\"\\\"a@b\\\"@example.com\"",
      "why": "Splitting on the first \"@\" yields the wrong domain; use the last \"@\".",
      "tags": [
        "valid",
        "quoted"
      ]
    },
    {
      "generator": "emails",
      "label": "IP address literal domain",
      "value": "\"user@[192.168.0.1]\"",
      "why": "Domain literal in brackets; DNS based checks and domain allow lists do not expect it.",
      "tags": [
        "valid",
        "domain"
      ]
    },
    {
      "generator": "emails",
      "label": "dotless domain",
      "value": "\"user@localhost\"",
      "why": "Valid syntax used on intranets and in tests, rejected by \"needs a TLD\" rules.",
      "tags": [
        "valid",
        "domain"
      ]
    },
    {
      "generator": "emails",
      "label": "uppercase address",
      "value": "\"USER@EXAMPLE.COM\"",
      "why": "Domains are case insensitive, local parts technically are not; lowercasing everything can merge different mailboxes, not lowercasing creates duplicates.",
      "tags": [
        "valid",
        "case"
      ]
    },
    {
      "generator": "emails",
      "label": "subdomains and long TLD",
      "value": "\"user@mail.sub.example.co.uk\"",
      "why": "Multi label domains and two part public suffixes; \"last two labels\" logic picks co.uk.",
      "tags": [
        "valid",
        "domain"
      ]
    },
    {
      "generator": "emails",
      "label": "new generic TLD",
      "value": "\"user@example.photography\"",
      "why": "TLDs longer than 4 letters exist; {2,4} quantifiers reject them.",
      "tags": [
        "valid",
        "domain"
      ]
    },
    {
      "generator": "emails",
      "label": "shortest realistic address",
      "value": "\"a@b.co\"",
      "why": "Single character local part and short domain; minimum length rules are often too strict.",
      "tags": [
        "valid",
        "short"
      ]
    },
    {
      "generator": "emails",
      "label": "64 character local part (maximum)",
      "value": "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@example.com\"",
      "why": "The longest local part RFC 5321 allows; storage columns sized at 50 truncate it.",
      "tags": [
        "valid",
        "long",
        "limit"
      ]
    },
    {
      "generator": "emails",
      "label": "internationalized local part",
      "value": "\"jos\\u00E9@example.com\"",
      "why": "Valid with SMTPUTF8 (RFC 6531) but rejected by ASCII only servers; decide explicitly what you accept.",
      "tags": [
        "valid",
        "smtputf8",
        "unicode"
      ]
    },
    {
      "generator": "emails",
      "label": "internationalized domain",
      "value": "\"user@\\u4F8B\\u3048.jp\"",
      "why": "The domain must be converted to punycode for DNS and SMTP; comparing raw strings fails.",
      "tags": [
        "valid",
        "smtputf8",
        "unicode",
        "idn"
      ]
    },
    {
      "generator": "emails",
      "label": "65 character local part (too long)",
      "value": "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@example.com\"",
      "why": "One over the RFC 5321 limit; lenient validators accept it and the SMTP server rejects it later.",
      "tags": [
        "invalid",
        "long",
        "limit"
      ]
    },
    {
      "generator": "emails",
      "label": "missing @",
      "value": "\"plainaddress\"",
      "why": "No separator at all; code that splits on \"@\" gets one part and reads undefined.",
      "tags": [
        "invalid"
      ]
    },
    {
      "generator": "emails",
      "label": "missing local part",
      "value": "\"@example.com\"",
      "why": "Empty local part; split(\"@\")[0] is \"\".",
      "tags": [
        "invalid",
        "empty"
      ]
    },
    {
      "generator": "emails",
      "label": "missing domain",
      "value": "\"user@\"",
      "why": "Empty domain; split(\"@\")[1] is \"\".",
      "tags": [
        "invalid",
        "empty"
      ]
    },
    {
      "generator": "emails",
      "label": "two @ signs",
      "value": "\"user@@example.com\"",
      "why": "Unquoted second \"@\" is invalid; splitting gives three parts.",
      "tags": [
        "invalid"
      ]
    },
    {
      "generator": "emails",
      "label": "leading dot",
      "value": "\".user@example.com\"",
      "why": "A dot may not start the local part.",
      "tags": [
        "invalid",
        "local-part"
      ]
    },
    {
      "generator": "emails",
      "label": "trailing dot in local part",
      "value": "\"user.@example.com\"",
      "why": "A dot may not end the local part (some providers accept it anyway).",
      "tags": [
        "invalid",
        "local-part"
      ]
    },
    {
      "generator": "emails",
      "label": "consecutive dots",
      "value": "\"us..er@example.com\"",
      "why": "Consecutive dots are not allowed unquoted.",
      "tags": [
        "invalid",
        "local-part"
      ]
    },
    {
      "generator": "emails",
      "label": "consecutive dots in domain",
      "value": "\"user@example..com\"",
      "why": "Empty domain label; DNS lookups fail.",
      "tags": [
        "invalid",
        "domain"
      ]
    },
    {
      "generator": "emails",
      "label": "domain label starting with hyphen",
      "value": "\"user@-example.com\"",
      "why": "Host labels may not start with a hyphen.",
      "tags": [
        "invalid",
        "domain"
      ]
    },
    {
      "generator": "emails",
      "label": "unquoted space",
      "value": "\"john doe@example.com\"",
      "why": "Spaces need quoting; forms that do not trim also produce trailing spaces.",
      "tags": [
        "invalid",
        "whitespace"
      ]
    },
    {
      "generator": "emails",
      "label": "display name format",
      "value": "\"John Doe <john@example.com>\"",
      "why": "A valid mailbox header, not a bare address; pasted from mail clients into address fields.",
      "tags": [
        "invalid",
        "header"
      ]
    },
    {
      "generator": "paths",
      "label": "Windows absolute path",
      "value": "\"C:\\\\Users\\\\Ana\\\\file.txt\"",
      "why": "Backslash separators: splitting on \"/\" returns one segment, and on POSIX this is a relative file name containing backslashes.",
      "tags": [
        "windows",
        "absolute"
      ]
    },
    {
      "generator": "paths",
      "label": "Windows path with forward slashes",
      "value": "\"C:/Users/Ana/file.txt\"",
      "why": "Windows accepts it, path.win32 understands it, path.posix treats it as relative.",
      "tags": [
        "windows",
        "absolute",
        "mixed"
      ]
    },
    {
      "generator": "paths",
      "label": "drive relative path",
      "value": "\"C:file.txt\"",
      "why": "Relative to the current directory of drive C, not the root; path.win32.isAbsolute returns false.",
      "tags": [
        "windows",
        "relative"
      ]
    },
    {
      "generator": "paths",
      "label": "root relative on Windows",
      "value": "\"\\\\temp\\\\file.txt\"",
      "why": "Absolute on the current drive only; the result depends on process.cwd() drive.",
      "tags": [
        "windows",
        "absolute"
      ]
    },
    {
      "generator": "paths",
      "label": "UNC share path",
      "value": "\"\\\\\\\\server\\\\share\\\\folder\\\\file.txt\"",
      "why": "Starts with two backslashes; the \"root\" is \\\\server\\share\\, so dirname and parent walking stop there.",
      "tags": [
        "windows",
        "absolute",
        "unc"
      ]
    },
    {
      "generator": "paths",
      "label": "long path prefix",
      "value": "\"\\\\\\\\?\\\\C:\\\\very\\\\long\\\\path\"",
      "why": "Disables normalization: \"/\" is not a separator and \"..\" is literal; needed beyond 260 characters.",
      "tags": [
        "windows",
        "absolute",
        "long"
      ]
    },
    {
      "generator": "paths",
      "label": "path longer than 260 characters",
      "value": "\"C:\\\\segment\\\\segment\\\\segment\\\\segment\\\\segme...\" (291 chars)",
      "why": "Exceeds the classic MAX_PATH limit; many Windows tools fail without long path support.",
      "tags": [
        "windows",
        "long",
        "limit"
      ]
    },
    {
      "generator": "paths",
      "label": "reserved device name",
      "value": "\"CON\"",
      "why": "CON, PRN, AUX, NUL, COM1 and LPT1 cannot be file names on Windows, with any extension.",
      "tags": [
        "windows",
        "reserved"
      ]
    },
    {
      "generator": "paths",
      "label": "reserved name with extension",
      "value": "\"aux.txt\"",
      "why": "Still the AUX device on Windows; repositories with this file cannot be checked out there.",
      "tags": [
        "windows",
        "reserved"
      ]
    },
    {
      "generator": "paths",
      "label": "trailing dot",
      "value": "\"file.\"",
      "why": "Windows strips trailing dots, so \"file.\" and \"file\" are the same file there but different on POSIX.",
      "tags": [
        "windows",
        "trailing"
      ]
    },
    {
      "generator": "paths",
      "label": "trailing space",
      "value": "\"file \"",
      "why": "Windows strips trailing spaces as well; invisible in most UIs.",
      "tags": [
        "windows",
        "trailing",
        "whitespace"
      ]
    },
    {
      "generator": "paths",
      "label": "case only difference",
      "value": "\"README.md\"",
      "why": "Case insensitive on default Windows and macOS file systems, so readme.md and README.md collide.",
      "tags": [
        "windows",
        "posix",
        "case"
      ]
    },
    {
      "generator": "paths",
      "label": "POSIX absolute path",
      "value": "\"/usr/local/bin\"",
      "why": "Absolute on POSIX; on Windows path.win32 treats it as root relative on the current drive.",
      "tags": [
        "posix",
        "absolute"
      ]
    },
    {
      "generator": "paths",
      "label": "trailing slash",
      "value": "\"dir/sub/\"",
      "why": "basename(\"dir/sub/\") is \"sub\", but split(\"/\").pop() is \"\"; joining adds a double slash.",
      "tags": [
        "posix",
        "trailing"
      ]
    },
    {
      "generator": "paths",
      "label": "repeated slashes",
      "value": "\"/a//b///c\"",
      "why": "Equivalent to /a/b/c after normalization; string comparisons and cache keys disagree.",
      "tags": [
        "posix",
        "normalization"
      ]
    },
    {
      "generator": "paths",
      "label": "root only",
      "value": "\"/\"",
      "why": "dirname(\"/\") is \"/\" and basename is \"\"; loops that walk up until dirname changes must stop here.",
      "tags": [
        "posix",
        "absolute",
        "root"
      ]
    },
    {
      "generator": "paths",
      "label": "empty path",
      "value": "\"\"",
      "why": "path.join(\"\", \"\") is \".\" and path.resolve(\"\") is the cwd; empty is not \"no path\".",
      "tags": [
        "posix",
        "windows",
        "empty"
      ]
    },
    {
      "generator": "paths",
      "label": "current directory",
      "value": "\".\"",
      "why": "A path that refers to the cwd; extname(\".\") is \"\" and basename is \".\".",
      "tags": [
        "posix",
        "windows",
        "relative"
      ]
    },
    {
      "generator": "paths",
      "label": "parent directory traversal",
      "value": "\"../../etc/passwd\"",
      "why": "Escapes the base directory after join; validate with path.relative after resolving.",
      "tags": [
        "posix",
        "traversal",
        "security"
      ]
    },
    {
      "generator": "paths",
      "label": "traversal hidden inside a path",
      "value": "\"uploads/./a/../../../secret\"",
      "why": "Looks rooted in uploads/ but normalizes outside it.",
      "tags": [
        "posix",
        "traversal",
        "security"
      ]
    },
    {
      "generator": "paths",
      "label": "Windows traversal with backslashes",
      "value": "\"..\\\\..\\\\Windows\\\\win.ini\"",
      "why": "Checks that only look for \"../\" miss backslash traversal on Windows.",
      "tags": [
        "windows",
        "traversal",
        "security"
      ]
    },
    {
      "generator": "paths",
      "label": "dotfile",
      "value": "\".env\"",
      "why": "extname(\".env\") is \"\", not \".env\"; hidden on POSIX and easy to leak in static servers.",
      "tags": [
        "posix",
        "extension",
        "hidden"
      ]
    },
    {
      "generator": "paths",
      "label": "double extension",
      "value": "\"archive.tar.gz\"",
      "why": "extname gives \".gz\"; type detection and \"strip the extension\" give \"archive.tar\".",
      "tags": [
        "posix",
        "windows",
        "extension"
      ]
    },
    {
      "generator": "paths",
      "label": "spaces in names",
      "value": "\"My Documents/file name.txt\"",
      "why": "Breaks unquoted shell commands and URL building without encoding.",
      "tags": [
        "posix",
        "windows",
        "whitespace"
      ]
    },
    {
      "generator": "paths",
      "label": "backslash in a POSIX file name",
      "value": "\"a\\\\b.txt\"",
      "why": "A legal single file name on Linux that becomes two segments on Windows.",
      "tags": [
        "posix",
        "mixed"
      ]
    },
    {
      "generator": "paths",
      "label": "NFC unicode name",
      "value": "\"caf\\u00E9.txt\"",
      "why": "Precomposed form, as typed on Windows and Linux.",
      "tags": [
        "posix",
        "windows",
        "unicode",
        "normalization"
      ]
    },
    {
      "generator": "paths",
      "label": "NFD unicode name",
      "value": "\"cafe\\u0301.txt\"",
      "why": "Decomposed form produced by older macOS file systems; looks the same as the NFC name but does not match it.",
      "tags": [
        "posix",
        "unicode",
        "normalization"
      ]
    },
    {
      "generator": "paths",
      "label": "emoji in file name",
      "value": "\"notes \\u{1F4DD}.md\"",
      "why": "Surrogate pairs in a path: byte limits, truncation and some archive tools mishandle them.",
      "tags": [
        "posix",
        "windows",
        "unicode",
        "emoji"
      ]
    },
    {
      "generator": "paths",
      "label": "leading dash",
      "value": "\"-rf\"",
      "why": "Interpreted as an option by command line tools unless passed after \"--\".",
      "tags": [
        "posix",
        "security"
      ]
    },
    {
      "generator": "paths",
      "label": "newline in file name",
      "value": "\"a\\nb.txt\"",
      "why": "Legal on Linux; breaks line based tools such as `find | xargs` and log parsing.",
      "tags": [
        "posix",
        "control"
      ]
    },
    {
      "generator": "json",
      "label": "deeply nested arrays (10000 levels)",
      "value": "\"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[...\" (20000 chars)",
      "why": "Valid JSON that overflows the stack of recursive walkers, deep equality checks and schema validators.",
      "tags": [
        "valid",
        "deep"
      ]
    },
    {
      "generator": "json",
      "label": "deeply nested objects (10000 levels)",
      "value": "\"{\\\"a\\\":{\\\"a\\\":{\\\"a\\\":{\\\"a\\\":{\\\"a\\\":{\\\"a\\\":{\\\"a\\\":{\\\"a\\\":...\" (60001 chars)",
      "why": "Same as nested arrays for code that recurses into object values, such as deep merge and clone helpers.",
      "tags": [
        "valid",
        "deep"
      ]
    },
    {
      "generator": "json",
      "label": "duplicate keys",
      "value": "\"{\\\"a\\\":1,\\\"a\\\":2}\"",
      "why": "Allowed by JSON.parse, which keeps the last value; other parsers keep the first or reject it, so validators and consumers disagree.",
      "tags": [
        "valid",
        "duplicate-keys",
        "security"
      ]
    },
    {
      "generator": "json",
      "label": "integer above 2^53",
      "value": "\"{\\\"id\\\":9007199254740993}\"",
      "why": "Parses to 9007199254740992: IDs silently change. Send large IDs as strings.",
      "tags": [
        "valid",
        "big-number",
        "precision"
      ]
    },
    {
      "generator": "json",
      "label": "huge exponent",
      "value": "\"1e400\"",
      "why": "Valid JSON that parses to Infinity, which JSON.stringify then writes as null.",
      "tags": [
        "valid",
        "big-number",
        "infinity"
      ]
    },
    {
      "generator": "json",
      "label": "negative zero",
      "value": "\"-0\"",
      "why": "Parses to -0, but JSON.stringify(-0) is \"0\", so round trips lose the sign.",
      "tags": [
        "valid",
        "sign"
      ]
    },
    {
      "generator": "json",
      "label": "number with trailing zeros",
      "value": "\"1.0\"",
      "why": "Parses to 1 and stringifies as \"1\": signatures and hashes over JSON text change after a round trip.",
      "tags": [
        "valid",
        "canonical"
      ]
    },
    {
      "generator": "json",
      "label": "__proto__ key",
      "value": "\"{\\\"__proto__\\\":{\\\"isAdmin\\\":true}}\"",
      "why": "JSON.parse creates an own property, but merging the result into another object with assignment pollutes its prototype.",
      "tags": [
        "valid",
        "security",
        "prototype"
      ]
    },
    {
      "generator": "json",
      "label": "empty key",
      "value": "\"{\\\"\\\":1}\"",
      "why": "Valid; path based libraries (a.b.c syntax) cannot address it.",
      "tags": [
        "valid",
        "keys"
      ]
    },
    {
      "generator": "json",
      "label": "escaped lone surrogate",
      "value": "\"\\\"\\\\ud800\\\"\"",
      "why": "Valid JSON that decodes to malformed UTF-16; re-encoding to UTF-8 or a database fails.",
      "tags": [
        "valid",
        "unicode",
        "surrogate"
      ]
    },
    {
      "generator": "json",
      "label": "line and paragraph separators",
      "value": "\"\\\"a\\u2028b\\u2029c\\\"\"",
      "why": "Valid JSON that was invalid in JavaScript string literals before ES2019, which broke JSONP and inline script tags.",
      "tags": [
        "valid",
        "unicode"
      ]
    },
    {
      "generator": "json",
      "label": "top level string",
      "value": "\"\\\"just a string\\\"\"",
      "why": "Valid JSON since RFC 7159; code that assumes an object reads properties of a string.",
      "tags": [
        "valid",
        "scalar"
      ]
    },
    {
      "generator": "json",
      "label": "top level null",
      "value": "\"null\"",
      "why": "Valid JSON that parses to null; `const { a } = JSON.parse(text)` throws.",
      "tags": [
        "valid",
        "scalar"
      ]
    },
    {
      "generator": "json",
      "label": "whitespace around value",
      "value": "\" \\n\\t {\\\"a\\\":1} \\r\\n\"",
      "why": "Valid; byte or regex based detectors that check the first character for \"{\" fail.",
      "tags": [
        "valid",
        "whitespace"
      ]
    },
    {
      "generator": "json",
      "label": "byte order mark prefix",
      "value": "\"\\uFEFF{\\\"a\\\":1}\"",
      "why": "Windows tools write a BOM; JSON.parse throws on it, so strip it when reading files.",
      "tags": [
        "invalid",
        "bom"
      ]
    },
    {
      "generator": "json",
      "label": "trailing comma",
      "value": "\"[1,2,]\"",
      "why": "Accepted by JavaScript and JSON5, rejected by JSON.parse.",
      "tags": [
        "invalid",
        "syntax"
      ]
    },
    {
      "generator": "json",
      "label": "comments",
      "value": "\"{\\\"a\\\":1 /* note */}\"",
      "why": "Common in config files (JSONC) but invalid JSON.",
      "tags": [
        "invalid",
        "syntax"
      ]
    },
    {
      "generator": "json",
      "label": "single quotes",
      "value": "\"{'a':1}\"",
      "why": "JavaScript object syntax, not JSON.",
      "tags": [
        "invalid",
        "syntax"
      ]
    },
    {
      "generator": "json",
      "label": "NaN literal",
      "value": "\"{\\\"a\\\":NaN}\"",
      "why": "Python json.dumps writes NaN by default, and JSON.parse rejects it.",
      "tags": [
        "invalid",
        "nan"
      ]
    },
    {
      "generator": "json",
      "label": "unquoted key",
      "value": "\"{a:1}\"",
      "why": "JavaScript object literal syntax that JSON does not allow.",
      "tags": [
        "invalid",
        "syntax"
      ]
    },
    {
      "generator": "json",
      "label": "empty text",
      "value": "\"\"",
      "why": "An empty response body is not JSON; JSON.parse(\"\") throws \"Unexpected end of JSON input\".",
      "tags": [
        "invalid",
        "empty"
      ]
    },
    {
      "generator": "json",
      "label": "raw control character in string",
      "value": "\"\\\"a\\tb\\\"\"",
      "why": "Unescaped tab inside a string is invalid JSON even though it looks harmless.",
      "tags": [
        "invalid",
        "control"
      ]
    },
    {
      "generator": "arrays",
      "label": "empty array",
      "value": "[]",
      "why": "Truthy even though empty; reduce without a seed throws and Math.max(...[]) is -Infinity.",
      "tags": [
        "empty"
      ]
    },
    {
      "generator": "arrays",
      "label": "array with a hole",
      "value": "[1, <hole>, 3]",
      "why": "forEach, map and filter skip the hole but for...of and spread yield undefined, so the two styles disagree.",
      "tags": [
        "sparse",
        "hole"
      ]
    },
    {
      "generator": "arrays",
      "label": "explicit undefined",
      "value": "[1, undefined, 3]",
      "why": "Looks like the hole case when printed, but every iteration method visits it and `1 in arr` is true.",
      "tags": [
        "undefined"
      ]
    },
    {
      "generator": "arrays",
      "label": "length 5 with no elements",
      "value": "[<hole>, <hole>, <hole>, <hole>, <hole>]",
      "why": "new Array(5) has five holes: map returns holes, not values, and JSON.stringify writes nulls.",
      "tags": [
        "sparse",
        "hole"
      ]
    },
    {
      "generator": "arrays",
      "label": "huge sparse length (2^32 - 1)",
      "value": "[\"first\", <hole>, <hole>, <hole>, <hole>, <hole>, ...] (length 4294967295)",
      "why": "The maximum array length: cheap to create, but any loop to length or Array.from runs four billion times.",
      "tags": [
        "sparse",
        "huge",
        "limit"
      ]
    },
    {
      "generator": "arrays",
      "label": "NaN element",
      "value": "[NaN]",
      "why": "indexOf(NaN) is -1 while includes(NaN) is true; Set and Map treat NaN as equal to itself.",
      "tags": [
        "nan"
      ]
    },
    {
      "generator": "arrays",
      "label": "-0 and 0",
      "value": "[-0, 0]",
      "why": "Set collapses them into one value and includes(-0) finds 0; Object.is tells them apart.",
      "tags": [
        "zero",
        "sign"
      ]
    },
    {
      "generator": "arrays",
      "label": "numbers that sort as strings",
      "value": "[10, 9, 1, 100]",
      "why": "Default sort() compares strings, giving [1, 10, 100, 9]; always pass a comparator.",
      "tags": [
        "sort"
      ]
    },
    {
      "generator": "arrays",
      "label": "undefined during sort",
      "value": "[3, undefined, 1]",
      "why": "sort() moves undefined to the end without calling the comparator, so comparators never see it.",
      "tags": [
        "sort",
        "undefined"
      ]
    },
    {
      "generator": "arrays",
      "label": "mixed number and numeric string",
      "value": "[1, \"1\"]",
      "why": "includes(\"1\") and Set treat them as different, while == and loose lookups do not.",
      "tags": [
        "mixed",
        "coercion"
      ]
    },
    {
      "generator": "arrays",
      "label": "nested empty arrays",
      "value": "[[[]]]",
      "why": "flat() and recursive flatten helpers must handle empty levels; String([[[]]]) is \"\".",
      "tags": [
        "nested"
      ]
    },
    {
      "generator": "arrays",
      "label": "array with extra property",
      "value": "[1, 2]",
      "why": "for...in visits \"extra\" and Object.keys includes it, but length and JSON.stringify ignore it.",
      "tags": [
        "properties"
      ]
    },
    {
      "generator": "arrays",
      "label": "frozen array",
      "value": "[1, 2, 3]",
      "why": "push and in place sort throw TypeError in strict mode; libraries that mutate input break.",
      "tags": [
        "frozen"
      ]
    },
    {
      "generator": "arrays",
      "label": "500000 elements (too many to spread)",
      "value": "[0, 1, 2, 3, 4, 5, ...] (length 500000)",
      "why": "Math.max(...arr) and fn.apply(null, arr) exceed the argument limit and throw RangeError.",
      "tags": [
        "large",
        "stack"
      ]
    }
  ]
}
