@claudinho/core 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +550 -181
  2. package/dist/index.js +300 -20
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -153,11 +153,27 @@ type Stage = 'GROUP' | 'R32' | 'R16' | 'QF' | 'SF' | '3P' | 'F' | 'FRIENDLY' | '
153
153
  type Status = 'SCHEDULED' | 'LIVE' | 'HT' | 'FT' | 'POSTPONED' | 'CANCELLED';
154
154
  /** Match outcome from the home team's perspective. */
155
155
  type Outcome = 'H' | 'D' | 'A';
156
- /** A discrete in-match event (provider-dependent; often absent on free tiers). */
156
+ /**
157
+ * One of a match's goals or cards, as the provider listed it (ESPN's
158
+ * `competitions[0].details`, read by the grammar in `trust/espn.ts` and sealed
159
+ * by `sealEvent` in `trust/match.ts`, on the feed and the cache path alike).
160
+ * Key order is the serialized order.
161
+ */
157
162
  interface MatchEvent {
163
+ /** The kind. `SUB` stays in the type; ESPN's scoreboard never produces one. */
158
164
  type: 'GOAL' | 'OWN_GOAL' | 'PEN' | 'YELLOW' | 'RED' | 'SUB';
165
+ /** The minute the provider's clock showed: `90` for `90'+3'`. */
159
166
  minute: number;
167
+ /** Added time past `minute` (`3` for `90'+3'`), 1 to 30; absent when none. */
168
+ added?: number;
169
+ /**
170
+ * The side the event belongs to: the side a goal COUNTED for (an own goal
171
+ * included), the side a card was shown to. The identity; `teamCode` is a label.
172
+ */
173
+ side: 'home' | 'away';
174
+ /** That side's code, a display label. */
160
175
  teamCode: string;
176
+ /** The player, when the provider names exactly one of the expected team. */
161
177
  player?: string;
162
178
  }
163
179
  /** A single fixture/result — the central entity. */
@@ -201,7 +217,13 @@ interface Match {
201
217
  /** Live match minute when in progress. */
202
218
  minute?: number;
203
219
  status: Status;
204
- /** Goals/cards when the provider supplies them. */
220
+ /**
221
+ * The provider's goals and cards that could be read, in time order (minute,
222
+ * then added time). Never a claim that the list is every goal: a detail the
223
+ * grammar cannot read is left out, and a live timeline lags its score by
224
+ * nature. None on a match with no score (scheduled, postponed, cancelled);
225
+ * the key is absent when none was read.
226
+ */
205
227
  events?: MatchEvent[];
206
228
  /**
207
229
  * Winner's team code when the provider marks one (e.g. ESPN `competitor.winner`
@@ -279,6 +301,27 @@ type Lang = 'en' | 'es' | 'pt' | 'fr';
279
301
  declare function normalizeLang(lang?: string): Lang;
280
302
  /** Translate a message key with optional `{placeholder}` interpolation. */
281
303
  declare function t(lang: string | undefined, key: string, vars?: Record<string, string>): string;
304
+ /**
305
+ * The ten words of the plugin's moments, as `claudinho ambient --json` sends
306
+ * them (`words`), in this order: core's `moment.*` keys in one language.
307
+ * `goalFor` and `win` are templates holding `{team}` once, which the plugin
308
+ * fills with the record's own names; names, scores and minutes are never
309
+ * translated.
310
+ */
311
+ interface MomentWords {
312
+ readonly goal: string;
313
+ readonly ownGoal: string;
314
+ readonly ownGoalDetail: string;
315
+ readonly goalFor: string;
316
+ readonly goals: string;
317
+ readonly scoreUpdated: string;
318
+ readonly penalties: string;
319
+ readonly fullTime: string;
320
+ readonly win: string;
321
+ readonly draw: string;
322
+ }
323
+ /** The moment words in `lang` (an unsupported one is English), the templates left unfilled. */
324
+ declare function momentWords(lang: string | undefined): MomentWords;
282
325
  /**
283
326
  * Localized stage label, from the match (its stage, its group letter under the
284
327
  * group stage, and the words an OTHER stage carries). An `OTHER` stage prints
@@ -313,16 +356,21 @@ declare function formatDate(iso: string, opts?: FormatOpts): string;
313
356
  declare function formatTime(iso: string, opts?: FormatOpts): string;
314
357
  /** What {@link countdown} says of a kickoff that has passed (the statusline prints it as it is: English, by its rule). */
315
358
  declare const COUNTDOWN_NOW = "now";
316
- /** Compact human countdown until kickoff: "3d4h", "2h10m", "45m", or {@link COUNTDOWN_NOW}. */
317
- declare function countdown(iso: string, from?: Date): string;
359
+ /**
360
+ * Compact human countdown until kickoff: "3d4h", "2h10m", "45m", or {@link COUNTDOWN_NOW}, from `from`: the clock of
361
+ * the request or render that says it, which every caller hands in (no default: the wall clock is never read here).
362
+ */
363
+ declare function countdown(iso: string, from: Date): string;
318
364
  /**
319
365
  * The countdown as the reader's phrase, ONE rule for every localized line that
320
366
  * says it (CLI `next`, the MCP match line): "in 3d4h" (`next.in`), or, for a
321
367
  * kickoff that has passed (a stale record, the bundle's skeleton during an
322
368
  * outage), the language's own word for now (`countdown.now`), never the
323
- * English word inside a translated "in".
369
+ * English word inside a translated "in". Relative to the REQUEST's clock
370
+ * (`from`), the one every other read of the request takes and every caller
371
+ * passes: the wall clock is never read here.
324
372
  */
325
- declare function countdownPhrase(lang: string | undefined, iso: string, from?: Date): string;
373
+ declare function countdownPhrase(lang: string | undefined, iso: string, from: Date): string;
326
374
  /**
327
375
  * The calendar date (YYYY-MM-DD) of a kickoff in the target timezone, or ''
328
376
  * when the input can't be parsed — an unfileable fixture matches no date rather
@@ -379,6 +427,42 @@ declare function padVisible(s: string, width: number): string;
379
427
  */
380
428
  declare function withFlag(text: string, flag: string | undefined, side: 'home' | 'away'): string;
381
429
 
430
+ interface TimelineOptions {
431
+ /** The reader's language (en/es/pt/fr); English when absent. */
432
+ readonly lang?: string;
433
+ /** Whether a nation's flag is printed beside its code (a club has none either way). */
434
+ readonly flags: boolean;
435
+ }
436
+ /** One part of a timeline row: its text, and `strong` on the player. */
437
+ interface TimelinePart {
438
+ readonly text: string;
439
+ readonly style?: 'strong';
440
+ }
441
+ /**
442
+ * The match's events as rows of parts; `[]` when it has none. Each row is
443
+ * the aligned columns as one plain part (two spaces, the minute, the marker,
444
+ * one space and the localized kind word, the side's label), then, when the
445
+ * provider named a player, two spaces and the player as one `strong` part.
446
+ * Joined, a row is its {@link timelineRows} line.
447
+ */
448
+ declare function timelineParts(match: Match, opts: TimelineOptions): TimelinePart[][];
449
+ /** The match's events as aligned text rows ({@link timelineParts} joined); `[]` when it has none. */
450
+ declare function timelineRows(match: Match, opts: TimelineOptions): string[];
451
+ /**
452
+ * The goal that made the record's score, PROVEN, or `null`. The record's
453
+ * scoring events, counted per side in their order (an own goal for the side
454
+ * it credited, which is the event's `side`), must equal its regulation score:
455
+ * then the timeline is whole and its last scoring event is the goal that made
456
+ * this score. Anything else proves nothing (a timeline that lags the score, a
457
+ * disallowed goal still listed, no score, no scoring event): the first scorer
458
+ * is never named for a second goal. Two scoring events identical in type,
459
+ * minute, added time, side and player prove nothing either: the same goal
460
+ * listed twice beside a timeline that lags would count as two. The ambient
461
+ * view's `lastGoal`, written by the refresher on each live record it
462
+ * publishes.
463
+ */
464
+ declare function provenLastGoal(match: Match): MatchEvent | null;
465
+
382
466
  /** Outcome (home perspective) from a final/looking scoreline. */
383
467
  declare function outcomeFromScore(home: number, away: number): Outcome;
384
468
  /** Is the match currently in play (including halftime)? */
@@ -866,8 +950,9 @@ declare function fixturesByGroup(group: string, fixtures?: Match[]): Match[];
866
950
  /**
867
951
  * Eligible to be "the next match": the kickoff is still ahead AND the match is
868
952
  * still going to be played. ONE predicate for every selector (`next`, the
869
- * statusline countdown, the knockout-fixture cache, the market fixture, the
870
- * refresher cadence) — a cancelled or postponed fixture keeps its kickoff, so
953
+ * knockout-fixture cache, the market fixture, the refresher cadence; the
954
+ * statusline countdown asks it for a kickoff strictly ahead and also names a
955
+ * DUE fixture, the CLI's `isDue`) — a cancelled or postponed fixture keeps its kickoff, so
871
956
  * a time-only check advertised it as the next game (audit A07). Finished is
872
957
  * deliberately NOT a clause: under a real clock a finished match never has a
873
958
  * future kickoff, and excluding it only changed seeded-clock replays of an
@@ -1384,6 +1469,15 @@ interface LiveResult {
1384
1469
  */
1385
1470
  served?: readonly string[];
1386
1471
  }
