@mailwoman/kind-classifier 10.0.0 → 10.1.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.
package/out/index.js CHANGED
@@ -3,14 +3,7 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * `@mailwoman/kind-classifier` — Stage 2.5 of the runtime pipeline.
7
- *
8
- * Categorize inputs into one of eight `QueryKind`s by composing rule-based scorers over the
9
- * QueryShape sub-system's output. Pure functions, no ML, no place-name dictionaries. Returns
10
- * possibilities (alternatives) alongside the top pick so the coordinator can fall back when the
11
- * winning kind isn't actionable.
12
- *
13
- * See `docs/engineering/reference/STAGES.md` § Stage 2.5 for the contract.
6
+ * Stage 2.5 classifier: compose rule-based scorers over QueryShape and return a top kind with alternatives.
14
7
  */
15
8
  export { classifyKind, classifyKindSync, createKindClassifier } from "#classify";
16
9
  export { deriveIntentMarkers } from "#intent/markers";
package/out/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAEhF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC5F,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAGxD,OAAO,EACN,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,kBAAkB,GAClB,MAAM,QAAQ,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAEhF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC5F,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAGxD,OAAO,EACN,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,kBAAkB,GAClB,MAAM,QAAQ,CAAA"}
@@ -3,16 +3,15 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * Marker derivation for the ROAD_TO_V9 §4 intent vocabulary. Pure, synchronous, and the ONLY place
7
- * the classifier turns a fired rule into something a caller reads.
6
+ * Marker derivation for the ROAD_TO_V9 §4 intent vocabulary. This code is pure and synchronous. It is the only place the
7
+ * classifier turns a fired rule into something a caller reads.
8
8
  *
9
- * Three of the four intent kinds can raise their marker here, from the string alone. The fourth —
10
- * `bare_toponym`'s `declared_ambiguity` — cannot: its trigger is the dominance margin of the
11
- * RESOLVED candidate list, which does not exist yet at Stage 2.5. That one is raised by
12
- * `mailwoman/query-intent.ts` after the resolve, against the measured 0.5-log10 threshold. The split is
13
- * deliberate and it is why this module never emits `declared_ambiguity`: a marker that asserted
14
- * ambiguity from the string alone would be declaring that every bare city name is ambiguous, which
15
- * is false 89.1% of the time (the measured table behind `DECISIVE_MARGIN_LOG10`).
9
+ * Three of the four intent kinds can raise their marker here from the string by itself. The fourth,
10
+ * Stage 2.5 cannot raise `bare_toponym`'s `declared_ambiguity` from the string by itself.
11
+ * Its trigger is the dominance margin of the resolved candidate list. `mailwoman/query-intent.ts` raises it
12
+ * after the resolve against `DECISIVE_MARGIN_LOG10`. This module therefore never emits
13
+ * `declared_ambiguity`, since a marker asserting ambiguity from the string by itself would declare every
14
+ * bare city name ambiguous.
16
15
  */
17
16
  import type { QueryIntentMarker, QueryKind } from "@mailwoman/core/pipeline";
18
17
  import type { NormalizedInputLite } from "@mailwoman/query-shape";
@@ -23,21 +22,21 @@ import { type POIPhraseLookup } from "#poi";
23
22
  export interface IntentMarkerContext {
24
23
  input: NormalizedInputLite;
25
24
  /**
26
- * The injected POI lexicon, when one was wired. Absent → no `poi_category` marker can be built, which is consistent
27
- * because the kind cannot fire without it either.
25
+ * The injected POI lexicon when one was wired.
26
+ *
27
+ * Absent means no `poi_category` marker can be built, consistent with the
28
+ * kind not firing without it either.
28
29
  */
29
30
  poiLexicon?: POIPhraseLookup;
30
31
  locale?: string;
31
32
  }
32
33
  /**
33
- * Build the advisories for one classified query.
34
+ * Build the advisories for one classified query, taking the full verdict — top plus alternatives —
35
+ * because two of the four intent kinds live in `alternatives` by design (see `intent-rules.ts`).
34
36
  *
35
- * `kinds` is the FULL verdict — top plus alternatives — because two of the four intent kinds live in `alternatives` by
36
- * design (see `intent-rules.ts`). Reading only the top kind would make them invisible, which is the mistake this
37
- * signature exists to prevent.
38
- *
39
- * Returns `[]` when no intent kind fired. Callers surface that empty array rather than dropping the field: an empty
40
- * array is the classifier stating it looked.
37
+ * @returns `[]` when no intent kind fired.
38
+ * Callers surface that empty array rather than dropping the field, because an
39
+ * empty array is the classifier stating it looked.
41
40
  */