1472
+ /**
1473
+ * THE clock of a request: the one its caller gave (a test's, a command's
1474
+ * context), else the adapter's read clock ({@link clockOf}: the clock the
1475
+ * adapter's reads and its cooldown count by, the wall clock in production).
1476
+ * A surface reads it ONCE per request, after resolving its adapter, and hands
1477
+ * it to every read and every rendering of the request, so a lookup and a
1478
+ * countdown in one answer agree on "now".
1479
+ */
1480
+ declare function requestClock(adapter: ProviderAdapter, given?: Date): Date;
1387
1481
  /** Human label for a live-data provider name (attribution). Text only. */
1388
1482
  declare function liveSourceLabel(source: string): string;
1389
1483
  /**
@@ -1669,7 +1763,7 @@ interface KnockoutFixturesResult {
1669
1763
  /**
1670
1764
  * The RESOLVED upcoming knockout fixtures from the live overlay — the data the
1671
1765
  * hot-path statusline can't fetch itself but needs to show a real next-match
1672
- * countdown (e.g. "🇲🇽 vs 🇪🇨 in 2d") instead of a 🏳️ placeholder. The cold-path
1766
+ * countdown (e.g. "⚽ 🇲🇽 vs 🇪🇨 in 2d") instead of a 🏳️ placeholder. The cold-path
1673
1767
  * refresher calls this and caches the result; the statusline reads the cache.
1674
1768
  *
1675
1769
  * Returns only fixtures where BOTH sides are resolved (neither is the 🏳️ placeholder) and kickoff
@@ -1780,6 +1874,8 @@ declare function getScheduleAhead(adapter: ProviderAdapter, now?: Date): Promise
1780
1874
  * an adjacent bucket. Adapters without a window fetch fall back to `fetchLive()`.
1781
1875
  */
1782
1876
  declare function getLiveMatches(adapter: ProviderAdapter, now?: Date): Promise<LiveResult>;
1877
+ /** The finished records a live read returns, at most (the refresher's record of play keeps as many). */
1878
+ declare const MAX_LIVE_FINISHED = 64;
1783
1879
  /** A live read with the answer's own account of itself: what the refresher decides from. */
1784
1880
  interface LiveReadResult extends LiveResult {
1785
1881
  /**
@@ -1788,14 +1884,30 @@ interface LiveReadResult extends LiveResult {
1788
1884
  * whole and holds no match in play does not prove none is.
1789
1885
  */
1790
1886
  complete: boolean;
1887
+ /**
1888
+ * The window's records with status `FT` that hold a score, as the adapter
1889
+ * sealed them, asked of the whole window before the in-play filter: the ids
1890
+ * the caller passed as `seen` first, in the window's order, then the others,
1891
+ * at most {@link MAX_LIVE_FINISHED}. `[]` for a failed read. The evidence of
1892
+ * full time for a match the refresher saw in play; never on
1893
+ * {@link getLiveMatches}' result.
1894
+ */
1895
+ finished: Match[];
1896
+ /**
1897
+ * The cap left finished records out: an id the caller saw that is absent
1898
+ * from `finished` may then be one of them, so its absence decides nothing.
1899
+ */
1900
+ finishedTruncated: boolean;
1791
1901
  }
1792
1902
  /**
1793
1903
  * {@link getLiveMatches}, keeping the window's `complete` verdict (read from
1794
- * the window's result BEFORE the in-play filter makes a new array). For the
1795
- * cold-path refresher, which keeps polling after a match was seen in play
1796
- * until a WHOLE read holds none.
1904
+ * the window's result BEFORE the in-play filter makes a new array), and the
1905
+ * window's finished records (`finished`, chosen ids-first by `seen`, the ids
1906
+ * the refresher's record of play holds as seen in play). For the cold-path
1907
+ * refresher, which keeps polling after a match was seen in play until a WHOLE
1908
+ * read holds none.
1797
1909
  */
1798
- declare function getLiveRead(adapter: ProviderAdapter, now?: Date): Promise<LiveReadResult>;
1910
+ declare function getLiveRead(adapter: ProviderAdapter, now?: Date, seen?: readonly string[]): Promise<LiveReadResult>;
1799
1911
 
1800
1912
  /** A roster team plus its group letter (A–L). */
1801
1913
  interface TeamInfo extends Team {
@@ -1937,6 +2049,15 @@ interface BoundedList<T> {
1937
2049
  * make an unbounded traversal safe. `takeBounded` is the one that bounds work.
1938
2050
  */
1939
2051
  declare function bounded<T>(items: readonly T[], max: number, complete?: boolean): BoundedList<T>;
2052
+ /**
2053
+ * Take at most `max` items from something that may not be an array at all,
2054
+ * BEFORE any per-item work happens.
2055
+ *
2056
+ * This is the work bound. Mapping, sorting or sanitizing first and slicing
2057
+ * afterwards is what made a 4,000-row group cost 300ms to return 32, and a
2058
+ * 100k-event record cost 5.3s on a 150ms surface.
2059
+ */
2060
+ declare function takeBounded<T>(value: unknown, max: number): T[];
1940
2061
 
1941
2062
  /**
1942
2063
  * The vocabulary for "we could not use this".
@@ -2500,7 +2621,7 @@ declare const DEFAULT_MAX_AGE_MS: number;
2500
2621
  * "markets favor X 100%" after full time reads as a bug, not information.
2501
2622
  * An unparseable kickoff fails open (the reliability gate still applies).
2502
2623
  */
2503
- declare function marketRelevant(match: Match, now?: Date): boolean;
2624
+ declare function marketRelevant(match: Match, now: Date): boolean;
2504
2625
  /**
2505
2626
  * Re-scale outcome probabilities so the positive ones sum to 1. This removes
2506
2627
  * market "vig" (raw prices sum to >1) and is scale-agnostic: inputs may be
@@ -2872,6 +2993,15 @@ declare function isPinnedSide(side: Team, pin: {
2872
2993
  readonly code: string;
2873
2994
  readonly name: string;
2874
2995
  }): boolean;
2996
+ /**
2997
+ * THE constructor of a `MatchEvent`, on the feed path (the candidates the ESPN
2998
+ * detail grammar built) and the cache path alike. An event with no side, a
2999
+ * side that is neither, an unreadable minute or an added time outside 1..30 is
3000
+ * refused (`null`); the match stands. Keys in the order `MatchEvent` declares
3001
+ * them. Exported for the one other reader of an event, the ambient view, which
3002
+ * re-seals the `lastGoal` the refresher stored on a cached live record.
3003
+ */
3004
+ declare function sealEvent(raw: unknown): MatchEvent | null;
2875
3005
  /**
2876
3006
  * Validate candidate parts into a Match, or say why not.
2877
3007
  *
@@ -3054,6 +3184,411 @@ declare const FAN_PROJECT = "Independent fan project";
3054
3184
  */
3055
3185
  declare function disclaimerLine(host?: string): string;
3056
3186
 
3187
+ /**
3188
+ * Where a selection came from: the command line's `--competition` or a tool's
3189
+ * `competition` argument (`flag`), `CLAUDINHO_COMPETITION` (`env`), or the
3190
+ * user's saved choice (`saved`: the config file `claudinho follow` writes).
3191
+ * Nothing else chooses: with none of the three there is no competition
3192
+ * (`{ kind: 'none' }`), never a default.
3193
+ */
3194
+ type ChosenBy = 'flag' | 'env' | 'saved';
3195
+ /** A competition a request is for, and where that choice came from. */
3196
+ interface SelectedCompetition {
3197
+ readonly kind: 'selected';
3198
+ /** The provider's slug the request asks for. */
3199
+ readonly slug: string;
3200
+ /** The table's alias; absent for a raw slug. */
3201
+ readonly alias?: string;
3202
+ /** What a surface names it: the table's name, or a raw slug as it is. */
3203
+ readonly name: string;
3204
+ readonly chosenBy: ChosenBy;
3205
+ /** A raw slug the table does not hold: the escape hatch, labelled. */
3206
+ readonly experimental: boolean;
3207
+ }
3208
+ /**
3209
+ * What the edge resolved: a competition; a value that is neither an alias nor
3210
+ * a slug, REFUSED with the aliases (an unknown value is never a request); or
3211
+ * `none`: nothing was chosen (no flag, no environment, no saved choice). The
3212
+ * finished World Cup is not a default anyone falls into without choosing.
3213
+ */
3214
+ type CompetitionSelection = SelectedCompetition | {
3215
+ readonly kind: 'refused';
3216
+ readonly value: string;
3217
+ readonly aliases: string[];
3218
+ /** The source that gave the refused value (a flag or the environment: the file's reader refuses its own). */
3219
+ readonly chosenBy: ChosenBy;
3220
+ } | {
3221
+ readonly kind: 'none';
3222
+ };
3223
+ /**
3224
+ * The ONE constructor of a selected competition: a slug and where it was
3225
+ * chosen, described by the table (its alias and name) or, for a slug the
3226
+ * table does not hold, as itself and experimental. The resolver builds every
3227
+ * selection through it; an edge that already holds a slug (a config built
3228
+ * without the resolver) describes it through it too, never by hand.
3229
+ */
3230
+ declare function selectedCompetition(slug: string, chosenBy: ChosenBy): SelectedCompetition;
3231
+ /**
3232
+ * THE EDGE. The one function that decides which competition a request is for,
3233
+ * from the values its edge hands in: the flag (`--competition`, a tool's
3234
+ * `competition` argument), then the environment (`CLAUDINHO_COMPETITION`), then
3235
+ * the saved choice (the config file's `competition`, read at the edge through
3236
+ * core's one reader: `readUserConfig`). The FIRST present source decides (an
3237
+ * empty string is absent): a present value that is refused is refused, even
3238
+ * when a lower source holds a valid one (what was asked for is not answered
3239
+ * with something else). With no source present, `none`: nothing is chosen,
3240
+ * and every competition-answering surface says so instead of answering.
3241
+ *
3242
+ * Each value is an alias (`premier-league`), a slug in the table (`eng.1`), or
3243
+ * a raw ESPN slug the table does not hold (`fifa.friendly`, `esp.copa_del_rey`:
3244
+ * lower-case segments of letters, digits and underscores joined by dots, 64
3245
+ * units at most; experimental);
3246
+ * anything else (`foo`, `ENG.1`, a space) is refused with the aliases.
3247
+ *
3248
+ * Core reads NO environment and no file: the edges pass them. It is called
3249
+ * where a request ENTERS (the CLI's option resolution, the MCP server's
3250
+ * request) and nowhere else. From there the competition travels as a value
3251
+ * (on the config, on the adapter), so nothing further down can answer for a
3252
+ * different competition halfway through. `core/test/selection-identity.test.ts`
3253
+ * fails if a call appears anywhere else.
3254
+ */
3255
+ declare function resolveCompetition(explicit?: string, env?: string, saved?: string): CompetitionSelection;
3256
+ /**
3257
+ * The line every competition-answering text answer prints after its header:
3258
+ * the competition's name, then where the choice came from when it was the
3259
+ * flag or the environment (`from the command line`; on MCP, `from the
3260
+ * request`; `from the environment`), then `experimental` for a raw slug. A
3261
+ * saved choice prints the name alone. The name is not localized; the rest is.
3262
+ * Empty for a selection that is not a competition.
3263
+ */
3264
+ declare function modeLine(selection: CompetitionSelection, lang?: string,
3265
+ /** What a flag is on this surface: the command line's, or a tool request's argument. */
3266
+ flag?: 'command' | 'request'): string;
3267
+ /** The structured form of a selection: what `--json` and MCP `data` carry. */
3268
+ interface CompetitionKey {
3269
+ readonly slug: string;
3270
+ readonly alias?: string;
3271
+ readonly name: string;
3272
+ readonly chosenBy: ChosenBy;
3273
+ readonly experimental?: true;
3274
+ }
3275
+ /**
3276
+ * The selection as ONE structured key, `competition`, for every
3277
+ * competition-answering structured answer (CLI `--json`, MCP `data`): the
3278
+ * alias only when there is one, `experimental` only when true; `null` when
3279
+ * nothing is chosen (beside the `noCompetition` verdict: see
3280
+ * {@link selectionVerdict}). Nothing for a refused value (it is an error, never
3281
+ * an answer). Every emit site spreads this; none builds the key by hand.
3282
+ */
3283
+ declare function selectionExtras(selection: CompetitionSelection): {
3284
+ competition?: CompetitionKey | null;
3285
+ };
3286
+ /**
3287
+ * The verdict a selection states about every answer made under it: with
3288
+ * nothing chosen, `noCompetition` (the first replacing verdict: its sentence
3289
+ * stands instead of any answer, and its key goes beside `competition: null`);
3290
+ * nothing otherwise. A surface hands THIS to `verdictNotice`/`verdictExtras`,
3291
+ * never an object it builds itself.
3292
+ */
3293
+ declare function selectionVerdict(selection: CompetitionSelection): VerdictSource;
3294
+ /**
3295
+ * Why a selection is not a competition, in the reader's language; undefined
3296
+ * for a competition. A refused value names the value (bounded) and the
3297
+ * aliases; nothing chosen is the CLI's sentence (`claudinho follow <alias>`,
3298
+ * `follow --list`): MCP answers nothing chosen with the `noCompetition`
3299
+ * verdict's own sentence (`verdictNotice`), never this one. The CLI raises it
3300
+ * as an input error, MCP a refused value as a tool error, before any request.
3301
+ */
3302
+ declare function selectionRefusal(selection: CompetitionSelection, lang?: string): string | undefined;
3303
+ /** The competition whose schedule ships bundled in the clients: the World Cup. */
3304
+ declare const BUNDLE_COMPETITION = "fifa.world";
3305
+ /**
3306
+ * The edition the bundled schedule describes, read from the schedule itself
3307
+ * (the year of its first kickoff) rather than written down a second time.
3308
+ */
3309
+ declare function bundleSeasonYear(): number;
3310
+ /**
3311
+ * Does the bundled schedule describe what this request is about?
3312
+ *
3313
+ * The competition is an ARGUMENT — the caller's adapter states it — never a
3314
+ * default. Off the bundle, every path built on the skeleton (date merge,
3315
+ * `match <id>`, `next`, the bracket, the knockout-fixture cache, the market
3316
+ * fixture) must not read it: an empty foreign day once showed 104 World Cup
3317
+ * fixtures with foreign attribution (audit A03).
3318
+ *
3319
+ * The bundle is ONE EDITION of its competition. When the provider reported the
3320
+ * season a response belongs to and it is a different one, the bundle does not
3321
+ * describe that response. With no provider answer (offline, degraded) there is
3322
+ * nothing to compare, and the bundle stays what it is: the 2026 edition.
3323
+ */
3324
+ declare function bundleApplies(competition: string, season?: SeasonInfo): boolean;
3325
+ /**
3326
+ * The competitions that HAVE NO BRACKET: league seasons with no knockout tie of
3327
+ * their own, where "no bracket" is the answer, not a gap. Written down in the
3328
+ * supported table (`bracket: 'not-applicable'`), one fact each, never inferred
3329
+ * from the standings shape (`STANDINGS_SHAPE` says
3330
+ * how a table is read, not whether a knockout follows it: `uefa.champions` and
3331
+ * `mex.1` read as one league table and both have one).
3332
+ * - `eng.1`: the Premier League; a 38-round league, no play-off.
3333
+ * - `esp.1`: LaLiga; a 38-round league, no play-off.
3334
+ * Deliberately NOT here: `ita.1` (championship and relegation play-offs since
3335
+ * the FIGC's May 2026 decision), `ger.1` (the relegation play-off), `mex.1`
3336
+ * (the Liguilla), `uefa.champions` (a knockout after the league phase). A
3337
+ * competition joins by a written fact. A derived view, kept for its readers (it
3338
+ * is exported); {@link bracketCapability} reads the row itself.
3339
+ */
3340
+ declare const NO_BRACKET: ReadonlySet<string>;
3341
+ /**
3342
+ * What `bracket` is for a competition, one of three values, read from its ROW
3343
+ * (one row, one fact: a listing, the README matrix and the command cannot
3344
+ * disagree):
3345
+ * - `offered`: the row offers it (only the bundled competition can:
3346
+ * `deriveTables` refuses any other row that does);
3347
+ * - `inapplicable`: the row says the competition has none (`not-applicable`);
3348
+ * - `unsupported`: it may have one, and it is not offered yet; also a slug
3349
+ * the table does not hold.
3350
+ */
3351
+ declare function bracketCapability(competition: string, table?: readonly CompetitionEntry[]): 'offered' | 'inapplicable' | 'unsupported';
3352
+
3353
+ /**
3354
+ * The ambient view: what `claudinho ambient --json` prints, ONE JSON object on
3355
+ * one line, for a program that shows the statusline and the hook itself (the
3356
+ * Claude Code plugin's band, its toasts and its prompt context). A type and
3357
+ * its documentation only: the CLI builds it from its local cache (the
3358
+ * statusline's reader, in `packages/cli`), and core reads no cache and no
3359
+ * environment for it.
3360
+ *
3361
+ * Three shapes reach a reader, and the command always exits 0:
3362
+ * - nothing chosen (no `--competition`, no `CLAUDINHO_COMPETITION`, no saved
3363
+ * choice): the selection's structured twin, `competition: null` beside the
3364
+ * verdict that says nothing is chosen, and `line` (the statusline's
3365
+ * first-run line); no cache is read and no refresher started;
3366
+ * - a value that is no competition, or a failure anywhere: `line` (the
3367
+ * statusline's empty line) and `empty: true` alone, no view;
3368
+ * - a selected competition: an {@link AmbientView}.
3369
+ */
3370
+
3371
+ /**
3372
+ * One part of the band's line (`lineParts`): a run of its text, `strong` for a
3373
+ * score token the fit kept whole. The parts' texts joined are the line.
3374
+ */
3375
+ interface AmbientLinePart {
3376
+ readonly text: string;
3377
+ readonly style?: 'strong';
3378
+ }
3379
+ /** The two names the hook's line prints for a record (a nation's roster name on the bundled competition). */
3380
+ interface AmbientNames {
3381
+ readonly home: string;
3382
+ readonly away: string;
3383
+ }
3384
+ /**
3385
+ * A finished match as the ambient view lists it (`finished`): the sealed
3386
+ * record (status `FT`, its final score), as a live one is serialized, with:
3387
+ */
3388
+ type AmbientFinishedMatch = Match & {
3389
+ /**
3390
+ * The side of the SAVED pin (`claudinho follow <alias> --team`, by core's
3391
+ * `isPinnedSide`), or `null`: never `CLAUDINHO_TEAM`, which only orders.
3392
+ */
3393
+ readonly pinnedSide: 'home' | 'away' | null;
3394
+ /** The names the hook's line prints for it. */
3395
+ readonly names: AmbientNames;
3396
+ /** The hook's own line for it, `(FT)` in the minute's place. */
3397
+ readonly line: string;
3398
+ };
3399
+ /**
3400
+ * A live match as the ambient view lists it: the sealed record, as the other
3401
+ * `--json` twins serialize a `Match` (`status`, the `score` object, `shootout`
3402
+ * after a shootout, `Team.id` where the cache holds it, a nation's generated
3403
+ * `flag`, no `flag` key on a club), with no `events` key (the ambient reader
3404
+ * never seals a timeline), and what it says about the reader's own team, the
3405
+ * names and the last goal:
3406
+ */
3407
+ type AmbientMatch = Match & {
3408
+ /**
3409
+ * A side of it is the ambient PREFERENCE's (`pick`): `CLAUDINHO_TEAM`'s
3410
+ * code, else the saved pin. The picked matches come first in the list.
3411
+ */
3412
+ readonly picked: boolean;
3413
+ /**
3414
+ * A side of it is the SAVED pin's (`claudinho follow <alias> --team`), by
3415
+ * the pin's id when it has one (a club), by its code when it has none (the
3416
+ * World Cup's nations); whatever `CLAUDINHO_TEAM` prefers.
3417
+ */
3418
+ readonly pinned: boolean;
3419
+ /** Which side is the SAVED pin's (by core's `isPinnedSide`), or `null`: never `CLAUDINHO_TEAM`'s. */
3420
+ readonly pinnedSide: 'home' | 'away' | null;
3421
+ /** The names the hook's line prints for it (a nation's roster name on the bundled competition). */
3422
+ readonly names: AmbientNames;
3423
+ /**
3424
+ * The hook's own line for this record, as `claudinho hook` prints it (the
3425
+ * names, pinned to the World Cup's roster on the bundle, each with its flag
3426
+ * where flags are on and the side has one, the scoreline with a shootout's
3427
+ * tally, the minute token: `67'`, `half-time`, `live`). A program says it,
3428
+ * never composes one.
3429
+ */
3430
+ readonly line: string;
3431
+ /**
3432
+ * The goal that made the record's score, PROVEN by the refresher (its
3433
+ * scoring events counted per side equal the score: core's
3434
+ * `provenLastGoal`), stored on the cached record and re-sealed by the
3435
+ * reader with core's `sealEvent` and kept only as a goal, an own goal or a
3436
+ * penalty whose `teamCode` is the code of the side its `side` names, a side
3437
+ * that has scored (its regulation score at least 1); `null`
3438
+ * when nothing is proven or the stored value is anything else.
3439
+ */
3440
+ readonly lastGoal: MatchEvent | null;
3441
+ };
3442
+ /** The ambient view of a selected competition, its keys in this order. */
3443
+ interface AmbientView {
3444
+ /**
3445
+ * The statusline's line rendered in `lang` (the same reader and the same
3446
+ * options as `claudinho prompt`, which prints it in English), fitted to
3447
+ * `--columns N` when given: whole matches are kept while they fit and
3448
+ * the rest counted in the `+N` (or `+more`) suffix, which is never cut
3449
+ * while the width holds it; below the suffix's own width
3450
+ * the line is the width's cut, never wider than asked. Its own tokens are in
3451
+ * `lang` (the countdown, the syncing phrase, the live segment's half-time
3452
+ * and live words); the overflow marker (`+N`, `+more`), the World Cup's
3453
+ * sign-off and nothing known (`⚽ —`) are English in every language, so
3454
+ * `idle` and `empty` say what they say in every language.
3455
+ */
3456
+ readonly line: string;
3457
+ /**
3458
+ * The line as parts, built by the fitter as it places each shown score
3459
+ * token: their texts joined are `line` exactly, a score token the fit kept
3460
+ * whole is `strong`, one it cut is not. One plain part, the line itself, on
3461
+ * the countdown, the syncing line, nothing known and the sign-off, and
3462
+ * whenever the parts would not join to the line.
3463
+ */
3464
+ readonly lineParts: readonly AmbientLinePart[];
3465
+ /**
3466
+ * The line is the one long-lived line, the edition's sign-off (the World
3467
+ * Cup's, once every bundled window has closed): nothing changes until the
3468
+ * user follows another competition, so a program reads it slowly. Said of
3469
+ * the line before any fit: a program reads the pace from this, never from the
3470
+ * text, which `--columns` may have cut.
3471
+ */
3472
+ readonly idle: boolean;
3473
+ /**
3474
+ * The line says nothing is known (`⚽ —`): no live match read, no window to
3475
+ * sync in, nothing to count down to. A program shows nothing for it. Said
3476
+ * of the line before any fit: a program reads the visibility from this,
3477
+ * never from the text.
3478
+ */
3479
+ readonly empty: boolean;
3480
+ /** The hook's block, as `claudinho hook` prints it while a match is live; `null` when it prints nothing. */
3481
+ readonly context: string | null;
3482
+ /**
3483
+ * The live matches the statusline reads (a believed snapshot's, inside the
3484
+ * display window), the preference's first. `complete` says the scan was
3485
+ * whole and `total` is exact only then; an empty list with `complete: false`
3486
+ * is "not known". An empty list is "nothing on" ONLY beside `current: true`:
3487
+ * with `current: false` (no snapshot, a stale one, a stamp the reader does
3488
+ * not believe, a degraded one, one whose read was not whole or that does
3489
+ * not say, the syncing window) it says nothing about
3490
+ * play, a match may be on (`line` is the authority: it prints
3491
+ * `live · syncing…` in the window), and a program must never read
3492
+ * `complete && items.length === 0` alone as "nothing on". A degraded
3493
+ * snapshot (the last read failed) may still carry a live record: it is
3494
+ * listed, best effort, as the line shows it, and is never current.
3495
+ */
3496
+ readonly live: BoundedList<AmbientMatch>;
3497
+ /**
3498
+ * The matches the refresher SAW in play that a whole read then returned
3499
+ * finished (the snapshot's record of play), each for 10 minutes from the
3500
+ * read that first saw it finished, judged by the reader's clock (a stamp in
3501
+ * the future is not believed), whatever the snapshot's display window (the
3502
+ * refresher stops polling once the last match ends, so the snapshot ages
3503
+ * past it while an entry is still inside its own 10 minutes); never one the
3504
+ * live list holds. Listed only from a snapshot whose live read was whole
3505
+ * (`liveComplete: true`); otherwise `[]`, which then says nothing. At most
3506
+ * 64. Absence from it never means a match is over.
3507
+ */
3508
+ readonly finished: readonly AmbientFinishedMatch[];
3509
+ /**
3510
+ * The live list is a believed snapshot's inside its display window (its
3511
+ * stamp's age, by the reader's own rule, is finite and short of the window),
3512
+ * the snapshot is not degraded (a degraded one means the fetch failed, not
3513
+ * that the feed said nothing: it is never current, whatever it carries), the
3514
+ * snapshot states that the read that filled its live slice was whole (a read
3515
+ * that was not, an unreadable record left out beside readable ones, is never
3516
+ * current; nor is a snapshot that does not say, written before 0.11.2, until
3517
+ * one refresh cycle rewrites it), and the line is not syncing: then, and
3518
+ * only then, an empty list means the feed said nothing is in play.
3519
+ */
3520
+ readonly current: boolean;
3521
+ /**
3522
+ * The fixture the statusline's countdown names (its resolved pairing; the
3523
+ * preference's first), whether or not a match is in play now; `null` when
3524
+ * there is none to count down to. A fixture ahead, or a DUE one (still
3525
+ * scheduled, its kickoff passed by at most 30 minutes, not held by the
3526
+ * snapshot's record of play: the line reads "now"); never one in play.
3527
+ */
3528
+ readonly next: Match | null;
3529
+ /**
3530
+ * The ambient preference as the CLI holds it: `{ code }` from
3531
+ * `CLAUDINHO_TEAM`, the saved pin (`{ id?, code, name }`) when that is
3532
+ * unset, or `null`.
3533
+ */
3534
+ readonly pick: {
3535
+ readonly code: string;
3536
+ } | Pin | null;
3537
+ /**
3538
+ * Present (and `true`) when `CLAUDINHO_TEAM` is set to a value the hot path
3539
+ * cannot read offline (off the World Cup, anything but a three-letter code;
3540
+ * on it, a name its roster does not hold): `pick` is then `null`, never the
3541
+ * pin (the environment is the override).
3542
+ */
3543
+ readonly pickUnreadable?: true;
3544
+ /** The selection, as every `--json` answer carries it (core `selectionExtras`). */
3545
+ readonly competition: CompetitionKey;
3546
+ /**
3547
+ * The CLI's resolved language (`--lang`, `CLAUDINHO_LANG`, `LANG`'s language
3548
+ * part, each only when it is one of the four, else `en`), the language of
3549
+ * `line`, `lineParts` and `words`. `context`, `attribution`, `disclaimer`
3550
+ * and each record's `line` stay English in every language.
3551
+ */
3552
+ readonly lang: Lang;
3553
+ /**
3554
+ * The plugin's moment words in `lang` (core's `moment.*` keys, `momentWords`):
3555
+ * `goalFor` and `win` templates holding `{team}` once, for the plugin to
3556
+ * fill with a record's own `names`.
3557
+ */
3558
+ readonly words: MomentWords;
3559
+ /** The snapshot says its last refresh failed (`false` with no snapshot). */
3560
+ readonly degraded: boolean;
3561
+ /** The provider the snapshot was read from, whatever its stamp; `null` with no snapshot. */
3562
+ readonly source: string | null;
3563
+ /**
3564
+ * When the snapshot was written (ISO 8601, re-emitted canonically), or
3565
+ * `null` with no snapshot or a stamp the reader does not believe (further in
3566
+ * the future than its clock-skew allowance: its live scores are not shown).
3567
+ */
3568
+ readonly updatedAt: string | null;
3569
+ /**
3570
+ * When the snapshot's live scores stop being shown (`updatedAt` plus the
3571
+ * statusline's display window), or `null` whenever `updatedAt` is.
3572
+ */
3573
+ readonly staleAfter: string | null;
3574
+ /** The non-affiliation sentence, core's `DISCLAIMER`. */
3575
+ readonly disclaimer: string;
3576
+ /**
3577
+ * The provider's attribution sentence, in English as every ambient string:
3578
+ * core's `live.data` copy with `liveSourceLabel(source)` (`Live data:
3579
+ * ESPN`), when the snapshot names a provider (`source` is a string) AND
3580
+ * the line is neither the sign-off (`idle`) nor nothing known (`empty`);
3581
+ * `null` otherwise: no snapshot, the sign-off (made from the bundled clock),
3582
+ * nothing known. `degraded` does not decide: a degraded snapshot still shows
3583
+ * a live row an earlier read served, or a countdown to a fixture discovery
3584
+ * read; nor does a read that was not whole. A limit: on the bundled
3585
+ * competition, a countdown made from the bundled skeleton (before its
3586
+ * knockout pairings resolve) would be attributed too; unreachable while that
3587
+ * edition is over.
3588
+ */
3589
+ readonly attribution: string | null;
3590
+ }
3591
+
3057
3592
  /** The two v1 snippet shapes. `social` is the rich card; `compact` is one terse line per match. */
3058
3593
  type ShareStyle = 'compact' | 'social';
3059
3594
  /** The project social tag — a distribution unit, default-on but removable. */
@@ -3544,172 +4079,6 @@ declare function isPlaceholderSide(team: Pick<Team, 'flag'>): boolean;
3544
4079
  /** The bundled knockout bracket topology (generated by gen:schedule). */
3545
4080
  declare function loadBracketTopology(): BracketTopology;
3546
4081
 
3547
- /**
3548
- * Where a selection came from: the command line's `--competition` or a tool's
3549
- * `competition` argument (`flag`), `CLAUDINHO_COMPETITION` (`env`), or the
3550
- * user's saved choice (`saved`: the config file `claudinho follow` writes).
3551
- * Nothing else chooses: with none of the three there is no competition
3552
- * (`{ kind: 'none' }`), never a default.
3553
- */
3554
- type ChosenBy = 'flag' | 'env' | 'saved';
3555
- /** A competition a request is for, and where that choice came from. */
3556
- interface SelectedCompetition {
3557
- readonly kind: 'selected';
3558
- /** The provider's slug the request asks for. */
3559
- readonly slug: string;
3560
- /** The table's alias; absent for a raw slug. */
3561
- readonly alias?: string;
3562
- /** What a surface names it: the table's name, or a raw slug as it is. */
3563
- readonly name: string;
3564
- readonly chosenBy: ChosenBy;
3565
- /** A raw slug the table does not hold: the escape hatch, labelled. */
3566
- readonly experimental: boolean;
3567
- }
3568
- /**
3569
- * What the edge resolved: a competition; a value that is neither an alias nor
3570
- * a slug, REFUSED with the aliases (an unknown value is never a request); or
3571
- * `none`: nothing was chosen (no flag, no environment, no saved choice). The
3572
- * finished World Cup is not a default anyone falls into without choosing.
3573
- */
3574
- type CompetitionSelection = SelectedCompetition | {
3575
- readonly kind: 'refused';
3576
- readonly value: string;
3577
- readonly aliases: string[];
3578
- /** The source that gave the refused value (a flag or the environment: the file's reader refuses its own). */
3579
- readonly chosenBy: ChosenBy;
3580
- } | {
3581
- readonly kind: 'none';
3582
- };
3583
- /**
3584
- * The ONE constructor of a selected competition: a slug and where it was
3585
- * chosen, described by the table (its alias and name) or, for a slug the
3586
- * table does not hold, as itself and experimental. The resolver builds every
3587
- * selection through it; an edge that already holds a slug (a config built
3588
- * without the resolver) describes it through it too, never by hand.
3589
- */
3590
- declare function selectedCompetition(slug: string, chosenBy: ChosenBy): SelectedCompetition;
3591
- /**
3592
- * THE EDGE. The one function that decides which competition a request is for,
3593
- * from the values its edge hands in: the flag (`--competition`, a tool's
3594
- * `competition` argument), then the environment (`CLAUDINHO_COMPETITION`), then
3595
- * the saved choice (the config file's `competition`, read at the edge through
3596
- * core's one reader: `readUserConfig`). The FIRST present source decides (an
3597
- * empty string is absent): a present value that is refused is refused, even
3598
- * when a lower source holds a valid one (what was asked for is not answered
3599
- * with something else). With no source present, `none`: nothing is chosen,
3600
- * and every competition-answering surface says so instead of answering.
3601
- *
3602
- * Each value is an alias (`premier-league`), a slug in the table (`eng.1`), or
3603
- * a raw ESPN slug the table does not hold (`fifa.friendly`, `esp.copa_del_rey`:
3604
- * lower-case segments of letters, digits and underscores joined by dots, 64
3605
- * units at most; experimental);
3606
- * anything else (`foo`, `ENG.1`, a space) is refused with the aliases.
3607
- *
3608
- * Core reads NO environment and no file: the edges pass them. It is called
3609
- * where a request ENTERS (the CLI's option resolution, the MCP server's
3610
- * request) and nowhere else. From there the competition travels as a value
3611
- * (on the config, on the adapter), so nothing further down can answer for a
3612
- * different competition halfway through. `core/test/selection-identity.test.ts`
3613
- * fails if a call appears anywhere else.
3614
- */
3615
- declare function resolveCompetition(explicit?: string, env?: string, saved?: string): CompetitionSelection;
3616
- /**
3617
- * The line every competition-answering text answer prints after its header:
3618
- * the competition's name, then where the choice came from when it was the
3619
- * flag or the environment (`from the command line`; on MCP, `from the
3620
- * request`; `from the environment`), then `experimental` for a raw slug. A
3621
- * saved choice prints the name alone. The name is not localized; the rest is.
3622
- * Empty for a selection that is not a competition.
3623
- */
3624
- declare function modeLine(selection: CompetitionSelection, lang?: string,
3625
- /** What a flag is on this surface: the command line's, or a tool request's argument. */
3626
- flag?: 'command' | 'request'): string;
3627
- /** The structured form of a selection: what `--json` and MCP `data` carry. */
3628
- interface CompetitionKey {
3629
- readonly slug: string;
3630
- readonly alias?: string;
3631
- readonly name: string;
3632
- readonly chosenBy: ChosenBy;
3633
- readonly experimental?: true;
3634
- }
3635
- /**
3636
- * The selection as ONE structured key, `competition`, for every
3637
- * competition-answering structured answer (CLI `--json`, MCP `data`): the
3638
- * alias only when there is one, `experimental` only when true; `null` when
3639
- * nothing is chosen (beside the `noCompetition` verdict: see
3640
- * {@link selectionVerdict}). Nothing for a refused value (it is an error, never
3641
- * an answer). Every emit site spreads this; none builds the key by hand.
3642
- */
3643
- declare function selectionExtras(selection: CompetitionSelection): {
3644
- competition?: CompetitionKey | null;
3645
- };
3646
- /**
3647
- * The verdict a selection states about every answer made under it: with
3648
- * nothing chosen, `noCompetition` (the first replacing verdict: its sentence
3649
- * stands instead of any answer, and its key goes beside `competition: null`);
3650
- * nothing otherwise. A surface hands THIS to `verdictNotice`/`verdictExtras`,
3651
- * never an object it builds itself.
3652
- */
3653
- declare function selectionVerdict(selection: CompetitionSelection): VerdictSource;
3654
- /**
3655
- * Why a selection is not a competition, in the reader's language; undefined
3656
- * for a competition. A refused value names the value (bounded) and the
3657
- * aliases; nothing chosen is the CLI's sentence (`claudinho follow <alias>`,
3658
- * `follow --list`): MCP answers nothing chosen with the `noCompetition`
3659
- * verdict's own sentence (`verdictNotice`), never this one. The CLI raises it
3660
- * as an input error, MCP a refused value as a tool error, before any request.
3661
- */
3662
- declare function selectionRefusal(selection: CompetitionSelection, lang?: string): string | undefined;
3663
- /** The competition whose schedule ships bundled in the clients: the World Cup. */
3664
- declare const BUNDLE_COMPETITION = "fifa.world";
3665
- /**
3666
- * The edition the bundled schedule describes, read from the schedule itself
3667
- * (the year of its first kickoff) rather than written down a second time.
3668
- */
3669
- declare function bundleSeasonYear(): number;
3670
- /**
3671
- * Does the bundled schedule describe what this request is about?
3672
- *
3673
- * The competition is an ARGUMENT — the caller's adapter states it — never a
3674
- * default. Off the bundle, every path built on the skeleton (date merge,
3675
- * `match <id>`, `next`, the bracket, the knockout-fixture cache, the market
3676
- * fixture) must not read it: an empty foreign day once showed 104 World Cup
3677
- * fixtures with foreign attribution (audit A03).
3678
- *
3679
- * The bundle is ONE EDITION of its competition. When the provider reported the
3680
- * season a response belongs to and it is a different one, the bundle does not
3681
- * describe that response. With no provider answer (offline, degraded) there is
3682
- * nothing to compare, and the bundle stays what it is: the 2026 edition.
3683
- */
3684
- declare function bundleApplies(competition: string, season?: SeasonInfo): boolean;
3685
- /**
3686
- * The competitions that HAVE NO BRACKET: league seasons with no knockout tie of
3687
- * their own, where "no bracket" is the answer, not a gap. Written down in the
3688
- * supported table (`bracket: 'not-applicable'`), one fact each, never inferred
3689
- * from the standings shape (`STANDINGS_SHAPE` says
3690
- * how a table is read, not whether a knockout follows it: `uefa.champions` and
3691
- * `mex.1` read as one league table and both have one).
3692
- * - `eng.1`: the Premier League; a 38-round league, no play-off.
3693
- * - `esp.1`: LaLiga; a 38-round league, no play-off.
3694
- * Deliberately NOT here: `ita.1` (championship and relegation play-offs since
3695
- * the FIGC's May 2026 decision), `ger.1` (the relegation play-off), `mex.1`
3696
- * (the Liguilla), `uefa.champions` (a knockout after the league phase). A
3697
- * competition joins by a written fact. A derived view, kept for its readers (it
3698
- * is exported); {@link bracketCapability} reads the row itself.
3699
- */
3700
- declare const NO_BRACKET: ReadonlySet<string>;
3701
- /**
3702
- * What `bracket` is for a competition, one of three values, read from its ROW
3703
- * (one row, one fact: a listing, the README matrix and the command cannot
3704
- * disagree):
3705
- * - `offered`: the row offers it (only the bundled competition can:
3706
- * `deriveTables` refuses any other row that does);
3707
- * - `inapplicable`: the row says the competition has none (`not-applicable`);
3708
- * - `unsupported`: it may have one, and it is not offered yet; also a slug
3709
- * the table does not hold.
3710
- */
3711
- declare function bracketCapability(competition: string, table?: readonly CompetitionEntry[]): 'offered' | 'inapplicable' | 'unsupported';
3712
-
3713
4082
  /**
3714
4083
  * Metadata that belongs to ONE fetch result.
3715
4084
  *
@@ -3911,4 +4280,4 @@ declare function lookAtEntry(path: string): FileEntry;
3911
4280
  */
3912
4281
  declare function lookAtOwnFile(path: string, maxBytes: number): OwnFile;
3913
4282
 
3914
- export { BRACKET_STAGE_ORDER, BUNDLE_COMPETITION, type BatchResolution, type BetweenEditions, type BoundedList, type BracketFormatOpts, type BracketMatchNode, type BracketMatchView, type BracketResult, type BracketShareCard, type BracketTopology, type BracketView, type BuildSignalInput, COMPETITION_KIND, COUNTDOWN_NOW, type Capabilities, type Capability, type ChosenBy, type ClubResolution, type CompetitionEntry, type CompetitionKey, type CompetitionKind, type CompetitionSelection, DEFAULT_COMPETITION, DEFAULT_COOLDOWN_MS, DEFAULT_FLAVOR, DEFAULT_MAX_AGE_MS, DISCLAIMER, type DayAttribution, type DerivedTables, EARLIER_RECORD_NOTE, EspnAdapter, type EspnAdapterOptions, FAN_PROJECT, FLAVOR_BANKS, FLAVOR_LEVELS, FLAVOR_MOMENTS, FakeMarketProvider, type FakeMarketProviderOptions, type FavoriteStrength, type FetchMeta, type FetchWindowOptions, type FileEntry, type Flair, type FlairOpts, type FlavorBank, type FlavorLevel, type Moment as FlavorMoment, type FlavorOpts, type FormatOpts, type GroupStandings, KNOCKOUT_EXTRA_TIME_MS, KNOWN_SOURCES, type KnockoutFixturesResult, LIVE_WINDOW_MS, type Lang, type LedgerRow, type ListedCompetition, type LiveReadResult, type LiveResult, MARKETS_SCOPE_NOTE, MARKET_COMPETITIONS, MAX_CONFIG_BYTES, MAX_COOLDOWN_MS, MAX_LABEL_COLUMNS, MAX_RESPONSE_BYTES, MAX_SCHEDULE_INDEX, type MapContext, type MarketFavorite, type MarketMapping, type MarketMappingTable, type MarketOutcome, type MarketOutcomeKind, type MarketProvider, type MarketSignal, type MarketSignalOptions, type MarketSignalsResult, type Match, type MatchByIdResult, type MatchEvent, type MatchShareCard, NO_BRACKET, type NextFixtureResult, type NoConfigReason, type Outcome, type OwnFile, type ParseResult, type Pin, PolymarketProvider, type PolymarketProviderOptions, type ProviderAdapter, type ProviderCapabilities, ProviderError, type ProviderErrorKind, type PunditPick, RALLY_CRIES, type RallyCry, type RallyPin, type ReadAccount, type ResolvedParticipant, ResponseTooLargeError, type Roster, SCHEDULE_AHEAD_DAYS, SCHEDULE_LOOKBACK_DAYS, SEASON_SLUG, SHARE_DISCLAIMER, SHARE_HASHTAG, STANDINGS_SHAPE, SUPPORTED, type ScheduleAheadResult, type ScheduleEntry, type SeasonInfo, type SelectedCompetition, type Selection, type ShareBracketInput, type ShareBracketOptions, type ShareCardContext, type ShareCardMarket, type ShareCardView, type ShareSnippetInput, type ShareSnippetOptions, type ShareStyle, type ShareTableInput, type SlotRef, type SmallFile, type Stage, type StandingRow, type StandingsResult, type Status, TABLE_KEY_ARG, TEAM_KIND, type TableData, type TableShareCard, type Team, type TeamInfo, type TeamKind, type TeamLookup, type UserConfig, type UserConfigRead, type VerdictExtras, type VerdictSource, allFixtures, allTeams, ambiguous, asFlavorLevel, attachFetchMeta, bounded, bracketCapability, bracketShareCard, buildBracketTopology, buildBracketView, buildMarketSignal, bundleApplies, bundleSeasonYear, byKickoff, cacheDirFor, cacheableKeys, capabilitiesOf, competitionBase, competitionKind, competitionLabel, competitionValue, computeStandings, configPath, countdown, countdownPhrase, currentOrNextFixtureForTeam, dateNoneRead, dateNoneReadSentence, dateShareCard, dateUnreached, dateUnreachedSentence, dayAttribution, definitiveNone, deriveFavorite, deriveTables, disclaimerLine, displayWidth, emptyBatch, entryOf, favoriteStrength, fetchMeta, fixturesByDate, fixturesByGroup, fixturesByTeam, fixturesInLiveWindow, flagEmoji, flavorsFor, formatBracketCompactLine, formatBracketList, formatBracketMatchLine, formatBracketTree, formatDate, formatKickoff, formatShareBracket, formatShareSnippet, formatShareTable, formatTime, getBracket, getKnockoutFixtures, getLiveMatches, getLiveRead, getMarketSignal, getMarketSignals, getMatchById, getMatchesForDate, getNextFixtureForTeam, getScheduleAhead, getStandings, groups, hasLiveWindow, hasSaneDistribution, humanLabel, isCacheable, isFinished, isFlavorLevel, isHumanLabel, isKnockoutStage, isKnownSource, isLive, isMexicoNationalTeam, isPinnedSide, isPlaceholderSide, isReliableMarketSignal, isStaleSignal, isTeam, isTournamentWindowOver, isUpcoming, isValidDate, isValidTimeZone, joinSegments, knockoutWindow, listCompetitions, liveNoneRead, liveNoneReadSentence, liveShareCard, liveSourceLabel, liveWindowMsFor, loadBracketTopology, localDate, lookAtEntry, lookAtOwnFile, lookAtSmallFile, lookupTeam, makeAdapter, makeMarketProvider, malformed, mapEspnEvent, mapsCleanly, marketAttributionText, marketBlock, marketDisplayable, marketFavoriteText, marketFixtureForTeam, marketLine, marketProbabilityText, marketRelevant, marketScopeVerdict, marketSignalRendersFor, marketSourceLabel, marketsCoverCompetition, marketsNoneRead, marketsNoneReadNote, marketsNoneReadSentence, matchFlair, matchFlairs, matchFlavor, matchKey, matchLocation, matchNoneReadSentence, matchShareCard, matchWindowSentence, mergeLive, modeLine, nationArg, nationToFlag, nationToRegion, nextFixtureForPin, nextFixtureForTeam, nextHorizonSentence, nextNoneReadSentence, nextShareCard, normalizeLang, normalizeOutcomes, outcomeFromScore, padVisible, parseCachedMarketSignal, parseCachedMatch, parseCachedMatches, parseCachedScheduleIndex, parseStandings, parseTeamSlot, parsedValue, pinUnder, productFlag, rallyCryFor, rallyEntryFor, readJsonBounded, readSmallFile, readUserConfig, resolveClub, resolveCompetition, resolveMarketSource, resolveTz, resolvedValues, retryAfterMs, rosterFor, sanitizeBundledFixture, savedSlug, scheduleEntryOf, scheduleSpan, scoreline, sealMarketSignal, sealMatch, sealScheduleEntry, sealSeason, selectOne, selectedCompetition, selectionExtras, selectionRefusal, selectionVerdict, servedExtras, stageLabel, stageLabelI18n, standingsShapeOf, statesPartial, t, tableData, tableKeyArg, tableShareCard, tableTitle, teamKind, truncateVisible, unresolved, unservedSentence, valid, verdictExtras, verdictNotice, verdictQualifiers, withFlag };
4283
+ export { type AmbientFinishedMatch, type AmbientLinePart, type AmbientMatch, type AmbientNames, type AmbientView, BRACKET_STAGE_ORDER, BUNDLE_COMPETITION, type BatchResolution, type BetweenEditions, type BoundedList, type BracketFormatOpts, type BracketMatchNode, type BracketMatchView, type BracketResult, type BracketShareCard, type BracketTopology, type BracketView, type BuildSignalInput, COMPETITION_KIND, COUNTDOWN_NOW, type Capabilities, type Capability, type ChosenBy, type ClubResolution, type CompetitionEntry, type CompetitionKey, type CompetitionKind, type CompetitionSelection, DEFAULT_COMPETITION, DEFAULT_COOLDOWN_MS, DEFAULT_FLAVOR, DEFAULT_MAX_AGE_MS, DISCLAIMER, type DayAttribution, type DerivedTables, EARLIER_RECORD_NOTE, EspnAdapter, type EspnAdapterOptions, FAN_PROJECT, FLAVOR_BANKS, FLAVOR_LEVELS, FLAVOR_MOMENTS, FakeMarketProvider, type FakeMarketProviderOptions, type FavoriteStrength, type FetchMeta, type FetchWindowOptions, type FileEntry, type Flair, type FlairOpts, type FlavorBank, type FlavorLevel, type Moment as FlavorMoment, type FlavorOpts, type FormatOpts, type GroupStandings, KNOCKOUT_EXTRA_TIME_MS, KNOWN_SOURCES, type KnockoutFixturesResult, LIVE_WINDOW_MS, type Lang, type LedgerRow, type ListedCompetition, type LiveReadResult, type LiveResult, MARKETS_SCOPE_NOTE, MARKET_COMPETITIONS, MAX_CONFIG_BYTES, MAX_COOLDOWN_MS, MAX_LABEL_COLUMNS, MAX_LIVE_FINISHED, MAX_RESPONSE_BYTES, MAX_SCHEDULE_INDEX, type MapContext, type MarketFavorite, type MarketMapping, type MarketMappingTable, type MarketOutcome, type MarketOutcomeKind, type MarketProvider, type MarketSignal, type MarketSignalOptions, type MarketSignalsResult, type Match, type MatchByIdResult, type MatchEvent, type MatchShareCard, type MomentWords, NO_BRACKET, type NextFixtureResult, type NoConfigReason, type Outcome, type OwnFile, type ParseResult, type Pin, PolymarketProvider, type PolymarketProviderOptions, type ProviderAdapter, type ProviderCapabilities, ProviderError, type ProviderErrorKind, type PunditPick, RALLY_CRIES, type RallyCry, type RallyPin, type ReadAccount, type ResolvedParticipant, ResponseTooLargeError, type Roster, SCHEDULE_AHEAD_DAYS, SCHEDULE_LOOKBACK_DAYS, SEASON_SLUG, SHARE_DISCLAIMER, SHARE_HASHTAG, STANDINGS_SHAPE, SUPPORTED, type ScheduleAheadResult, type ScheduleEntry, type SeasonInfo, type SelectedCompetition, type Selection, type ShareBracketInput, type ShareBracketOptions, type ShareCardContext, type ShareCardMarket, type ShareCardView, type ShareSnippetInput, type ShareSnippetOptions, type ShareStyle, type ShareTableInput, type SlotRef, type SmallFile, type Stage, type StandingRow, type StandingsResult, type Status, TABLE_KEY_ARG, TEAM_KIND, type TableData, type TableShareCard, type Team, type TeamInfo, type TeamKind, type TeamLookup, type TimelineOptions, type TimelinePart, type UserConfig, type UserConfigRead, type VerdictExtras, type VerdictSource, allFixtures, allTeams, ambiguous, asFlavorLevel, attachFetchMeta, bounded, bracketCapability, bracketShareCard, buildBracketTopology, buildBracketView, buildMarketSignal, bundleApplies, bundleSeasonYear, byKickoff, cacheDirFor, cacheableKeys, capabilitiesOf, competitionBase, competitionKind, competitionLabel, competitionValue, computeStandings, configPath, countdown, countdownPhrase, currentOrNextFixtureForTeam, dateNoneRead, dateNoneReadSentence, dateShareCard, dateUnreached, dateUnreachedSentence, dayAttribution, definitiveNone, deriveFavorite, deriveTables, disclaimerLine, displayWidth, emptyBatch, entryOf, favoriteStrength, fetchMeta, fixturesByDate, fixturesByGroup, fixturesByTeam, fixturesInLiveWindow, flagEmoji, flavorsFor, formatBracketCompactLine, formatBracketList, formatBracketMatchLine, formatBracketTree, formatDate, formatKickoff, formatShareBracket, formatShareSnippet, formatShareTable, formatTime, getBracket, getKnockoutFixtures, getLiveMatches, getLiveRead, getMarketSignal, getMarketSignals, getMatchById, getMatchesForDate, getNextFixtureForTeam, getScheduleAhead, getStandings, groups, hasLiveWindow, hasSaneDistribution, humanLabel, isCacheable, isFinished, isFlavorLevel, isHumanLabel, isKnockoutStage, isKnownSource, isLive, isMexicoNationalTeam, isPinnedSide, isPlaceholderSide, isReliableMarketSignal, isStaleSignal, isTeam, isTournamentWindowOver, isUpcoming, isValidDate, isValidTimeZone, joinSegments, knockoutWindow, listCompetitions, liveNoneRead, liveNoneReadSentence, liveShareCard, liveSourceLabel, liveWindowMsFor, loadBracketTopology, localDate, lookAtEntry, lookAtOwnFile, lookAtSmallFile, lookupTeam, makeAdapter, makeMarketProvider, malformed, mapEspnEvent, mapsCleanly, marketAttributionText, marketBlock, marketDisplayable, marketFavoriteText, marketFixtureForTeam, marketLine, marketProbabilityText, marketRelevant, marketScopeVerdict, marketSignalRendersFor, marketSourceLabel, marketsCoverCompetition, marketsNoneRead, marketsNoneReadNote, marketsNoneReadSentence, matchFlair, matchFlairs, matchFlavor, matchKey, matchLocation, matchNoneReadSentence, matchShareCard, matchWindowSentence, mergeLive, modeLine, momentWords, nationArg, nationToFlag, nationToRegion, nextFixtureForPin, nextFixtureForTeam, nextHorizonSentence, nextNoneReadSentence, nextShareCard, normalizeLang, normalizeOutcomes, outcomeFromScore, padVisible, parseCachedMarketSignal, parseCachedMatch, parseCachedMatches, parseCachedScheduleIndex, parseStandings, parseTeamSlot, parsedValue, pinUnder, productFlag, provenLastGoal, rallyCryFor, rallyEntryFor, readJsonBounded, readSmallFile, readUserConfig, requestClock, resolveClub, resolveCompetition, resolveMarketSource, resolveTz, resolvedValues, retryAfterMs, rosterFor, sanitizeBundledFixture, savedSlug, scheduleEntryOf, scheduleSpan, scoreline, sealEvent, sealMarketSignal, sealMatch, sealScheduleEntry, sealSeason, selectOne, selectedCompetition, selectionExtras, selectionRefusal, selectionVerdict, servedExtras, stageLabel, stageLabelI18n, standingsShapeOf, statesPartial, t, tableData, tableKeyArg, tableShareCard, tableTitle, takeBounded, teamKind, timelineParts, timelineRows, truncateVisible, unresolved, unservedSentence, valid, verdictExtras, verdictNotice, verdictQualifiers, withFlag };