42
41
  export declare function deriveIntentMarkers(kinds: ReadonlyArray<{
43
42
  kind: QueryKind;
@@ -1 +1 @@
1
- {"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../lib/intent/markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAGjE,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,MAAM,CAAA;AAE7D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,mBAAmB,CAAA;IAC1B;;;OAGG;IACH,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7D,GAAG,EAAE,mBAAmB,GACtB,iBAAiB,EAAE,CAgErB"}
1
+ {"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../lib/intent/markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAGjE,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,MAAM,CAAA;AAE7D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,mBAAmB,CAAA;IAC1B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7D,GAAG,EAAE,mBAAmB,GACtB,iBAAiB,EAAE,CAoErB"}
@@ -3,35 +3,32 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * Marker derivation for the ROAD_TO_V9 §4 intent vocabulary. Pure, synchronous, and the ONLY place
7
- * the classifier turns a fired rule into something a caller reads.
6
+ * Marker derivation for the ROAD_TO_V9 §4 intent vocabulary. This code is pure and synchronous. It is the only place the
7
+ * classifier turns a fired rule into something a caller reads.
8
8
  *
9
- * Three of the four intent kinds can raise their marker here, from the string alone. The fourth —
10
- * `bare_toponym`'s `declared_ambiguity` — cannot: its trigger is the dominance margin of the
11
- * RESOLVED candidate list, which does not exist yet at Stage 2.5. That one is raised by
12
- * `mailwoman/query-intent.ts` after the resolve, against the measured 0.5-log10 threshold. The split is
13
- * deliberate and it is why this module never emits `declared_ambiguity`: a marker that asserted
14
- * ambiguity from the string alone would be declaring that every bare city name is ambiguous, which
15
- * is false 89.1% of the time (the measured table behind `DECISIVE_MARGIN_LOG10`).
9
+ * Three of the four intent kinds can raise their marker here from the string by itself. The fourth,
10
+ * Stage 2.5 cannot raise `bare_toponym`'s `declared_ambiguity` from the string by itself.
11
+ * Its trigger is the dominance margin of the resolved candidate list. `mailwoman/query-intent.ts` raises it
12
+ * after the resolve against `DECISIVE_MARGIN_LOG10`. This module therefore never emits
13
+ * `declared_ambiguity`, since a marker asserting ambiguity from the string by itself would declare every
14
+ * bare city name ambiguous.
16
15
  */
17
16
  import { nearMeSubject } from "#intent/rules";
18
17
  import { matchPOICategory } from "#poi";
19
18
  /**
20
- * Build the advisories for one classified query.
19
+ * Build the advisories for one classified query, taking the full verdict — top plus alternatives —
20
+ * because two of the four intent kinds live in `alternatives` by design (see `intent-rules.ts`).
21
21
  *
22
- * `kinds` is the FULL verdict — top plus alternatives — because two of the four intent kinds live in `alternatives` by
23
- * design (see `intent-rules.ts`). Reading only the top kind would make them invisible, which is the mistake this
24
- * signature exists to prevent.
25
- *
26
- * Returns `[]` when no intent kind fired. Callers surface that empty array rather than dropping the field: an empty
27
- * array is the classifier stating it looked.
22
+ * @returns `[]` when no intent kind fired.
23
+ * Callers surface that empty array rather than dropping the field, because an
24
+ * empty array is the classifier stating it looked.
28
25
  */
29
26
  export function deriveIntentMarkers(kinds, ctx) {
30
27
  const fired = new Set(kinds.map((k) => k.kind));
31
28
  const markers = [];
32
29
  if (fired.has("route_pair")) {
33
- // Whitespace-only split, not `wordsOf`: `route_pair` inputs are comma-free by construction (a comma
34
- // disqualifies the kind), and the tokens are re-joined verbatim into the message.
30
+ // Whitespace-only split rather than `wordsOf`, because `route_pair` inputs are
31
+ // comma-free by construction and the tokens are re-joined verbatim into the message.
35
32
  const tokens = ctx.input.normalized.trim().split(/\s+/);
36
33
  markers.push({
37
34
  kind: "route_pair",
@@ -41,8 +38,11 @@ export function deriveIntentMarkers(kinds, ctx) {
41
38
  evidence: {
42
39
  tokens,
43
40
  /**
44
- * Both readings, named. The order is stable (pair first, then the admin reading) so a consumer can index it; it
45
- * is NOT a ranking, and nothing downstream reads it as one.
41
+ * Both readings, listed.
42
+ *
43
+ * The order is stable: pair first, then the admin reading.
44
+ * A consumer can index it.
45
+ * This order does not rank the entries.
46
46
  */
47
47
  interpretations: ["two_toponyms", "locality_with_admin_context"],
48
48
  },
@@ -58,9 +58,10 @@ export function deriveIntentMarkers(kinds, ctx) {
58
58
  evidence: {
59
59
  subject,
60
60
  /**
61
- * THE PLUG POINT, named but not wired (ROAD_TO_V9 §4.4 scopes v9 to classification). Photon's `/api` already
62
- * accepts `lat`/`lon` location-bias params — `photon/` is the eventual consumer of this marker, and this string
63
- * is the note that says where it plugs in.
61
+ * The plug point is documented but not wired.
62
+ *
63
+ * `photon/` is the eventual consumer.
64
+ * Its `/api` already accepts `lat`/`lon` location-bias params.
64
65
  */
65
66
  focusParameter: "photon:lat/lon",
66
67
  },
@@ -1 +1 @@
1
- {"version":3,"file":"markers.js","sourceRoot":"","sources":["../../lib/intent/markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAwB,MAAM,MAAM,CAAA;AAe7D;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAClC,KAA6D,EAC7D,GAAwB;IAExB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAY,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAwB,EAAE,CAAA;IAEvC,IAAI,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,oGAAoG;QACpG,kFAAkF;QAClF,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAEvD,OAAO,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,iBAAiB;YAC5B,OAAO,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,2HAA2H;YACxJ,QAAQ,EAAE;gBACT,MAAM;gBACN;;;mBAGG;gBACH,eAAe,EAAE,CAAC,cAAc,EAAE,6BAA6B,CAAC;aAChE;SACD,CAAC,CAAA;IACH,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAExC,OAAO,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,sBAAsB;YAC5B,SAAS,EAAE,cAAc;YACzB,OAAO,EAAE,IAAI,OAAO,yEAAyE;YAC7F,QAAQ,EAAE;gBACT,OAAO;gBACP;;;;mBAIG;gBACH,cAAc,EAAE,gBAAgB;aAChC;SACD,CAAC,CAAA;IACH,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,UAAU,CAAC,CAAA;QAE3G,IAAI,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,cAAc;gBACpB,SAAS,EAAE,sBAAsB;gBACjC,OAAO,EAAE,IAAI,KAAK,CAAC,aAAa,yFAAyF;gBACzH,QAAQ,EAAE;oBACT,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvD;aACD,CAAC,CAAA;QACH,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"markers.js","sourceRoot":"","sources":["../../lib/intent/markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAwB,MAAM,MAAM,CAAA;AAiB7D;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAClC,KAA6D,EAC7D,GAAwB;IAExB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAY,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAwB,EAAE,CAAA;IAEvC,IAAI,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,+EAA+E;QAC/E,qFAAqF;QACrF,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAEvD,OAAO,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,iBAAiB;YAC5B,OAAO,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,2HAA2H;YACxJ,QAAQ,EAAE;gBACT,MAAM;gBACN;;;;;;mBAMG;gBACH,eAAe,EAAE,CAAC,cAAc,EAAE,6BAA6B,CAAC;aAChE;SACD,CAAC,CAAA;IACH,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAExC,OAAO,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,sBAAsB;YAC5B,SAAS,EAAE,cAAc;YACzB,OAAO,EAAE,IAAI,OAAO,yEAAyE;YAC7F,QAAQ,EAAE;gBACT,OAAO;gBACP;;;;;mBAKG;gBACH,cAAc,EAAE,gBAAgB;aAChC;SACD,CAAC,CAAA;IACH,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,UAAU,CAAC,CAAA;QAE3G,IAAI,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,cAAc;gBACpB,SAAS,EAAE,sBAAsB;gBACjC,OAAO,EAAE,IAAI,KAAK,CAAC,aAAa,yFAAyF;gBACzH,QAAQ,EAAE;oBACT,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvD;aACD,CAAC,CAAA;QACH,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAA;AACf,CAAC"}
@@ -3,57 +3,53 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * ROAD_TO_V9 §4 — the query-INTENT rules. Same contract as `rules.ts` (a `(input, shape) => number`
7
- * in [0, 1], 0 when the rule does not fire) and the same bitter-lesson invariant: universal
8
- * structural patterns and bounded linguistic categories only, never a place-name dictionary. The
9
- * one lexicon these kinds consult — the POI synonym table — is INJECTED, exactly as `poi.ts`
10
- * already does it.
11
- *
12
- * ## Why two of these three deliberately lose
13
- *
14
- * `bare_toponym` and `route_pair` are scored BELOW the structural kind that already owns their
15
- * population (`locality_only`, 0.85). They therefore surface in `QueryKindResult.alternatives` and
16
- * never as the top kind. That is not timidity — it is the D-rule discharge. The top kind is the
17
- * only thing the coordinator routes on (`deriveInputMode`, `canShortCircuit`, the POI branch), so
18
- * pinning it is what makes these additions provably answer-neutral on the bare-city-name register,
19
- * which is the single largest population in map search. The intent they carry travels on the
20
- * marker instead, where it is advisory by construction.
21
- *
22
- * `near_me` DOES win its top slot (0.91), because there is no incumbent worth preserving: a query
23
- * ending "near me" is not a locality and answering it as one is the bug.
6
+ * ROAD_TO_V9 §4 — the query-intent rules, with the same `(input, shape) => number` interface as
7
+ * `rules.ts` and the same bitter-lesson invariant: universal structural patterns and bounded linguistic
8
+ * categories only, never a place-name dictionary, with the POI synonym table injected exactly as
9
+ * `poi.ts` does it.
10
+ *
11
+ * `bare_toponym` and `route_pair` score below the structural kind that already owns their population
12
+ * (`locality_only`, 0.85), so they surface in `QueryKindResult.alternatives` and never as the top kind.
13
+ * The top kind is the only thing the coordinator routes on, so pinning it is what makes these additions
14
+ * answer-neutral on the bare-city-name register. Their intent travels on the marker.
15
+ *
16
+ * `near_me` does win its top slot (0.91), because there is no incumbent worth preserving: a query
17
+ * ending "near me" is not a locality.
24
18
  */
25
19
  import type { NormalizedInputLite, QueryShapeSegmentsView as QueryShapeLike } from "@mailwoman/query-shape";
26
20
  /**
27
- * `bare_toponym` rule: a single coherent place-name carrying no address grammar.
28
- *
29
- * Feeds the declared-ambiguity path. The rule itself asserts nothing about WHICH place — that is the resolver's
30
- * question, and `mailwoman/query-intent.ts` is where the answer's dominance margin decides whether the ambiguity gets
31
- * declared.
21
+ * `bare_toponym` rule: a single coherent place-name carrying no address grammar, feeding the
22
+ * declared-ambiguity path without asserting which place — that is the resolver's question,
23
+ * decided by the answer's dominance margin in `mailwoman/query-intent.ts`.
32
24
  */
33
25
  export declare function scoreBareToponym(input: NormalizedInputLite, shape: QueryShapeLike): number;
34
26
  /**
35
- * `route_pair` rule: exactly two toponym-shaped tokens with nothing between them.
27
+ * `route_pair` rule: exactly two toponym-shaped tokens with no token between them.
28
+ *
29
+ * The known confound is structural and unfixable here.
30
+ * "Paris London" and "Moscow Idaho" have the same string shape.
36
31
  *
37
- * **The known confound is structural and unfixable here.** "Paris London" and "Moscow Idaho" are the same string shape
38
- * — two bare capitalized words — and separating them needs to know that Idaho is a region, which is a gazetteer fact,
39
- * not a structural one. The hard-slice board's 18 `comma_free` rows are that population, and they fire this rule. That
40
- * is the reason ROAD_TO_V9 §4.3 specifies **classification + a declared fork, never a router**: both readings are named
41
- * in the marker, neither wins, and the resolver keeps answering exactly as it did.
32
+ * A classifier needs gazetteer knowledge that Idaho is a region to distinguish them.
33
+ * ROAD_TO_V9 §4.3 therefore specifies classification plus a declared fork.
42
34
  *
43
- * The one class that IS separable structurally is the two-token SINGLE name — "New York", "Fort Worth", "San Francisco"
44
- * — because those carry a toponymic head particle. That guard is what keeps the fork off the common case.
35
+ * Both readings appear in the marker, neither wins and the resolver keeps its existing answer.
36
+ *
37
+ * The structurally separable class is a two-token single name ("New York", "Fort Worth")
38
+ * with a toponymic head particle.
39
+ * That guard keeps the fork off the common case.
45
40
  */
46
41
  export declare function scoreRoutePair(input: NormalizedInputLite, shape: QueryShapeLike): number;
47
42
  /**
48
43
  * `near_me` rule: a subject plus a deictic locator, with no anchor.
49
44
  *
50
- * Requires a non-empty subject before the locator, so a bare "near me" stays with the `landmark` leaders rule rather
51
- * than claiming to be a category search with a missing focus point.
45
+ * A non-empty subject is required, so a bare "near me" stays with the `landmark` leaders rule.
52
46
  */
53
47
  export declare function scoreNearMe(input: NormalizedInputLite, _shape: QueryShapeLike): number;
54
48
  /**
55
- * The subject of a `near_me` query — the category or thing the asker wants, with the locator stripped. Empty string
56
- * when the rule would not have fired. Used to build the marker's evidence, never to route.
49
+ * The subject of a `near_me` query is the requested category or thing with the locator stripped.
50
+ *
51
+ * It is empty when the rule would not have fired.
52
+ * The subject builds marker evidence and never a route.
57
53
  */
58
54
  export declare function nearMeSubject(input: NormalizedInputLite): string;
59
55
  //# sourceMappingURL=rules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../lib/intent/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,IAAI,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAgN3G;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAE1F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAgBxF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAYtF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAQhE"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../lib/intent/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,IAAI,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAkN3G;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAE1F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAgBxF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAatF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAQhE"}
@@ -3,56 +3,52 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * ROAD_TO_V9 §4 — the query-INTENT rules. Same contract as `rules.ts` (a `(input, shape) => number`
7
- * in [0, 1], 0 when the rule does not fire) and the same bitter-lesson invariant: universal
8
- * structural patterns and bounded linguistic categories only, never a place-name dictionary. The
9
- * one lexicon these kinds consult — the POI synonym table — is INJECTED, exactly as `poi.ts`
10
- * already does it.
6
+ * ROAD_TO_V9 §4 — the query-intent rules, with the same `(input, shape) => number` interface as
7
+ * `rules.ts` and the same bitter-lesson invariant: universal structural patterns and bounded linguistic
8
+ * categories only, never a place-name dictionary, with the POI synonym table injected exactly as
9
+ * `poi.ts` does it.
11
10
  *
12
- * ## Why two of these three deliberately lose
11
+ * `bare_toponym` and `route_pair` score below the structural kind that already owns their population
12
+ * (`locality_only`, 0.85), so they surface in `QueryKindResult.alternatives` and never as the top kind.
13
+ * The top kind is the only thing the coordinator routes on, so pinning it is what makes these additions
14
+ * answer-neutral on the bare-city-name register. Their intent travels on the marker.
13
15
  *
14
- * `bare_toponym` and `route_pair` are scored BELOW the structural kind that already owns their
15
- * population (`locality_only`, 0.85). They therefore surface in `QueryKindResult.alternatives` and
16
- * never as the top kind. That is not timidity — it is the D-rule discharge. The top kind is the
17
- * only thing the coordinator routes on (`deriveInputMode`, `canShortCircuit`, the POI branch), so
18
- * pinning it is what makes these additions provably answer-neutral on the bare-city-name register,
19
- * which is the single largest population in map search. The intent they carry travels on the
20
- * marker instead, where it is advisory by construction.
21
- *
22
- * `near_me` DOES win its top slot (0.91), because there is no incumbent worth preserving: a query
23
- * ending "near me" is not a locality and answering it as one is the bug.
16
+ * `near_me` does win its top slot (0.91), because there is no incumbent worth preserving: a query
17
+ * ending "near me" is not a locality.
24
18
  */
25
- import { isDisqualifyingStreetSuffix, MAX_LOCALITY_ONLY_LENGTH, wordsOf } from "#rules";
19
+ import { carriesLetter, isDisqualifyingStreetSuffix, MAX_LOCALITY_ONLY_LENGTH, wordsOf } from "#rules";
26
20
  /**
27
- * `locality_only` scores 0.85. Both refinement kinds sit under it by a whole confidence step so no float-comparison
28
- * accident can flip the top slot, and so the gap reads as deliberate to the next person.
21
+ * Both refinement kinds sit a whole confidence step below `locality_only`'s 0.85
22
+ * so no float-comparison accident can flip the top slot.
29
23
  */
30
24
  const BARE_TOPONYM_CONFIDENCE = 0.84;
31
25
  /**
32
- * Lower still, and for a second reason on top of the ranking discipline: a route pair is a HYPOTHESIS about a query
33
- * whose competing reading (locality + region) is more common in this corpus. The number states that.
26
+ * Lower still for a second reason beyond the ranking discipline.
27
+ *
28
+ * A route pair is a hypothesis whose competing reading (locality + region) is more common in this corpus.
34
29
  */
35
30
  const ROUTE_PAIR_CONFIDENCE = 0.55;
36
31
  /**
37
- * Above `landmark`'s venue ceiling (0.88) and above `poi_query`'s anchored band (0.90), because a deictic tail is a
38
- * stronger signal than either shape heuristic: nothing else in the vocabulary explains why "me" is at the end of the
39
- * string.
32
+ * Above `landmark`'s venue ceiling (0.88) and above `poi_query`'s anchored band (0.90),
33
+ * because a deictic tail is a stronger signal than either shape heuristic:
34
+ * no other rule explains why "me" ends the string.
40
35
  */
41
36
  const NEAR_ME_CONFIDENCE = 0.91;
42
37
  /**
43
- * Word ceiling for a single bare toponym. Four covers the long tail that actually exists as one place name ("Newcastle
44
- * upon Tyne", "Sault Sainte Marie", "Las Palmas de Gran Canaria"); past it the input is carrying more than a name.
38
+ * Word ceiling for a single bare toponym: four covers the long tail that exists as one
39
+ * place name ("Newcastle upon Tyne", "Sault Sainte Marie", "Las Palmas de Gran Canaria"),
40
+ * and past it the input contains more than a name.
45
41
  */
46
42
  const MAX_BARE_TOPONYM_WORDS = 4;
47
43
  /**
48
- * Toponymic HEAD particles — the bounded linguistic category that makes a multi-token string ONE place name.
49
- *
50
- * Same justification, and the same boundary, as `@mailwoman/phrase-grouper`'s `PLACE_NAME_PARTICLES` (which covers the
51
- * INFIX glue: `de`, `am`, `aan den`). This set covers the PREFIX heads, and it exists for exactly one job: keeping
52
- * `route_pair` off "New York", "San Francisco", "Fort Worth" and their kin. It is a closed morphological class, not a
53
- * gazetteer — growing it with actual place names is the wrong move, and the pressure for that belongs on the resolver.
44
+ * Toponymic head particles — the bounded linguistic category that makes a multi-token
45
+ * string one place name, with the same boundary as `@mailwoman/phrase-grouper`'s
46
+ * `PLACE_NAME_PARTICLES` (which covers the infix glue `de`, `am`, `aan den`) and the one
47
+ * job of keeping `route_pair` off "New York", "San Francisco", "Fort Worth" and their kin.
54
48
  *
55
- * Case-folded on read, because lowercase is the primary user register and "new york" is the same query.
49
+ * It is a closed morphological class rather than a gazetteer, so growing it
50
+ * with actual place names is the wrong move.
51
+ * It is case-folded on read, because "new york" is the same query.
56
52
  */
57
53
  const TOPONYM_HEAD_PARTICLES = new Set([
58
54
  // English
@@ -115,9 +111,10 @@ const TOPONYM_HEAD_PARTICLES = new Set([
115
111
  "sint",
116
112
  // Definite article as a head — "The Valley" (Anguilla), "The Hague", "The Bottom".
117
113
  "the",
118
- // Generic toponymic heads outside the Latin/Germanic families, added because the 306-case corpus MEASURED them
119
- // (see `mailwoman/test/kind-intent-invariance.test.ts`): each is a common noun in its own language — Semitic "tel"
120
- // (mound), Malay "kuala" (confluence), Khmer "phnom" (hill) — that heads a place name the way "mount" does.
114
+ // Generic toponymic heads outside the Latin/Germanic families, each a common
115
+ // noun in its own language — Semitic "tel" (mound), Malay "kuala" (confluence),
116
+ // Khmer "phnom" (hill) — that heads a place name the way "mount" does.
117
+ // `mailwoman/test/kind-intent-invariance.test.ts` covers them.
121
118
  "tel",
122
119
  "kuala",
123
120
  "phnom",
@@ -127,11 +124,9 @@ const TOPONYM_HEAD_PARTICLES = new Set([
127
124
  "ilha",
128
125
  ]);
129
126
  /**
130
- * Generic toponymic TAIL nouns — the other half of the same bounded morphological class. "Belize City", "George Town",
131
- * "Cape Town", "Palm Springs": a place name whose last token is a settlement/landform generic is ONE name, not two.
132
- *
133
- * Measured additions, same as the heads above: `city`, `town` and `valley` each came off a real corpus row that was
134
- * forking wrongly.
127
+ * Generic toponymic tail nouns — the other half of the same bounded morphological
128
+ * class, so a place name whose last token is a settlement/landform generic
129
+ * ("Belize City", "George Town", "Palm Springs") is one name rather than two.
135
130
  */
136
131
  const TOPONYM_TAIL_NOUNS = new Set([
137
132
  "city",
@@ -158,47 +153,48 @@ const TOPONYM_TAIL_NOUNS = new Set([
158
153
  "burg",
159
154
  ]);
160
155
  /**
161
- * Deictic locator tails — "near me", "nearby", "around here", "in my area".
156
+ * Deictic locator tails — "near me", "nearby", "around here", "in my area" —
157
+ * the bounded class `preposition + a reference to the asker`, where `me`, `here`,
158
+ * `my <noun>` are function words rather than places.
162
159
  *
163
- * The class is `preposition + a reference to the ASKER`, which is why it is bounded and why it is safe: `me`, `here`,
164
- * `my <noun>` are function words, not places. Anchored to the END of the string (`$`) on purpose — the whole point of
165
- * the kind is that the query names no anchor, so anything AFTER the locator is an anchor and disqualifies it.
160
+ * Anchored to the end of the string (`$`) on purpose: the query names no anchor,
161
+ * so anything after the locator is an anchor and disqualifies it.
166
162
  *
167
- * Linear by construction: every alternative begins with a required literal, and the only quantifiers are bounded `\s+`
168
- * runs BETWEEN two required literals or trailing before `$`. No unbounded-whitespace-then-literal prefix, which is the
169
- * `js/polynomial-redos` shape (see the `ANCHOR_SEPARATOR` docstring in `poi.ts` for the same analysis).
163
+ * Linear by construction: every alternative begins with a required literal and the only
164
+ * quantifiers are bounded `\s+` runs between two required literals or trailing before `$`,
165
+ * with no unbounded-whitespace-then-literal prefix (the `js/polynomial-redos` shape).
166
+ * `ANCHOR_SEPARATOR` in `poi.ts` uses the same analysis.
170
167
  */
171
168
  const DEICTIC_LOCATOR_TAIL = /\b(?:near|close\s+to|next\s+to|around|by|closest\s+to|nearest\s+to)\s+(?:me|us|here|my\s+(?:location|position|area|place|house|home))\s*$/;
172
169
  /**
173
- * The adverbial half of the same class — no preposition, the deixis is baked into the word.
170
+ * The adverbial half of the same class, where the deixis is baked into the word
171
+ * rather than introduced by a preposition.
174
172
  */
175
173
  const DEICTIC_ADVERB_TAIL = /\b(?:nearby|near\s?by|close\s+by|around\s+here|in\s+my\s+(?:area|neighborhood|neighbourhood))\s*$/;
176
- /**
177
- * True when the input carries a deictic locator tail in EITHER form.
178
- */
179
174
  function hasDeicticTail(lowercased) {
180
175
  return DEICTIC_LOCATOR_TAIL.test(lowercased) || DEICTIC_ADVERB_TAIL.test(lowercased);
181
176
  }
182
177
  /**
183
- * The conditions `bare_toponym` and `route_pair` share: no address grammar of any kind, one segment, alpha throughout.
178
+ * The conditions `bare_toponym` and `route_pair` share: no address grammar of any kind,
179
+ * one segment, alpha throughout.
184
180
  *
185
- * Returns the word list when the input clears them, `null` when it does not. Deliberately a SUPERSET of
186
- * `scoreLocalityOnly`'s conditions (which admit two segments), so `bare_toponym` is a strict refinement of
187
- * `locality_only` and can never fire where `locality_only` did not — the property `intent-rules.test.ts` asserts and
188
- * the reason the ranking discipline above is enough to keep the top kind pinned.
181
+ * @returns the word list when the input clears them, `null` when it does not.
182
+ * The conditions are deliberately a superset of `scoreLocalityOnly`'s, so `bare_toponym` is
183
+ * a strict refinement of `locality_only` and can never fire where `locality_only` did not.
189
184
  */
190
185
  function bareNameWords(input, shape) {
191
186
  const text = input.normalized.trim();
192
187
  if (!text || text.length > MAX_LOCALITY_ONLY_LENGTH)
193
188
  return null;
194
- // A recognized postcode/known format IS address grammar. Nothing bare survives this.
189
+ // A recognized postcode/known format is address grammar, so no bare toponym survives it.
195
190
  if (shape.knownFormats.length)
196
191
  return null;
197
- // `alpha` excludes every house number and every postcode by construction — the cheapest available statement of
198
- // "no address grammar", and it costs no lexicon.
199
- if (shape.characterClass !== "alpha")
192
+ // `alpha` excludes every house number and postcode by construction, the cheapest statement of
193
+ // "no address grammar"; it is silent about whether a name is present, so the letter test stands
194
+ // beside it because `foldInputClass` answers `alpha` for input carrying no classified token.
195
+ if (shape.characterClass !== "alpha" || !carriesLetter(text))
200
196
  return null;
201
- // A comma is the admin-context marker ("Paris, FR"). One segment, or the name is not bare.
197
+ // A comma is the admin-context marker ("Paris, FR"), so one segment or the name is not bare.
202
198
  if ((shape.segments?.length ?? 1) !== 1)
203
199
  return null;
204
200
  const lowercased = text.toLowerCase();
@@ -214,34 +210,35 @@ function bareNameWords(input, shape) {
214
210
  return words;
215
211
  }
216
212
  /**
217
- * `bare_toponym` rule: a single coherent place-name carrying no address grammar.
218
- *
219
- * Feeds the declared-ambiguity path. The rule itself asserts nothing about WHICH place — that is the resolver's
220
- * question, and `mailwoman/query-intent.ts` is where the answer's dominance margin decides whether the ambiguity gets
221
- * declared.
213
+ * `bare_toponym` rule: a single coherent place-name carrying no address grammar, feeding the
214
+ * declared-ambiguity path without asserting which place — that is the resolver's question,
215
+ * decided by the answer's dominance margin in `mailwoman/query-intent.ts`.
222
216
  */
223
217
  export function scoreBareToponym(input, shape) {
224
218
  return bareNameWords(input, shape) ? BARE_TOPONYM_CONFIDENCE : 0;
225
219
  }
226
220
  /**
227
- * `route_pair` rule: exactly two toponym-shaped tokens with nothing between them.
221
+ * `route_pair` rule: exactly two toponym-shaped tokens with no token between them.
222
+ *
223
+ * The known confound is structural and unfixable here.
224
+ * "Paris London" and "Moscow Idaho" have the same string shape.
228
225
  *
229
- * **The known confound is structural and unfixable here.** "Paris London" and "Moscow Idaho" are the same string shape
230
- * — two bare capitalized words — and separating them needs to know that Idaho is a region, which is a gazetteer fact,
231
- * not a structural one. The hard-slice board's 18 `comma_free` rows are that population, and they fire this rule. That
232
- * is the reason ROAD_TO_V9 §4.3 specifies **classification + a declared fork, never a router**: both readings are named
233
- * in the marker, neither wins, and the resolver keeps answering exactly as it did.
226
+ * A classifier needs gazetteer knowledge that Idaho is a region to distinguish them.
227
+ * ROAD_TO_V9 §4.3 therefore specifies classification plus a declared fork.
234
228
  *
235
- * The one class that IS separable structurally is the two-token SINGLE name — "New York", "Fort Worth", "San Francisco"
236
- * — because those carry a toponymic head particle. That guard is what keeps the fork off the common case.
229
+ * Both readings appear in the marker, neither wins and the resolver keeps its existing answer.
230
+ *
231
+ * The structurally separable class is a two-token single name ("New York", "Fort Worth")
232
+ * with a toponymic head particle.
233
+ * That guard keeps the fork off the common case.
237
234
  */
238
235
  export function scoreRoutePair(input, shape) {
239
236
  const words = bareNameWords(input, shape);
240
237
  if (!words || words.length !== 2)
241
238
  return 0;
242
239
  const [first, second] = [words[0].toLowerCase(), words[1].toLowerCase()];
243
- // Reduplication — "Pago Pago", "Baden-Baden", "Walla Walla", "Bora Bora". Nobody travels from a place to itself,
244
- // so a repeated token is a universal single-name signal and needs no lexicon at all.
240
+ // Reduplication — "Pago Pago", "Baden-Baden", "Walla Walla" — is a universal single-name
241
+ // signal that needs no lexicon, because a route from a place to itself is invalid.
245
242
  if (first === second)
246
243
  return 0;
247
244
  if (TOPONYM_HEAD_PARTICLES.has(first) || TOPONYM_HEAD_PARTICLES.has(second))
@@ -253,23 +250,25 @@ export function scoreRoutePair(input, shape) {
253
250
  /**
254
251
  * `near_me` rule: a subject plus a deictic locator, with no anchor.
255
252
  *
256
- * Requires a non-empty subject before the locator, so a bare "near me" stays with the `landmark` leaders rule rather
257
- * than claiming to be a category search with a missing focus point.
253
+ * A non-empty subject is required, so a bare "near me" stays with the `landmark` leaders rule.
258
254
  */
259
255
  export function scoreNearMe(input, _shape) {
260
256
  const lowercased = input.normalized.trim().toLowerCase();
261
257
  if (!hasDeicticTail(lowercased))
262
258
  return 0;
263
- // The subject is everything before the locator. `hasDeicticTail` already anchored the match to the end, so the
264
- // first match index is where the subject stops.
259
+ // The subject is everything before the locator.
260
+ // `hasDeicticTail` already anchored the match to the end, so the first match
261
+ // index marks where the subject stops.
265
262
  const match = DEICTIC_LOCATOR_TAIL.exec(lowercased) ?? DEICTIC_ADVERB_TAIL.exec(lowercased);
266
263
  if (!match)
267
264
  return 0;
268
265
  return lowercased.slice(0, match.index).trim() ? NEAR_ME_CONFIDENCE : 0;
269
266
  }
270
267
  /**
271
- * The subject of a `near_me` query — the category or thing the asker wants, with the locator stripped. Empty string
272
- * when the rule would not have fired. Used to build the marker's evidence, never to route.
268
+ * The subject of a `near_me` query is the requested category or thing with the locator stripped.
269
+ *
270
+ * It is empty when the rule would not have fired.
271
+ * The subject builds marker evidence and never a route.
273
272
  */
274
273
  export function nearMeSubject(input) {
275
274
  const trimmed = input.normalized.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../lib/intent/rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../lib/intent/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAE,aAAa,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACtG;;;GAGG;AACH,MAAM,uBAAuB,GAAG,IAAI,CAAA;AAEpC;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,IAAI,CAAA;AAElC;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,IAAI,CAAA;AAE/B;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEhC;;;;;;;;;GASG;AACH,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC;IAC3D,UAAU;IACV,KAAK;IACL,KAAK;IACL,MAAM;IACN,IAAI;IACJ,MAAM;IACN,MAAM;IACN,OAAO;IACP,IAAI;IACJ,OAAO;IACP,OAAO;IACP,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,IAAI;IACJ,KAAK;IACL,UAAU;IACV,KAAK;IACL,OAAO;IACP,OAAO;IACP,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,OAAO;IACP,KAAK;IACL,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,oBAAoB;IACpB,KAAK;IACL,OAAO;IACP,KAAK;IACL,KAAK;IACL,MAAM;IACN,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,OAAO;IACP,KAAK;IACL,IAAI;IACJ,MAAM;IACN,OAAO;IACP,MAAM;IACN,mFAAmF;IACnF,KAAK;IACL,6EAA6E;IAC7E,gFAAgF;IAChF,uEAAuE;IACvE,+DAA+D;IAC/D,KAAK;IACL,OAAO;IACP,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACN,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IACvD,MAAM;IACN,MAAM;IACN,OAAO;IACP,SAAS;IACT,SAAS;IACT,SAAS;IACT,OAAO;IACP,OAAO;IACP,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,KAAK;IACL,SAAS;IACT,QAAQ;IACR,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;CACN,CAAC,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,oBAAoB,GACzB,2IAA2I,CAAA;AAE5I;;;GAGG;AACH,MAAM,mBAAmB,GACxB,mGAAmG,CAAA;AAEpG,SAAS,cAAc,CAAC,UAAkB;IACzC,OAAO,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;AACrF,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,aAAa,CAAC,KAA0B,EAAE,KAAqB;IACvE,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAA;IAEpC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,wBAAwB;QAAE,OAAO,IAAI,CAAA;IAEhE,yFAAyF;IACzF,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IAE1C,8FAA8F;IAC9F,gGAAgG;IAChG,6FAA6F;IAC7F,IAAI,KAAK,CAAC,cAAc,KAAK,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAEzE,6FAA6F;IAC7F,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAEpD,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IAErC,IAAI,cAAc,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAA;IAE3C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3B,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,sBAAsB;QAAE,OAAO,IAAI,CAAA;IAEvE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,2BAA2B,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;IACnD,CAAC;IAED,OAAO,KAAK,CAAA;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA0B,EAAE,KAAqB;IACjF,OAAO,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAA;AACjE,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAC,KAA0B,EAAE,KAAqB;IAC/E,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAEzC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IAE1C,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC,CAAA;IAE1E,yFAAyF;IACzF,mFAAmF;IACnF,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,CAAC,CAAA;IAE9B,IAAI,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAA;IAErF,IAAI,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAA;IAE5C,OAAO,qBAAqB,CAAA;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAA0B,EAAE,MAAsB;IAC7E,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAExD,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC;QAAE,OAAO,CAAC,CAAA;IAEzC,gDAAgD;IAChD,6EAA6E;IAC7E,uCAAuC;IACvC,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAE3F,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAA;IAEpB,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAA;AACxE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAA0B;IACvD,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAA;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IACxC,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAE3F,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAA;IAErB,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAA;AAC5C,CAAC"}