@metweave/parser 0.1.2 → 0.2.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/README.md +13 -2
- package/dist/index.cjs +1970 -814
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +133 -3
- package/dist/index.d.ts +133 -3
- package/dist/index.js +1965 -815
- package/dist/index.js.map +1 -1
- package/package.json +28 -18
- package/LICENSE +0 -21
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @metweave/parser — 解析层:METAR/SPECI(tolerant)→ IR。\n * The parsing layer: METAR/SPECI (tolerant mode) → IR.\n *\n * v0.1 实现范围:METAR 正文 + 趋势组半结构化 + RMK 认组 + 跑道状态最小形。\n * 纪律:不静默——看不懂的 token 一律进 warnings[](unknown-token,info 级),绝不丢弃;\n * 缺测电码(////、/////KT、//)与不可信值(5 位数 QNH)→ Observed missing + 告警;\n * 单位跟组走;一切产物携带原文 span。strict 模式预留给报文校验场景。\n */\nimport type {\n AltimeterReading,\n CloudAmount,\n CloudCondition,\n CloudElement,\n ConvectiveType,\n MetarReport,\n WindShearGroup,\n Observed,\n ParseOptions,\n ParseWarning,\n RemarkGroup,\n RemarkKind,\n ReportKind,\n RunwayStateGroup,\n RunwayVisualRange,\n SkyClearCode,\n Span,\n TemperatureReading,\n TrendElements,\n TrendGroup,\n VisibilityGroup,\n WeatherDescriptor,\n WeatherGroup,\n WeatherPhenomenon,\n WindGroup,\n} from \"@metweave/core\";\nimport { MetarParseError } from \"@metweave/core\";\n\n// IR 类型就近供给:本包 API 的返回/告警类型即 core 的 IR 类型(唯一来源在 core,此处仅转发)——\n// 免去消费方猜测「parse 的返回类型去哪 import」(2026-09-16 五方实测评测反馈)\nexport type {\n AltimeterReading,\n CloudCondition,\n CloudElement,\n MetarReport,\n Observed,\n ParseWarning,\n ReportKind,\n RunwayStateGroup,\n RunwayVisualRange,\n Span,\n TemperatureReading,\n TrendElements,\n TrendGroup,\n TrendKind,\n VisibilityGroup,\n WeatherGroup,\n WindGroup,\n} from \"@metweave/core\";\n\ninterface Token {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\nconst PHENOMENA: readonly WeatherPhenomenon[] = [\n \"DZ\",\n \"RA\",\n \"SN\",\n \"SG\",\n \"IC\",\n \"PL\",\n \"GR\",\n \"GS\",\n \"UP\",\n \"BR\",\n \"FG\",\n \"FU\",\n \"VA\",\n \"DU\",\n \"SA\",\n \"HZ\",\n \"PY\",\n \"PO\",\n \"SQ\",\n \"FC\",\n \"SS\",\n \"DS\",\n];\nconst DESCRIPTORS: readonly WeatherDescriptor[] = [\"MI\", \"PR\", \"BC\", \"DR\", \"BL\", \"SH\", \"TS\", \"FZ\"];\nconst TREND_KINDS = new Set<string>([\"NOSIG\", \"BECMG\", \"TEMPO\"]);\n/** 趋势段拖词容忍集(无 typed 语义的磨损尾/连接词——收进 trend.raw 静默保真,不产生噪声):\n * 语料实弹 VNKT 120930Z「NOSIG CB TO NE AND E」(观测员补记磨损尾)与既有回归锁契约\n * (拖词不告警、原文留 raw);含裸对流码 CB/TCU(无云量云高位的残缺云信息,无解码面)与\n * 16 方位词、TO/AND 连接词。与「交回正文恢复 typed 语义」的收窄主判据互补:\n * 有语义可恢复的(温露/QNH/$/WS/TX/TN/RVRNO)一律收口交回,纯噪声拖词保持原文静默。 */\nconst TREND_FILLER_WORDS = new Set([\n \"TO\",\n \"AND\",\n \"CB\",\n \"TCU\",\n \"N\",\n \"NNE\",\n \"NE\",\n \"ENE\",\n \"E\",\n \"ESE\",\n \"SE\",\n \"SSE\",\n \"S\",\n \"SSW\",\n \"SW\",\n \"WSW\",\n \"W\",\n \"WNW\",\n \"NW\",\n \"NNW\",\n]);\n/** 趋势段收组判据(封闭清单):只有趋势合法要素族(WMO 306 FM15 §15.14.2/§15.14.10:风/能见度/现在天气/云,\n * 加趋势专属 NSW 与 CAVOK 顶替)与风组变化组拖带形(dddVddd)可收进趋势段;其余 token 一律收口\n * 交回正文循环——正文各分支自带认组与 unknown-token 出声,语义无损恢复,冲突组自然触发重复组告警。\n *\n * 根因一(2026-09-12 复评实弹):旧收集循环只认趋势指示组,俄区报文「NOSIG RMK QFE749」把 RMK 段\n * 整段吞进 trends(RU 61/65、KZ 18/18 条命中)、remarks 反而为空。\n * 根因二(2026-09-14 复评实弹):收口改「白名单补洞」后正文专属组(温露/QNH/$/WS/TX/TN/RVRNO)\n * 仍被静默吞进 trend.raw、typed 语义蒸发——RMK、Rxx/、$ 已是三次逃逸,补洞循环就此终结:\n * 判据反转为规范封闭清单,未来一切新正文分支自动获得「交回正文 + 出声」兜底。\n * 硬边界保留:RMK(含词身粘连 startsWith)与 R 组形态——R 组收口另有 trendCloseWarning 出声。 */\nconst isTrendCollectible = (t: Token, next: Token | undefined): boolean => {\n const text = t.text;\n // 段间切换与正文硬边界:下一个趋势指示组、RMK、R 组形态(Rxx/…、R/SNOCLO)一律收口\n if (TREND_KINDS.has(text) || text.startsWith(\"RMK\")) return false;\n if (/^R(\\d{2}[RLC]?\\/|\\/SNOCLO$)/.test(text)) return false;\n // 趋势专属词与天气缺测电码\n if (text === \"CAVOK\" || text === \"NSW\" || text === \"//\") return true;\n // 拖词容忍集(见 TREND_FILLER_WORDS 注:无 typed 语义,静默保真优于 unknown 噪声)\n if (TREND_FILLER_WORDS.has(text)) return true;\n // 磨损时段词(一趋势内第二/三个 AT|TL|FM ddhh——指示组已在,按拖词静默保真;\n // tgftp/归档实弹,回归锁:标准位置时段词零告警)\n if (/^(AT|TL|FM)\\d{4}$/.test(text)) return true;\n // 风(含 /////KT 缺测、VRB、P 超上限形)与风组变化组拖带(dddVddd 单独成 token)\n if (parseWindToken(t, next) !== null || /^\\d{3}V\\d{3}$/.test(text)) return true;\n // 能见度(米制 4 位/NDV/方向组/SM 族/混分数跨 token///// 缺测家族)\n if (parseVisibilityToken(t, next) !== null) return true;\n // 现在天气(VC 邻近/-+ 强度/组合词身/裸 TS;RE 近期天气不属趋势族——交回正文按 recentWeather 认组)\n if (parseWeatherBody(text) !== null) return true;\n // 云(层组/VV/晴空码)\n if (CLOUD_LAYER_PATTERN.test(text) || VV_PATTERN.test(text) || isSkyClear(text)) return true;\n return false;\n};\nconst SKY_CLEAR_CODES: readonly SkyClearCode[] = [\"SKC\", \"NSC\", \"NCD\", \"CLR\"];\nconst CLOUD_AMOUNTS: readonly CloudAmount[] = [\"FEW\", \"SCT\", \"BKN\", \"OVC\"];\nconst SPEED_UNITS: readonly WindGroup[\"speed\"][\"unit\"][] = [\"kt\", \"mps\", \"kmh\"];\n/** QNH/A 物理可信范围:世界海平面气压极值 870(台风 Tip)–1083.8 hPa(蒙古高压 Agata 1968)——\n * 上界取 1084(极值之上即物理不可能,复评实弹 Q1087 由此拦截),下界 800 留裕量;\n * A 组(inHg)按同区间镜像换算外圆整为 23.5–32.5(800 hPa ≈ 23.62、1084 ≈ 32.02)。\n * 越界 = 值不可信 → 判缺测 + value-out-of-range 告警(与 Q10054 位数超界同纪律,绝不静默留假值)。 */\nconst QNH_HPA_MIN = 800;\nconst QNH_HPA_MAX = 1084;\nconst ALT_INHG_MIN = 23.5;\nconst ALT_INHG_MAX = 32.5;\n/** 温度物理可信范围:世界极值 +56.7°C(Death Valley 1913)/ −89.2°C(Vostok 1983),\n * 取 60/−90 留裕量(与 QNH 世界极值门同款纪律)——两位数模板空间内的物理不可能值\n * (89/85 构造实弹)不可信判缺测,绝不静默留假值。 */\nconst TEMP_C_MIN = -90;\nconst TEMP_C_MAX = 60;\n/** LTG 尾随词表(FMH-1 雷电视词与方位):放电类型 IC/CG/CC/CA、位置 OHD/ALQDS/DSNT/VCNTY 与 16 方位点。\n * 实弹(tgftp 全 cycle)LTG 后的方位词此前逐个散落成 unknown remarks(ALQDS/OHD/方位词一片)。 */\nconst LTG_TAIL_VOCAB = new Set([\n \"IC\",\n \"CG\",\n \"CC\",\n \"CA\",\n \"OHD\",\n \"ALQDS\",\n \"DSNT\",\n \"VCNTY\",\n \"N\",\n \"NNE\",\n \"NE\",\n \"ENE\",\n \"E\",\n \"ESE\",\n \"SE\",\n \"SSE\",\n \"S\",\n \"SSW\",\n \"SW\",\n \"WSW\",\n \"W\",\n \"WNW\",\n \"NW\",\n \"NNW\",\n]);\n/** 变化能见度尾组形态(RMK VIS 1/2V2 / VIS 1/4V1/2):两侧为整数或分数(可带 M/P 阈值前缀)。 */\nconst VIS_V_RANGE = /^[MP]?\\d+(?:\\/\\d+)?V[MP]?\\d+(?:\\/\\d+)?$/;\n\n// —— E3 首字符位掩码(正文循环分支分流用;可达首字符推导见正文循环内注释)\nconst M_WIND = 1 << 0;\nconst M_VIS = 1 << 1;\nconst M_R = 1 << 2;\nconst M_WEATHER = 1 << 3;\nconst M_CLOUD = 1 << 4;\nconst M_VV = 1 << 5;\nconst M_SKY_CLEAR = 1 << 6;\nconst M_TEMP = 1 << 7;\nconst M_QNH = 1 << 8;\nconst M_ALTIMETER_A = 1 << 9;\nconst M_VIS_RANGE = 1 << 10;\nconst M_DOLLAR = 1 << 11;\nconst M_WS_RWY = 1 << 12;\n\n/** 首字符(charCode)→ 候选分支位掩码;0 = 无分支可达(直接落 unknown-token) */\nfunction maskOf(code: number): number {\n if (code >= 48 && code <= 57) return M_WIND | M_VIS | M_TEMP; // 0-9\n switch (code) {\n case 47: // /\n return M_WIND | M_VIS | M_WEATHER | M_CLOUD | M_TEMP;\n case 86: // V(VRB 风 / VC 天气 / VV / VIS)\n return M_WIND | M_WEATHER | M_VV | M_VIS_RANGE;\n case 77: // M(M1/4SM / MIFG / M10/)\n return M_VIS | M_WEATHER | M_TEMP;\n case 80: // P(P6SM / PL PO PY PR)\n return M_VIS | M_WEATHER;\n case 82: // R(RVRNO / R 组 / RA…)\n return M_R | M_WEATHER;\n case 81: // Q\n return M_QNH;\n case 65: // A(AUTO 词已在前置词位收口,此处仅 A 组)\n return M_ALTIMETER_A;\n case 66: // B\n case 70: // F\n return M_WEATHER | M_CLOUD;\n case 79: // O(现象/描述符无 O 首字母)\n return M_CLOUD;\n case 83: // S\n return M_WEATHER | M_CLOUD | M_SKY_CLEAR;\n case 78: // N\n case 67: // C\n return M_SKY_CLEAR;\n case 68: // D\n case 71: // G\n case 72: // H\n case 73: // I\n case 84: // T\n case 85: // U\n case 45: // -\n case 43: // +\n return M_WEATHER;\n case 36: // $\n return M_DOLLAR;\n case 87: // W(WS 风切变组)\n return M_WS_RWY;\n default:\n return 0;\n }\n}\n\nconst isPhenomenon = (s: string): s is WeatherPhenomenon => PHENOMENA.some((p) => p === s);\nconst isDescriptor = (s: string): s is WeatherDescriptor => DESCRIPTORS.some((p) => p === s);\nconst isCloudAmount = (s: string): s is CloudAmount => CLOUD_AMOUNTS.some((p) => p === s);\nconst isSkyClear = (s: string): s is SkyClearCode => SKY_CLEAR_CODES.some((p) => p === s);\nconst isSpeedUnit = (s: string): s is WindGroup[\"speed\"][\"unit\"] =>\n SPEED_UNITS.some((p) => p === s);\nconst isConvective = (s: string): s is ConvectiveType => s === \"CB\" || s === \"TCU\";\n\nfunction tokenize(raw: string): Token[] {\n const tokens: Token[] = [];\n const rx = /\\S+/g;\n let m: RegExpExecArray | null;\n while ((m = rx.exec(raw)) !== null) {\n tokens.push({ text: m[0], start: m.index, end: m.index + m[0].length });\n }\n return tokens;\n}\n\nconst spanOf = (t: Token): Span => ({ start: t.start, end: t.end });\n\n/** 云层组形态(FEW023CB / /////01CB/// 缺测位形态)——正文循环与趋势段结构化共用一份正则防漂移 */\nconst CLOUD_LAYER_PATTERN = /^(FEW|SCT|BKN|OVC|\\/\\/\\/)(\\d{3}|\\/\\/\\/)(CB|TCU)?(\\/\\/\\/)?$/;\n/** VV 组形态(VV / VV/// / VV002)——同上共用 */\nconst VV_PATTERN = /^VV(\\/\\/\\/|\\d{3})?$/;\n\n/**\n * 趋势段内要素结构化(WMO 306 FM15 §15.14.2:风/能见度/天气/云四族 + 趋势专属 NSW(§15.14.13)与 CAVOK(§15.10)顶替)。\n * best-effort 且静默:认不出的组不产生任何告警(告警面受语料快照锁保护),原文在 raw 保真;\n * 正文循环同款的 token 级解析函数直接复用(parseWindToken/parseVisibilityToken/parseWeatherBody),\n * 组形正则取共享常量。返回 undefined = 没有任何组被识别(如裸 NOSIG)。\n */\nfunction structureTrendElements(\n tokens: readonly Token[],\n start: number,\n): TrendElements | undefined {\n let wind: WindGroup | undefined;\n let visibility: VisibilityGroup | undefined;\n let cavok: TrendElements[\"cavok\"];\n let nsw: TrendElements[\"nsw\"];\n const weather: WeatherGroup[] = [];\n let clouds: CloudCondition | undefined;\n let k = start;\n while (k < tokens.length) {\n const t = tokens[k];\n if (t === undefined) break;\n const next = tokens[k + 1];\n if (t.text === \"CAVOK\") {\n cavok = { span: spanOf(t) };\n k += 1;\n continue;\n }\n if (t.text === \"NSW\") {\n nsw = { span: spanOf(t) };\n k += 1;\n continue;\n }\n if (wind === undefined) {\n const w = parseWindToken(t, next);\n if (w !== null && w !== \"missing\") {\n wind = w.group;\n k += w.consumed;\n continue;\n }\n }\n if (visibility === undefined) {\n const vis = parseVisibilityToken(t, next);\n if (vis !== null && vis.kind === \"ok\") {\n visibility = vis.group;\n k += vis.consumed;\n continue;\n }\n }\n const wx = parseWeatherBody(t.text);\n if (wx !== null) {\n // 内部信号(outOfOrder/signWithVc)不进 IR;趋势段 tolerant 静默收下\n const { outOfOrder: _outOfOrder, signWithVc: _signWithVc, ...group } = wx;\n weather.push({ ...group, span: spanOf(t) });\n k += 1;\n continue;\n }\n const cloudM = CLOUD_LAYER_PATTERN.exec(t.text);\n if (cloudM !== null) {\n const amountRaw = cloudM[1];\n const heightRaw = cloudM[2];\n const convectiveRaw = cloudM[3];\n clouds = {\n elements: [\n ...(clouds?.elements ?? []),\n {\n kind: \"layer\",\n amount: amountRaw !== undefined && isCloudAmount(amountRaw) ? amountRaw : null,\n heightFt: {\n value:\n heightRaw !== undefined && heightRaw !== \"///\"\n ? Number.parseInt(heightRaw, 10) * 100\n : null,\n span: spanOf(t),\n },\n convective:\n convectiveRaw !== undefined && isConvective(convectiveRaw)\n ? convectiveRaw\n : undefined,\n span: spanOf(t),\n },\n ],\n ...(clouds?.clear !== undefined ? { clear: clouds.clear } : {}),\n };\n k += 1;\n continue;\n }\n const vvM = VV_PATTERN.exec(t.text);\n if (vvM !== null) {\n const heightRaw = vvM[1];\n clouds = {\n elements: [\n ...(clouds?.elements ?? []),\n {\n kind: \"vertical-visibility\",\n heightFt: {\n value:\n heightRaw === undefined || heightRaw === \"///\"\n ? null\n : Number.parseInt(heightRaw, 10) * 100,\n span: spanOf(t),\n },\n span: spanOf(t),\n },\n ],\n ...(clouds?.clear !== undefined ? { clear: clouds.clear } : {}),\n };\n k += 1;\n continue;\n }\n if (isSkyClear(t.text)) {\n clouds = { elements: clouds?.elements ?? [], clear: { code: t.text, span: spanOf(t) } };\n k += 1;\n continue;\n }\n k += 1; // 认不出的组:原文保真、静默跳过(tolerant 纪律,绝不静默丢原文)\n }\n if (\n wind === undefined &&\n visibility === undefined &&\n cavok === undefined &&\n nsw === undefined &&\n weather.length === 0 &&\n clouds === undefined\n )\n return undefined;\n return {\n ...(wind !== undefined ? { wind } : {}),\n ...(visibility !== undefined ? { visibility } : {}),\n ...(cavok !== undefined ? { cavok } : {}),\n weather,\n ...(nsw !== undefined ? { nsw } : {}),\n ...(clouds !== undefined ? { clouds } : {}),\n };\n}\n\nfunction joinSpan(tokens: readonly Token[]): Span {\n const first = tokens[0];\n const last = tokens[tokens.length - 1];\n if (first === undefined || last === undefined) return { start: 0, end: 0 };\n return { start: first.start, end: last.end };\n}\n\n/**\n * 紧凑模式出口剥除(E1)v2——重建式:遍历构造全新对象(不含 span/cavokSpan 键),零 mutation。\n * 设计权衡(实测驱动,两版对比):\n * - 构造期逐点跳过 span 的方案在 full 模式引入 ~20% 退化(分支插入组构造热路径),否决;\n * - 旧版出口就地删键(Reflect.deleteProperty)让 V8 把产物退化为 dictionary mode(慢属性):\n * 实测紧凑吞吐仅全模式 ~32%(23 万 vs 72 万行/秒)、存活对象驻留反升 ~2.2×——此为本版根因修复对象;\n * - 重建式出口一次遍历:full 模式与旧版逐字节同路径(零开销),紧凑产物保持 fast properties\n * (隐藏类不丢),实测吞吐回到全模式 ~55% 量级(40.6 万 vs 72.8 万行/秒,旧版仅 32%)、\n * 驻留与全模式持平(1.01×,旧版反升 2.21×——数字见 E 批性能冒烟锁注释)。\n * 数组重建新数组、原语透传;对象均为本次 parse 新建(无共享引用),键序保持原插入序(JSON 面稳定)。\n */\nfunction compactNode<T>(node: T): T {\n if (Array.isArray(node)) {\n const out: unknown[] = [];\n for (const item of node) out.push(compactNode(item));\n // 重建副本与原值同构(仅少 span 键)——与 structuredClone 同款「unknown → T」定型需求,断言无法避免\n // oxlint-disable-next-line no-unsafe-type-assertion\n return out as T;\n }\n if (node === null || typeof node !== \"object\") return node;\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n if (key === \"span\" || key === \"cavokSpan\") continue; // 剥除目标键:不进新对象(而非删除)\n out[key] = compactNode(value);\n }\n // 同上:键值逐项来自原对象(仅滤除 span),与 T 同构\n // oxlint-disable-next-line no-unsafe-type-assertion\n return out as T;\n}\n\n/** 天气组合词切分:把「TSRA」拆成描述符 TS + 现象 RA;无法合法切分返回 null。\n * outOfOrder = 能完整切解但语序不合电码表(描述符出现在现象之后,如 RATS=RA+TS)——\n * tolerant 纪律下仍按切解结果收下,由调用方追加 invalid-format 告警。\n * bare = 描述符单独编报(无现象)——TS 恒合法;SH 仅在 VC 邻近语境内合法(VCSH,\n * WMO 306 表 4678 注:机场附近有阵性降水但降水类型不可辨),由 parseWeatherBody 收口。 */\nfunction splitWeatherToken(body: string): {\n descriptor?: WeatherDescriptor;\n phenomena: readonly WeatherPhenomenon[];\n outOfOrder: boolean;\n bare: boolean;\n} | null {\n const chunks: string[] = [];\n for (let i = 0; i < body.length; i += 2) chunks.push(body.slice(i, i + 2));\n if (chunks.some((c) => c.length !== 2)) return null;\n const phenomena: WeatherPhenomenon[] = [];\n let descriptor: WeatherDescriptor | undefined;\n let sawPhenomenon = false;\n let outOfOrder = false;\n for (const c of chunks) {\n if (isPhenomenon(c)) {\n phenomena.push(c);\n sawPhenomenon = true;\n } else if (isDescriptor(c) && descriptor === undefined) {\n descriptor = c;\n if (sawPhenomenon) outOfOrder = true; // 电码表语序:描述符须先于现象\n } else return null;\n }\n if (phenomena.length === 0 && descriptor !== \"TS\" && descriptor !== \"SH\") return null; // TS/SH 单独编报见 bare 注\n return { descriptor, phenomena, outOfOrder, bare: phenomena.length === 0 };\n}\n\n/** 天气组词身解析:VC 邻近 / -+ 强度 / 双字母组合切分。返回 null 表示不是合法天气组。\n * signWithVc = 强度符与 VC 并存(-VCTSRA 家族,NWS 自动站实弹):4678 限定槽四选一\n * (light −/moderate 无符/heavy +/vicinity VC)、FAA AIM 明文互斥——tolerant 纪律下按切解\n * 收下(强度+邻近+现象语义可无损恢复,与 RATS→outOfOrder 容忍同构),由调用方出声。 */\nfunction parseWeatherBody(text: string): {\n intensity?: \"-\" | \"+\";\n proximity: boolean;\n descriptor?: WeatherDescriptor;\n phenomena: readonly WeatherPhenomenon[];\n outOfOrder: boolean;\n signWithVc: boolean;\n} | null {\n let rest = text;\n let proximity = false;\n let signWithVc = false;\n if (rest.startsWith(\"VC\")) {\n proximity = true;\n rest = rest.slice(2);\n }\n let intensity: \"-\" | \"+\" | undefined;\n const sign = rest.slice(0, 1);\n if (sign === \"-\" || sign === \"+\") {\n intensity = sign;\n rest = rest.slice(1);\n // 强度符后随 VC(-VCTSRA / -VCSH):非规范词序(规范语序 VC 在最前、强度符与 VC 互斥)\n if (rest.startsWith(\"VC\")) {\n proximity = true;\n signWithVc = true;\n rest = rest.slice(2);\n }\n }\n if (rest.length < 2 || rest.length % 2 !== 0) return null;\n const split = splitWeatherToken(rest);\n if (split === null) return null;\n // 裸 SH(无现象)仅在 VC 邻近形态合法(VCSH);非 VC 的裸 SH 是坏组不收\n if (split.bare && split.descriptor === \"SH\" && !proximity) return null;\n return {\n intensity,\n proximity,\n descriptor: split.descriptor,\n phenomena: split.phenomena,\n outOfOrder: split.outOfOrder,\n signWithVc,\n };\n}\n\n/**\n * 解析天气组 token(含 RE 前缀 / VC 邻近 / -+ 强度)。\n * 返回 kind「current」仅当组进入当前天气列表;「recent」= RE 近期天气(另一组位,不参与 weather 三态);\n * outOfOrder = 词身能切解但语序不合电码表;false = 不是天气组。\n */\n/** 强度符适用面(WMO 306 表 4678 注 4):降水全族可带 -/+;+SS/+FC/+DS 为 4678 表内合法电码\n * (codes.wmo.int/306/4678 稳定概念:+DS heavy duststorm、+SS heavy sandstorm、+FC 发展完好\n * 漏斗云;加拿大差异版另有官方能见度判据 <5/16 SM)——表内形态照常收下、零告警;\n * FMH-1 仅对降水族定义强度测定(美国实务不产 +DS),出处为 4678 电码表本身而非 FMH-1 容错。\n * (2026-09-14 口径归位:旧注释称「+DS 由调用方出声」与实现不符——它本就是表内电码。) */\nconst PRECIP_PHENOMENA = new Set<WeatherPhenomenon>([\n \"RA\",\n \"SN\",\n \"SG\",\n \"IC\",\n \"PL\",\n \"GR\",\n \"GS\",\n \"UP\",\n]);\nfunction intensityAllowedFor(\n intensity: \"-\" | \"+\",\n phenomena: readonly WeatherPhenomenon[],\n): boolean {\n if (phenomena.length > 0 && phenomena.every((x) => PRECIP_PHENOMENA.has(x))) return true;\n return intensity === \"+\" && phenomena.every((x) => x === \"SS\" || x === \"FC\" || x === \"DS\");\n}\n\nfunction tryWeatherToken(\n t: Token,\n weather: WeatherGroup[],\n recent: WeatherGroup[],\n):\n | {\n kind: \"current\" | \"recent\";\n outOfOrder: boolean;\n signWithVc: boolean;\n intensityMisuse?: boolean;\n }\n | false {\n const current = parseWeatherBody(t.text);\n if (current !== null) {\n const { outOfOrder, signWithVc, ...group } = current;\n weather.push({ ...group, span: spanOf(t) });\n return {\n kind: \"current\",\n outOfOrder,\n signWithVc,\n ...(current.intensity !== undefined &&\n !intensityAllowedFor(current.intensity, current.phenomena)\n ? { intensityMisuse: true }\n : {}),\n };\n }\n // RE 前缀(近期天气,15.13.2):REFC = RE + FC;RE 组不带强度符(15.13.2.1)\n if (t.text.startsWith(\"RE\")) {\n const recentBody = parseWeatherBody(t.text.slice(2));\n if (recentBody !== null) {\n const { outOfOrder, signWithVc: _signWithVc, ...group } = recentBody;\n recent.push({ ...group, span: spanOf(t) });\n return {\n kind: \"recent\",\n outOfOrder,\n signWithVc: false,\n ...(recentBody.intensity !== undefined ? { intensityMisuse: true } : {}),\n };\n }\n }\n return false;\n}\n\n/** 能见度解析结果三路:ok=有值;missing=显式缺测电码(//// 家族);\n * invalid=形态合法但值不可信(零分母 1/0SM——解码出 Infinity/NaN 的唯一入口),\n * 由调用方落 missing + value-out-of-range 告警(与 QNH 超界同款纪律,绝不留假值)。 */\ntype VisibilityResult =\n | { readonly kind: \"ok\"; readonly group: VisibilityGroup; readonly consumed: number }\n | {\n readonly kind: \"directional\";\n readonly group: { readonly value: number; readonly direction: string; readonly span: Span };\n readonly consumed: number;\n }\n | { readonly kind: \"missing\"; readonly consumed: number }\n | {\n readonly kind: \"invalid\";\n readonly message: string;\n readonly span: Span;\n readonly consumed: number;\n };\n\n/** 能见度:米制 4 位(可带 NDV 后缀)/ 美制 SM(含混分数跨 token 的预合并、P6SM 超上限)/ //// 缺测家族。 */\nfunction parseVisibilityToken(t: Token, next: Token | undefined): VisibilityResult | null {\n // 缺测家族两形态(与单位正交)://// = 米制缺测;////SM = 英里制缺测(加拿大自动站,\n // RMK VIS MISG 佐证)——同为 visibility missing + missing-expected 告警(单位不进 missing 态)\n if (t.text === \"////\" || t.text === \"////SM\") return { kind: \"missing\", consumed: 1 };\n // NDV = No Directional Variation(无方向变化,加拿大自动站惯例后缀)——\n // 语义为「能见度各方向一致」,IR 无落点:剥离丢弃(原码经组 span 回溯),按 4 位主体正常解析\n // 最低能见度方向组(VNVNVNVNDv,如 1200NW)——须在 m4 之前判(带 1–2 位方位后缀)\n const mDir = /^(\\d{4})(NE|NW|SE|SW|N|E|S|W)$/.exec(t.text);\n if (mDir !== null) {\n return {\n kind: \"directional\",\n group: {\n value: Number.parseInt(mDir[1] ?? \"0\", 10),\n direction: mDir[2] ?? \"\",\n span: spanOf(t),\n },\n consumed: 1,\n };\n }\n const m4 = /^(\\d{4})(NDV)?$/.exec(t.text);\n if (m4 !== null) {\n const digits = m4[1] ?? \"\";\n const ceiling = digits === \"9999\";\n // 0000 = 下限编码(<100m,与 9999 上限编码同族)——非实测 0 米,exact=false + beyond below\n const floor = digits === \"0000\";\n return {\n kind: \"ok\",\n group: {\n value: Number.parseInt(digits, 10),\n unit: \"m\",\n exact: !ceiling && !floor,\n ...(ceiling ? { beyond: \"above\" as const } : {}), // 9999 = 10km 或以上(上限编码)\n ...(floor ? { beyond: \"below\" as const } : {}), // 0000 = 不足下限(下限编码)\n span: spanOf(t),\n },\n consumed: 1,\n };\n }\n // 混分数跨 token:`1 1/4SM`(裸整数 + 带分数 SM 是一个组)\n if (/^\\d$/.test(t.text) && next !== undefined && /^\\d\\/\\d+SM$/.test(next.text)) {\n const whole = Number.parseInt(t.text, 10);\n const parts = next.text.slice(0, -2).split(\"/\");\n const num = parts[0];\n const den = parts[1];\n if (num === undefined || den === undefined) return null;\n if (Number(den) === 0) {\n // 零分母(1 0/0SM):解码结果 Infinity/NaN——值不可信判缺测(span 覆盖整数与分数两个 token)\n return {\n kind: \"invalid\",\n message: `能见度混分数分母为零(${t.text} ${next.text})——解码不出有限值,值不可信判缺测,原码经 span 回溯`,\n span: { start: t.start, end: next.end },\n consumed: 2,\n };\n }\n return {\n kind: \"ok\",\n group: {\n value: whole + Number(num) / Number(den),\n unit: \"sm\",\n exact: true,\n span: { start: t.start, end: next.end },\n },\n consumed: 2,\n };\n }\n const sm = /^(M|P)?(\\d+)\\/(\\d+)SM$|^(M|P)?(\\d+)SM$/.exec(t.text);\n if (sm !== null) {\n const prefix = sm[1] ?? sm[4];\n const below = prefix === \"M\";\n const above = prefix === \"P\"; // P6SM:6 英里以上(美式超上限,FAA/AF 口径)——exact=false,与 9999 同族\n const den = sm[3];\n if (den !== undefined && Number(den) === 0) {\n // 单 token 零分母(1/0SM、0/0SM、M1/0SM——0/0 解码出 NaN,同属值不可信)\n return {\n kind: \"invalid\",\n message: `能见度分数分母为零(${t.text})——解码不出有限值,值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n consumed: 1,\n };\n }\n const value =\n sm[2] !== undefined ? Number(sm[2]) / Number(den) : Number.parseInt(sm[5] ?? \"0\", 10);\n // exact 语义统一:分数(1/2SM、1 1/4SM)与整数本身是精确值;\n // 阈值性编码(M 前缀小于下界、P 前缀大于上界、9999 上限)为 false,beyond 记方向\n return {\n kind: \"ok\",\n group: {\n value,\n unit: \"sm\",\n exact: !below && !above,\n ...(below ? { beyond: \"below\" as const } : {}),\n ...(above ? { beyond: \"above\" as const } : {}),\n span: spanOf(t),\n },\n consumed: 1,\n };\n }\n return null;\n}\n\ninterface WindParsed {\n group: WindGroup;\n consumed: number;\n /** 越界发现(风向位/变化组端点 >360°):子项判缺测,由调用方落 value-out-of-range 告警 */\n rangeFindings: readonly { message: string; span: Span }[];\n /** 阵风位缺测(27010G//KT):组照常成立、gust 不设,由调用方落 missing-expected info */\n gustMissing?: boolean;\n}\n\n/** 风:33002MPS / VRB02KT / 31015G25KT / /////KT 缺测形态 + 260V050 变化组。 */\nfunction parseWindToken(t: Token, next: Token | undefined): WindParsed | \"missing\" | null {\n if (/^\\/{5}(KT|MPS|KMH)$/.test(t.text)) return \"missing\";\n // 部分缺测两形态(速度位 // / 阵风位 //,如 180//KT、27010G//KT)——此前整体落 unknown。\n // 超上限 P 前缀(P99KT/P49MPS,WMO 15.5.6 / AP-117 54 条):值存原码、beyond 标注超界端\n const m =\n /^(VRB|\\d{3}|\\/\\/\\/)(\\d{2,3}|P\\d{2}|\\/\\/\\/|\\/\\/)(?:G(\\d{2,3}|P\\d{2}|\\/\\/\\/|\\/\\/))?(KT|MPS|KMH)$/.exec(\n t.text,\n );\n if (m === null) return null;\n const span = spanOf(t);\n const dirRaw = m[1] ?? \"\";\n const speedRaw = m[2] ?? \"\";\n const unitRaw = (m[4] ?? \"kt\").toLowerCase();\n if (!isSpeedUnit(unitRaw)) return null;\n if (dirRaw === \"///\" || speedRaw === \"///\" || speedRaw === \"//\") return \"missing\";\n const variable = dirRaw === \"VRB\";\n const gustRaw = m[3];\n const speedBeyond = speedRaw.startsWith(\"P\") ? (\"above\" as const) : undefined;\n const gustBeyond =\n gustRaw !== undefined && gustRaw.startsWith(\"P\") ? (\"above\" as const) : undefined;\n const rangeFindings: { message: string; span: Span }[] = [];\n // 风向位 0–360(正北可编 360、静风 000 编 0):越界 = 值不可信 → 子项级判缺测(direction=null),\n // 风组其余子项(风速等)照常保留——两级建模:组内子项缺测 = 值字段 | null\n let direction: number | null = variable ? null : Number.parseInt(dirRaw, 10);\n if (!variable && direction !== null && direction > 360) {\n rangeFindings.push({\n message: `风向越界(${dirRaw},须 0–360)——风向位判缺测,原码经 span 回溯`,\n span,\n });\n direction = null;\n }\n let consumed = 1;\n let variation: WindGroup[\"variation\"];\n if (next !== undefined && /^\\d{3}V\\d{3}$/.test(next.text)) {\n const parts = next.text.split(\"V\");\n const min = parts[0];\n const max = parts[1];\n if (min !== undefined && max !== undefined) {\n const minDeg = Number.parseInt(min, 10);\n const maxDeg = Number.parseInt(max, 10);\n if (minDeg > 360 || maxDeg > 360) {\n // 变化组端点同为风向数值(0–360):任一越界即整组不可信 → 变化组判缺测(组已消费,不留假值)\n rangeFindings.push({\n message: `风向变化组端点越界(${next.text},须 0–360)——变化组判缺测,原码经 span 回溯`,\n span: spanOf(next),\n });\n } else {\n variation = { min: minDeg, max: maxDeg, span: spanOf(next) };\n }\n consumed = 2;\n }\n }\n // 阵风位缺测双形态:G 后 // (两位斜杠——2 字符场的逐字符惯例)与 /// (三斜杠磨损多一位,\n // 同按缺测建模——任何规范都无三斜杠形态,最合理的来源是 G// 的传输磨损;2026-09-14 补建模:\n // 此前 /// 走 parseInt 产 NaN 零告警入 IR,穿透缺测路由/gustMissing/值域门三道防线)\n const gustMissing = gustRaw === \"//\" || gustRaw === \"///\";\n const group: WindGroup = {\n variable,\n direction,\n speed: {\n value: Number.parseInt(speedRaw.startsWith(\"P\") ? speedRaw.slice(1) : speedRaw, 10),\n unit: unitRaw,\n span,\n ...(speedBeyond !== undefined ? { beyond: speedBeyond } : {}),\n },\n gust:\n gustRaw !== undefined && !gustMissing\n ? {\n value: Number.parseInt(gustRaw.startsWith(\"P\") ? gustRaw.slice(1) : gustRaw, 10),\n unit: unitRaw,\n span,\n ...(gustBeyond !== undefined ? { beyond: gustBeyond } : {}),\n }\n : undefined,\n variation,\n };\n return { group, consumed, rangeFindings, ...(gustMissing ? { gustMissing: true } : {}) };\n}\n\n/**\n * Temperature/dewpoint group shape: always dd/dd (M = negative; // on either side = that side missing).\n * 温度/露点组形态:恒为 dd/dd(M = 负;任一侧 // = 该侧缺测)——两位是形态定义本身,不是惯例:\n * WMO 电码表每个符号字母严格对应一位数字(T' 十位 / T 个位,负值加 M),官方示例含补零(01/M12、\n * 00/M00),任何规范版本无一位数形态。两侧 \\d{1,2} 曾让裸分数 token(VIS 词丢失的 1/2、2/1——\n * 上游脏输入)被误判为温露组:降序分数捏造假值且完全静默,升序触发误导性温露倒挂告警\n * (2026-09-14 复评收紧);不匹配即落 unknown-token 出声,原码经 span 回溯。\n * The regex requires the `/` separator — a bare \"//\" is the weather missing group (see the body loop) and must not be swallowed here.\n * 正则必须有 `/` 分隔——裸 `//` 是天气缺测组(见正文循环),不得被本组吞掉。\n * Exported for direct shape assertions in regression tests (red line: \"//\" must not match; \"1/2\"/\"2/1\" must not match either).\n * 导出供回归测试直接对形态断言(红线:对 \"//\" 与裸分数均不得匹配)。\n */\nexport const TEMP_DEW_PATTERN = /^(M?\\d{2}|\\/\\/)\\/(M?\\d{2}|\\/\\/)$/;\n\n/** 温度/露点组:恒为 dd/dd 形态(M = 负;// = 缺测 → null,调用方补告警)。 */\nfunction parseTempDewToken(t: Token): {\n temperature: TemperatureReading | null;\n dewpoint: TemperatureReading | null;\n span: Span;\n} | null {\n const read = (raw: string | undefined): TemperatureReading | null => {\n // undefined = 第二组整体缺失(FMH-1 12.6.10 露点缺测形态 24/);\"//\" = 显式缺测——\n // 两者同为 null,但 missing-expected 文案由调用方按形态区分\n if (raw === undefined || raw === \"//\") return null;\n const n = raw.startsWith(\"M\") ? -Number.parseInt(raw.slice(1), 10) : Number.parseInt(raw, 10);\n // −0 归一(M00 → 0):负零序列化变形(JSON 出 -0),消费方 Object.is 判别出边角差异\n const celsius = n === 0 ? 0 : n;\n return { celsius, span: spanOf(t) };\n };\n const m = TEMP_DEW_PATTERN.exec(t.text);\n if (m === null) {\n // FMH-1 12.6.10 露点缺测形态「24/」(第二组整体省略,同恒两位)——裸 // 与 /// 仍不得匹配\n const trailing = /^(M?\\d{2})\\/$/.exec(t.text);\n if (trailing === null) return null;\n return { temperature: read(trailing[1]), dewpoint: null, span: spanOf(t) };\n }\n return { temperature: read(m[1]), dewpoint: read(m[2]), span: spanOf(t) };\n}\n\nfunction beyondRangeOf(flag: string | undefined): \"above\" | \"below\" | undefined {\n if (flag === \"P\") return \"above\";\n if (flag === \"M\") return \"below\";\n return undefined;\n}\n\n/** RVR 组:R07R/1800V2200FT / R36/0500V0800D / P·M 超界 / 斜杠趋势(R13/3500FT/N、R07/P6000FT/U)。\n * R/SNOCLO 与 R10L/SNOCLO 属跑道状态语义(15.13.6.1),由 parseRunwayStateToken 收口。 */\nfunction parseRvrToken(t: Token): RunwayVisualRange | null {\n // 趋势后缀双形态:无斜杠(0500V0800D,WMO)与斜杠(3500FT/N,FAA/加式——FT 单位标记后带 /D //N //U)\n const m = /^R(\\d{2}[RLC]?)\\/(P|M)?(\\d{4})(?:V(P|M)?(\\d{4}))?(FT)?(?:\\/([DNU])|([DNU]))?$/.exec(\n t.text,\n );\n if (m === null) return null;\n const minRaw = m[3] ?? \"0\";\n const maxRaw = m[5];\n const trendRaw = m[7] ?? m[8];\n return {\n runway: m[1] ?? \"\",\n value: maxRaw === undefined ? Number.parseInt(minRaw, 10) : undefined,\n min: maxRaw !== undefined ? Number.parseInt(minRaw, 10) : undefined,\n max: maxRaw !== undefined ? Number.parseInt(maxRaw, 10) : undefined,\n beyondRange: beyondRangeOf(m[2] ?? m[4]),\n unit: m[6] === \"FT\" ? \"ft\" : \"m\",\n trend:\n trendRaw === \"U\"\n ? \"up\"\n : trendRaw === \"D\"\n ? \"down\"\n : trendRaw === \"N\"\n ? \"no-change\"\n : undefined,\n span: spanOf(t),\n };\n}\n\n/** 摩擦两位电码(15.13.6.1 表 0366)解码:01–90 → 摩擦系数 0.01–0.90;91–95 → 制动作用五档;\n * 99 → unreliable;// 或 96–98(电码表未用)→ 两字段皆 undefined(原码经 span 回溯)。 */\nfunction parseFrictionCode(\n code: string | undefined,\n): Pick<RunwayStateGroup, \"frictionCoefficient\" | \"brakingAction\"> {\n if (code === undefined || !/^\\d{2}$/.test(code)) return {};\n const f = Number.parseInt(code, 10);\n if (f <= 90) return { frictionCoefficient: f / 100 };\n if (f >= 91 && f <= 95)\n return {\n brakingAction: ([\"poor\", \"medium-poor\", \"medium\", \"medium-good\", \"good\"] as const)[f - 91],\n };\n if (f === 99) return { brakingAction: \"unreliable\" };\n return {};\n}\n\n/** 跑道状态组三形态(WMO 15.13.6):①六位状态电码(R21/490160:沉积/覆盖/深度/摩擦,位缺测 /);\n * ②CLRD 清除家族(R07L/CLRD// 标准、CLRD62 俄区、CLRD/// 非标容忍);③SNOCLO 关闭(R/SNOCLO 全机场、R10L/SNOCLO 逐跑道)。\n * 覆盖位非法电码(表 0519 外数字)不静默留值:该位判缺测 + findings 交调用方落 invalid-format 告警。 */\nfunction parseRunwayStateToken(\n t: Token,\n): { group: RunwayStateGroup; findings: readonly { message: string; span: Span }[] } | null {\n // ③ SNOCLO(15.13.6.1):跑道因雪/冰/清雪不可用\n const snoclo = /^R(\\d{2}[RLC]?)?\\/SNOCLO$/.exec(t.text);\n if (snoclo !== null) {\n return {\n group: { runway: snoclo[1] ?? \"\", closed: true, cleared: false, span: spanOf(t) },\n findings: [],\n };\n }\n // ② CLRD 家族\n const clrd = /^R(\\d{2}[RLC]?)\\/CLRD(\\d{2}|\\/\\/|\\/\\/\\/)?$/.exec(t.text);\n if (clrd !== null) {\n return {\n group: {\n runway: clrd[1] ?? \"\",\n cleared: true,\n ...parseFrictionCode(clrd[2]),\n span: spanOf(t),\n },\n findings: [],\n };\n }\n // ① 六位状态电码:沉积物类型 1 位 + 覆盖范围 1 位 + 深度 2 位 + 摩擦 2 位(各可 / 缺报)\n const num = /^R(\\d{2}[RLC]?)\\/(\\d|\\/)(\\d|\\/)(\\d{2}|\\/\\/)(\\d{2}|\\/\\/)$/.exec(t.text);\n if (num === null) return null;\n const depthCode = num[4] ?? \"\";\n // 深度解码(15.13.6.1 表 1079):00–90 = 毫米(00 即 <1mm 记 0);91 未用判缺测;92–98 = 10–40cm 段记下限;\n // 99 = 跑道不可用(同 SNOCLO 语义 → closed,深度不落值)\n const depthNum = /^\\d{2}$/.test(depthCode) ? Number.parseInt(depthCode, 10) : null;\n const depth =\n depthNum === null\n ? null\n : depthNum <= 90\n ? depthNum\n : depthNum === 91\n ? null\n : depthNum === 99\n ? null\n : (depthNum - 90) * 50;\n // 覆盖位电码合法性(15.13.6.1 表 0519):表内仅 1/2/5/9 与 /——表外数字(0/3/4/6/7/8)为非法电码,\n // 按三态纪律判缺测(null)+ invalid-format 告警,绝不把表外值留在 IR(tgftp 实弹 R24/000062 命中位 2 的 0)\n const coverageCode = num[3] ?? \"/\";\n const coverageIllegal = coverageCode !== \"/\" && !\"1259\".includes(coverageCode);\n const findings: { message: string; span: Span }[] = coverageIllegal\n ? [\n {\n message: `跑道状态覆盖位电码非法(${t.text} 覆盖位 ${coverageCode}——WMO 表 0519 仅用 1/2/5/9 与 /)——该位判缺测,原码经 span 回溯`,\n span: spanOf(t),\n },\n ]\n : [];\n return {\n group: {\n runway: num[1] ?? \"\",\n closed: depthNum === 99 || undefined,\n cleared: false,\n deposit: num[2] === \"/\" ? null : Number(num[2]),\n coverage: coverageCode === \"/\" || coverageIllegal ? null : Number(coverageCode),\n depth,\n ...parseFrictionCode(num[5]),\n span: spanOf(t),\n },\n findings,\n };\n}\n\n// ---------------------------------------------------------------- 主入口\n\n/**\n * Parse one METAR/SPECI report (tolerant mode) into the IR — the package's single entry.\n * 解析单条 METAR/SPECI 报文(tolerant)为 IR——本包唯一入口。\n *\n * Throws MetarParseError (stable machine-readable `code`) on whole-report failure\n * (non-string input / missing station / missing time / invalid time / unsupported mode); anything the\n * parser does not recognize lands in `warnings[]` with its span — never dropped.\n * 整体失败(输入非字符串/无站名/无时组/时组越界/未实现模式)抛 MetarParseError(code 稳定契约);\n * 看不懂的组带 span 进 warnings[],绝不丢弃。\n * @param raw - Report text, verbatim (kept on report.raw). 报文原文(原样保真于 report.raw)。\n * @param options - See ParseOptions (kind override, compact spans). 见 ParseOptions(类型位注入、紧凑模式)。\n */\nexport function parse(raw: string, options?: ParseOptions): MetarReport {\n // 紧凑模式(E1):spans === false 时在出口以重建式剥除全部 span(见 compactNode 注释)\n const compact = options?.spans === false;\n const compactIfEnabled = <T>(report: T): T => (compact ? compactNode(report) : report);\n // 输入校验:非字符串走 MetarParseError 稳定契约(code: \"invalid-input\")——code 是\n // 消费方分流的稳定面、EN_MESSAGES 查表英化的键,裸 Error 会同时绕过两者(此前为裸 Error)\n if (typeof raw !== \"string\") {\n throw new MetarParseError(\n \"invalid-input\",\n String(raw),\n `parse 需要一个 METAR/SPECI 报文字符串,收到 ${raw === null ? \"null\" : typeof raw}`,\n );\n }\n if ((options?.mode ?? \"tolerant\") === \"strict\") {\n // 错误面契约:strict 留在类型上(路线图项),但 v0.1 未实现——调用方 catch 不漏接裸 Error\n throw new MetarParseError(\n \"unsupported-mode\",\n raw,\n \"strict 模式尚未实现(v0.1 仅 tolerant)——请省略 mode 或显式传 'tolerant'\",\n );\n }\n const warnings: ParseWarning[] = [];\n // 报尾 = 终结符剥离(GTS/AFTN 通路报文行以 = 定界,常粘连末组如 Q1006= / NOSIG=)——\n // 仅剥尾部空白与 =,正文 token 偏移不变,span 仍对应原 raw(raw 保真含 =)。\n // 末字符预判(E2 性能项):语料大头无报尾,尾字符既非 = 也非空白时跳过整串正则——\n // 预判用单字符 \\s 测试(与 [\\s=] 字符类完全同域,行为等价),省一次全文回溯扫描\n const tail = raw.at(-1);\n const body =\n tail === undefined || tail === \"=\" || /\\s/.test(tail) ? raw.replace(/[\\s=]+$/, \"\") : raw;\n const tokens = tokenize(body);\n // 输入规模护栏(只告警不截断——截断破坏 raw 保真与「不丢弃」纪律):语料单行最大 30 token,\n // 上限 128 = 4 倍余量;超限报文照常完整解析,仅以一条聚合告警标记异常输入\n //(span 缺省 = 报文级;整体失败路径不经过此处,失败契约不受影响)\n const TOKEN_COUNT_LIMIT = 128;\n if (tokens.length > TOKEN_COUNT_LIMIT) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `输入 token 数超上限(${tokens.length} > ${TOKEN_COUNT_LIMIT})——按异常输入标记,解析照常完整,原文经 raw 保真`,\n });\n }\n let i = 0;\n const peek = (ahead = 0): Token | undefined => tokens[i + ahead];\n\n const externalKind = options?.kind;\n let kind: ReportKind = externalKind ?? \"metar\";\n let corrected = false;\n let auto = false;\n\n // —— 头部:类型词 / COR(WMO 形态)/ 站名 / 时组 / AUTO / COR(美式时组后形态)\n const head = peek();\n if (head !== undefined && (head.text === \"METAR\" || head.text === \"SPECI\")) {\n if (externalKind === undefined) kind = head.text === \"SPECI\" ? \"speci\" : \"metar\";\n i += 1; // 类型词 token 无论由谁决定 kind 都要消费\n }\n if (peek()?.text === \"COR\") {\n corrected = true;\n i += 1;\n }\n // AMD(修订发布标志,部分 CAA 用于 METAR 标题位,TAF 更常见):标题元数据词,\n // 语义为「本报告取代此前发布」——消费之不进站名位;是否置 corrected 不越权代判\n //(修订 ≠ 更正),IR 无 amended 位故仅放行不标注\n if (peek()?.text === \"AMD\") {\n i += 1;\n }\n const stTok = peek();\n if (stTok === undefined || !/^[A-Z0-9]{4}$/.test(stTok.text)) {\n // 契约:无站名组 = 整体解析失败(不是字段级三态);code 是稳定契约,message 中文为权威\n // 文案——英文经 @metweave/core EN_MESSAGES[code] 查表或渲染层 locale:\"en\" 切换\n throw new MetarParseError(\n \"missing-station\",\n raw,\n `无法识别站名组——输入不是 METAR/SPECI 报文(${stTok?.text ?? \"空输入\"})`,\n );\n }\n const station: string = stTok.text;\n i += 1;\n // CCA/CCB/CCC 与 COR 槽位磨损兜底(站名后/时组前——规范槽位:BBB 系列在时组后(见下方\n // BBB 消费位)、COR 在类型词位(见报头 COR 位)):部分 feed 的更正标记出现在此槽——此前\n // 直接 throw missing-time,「合法更正报整体失败」是最恶性失败模式。后随 token 为合法时组时\n // 消费放行并置 corrected + 出声(槽位漂移本身须可观测——不静默,2026-09-14 独立复评补\n // COR 对称缺口与出声);后随非时组则照旧走 missing-time。已知留案:标记若出现在 AUTO\n // 之前的其他相对序(如 CCA AUTO),AUTO 会落正文 unknown——语料无实证,暂不设防\n const driftTok = peek();\n if (driftTok !== undefined && /^(CC[A-Z]|COR)$/.test(driftTok.text)) {\n const afterDrift = peek(1);\n if (afterDrift !== undefined && /^\\d{2}\\d{2}\\d{2}Z$/.test(afterDrift.text)) {\n corrected = true;\n i += 1;\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `更正标记槽位漂移(${driftTok.text} 出现在站名后/时组前——已消费并置更正标志)`,\n span: spanOf(driftTok),\n });\n }\n }\n const tmTok = peek();\n const tm = tmTok !== undefined ? /^(\\d{2})(\\d{2})(\\d{2})Z$/.exec(tmTok.text) : null;\n if (tmTok === undefined || tm === null) {\n throw new MetarParseError(\n \"missing-time\",\n raw,\n `无法识别时组——输入不是完整的 METAR/SPECI 报文(${tmTok?.text ?? \"时组缺失\"})`,\n );\n }\n const time: MetarReport[\"time\"] = {\n day: Number.parseInt(tm[1] ?? \"0\", 10),\n hour: Number.parseInt(tm[2] ?? \"0\", 10),\n minute: Number.parseInt(tm[3] ?? \"0\", 10),\n };\n // 契约:时组为两态必填(无缺测形态,无 Observed)——数值越界即不可信时组,等同无效时组整体失败,\n // 绝不把假值(日 99、时 24、分 60)留在 IR(同 Q10054 脏 QNH 的「值不可信」纪律,时组无处判缺测故整体失败)\n if (time.day < 1 || time.day > 31 || time.hour > 23 || time.minute > 59) {\n throw new MetarParseError(\n \"invalid-time\",\n raw,\n `时组数值越界(${tmTok.text}:须日 01–31 / 时 00–23 / 分 00–59)——输入不是完整的 METAR/SPECI 报文`,\n );\n }\n i += 1;\n if (peek()?.text === \"AUTO\") {\n auto = true;\n i += 1;\n }\n if (peek()?.text === \"COR\") {\n corrected = true;\n i += 1;\n }\n // RRA/RRB/RRC 迟到报标记(AP-117-TM-01R2 第 21 条:报头时间组后)——标题元数据,消费放行\n if (/^RR[ABC]$/.test(peek()?.text ?? \"\")) {\n i += 1;\n }\n // CCA/CCB/CCC 更正指示符(WMO FM15 §1.3.3 BBB 系列:第一次更正 CCA、第二次 CCB 顺延;\n // 规范槽位即本位——时组后。加拿大 NAV CANADA 明文采用,中国 AFTN 实务沿用;仓库声明的\n // 编码基准含 MANOPS-MET)。语义即更正报——与 COR 同义异位(COR 在类型词位、BBB 在时组后位),\n // 消费并置 corrected;此前落 unknown-token,更正语义丢失(2026-09-14 复评:基准内形态未实现)\n if (/^CC[A-Z]$/.test(peek()?.text ?? \"\")) {\n corrected = true;\n i += 1;\n }\n\n // —— NIL:台站无观测(FM15 代码形注 2 的 NIL 码词;§15.4 是 AUTO 条款)——最小形态:站名/时组凭据保留,正文组不解析(本就无正文),零告警\n if (peek()?.text === \"NIL\") {\n return compactIfEnabled({\n kind,\n raw,\n nil: true,\n station,\n time,\n flags: { auto, corrected },\n cavok: false,\n trends: [],\n runwayStates: [],\n remarks: [],\n warnings,\n });\n }\n\n // —— 正文状态\n let cavok = false;\n let cavokSpan: Span | undefined;\n let wind: Observed<WindGroup> | undefined;\n let visibility: Observed<VisibilityGroup> | undefined;\n // 脱离主导能见度的方向组被按主导收下的局部标记(见正文循环方向组分支注释;非 IR 字段)\n let directionalAsPrimary = false;\n let rvr: Observed<readonly RunwayVisualRange[]> | undefined;\n const rvrList: RunwayVisualRange[] = [];\n // 多组 RVR 的组级 span 首组至末组(与天气组同口径——单组 span 在各自元素上)\n let rvrSpan: Span | undefined;\n let weather: Observed<readonly WeatherGroup[]> | undefined;\n const weatherList: WeatherGroup[] = [];\n const recentList: WeatherGroup[] = [];\n let clouds: CloudCondition | undefined;\n let cloudSeen = false;\n const cloudElements: CloudElement[] = [];\n let clearCode: CloudCondition[\"clear\"];\n let temperature: TemperatureReading | undefined;\n let dewpoint: TemperatureReading | undefined;\n let altimeter: AltimeterReading | undefined;\n // 双气压组口径(tolerant 惯例):末组为准(保持既有 last-wins 行为),重复组追加 info 告警不静默\n let altimeterSeen = false;\n const setAltimeter = (reading: AltimeterReading): void => {\n if (altimeterSeen) {\n dupGroupWarning(\"气压组\", altimeter?.span, reading.span);\n }\n altimeterSeen = true;\n altimeter = reading;\n };\n const trends: TrendGroup[] = [];\n const runwayStates: RunwayStateGroup[] = [];\n const remarks: RemarkGroup[] = [];\n // 重复组口径(与双气压组同款 tolerant 惯例):末组为准(保持既有 last-wins 行为),\n // 重复组出声不静默——专用码 duplicate-group(2026-09-15 五角色评测定案:此前借用\n // cross-check-conflict+info,消费方无法按「重复」分流;severity 升 warning)。\n // 前值后值原文都进 message:last-wins 会覆盖 IR 里的前值 span,前值唯一可回溯通道就是这条告警\n const dupGroupWarning = (\n label: string,\n prevSpan: Span | undefined,\n newSpan: Span | undefined,\n ): void => {\n const prevText =\n prevSpan === undefined ? `(原${label})` : raw.slice(prevSpan.start, prevSpan.end);\n const newText = newSpan === undefined ? label : raw.slice(newSpan.start, newSpan.end);\n warnings.push({\n code: \"duplicate-group\",\n severity: \"warning\",\n message: `重复${label}(前值 ${prevText},后值 ${newText})——报文只应有一组${label},以末组为准,前值经原文回溯`,\n span: newSpan,\n });\n };\n // 趋势段收口可观测性:R 组收口(RVR/跑道状态不属趋势要素)沿用既有口径出声;\n // 其余非趋势组收口(温露/QNH/WS/TX/TN/RVRNO/无法认领 token 等——2026-09-14 收窄新增)\n // 同样出声 info:该组交回正文循环认组(typed 语义无损恢复,冲突自然触发重复组告警),\n // 但趋势语境存疑须可观测——不静默。RMK/RMK 粘连与趋势指示组切换(含粘连形\n // BECMGAT0130——它本身就是趋势指示组,下一步由正文粘连分支认领)、以及规范报尾位 $\n // (FMH-1:$ 为整报最后一组,趋势段后随 $ 属规范位置)不出声(2026-09-14 独立复评补豁免)。\n const trendCloseWarning = (): void => {\n const btTok = tokens[i];\n const bt = btTok?.text;\n if (bt === undefined || btTok === undefined) return;\n if (TREND_KINDS.has(bt) || bt.startsWith(\"RMK\") || bt === \"$\") return;\n if (/^(BECMG|TEMPO)(AT|TL|FM)\\d{4}$/.test(bt)) return; // 粘连指示组:由正文粘连分支认领\n if (/^R(\\d{2}[RLC]?\\/|\\/SNOCLO$)/.test(bt)) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `趋势段收口于 R 组(${bt}——RVR/跑道状态不属趋势要素,按正文组处理,趋势语境存疑)`,\n span: spanOf(btTok),\n });\n return;\n }\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `趋势段收口于非趋势组(${bt}——不属趋势要素族,交回正文认组,趋势语境存疑)`,\n span: spanOf(btTok),\n });\n };\n // 趋势段收组:仅封闭清单内 token 收进 collected(判据见 isTrendCollectible),其余留在\n // tokens[i] 交回正文循环——三处收集入口(指示组/粘连/裸时段词)共用一份循环防漂移\n const collectTrendTokens = (collected: Token[]): void => {\n for (;;) {\n const inner = tokens[i];\n if (inner === undefined || !isTrendCollectible(inner, tokens[i + 1])) break;\n collected.push(inner);\n i += 1;\n }\n };\n // CAVOK 三面交叉校验(能见度/天气/云)。词位时对「前序」组校验;正文循环收口后对「后续」\n // 组再校验——CAVOK 让位发生在词位,其后再出现的矛盾组此前静默并存(CAVOK BKN012 形态)。\n // 判据词位/词后完全一致:确定矛盾才告警(下界编码/真值天气/低云或对流云;缺测云高不判)。\n // 告警 span 统一指 CAVOK 词位(既有契约:矛盾双方中「主张」所在)。\n const cavokConflicts = (whenLabel: string): void => {\n const at = cavokSpan;\n if (visibility?.kind === \"value\") {\n const g = visibility.value;\n const meters = g.unit === \"m\" ? g.value : g.value * 1609.344;\n const visRaw =\n visibility.span === undefined\n ? `${g.value} ${g.unit}`\n : raw.slice(visibility.span.start, visibility.span.end);\n const definitelyBelow =\n g.beyond === \"below\" ||\n (g.unit === \"sm\" && visRaw.startsWith(\"M\")) ||\n (g.exact && meters < 10_000);\n if (definitelyBelow) {\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `CAVOK 与${whenLabel}能见度组矛盾(${visRaw},CAVOK 语义要求 ≥10km)——让位照旧,报文自洽性存疑`,\n span: at,\n });\n }\n }\n if (weatherList.length > 0) {\n const wxRaw = weatherList\n .map(\n (g) =>\n `${g.proximity ? \"VC\" : \"\"}${g.intensity ?? \"\"}${g.descriptor ?? \"\"}${g.phenomena.join(\"\")}`,\n )\n .join(\" \");\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `CAVOK 与${whenLabel}天气组矛盾(${wxRaw},CAVOK 语义要求无重要天气)——让位照旧,报文自洽性存疑`,\n span: at,\n });\n }\n if (rvr !== undefined && rvr.kind === \"value\") {\n const rvrRaw = rvr.span === undefined ? \"\" : raw.slice(rvr.span.start, rvr.span.end);\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `CAVOK 与${whenLabel}RVR 组矛盾(${rvrRaw}——AP-117 第 140 条:CAVOK 代替能见度、跑道视程、现在天气和云)——让位照旧,报文自洽性存疑`,\n span: at,\n });\n }\n const cloudConflict = cloudElements.some((e) => {\n if (e.kind === \"layer\" && e.convective !== undefined) return true;\n const h = e.heightFt.value;\n return h !== null && h < 5_000;\n });\n if (cloudConflict) {\n const cloudRaw = cloudElements\n .map(\n (e) =>\n `${e.kind === \"layer\" ? (e.amount ?? \"///\") : \"VV\"}${\n e.heightFt.value === null\n ? \"///\"\n : String(Math.round(e.heightFt.value / 100)).padStart(3, \"0\")\n }${e.kind === \"layer\" ? (e.convective ?? \"\") : \"\"}`,\n )\n .join(\" \");\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `CAVOK 与${whenLabel}云组矛盾(${cloudRaw},CAVOK 语义要求 5000ft 以下无云且无 CB/TCU)——让位照旧,报文自洽性存疑`,\n span: at,\n });\n }\n };\n // 风切变组累积器(同报多组 WS 合一:runways 连接、span 首组至末组)\n let windShear: WindShearGroup | undefined;\n let wsRunways: string[] | undefined;\n let wsAll = false;\n let wsSpan: Span | undefined;\n\n // —— 正文循环(RMK 交段外处理)\n while (i < tokens.length) {\n const t = tokens[i];\n if (t === undefined) break;\n const text = t.text;\n\n if (text === \"RMK\") {\n i += 1;\n break;\n }\n // RMK 磨损粘连(RMKQFE749/0998 = RMK 与后组丢空格,fuzz 实弹 35/5 万例命中):进 RMK 段\n // 但不跳过 token 本身——由 RMK 段按认组粒度收下(多为 unknown,raw 保真不蒸发)\n if (text.startsWith(\"RMK\")) {\n break;\n }\n\n // 趋势指示组:NOSIG / BECMG / TEMPO(吞到下一个指示组、RMK 或结尾)\n if (TREND_KINDS.has(text)) {\n const kindText = text;\n const collected: Token[] = [t];\n i += 1;\n let period: TrendGroup[\"period\"];\n const periodTok = peek();\n if (\n kindText !== \"NOSIG\" &&\n periodTok !== undefined &&\n // 时段词双形态:AT/TL/FM+DDHH(WMO 306 FM15 §15.14.3)与 DDHH/DDHH 斜杠时段\n //(ICAO Annex 3 模板 / 中国民航主流编法,2026-09-16 五方实测评测发现的缺失形态)\n (/^(?:AT|FM|TL)\\d{4}$/.test(periodTok.text) || /^\\d{4}\\/\\d{4}$/.test(periodTok.text))\n ) {\n period = { text: periodTok.text, span: spanOf(periodTok) };\n collected.push(periodTok);\n i += 1;\n }\n // 收口语义见 isTrendCollectible:仅趋势合法要素族可收,其余收口交回正文(trendCloseWarning 出声)\n collectTrendTokens(collected);\n trendCloseWarning();\n const elements =\n kindText === \"NOSIG\"\n ? undefined\n : structureTrendElements(collected, period !== undefined ? 2 : 1);\n trends.push({\n kind: kindText === \"NOSIG\" ? \"nosig\" : kindText === \"BECMG\" ? \"becmg\" : \"tempo\",\n period,\n ...(elements !== undefined ? { elements } : {}),\n raw: collected.map((c) => c.text).join(\" \"),\n span: joinSpan(collected),\n });\n continue;\n }\n\n // 指示组缺失趋势段两形态——传输磨损所致(WMO 306 FM15 §15.14.3 时段词 AT/TL/FM 不得脱离指示组):\n // ①粘连——指示组与时段词丢空格(BECMGTL0350,IEM 归档实弹 10 次):宽容拆分,语义完整可恢复;\n // ②裸时段词——指示组整组丢失(Q1009 TL0730 …,IEM 归档实弹 128 次):按 kind 'unspecified'\n // 收段(要素组不再散落正文——尤其防趋势风组以 last-wins 覆盖正文真风组),告警标注指示组不可辨。\n // NOSIG 粘连不拆(NOSIG 语义上不配时段词);标准位置的时段词已在上方指示组分支内消费,此处不重复触达。\n if (\n (text.length === 6 &&\n (text.charCodeAt(0) === 65 || text.charCodeAt(0) === 84 || text.charCodeAt(0) === 70)) ||\n text.startsWith(\"BECMG\") ||\n text.startsWith(\"TEMPO\")\n ) {\n const fused = /^(BECMG|TEMPO)((?:AT|TL|FM)\\d{4}|\\d{4}\\/\\d{4})$/.exec(text);\n if (fused !== null) {\n const indicator = fused[1] ?? \"\";\n const collected: Token[] = [t];\n i += 1;\n collectTrendTokens(collected);\n trendCloseWarning();\n const fusedElements = structureTrendElements(collected, 1);\n trends.push({\n kind: indicator === \"BECMG\" ? \"becmg\" : \"tempo\",\n period: {\n text: text.slice(indicator.length),\n span: { start: t.start + indicator.length, end: t.end },\n },\n ...(fusedElements !== undefined ? { elements: fusedElements } : {}),\n raw: collected.map((c) => c.text).join(\" \"),\n span: joinSpan(collected),\n });\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `趋势指示组与时段词粘连(${text}——传输磨损丢空格,BECMG/TEMPO 与 AT/TL/FM 时段语义完整可恢复)`,\n span: spanOf(t),\n });\n continue;\n }\n if (/^(AT|TL|FM)\\d{4}$/.test(text)) {\n const collected: Token[] = [t];\n i += 1;\n collectTrendTokens(collected);\n trendCloseWarning();\n const bareElements = structureTrendElements(collected, 1);\n trends.push({\n kind: \"unspecified\",\n period: { text, span: spanOf(t) },\n ...(bareElements !== undefined ? { elements: bareElements } : {}),\n raw: collected.map((c) => c.text).join(\" \"),\n span: joinSpan(collected),\n });\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `趋势时段词缺指示组(${text}——§15.14.3 时段词须随 BECMG/TEMPO 出现)——按指示组缺失的趋势段收下,指示组类型不可辨`,\n span: spanOf(t),\n });\n continue;\n }\n }\n // 裸斜杠时段词(1616/1618——ICAO Annex 3 模板 / 中国民航主流趋势时段编法,指示组缺失):\n // 与 AT/TL/FM 裸词同纪律——kind 'unspecified' 收段出声,要素组不再散落正文\n //(2026-09-16 五方实测评测发现:此前该形态散落正文,趋势能见度以 last-wins 顶掉正文能见度)。\n // 前置守卫(长度 9 + 第 5 字符为斜杠)保正文热路径不为逐 token 正则付费\n if (text.length === 9 && text.charCodeAt(4) === 47 && /^\\d{4}\\/\\d{4}$/.test(text)) {\n const collected: Token[] = [t];\n i += 1;\n collectTrendTokens(collected);\n trendCloseWarning();\n const bareElements = structureTrendElements(collected, 1);\n trends.push({\n kind: \"unspecified\",\n period: { text, span: spanOf(t) },\n ...(bareElements !== undefined ? { elements: bareElements } : {}),\n raw: collected.map((c) => c.text).join(\" \"),\n span: joinSpan(collected),\n });\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `趋势时段词缺指示组(${text}——ICAO Annex 3 模板趋势时段须随 BECMG/TEMPO 出现)——按指示组缺失的趋势段收下,指示组类型不可辨`,\n span: spanOf(t),\n });\n continue;\n }\n\n if (text === \"CAVOK\") {\n cavok = true;\n cavokSpan = spanOf(t);\n // 交叉校验(三面:能见度/天气/云,判据见 cavokConflicts 注)——CAVOK 语义要求能见度\n // ≥10km、无重要天气、5000ft 以下无云且无 CB/TCU;前序组确定矛盾即出声。\n // 下界语义的编码(9999 ≥10km、P6SM >9.6km)与 CAVOK 相容不告警;M 前缀(小于下界)必矛盾。\n // 让位契约照旧(vis/weather/cloud 三组让位),矛盾仅追加 cross-check-conflict 告警\n cavokConflicts(\"前序\");\n // 契约(IR):CAVOK = 能见度 ≥10km + 无低云 + 无天气,前序 vis/weather/cloud 三组让位为 undefined\n // (让位是契约行为不发告警;词位以 cavokSpan 标记,前序组原码仍可从 raw 回溯)\n visibility = undefined;\n directionalAsPrimary = false;\n weather = undefined;\n weatherList.length = 0;\n cloudSeen = false;\n cloudElements.length = 0;\n clearCode = undefined;\n i += 1;\n continue;\n }\n\n // E3 性能项——首字符位掩码分流:每轮按首字符一次 switch 得「可能匹配的分支」位集,\n // 各分支先做一次位测试再进正则——不可能匹配的分支零正则尝试。分支相对顺序与原\n // 全试链完全一致(行为等价由全量语料回放快照锁定)。可达首字符推导:\n // 风 V/数字//;能见度 数字//M/P;RVRNO 与 R 组 R;天气 = 现象/描述符首字母\n // (B D F G H I M P R S T U)+ -/+/V(VC);裸 // 与云 /;云 F/S/B/O//;\n // VV 与 VIS 的 V;晴空词 S/N/C;温露 M/数字//;QNH 的 Q;A 组的 A;维护符 $。\n const mask = maskOf(text.charCodeAt(0));\n\n // 风(含 /////KT 缺测与 260V050 变化组)\n const windParsed = (mask & M_WIND) !== 0 ? parseWindToken(t, peek(1)) : null;\n if (windParsed !== null) {\n if (wind !== undefined) dupGroupWarning(\"风组\", wind.span, spanOf(t));\n if (windParsed === \"missing\") {\n if (wind === undefined) {\n wind = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n // 全缺测 /////KT(自动站假报文形态)与部分缺测(180//KT 风速位缺)同口径出声\n message: t.text.startsWith(\"/////\")\n ? \"风组缺测(/////KT,疑似自动站假报文形态)\"\n : `风组缺测(${t.text},风速位缺测)`,\n span: spanOf(t),\n });\n }\n // 已有风组时:缺测电码不顶替在场值(duplicate-group 已出声)——\n // 零信息量的缺测码按 last-wins 覆盖真实观测是纯信息损失(2026-09-15 五角色评测批)\n i += 1;\n } else {\n const wg = windParsed.group;\n // 风速模板上限:三位数(≤199,WMO 15.5.6「100 单位以上以精确位数替代两位电码」注至\n // 199;FMH-1 12.6.5.a「two or three digits」)——超 199 即非规范报文(270250KT 构造探针),\n // 按 QNH 超界同款纪律整组不可信判缺测,绝不静默留假值。P 前缀超上限形态(P99KT)合法\n // NaN 终结防线(终结断言,预期不可达):任何数值入口产 NaN 即整组不可信判缺测。\n // NaN 恰是现有防线的双重盲区——值域门 >199 对 NaN 恒 false、JSON.stringify 消 NaN 为\n // null、fuzz 不变量(2026-09-14 实弹 G/// 之前)无有限性检查——故独立成支并配哨兵不变量\n if (\n !Number.isFinite(wg.speed.value) ||\n (wg.gust !== undefined && !Number.isFinite(wg.gust.value))\n ) {\n wind = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: `风组解码出非有限值(${t.text})——值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n });\n } else if (wg.speed.value > 199 || (wg.gust?.value ?? 0) > 199) {\n wind = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: `风速超出编码范围(${t.text},三位数模板上限 199 ${wg.speed.unit})——值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n });\n } else {\n wind = { kind: \"value\", value: wg, span: spanOf(t) };\n for (const finding of windParsed.rangeFindings) {\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: finding.message,\n span: finding.span,\n });\n }\n if (windParsed.gustMissing === true) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n // 缺测电码双形态(G// 标准两位 / G/// 磨损三斜杠)直出原文\n message: `阵风位缺测(${t.text}——G 后斜杠位缺测,组照常成立)`,\n span: spanOf(t),\n });\n }\n if (wg.variable && wg.variation !== undefined) {\n const vs = wg.variation.span;\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"info\",\n message: `静风变向(VRB)与风向变化组(${\n vs === undefined ? \"\" : raw.slice(vs.start, vs.end)\n })并存——VRB 本义方向不定,变化组冗余,报文自洽性存疑`,\n span: vs,\n });\n }\n }\n i += windParsed.consumed;\n }\n continue;\n }\n\n // 能见度(//// 显式缺测补 info 告警——对齐风/天气缺测口径;零分母判缺测补超界告警)\n const visParsed = (mask & M_VIS) !== 0 ? parseVisibilityToken(t, peek(1)) : null;\n if (visParsed !== null) {\n // 最低能见度方向组(WMO 15.6.2):挂到已存主导能见度(非重复组不出 duplicate 告警);\n // 脱离主导能见度单独出现属非规范形态——按能见度收下 + info 出声。\n // directionalAsPrimary = 脱离主导的方向组被按主导收下(非规范状态,解析器局部标记)——\n // 其后再来的方向组是「连挂第二枚」(1200NW 1200NE),同样出声不静默\n //(2026-09-14 独立复评补齐:此前连挂时第二枚静默覆写第一枚)\n if (visParsed.kind === \"directional\") {\n if (visibility?.kind === \"value\") {\n if (visibility.value.minimum !== undefined || directionalAsPrimary) {\n dupGroupWarning(\"最低能见度方向组\", visibility.value.minimum?.span, spanOf(t));\n }\n visibility = {\n kind: \"value\",\n value: {\n ...visibility.value,\n minimum: {\n value: visParsed.group.value,\n direction: visParsed.group.direction,\n span: visParsed.group.span,\n },\n },\n span: visibility.span,\n };\n } else {\n visibility = {\n kind: \"value\",\n value: {\n value: visParsed.group.value,\n unit: \"m\",\n exact: true,\n span: visParsed.group.span,\n },\n };\n directionalAsPrimary = true;\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `最低能见度方向组脱离主导能见度(${t.text})——按能见度收下`,\n span: spanOf(t),\n });\n }\n i += visParsed.consumed;\n continue;\n }\n if (visibility !== undefined) dupGroupWarning(\"能见度组\", visibility.span, spanOf(t));\n if (visParsed.kind === \"missing\") {\n if (visibility === undefined) {\n visibility = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n // 缺测电码两形态直出原文(//// 米制 / ////SM 英里制——加拿大自动站,RMK VIS MISG 佐证)\n message: `能见度组缺测(${t.text},无法观测能见度)`,\n span: spanOf(t),\n });\n }\n // 已有能见度组时:缺测电码不顶替在场值(duplicate-group 已出声)——\n // 后位 ////(温露位畸形/错位落点)按 last-wins 把 9999 冲成 missing 是纯信息损失\n //(2026-09-15 五角色评测批;WMO 正常报文能见度缺测只出现在能见度槽位,此形态仅见于错位/磨损报文)\n directionalAsPrimary = false;\n i += visParsed.consumed;\n continue;\n } else if (visParsed.kind === \"invalid\") {\n visibility = { kind: \"missing\", span: visParsed.span };\n directionalAsPrimary = false;\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: visParsed.message,\n span: visParsed.span,\n });\n } else {\n visibility = { kind: \"value\", value: visParsed.group, span: visParsed.group.span };\n directionalAsPrimary = false;\n }\n i += visParsed.consumed;\n continue;\n }\n\n // RVRNO:RVR 设备存在但明示不可用(显式缺测,区别于组省略)。\n // 正文位与 RMK 位行为统一(2026-09-15 方案一,专业判读定案):一律进 remarks(kind\n // 'rvr-no')——站级状态声明 typed 可见,原正文位不留痕的双标消除;RVRNO 单独出现\n //(此前无值组)仍 = rvr 显式缺测(既有 IR 契约不变)。\n // 值组与 RVRNO 并存 = 自相矛盾形态(规范未定义并存):值组按跑道级明细保留——具体\n // 值组是逐道运行信息、可信度高于无道号的站级状态码(预报员/塔台标准判读;NWS 官方\n // 解码器即「值组 + RVRNO 旗标并存不复算」),矛盾出声、文案描述矛盾本身不预言终态。\n if ((mask & M_R) !== 0 && text === \"RVRNO\") {\n if (rvr?.kind === \"value\") {\n const prevText = rvr.span === undefined ? \"\" : raw.slice(rvr.span.start, rvr.span.end);\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"info\",\n message: `RVRNO(站级:应报而缺)与 RVR 值组并存(${prevText})——矛盾形态,值组按跑道级明细保留,RVRNO 经 remarks/raw 可回溯`,\n span: spanOf(t),\n });\n } else {\n rvr = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"RVR 设备在但明示不可用(RVRNO)\",\n span: spanOf(t),\n });\n }\n remarks.push({ kind: \"rvr-no\", raw: text, span: spanOf(t) });\n i += 1;\n continue;\n }\n\n // RVR 与跑道状态(同为 R 前缀组,先按 RVR 语法试解、再按跑道状态电码试解)\n if ((mask & M_R) !== 0 && text.startsWith(\"R\") && text.includes(\"/\")) {\n const rvrParsed = parseRvrToken(t);\n if (rvrParsed !== null) {\n // 反向次序对称口径:RVRNO 在前、值组在后同样出声(方案一:可解读为传感器恢复,\n // 值组按明细保留——与正序矛盾并存同一文案口径,见 RVRNO 位注释)\n if (rvr?.kind === \"missing\") {\n const prevText = rvr.span === undefined ? \"\" : raw.slice(rvr.span.start, rvr.span.end);\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"info\",\n message: `RVRNO(站级:应报而缺)与后随 RVR 值组并存(${prevText})——矛盾形态,值组按跑道级明细保留(可解读为传感器恢复),RVRNO 经 remarks/raw 可回溯`,\n span: spanOf(t),\n });\n }\n rvrList.push(rvrParsed);\n const s = spanOf(t);\n rvrSpan = rvrSpan === undefined ? s : { start: rvrSpan.start, end: s.end };\n rvr = { kind: \"value\", value: [...rvrList], span: rvrSpan };\n i += 1;\n continue;\n }\n const runwayState = parseRunwayStateToken(t);\n if (runwayState !== null) {\n runwayStates.push(runwayState.group);\n for (const finding of runwayState.findings) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: finding.message,\n span: finding.span,\n });\n }\n i += 1;\n continue;\n }\n // RVR 全斜杠缺测:R## + / + ////(分离符 + 四位值位斜杠 = 5 斜杠,标准缺测形态)。\n // 依据:WMO 306 FM15 RVR 值位恒四位(VRVRVRVR),全斜杠即数值缺测(斜杠逐位填充的缺测惯例);\n // 4 斜杠(R10////)为磨损短一段——按缺测收下,另附 invalid-format info(tgftp/IEM 实弹均见)\n const rvrSlash = /^R\\d{2}[RLC]?(\\/{4,5})$/.exec(text);\n if (rvrSlash !== null) {\n rvr = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: `RVR 组缺测(${text}——跑道号在位、视程值位全斜杠)`,\n span: spanOf(t),\n });\n if ((rvrSlash[1] ?? \"\").length === 4) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `RVR 缺测段磨损(${text}——4 位斜杠对标准 5 位(分离符 + 四位值位),少一位;按缺测收下)`,\n span: spanOf(t),\n });\n }\n i += 1;\n continue;\n }\n }\n\n // 风切变组(WMO 306 FM15 §15.13.3 / ICAO Annex 3 模板):标准形态 WS ALL RWY(全部跑道)\n // 与 WS R##[RLC](WS RDRDR,如 WS R24——IEM 归档实弹 544 次、中国区多发且为近月主流形态)。\n // 中国区实务变体 WS RWY##[RLC](RWY 前缀 + 设计器,教材常用)与 WS RWY ALL(词序倒置)\n // 同样语义无损一等收下——四形态正文组(跑道状态之后、趋势之前)。\n // 低空风切变对起降阶段是重大危害,IR 一等字段不蒸发。\n if ((mask & M_WS_RWY) !== 0 && text === \"WS\") {\n const rwyTok = peek(1);\n const designator = rwyTok !== undefined ? /^RWY(\\d{2}[RLC]?)$/.exec(rwyTok.text) : null;\n const stdDesignator = rwyTok !== undefined ? /^R(\\d{2}[RLC]?)$/.exec(rwyTok.text) : null;\n // 全跑道两形态:标准 WS ALL RWY 与词序倒置变体 WS RWY ALL\n const isAll =\n (rwyTok?.text === \"ALL\" && peek(2)?.text === \"RWY\") ||\n (rwyTok?.text === \"RWY\" && peek(2)?.text === \"ALL\");\n if (designator !== null || isAll || stdDesignator !== null) {\n const endTok = isAll ? peek(2) : rwyTok;\n const startSpan = spanOf(t);\n const endSpan = endTok !== undefined ? spanOf(endTok) : startSpan;\n wsRunways ??= [];\n if (designator !== null) wsRunways.push(designator[1] ?? \"\");\n if (stdDesignator !== null) wsRunways.push(stdDesignator[1] ?? \"\");\n if (isAll) wsAll = true;\n wsSpan =\n wsSpan === undefined\n ? { start: startSpan.start, end: endSpan.end }\n : { start: wsSpan.start, end: endSpan.end };\n windShear = { runways: wsRunways, allRunways: wsAll, span: wsSpan };\n i += isAll ? 3 : 2;\n continue;\n }\n }\n\n // 温度预告组(TAF TX/TN 混入 METAR 通路,IEM 归档实弹 26 次——中国区 TAF 行混入 METAR 流):\n // TX25/0907Z = 最高 25°C、09 日 07Z 到达(ICAO Annex 3 附录五温度预告组,M 前缀 = 负值)。\n // 认组收下进 remarks(kind 'temperature-forecast',raw 保真)——TAF 语义不属于 METAR 趋势段,\n // 与既有 temp-extrema-6h/24h 同款认组粒度,不解码数值(RemarkGroup 无值槽,数值化留待后续 additive 扩展)\n const txTnM = (mask & M_WEATHER) !== 0 ? /^(TX|TN)M?\\d{2}\\/\\d{4}Z$/.exec(text) : null;\n if (txTnM !== null) {\n remarks.push({ kind: \"temperature-forecast\", raw: text, span: spanOf(t) });\n i += 1;\n continue;\n }\n\n // 天气组(RE 近期天气一并识别——不参与当前天气三态判定)\n const weatherParsed =\n (mask & M_WEATHER) !== 0 ? tryWeatherToken(t, weatherList, recentList) : false;\n if (weatherParsed !== false) {\n if (weatherParsed.outOfOrder) {\n // 能完整切解但语序反常(描述符在现象之后,如 RATS):按切解结果收下 + invalid-format 告警,\n // 不静默也不拒收;完全无法切解的仍走下方 unknown-token\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `天气组语序不合电码表(${text}:描述符须先于现象)——已按切解结果收下`,\n span: spanOf(t),\n });\n }\n if (weatherParsed.signWithVc) {\n // 强度符与 VC 并存(-VCTSRA 家族,NWS 自动站实弹):互斥是明文条款(4678 限定槽\n // 四选一、FAA AIM「Intensity and 'VC' will not appear together」),语义可无损恢复\n //(强度+邻近+现象俱全)故容忍切解收下并出声——此前整体落 unknown-token 语义全丢\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `强度符与 VC 邻近指示并存(${text}——强度符不与 VC 同组)——已按切解结果收下`,\n span: spanOf(t),\n });\n }\n if (weatherParsed.intensityMisuse === true) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message:\n weatherParsed.kind === \"recent\"\n ? `RE 近期天气组带强度符(${text}——15.13.2.1 RE 组无强度位)——已收下`\n : `强度符超适用面(${text}——表 4678 注 4:-/+ 仅限降水族,非降水唯 +SS/+FC/+DS)——已收下`,\n span: spanOf(t),\n });\n }\n i += 1;\n continue;\n }\n\n // 裸 // 天气缺测组(自动站无法观测天气;IR 口径 = weather missing,绝不捏造也不吞进温度组)\n if ((mask & M_WEATHER) !== 0 && text === \"//\") {\n weather = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"天气组缺测(//,无法观测天气)\",\n span: spanOf(t),\n });\n i += 1;\n continue;\n }\n\n // 云:云量位 /// 与云高 /// 双缺测形态(绝不捏造)\n const cloudM = (mask & M_CLOUD) !== 0 ? CLOUD_LAYER_PATTERN.exec(text) : null;\n if (cloudM !== null) {\n cloudSeen = true;\n const amountRaw = cloudM[1];\n const heightRaw = cloudM[2];\n const convectiveRaw = cloudM[3];\n const typeMissing = cloudM[4] !== undefined;\n const amountMissing = amountRaw === \"///\";\n const heightMissing = heightRaw === \"///\";\n if (heightMissing) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"云高缺测(///),不捏造基高\",\n span: spanOf(t),\n });\n }\n if (amountMissing) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"云量位缺测(///),探测到云但云量无法观测\",\n span: spanOf(t),\n });\n }\n if (typeMissing) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"云型位缺测(///)\",\n span: spanOf(t),\n });\n }\n cloudElements.push({\n kind: \"layer\",\n amount: amountRaw !== undefined && isCloudAmount(amountRaw) ? amountRaw : null,\n heightFt: {\n value:\n heightRaw !== undefined && heightRaw !== \"///\"\n ? Number.parseInt(heightRaw, 10) * 100\n : null,\n span: spanOf(t),\n },\n convective:\n convectiveRaw !== undefined && isConvective(convectiveRaw) ? convectiveRaw : undefined,\n span: spanOf(t),\n });\n i += 1;\n continue;\n }\n const vvM = (mask & M_VV) !== 0 ? VV_PATTERN.exec(text) : null;\n if (vvM !== null) {\n cloudSeen = true;\n const heightRaw = vvM[1];\n if (heightRaw === undefined || heightRaw === \"///\") {\n // 缺测电码形态才告警——合法数值组(VV002 = 垂直能见度 200ft)零告警\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message:\n heightRaw === \"///\"\n ? \"垂直能见度缺测(VV///,天空全遮蔽但垂直能见度不可测)\"\n : \"垂直能见度缺测(VV,兼容形态)\",\n span: spanOf(t),\n });\n }\n cloudElements.push({\n kind: \"vertical-visibility\",\n heightFt: {\n value:\n heightRaw === undefined || heightRaw === \"///\"\n ? null\n : Number.parseInt(heightRaw, 10) * 100,\n span: spanOf(t),\n },\n span: spanOf(t),\n });\n i += 1;\n continue;\n }\n if ((mask & M_SKY_CLEAR) !== 0 && isSkyClear(text)) {\n cloudSeen = true;\n clearCode = { code: text, span: spanOf(t) };\n i += 1;\n continue;\n }\n\n // 温度/露点\n const tempParsed = (mask & M_TEMP) !== 0 ? parseTempDewToken(t) : null;\n if (tempParsed !== null) {\n const dupTemp = temperature !== undefined || dewpoint !== undefined;\n if (dupTemp) dupGroupWarning(\"温度组\", temperature?.span ?? dewpoint?.span, tempParsed.span);\n // 已有温露组时:全缺测电码(/////)不顶替在场值(duplicate-group 已出声)——\n // 零信息量形态覆盖真实观测是纯信息损失;带部分值的形态(如 12//)照常 last-wins\n if (dupTemp && tempParsed.temperature === null && tempParsed.dewpoint === null) {\n i += 1;\n continue;\n }\n // 温度物理极值门(与 QNH 同款纪律):超可信范围判缺测 + value-out-of-range,\n // 绝不静默留假值;双侧同时超界合并为一条告警(M91/M95 不重复出声);\n // 显式缺测(//)另发 missing-expected,两告警互不替代\n const rawTemp = tempParsed.temperature;\n const rawDew = tempParsed.dewpoint;\n const outOfRange = (r: TemperatureReading | null): boolean =>\n r !== null && (r.celsius < TEMP_C_MIN || r.celsius > TEMP_C_MAX);\n const outT = outOfRange(rawTemp);\n const outD = outOfRange(rawDew);\n if (outT || outD) {\n const single = outT ? rawTemp : rawDew;\n const span = outT && outD ? tempParsed.span : single?.span;\n const shown = span === undefined ? `${TEMP_C_MIN}` : raw.slice(span.start, span.end);\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: `温度超出可信范围(${shown},合理区间 ${TEMP_C_MIN}–${TEMP_C_MAX}°C)——值不可信判缺测,原码经 span 回溯`,\n span,\n });\n }\n temperature = outT ? undefined : (rawTemp ?? undefined);\n dewpoint = outD ? undefined : (rawDew ?? undefined);\n if (rawTemp === null || rawDew === null) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n // 形态判别精确到正则(2026-09-14 独立复评收口:endsWith(\"/\") 会把 12// 的标准\n // 缺测与 12/// 的磨损形都误述为 24/ 形态)\n message: /^M?\\d{2}\\/$/.test(t.text)\n ? \"露点位缺测(24/ 形态,FMH-1 12.6.10)\"\n : \"温度/露点位缺测(//)\",\n span: tempParsed.span,\n });\n }\n // 交叉校验:露点不可能高于温度(相对湿度 >100% 物理不可能)——典型传感器故障形态。\n // 两组值照常保留(含 M 负值),矛盾交由告警呈现,绝不静默也不捏造\n if (\n temperature !== undefined &&\n dewpoint !== undefined &&\n temperature.celsius < dewpoint.celsius\n ) {\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `温度低于露点(${t.text})——物理不可能,疑似传感器故障`,\n span: tempParsed.span,\n });\n }\n i += 1;\n continue;\n }\n\n // 气压:Q(hPa)/ A(inHg,隐含小数点);5 位数 QNH 与物理范围外值 = 脏值(Q10054 家族)\n const qM = (mask & M_QNH) !== 0 ? /^Q(\\d{4,5})$/.exec(text) : null;\n if (qM !== null) {\n const digits = qM[1] ?? \"\";\n const hpa = Number.parseInt(digits, 10);\n if (digits.length === 5 || hpa < QNH_HPA_MIN || hpa > QNH_HPA_MAX) {\n altimeter = undefined;\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: `QNH 超出可信范围(${text},合理区间 ${QNH_HPA_MIN}–${QNH_HPA_MAX} hPa)——值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n });\n } else {\n setAltimeter({ value: hpa, unit: \"hPa\", span: spanOf(t) });\n }\n i += 1;\n continue;\n }\n const aM = (mask & M_ALTIMETER_A) !== 0 ? /^A(\\d{4})$/.exec(text) : null;\n if (aM !== null) {\n const inhg = Number.parseInt(aM[1] ?? \"0\", 10) / 100;\n if (inhg < ALT_INHG_MIN || inhg > ALT_INHG_MAX) {\n altimeter = undefined;\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: `高度表设定超出可信范围(${text} → ${inhg} inHg,合理区间 ${ALT_INHG_MIN}–${ALT_INHG_MAX})——值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n });\n } else {\n setAltimeter({ value: inhg, unit: \"inHg\", span: spanOf(t) });\n }\n i += 1;\n continue;\n }\n\n // 变化能见度(FAA 正文位形态:主能见度组后跟「VIS 1/4V1/2」变化区间)——\n // IR 建模为 RemarkKind 'variable-visibility'(不占 visibility 槽),与 RMK 段同族同 kind\n if ((mask & M_VIS_RANGE) !== 0 && text === \"VIS\" && VIS_V_RANGE.test(peek(1)?.text ?? \"\")) {\n const nextTok = peek(1);\n if (nextTok !== undefined) {\n remarks.push({\n kind: \"variable-visibility\",\n raw: `${text} ${nextTok.text}`,\n span: { start: t.start, end: nextTok.end },\n });\n i += 2;\n continue;\n }\n }\n\n // 维护指示符(正文级孤例)\n if ((mask & M_DOLLAR) !== 0 && text === \"$\") {\n remarks.push({ kind: \"maintenance\", raw: \"$\", span: spanOf(t) });\n i += 1;\n continue;\n }\n\n // 不静默:看不懂的 token 进 warnings,绝不丢弃\n warnings.push({\n code: \"unknown-token\",\n severity: \"info\",\n message: `未识别的组(${text})——已如实收下`,\n span: spanOf(t),\n });\n i += 1;\n }\n\n // 当前天气组:仅有实组时给值;RE-only 报文 weather 保持 undefined(组省略 ≠ 缺测)\n if (weatherList.length > 0) {\n const first = weatherList[0];\n const last = weatherList[weatherList.length - 1];\n if (first !== undefined && last !== undefined) {\n weather = {\n kind: \"value\",\n value: [...weatherList],\n span:\n first.span !== undefined && last.span !== undefined\n ? { start: first.span.start, end: last.span.end }\n : undefined,\n };\n }\n }\n if (cloudSeen) {\n clouds = { elements: cloudElements, clear: clearCode };\n }\n\n // CAVOK 词后矛盾校验:词位让位后,其后新出现的能见度/天气/云组若与 CAVOK 语义确定矛盾,\n // 此前静默并存——同三面判据出声(趋势段已被围栏隔离,不会流入此处的正文状态)\n if (cavok) cavokConflicts(\"后续\");\n\n // 云组自洽(WMO 15.9.2 / 15.9.1):VV 顶替整个云组、NSC/SKC/NCD/CLR 为无云电码——\n // 与层组并存均互斥矛盾形态,出声不静默(规范外容错照旧收下)\n const hasVvElement = cloudElements.some((e) => e.kind === \"vertical-visibility\");\n const hasLayerElement = cloudElements.some((e) => e.kind === \"layer\");\n if (hasVvElement && hasLayerElement) {\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: \"VV 组与云层组并存(WMO 15.9.2:VV 顶替整个云组)——报文自洽性存疑\",\n span: cloudElements[0]?.span,\n });\n }\n if (clearCode !== undefined && hasLayerElement) {\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `${clearCode.code}(无云电码)与云层组并存——互斥形态,报文自洽性存疑`,\n span: clearCode.span,\n });\n }\n\n // —— RMK 段(认组粒度;未知 ≠ 错误,不进 warnings)\n while (i < tokens.length) {\n const t = tokens[i];\n if (t === undefined) break;\n const text = t.text;\n const push = (remarkKind: RemarkKind, consumed = 1): void => {\n const slice = tokens.slice(i, i + consumed);\n remarks.push({\n kind: remarkKind,\n raw: slice.map((c) => c.text).join(\" \"),\n span: joinSpan(slice),\n });\n i += consumed;\n };\n\n if (text === \"AO1\" || text === \"AO2\" || text === \"A01\" || text === \"A02\") {\n // A01/A02 数字形态:tgftp 通路实弹 268 站次(与 FMH-1 字母形态 AO1/AO2 并存)\n push(\"auto-type\");\n continue;\n }\n if (/^SLP(\\d{3}|NO)$/.test(text)) {\n push(\"sea-level-pressure\");\n continue;\n }\n if (/^T[01]\\d{7}(T[01]\\d{7})?$/.test(text) || /^T[01]\\d{3}$/.test(text)) {\n push(\"precise-temperature\");\n continue;\n }\n if (/^P\\d{4}$/.test(text)) {\n push(\"precip-1h\");\n continue;\n }\n if (/^[67](?:\\d{4}|\\/{4})$/.test(text)) {\n // 6/7 组降水窗口(3/24h):量值 4 位;//// = 窗口降水缺测(FMH-1 实弹 6////,tgftp 语料 17 处)\n push(\"precip-window\");\n continue;\n }\n if (/^4\\/\\d{3}$/.test(text)) {\n push(\"snow-depth\");\n continue;\n }\n if (/^I[136]\\d{3}$/.test(text)) {\n // FMH-1 冰积组 = I + 间隔位(1/3/6h) + 3 位量值(I1001 → 1 小时 0.01 英寸);\n // 旧正则 \\d{4} 多吞一位致 I1001 形态全数落 unknown(2026-09-12 复评命中)\n push(\"ice-accretion\");\n continue;\n }\n if (/^5[0-8]\\d{3}$/.test(text)) {\n push(\"pressure-tendency\");\n continue;\n }\n // 24h 温度极值组:现行 FMH-1 为 9 位(4 + 最高[符号位 3 位] + 最低[符号位 3 位],\n // 如 401280089 = 最高 +12.8 / 最低 +8.9;符号位 1 = 负),IEM/tgftp 实弹全数 9 位;\n // 8 位旧形态兼容保留\n if (/^4(?:[01]\\d{3}[01]\\d{3}|\\d{7})$/.test(text)) {\n push(\"temp-extrema-24h\");\n continue;\n }\n if (/^[12]\\d{4}$/.test(text)) {\n push(\"temp-extrema-6h\");\n continue;\n }\n if (text === \"PK\" && tokens[i + 1]?.text === \"WND\") {\n push(\"peak-wind\", 3);\n continue;\n }\n if (text === \"WSHFT\" && tokens[i + 1] !== undefined) {\n push(\"wind-shift\", 2);\n continue;\n }\n if (text === \"PRESRR\" || text === \"PRESFR\") {\n push(\"pressure-change\");\n continue;\n }\n if (text === \"VISNO\") {\n push(\"vis-no\");\n continue;\n }\n if (text === \"TSNO\") {\n // TSNO(美网高频):雷暴传感器不工作——雷暴探测不可用(≠无雷暴),认组不再 unknown\n push(\"thunderstorm-sensor\");\n continue;\n }\n if (text === \"RVRNO\") {\n // RMK 位与正文位同口径(方案一):并存矛盾出声、值组明细保留(终态不改),\n // RVRNO 自身留痕 remarks——见正文 RVRNO 位注释\n if (rvr?.kind === \"value\") {\n const prevText = rvr.span === undefined ? \"\" : raw.slice(rvr.span.start, rvr.span.end);\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"info\",\n message: `RVRNO(站级:应报而缺)与 RVR 值组并存(${prevText})——矛盾形态,值组按跑道级明细保留,RVRNO 经 remarks/raw 可回溯`,\n span: spanOf(t),\n });\n } else {\n rvr = { kind: \"missing\", span: spanOf(t) };\n }\n push(\"rvr-no\");\n continue;\n }\n if (text === \"SFC\" && tokens[i + 1]?.text === \"VIS\") {\n // 分数尾 token(SFC VIS 2 1/2)一并吸收,不再散落 unknown(FMH-1 12.7.1.f)\n const frac = /^\\d\\/\\d(SM)?$/.test(tokens[i + 3]?.text ?? \"\") ? 1 : 0;\n push(\"surface-visibility\", 3 + frac);\n continue;\n }\n if (text === \"TWR\" && tokens[i + 1]?.text === \"VIS\") {\n // TWR VIS 塔台能见度(FMH-1 12.7.1.f,值可为分数对)\n const frac = /^\\d\\/\\d(SM)?$/.test(tokens[i + 3]?.text ?? \"\") ? 1 : 0;\n push(\"twr-visibility\", 3 + frac);\n continue;\n }\n const visDirNext = tokens[i + 1]?.text;\n const RMK_VIS_DIR = /^(N|NE|E|SE|S|SW|W|NW)$/;\n const RMK_VIS_VAL = /^[MP]?\\d+(\\/\\d+)?(SM)?$/;\n if (\n text === \"VIS\" &&\n visDirNext !== undefined &&\n RMK_VIS_DIR.test(visDirNext) &&\n tokens[i + 2] !== undefined\n ) {\n // 分区能见度(方位在前)VIS <方位> <量值>〔<方位> <量值>…〕(FMH-1 12.7.1.h,量值可为整数+分数对)\n // 多扇区实弹(PANC:VIS E 10 SE 10 S 10)整段并组保真,后续方位对不再散落 unknown\n const frac = /^\\d\\/\\d(SM)?$/.test(tokens[i + 3]?.text ?? \"\") ? 1 : 0;\n let consumed = 3 + frac;\n for (let j = i + consumed; ;) {\n const dir = tokens[j]?.text;\n if (dir === undefined || !RMK_VIS_DIR.test(dir)) break;\n const val = tokens[j + 1]?.text;\n if (val === undefined || !RMK_VIS_VAL.test(val)) break;\n const pair = /^\\d+$/.test(val) && /^\\d\\/\\d(SM)?$/.test(tokens[j + 2]?.text ?? \"\") ? 3 : 2;\n consumed += pair;\n j += pair;\n }\n push(\"sectoral-visibility\", consumed);\n continue;\n }\n if (text === \"VIS\" && visDirNext !== undefined && RMK_VIS_VAL.test(visDirNext)) {\n // 分区能见度(量值在前)VIS <量值>〔<方位>〕(FMH-1 12.7.1.h;PANC 实弹:VIS 1 1/2 N)\n let consumed = 2; // VIS + 量值\n if (/^\\d+$/.test(visDirNext) && /^\\d\\/\\d(SM)?$/.test(tokens[i + 2]?.text ?? \"\"))\n consumed += 1; // 整数+分数对\n if (\n tokens[i + consumed]?.text !== undefined &&\n RMK_VIS_DIR.test(tokens[i + consumed]?.text ?? \"\")\n )\n consumed += 1;\n push(\"sectoral-visibility\", consumed);\n continue;\n }\n if (/^CIGNO$/.test(text)) {\n // 云高计不可用(FMH-1 12.7.1.p 族,与 VISNO/TSNO/RVRNO 同族口径)\n push(\"cig-not-available\");\n continue;\n }\n const cigNext = tokens[i + 1]?.text;\n if (text === \"CIG\" && cigNext !== undefined) {\n // CIG hhhVhhh 波动 / CIG hhh LOC / CIG hhh(FMH-1 12.7.1.p)\n const nxt = cigNext;\n if (/^\\d{3}V\\d{3}$/.test(nxt)) {\n push(\"ceiling-variation\", 2);\n continue;\n }\n if (/^\\d{3}$/.test(nxt)) {\n if (tokens[i + 2]?.text === \"LOC\") {\n push(\"ceiling-at-location\", 3);\n continue;\n }\n push(\"ceiling\", 2);\n continue;\n }\n }\n if (text === \"PNO\") {\n // 降水传感器不可用(FMH-1 12.7.2.g 族)\n push(\"precip-not-available\");\n continue;\n }\n if (text === \"FZRANO\") {\n push(\"fzr-not-available\");\n continue;\n }\n if (text === \"CHINO\") {\n push(\"chino\");\n continue;\n }\n if (/^8\\/[0-9X/]{3}$/.test(text)) {\n // 8/CCC 云型组(低/中/高云型电码 0–9,X 未知,/ 缺测;FMH-1 12.7.2.b)\n push(\"cloud-type-8group\");\n continue;\n }\n if (/^933\\d{3}$/.test(text)) {\n // 933RRR 积雪水当量(英寸百分之一;FMH-1 12.7.2.a)\n push(\"snow-water-equivalent\");\n continue;\n }\n if (text === \"FUNNEL\" && tokens[i + 1]?.text === \"CLOUD\") {\n push(\"phenomenon-began-ended\", 2);\n continue;\n }\n if (text === \"LTG\") {\n // 多 token 聚合:LTG 后按词表(LTG_TAIL_VOCAB)连收 + 词表词后夹带至多一个 1–2 位\n // 数字距离 token(FMH-1 ch.12:自动站雷电视频距离为海里裸数字,如 LTG ALQDS CG 12 OHD——\n // 数字须跟在词表词后,LTG 直连裸数字无出处)。聚合仍被词表外 token 截断;\n // 数字吸收以「前一吸收 token ∈ 词表」为前置且至多一个——防无关散落数字被静默吞进\n // lightning remark(2026-09-14 收紧:实现此前与注释声明不符,语料 229 处 LTG 零裸数字)\n let consumed = 1;\n let prevInVocab = false;\n let digitsAbsorbed = 0;\n for (;;) {\n const nextTok = tokens[i + consumed];\n if (nextTok === undefined) break;\n if (LTG_TAIL_VOCAB.has(nextTok.text)) {\n consumed += 1;\n prevInVocab = true;\n continue;\n }\n if (prevInVocab && digitsAbsorbed === 0 && /^\\d{1,2}$/.test(nextTok.text)) {\n consumed += 1;\n digitsAbsorbed += 1;\n prevInVocab = false;\n continue;\n }\n break;\n }\n push(\"lightning\", Math.min(consumed, tokens.length - i));\n continue;\n }\n if (text === \"SNINCR\" && /^\\d+\\/\\d+$/.test(tokens[i + 1]?.text ?? \"\")) {\n // SNINCR <时增>/<总量>(英寸,两 token 一组)——积雪增率,2026-09-12 复评补建模\n push(\"snow-increase\", 2);\n continue;\n }\n if (text === \"VIS\" && VIS_V_RANGE.test(tokens[i + 1]?.text ?? \"\")) {\n // 变化能见度 VIS 1/2V2(IR RemarkKind 'variable-visibility' 声明补实现)\n push(\"variable-visibility\", 2);\n continue;\n }\n // began/ended 家族(FZRAB43E50 合并形态 / RAB42·RAE50 拆分形态 / B43 裸起止)——\n // 边界收紧(2026-09-12):词身须能按天气组切解(FZRA/RA/TS…),俄区 QBB(云底高度,\n // 国家组)等非天气字母组不再被 [A-Z]{2,8} 前缀误吞进本类\n const beganMerged = /^([A-Z]{2,8})B\\d{2,4}(?:E\\d{2,4})?$/.exec(text);\n const beganSplit = /^([A-Z]{2})[BE]\\d{2,4}$/.exec(text);\n const beganBodyOk = (m: RegExpExecArray | null): boolean =>\n m !== null && splitWeatherToken(m[1] ?? \"\") !== null;\n if (beganBodyOk(beganMerged) || beganBodyOk(beganSplit) || /^[BE]\\d{2,4}$/.test(text)) {\n push(\"phenomenon-began-ended\");\n continue;\n }\n if (/^QBB\\d{3}$/.test(text)) {\n // QBB(俄区国家组):云底高度(米,3 位直读,与正文云组互为印证)\n push(\"cloud-base-height\");\n continue;\n }\n if (/^QFE\\d{3,4}(\\/\\d{3,4})?$/.test(text)) {\n // QFE(俄区国家组):场面气压。值语义(查证 2026-09-12):三位数 = 毫米汞柱(QFE749 = 749 mmHg,\n // 俄区惯例报 mmHg 场压);双段 QFE746/0995 = 746 mmHg 与 995 hPa 双单位(760 mmHg = 1013.25 hPa\n // 标准大气换算互证,metar-taf.com 俄区实报 RMK R08L/QFE741/0988 同族);四位数直读 hPa(QFE1003)。\n // 认组粒度收下不解码数值(RemarkGroup 无值槽;单位歧义风险由「不解码」规避),原码经 span 可取\n push(\"aerodrome-pressure\");\n continue;\n }\n if (text === \"$\") {\n push(\"maintenance\");\n continue;\n }\n push(\"unknown\");\n }\n\n return compactIfEnabled({\n kind,\n raw,\n station,\n time,\n flags: { auto, corrected },\n cavok,\n cavokSpan,\n wind,\n visibility,\n runwayVisualRange: rvr,\n weather,\n recentWeather: recentList.length > 0 ? recentList : undefined,\n clouds,\n temperature,\n dewpoint,\n altimeter,\n seaLevelPressure: undefined,\n trends,\n runwayStates,\n windShear,\n remarks,\n warnings,\n });\n}\n\n/** Result-style parse outcome: never throws for parse-level failures — branch on `ok` instead of try/catch.\n * 结果式解析出口:解析层失败不抛出,按 ok 分流——批量回放/管道消费免 try/catch 控制流。 */\nexport type TryParseResult =\n | { readonly ok: true; readonly report: MetarReport }\n | { readonly ok: false; readonly error: MetarParseError };\n\n/**\n * `parse` 的问题式变体:整体失败返回 `{ ok:false, error }`(MetarParseError,code 契约同 parse),\n * 成功返回 `{ ok:true, report }`。仅编程性意外(非 MetarParseError 的内部异常)原样抛出——\n * 不吞实现缺陷。语义与 parse 完全一致(同一实现,确定性继承)。\n * Result-style variant of `parse`: whole-report failures come back as `{ ok:false, error }`\n * with the same stable `code` contract; unexpected non-MetarParseError exceptions still throw.\n */\nexport function tryParse(raw: string, options?: ParseOptions): TryParseResult {\n try {\n return { ok: true, report: parse(raw, options) };\n } catch (err) {\n if (err instanceof MetarParseError) return { ok: false, error: err };\n throw err;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/groups.ts","../src/validate.ts","../src/taf.ts","../src/expand.ts","../src/index.ts"],"sourcesContent":["/**\n * @metweave/parser — 组级解析共享层(token 游标之上的纯函数与词表)。\n * Group-level parsing shared layer: pure functions and vocabularies above the token cursor.\n *\n * 2026-09-23 批 1.0 自 index.ts 机械迁出(METAR 行为零变化:324 测试零改动 + 语料回放零漂移)——\n * 供 parse()(METAR/SPECI)与 parseTaf()(TAF,批 1 起)共用;本模块不出口包 API(入口仍 index.ts)。\n */\nimport type {\n AltimeterReading,\n CloudAmount,\n CloudCondition,\n CloudElement,\n ConvectiveType,\n Observed,\n ParseWarning,\n RemarkGroup,\n RemarkKind,\n RunwayStateGroup,\n RunwayVisualRange,\n SkyClearCode,\n Span,\n TemperatureReading,\n TrendElements,\n TrendGroup,\n VisibilityGroup,\n WeatherDescriptor,\n WeatherGroup,\n WeatherPhenomenon,\n WindGroup,\n} from \"@metweave/core\";\n\nexport interface Token {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\nconst PHENOMENA: readonly WeatherPhenomenon[] = [\n \"DZ\",\n \"RA\",\n \"SN\",\n \"SG\",\n \"IC\",\n \"PL\",\n \"GR\",\n \"GS\",\n \"UP\",\n \"BR\",\n \"FG\",\n \"FU\",\n \"VA\",\n \"DU\",\n \"SA\",\n \"HZ\",\n \"PY\",\n \"PO\",\n \"SQ\",\n \"FC\",\n \"SS\",\n \"DS\",\n];\nconst DESCRIPTORS: readonly WeatherDescriptor[] = [\"MI\", \"PR\", \"BC\", \"DR\", \"BL\", \"SH\", \"TS\", \"FZ\"];\nexport const TREND_KINDS = new Set<string>([\"NOSIG\", \"BECMG\", \"TEMPO\"]);\n/** 趋势段拖词容忍集(无 typed 语义的磨损尾/连接词——收进 trend.raw 静默保真,不产生噪声):\n * 语料实弹 VNKT 120930Z「NOSIG CB TO NE AND E」(观测员补记磨损尾)与既有回归锁契约\n * (拖词不告警、原文留 raw);含裸对流码 CB/TCU(无云量云高位的残缺云信息,无解码面)与\n * 16 方位词、TO/AND 连接词。与「交回正文恢复 typed 语义」的收窄主判据互补:\n * 有语义可恢复的(温露/QNH/$/WS/TX/TN/RVRNO)一律收口交回,纯噪声拖词保持原文静默。 */\nconst TREND_FILLER_WORDS = new Set([\n \"TO\",\n \"AND\",\n \"CB\",\n \"TCU\",\n \"N\",\n \"NNE\",\n \"NE\",\n \"ENE\",\n \"E\",\n \"ESE\",\n \"SE\",\n \"SSE\",\n \"S\",\n \"SSW\",\n \"SW\",\n \"WSW\",\n \"W\",\n \"WNW\",\n \"NW\",\n \"NNW\",\n]);\n/** 趋势段收组判据(封闭清单):只有趋势合法要素族(WMO 306 FM15 §15.14.2/§15.14.10:风/能见度/现在天气/云,\n * 加趋势专属 NSW 与 CAVOK 顶替)与风组变化组拖带形(dddVddd)可收进趋势段;其余 token 一律收口\n * 交回正文循环——正文各分支自带认组与 unknown-token 出声,语义无损恢复,冲突组自然触发重复组告警。\n *\n * 根因一(2026-09-12 复评实弹):旧收集循环只认趋势指示组,俄区报文「NOSIG RMK QFE749」把 RMK 段\n * 整段吞进 trends(RU 61/65、KZ 18/18 条命中)、remarks 反而为空。\n * 根因二(2026-09-14 复评实弹):收口改「白名单补洞」后正文专属组(温露/QNH/$/WS/TX/TN/RVRNO)\n * 仍被静默吞进 trend.raw、typed 语义蒸发——RMK、Rxx/、$ 已是三次逃逸,补洞循环就此终结:\n * 判据反转为规范封闭清单,未来一切新正文分支自动获得「交回正文 + 出声」兜底。\n * 硬边界保留:RMK(含词身粘连 startsWith)与 R 组形态——R 组收口另有 trendCloseWarning 出声。 */\nconst isTrendCollectible = (t: Token, next: Token | undefined): boolean => {\n const text = t.text;\n // 段间切换与正文硬边界:下一个趋势指示组、RMK、R 组形态(Rxx/…、R/SNOCLO)一律收口\n if (TREND_KINDS.has(text) || text.startsWith(\"RMK\")) return false;\n if (/^R(\\d{2}[RLC]?\\/|\\/SNOCLO$)/.test(text)) return false;\n // 趋势专属词与天气缺测电码\n if (text === \"CAVOK\" || text === \"NSW\" || text === \"//\") return true;\n // 拖词容忍集(见 TREND_FILLER_WORDS 注:无 typed 语义,静默保真优于 unknown 噪声)\n if (TREND_FILLER_WORDS.has(text)) return true;\n // 磨损时段词(一趋势内第二/三个 AT|TL|FM ddhh——指示组已在,按拖词静默保真;\n // tgftp/归档实弹,回归锁:标准位置时段词零告警)\n if (/^(AT|TL|FM)\\d{4}$/.test(text)) return true;\n // 风(含 /////KT 缺测、VRB、P 超上限形)与风组变化组拖带(dddVddd 单独成 token)\n if (parseWindToken(t, next) !== null || /^\\d{3}V\\d{3}$/.test(text)) return true;\n // 能见度(米制 4 位/NDV/方向组/SM 族/混分数跨 token///// 缺测家族)\n if (parseVisibilityToken(t, next) !== null) return true;\n // 现在天气(VC 邻近/-+ 强度/组合词身/裸 TS;RE 近期天气不属趋势族——交回正文按 recentWeather 认组)\n if (parseWeatherBody(text) !== null) return true;\n // 云(层组/VV/晴空码)\n if (CLOUD_LAYER_PATTERN.test(text) || VV_PATTERN.test(text) || isSkyClear(text)) return true;\n return false;\n};\nconst SKY_CLEAR_CODES: readonly SkyClearCode[] = [\"SKC\", \"NSC\", \"NCD\", \"CLR\"];\nconst CLOUD_AMOUNTS: readonly CloudAmount[] = [\"FEW\", \"SCT\", \"BKN\", \"OVC\"];\nconst SPEED_UNITS: readonly WindGroup[\"speed\"][\"unit\"][] = [\"kt\", \"mps\", \"kmh\"];\n/** QNH/A 物理可信范围:世界海平面气压极值 870(台风 Tip)–1083.8 hPa(蒙古高压 Agata 1968)——\n * 上界取 1084(极值之上即物理不可能,复评实弹 Q1087 由此拦截),下界 800 留裕量;\n * A 组(inHg)按同区间镜像换算外圆整为 23.5–32.5(800 hPa ≈ 23.62、1084 ≈ 32.02)。\n * 越界 = 值不可信 → 判缺测 + value-out-of-range 告警(与 Q10054 位数超界同纪律,绝不静默留假值)。 */\nconst QNH_HPA_MIN = 800;\nconst QNH_HPA_MAX = 1084;\nconst ALT_INHG_MIN = 23.5;\nconst ALT_INHG_MAX = 32.5;\n/** 温度物理可信范围:世界极值 +56.7°C(Death Valley 1913)/ −89.2°C(Vostok 1983),\n * 取 60/−90 留裕量(与 QNH 世界极值门同款纪律)——两位数模板空间内的物理不可能值\n * (89/85 构造实弹)不可信判缺测,绝不静默留假值。 */\nconst TEMP_C_MIN = -90;\nconst TEMP_C_MAX = 60;\n/** LTG 尾随词表(FMH-1 雷电视词与方位):放电类型 IC/CG/CC/CA、位置 OHD/ALQDS/DSNT/VCNTY 与 16 方位点。\n * 实弹(tgftp 全 cycle)LTG 后的方位词此前逐个散落成 unknown remarks(ALQDS/OHD/方位词一片)。 */\nconst LTG_TAIL_VOCAB = new Set([\n \"IC\",\n \"CG\",\n \"CC\",\n \"CA\",\n \"OHD\",\n \"ALQDS\",\n \"DSNT\",\n \"VCNTY\",\n \"N\",\n \"NNE\",\n \"NE\",\n \"ENE\",\n \"E\",\n \"ESE\",\n \"SE\",\n \"SSE\",\n \"S\",\n \"SSW\",\n \"SW\",\n \"WSW\",\n \"W\",\n \"WNW\",\n \"NW\",\n \"NNW\",\n]);\n/** 变化能见度尾组形态(RMK VIS 1/2V2 / VIS 1/4V1/2):两侧为整数或分数(可带 M/P 阈值前缀)。 */\nexport const VIS_V_RANGE = /^[MP]?\\d+(?:\\/\\d+)?V[MP]?\\d+(?:\\/\\d+)?$/;\n/** 温度预告组形态(TAF TX/TN 混入 METAR 通路:TX25/0907Z = 最高 25°C、09 日 07Z 到达,M 前缀 = 负值)。 */\nexport const TX_TN_PATTERN = /^(TX|TN)M?\\d{2}\\/\\d{4}Z$/;\n\n// —— E3 首字符位掩码(正文循环分支分流用;可达首字符推导见正文循环内注释)\nexport const M_WIND = 1 << 0;\nexport const M_VIS = 1 << 1;\nexport const M_R = 1 << 2;\nexport const M_WEATHER = 1 << 3;\nexport const M_CLOUD = 1 << 4;\nexport const M_VV = 1 << 5;\nexport const M_SKY_CLEAR = 1 << 6;\nexport const M_TEMP = 1 << 7;\nexport const M_QNH = 1 << 8;\nexport const M_ALTIMETER_A = 1 << 9;\nexport const M_VIS_RANGE = 1 << 10;\nexport const M_DOLLAR = 1 << 11;\nexport const M_WS_RWY = 1 << 12;\n\n/** 首字符(charCode)→ 候选分支位掩码;0 = 无分支可达(直接落 unknown-token) */\nexport function maskOf(code: number): number {\n if (code >= 48 && code <= 57) return M_WIND | M_VIS | M_TEMP; // 0-9\n switch (code) {\n case 47: // /\n return M_WIND | M_VIS | M_WEATHER | M_CLOUD | M_TEMP;\n case 86: // V(VRB 风 / VC 天气 / VV / VIS)\n return M_WIND | M_WEATHER | M_VV | M_VIS_RANGE;\n case 77: // M(M1/4SM / MIFG / M10/)\n return M_VIS | M_WEATHER | M_TEMP;\n case 80: // P(P6SM / PL PO PY PR)\n return M_VIS | M_WEATHER;\n case 82: // R(RVRNO / R 组 / RA…)\n return M_R | M_WEATHER;\n case 81: // Q\n return M_QNH;\n case 65: // A(AUTO 词已在前置词位收口,此处仅 A 组)\n return M_ALTIMETER_A;\n case 66: // B\n case 70: // F\n return M_WEATHER | M_CLOUD;\n case 79: // O(现象/描述符无 O 首字母)\n return M_CLOUD;\n case 83: // S\n return M_WEATHER | M_CLOUD | M_SKY_CLEAR;\n case 78: // N\n case 67: // C\n return M_SKY_CLEAR;\n case 68: // D\n case 71: // G\n case 72: // H\n case 73: // I\n case 84: // T\n case 85: // U\n case 45: // -\n case 43: // +\n return M_WEATHER;\n case 36: // $\n return M_DOLLAR;\n case 87: // W(WS 风切变组)\n return M_WS_RWY;\n default:\n return 0;\n }\n}\n\nconst isPhenomenon = (s: string): s is WeatherPhenomenon => PHENOMENA.some((p) => p === s);\nconst isDescriptor = (s: string): s is WeatherDescriptor => DESCRIPTORS.some((p) => p === s);\nconst isCloudAmount = (s: string): s is CloudAmount => CLOUD_AMOUNTS.some((p) => p === s);\nexport const isSkyClear = (s: string): s is SkyClearCode => SKY_CLEAR_CODES.some((p) => p === s);\nconst isSpeedUnit = (s: string): s is WindGroup[\"speed\"][\"unit\"] =>\n SPEED_UNITS.some((p) => p === s);\nconst isConvective = (s: string): s is ConvectiveType => s === \"CB\" || s === \"TCU\";\n\nexport function tokenize(raw: string): Token[] {\n const tokens: Token[] = [];\n const rx = /\\S+/g;\n let m: RegExpExecArray | null;\n while ((m = rx.exec(raw)) !== null) {\n tokens.push({ text: m[0], start: m.index, end: m.index + m[0].length });\n }\n return tokens;\n}\n\nexport const spanOf = (t: Token): Span => ({ start: t.start, end: t.end });\n\n/** 云层组形态(FEW023CB / /////01CB/// 缺测位形态)——正文循环与趋势段结构化共用一份正则防漂移 */\nconst CLOUD_LAYER_PATTERN = /^(FEW|SCT|BKN|OVC|\\/\\/\\/)(\\d{3}|\\/\\/\\/)(CB|TCU)?(\\/\\/\\/)?$/;\n/** VV 组形态(VV / VV/// / VV002)——同上共用 */\nconst VV_PATTERN = /^VV(\\/\\/\\/|\\d{3})?$/;\n\n/**\n * 趋势段内要素结构化(WMO 306 FM15 §15.14.2:风/能见度/天气/云四族 + 趋势专属 NSW(§15.14.13)与 CAVOK(§15.10)顶替)。\n * best-effort 且静默:认不出的组不产生任何告警(告警面受语料快照锁保护),原文在 raw 保真;\n * 正文循环同款的 token 级解析函数直接复用(parseWindToken/parseVisibilityToken/parseWeatherBody),\n * 组形正则取共享常量。返回 undefined = 没有任何组被识别(如裸 NOSIG)。\n */\nexport function structureTrendElements(\n tokens: readonly Token[],\n start: number,\n): TrendElements | undefined {\n let wind: WindGroup | undefined;\n let visibility: VisibilityGroup | undefined;\n let cavok: TrendElements[\"cavok\"];\n let nsw: TrendElements[\"nsw\"];\n const weather: WeatherGroup[] = [];\n let clouds: CloudCondition | undefined;\n let k = start;\n while (k < tokens.length) {\n const t = tokens[k];\n if (t === undefined) break;\n const next = tokens[k + 1];\n if (t.text === \"CAVOK\") {\n cavok = { span: spanOf(t) };\n k += 1;\n continue;\n }\n if (t.text === \"NSW\") {\n nsw = { span: spanOf(t) };\n k += 1;\n continue;\n }\n if (wind === undefined) {\n const w = parseWindToken(t, next);\n if (w !== null && w !== \"missing\") {\n wind = w.group;\n k += w.consumed;\n continue;\n }\n }\n if (visibility === undefined) {\n const vis = parseVisibilityToken(t, next);\n if (vis !== null && vis.kind === \"ok\") {\n visibility = vis.group;\n k += vis.consumed;\n continue;\n }\n }\n const wx = parseWeatherBody(t.text);\n if (wx !== null) {\n // 内部信号(outOfOrder/signWithVc)不进 IR;趋势段 tolerant 静默收下\n const { outOfOrder: _outOfOrder, signWithVc: _signWithVc, ...group } = wx;\n weather.push({ ...group, span: spanOf(t) });\n k += 1;\n continue;\n }\n const cloudM = CLOUD_LAYER_PATTERN.exec(t.text);\n if (cloudM !== null) {\n const amountRaw = cloudM[1];\n const heightRaw = cloudM[2];\n const convectiveRaw = cloudM[3];\n clouds = {\n elements: [\n ...(clouds?.elements ?? []),\n {\n kind: \"layer\",\n amount: amountRaw !== undefined && isCloudAmount(amountRaw) ? amountRaw : null,\n heightFt: {\n value:\n heightRaw !== undefined && heightRaw !== \"///\"\n ? Number.parseInt(heightRaw, 10) * 100\n : null,\n span: spanOf(t),\n },\n convective:\n convectiveRaw !== undefined && isConvective(convectiveRaw)\n ? convectiveRaw\n : undefined,\n span: spanOf(t),\n },\n ],\n ...(clouds?.clear !== undefined ? { clear: clouds.clear } : {}),\n };\n k += 1;\n continue;\n }\n const vvM = VV_PATTERN.exec(t.text);\n if (vvM !== null) {\n const heightRaw = vvM[1];\n clouds = {\n elements: [\n ...(clouds?.elements ?? []),\n {\n kind: \"vertical-visibility\",\n heightFt: {\n value:\n heightRaw === undefined || heightRaw === \"///\"\n ? null\n : Number.parseInt(heightRaw, 10) * 100,\n span: spanOf(t),\n },\n span: spanOf(t),\n },\n ],\n ...(clouds?.clear !== undefined ? { clear: clouds.clear } : {}),\n };\n k += 1;\n continue;\n }\n if (isSkyClear(t.text)) {\n clouds = { elements: clouds?.elements ?? [], clear: { code: t.text, span: spanOf(t) } };\n k += 1;\n continue;\n }\n k += 1; // 认不出的组:原文保真、静默跳过(tolerant 纪律,绝不静默丢原文)\n }\n if (\n wind === undefined &&\n visibility === undefined &&\n cavok === undefined &&\n nsw === undefined &&\n weather.length === 0 &&\n clouds === undefined\n )\n return undefined;\n return {\n ...(wind !== undefined ? { wind } : {}),\n ...(visibility !== undefined ? { visibility } : {}),\n ...(cavok !== undefined ? { cavok } : {}),\n weather,\n ...(nsw !== undefined ? { nsw } : {}),\n ...(clouds !== undefined ? { clouds } : {}),\n };\n}\n\nfunction joinSpan(tokens: readonly Token[]): Span {\n const first = tokens[0];\n const last = tokens[tokens.length - 1];\n if (first === undefined || last === undefined) return { start: 0, end: 0 };\n return { start: first.start, end: last.end };\n}\n\n/**\n * 紧凑模式出口剥除(E1)v2——重建式:遍历构造全新对象(不含 span/cavokSpan 键),零 mutation。\n * 设计权衡(实测驱动,两版对比):\n * - 构造期逐点跳过 span 的方案在 full 模式引入 ~20% 退化(分支插入组构造热路径),否决;\n * - 旧版出口就地删键(Reflect.deleteProperty)让 V8 把产物退化为 dictionary mode(慢属性):\n * 实测紧凑吞吐仅全模式 ~32%(23 万 vs 72 万行/秒)、存活对象驻留反升 ~2.2×——此为本版根因修复对象;\n * - 重建式出口一次遍历:full 模式与旧版逐字节同路径(零开销),紧凑产物保持 fast properties\n * (隐藏类不丢),实测吞吐回到全模式 ~55% 量级(40.6 万 vs 72.8 万行/秒,旧版仅 32%)、\n * 驻留与全模式持平(1.01×,旧版反升 2.21×——数字见 E 批性能冒烟锁注释)。\n * 数组重建新数组、原语透传;对象均为本次 parse 新建(无共享引用),键序保持原插入序(JSON 面稳定)。\n */\nexport function compactNode<T>(node: T): T {\n if (Array.isArray(node)) {\n const out: unknown[] = [];\n for (const item of node) out.push(compactNode(item));\n // 重建副本与原值同构(仅少 span 键)——与 structuredClone 同款「unknown → T」定型需求,断言无法避免\n // oxlint-disable-next-line no-unsafe-type-assertion\n return out as T;\n }\n if (node === null || typeof node !== \"object\") return node;\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n if (key === \"span\" || key === \"cavokSpan\") continue; // 剥除目标键:不进新对象(而非删除)\n out[key] = compactNode(value);\n }\n // 同上:键值逐项来自原对象(仅滤除 span),与 T 同构\n // oxlint-disable-next-line no-unsafe-type-assertion\n return out as T;\n}\n\n/** 天气组合词切分:把「TSRA」拆成描述符 TS + 现象 RA;无法合法切分返回 null。\n * outOfOrder = 能完整切解但语序不合电码表(描述符出现在现象之后,如 RATS=RA+TS)——\n * tolerant 纪律下仍按切解结果收下,由调用方追加 invalid-format 告警。\n * bare = 描述符单独编报(无现象)——TS 恒合法;SH 仅在 VC 邻近语境内合法(VCSH,\n * WMO 306 表 4678 注:机场附近有阵性降水但降水类型不可辨),由 parseWeatherBody 收口。 */\nfunction splitWeatherToken(body: string): {\n descriptor?: WeatherDescriptor;\n phenomena: readonly WeatherPhenomenon[];\n outOfOrder: boolean;\n bare: boolean;\n} | null {\n const chunks: string[] = [];\n for (let i = 0; i < body.length; i += 2) chunks.push(body.slice(i, i + 2));\n if (chunks.some((c) => c.length !== 2)) return null;\n const phenomena: WeatherPhenomenon[] = [];\n let descriptor: WeatherDescriptor | undefined;\n let sawPhenomenon = false;\n let outOfOrder = false;\n for (const c of chunks) {\n if (isPhenomenon(c)) {\n phenomena.push(c);\n sawPhenomenon = true;\n } else if (isDescriptor(c) && descriptor === undefined) {\n descriptor = c;\n if (sawPhenomenon) outOfOrder = true; // 电码表语序:描述符须先于现象\n } else return null;\n }\n if (phenomena.length === 0 && descriptor !== \"TS\" && descriptor !== \"SH\") return null; // TS/SH 单独编报见 bare 注\n return { descriptor, phenomena, outOfOrder, bare: phenomena.length === 0 };\n}\n\n/** 天气组词身解析:VC 邻近 / -+ 强度 / 双字母组合切分。返回 null 表示不是合法天气组。\n * signWithVc = 强度符与 VC 并存(-VCTSRA 家族,NWS 自动站实弹):4678 限定槽四选一\n * (light −/moderate 无符/heavy +/vicinity VC)、FAA AIM 明文互斥——tolerant 纪律下按切解\n * 收下(强度+邻近+现象语义可无损恢复,与 RATS→outOfOrder 容忍同构),由调用方出声。 */\nfunction parseWeatherBody(text: string): {\n intensity?: \"-\" | \"+\";\n proximity: boolean;\n descriptor?: WeatherDescriptor;\n phenomena: readonly WeatherPhenomenon[];\n outOfOrder: boolean;\n signWithVc: boolean;\n} | null {\n let rest = text;\n let proximity = false;\n let signWithVc = false;\n if (rest.startsWith(\"VC\")) {\n proximity = true;\n rest = rest.slice(2);\n }\n let intensity: \"-\" | \"+\" | undefined;\n const sign = rest.slice(0, 1);\n if (sign === \"-\" || sign === \"+\") {\n intensity = sign;\n rest = rest.slice(1);\n // 强度符后随 VC(-VCTSRA / -VCSH):非规范词序(规范语序 VC 在最前、强度符与 VC 互斥)\n if (rest.startsWith(\"VC\")) {\n proximity = true;\n signWithVc = true;\n rest = rest.slice(2);\n }\n }\n if (rest.length < 2 || rest.length % 2 !== 0) return null;\n const split = splitWeatherToken(rest);\n if (split === null) return null;\n // 裸 SH(无现象)仅在 VC 邻近形态合法(VCSH);非 VC 的裸 SH 是坏组不收\n if (split.bare && split.descriptor === \"SH\" && !proximity) return null;\n return {\n intensity,\n proximity,\n descriptor: split.descriptor,\n phenomena: split.phenomena,\n outOfOrder: split.outOfOrder,\n signWithVc,\n };\n}\n\n/**\n * 解析天气组 token(含 RE 前缀 / VC 邻近 / -+ 强度)。\n * 返回 kind「current」仅当组进入当前天气列表;「recent」= RE 近期天气(另一组位,不参与 weather 三态);\n * outOfOrder = 词身能切解但语序不合电码表;false = 不是天气组。\n */\n/** 强度符适用面(WMO 306 表 4678 注 4):降水全族可带 -/+;+SS/+FC/+DS 为 4678 表内合法电码\n * (codes.wmo.int/306/4678 稳定概念:+DS heavy duststorm、+SS heavy sandstorm、+FC 发展完好\n * 漏斗云;加拿大差异版另有官方能见度判据 <5/16 SM)——表内形态照常收下、零告警;\n * FMH-1 仅对降水族定义强度测定(美国实务不产 +DS),出处为 4678 电码表本身而非 FMH-1 容错。\n * (2026-09-14 口径归位:旧注释称「+DS 由调用方出声」与实现不符——它本就是表内电码。) */\nconst PRECIP_PHENOMENA = new Set<WeatherPhenomenon>([\n \"RA\",\n \"SN\",\n \"SG\",\n \"IC\",\n \"PL\",\n \"GR\",\n \"GS\",\n \"UP\",\n]);\nfunction intensityAllowedFor(\n intensity: \"-\" | \"+\",\n phenomena: readonly WeatherPhenomenon[],\n): boolean {\n if (phenomena.length > 0 && phenomena.every((x) => PRECIP_PHENOMENA.has(x))) return true;\n return intensity === \"+\" && phenomena.every((x) => x === \"SS\" || x === \"FC\" || x === \"DS\");\n}\n\nexport function tryWeatherToken(\n t: Token,\n weather: WeatherGroup[],\n recent: WeatherGroup[],\n):\n | {\n kind: \"current\" | \"recent\";\n outOfOrder: boolean;\n signWithVc: boolean;\n intensityMisuse?: boolean;\n }\n | false {\n const current = parseWeatherBody(t.text);\n if (current !== null) {\n const { outOfOrder, signWithVc, ...group } = current;\n weather.push({ ...group, span: spanOf(t) });\n return {\n kind: \"current\",\n outOfOrder,\n signWithVc,\n ...(current.intensity !== undefined &&\n !intensityAllowedFor(current.intensity, current.phenomena)\n ? { intensityMisuse: true }\n : {}),\n };\n }\n // RE 前缀(近期天气,15.13.2):REFC = RE + FC;RE 组不带强度符(15.13.2.1)\n if (t.text.startsWith(\"RE\")) {\n const recentBody = parseWeatherBody(t.text.slice(2));\n if (recentBody !== null) {\n const { outOfOrder, signWithVc: _signWithVc, ...group } = recentBody;\n recent.push({ ...group, span: spanOf(t) });\n return {\n kind: \"recent\",\n outOfOrder,\n signWithVc: false,\n ...(recentBody.intensity !== undefined ? { intensityMisuse: true } : {}),\n };\n }\n }\n return false;\n}\n\n/** 能见度解析结果三路:ok=有值;missing=显式缺测电码(//// 家族);\n * invalid=形态合法但值不可信(零分母 1/0SM——解码出 Infinity/NaN 的唯一入口),\n * 由调用方落 missing + value-out-of-range 告警(与 QNH 超界同款纪律,绝不留假值)。 */\nexport type VisibilityResult =\n | { readonly kind: \"ok\"; readonly group: VisibilityGroup; readonly consumed: number }\n | {\n readonly kind: \"directional\";\n readonly group: { readonly value: number; readonly direction: string; readonly span: Span };\n readonly consumed: number;\n }\n | { readonly kind: \"missing\"; readonly consumed: number }\n | {\n readonly kind: \"invalid\";\n readonly message: string;\n readonly span: Span;\n readonly consumed: number;\n };\n\n/** 能见度:米制 4 位(可带 NDV 后缀)/ 美制 SM(含混分数跨 token 的预合并、P6SM 超上限)/ //// 缺测家族。 */\nexport function parseVisibilityToken(t: Token, next: Token | undefined): VisibilityResult | null {\n // 缺测家族两形态(与单位正交)://// = 米制缺测;////SM = 英里制缺测(加拿大自动站,\n // RMK VIS MISG 佐证)——同为 visibility missing + missing-expected 告警(单位不进 missing 态)\n if (t.text === \"////\" || t.text === \"////SM\") return { kind: \"missing\", consumed: 1 };\n // NDV = No Directional Variation(无方向变化,加拿大自动站惯例后缀)——\n // 语义为「能见度各方向一致」,IR 无落点:剥离丢弃(原码经组 span 回溯),按 4 位主体正常解析\n // 最低能见度方向组(VNVNVNVNDv,如 1200NW)——须在 m4 之前判(带 1–2 位方位后缀)\n const mDir = /^(\\d{4})(NE|NW|SE|SW|N|E|S|W)$/.exec(t.text);\n if (mDir !== null) {\n return {\n kind: \"directional\",\n group: {\n value: Number.parseInt(mDir[1] ?? \"0\", 10),\n direction: mDir[2] ?? \"\",\n span: spanOf(t),\n },\n consumed: 1,\n };\n }\n const m4 = /^(\\d{4})(NDV)?$/.exec(t.text);\n if (m4 !== null) {\n const digits = m4[1] ?? \"\";\n const ceiling = digits === \"9999\";\n // 0000 = 下限编码(<100m,与 9999 上限编码同族)——非实测 0 米,exact=false + beyond below\n const floor = digits === \"0000\";\n return {\n kind: \"ok\",\n group: {\n value: Number.parseInt(digits, 10),\n unit: \"m\",\n exact: !ceiling && !floor,\n ...(ceiling ? { beyond: \"above\" as const } : {}), // 9999 = 10km 或以上(上限编码)\n ...(floor ? { beyond: \"below\" as const } : {}), // 0000 = 不足下限(下限编码)\n span: spanOf(t),\n },\n consumed: 1,\n };\n }\n // 混分数跨 token:`1 1/4SM`(裸整数 + 带分数 SM 是一个组)\n if (/^\\d$/.test(t.text) && next !== undefined && /^\\d\\/\\d+SM$/.test(next.text)) {\n const whole = Number.parseInt(t.text, 10);\n const parts = next.text.slice(0, -2).split(\"/\");\n const num = parts[0];\n const den = parts[1];\n if (num === undefined || den === undefined) return null;\n if (Number(den) === 0) {\n // 零分母(1 0/0SM):解码结果 Infinity/NaN——值不可信判缺测(span 覆盖整数与分数两个 token)\n return {\n kind: \"invalid\",\n message: `能见度混分数分母为零(${t.text} ${next.text})——解码不出有限值,值不可信判缺测,原码经 span 回溯`,\n span: { start: t.start, end: next.end },\n consumed: 2,\n };\n }\n return {\n kind: \"ok\",\n group: {\n value: whole + Number(num) / Number(den),\n unit: \"sm\",\n exact: true,\n span: { start: t.start, end: next.end },\n },\n consumed: 2,\n };\n }\n const sm = /^(M|P)?(\\d+)\\/(\\d+)SM$|^(M|P)?(\\d+)SM$/.exec(t.text);\n if (sm !== null) {\n const prefix = sm[1] ?? sm[4];\n const below = prefix === \"M\";\n const above = prefix === \"P\"; // P6SM:6 英里以上(美式超上限,FAA/AF 口径)——exact=false,与 9999 同族\n const den = sm[3];\n if (den !== undefined && Number(den) === 0) {\n // 单 token 零分母(1/0SM、0/0SM、M1/0SM——0/0 解码出 NaN,同属值不可信)\n return {\n kind: \"invalid\",\n message: `能见度分数分母为零(${t.text})——解码不出有限值,值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n consumed: 1,\n };\n }\n const value =\n sm[2] !== undefined ? Number(sm[2]) / Number(den) : Number.parseInt(sm[5] ?? \"0\", 10);\n // exact 语义统一:分数(1/2SM、1 1/4SM)与整数本身是精确值;\n // 阈值性编码(M 前缀小于下界、P 前缀大于上界、9999 上限)为 false,beyond 记方向\n return {\n kind: \"ok\",\n group: {\n value,\n unit: \"sm\",\n exact: !below && !above,\n ...(below ? { beyond: \"below\" as const } : {}),\n ...(above ? { beyond: \"above\" as const } : {}),\n span: spanOf(t),\n },\n consumed: 1,\n };\n }\n return null;\n}\n\nexport interface WindParsed {\n group: WindGroup;\n consumed: number;\n /** 越界发现(风向位/变化组端点 >360°):子项判缺测,由调用方落 value-out-of-range 告警 */\n rangeFindings: readonly { message: string; span: Span }[];\n /** 阵风位缺测(27010G//KT):组照常成立、gust 不设,由调用方落 missing-expected info */\n gustMissing?: boolean;\n}\n\n/** 风:33002MPS / VRB02KT / 31015G25KT / /////KT 缺测形态 + 260V050 变化组。 */\nexport function parseWindToken(t: Token, next: Token | undefined): WindParsed | \"missing\" | null {\n if (/^\\/{5}(KT|MPS|KMH)$/.test(t.text)) return \"missing\";\n // 部分缺测两形态(速度位 // / 阵风位 //,如 180//KT、27010G//KT)——此前整体落 unknown。\n // 超上限 P 前缀(P99KT/P49MPS,WMO 15.5.6 / AP-117 54 条):值存原码、beyond 标注超界端\n const m =\n /^(VRB|\\d{3}|\\/\\/\\/)(\\d{2,3}|P\\d{2}|\\/\\/\\/|\\/\\/)(?:G(\\d{2,3}|P\\d{2}|\\/\\/\\/|\\/\\/))?(KT|MPS|KMH)$/.exec(\n t.text,\n );\n if (m === null) return null;\n const span = spanOf(t);\n const dirRaw = m[1] ?? \"\";\n const speedRaw = m[2] ?? \"\";\n const unitRaw = (m[4] ?? \"kt\").toLowerCase();\n if (!isSpeedUnit(unitRaw)) return null;\n if (dirRaw === \"///\" || speedRaw === \"///\" || speedRaw === \"//\") return \"missing\";\n const variable = dirRaw === \"VRB\";\n const gustRaw = m[3];\n const speedBeyond = speedRaw.startsWith(\"P\") ? (\"above\" as const) : undefined;\n const gustBeyond =\n gustRaw !== undefined && gustRaw.startsWith(\"P\") ? (\"above\" as const) : undefined;\n const rangeFindings: { message: string; span: Span }[] = [];\n // 风向位 0–360(正北可编 360、静风 000 编 0):越界 = 值不可信 → 子项级判缺测(direction=null),\n // 风组其余子项(风速等)照常保留——两级建模:组内子项缺测 = 值字段 | null\n let direction: number | null = variable ? null : Number.parseInt(dirRaw, 10);\n if (!variable && direction !== null && direction > 360) {\n rangeFindings.push({\n message: `风向越界(${dirRaw},须 0–360)——风向位判缺测,原码经 span 回溯`,\n span,\n });\n direction = null;\n }\n let consumed = 1;\n let variation: WindGroup[\"variation\"];\n if (next !== undefined && /^\\d{3}V\\d{3}$/.test(next.text)) {\n const parts = next.text.split(\"V\");\n const min = parts[0];\n const max = parts[1];\n if (min !== undefined && max !== undefined) {\n const minDeg = Number.parseInt(min, 10);\n const maxDeg = Number.parseInt(max, 10);\n if (minDeg > 360 || maxDeg > 360) {\n // 变化组端点同为风向数值(0–360):任一越界即整组不可信 → 变化组判缺测(组已消费,不留假值)\n rangeFindings.push({\n message: `风向变化组端点越界(${next.text},须 0–360)——变化组判缺测,原码经 span 回溯`,\n span: spanOf(next),\n });\n } else {\n variation = { min: minDeg, max: maxDeg, span: spanOf(next) };\n }\n consumed = 2;\n }\n }\n // 阵风位缺测双形态:G 后 // (两位斜杠——2 字符场的逐字符惯例)与 /// (三斜杠磨损多一位,\n // 同按缺测建模——任何规范都无三斜杠形态,最合理的来源是 G// 的传输磨损;2026-09-14 补建模:\n // 此前 /// 走 parseInt 产 NaN 零告警入 IR,穿透缺测路由/gustMissing/值域门三道防线)\n const gustMissing = gustRaw === \"//\" || gustRaw === \"///\";\n const group: WindGroup = {\n variable,\n direction,\n speed: {\n value: Number.parseInt(speedRaw.startsWith(\"P\") ? speedRaw.slice(1) : speedRaw, 10),\n unit: unitRaw,\n span,\n ...(speedBeyond !== undefined ? { beyond: speedBeyond } : {}),\n },\n gust:\n gustRaw !== undefined && !gustMissing\n ? {\n value: Number.parseInt(gustRaw.startsWith(\"P\") ? gustRaw.slice(1) : gustRaw, 10),\n unit: unitRaw,\n span,\n ...(gustBeyond !== undefined ? { beyond: gustBeyond } : {}),\n }\n : undefined,\n variation,\n };\n return { group, consumed, rangeFindings, ...(gustMissing ? { gustMissing: true } : {}) };\n}\n\n/**\n * Temperature/dewpoint group shape: always dd/dd (M = negative; // on either side = that side missing).\n * 温度/露点组形态:恒为 dd/dd(M = 负;任一侧 // = 该侧缺测)——两位是形态定义本身,不是惯例:\n * WMO 电码表每个符号字母严格对应一位数字(T' 十位 / T 个位,负值加 M),官方示例含补零(01/M12、\n * 00/M00),任何规范版本无一位数形态。两侧 \\d{1,2} 曾让裸分数 token(VIS 词丢失的 1/2、2/1——\n * 上游脏输入)被误判为温露组:降序分数捏造假值且完全静默,升序触发误导性温露倒挂告警\n * (2026-09-14 复评收紧);不匹配即落 unknown-token 出声,原码经 span 回溯。\n * The regex requires the `/` separator — a bare \"//\" is the weather missing group (see the body loop) and must not be swallowed here.\n * 正则必须有 `/` 分隔——裸 `//` 是天气缺测组(见正文循环),不得被本组吞掉。\n * Exported for direct shape assertions in regression tests (red line: \"//\" must not match; \"1/2\"/\"2/1\" must not match either).\n * 导出供回归测试直接对形态断言(红线:对 \"//\" 与裸分数均不得匹配)。\n */\nexport const TEMP_DEW_PATTERN = /^(M?\\d{2}|\\/\\/)\\/(M?\\d{2}|\\/\\/)$/;\n\n/** 温度/露点组:恒为 dd/dd 形态(M = 负;// = 缺测 → null,调用方补告警)。 */\nexport function parseTempDewToken(t: Token): {\n temperature: TemperatureReading | null;\n dewpoint: TemperatureReading | null;\n span: Span;\n} | null {\n const read = (raw: string | undefined): TemperatureReading | null => {\n // undefined = 第二组整体缺失(FMH-1 12.6.10 露点缺测形态 24/);\"//\" = 显式缺测——\n // 两者同为 null,但 missing-expected 文案由调用方按形态区分\n if (raw === undefined || raw === \"//\") return null;\n const n = raw.startsWith(\"M\") ? -Number.parseInt(raw.slice(1), 10) : Number.parseInt(raw, 10);\n // −0 归一(M00 → 0):负零序列化变形(JSON 出 -0),消费方 Object.is 判别出边角差异\n const celsius = n === 0 ? 0 : n;\n return { celsius, span: spanOf(t) };\n };\n const m = TEMP_DEW_PATTERN.exec(t.text);\n if (m === null) {\n // FMH-1 12.6.10 露点缺测形态「24/」(第二组整体省略,同恒两位)——裸 // 与 /// 仍不得匹配\n const trailing = /^(M?\\d{2})\\/$/.exec(t.text);\n if (trailing === null) return null;\n return { temperature: read(trailing[1]), dewpoint: null, span: spanOf(t) };\n }\n return { temperature: read(m[1]), dewpoint: read(m[2]), span: spanOf(t) };\n}\n\nfunction beyondRangeOf(flag: string | undefined): \"above\" | \"below\" | undefined {\n if (flag === \"P\") return \"above\";\n if (flag === \"M\") return \"below\";\n return undefined;\n}\n\n/** RVR 组:R07R/1800V2200FT / R36/0500V0800D / P·M 超界 / 斜杠趋势(R13/3500FT/N、R07/P6000FT/U)。\n * R/SNOCLO 与 R10L/SNOCLO 属跑道状态语义(15.13.6.1),由 parseRunwayStateToken 收口。 */\nexport function parseRvrToken(t: Token): RunwayVisualRange | null {\n // 趋势后缀双形态:无斜杠(0500V0800D,WMO)与斜杠(3500FT/N,FAA/加式——FT 单位标记后带 /D //N //U)\n const m = /^R(\\d{2}[RLC]?)\\/(P|M)?(\\d{4})(?:V(P|M)?(\\d{4}))?(FT)?(?:\\/([DNU])|([DNU]))?$/.exec(\n t.text,\n );\n if (m === null) return null;\n const minRaw = m[3] ?? \"0\";\n const maxRaw = m[5];\n const trendRaw = m[7] ?? m[8];\n return {\n runway: m[1] ?? \"\",\n value: maxRaw === undefined ? Number.parseInt(minRaw, 10) : undefined,\n min: maxRaw !== undefined ? Number.parseInt(minRaw, 10) : undefined,\n max: maxRaw !== undefined ? Number.parseInt(maxRaw, 10) : undefined,\n beyondRange: beyondRangeOf(m[2] ?? m[4]),\n unit: m[6] === \"FT\" ? \"ft\" : \"m\",\n trend:\n trendRaw === \"U\"\n ? \"up\"\n : trendRaw === \"D\"\n ? \"down\"\n : trendRaw === \"N\"\n ? \"no-change\"\n : undefined,\n span: spanOf(t),\n };\n}\n\n/** 摩擦两位电码(15.13.6.1 表 0366)解码:01–90 → 摩擦系数 0.01–0.90;91–95 → 制动作用五档;\n * 99 → unreliable;// 或 96–98(电码表未用)→ 两字段皆 undefined(原码经 span 回溯)。 */\nfunction parseFrictionCode(\n code: string | undefined,\n): Pick<RunwayStateGroup, \"frictionCoefficient\" | \"brakingAction\"> {\n if (code === undefined || !/^\\d{2}$/.test(code)) return {};\n const f = Number.parseInt(code, 10);\n if (f <= 90) return { frictionCoefficient: f / 100 };\n if (f >= 91 && f <= 95)\n return {\n brakingAction: ([\"poor\", \"medium-poor\", \"medium\", \"medium-good\", \"good\"] as const)[f - 91],\n };\n if (f === 99) return { brakingAction: \"unreliable\" };\n return {};\n}\n\n/** 跑道状态组三形态(WMO 15.13.6):①六位状态电码(R21/490160:沉积/覆盖/深度/摩擦,位缺测 /);\n * ②CLRD 清除家族(R07L/CLRD// 标准、CLRD62 俄区、CLRD/// 非标容忍);③SNOCLO 关闭(R/SNOCLO 全机场、R10L/SNOCLO 逐跑道)。\n * 覆盖位非法电码(表 0519 外数字)不静默留值:该位判缺测 + findings 交调用方落 invalid-format 告警。 */\nexport function parseRunwayStateToken(\n t: Token,\n): { group: RunwayStateGroup; findings: readonly { message: string; span: Span }[] } | null {\n // ③ SNOCLO(15.13.6.1):跑道因雪/冰/清雪不可用\n const snoclo = /^R(\\d{2}[RLC]?)?\\/SNOCLO$/.exec(t.text);\n if (snoclo !== null) {\n return {\n group: { runway: snoclo[1] ?? \"\", closed: true, cleared: false, span: spanOf(t) },\n findings: [],\n };\n }\n // ② CLRD 家族\n const clrd = /^R(\\d{2}[RLC]?)\\/CLRD(\\d{2}|\\/\\/|\\/\\/\\/)?$/.exec(t.text);\n if (clrd !== null) {\n return {\n group: {\n runway: clrd[1] ?? \"\",\n cleared: true,\n ...parseFrictionCode(clrd[2]),\n span: spanOf(t),\n },\n findings: [],\n };\n }\n // ① 六位状态电码:沉积物类型 1 位 + 覆盖范围 1 位 + 深度 2 位 + 摩擦 2 位(各可 / 缺报)\n const num = /^R(\\d{2}[RLC]?)\\/(\\d|\\/)(\\d|\\/)(\\d{2}|\\/\\/)(\\d{2}|\\/\\/)$/.exec(t.text);\n if (num === null) return null;\n const depthCode = num[4] ?? \"\";\n // 深度解码(15.13.6.1 表 1079):00–90 = 毫米(00 即 <1mm 记 0);91 未用判缺测;92–98 = 10–40cm 段记下限;\n // 99 = 跑道不可用(同 SNOCLO 语义 → closed,深度不落值)\n const depthNum = /^\\d{2}$/.test(depthCode) ? Number.parseInt(depthCode, 10) : null;\n const depth =\n depthNum === null\n ? null\n : depthNum <= 90\n ? depthNum\n : depthNum === 91\n ? null\n : depthNum === 99\n ? null\n : (depthNum - 90) * 50;\n // 覆盖位电码合法性(15.13.6.1 表 0519):表内仅 1/2/5/9 与 /——表外数字(0/3/4/6/7/8)为非法电码,\n // 按三态纪律判缺测(null)+ invalid-format 告警,绝不把表外值留在 IR(tgftp 实弹 R24/000062 命中位 2 的 0)\n const coverageCode = num[3] ?? \"/\";\n const coverageIllegal = coverageCode !== \"/\" && !\"1259\".includes(coverageCode);\n const findings: { message: string; span: Span }[] = coverageIllegal\n ? [\n {\n message: `跑道状态覆盖位电码非法(${t.text} 覆盖位 ${coverageCode}——WMO 表 0519 仅用 1/2/5/9 与 /)——该位判缺测,原码经 span 回溯`,\n span: spanOf(t),\n },\n ]\n : [];\n return {\n group: {\n runway: num[1] ?? \"\",\n closed: depthNum === 99 || undefined,\n cleared: false,\n deposit: num[2] === \"/\" ? null : Number(num[2]),\n coverage: coverageCode === \"/\" || coverageIllegal ? null : Number(coverageCode),\n depth,\n ...parseFrictionCode(num[5]),\n span: spanOf(t),\n },\n findings,\n };\n}\n\n// ———————————————— 组级纯函数(v0.2 批 0.1 抽取) ————————————————\n// parse() 内的组级解析闭包/内联块迁出为模块级纯函数:游标位置(tokens+pos)与共享累加器\n// (warnings/remarks)一律显式传参,不再闭包捕获 parse() 局部状态——目的:TAF 解析器\n// (parseTaf,后续批次)复用组级逻辑。本迁移为零行为变化重构:解析语义、告警文案与\n// 顺序、span、消费 token 数保持原样(全量语料回放快照锁定)。\n\n/** 重复组告警(原 parse() 内 dupGroupWarning 闭包):前值后值原文都进 message——\n * last-wins 会覆盖 IR 里的前值 span,前值唯一可回溯通道就是这条告警。 */\nexport function warnDuplicateGroup(\n raw: string,\n warnings: ParseWarning[],\n label: string,\n prevSpan: Span | undefined,\n newSpan: Span | undefined,\n): void {\n const prevText =\n prevSpan === undefined ? `(原${label})` : raw.slice(prevSpan.start, prevSpan.end);\n const newText = newSpan === undefined ? label : raw.slice(newSpan.start, newSpan.end);\n warnings.push({\n code: \"duplicate-group\",\n severity: \"warning\",\n message: `重复${label}(前值 ${prevText},后值 ${newText})——报文只应有一组${label},以末组为准,前值经原文回溯`,\n span: newSpan,\n });\n}\n\n/** 气压组落位(原 parse() 内 setAltimeter 闭包):末组为准(last-wins),重复组追加告警不静默;\n * 返回新的(altimeter, altimeterSeen)二元组交调用方落位。 */\nexport function applyAltimeterReading(\n altimeter: AltimeterReading | undefined,\n altimeterSeen: boolean,\n reading: AltimeterReading,\n raw: string,\n warnings: ParseWarning[],\n): { altimeter: AltimeterReading | undefined; altimeterSeen: boolean } {\n if (altimeterSeen) {\n warnDuplicateGroup(raw, warnings, \"气压组\", altimeter?.span, reading.span);\n }\n return { altimeter: reading, altimeterSeen: true };\n}\n\n/** QNH 组解析结果:ok = 可信读数;out-of-range = 值不可信(5 位数或物理范围外,\n * Q10054 家族脏值),由调用方判缺测 + value-out-of-range 告警;null = 非 Q 组形态。 */\nexport type AltimeterTokenResult =\n | { readonly kind: \"ok\"; readonly reading: AltimeterReading }\n | { readonly kind: \"out-of-range\"; readonly message: string; readonly span: Span };\n\n/** Q(hPa)组:5 位数 QNH 与物理范围外值 = 脏值(Q10054 家族)——绝不静默留假值。 */\nexport function parseQnhToken(t: Token): AltimeterTokenResult | null {\n const qM = /^Q(\\d{4,5})$/.exec(t.text);\n if (qM === null) return null;\n const digits = qM[1] ?? \"\";\n const hpa = Number.parseInt(digits, 10);\n if (digits.length === 5 || hpa < QNH_HPA_MIN || hpa > QNH_HPA_MAX) {\n return {\n kind: \"out-of-range\",\n message: `QNH 超出可信范围(${t.text},合理区间 ${QNH_HPA_MIN}–${QNH_HPA_MAX} hPa)——值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n };\n }\n return { kind: \"ok\", reading: { value: hpa, unit: \"hPa\", span: spanOf(t) } };\n}\n\n/** A(inHg,隐含小数点)组:物理范围外值判缺测,同 QNH 纪律。 */\nexport function parseAltimeterAToken(t: Token): AltimeterTokenResult | null {\n const aM = /^A(\\d{4})$/.exec(t.text);\n if (aM === null) return null;\n const inhg = Number.parseInt(aM[1] ?? \"0\", 10) / 100;\n if (inhg < ALT_INHG_MIN || inhg > ALT_INHG_MAX) {\n return {\n kind: \"out-of-range\",\n message: `高度表设定超出可信范围(${t.text} → ${inhg} inHg,合理区间 ${ALT_INHG_MIN}–${ALT_INHG_MAX})——值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n };\n }\n return { kind: \"ok\", reading: { value: inhg, unit: \"inHg\", span: spanOf(t) } };\n}\n\n/** 风组落位与值域校验(原正文循环风组分支内联块,非缺测路径):NaN 终结防线、三位数\n * 模板上限门(>199 判缺测)、风向/变化组端点越界 findings、阵风缺测 info、VRB 与变化组\n * 并存 cross-check——告警顺序与原分支逐条一致(rangeFindings → gustMissing → VRB 变化组)。 */\nexport function validateWindGroup(\n t: Token,\n windParsed: WindParsed,\n raw: string,\n): { wind: Observed<WindGroup>; warnings: ParseWarning[] } {\n const wg = windParsed.group;\n // 风速模板上限:三位数(≤199,WMO 15.5.6「100 单位以上以精确位数替代两位电码」注至\n // 199;FMH-1 12.6.5.a「two or three digits」)——超 199 即非规范报文(270250KT 构造探针),\n // 按 QNH 超界同款纪律整组不可信判缺测,绝不静默留假值。P 前缀超上限形态(P99KT)合法\n // NaN 终结防线(终结断言,预期不可达):任何数值入口产 NaN 即整组不可信判缺测。\n // NaN 恰是现有防线的双重盲区——值域门 >199 对 NaN 恒 false、JSON.stringify 消 NaN 为\n // null、fuzz 不变量(2026-09-14 实弹 G/// 之前)无有限性检查——故独立成支并配哨兵不变量\n if (\n !Number.isFinite(wg.speed.value) ||\n (wg.gust !== undefined && !Number.isFinite(wg.gust.value))\n ) {\n return {\n wind: { kind: \"missing\", span: spanOf(t) },\n warnings: [\n {\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: `风组解码出非有限值(${t.text})——值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n },\n ],\n };\n }\n if (wg.speed.value > 199 || (wg.gust?.value ?? 0) > 199) {\n return {\n wind: { kind: \"missing\", span: spanOf(t) },\n warnings: [\n {\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: `风速超出编码范围(${t.text},三位数模板上限 199 ${wg.speed.unit})——值不可信判缺测,原码经 span 回溯`,\n span: spanOf(t),\n },\n ],\n };\n }\n const found: ParseWarning[] = [];\n for (const finding of windParsed.rangeFindings) {\n found.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: finding.message,\n span: finding.span,\n });\n }\n if (windParsed.gustMissing === true) {\n found.push({\n code: \"missing-expected\",\n severity: \"info\",\n // 缺测电码双形态(G// 标准两位 / G/// 磨损三斜杠)直出原文\n message: `阵风位缺测(${t.text}——G 后斜杠位缺测,组照常成立)`,\n span: spanOf(t),\n });\n }\n if (wg.variable && wg.variation !== undefined) {\n const vs = wg.variation.span;\n found.push({\n code: \"cross-check-conflict\",\n severity: \"info\",\n message: `静风变向(VRB)与风向变化组(${\n vs === undefined ? \"\" : raw.slice(vs.start, vs.end)\n })并存——VRB 本义方向不定,变化组冗余,报文自洽性存疑`,\n span: vs,\n });\n }\n return { wind: { kind: \"value\", value: wg, span: spanOf(t) }, warnings: found };\n}\n\n/** 能见度组落位(原正文循环能见度分支内联块):方向组挂靠/脱离主导、缺测不顶替在场值、\n * 零分母 invalid 判缺测、ok 落值——返回新的(visibility, directionalAsPrimary)二元组。 */\nexport function applyVisibilityToken(\n t: Token,\n visParsed: VisibilityResult,\n state: { visibility: Observed<VisibilityGroup> | undefined; directionalAsPrimary: boolean },\n raw: string,\n warnings: ParseWarning[],\n): { visibility: Observed<VisibilityGroup> | undefined; directionalAsPrimary: boolean } {\n const visibility = state.visibility;\n const directionalAsPrimary = state.directionalAsPrimary;\n // 最低能见度方向组(WMO 15.6.2):挂到已存主导能见度(非重复组不出 duplicate 告警);\n // 脱离主导能见度单独出现属非规范形态——按能见度收下 + info 出声。\n // directionalAsPrimary = 脱离主导的方向组被按主导收下(非规范状态,解析器局部标记)——\n // 其后再来的方向组是「连挂第二枚」(1200NW 1200NE),同样出声不静默\n //(2026-09-14 独立复评补齐:此前连挂时第二枚静默覆写第一枚)\n if (visParsed.kind === \"directional\") {\n if (visibility?.kind === \"value\") {\n if (visibility.value.minimum !== undefined || directionalAsPrimary) {\n warnDuplicateGroup(\n raw,\n warnings,\n \"最低能见度方向组\",\n visibility.value.minimum?.span,\n spanOf(t),\n );\n }\n return {\n visibility: {\n kind: \"value\",\n value: {\n ...visibility.value,\n minimum: {\n value: visParsed.group.value,\n direction: visParsed.group.direction,\n span: visParsed.group.span,\n },\n },\n span: visibility.span,\n },\n directionalAsPrimary,\n };\n }\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `最低能见度方向组脱离主导能见度(${t.text})——按能见度收下`,\n span: spanOf(t),\n });\n return {\n visibility: {\n kind: \"value\",\n value: {\n value: visParsed.group.value,\n unit: \"m\",\n exact: true,\n span: visParsed.group.span,\n },\n },\n directionalAsPrimary: true,\n };\n }\n if (visibility !== undefined) {\n warnDuplicateGroup(raw, warnings, \"能见度组\", visibility.span, spanOf(t));\n }\n if (visParsed.kind === \"missing\") {\n // 已有能见度组时:缺测电码不顶替在场值(duplicate-group 已出声)——\n // 后位 ////(温露位畸形/错位落点)按 last-wins 把 9999 冲成 missing 是纯信息损失\n //(2026-09-15 五角色评测批;WMO 正常报文能见度缺测只出现在能见度槽位,此形态仅见于错位/磨损报文)\n if (visibility === undefined) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n // 缺测电码两形态直出原文(//// 米制 / ////SM 英里制——加拿大自动站,RMK VIS MISG 佐证)\n message: `能见度组缺测(${t.text},无法观测能见度)`,\n span: spanOf(t),\n });\n return { visibility: { kind: \"missing\", span: spanOf(t) }, directionalAsPrimary: false };\n }\n return { visibility, directionalAsPrimary: false };\n }\n if (visParsed.kind === \"invalid\") {\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: visParsed.message,\n span: visParsed.span,\n });\n return {\n visibility: { kind: \"missing\", span: visParsed.span },\n directionalAsPrimary: false,\n };\n }\n return {\n visibility: { kind: \"value\", value: visParsed.group, span: visParsed.group.span },\n directionalAsPrimary: false,\n };\n}\n\n/** 温度读数物理极值门(世界极值 ±裕量,与 QNH 世界极值门同款纪律)。 */\nconst tempOutOfRange = (r: TemperatureReading | null): boolean =>\n r !== null && (r.celsius < TEMP_C_MIN || r.celsius > TEMP_C_MAX);\n\n/** 温度/露点组落位(原正文循环温露分支内联块):重复组告警、全缺测不顶替在场值、\n * 物理极值门(双侧同超界合并一条告警)、显式缺测 info、温露倒挂 cross-check——\n * 返回新的(temperature, dewpoint)二元组。 */\nexport function applyTempDewToken(\n t: Token,\n tempParsed: {\n temperature: TemperatureReading | null;\n dewpoint: TemperatureReading | null;\n span: Span;\n },\n state: { temperature: TemperatureReading | undefined; dewpoint: TemperatureReading | undefined },\n raw: string,\n warnings: ParseWarning[],\n): { temperature: TemperatureReading | undefined; dewpoint: TemperatureReading | undefined } {\n const temperature = state.temperature;\n const dewpoint = state.dewpoint;\n const dupTemp = temperature !== undefined || dewpoint !== undefined;\n if (dupTemp) {\n warnDuplicateGroup(\n raw,\n warnings,\n \"温度组\",\n temperature?.span ?? dewpoint?.span,\n tempParsed.span,\n );\n }\n // 已有温露组时:全缺测电码(/////)不顶替在场值(duplicate-group 已出声)——\n // 零信息量形态覆盖真实观测是纯信息损失;带部分值的形态(如 12//)照常 last-wins\n if (dupTemp && tempParsed.temperature === null && tempParsed.dewpoint === null) {\n return { temperature, dewpoint };\n }\n // 温度物理极值门(与 QNH 同款纪律):超可信范围判缺测 + value-out-of-range,\n // 绝不静默留假值;双侧同时超界合并为一条告警(M91/M95 不重复出声);\n // 显式缺测(//)另发 missing-expected,两告警互不替代\n const rawTemp = tempParsed.temperature;\n const rawDew = tempParsed.dewpoint;\n const outT = tempOutOfRange(rawTemp);\n const outD = tempOutOfRange(rawDew);\n if (outT || outD) {\n const single = outT ? rawTemp : rawDew;\n const span = outT && outD ? tempParsed.span : single?.span;\n const shown = span === undefined ? `${TEMP_C_MIN}` : raw.slice(span.start, span.end);\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: `温度超出可信范围(${shown},合理区间 ${TEMP_C_MIN}–${TEMP_C_MAX}°C)——值不可信判缺测,原码经 span 回溯`,\n span,\n });\n }\n const gatedTemperature = outT ? undefined : (rawTemp ?? undefined);\n const gatedDewpoint = outD ? undefined : (rawDew ?? undefined);\n if (rawTemp === null || rawDew === null) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n // 形态判别精确到正则(2026-09-14 独立复评收口:endsWith(\"/\") 会把 12// 的标准\n // 缺测与 12/// 的磨损形都误述为 24/ 形态)\n message: /^M?\\d{2}\\/$/.test(t.text)\n ? \"露点位缺测(24/ 形态,FMH-1 12.6.10)\"\n : \"温度/露点位缺测(//)\",\n span: tempParsed.span,\n });\n }\n // 交叉校验:露点不可能高于温度(相对湿度 >100% 物理不可能)——典型传感器故障形态。\n // 两组值照常保留(含 M 负值),矛盾交由告警呈现,绝不静默也不捏造\n if (\n gatedTemperature !== undefined &&\n gatedDewpoint !== undefined &&\n gatedTemperature.celsius < gatedDewpoint.celsius\n ) {\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `温度低于露点(${t.text})——物理不可能,疑似传感器故障`,\n span: tempParsed.span,\n });\n }\n return { temperature: gatedTemperature, dewpoint: gatedDewpoint };\n}\n\n/** 趋势段收口出声(原 parse() 内 trendCloseWarning 闭包):R 组收口(RVR/跑道状态不属趋势\n * 要素)沿用既有口径出声;其余非趋势组收口(温露/QNH/WS/TX/TN/RVRNO/无法认领 token 等)\n * 同样出声 info:该组交回正文循环认组(typed 语义无损恢复,冲突自然触发重复组告警),\n * 但趋势语境存疑须可观测——不静默。RMK/RMK 粘连与趋势指示组切换(含粘连形\n * BECMGAT0130——它本身就是趋势指示组,下一步由正文粘连分支认领)、以及规范报尾位 $\n * (FMH-1:$ 为整报最后一组,趋势段后随 $ 属规范位置)不出声(2026-09-14 独立复评补豁免)。 */\nexport function warnTrendClose(\n tokens: readonly Token[],\n pos: number,\n warnings: ParseWarning[],\n): void {\n const btTok = tokens[pos];\n const bt = btTok?.text;\n if (bt === undefined || btTok === undefined) return;\n if (TREND_KINDS.has(bt) || bt.startsWith(\"RMK\") || bt === \"$\") return;\n if (/^(BECMG|TEMPO)(AT|TL|FM)\\d{4}$/.test(bt)) return; // 粘连指示组:由正文粘连分支认领\n if (/^R(\\d{2}[RLC]?\\/|\\/SNOCLO$)/.test(bt)) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `趋势段收口于 R 组(${bt}——RVR/跑道状态不属趋势要素,按正文组处理,趋势语境存疑)`,\n span: spanOf(btTok),\n });\n return;\n }\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `趋势段收口于非趋势组(${bt}——不属趋势要素族,交回正文认组,趋势语境存疑)`,\n span: spanOf(btTok),\n });\n}\n\n/** 趋势段收组(原 parse() 内 collectTrendTokens 闭包):仅封闭清单内 token 收进 collected\n * (判据见 isTrendCollectible),其余留在收口位置交回正文循环——三处收集入口\n * (指示组/粘连/裸时段词)共用一份循环防漂移;返回收口位置。 */\nexport function collectTrendSegment(\n tokens: readonly Token[],\n pos: number,\n collected: Token[],\n): number {\n let idx = pos;\n for (;;) {\n const inner = tokens[idx];\n if (inner === undefined || !isTrendCollectible(inner, tokens[idx + 1])) break;\n collected.push(inner);\n idx += 1;\n }\n return idx;\n}\n\n/** 趋势段构造(三形态共用尾半段:标准指示组/粘连/裸时段词分支):要素结构化复用\n * structureTrendElements;NOSIG 不做要素结构化(原分支口径),elementsStart 为\n * 结构化起始下标(跳过已收下的指示组/时段词 token)。 */\nexport function buildTrendGroup(\n kind: TrendGroup[\"kind\"],\n period: TrendGroup[\"period\"],\n collected: readonly Token[],\n elementsStart: number,\n): TrendGroup {\n const elements = kind === \"nosig\" ? undefined : structureTrendElements(collected, elementsStart);\n return {\n kind,\n period,\n ...(elements !== undefined ? { elements } : {}),\n raw: collected.map((c) => c.text).join(\" \"),\n span: joinSpan(collected),\n };\n}\n\n/** 云层组元素构造(原正文循环云层分支内联块):云量/云高/云型缺测位告警随构造直出;\n * null = 非云层组形态。趋势段的云层构造为静默口径(structureTrendElements)——\n * 两处行为刻意不同(正文出声、趋势保真静默),不合并。 */\nexport function cloudLayerElementOf(t: Token, warnings: ParseWarning[]): CloudElement | null {\n const cloudM = CLOUD_LAYER_PATTERN.exec(t.text);\n if (cloudM === null) return null;\n const amountRaw = cloudM[1];\n const heightRaw = cloudM[2];\n const convectiveRaw = cloudM[3];\n const typeMissing = cloudM[4] !== undefined;\n const amountMissing = amountRaw === \"///\";\n const heightMissing = heightRaw === \"///\";\n if (heightMissing) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"云高缺测(///),不捏造基高\",\n span: spanOf(t),\n });\n }\n if (amountMissing) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"云量位缺测(///),探测到云但云量无法观测\",\n span: spanOf(t),\n });\n }\n if (typeMissing) {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"云型位缺测(///)\",\n span: spanOf(t),\n });\n }\n return {\n kind: \"layer\",\n amount: amountRaw !== undefined && isCloudAmount(amountRaw) ? amountRaw : null,\n heightFt: {\n value:\n heightRaw !== undefined && heightRaw !== \"///\"\n ? Number.parseInt(heightRaw, 10) * 100\n : null,\n span: spanOf(t),\n },\n convective:\n convectiveRaw !== undefined && isConvective(convectiveRaw) ? convectiveRaw : undefined,\n span: spanOf(t),\n };\n}\n\n/** VV(垂直能见度)元素构造(原正文循环 VV 分支内联块):缺测电码形态告警、合法数值组\n * (VV002 = 垂直能见度 200ft)零告警;null = 非 VV 组形态。 */\nexport function verticalVisibilityElementOf(\n t: Token,\n warnings: ParseWarning[],\n): CloudElement | null {\n const vvM = VV_PATTERN.exec(t.text);\n if (vvM === null) return null;\n const heightRaw = vvM[1];\n if (heightRaw === undefined || heightRaw === \"///\") {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message:\n heightRaw === \"///\"\n ? \"垂直能见度缺测(VV///,天空全遮蔽但垂直能见度不可测)\"\n : \"垂直能见度缺测(VV,兼容形态)\",\n span: spanOf(t),\n });\n }\n return {\n kind: \"vertical-visibility\",\n heightFt: {\n value:\n heightRaw === undefined || heightRaw === \"///\"\n ? null\n : Number.parseInt(heightRaw, 10) * 100,\n span: spanOf(t),\n },\n span: spanOf(t),\n };\n}\n\n/** 风切变组识别(原正文循环 WS 分支内联块,四形态:WS ALL RWY / WS RWY ALL /\n * WS RWY##[RLC] / WS R##[RLC]):返回识别出的跑道号(或全跑道旗标)、组 span 与消费\n * token 数;null = 非风切变组(正文循环继续后续分支)。多组累积(runways 连接、\n * span 首组至末组)由调用方合并。 */\nexport interface WindShearMatch {\n readonly runway: string | null;\n readonly all: boolean;\n readonly span: Span;\n readonly consumed: number;\n}\n\nexport function parseWindShearSequence(\n t: Token,\n tok1: Token | undefined,\n tok2: Token | undefined,\n): WindShearMatch | null {\n const designator = tok1 !== undefined ? /^RWY(\\d{2}[RLC]?)$/.exec(tok1.text) : null;\n const stdDesignator = tok1 !== undefined ? /^R(\\d{2}[RLC]?)$/.exec(tok1.text) : null;\n // 全跑道两形态:标准 WS ALL RWY 与词序倒置变体 WS RWY ALL\n const isAll =\n (tok1?.text === \"ALL\" && tok2?.text === \"RWY\") ||\n (tok1?.text === \"RWY\" && tok2?.text === \"ALL\");\n if (designator === null && stdDesignator === null && !isAll) return null;\n const endTok = isAll ? tok2 : tok1;\n const startSpan = spanOf(t);\n const endSpan = endTok !== undefined ? spanOf(endTok) : startSpan;\n return {\n runway:\n designator !== null\n ? (designator[1] ?? \"\")\n : stdDesignator !== null\n ? (stdDesignator[1] ?? \"\")\n : null,\n all: isAll,\n span: { start: startSpan.start, end: endSpan.end },\n consumed: isAll ? 3 : 2,\n };\n}\n\n/** RVRNO 落位(正文位,原正文循环 RVRNO 分支内联块):与 RVR 值组并存 = 矛盾形态出声、\n * 值组按跑道级明细保留;否则 rvr 显式缺测 + missing-expected;remarks 一律留痕 rvr-no。\n * 返回新的 rvr 值。 */\nexport function applyRvrNoBodyToken(\n t: Token,\n rvr: Observed<readonly RunwayVisualRange[]> | undefined,\n raw: string,\n warnings: ParseWarning[],\n remarks: RemarkGroup[],\n): Observed<readonly RunwayVisualRange[]> | undefined {\n let next = rvr;\n if (rvr?.kind === \"value\") {\n const prevText = rvr.span === undefined ? \"\" : raw.slice(rvr.span.start, rvr.span.end);\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"info\",\n message: `RVRNO(站级:应报而缺)与 RVR 值组并存(${prevText})——矛盾形态,值组按跑道级明细保留,RVRNO 经 remarks/raw 可回溯`,\n span: spanOf(t),\n });\n } else {\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"RVR 设备在但明示不可用(RVRNO)\",\n span: spanOf(t),\n });\n next = { kind: \"missing\", span: spanOf(t) };\n }\n remarks.push({ kind: \"rvr-no\", raw: t.text, span: spanOf(t) });\n return next;\n}\n\n/** 反向次序矛盾出声(RVRNO 在前、值组在后,原 RVR 值组分支内联块):可解读为传感器恢复,\n * 值组按明细保留——与正序矛盾并存同一文案口径(见 applyRvrNoBodyToken 注释)。 */\nexport function warnRvrNoThenValues(\n t: Token,\n prevSpan: Span | undefined,\n raw: string,\n warnings: ParseWarning[],\n): void {\n const prevText = prevSpan === undefined ? \"\" : raw.slice(prevSpan.start, prevSpan.end);\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"info\",\n message: `RVRNO(站级:应报而缺)与后随 RVR 值组并存(${prevText})——矛盾形态,值组按跑道级明细保留(可解读为传感器恢复),RVRNO 经 remarks/raw 可回溯`,\n span: spanOf(t),\n });\n}\n\n/** RVR 全斜杠缺测(R##/#### 标准 5 斜杠与磨损 4 斜杠形态,原正文循环内联块):判缺测 +\n * missing-expected(4 斜杠另附磨损 info);null = 非本组形态。\n * 依据:WMO 306 FM15 RVR 值位恒四位(VRVRVRVR),全斜杠即数值缺测(斜杠逐位填充的缺测惯例)。 */\nexport function applyRvrSlashToken(\n t: Token,\n warnings: ParseWarning[],\n): Observed<readonly RunwayVisualRange[]> | null {\n const rvrSlash = /^R\\d{2}[RLC]?(\\/{4,5})$/.exec(t.text);\n if (rvrSlash === null) return null;\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: `RVR 组缺测(${t.text}——跑道号在位、视程值位全斜杠)`,\n span: spanOf(t),\n });\n if ((rvrSlash[1] ?? \"\").length === 4) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `RVR 缺测段磨损(${t.text}——4 位斜杠对标准 5 位(分离符 + 四位值位),少一位;按缺测收下)`,\n span: spanOf(t),\n });\n }\n return { kind: \"missing\", span: spanOf(t) };\n}\n\n/** 当前天气三态收口(原正文循环后内联块):仅有实组时给值;RE-only 报文 weather 保持\n * undefined(组省略 ≠ 缺测);组级 span 首组至末组。 */\nexport function observedWeatherOf(\n weatherList: readonly WeatherGroup[],\n): Observed<readonly WeatherGroup[]> | undefined {\n if (weatherList.length === 0) return undefined;\n const first = weatherList[0];\n const last = weatherList[weatherList.length - 1];\n if (first !== undefined && last !== undefined) {\n return {\n kind: \"value\",\n value: [...weatherList],\n span:\n first.span !== undefined && last.span !== undefined\n ? { start: first.span.start, end: last.span.end }\n : undefined,\n };\n }\n return undefined;\n}\n\n/** CAVOK 交叉校验的正文状态快照(cavokCrossCheck 入参,批 0.1 显式化)。 */\nexport interface CavokCrossCheckState {\n readonly cavokSpan: Span | undefined;\n readonly visibility: Observed<VisibilityGroup> | undefined;\n readonly weatherList: readonly WeatherGroup[];\n readonly rvr: Observed<readonly RunwayVisualRange[]> | undefined;\n readonly cloudElements: readonly CloudElement[];\n}\n\n/** CAVOK 三面交叉校验(能见度/天气/云,原 parse() 内 cavokConflicts 闭包)。词位时对\n * 「前序」组校验;正文循环收口后对「后续」组再校验——CAVOK 让位发生在词位,其后再出现\n * 的矛盾组此前静默并存(CAVOK BKN012 形态)。判据词位/词后完全一致:确定矛盾才告警\n * (下界编码/真值天气/低云或对流云;缺测云高不判)。告警 span 统一指 CAVOK 词位\n * (既有契约:矛盾双方中「主张」所在)。 */\nexport function cavokCrossCheck(\n state: CavokCrossCheckState,\n whenLabel: string,\n raw: string,\n warnings: ParseWarning[],\n): void {\n const at = state.cavokSpan;\n const visibility = state.visibility;\n if (visibility?.kind === \"value\") {\n const g = visibility.value;\n const meters = g.unit === \"m\" ? g.value : g.value * 1609.344;\n const visRaw =\n visibility.span === undefined\n ? `${g.value} ${g.unit}`\n : raw.slice(visibility.span.start, visibility.span.end);\n const definitelyBelow =\n g.beyond === \"below\" ||\n (g.unit === \"sm\" && visRaw.startsWith(\"M\")) ||\n (g.exact && meters < 10_000);\n if (definitelyBelow) {\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `CAVOK 与${whenLabel}能见度组矛盾(${visRaw},CAVOK 语义要求 ≥10km)——让位照旧,报文自洽性存疑`,\n span: at,\n });\n }\n }\n if (state.weatherList.length > 0) {\n const wxRaw = state.weatherList\n .map(\n (g) =>\n `${g.proximity ? \"VC\" : \"\"}${g.intensity ?? \"\"}${g.descriptor ?? \"\"}${g.phenomena.join(\"\")}`,\n )\n .join(\" \");\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `CAVOK 与${whenLabel}天气组矛盾(${wxRaw},CAVOK 语义要求无重要天气)——让位照旧,报文自洽性存疑`,\n span: at,\n });\n }\n if (state.rvr !== undefined && state.rvr.kind === \"value\") {\n const rvrRaw =\n state.rvr.span === undefined ? \"\" : raw.slice(state.rvr.span.start, state.rvr.span.end);\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `CAVOK 与${whenLabel}RVR 组矛盾(${rvrRaw}——AP-117 第 140 条:CAVOK 代替能见度、跑道视程、现在天气和云)——让位照旧,报文自洽性存疑`,\n span: at,\n });\n }\n const cloudConflict = state.cloudElements.some((e) => {\n if (e.kind === \"layer\" && e.convective !== undefined) return true;\n const h = e.heightFt.value;\n return h !== null && h < 5_000;\n });\n if (cloudConflict) {\n const cloudRaw = state.cloudElements\n .map(\n (e) =>\n `${e.kind === \"layer\" ? (e.amount ?? \"///\") : \"VV\"}${\n e.heightFt.value === null\n ? \"///\"\n : String(Math.round(e.heightFt.value / 100)).padStart(3, \"0\")\n }${e.kind === \"layer\" ? (e.convective ?? \"\") : \"\"}`,\n )\n .join(\" \");\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `CAVOK 与${whenLabel}云组矛盾(${cloudRaw},CAVOK 语义要求 5000ft 以下无云且无 CB/TCU)——让位照旧,报文自洽性存疑`,\n span: at,\n });\n }\n}\n\n/** RMK 段整体(原 parse() 内 RMK while 循环迁出):认组粒度收下 FMH-1 附加信息与俄区\n * 国家组,未知 ≠ 错误(不进 warnings,收 'unknown' remark);RVRNO 在 RMK 位与正文位\n * 同口径(并存矛盾出声、值组明细保留)。游标(tokens+start)与累加器(remarks/warnings)\n * 显式传参;返回 rvr 终态与段末位置。 */\nexport function parseRemarkSegment(\n tokens: readonly Token[],\n start: number,\n raw: string,\n remarks: RemarkGroup[],\n warnings: ParseWarning[],\n rvrIn: Observed<readonly RunwayVisualRange[]> | undefined,\n): { rvr: Observed<readonly RunwayVisualRange[]> | undefined; next: number } {\n let rvr = rvrIn;\n let i = start;\n while (i < tokens.length) {\n const t = tokens[i];\n if (t === undefined) break;\n const text = t.text;\n const push = (remarkKind: RemarkKind, consumed = 1): void => {\n const slice = tokens.slice(i, i + consumed);\n remarks.push({\n kind: remarkKind,\n raw: slice.map((c) => c.text).join(\" \"),\n span: joinSpan(slice),\n });\n i += consumed;\n };\n\n if (text === \"AO1\" || text === \"AO2\" || text === \"A01\" || text === \"A02\") {\n // A01/A02 数字形态:tgftp 通路实弹 268 站次(与 FMH-1 字母形态 AO1/AO2 并存)\n push(\"auto-type\");\n continue;\n }\n if (/^SLP(\\d{3}|NO)$/.test(text)) {\n push(\"sea-level-pressure\");\n continue;\n }\n if (/^T[01]\\d{7}(T[01]\\d{7})?$/.test(text) || /^T[01]\\d{3}$/.test(text)) {\n push(\"precise-temperature\");\n continue;\n }\n if (/^P\\d{4}$/.test(text)) {\n push(\"precip-1h\");\n continue;\n }\n if (/^[67](?:\\d{4}|\\/{4})$/.test(text)) {\n // 6/7 组降水窗口(3/24h):量值 4 位;//// = 窗口降水缺测(FMH-1 实弹 6////,tgftp 语料 17 处)\n push(\"precip-window\");\n continue;\n }\n if (/^4\\/\\d{3}$/.test(text)) {\n push(\"snow-depth\");\n continue;\n }\n if (/^I[136]\\d{3}$/.test(text)) {\n // FMH-1 冰积组 = I + 间隔位(1/3/6h) + 3 位量值(I1001 → 1 小时 0.01 英寸);\n // 旧正则 \\d{4} 多吞一位致 I1001 形态全数落 unknown(2026-09-12 复评命中)\n push(\"ice-accretion\");\n continue;\n }\n if (/^5[0-8]\\d{3}$/.test(text)) {\n push(\"pressure-tendency\");\n continue;\n }\n // 24h 温度极值组:现行 FMH-1 为 9 位(4 + 最高[符号位 3 位] + 最低[符号位 3 位],\n // 如 401280089 = 最高 +12.8 / 最低 +8.9;符号位 1 = 负),IEM/tgftp 实弹全数 9 位;\n // 8 位旧形态兼容保留\n if (/^4(?:[01]\\d{3}[01]\\d{3}|\\d{7})$/.test(text)) {\n push(\"temp-extrema-24h\");\n continue;\n }\n if (/^[12]\\d{4}$/.test(text)) {\n push(\"temp-extrema-6h\");\n continue;\n }\n if (text === \"PK\" && tokens[i + 1]?.text === \"WND\") {\n push(\"peak-wind\", 3);\n continue;\n }\n if (text === \"WSHFT\" && tokens[i + 1] !== undefined) {\n push(\"wind-shift\", 2);\n continue;\n }\n if (text === \"PRESRR\" || text === \"PRESFR\") {\n push(\"pressure-change\");\n continue;\n }\n if (text === \"VISNO\") {\n push(\"vis-no\");\n continue;\n }\n if (text === \"TSNO\") {\n // TSNO(美网高频):雷暴传感器不工作——雷暴探测不可用(≠无雷暴),认组不再 unknown\n push(\"thunderstorm-sensor\");\n continue;\n }\n if (text === \"RVRNO\") {\n // RMK 位与正文位同口径(方案一):并存矛盾出声、值组明细保留(终态不改),\n // RVRNO 自身留痕 remarks——见正文 RVRNO 位注释\n if (rvr?.kind === \"value\") {\n const prevText = rvr.span === undefined ? \"\" : raw.slice(rvr.span.start, rvr.span.end);\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"info\",\n message: `RVRNO(站级:应报而缺)与 RVR 值组并存(${prevText})——矛盾形态,值组按跑道级明细保留,RVRNO 经 remarks/raw 可回溯`,\n span: spanOf(t),\n });\n } else {\n rvr = { kind: \"missing\", span: spanOf(t) };\n }\n push(\"rvr-no\");\n continue;\n }\n if (text === \"SFC\" && tokens[i + 1]?.text === \"VIS\") {\n // 分数尾 token(SFC VIS 2 1/2)一并吸收,不再散落 unknown(FMH-1 12.7.1.f)\n const frac = /^\\d\\/\\d(SM)?$/.test(tokens[i + 3]?.text ?? \"\") ? 1 : 0;\n push(\"surface-visibility\", 3 + frac);\n continue;\n }\n if (text === \"TWR\" && tokens[i + 1]?.text === \"VIS\") {\n // TWR VIS 塔台能见度(FMH-1 12.7.1.f,值可为分数对)\n const frac = /^\\d\\/\\d(SM)?$/.test(tokens[i + 3]?.text ?? \"\") ? 1 : 0;\n push(\"twr-visibility\", 3 + frac);\n continue;\n }\n const visDirNext = tokens[i + 1]?.text;\n const RMK_VIS_DIR = /^(N|NE|E|SE|S|SW|W|NW)$/;\n const RMK_VIS_VAL = /^[MP]?\\d+(\\/\\d+)?(SM)?$/;\n if (\n text === \"VIS\" &&\n visDirNext !== undefined &&\n RMK_VIS_DIR.test(visDirNext) &&\n tokens[i + 2] !== undefined\n ) {\n // 分区能见度(方位在前)VIS <方位> <量值>〔<方位> <量值>…〕(FMH-1 12.7.1.h,量值可为整数+分数对)\n // 多扇区实弹(PANC:VIS E 10 SE 10 S 10)整段并组保真,后续方位对不再散落 unknown\n const frac = /^\\d\\/\\d(SM)?$/.test(tokens[i + 3]?.text ?? \"\") ? 1 : 0;\n let consumed = 3 + frac;\n for (let j = i + consumed; ;) {\n const dir = tokens[j]?.text;\n if (dir === undefined || !RMK_VIS_DIR.test(dir)) break;\n const val = tokens[j + 1]?.text;\n if (val === undefined || !RMK_VIS_VAL.test(val)) break;\n const pair = /^\\d+$/.test(val) && /^\\d\\/\\d(SM)?$/.test(tokens[j + 2]?.text ?? \"\") ? 3 : 2;\n consumed += pair;\n j += pair;\n }\n push(\"sectoral-visibility\", consumed);\n continue;\n }\n if (text === \"VIS\" && visDirNext !== undefined && RMK_VIS_VAL.test(visDirNext)) {\n // 分区能见度(量值在前)VIS <量值>〔<方位>〕(FMH-1 12.7.1.h;PANC 实弹:VIS 1 1/2 N)\n let consumed = 2; // VIS + 量值\n if (/^\\d+$/.test(visDirNext) && /^\\d\\/\\d(SM)?$/.test(tokens[i + 2]?.text ?? \"\"))\n consumed += 1; // 整数+分数对\n if (\n tokens[i + consumed]?.text !== undefined &&\n RMK_VIS_DIR.test(tokens[i + consumed]?.text ?? \"\")\n )\n consumed += 1;\n push(\"sectoral-visibility\", consumed);\n continue;\n }\n if (/^CIGNO$/.test(text)) {\n // 云高计不可用(FMH-1 12.7.1.p 族,与 VISNO/TSNO/RVRNO 同族口径)\n push(\"cig-not-available\");\n continue;\n }\n const cigNext = tokens[i + 1]?.text;\n if (text === \"CIG\" && cigNext !== undefined) {\n // CIG hhhVhhh 波动 / CIG hhh LOC / CIG hhh(FMH-1 12.7.1.p)\n const nxt = cigNext;\n if (/^\\d{3}V\\d{3}$/.test(nxt)) {\n push(\"ceiling-variation\", 2);\n continue;\n }\n if (/^\\d{3}$/.test(nxt)) {\n if (tokens[i + 2]?.text === \"LOC\") {\n push(\"ceiling-at-location\", 3);\n continue;\n }\n push(\"ceiling\", 2);\n continue;\n }\n }\n if (text === \"PNO\") {\n // 降水传感器不可用(FMH-1 12.7.2.g 族)\n push(\"precip-not-available\");\n continue;\n }\n if (text === \"FZRANO\") {\n push(\"fzr-not-available\");\n continue;\n }\n if (text === \"CHINO\") {\n push(\"chino\");\n continue;\n }\n if (/^8\\/[0-9X/]{3}$/.test(text)) {\n // 8/CCC 云型组(低/中/高云型电码 0–9,X 未知,/ 缺测;FMH-1 12.7.2.b)\n push(\"cloud-type-8group\");\n continue;\n }\n if (/^933\\d{3}$/.test(text)) {\n // 933RRR 积雪水当量(英寸百分之一;FMH-1 12.7.2.a)\n push(\"snow-water-equivalent\");\n continue;\n }\n if (text === \"FUNNEL\" && tokens[i + 1]?.text === \"CLOUD\") {\n push(\"phenomenon-began-ended\", 2);\n continue;\n }\n if (text === \"LTG\") {\n // 多 token 聚合:LTG 后按词表(LTG_TAIL_VOCAB)连收 + 词表词后夹带至多一个 1–2 位\n // 数字距离 token(FMH-1 ch.12:自动站雷电视频距离为海里裸数字,如 LTG ALQDS CG 12 OHD——\n // 数字须跟在词表词后,LTG 直连裸数字无出处)。聚合仍被词表外 token 截断;\n // 数字吸收以「前一吸收 token ∈ 词表」为前置且至多一个——防无关散落数字被静默吞进\n // lightning remark(2026-09-14 收紧:实现此前与注释声明不符,语料 229 处 LTG 零裸数字)\n let consumed = 1;\n let prevInVocab = false;\n let digitsAbsorbed = 0;\n for (;;) {\n const nextTok = tokens[i + consumed];\n if (nextTok === undefined) break;\n if (LTG_TAIL_VOCAB.has(nextTok.text)) {\n consumed += 1;\n prevInVocab = true;\n continue;\n }\n if (prevInVocab && digitsAbsorbed === 0 && /^\\d{1,2}$/.test(nextTok.text)) {\n consumed += 1;\n digitsAbsorbed += 1;\n prevInVocab = false;\n continue;\n }\n break;\n }\n push(\"lightning\", Math.min(consumed, tokens.length - i));\n continue;\n }\n if (text === \"SNINCR\" && /^\\d+\\/\\d+$/.test(tokens[i + 1]?.text ?? \"\")) {\n // SNINCR <时增>/<总量>(英寸,两 token 一组)——积雪增率,2026-09-12 复评补建模\n push(\"snow-increase\", 2);\n continue;\n }\n if (text === \"VIS\" && VIS_V_RANGE.test(tokens[i + 1]?.text ?? \"\")) {\n // 变化能见度 VIS 1/2V2(IR RemarkKind 'variable-visibility' 声明补实现)\n push(\"variable-visibility\", 2);\n continue;\n }\n // began/ended 家族(FZRAB43E50 合并形态 / RAB42·RAE50 拆分形态 / B43 裸起止)——\n // 边界收紧(2026-09-12):词身须能按天气组切解(FZRA/RA/TS…),俄区 QBB(云底高度,\n // 国家组)等非天气字母组不再被 [A-Z]{2,8} 前缀误吞进本类\n const beganMerged = /^([A-Z]{2,8})B\\d{2,4}(?:E\\d{2,4})?$/.exec(text);\n const beganSplit = /^([A-Z]{2})[BE]\\d{2,4}$/.exec(text);\n const beganBodyOk = (m: RegExpExecArray | null): boolean =>\n m !== null && splitWeatherToken(m[1] ?? \"\") !== null;\n if (beganBodyOk(beganMerged) || beganBodyOk(beganSplit) || /^[BE]\\d{2,4}$/.test(text)) {\n push(\"phenomenon-began-ended\");\n continue;\n }\n if (/^QBB\\d{3}$/.test(text)) {\n // QBB(俄区国家组):云底高度(米,3 位直读,与正文云组互为印证)\n push(\"cloud-base-height\");\n continue;\n }\n if (/^QFE\\d{3,4}(\\/\\d{3,4})?$/.test(text)) {\n // QFE(俄区国家组):场面气压。值语义(查证 2026-09-12):三位数 = 毫米汞柱(QFE749 = 749 mmHg,\n // 俄区惯例报 mmHg 场压);双段 QFE746/0995 = 746 mmHg 与 995 hPa 双单位(760 mmHg = 1013.25 hPa\n // 标准大气换算互证,metar-taf.com 俄区实报 RMK R08L/QFE741/0988 同族);四位数直读 hPa(QFE1003)。\n // 认组粒度收下不解码数值(RemarkGroup 无值槽;单位歧义风险由「不解码」规避),原码经 span 可取\n push(\"aerodrome-pressure\");\n continue;\n }\n if (text === \"$\") {\n push(\"maintenance\");\n continue;\n }\n push(\"unknown\");\n }\n return { rvr, next: i };\n}\n","/**\n * @metweave/parser — TAF 判据校验层(/validate,v0.2 补齐批:其他全部修复」指令)。\n * The TAF rule-validation layer:条文判据在解析层五处被显式移交至此(C2/C3/C5/B7 注释),本层收口。\n *\n * 判据清单(来源=学习线补全清单 + taf-tac §3,条款号核自 WMO 306 FM 51):\n * - C2 VRB 阈值两源(§51.3):WMO 风速 <1.5 m/s 才可编 VRB / CAAC <2 m/s 或雷暴——机器只判风速侧,\n * 「无法预报单一风向/雷暴」逃逸条款不由电码承载,明示不可判;\n * - C3 阵风阈值(§51.3):阵风超出平均 ≥5 m/s(10 kt)才合法编 Gfmfm——严格不等式按条文(D 节纪律);\n * - C5 天气白名单双层(§51.5.1):国际白名单为基(冻降水/中大降水含阵雨/尘沙暴/雷暴/冻雾/吹尘沙雪/飑/漏斗云),\n * 中国扩展层(弱档 -、BR、HZ——与 parser C5 注记同一判式)按 standard 取合法(caac)或违例(wmo);\n * - C7 三层选取(§51.6.1.4):第 1 组任意量、第 2 组 >2 oktas(SCT 起)、第 3 组起 >4 oktas(BKN 起)——\n * 仅全重报语境(基况段/FM 段)适用;BECMG/TEMPO 组内所列为局部清单不适用(B5);CB/TCU 缺报侧不可判;\n * - B7 间歇判据为空集:发作每次 <1h、累计 <半窗不由电码承载,机器不可判(判卷场景靠出题纪律,明示)。\n */\nimport { MetarParseError } from \"@metweave/core\";\nimport type { CloudCondition, Span, TafReport, WeatherGroup, WindGroup } from \"@metweave/core\";\n\n/** 判据阈值源:wmo(缺省)=国际白名单/VRB<1.5;caac=中国民航(中国扩展层天气合法/VRB<2) */\nexport type TafValidateStandard = \"wmo\" | \"caac\";\n\nexport interface TafValidateOptions {\n readonly standard?: TafValidateStandard;\n}\n\n/** 违例码(稳定契约,只增不改):C2/C3/C5/C7 四判据各一 */\nexport type TafViolationCode =\n | \"vrb-over-threshold\" /** C2:VRB 风速 ≥ 阈值(wmo 1.5 / caac 2 m/s),不应编 VRB */\n | \"gust-below-threshold\" /** C3:阵风超出平均 <5 m/s(10 kt),G 组不合法 */\n | \"wx-outside-list\" /** C5:天气组不在预报白名单(国际层外;中国扩展层在 wmo 标准下违例) */\n | \"cloud-layer-selection\"; /** C7:三层选取违例(第 2 组 FEW / 第 3 组起 FEW·SCT) */\n\nexport interface TafViolation {\n readonly code: TafViolationCode;\n readonly severity: \"warning\";\n readonly message: string;\n /** 违例所在段(「基况段」/「FM 0100」/「TEMPO 0609/0612」——变化组以变化词+窗口/时刻指位) */\n readonly where: string;\n readonly span?: Span;\n}\n\nconst MPS_OF = { mps: 1, kt: 0.514444, kmh: 1 / 3.6 } as const;\nconst mpsOf = (value: number, unit: keyof typeof MPS_OF): number => value * MPS_OF[unit];\n\n/** 国际白名单内的中/大降水现象码(弱档 - 一律出层;DZ 毛毛雨不在 TAF 白名单——教材 §3.5) */\nconst INTL_PRECIP = new Set([\"RA\", \"SN\", \"SG\", \"PL\", \"GS\", \"GR\"]);\n/** 独立成组即白名单的现象码:尘暴/沙暴/飑/漏斗云(任意强度含 +) */\nconst INTL_STANDALONE = new Set([\"DS\", \"SS\", \"SQ\", \"FC\"]);\n\n/**\n * C5 国际白名单判定(§51.5.1 教材口径):冻降水(FZRA/FZDZ)/ 雷暴族(TS 起头)/ 中大降水(含 SH 阵雨族,\n * 强度非弱档)/ 尘暴 DS / 沙暴 SS / 冻雾 FZFG / 吹尘沙雪(BLDU/BLSA/BLSN)/ 飑 SQ / 漏斗云 FC。\n * VC 邻近(METAR 语汇)一律出层。\n */\nconst inIntlWhitelist = (g: WeatherGroup): boolean => {\n if (g.proximity) return false;\n const codes = g.phenomena as readonly string[];\n const has = (p: string): boolean => codes.includes(p);\n\n if (g.descriptor === \"TS\") return true;\n if (g.descriptor === \"FZ\" && (has(\"RA\") || has(\"DZ\") || has(\"FG\"))) return true;\n if (g.descriptor === \"BL\" && (has(\"DU\") || has(\"SA\") || has(\"SN\"))) return true;\n if (codes.some((p) => INTL_STANDALONE.has(p))) return true;\n if (codes.length > 0 && codes.every((p) => INTL_PRECIP.has(p))) return g.intensity !== \"-\";\n return false;\n};\n\n/** 中国扩展层(与 parser C5 注记同一判式,单一真相):弱档 - 或 BR/HZ */\nconst isCnExtension = (g: WeatherGroup): boolean => {\n const codes = g.phenomena as readonly string[];\n return g.intensity === \"-\" || codes.includes(\"BR\") || codes.includes(\"HZ\");\n};\n\nconst weatherCodeOf = (g: WeatherGroup): string => {\n const i = g.intensity ?? \"\";\n const d = g.descriptor ?? \"\";\n return `${g.proximity ? \"VC\" : \"\"}${i}${d}${g.phenomena.join(\"\")}`;\n};\n\nconst UNIT_WORD = { mps: \"MPS\", kt: \"KT\", kmh: \"KMH\" } as const;\n\n/** 风组两判据(C2/C3):VRB 阈值与阵风增量(各自单位换算米/秒后比较) */\nconst windViolations = (\n wind: WindGroup,\n where: string,\n standard: TafValidateStandard,\n): TafViolation[] => {\n const out: TafViolation[] = [];\n const threshold = standard === \"caac\" ? 2 : 1.5;\n if (wind.variable && mpsOf(wind.speed.value, wind.speed.unit) >= threshold) {\n out.push({\n code: \"vrb-over-threshold\",\n severity: \"warning\",\n where,\n span: wind.speed.span,\n message: `VRB 风速 ${wind.speed.value}${UNIT_WORD[wind.speed.unit]} ≥ ${threshold} m/s(${standard === \"caac\" ? \"CAAC\" : \"WMO\"} 口径)——不应编 VRB(C2;「无法预报单一风向/雷暴」逃逸条款不由电码承载,本判不覆盖)`,\n });\n }\n const gust = wind.gust;\n if (\n gust !== undefined &&\n mpsOf(gust.value, gust.unit) - mpsOf(wind.speed.value, wind.speed.unit) < 5\n ) {\n out.push({\n code: \"gust-below-threshold\",\n severity: \"warning\",\n where,\n span: gust.span,\n message: `阵风超出平均不足 5 m/s(10 kt)——G 组不合法(C3,严格 ≥5 m/s 才可编)`,\n });\n }\n return out;\n};\n\n/** C7 三层选取(§51.6.1.4,仅全重报语境):第 2 组须 >2 oktas、第 3 组起须 >4 oktas(CB/TCU 缺报侧不可判) */\nconst cloudViolations = (clouds: CloudCondition | undefined, where: string): TafViolation[] => {\n if (clouds === undefined) return [];\n const layers = clouds.elements.filter((e) => e.kind === \"layer\");\n const out: TafViolation[] = [];\n layers.forEach((layer, idx) => {\n if (layer.amount === null) return;\n const illegal =\n idx === 1 && layer.amount === \"FEW\"\n ? \"第 2 组须 >2 oktas(SCT 起步)\"\n : idx >= 2 && (layer.amount === \"FEW\" || layer.amount === \"SCT\")\n ? \"第 3 组起须 >4 oktas(BKN 起步)\"\n : undefined;\n if (illegal !== undefined) {\n out.push({\n code: \"cloud-layer-selection\",\n severity: \"warning\",\n where,\n span: layer.span,\n message: `三层选取违例:第 ${idx + 1} 组编 ${layer.amount}——${illegal}(C7/§51.6.1.4;CB/TCU「未入前三必补」的缺报侧不由电码承载)`,\n });\n }\n });\n return out;\n};\n\n/**\n * 校验一份已解析的 TAF:返回全部条文违例(空数组=通过)。\n * 判据与边界见模块头注(C2/C3/C5/C7;B7 机器判据空集)。不修改报告、不抛错——\n * 严判入口是 parseTaf({mode:\"strict\"}),本函数供质控/判卷侧按需取用。\n */\nexport function validateTaf(\n report: TafReport,\n options: TafValidateOptions = {},\n): readonly TafViolation[] {\n const standard = options.standard ?? \"wmo\";\n const out: TafViolation[] = [];\n // 风组三态解包(Observed<WindGroup>):缺测/未知无判据意义,只有在场值参与判卷\n const baseWind = report.wind?.kind === \"value\" ? report.wind.value : undefined;\n if (baseWind !== undefined) out.push(...windViolations(baseWind, \"基况段\", standard));\n out.push(...cloudViolations(report.clouds, \"基况段\"));\n\n const wxCheck = (g: WeatherGroup, where: string): void => {\n if (inIntlWhitelist(g)) return;\n if (standard === \"caac\" && isCnExtension(g)) return;\n const layer = isCnExtension(g) ? \"中国扩展层,非 WMO 白名单\" : \"国际白名单外\";\n out.push({\n code: \"wx-outside-list\",\n severity: \"warning\",\n where,\n span: g.span,\n message: `天气组 ${weatherCodeOf(g)} 不在 TAF 预报白名单(${layer};C5/§51.5.1——caac 标准下中国扩展层合法)`,\n });\n };\n if (report.weather?.kind === \"value\") for (const g of report.weather.value) wxCheck(g, \"基况段\");\n\n for (const change of report.changes) {\n const where = change.window !== undefined ? `${change.kind} ${change.window.raw}` : change.kind;\n const e = change.elements;\n if (e === undefined) continue;\n if (e.wind !== undefined) out.push(...windViolations(e.wind, where, standard));\n if (change.kind === \"FM\") out.push(...cloudViolations(e.clouds, where)); // C7 仅全重报语境(B4)\n for (const g of e.weather) wxCheck(g, where);\n }\n return out;\n}\n\n/**\n * strict 门(parseTaf mode:\"strict\" 的判卷侧):任一条文违例(validateTaf)或 warning 级解析告警\n * (重复组/概率越界/组合违例等)即整体不通过——聚合为稳定错误码 strict-violation。\n * info 级(方言收编/缺测注记/中国扩展注记)不拦:真实世界被接受的形态。\n */\nexport function strictGate(\n report: TafReport,\n raw: string,\n standard: TafValidateStandard = \"wmo\",\n): void {\n const violations = validateTaf(report, { standard }).map((v) => `${v.where}:${v.message}`);\n const warnings = report.warnings.filter((w) => w.severity === \"warning\").map((w) => w.message);\n const all = [...violations, ...warnings];\n if (all.length === 0) return;\n throw new MetarParseError(\n \"strict-violation\",\n raw,\n `strict 校验未通过(${all.length} 项)——${all.slice(0, 3).join(\";\")}${all.length > 3 ? \"……\" : \"\"}`,\n );\n}\n","/**\n * @metweave/parser — TAF 解析层(FM 51,v0.2 批 1 骨架)。\n * The TAF parsing layer (FM 51): header + validity skeleton.\n *\n * 批 1 范围:电头 token 序列(清单 A4——TAF 词可省(剥词源同理)、AMD/COR 不写死槽位、\n * COR 时组后位)、发布时组 ddHHMMZ、有效期组 ddHH/ddHH(止时 24 = 午夜合法特例)、\n * 传输层终止符 `=` 剥离(A1)、NIL/CNL 位置判别(A2)、AAA/CCA 族仅容错(A3)、\n * 基况段四要素 + CAVOK(复用 groups 共享件,组装语义沿 METAR)。\n * 变化组与气温组(批 2/3.4)界后 token 暂一律 unknown-token 出声(不静默纪律)。\n * strict 模式(v0.2 补齐批):tolerant 解析后经 strictGate(validate.ts 四判据 + warning 级告警聚合)。\n * 纪律与 METAR 侧同源:不静默、span 保真、错误码只增不改(ParseError 别名自 v0.2 起)。\n */\nimport { MetarParseError } from \"@metweave/core\";\nimport type {\n CloudCondition,\n CloudElement,\n ParseWarning,\n TafChangeAt,\n TafChangeGroup,\n TafChangeKind,\n TafChangeWindow,\n TafTemperatureGroup,\n TrendElements,\n SkyClearCode,\n Span,\n TafParseOptions,\n TafReport,\n TafValidityGroup,\n WeatherGroup,\n} from \"@metweave/core\";\nimport {\n applyVisibilityToken,\n cloudLayerElementOf,\n compactNode,\n isSkyClear,\n observedWeatherOf,\n parseVisibilityToken,\n parseWindToken,\n spanOf,\n structureTrendElements,\n tokenize,\n tryWeatherToken,\n validateWindGroup,\n verticalVisibilityElementOf,\n warnDuplicateGroup,\n type Token,\n} from \"./groups\";\nimport { strictGate } from \"./validate\";\n\nconst STATION_PATTERN = /^[A-Z0-9]{4}$/;\nconst ISSUE_TIME_PATTERN = /^(\\d{2})(\\d{2})(\\d{2})Z$/;\nconst VALIDITY_PATTERN = /^(\\d{2})(\\d{2})\\/(\\d{2})(\\d{2})$/;\n\n/** 基况段右界(批 2/3.4 接管前的停靠点):变化组 FM####/BECMG/TEMPO/PROB30|40 与气温组 TX/TN */\nconst isChangeBoundary = (text: string): boolean =>\n /^FM\\d{4}$/.test(text) ||\n text === \"BECMG\" ||\n text === \"TEMPO\" ||\n /^PROB\\d{2}$/.test(text) ||\n text.startsWith(\"TX\") ||\n text.startsWith(\"TN\");\n\n/**\n * 有效期时长(小时)=有效期组差值(清单 B1★):`(止日−起日)×24 + (止时−起时)`,\n * **只看有效期组,禁用发布钟点**(钟点 03/09/15/21Z 与版本解耦、代际切换——taf-tac §3.1 v1.2)。\n * 止时 24(B2 午夜特例)自然进算术;起日 > 止日(B3 跨月回绕)按所跨月长度回绕天数——\n * 有效期组不含月信息,缺省按 31 天(保守缺省),带月锚的精确回绕由展开层(B3)负责。\n * 注意:wrapDaysInMonth 须 ≥ 起日(2 月锚 + 31 日组属不自洽输入,算术结果为负由调用方甄别)。\n */\nexport function tafDurationHours(validity: TafValidityGroup, wrapDaysInMonth = 31): number {\n const dayDiff =\n validity.endDay >= validity.startDay\n ? validity.endDay - validity.startDay\n : validity.endDay + wrapDaysInMonth - validity.startDay;\n return dayDiff * 24 + (validity.endHour - validity.startHour);\n}\n\n/**\n * Parse one TAF report (tolerant mode) into the TAF IR — the forecast-side entry.\n * 解析单条 TAF 报文(tolerant)为预报侧 IR。\n * 整体失败(输入非字符串/无站名/无发布时组/时组或有效期越界/未实现模式)抛 MetarParseError\n * (code 稳定契约,与 parse 同族;v0.2 起别名 ParseError)。\n */\nexport function parseTaf(raw: string, options?: TafParseOptions): TafReport {\n if (typeof raw !== \"string\") {\n throw new MetarParseError(\n \"invalid-input\",\n raw,\n `parseTaf 需要一个 TAF 报文字符串,收到 ${raw === null ? \"null\" : typeof raw}`,\n );\n }\n const compact = options?.spans === false;\n const compactIfEnabled = <T>(node: T): T => (compact ? compactNode(node) : node);\n // strict 门(v0.2 补齐批):tolerant 产物先过判据闸(validateTaf 四判据 + warning 级告警),\n // 违例聚合抛 strict-violation(info 级方言/缺测注记不拦);通过再按 spans 选项紧凑化\n const finish = (node: TafReport): TafReport => {\n if (options?.mode === \"strict\") {\n strictGate(node, raw, options.validateStandard ?? \"wmo\");\n }\n return compactIfEnabled(node);\n };\n\n // —— 传输层终止符(A1★):中国站/AFTN 通道报尾带 `=`、tgftp 与 aviationweather 通道不带——\n // 传输层惯例而非报文结构,剥离后不进 IR(span 只到末组电码;report.raw 仍原文保真)。\n // 只剥报尾(含贴末组 `6000=` 与独立 `=` 两种真实形态);中串 `=` 属传输磨损而非终止符,不剥。\n const body = raw.replace(/[=\\s]+$/, \"\");\n const tokens = tokenize(body);\n const warnings: ParseWarning[] = [];\n let i = 0;\n const peek = (ahead = 0): Token | undefined => tokens[i + ahead];\n\n let amended = false;\n let corrected = false;\n\n // —— 电头(A4):TAF 类型词可省;AMD/COR 在站名前不写死相对序(WMO/ICAO 与美式槽位并存)\n if (peek()?.text === \"TAF\") i += 1;\n for (let guard = 0; guard < 4; guard++) {\n const t = peek();\n if (t === undefined) break;\n if (t.text === \"AMD\") {\n if (amended) {\n warnings.push({\n code: \"duplicate-group\",\n severity: \"warning\",\n message: \"电头 AMD 重复出现——首枚已置修订位,重复枚出声不静默\",\n span: spanOf(t),\n });\n }\n amended = true;\n i += 1;\n } else if (t.text === \"COR\") {\n if (corrected) {\n warnings.push({\n code: \"duplicate-group\",\n severity: \"warning\",\n message: \"电头 COR 重复出现——首枚已置更正位,重复枚出声不静默\",\n span: spanOf(t),\n });\n }\n corrected = true;\n i += 1;\n } else break;\n }\n\n const stTok = peek();\n if (stTok === undefined || !STATION_PATTERN.test(stTok.text)) {\n throw new MetarParseError(\n \"missing-station\",\n raw,\n `无法识别站名组——输入不是 TAF 报文(${stTok?.text ?? \"空输入\"})`,\n );\n }\n const station: string = stTok.text;\n i += 1;\n\n // —— A2★ NIL(其一):站名后直接 NIL(实测无时组形态 `TAF ZSAM NIL=`,教材 §2)=缺报。\n // 最小形态与 METAR 侧 NIL 同语义:无有效期、无正文;其后零期待,多余 token 出声不静默\n if (peek()?.text === \"NIL\") {\n i += 1;\n collectTailAsUnknown(tokens, i, warnings);\n return finish({\n kind: \"taf\" as const,\n raw,\n station,\n nil: true,\n flags: { amended, corrected },\n cavok: false,\n changes: [],\n temperatures: [],\n remarks: [],\n warnings,\n });\n }\n\n const tmTok = peek();\n const tm = tmTok !== undefined ? ISSUE_TIME_PATTERN.exec(tmTok.text) : null;\n if (tmTok === undefined || tm === null) {\n throw new MetarParseError(\n \"missing-time\",\n raw,\n `无法识别发布时组——输入不是完整的 TAF 报文(${tmTok?.text ?? \"时组缺失\"})`,\n );\n }\n const day = Number(tm[1]);\n const hour = Number(tm[2]);\n const minute = Number(tm[3]);\n if (day < 1 || day > 31 || hour > 23 || minute > 59) {\n throw new MetarParseError(\n \"invalid-time\",\n raw,\n `发布时组数值越界(${tmTok.text})——日 01–31 / 时 00–23 / 分 00–59`,\n );\n }\n const issueTime = { day, hour, minute };\n i += 1;\n\n // —— A3★ AAA/CCA 族仅容错(AP-117 第三十条自有形态:修订加注 AAA/AAB、更正加注 CCA/CCB,\n // 出现在发布时组后如 `160000Z AAA`)。主解析路径不支持——824 万条三语料实测 0 出现\n // (2026-09-14 精读核对已入档,公开通路走 ICAO 惯例 TAF AMD / 时组后 COR)——\n // 消费放行不报错,按族置位(A 族→amended、C 族→corrected)+ 出声(非主路径形态须可观测)\n for (let guard = 0; guard < 2; guard++) {\n const annotation = peek();\n if (annotation === undefined || !/^(AAA|AAB|CCA|CCB)$/.test(annotation.text)) break;\n if (annotation.text.startsWith(\"A\")) amended = true;\n else corrected = true;\n i += 1;\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `AP-117 加注形态(${annotation.text} 于发布时组后——主路径为 TAF AMD/时组后 COR,条文自有形态已消费并按族置位)`,\n span: spanOf(annotation),\n });\n }\n\n // COR 时组后位(A4 序列第二槽位:中国 AFTN/ICAO 惯例;美式 COR 在类型词位已在上方消费)\n const corAfterTime = peek();\n if (corAfterTime !== undefined && corAfterTime.text === \"COR\") {\n if (corrected) {\n warnings.push({\n code: \"duplicate-group\",\n severity: \"warning\",\n message: \"COR 更正位重复出现(类型词位已置)——重复枚出声不静默\",\n span: spanOf(corAfterTime),\n });\n }\n corrected = true;\n i += 1;\n }\n\n // —— 有效期组 ddHH/ddHH\n const vTok = peek();\n // —— A2★ NIL(其二):带时组形态的 NIL 占**有效期组位**=缺报(同上最小形态,时组凭据保留)\n if (vTok?.text === \"NIL\") {\n i += 1;\n collectTailAsUnknown(tokens, i, warnings);\n return finish({\n kind: \"taf\" as const,\n raw,\n station,\n issueTime,\n nil: true,\n flags: { amended, corrected },\n cavok: false,\n changes: [],\n temperatures: [],\n remarks: [],\n warnings,\n });\n }\n const vStd = vTok !== undefined ? VALIDITY_PATTERN.exec(vTok.text) : null;\n // 无斜杠方言形态 dddddd(ogimet 实证 ZWWW 160024=16 日 00→24 同日窗;312 条抽样 1 例):\n // 日起止同日、起止时各两位——tolerant 收下 + invalid-format 出声(非 WMO 标准形)\n let dialectValidity = false;\n let gv: readonly (string | undefined)[] | null = vStd;\n if (gv === null && vTok !== undefined) {\n const d6 = /^(\\d{2})(\\d{2})(\\d{2})$/.exec(vTok.text);\n if (d6 !== null) {\n gv = [d6[0], d6[1], d6[2], d6[1], d6[3]];\n dialectValidity = true;\n }\n }\n if (vTok === undefined || gv === null) {\n throw new MetarParseError(\n \"missing-validity\",\n raw,\n `无法识别有效期组——TAF 发布时组后须为 ddHH/ddHH(NIL 缺报除外)(${vTok?.text ?? \"组缺失\"})`,\n );\n }\n const startDay = Number(gv[1]);\n const startHour = Number(gv[2]);\n const endDay = Number(gv[3]);\n const endHour = Number(gv[4]);\n if (\n startDay < 1 ||\n startDay > 31 ||\n startHour > 23 ||\n endDay < 1 ||\n endDay > 31 ||\n endHour > 24\n ) {\n throw new MetarParseError(\n \"invalid-validity\",\n raw,\n `有效期组数值越界(${vTok.text})——日 01–31 / 起时 00–23 / 止时 00–24(24=午夜合法特例)`,\n );\n }\n const validity: TafValidityGroup = {\n startDay,\n startHour,\n endDay,\n endHour,\n raw: vTok.text,\n span: spanOf(vTok),\n };\n if (dialectValidity) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `有效期无斜杠方言形态(${vTok.text}=同日起止)——已按 dddd/24 语义收下(非 WMO 标准形)`,\n span: spanOf(vTok),\n });\n }\n i += 1;\n\n // —— A2★ CNL:占**风组位**(有效期之后)=预报取消——有效期保留(发布与覆盖窗信息不丢),\n // 正文到此截断;其后零期待,多余 token 出声。CNL 出现在有效期位属结构违规 → missing-validity\n if (peek()?.text === \"CNL\") {\n i += 1;\n collectTailAsUnknown(tokens, i, warnings);\n return finish({\n kind: \"taf\" as const,\n raw,\n station,\n issueTime,\n validity,\n cancelled: true,\n flags: { amended, corrected },\n cavok: false,\n changes: [],\n temperatures: [],\n remarks: [],\n warnings,\n });\n }\n\n // —— 基况段(1.5):有效期后、首个变化组/气温组前——风/能见度/天气/云(含 NSC 晴空词族)\n // 四要素 + CAVOK。组装语义沿 METAR 侧(重复组 last-wins 出声、缺测不顶替在场值、\n // 三态 Observed、span 保真);TAF 无 RVR/温露对/QNH/RMK/NOSIG(教材 §1 电码格式)——\n // 此类组落入 unknown-token 出声。变化组/气温组(FM####/BECMG/TEMPO/PROB/TX/TN)属批 2/3.4:\n // 停在界上,其后暂一律 unknown-token。\n let wind: TafReport[\"wind\"];\n let visibility: TafReport[\"visibility\"];\n let weather: TafReport[\"weather\"];\n const weatherList: WeatherGroup[] = [];\n let directionalAsPrimary = false;\n const cloudElements: CloudElement[] = [];\n let clearCode: { code: SkyClearCode; span: Span } | undefined;\n let cavok = false;\n let cavokSpan: Span | undefined;\n\n for (; i < tokens.length;) {\n const t = tokens[i];\n if (t === undefined || isChangeBoundary(t.text)) break;\n const text = t.text;\n\n if (text === \"CAVOK\") {\n // CAVOK 三关让位契约同 METAR(vis/weather/clouds 让位为省略态,词位以 cavokSpan 标记);\n // 前序矛盾交叉校验(cavokCrossCheck)为 METAR 三态快照工具,TAF 侧语义待批 2 变化组接入后统一\n cavok = true;\n cavokSpan = spanOf(t);\n visibility = undefined;\n directionalAsPrimary = false;\n weather = undefined;\n weatherList.length = 0;\n cloudElements.length = 0;\n clearCode = undefined;\n i += 1;\n continue;\n }\n\n const windParsed = parseWindToken(t, tokens[i + 1]);\n if (windParsed !== null) {\n if (wind !== undefined) warnDuplicateGroup(raw, warnings, \"风组\", wind.span, spanOf(t));\n if (windParsed === \"missing\") {\n // 缺测电码不顶替在场值(同 METAR:零信息量缺测按 last-wins 覆盖真实值是纯信息损失)\n if (wind === undefined) {\n wind = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: `风组缺测(${t.text})`,\n span: spanOf(t),\n });\n }\n i += 1;\n } else {\n const applied = validateWindGroup(t, windParsed, raw);\n wind = applied.wind;\n warnings.push(...applied.warnings);\n i += windParsed.consumed;\n }\n continue;\n }\n\n const visParsed = parseVisibilityToken(t, tokens[i + 1]);\n if (visParsed !== null) {\n const applied = applyVisibilityToken(\n t,\n visParsed,\n { visibility, directionalAsPrimary },\n raw,\n warnings,\n );\n visibility = applied.visibility;\n directionalAsPrimary = applied.directionalAsPrimary;\n i += visParsed.consumed;\n continue;\n }\n\n const weatherParsed = tryWeatherToken(t, weatherList, []);\n if (weatherParsed !== false) {\n if (weatherParsed.outOfOrder) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `天气组语序不合电码表(${text}:描述符须先于现象)——已按切解结果收下`,\n span: spanOf(t),\n });\n }\n if (weatherParsed.signWithVc) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `强度符与 VC 邻近指示并存(${text}——强度符不与 VC 同组)——已按切解结果收下`,\n span: spanOf(t),\n });\n }\n i += 1;\n continue;\n }\n\n if (text === \"//\") {\n weather = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"天气组缺测(//,无法观测天气)\",\n span: spanOf(t),\n });\n i += 1;\n continue;\n }\n\n const cloudElem = cloudLayerElementOf(t, warnings);\n if (cloudElem !== null) {\n cloudElements.push(cloudElem);\n i += 1;\n continue;\n }\n const vvElem = verticalVisibilityElementOf(t, warnings);\n if (vvElem !== null) {\n cloudElements.push(vvElem);\n i += 1;\n continue;\n }\n if (isSkyClear(text)) {\n clearCode = { code: text, span: spanOf(t) };\n cloudElements.length = 0;\n i += 1;\n continue;\n }\n\n warnings.push({\n code: \"unknown-token\",\n severity: \"info\",\n message: `TAF 基况段未识别组(${text})——TAF 无此组位(RVR/温露对/QNH/RMK 属 METAR 语汇),保留原文`,\n span: spanOf(t),\n });\n i += 1;\n }\n\n // —— 变化组序列(2.2):FM/BECMG/TEMPO/PROB 结构化(B4/B5 token 层 + B8 组合规则 + B9 短窗)——\n // 语义边界:解析层只收「组内所列要素」(TrendElements,与 METAR 趋势段同构);\n // 未列要素继承/回溯、云例外、过渡带、间歇双态属展开器(2.3),解析层不越权代判\n const changes: TafChangeGroup[] = [];\n const temperatures: TafTemperatureGroup[] = [];\n while (i < tokens.length) {\n const t = tokens[i];\n if (t === undefined) break;\n const text = t.text;\n\n const txTn = /^(TX|TN)(M?\\d{2})\\/(?:(\\d{2})(\\d{2})|(\\d{2}))Z$/.exec(text);\n if (txTn !== null) {\n // C6★ 气温组:TX/TN 前缀 token、M 负值、1–4 组交错无固定序(跨基况/变化组分布照收)\n temperatures.push({\n extremum: txTn[1] === \"TX\" ? \"max\" : \"min\",\n celsius: Number(txTn[2]?.replace(\"M\", \"-\")),\n ...(txTn[3] !== undefined\n ? { at: { day: Number(txTn[3]), hour: Number(txTn[4]) } }\n : { at: { hour: Number(txTn[5]) } }),\n raw: text,\n span: spanOf(t),\n });\n if (temperatures.length > 4) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `气温组超 WMO 上限 4 组(第 ${temperatures.length} 组 ${text})——照收不丢弃,超出属编报违规(清单 C6)`,\n span: spanOf(t),\n });\n }\n i += 1;\n continue;\n }\n\n const fm = /^FM(\\d{2})(\\d{2})$/.exec(text);\n const prob = /^PROB(\\d{2})$/.exec(text);\n if (fm === null && prob === null && text !== \"BECMG\" && text !== \"TEMPO\") {\n warnings.push({\n code: \"unknown-token\",\n severity: \"info\",\n message: `TAF 变化组段未识别组(${text})`,\n span: spanOf(t),\n });\n i += 1;\n continue;\n }\n\n const startTok = t;\n i += 1;\n\n if (fm !== null) {\n // FM 硬时刻(B4):GGgg 到分钟;日归属由展开层在有效期语境内锚定\n const at: TafChangeAt = {\n hour: Number(fm[1]),\n minute: Number(fm[2]),\n raw: text,\n span: spanOf(startTok),\n };\n const [elements, next] = collectChangeElements(tokens, i);\n changes.push({\n kind: \"FM\",\n at,\n ...(elements !== undefined ? { elements } : {}),\n ...groupExtent(raw, tokens, startTok, next),\n });\n i = next;\n continue;\n }\n\n let kind: TafChangeKind;\n let probability: 30 | 40 | undefined;\n let withTempo = false;\n if (prob !== null) {\n kind = \"PROB\";\n const p = Number(prob[1]);\n if (p === 30 || p === 40) probability = p;\n else {\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `PROB 概率越界(${text}——C2C2 须为 30 或 40,清单 B8):概率位省略,组照常解析`,\n span: spanOf(startTok),\n });\n }\n const nx = tokens[i];\n if (nx?.text === \"TEMPO\") {\n withTempo = true;\n i += 1;\n } else if (nx?.text === \"BECMG\" || /^FM\\d{4}$/.test(nx?.text ?? \"\")) {\n // B8 违例:PROB 只可独立/连 TEMPO,禁与 BECMG/FM——出声后 PROB 空收、后者独立成组\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `PROB 组合违例(PROB 与 ${nx?.text} 并用——只可独立或连 TEMPO,清单 B8):PROB 段空收,后者独立成组`,\n span: spanOf(startTok),\n });\n changes.push({\n kind: \"PROB\",\n ...(probability !== undefined ? { probability } : {}),\n raw: text,\n span: spanOf(startTok),\n });\n continue;\n }\n } else {\n kind = text === \"TEMPO\" ? \"TEMPO\" : \"BECMG\";\n }\n\n // 窗口:ddHH/ddHH 全窗;或中方四位短窗(B9:无日位,日归属回有效期起日;\n // 仅接受后时>前时的前向时对——0700 一类回退按要素(能见度)处理,杜绝误吞)\n let window: TafChangeWindow | undefined;\n const winTok = tokens[i];\n if (winTok !== undefined) {\n const w = /^(\\d{2})(\\d{2})\\/(\\d{2})(\\d{2})$/.exec(winTok.text);\n const s = /^(\\d{2})(\\d{2})$/.exec(winTok.text);\n if (w !== null) {\n window = {\n startDay: Number(w[1]),\n startHour: Number(w[2]),\n endDay: Number(w[3]),\n endHour: Number(w[4]),\n raw: winTok.text,\n span: spanOf(winTok),\n };\n i += 1;\n } else if (\n s !== null &&\n validity !== undefined &&\n Number(s[2]) > Number(s[1]) &&\n Number(s[2]) <= 24 &&\n Number(s[1]) <= 23\n ) {\n window = {\n startDay: validity.startDay,\n startHour: Number(s[1]),\n endDay: validity.startDay,\n endHour: Number(s[2]),\n raw: winTok.text,\n span: spanOf(winTok),\n };\n i += 1;\n }\n }\n if (window === undefined && kind !== \"PROB\") {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `${kind} 组缺窗(变化词后未随 ddHH/ddHH 窗口组)——要素照常收`,\n span: spanOf(startTok),\n });\n }\n\n const [elements, next] = collectChangeElements(tokens, i);\n changes.push({\n kind,\n ...(probability !== undefined ? { probability } : {}),\n ...(withTempo ? { withTempo } : {}),\n ...(window !== undefined ? { window } : {}),\n ...(elements !== undefined ? { elements } : {}),\n ...groupExtent(raw, tokens, startTok, next),\n });\n i = next;\n }\n\n const clouds: CloudCondition | undefined =\n cloudElements.length > 0 || clearCode !== undefined\n ? { elements: [...cloudElements], ...(clearCode !== undefined ? { clear: clearCode } : {}) }\n : undefined;\n\n // —— C5★ 天气白名单双层:国际白名单(重要天气——中大降水/雷暴族/尘沙暴/冻雾/吹雪/飑/漏斗云等,\n // WMO 51.5)为基;中国扩展层(弱档 `-` 与 BR/HZ 等,ZBTJ/ZSSS 官方示例实证)容错收下 + 出声——\n // 完整白名单编码与拒收语义归 /validate(strict 侧),tolerant 层只标记不拒收\n const cnExtensionGroups: { group: WeatherGroup; where: string }[] = [];\n const baseWeather = weather ?? observedWeatherOf(weatherList);\n if (baseWeather?.kind === \"value\") {\n for (const g of baseWeather.value) cnExtensionGroups.push({ group: g, where: \"基况段\" });\n }\n for (const change of changes) {\n for (const g of change.elements?.weather ?? []) {\n cnExtensionGroups.push({ group: g, where: `${change.kind} 组` });\n }\n }\n for (const { group, where } of cnExtensionGroups) {\n const isCnExtension =\n group.intensity === \"-\" || group.phenomena.some((p) => p === \"BR\" || p === \"HZ\");\n if (!isCnExtension) continue;\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `TAF 国际白名单外天气组(${where}——弱档/BR/HZ 属中国扩展层,清单 C5):已收下`,\n span: group.span,\n });\n }\n\n return finish({\n kind: \"taf\" as const,\n raw,\n station,\n issueTime,\n validity,\n flags: { amended, corrected },\n wind,\n visibility,\n weather: weather ?? observedWeatherOf(weatherList),\n clouds,\n cavok,\n cavokSpan,\n changes,\n temperatures,\n remarks: [],\n warnings,\n });\n}\n\n/** 变化组要素收集:从 from 起收到下一个组界(变化词/气温组/末尾),交 structureTrendElements 结构化 */\nfunction collectChangeElements(\n tokens: readonly Token[],\n from: number,\n): [TrendElements | undefined, number] {\n const collected: Token[] = [];\n let k = from;\n while (k < tokens.length) {\n const t = tokens[k];\n if (t === undefined || isChangeBoundary(t.text)) break;\n collected.push(t);\n k += 1;\n }\n return [structureTrendElements(collected, 0), k];\n}\n\n/** 组的外包络(raw 切片 + span):变化词 token 起至 next 前一 token 止 */\nfunction groupExtent(\n raw: string,\n tokens: readonly Token[],\n startTok: Token,\n next: number,\n): { raw: string; span: Span } {\n const last = tokens[next - 1] ?? startTok;\n const span = { start: startTok.start, end: last.end };\n return { raw: raw.slice(span.start, span.end), span };\n}\n\n/** NIL/CNL/批 1 骨架共用的尾部处理:剩余 token 一律 unknown-token 出声(不静默纪律) */\nfunction collectTailAsUnknown(\n tokens: readonly Token[],\n from: number,\n warnings: ParseWarning[],\n): void {\n for (let k = from; k < tokens.length; k++) {\n const t = tokens[k];\n if (t === undefined) break;\n warnings.push({\n code: \"unknown-token\",\n severity: \"info\",\n message: `TAF 正文组暂未解析(${t.text})——批 1 骨架覆盖电头与有效期,该组保留原文待后续版本`,\n span: spanOf(t),\n });\n }\n}\n\n/**\n * Result-style variant of `parseTaf` (same contract as `tryParse`): whole-report failures come back\n * as `{ ok:false, error }`; unexpected non-MetarParseError exceptions still throw.\n * parseTaf 的问题式变体(契约同 tryParse):整体失败返回 { ok:false, error };\n * 仅编程性意外(非 MetarParseError 的内部异常)原样抛出——不吞实现缺陷。\n */\nexport type TryParseTafResult =\n | { readonly ok: true; readonly report: TafReport }\n | { readonly ok: false; readonly error: MetarParseError };\n\nexport function tryParseTaf(raw: string, options?: TafParseOptions): TryParseTafResult {\n try {\n return { ok: true, report: parseTaf(raw, options) };\n } catch (err) {\n if (err instanceof MetarParseError) return { ok: false, error: err };\n throw err;\n }\n}\n","/**\n * @metweave/parser — TAF 时间线展开器(FM 51,v0.2 批 2.3)。\n * The TAF timeline expander — the derived layer on top of the structural IR.\n *\n * 五步算法(taf-timeline §2「最新段绑定」):切段(FM 硬分页/BECMG 窗终切子段)→ 挂载\n * (TEMPO/PROB 挂段不切段)→ 绑段(时刻 t 绑到变化点已过的最近段)→ 合成(未列要素沿链\n * 回溯,云按例外整体取)→ 叠加(TEMPO 窗内双态:发作取组值、间歇回段值)。\n * B6 过渡带约定:t 落在 BECMG 窗内(含窗起、不含窗终)=变化时刻不可精确,`uncertain`\n * 置真并按**窗终已到**的前段值返回(保守约定,双态展示由消费方叠加「或」文案)。\n * B7 间歇语义:发作每次 <1h、累计 <半窗是 WMO 语义约束(条文判据归 /validate),\n * 展开层只按窗口边界给出双态,不预设发作时刻。\n * B3 跨月回绕:有效期组不含月,展开须带月锚(anchor = 有效期起日所在月),\n * 日序按锚月长度回绕成绝对序。\n * 自检三问(判卷同源,taf-timeline §2):窗开了吗(开窗前只有基况)?绑到最新完成段了吗?\n * 未列要素回溯了吗(云组落笔)?\n */\nimport type {\n CloudCondition,\n TafChangeGroup,\n TafReport,\n TrendElements,\n VisibilityGroup,\n WeatherGroup,\n WindGroup,\n} from \"@metweave/core\";\n\n/** 展开时刻:日(锚月内,可跨月回绕)+ 时分 */\nexport interface TafExpandAt {\n readonly day: number;\n readonly hour: number;\n readonly minute: number;\n}\n\n/** 月锚(B3):有效期起日所在月——`daysIn` 供给跨月回绕的天数表(大小月/闰年由调用方算好) */\nexport interface TafMonthAnchor {\n readonly daysIn: number;\n}\n\n/** 合成后的四要素(展开层两态视图:cavok 让位语义同解析层) */\nexport interface TafResolvedConditions {\n readonly wind?: WindGroup;\n readonly visibility?: VisibilityGroup;\n readonly weather: readonly WeatherGroup[];\n readonly clouds?: CloudCondition;\n readonly cavok: boolean;\n}\n\n/** TEMPO/PROB 发作态:只携带组内所列要素(覆盖语义:天气整列替换、云整体替换、未列继承段值) */\nexport interface TafTempoOverlay {\n readonly conditions: Pick<\n TafResolvedConditions,\n \"wind\" | \"visibility\" | \"weather\" | \"clouds\" | \"cavok\"\n >;\n /** PROB 组携带;TEMPO 无概率 */\n readonly probability?: 30 | 40;\n readonly withTempo: boolean;\n}\n\n/** 一次展开的完整结果 */\nexport interface TafExpansion {\n /** 间歇态/段值(B7:窗内非发作时刻的基线) */\n readonly conditions: TafResolvedConditions;\n /** 发作态(t 落在 TEMPO/PROB 窗内时在位;间歇态仍在 conditions) */\n readonly tempo?: TafTempoOverlay;\n /** B6 过渡带:t 在某 BECMG 窗内,变化时刻不可精确(保守按前段值返回) */\n readonly uncertain: boolean;\n /** 绑定段:base 或变化组序号(changes 下标) */\n readonly boundSegment:\n | { readonly kind: \"base\" }\n | { readonly kind: string; readonly index: number };\n}\n\ninterface Segment {\n /** 段起始绝对分(变化点已过即切到本段) */\n readonly from: number;\n /** 段来源:base=报文基况;FM/BECMG=changes[i](TEMPO/PROB 不切段,见挂载) */\n readonly source: { kind: \"base\" } | { kind: \"FM\" | \"BECMG\"; index: number };\n /** FM 段=硬分页(此前一切作废——回溯不越过 FM);BECMG 段沿链回溯 */\n readonly hard: boolean;\n readonly elements: TrendElements | undefined;\n}\n\nconst minutesOf = (day: number, hour: number, minute: number): number =>\n day * 1440 + hour * 60 + minute;\n\n/** 未列要素沿链回溯合成(云例外:最近一次列云处整体取——BECMG 云必全重报,天然满足) */\nfunction resolveConditions(chain: readonly Segment[], upto: number): TafResolvedConditions {\n let wind: WindGroup | undefined;\n let visibility: VisibilityGroup | undefined;\n let weather: readonly WeatherGroup[] | undefined;\n let clouds: CloudCondition | undefined;\n let cavok = false;\n let sawWeather = false;\n // CAVOK 让位语义(同解析层三关契约):回溯途中遇 CAVOK,其前未定值的 vis/weather/clouds 作废\n let visVoid = false;\n let weatherVoid = false;\n let cloudsVoid = false;\n // 从绑定段向前回溯(链序:越靠后越新)——FM 段为硬界,回溯止于其前\n for (let k = upto; k >= 0; k--) {\n const seg = chain[k];\n if (seg === undefined) continue;\n const e = seg.elements;\n if (e === undefined) continue;\n if (wind === undefined && e.wind !== undefined) wind = e.wind;\n if (visibility === undefined && e.visibility !== undefined) visibility = e.visibility;\n if (!sawWeather && (e.weather.length > 0 || e.nsw !== undefined)) {\n weather = e.nsw !== undefined && e.weather.length === 0 ? [] : e.weather;\n sawWeather = true;\n }\n if (clouds === undefined && (e.clouds !== undefined || e.cavok !== undefined)) {\n if (e.cavok !== undefined) cavok = true;\n clouds = e.clouds;\n }\n if (e.cavok !== undefined) {\n // 该段编 CAVOK:其前的未定要素按三关让位作废(已定值——如 CAVOK 后 BECMG 重编——不回退)\n if (visibility === undefined) visVoid = true;\n if (!sawWeather) {\n weatherVoid = true;\n sawWeather = true;\n }\n if (clouds === undefined) cloudsVoid = true;\n }\n if (seg.hard) break; // FM 硬分页:此前一切作废\n }\n return {\n ...(wind !== undefined ? { wind } : {}),\n ...(visibility !== undefined && !visVoid ? { visibility } : {}),\n weather: weatherVoid ? [] : (weather ?? []),\n ...(clouds !== undefined && !cloudsVoid ? { clouds } : {}),\n cavok,\n };\n}\n\n/** 变化组窗口/时刻 → 绝对分(跨月回绕按锚月天数折算日序) */\nfunction absOfChange(\n change: TafChangeGroup,\n anchorDay: number,\n daysIn: number,\n): { from: number; end: number } | undefined {\n const wrap = (day: number): number => (day < anchorDay ? day + daysIn : day);\n if (change.at !== undefined) {\n // FM 的日按「不早于前段起点」推断:时刻小于锚日起点时刻则视为次日\n const sameDay = minutesOf(anchorDay, change.at.hour, change.at.minute);\n return { from: sameDay, end: sameDay };\n }\n const w = change.window;\n if (w === undefined) return undefined;\n const from = minutesOf(wrap(w.startDay), w.startHour, 0);\n const end = minutesOf(wrap(w.endDay), w.endHour, 0);\n return { from, end };\n}\n\n/** 主导段切点构建(expandTaf 与 tafSegments 共用——切段规则单一来源):\n * base 起步;FM 硬分页(日归属按「不早于当前页起点」推断);BECMG 以窗终为段起点(保守约定) */\nfunction prevailingSegments(report: TafReport, daysIn: number, validFrom: number): Segment[] {\n const v = report.validity;\n const segments: Segment[] = [\n { from: validFrom, source: { kind: \"base\" }, hard: false, elements: baseElements(report) },\n ];\n let pageStart = validFrom; // 当前 FM 页起点(FM 的日归属在其页语境内推断)\n for (const [idx, change] of report.changes.entries()) {\n const kind = change.kind;\n if (kind === \"TEMPO\" || kind === \"PROB\") continue; // 挂载项:不切段\n if (kind === \"FM\" && change.at !== undefined) {\n // FM 日归属:不早于当前页起点——时刻倒挂视为次日\n let from = v !== undefined ? minutesOf(v.startDay, change.at.hour, change.at.minute) : 0;\n while (from < pageStart) from += 1440;\n pageStart = from;\n segments.push({ from, source: { kind, index: idx }, hard: true, elements: change.elements });\n } else if (kind === \"BECMG\") {\n const abs = v !== undefined ? absOfChange(change, v.startDay, daysIn) : undefined;\n if (abs === undefined) continue;\n segments.push({\n from: abs.end,\n source: { kind, index: idx },\n hard: false,\n elements: change.elements,\n });\n }\n }\n return segments;\n}\n\n/**\n * Expand a parsed TAF at one instant — the five-step algorithm (切段→挂载→绑段→合成→叠加).\n * 在给定时刻展开已解析的 TAF(五步算法,黄金基准=taf-timeline §3 三例逐时刻表)。\n * `anchor` 为有效期起日所在月的天数(大小月/闰年由调用方给定,B3);`at.day` 为锚月内日序\n * (跨月后的日按小日号传入,内部回绕)。\n */\nexport function expandTaf(\n report: TafReport,\n at: TafExpandAt,\n anchor: TafMonthAnchor,\n): TafExpansion {\n if (report.validity === undefined || report.nil === true || report.cancelled === true) {\n throw new Error(\"expandTaf 需要带有效期的完整 TAF(NIL/CNL 报无可展开时间线)\");\n }\n const v = report.validity;\n const wrapDay = (day: number): number => (day < v.startDay ? day + anchor.daysIn : day);\n const t = minutesOf(wrapDay(at.day), at.hour, at.minute);\n const validFrom = minutesOf(v.startDay, v.startHour, 0);\n\n // —— ① 切段(与 tafSegments 同一规则):base 起步;FM 硬分页;BECMG 按窗终切子段\n const segments = prevailingSegments(report, anchor.daysIn, validFrom);\n if (t < validFrom) {\n // 自检三问之一:窗开了吗——开窗前只有基况(勿预设双态),此处返回基段且不挂 TEMPO\n const baseSeg = segments[0] ?? {\n from: validFrom,\n source: { kind: \"base\" } as const,\n hard: false,\n elements: undefined,\n };\n return {\n conditions: resolveConditions([baseSeg], 0),\n uncertain: false,\n boundSegment: { kind: \"base\" },\n };\n }\n\n // —— ③ 绑段:变化点已过的最近一段(BECMG 的 from=窗终);t 落任何 BECMG 窗内 → 过渡带\n let bound = 0;\n let uncertain = false;\n for (const [k, seg] of segments.entries()) {\n if (seg.from <= t) bound = k;\n }\n for (const change of report.changes) {\n if (change.kind !== \"BECMG\") continue;\n const abs = absOfChange(change, v.startDay, anchor.daysIn);\n if (abs !== undefined && t >= abs.from && t < abs.end) uncertain = true; // B6(含窗起不含窗终)\n }\n\n // —— ④ 合成 + ② 挂载叠加:t 落 TEMPO/PROB 窗内 → 发作态(覆盖所列要素)\n const conditions = resolveConditions(segments, bound);\n let tempo: TafTempoOverlay | undefined;\n for (const change of report.changes) {\n if (change.kind !== \"TEMPO\" && change.kind !== \"PROB\") continue;\n const abs = absOfChange(change, v.startDay, anchor.daysIn);\n if (abs === undefined || t < abs.from || t >= abs.end) continue;\n const e = change.elements;\n if (e === undefined) continue;\n tempo = {\n conditions: {\n ...(e.wind !== undefined ? { wind: e.wind } : {}),\n ...(e.visibility !== undefined ? { visibility: e.visibility } : {}),\n weather: e.nsw !== undefined && e.weather.length === 0 ? [] : e.weather,\n ...(e.clouds !== undefined ? { clouds: e.clouds } : {}),\n cavok: e.cavok !== undefined,\n },\n ...(change.probability !== undefined ? { probability: change.probability } : {}),\n withTempo: change.withTempo === true,\n };\n break; // 同刻多窗取首个(报文原序);叠加多窗属极端形态,消费方可按需扩展\n }\n\n return {\n conditions,\n ...(tempo !== undefined ? { tempo } : {}),\n uncertain,\n boundSegment: segments[bound]?.source ?? { kind: \"base\" },\n };\n}\n\n/** 绝对分 → 时刻(日为绝对序,可直接喂 expandTaf——≥有效期起日不再回绕) */\nconst atOfAbs = (abs: number): TafExpandAt => ({\n day: Math.floor(abs / 1440),\n hour: Math.floor((abs % 1440) / 60),\n minute: abs % 60,\n});\n\n/** 分段视图行窗口:绝对分 → 时刻(显示序)——日按锚月回绕折回小日号(绝对日 32 在 31 天锚月 → 01) */\nconst atOfDisplay = (abs: number, daysIn: number): TafExpandAt => {\n const raw = atOfAbs(abs);\n return { ...raw, day: ((raw.day - 1) % daysIn) + 1 };\n};\n\n/** 分段视图行(渲染层②「分段天气明细」的数据面,v0.2):一行 = 一个时段的具体天气 */\nexport interface TafSegmentRow {\n /** 行类型:base=基况段;FM=自该时刻起(硬切);BECMG=渐变(过渡带行 uncertain=true)或转变后段(false);TEMPO/PROB=短暂/概率挂载行 */\n readonly kind: \"base\" | \"FM\" | \"BECMG\" | \"TEMPO\" | \"PROB\";\n /** 行窗口起点/终点(显示序:日按锚月回绕,跨月折回小日号) */\n readonly from: TafExpandAt;\n readonly to: TafExpandAt;\n /** BECMG 过渡带行:变化时刻不可精确(B6) */\n readonly uncertain: boolean;\n /** 该窗口的展开四要素(段中点口径;BECMG 过渡带行=转变前值,TEMPO/PROB 行=所在主导段值) */\n readonly conditions: TafResolvedConditions;\n /** 挂载行组内所列要素与概率(仅 TEMPO/PROB 行在位) */\n readonly overlay?: TafTempoOverlay;\n /** 来源变化组下标(changes 序;base 行无) */\n readonly sourceIndex?: number;\n}\n\n/**\n * Derive the period-by-period view of a TAF: prevailing rows (base / FM / after-BECMG) with the\n * BECMG transition band as its own uncertain row, plus TEMPO/PROB overlay rows — chronological.\n * 把 TAF 切成分段明细行(指令「按拆分时间段给具体天气」):主导段行 + BECMG 过渡带行 +\n * TEMPO/PROB 挂载行,按窗口起点升序稳定合并(同刻主导段在前);每行携带段中点展开结果——\n * 切段规则与 expandTaf 同一来源(prevailingSegments),黄金基准互通。\n */\nexport function tafSegments(\n report: TafReport,\n anchor: TafMonthAnchor = { daysIn: 31 },\n): readonly TafSegmentRow[] {\n if (report.validity === undefined || report.nil === true || report.cancelled === true) {\n throw new Error(\"tafSegments 需要带有效期的完整 TAF(NIL/CNL 报无可分段)\");\n }\n const v = report.validity;\n const validFrom = minutesOf(v.startDay, v.startHour, 0);\n const validEnd = minutesOf(\n v.endDay < v.startDay ? v.endDay + anchor.daysIn : v.endDay,\n v.endHour,\n 0,\n );\n\n const rows: { abs: number; row: TafSegmentRow }[] = [];\n\n // —— 主导段行:切点 → 下一切点(末段到有效期止),行值取段中点展开\n const segments = prevailingSegments(report, anchor.daysIn, validFrom);\n for (const [k, seg] of segments.entries()) {\n const next = segments[k + 1];\n const to = next !== undefined ? next.from : validEnd;\n if (to <= seg.from) continue; // 零长段(同刻多变化点):无展示窗,后段顶上\n const mid = seg.from + Math.floor((to - seg.from) / 2);\n const exp = expandTaf(report, atOfAbs(mid), anchor);\n rows.push({\n abs: seg.from,\n row: {\n kind: seg.source.kind,\n from: atOfDisplay(seg.from, anchor.daysIn),\n to: atOfDisplay(to, anchor.daysIn),\n uncertain: false,\n conditions: exp.conditions,\n ...(seg.source.kind !== \"base\" ? { sourceIndex: seg.source.index } : {}),\n },\n });\n }\n\n // —— BECMG 过渡带行(转变前值 + uncertain)与 TEMPO/PROB 挂载行\n for (const [idx, change] of report.changes.entries()) {\n if (change.kind === \"FM\") continue;\n const abs = absOfChange(change, v.startDay, anchor.daysIn);\n if (abs === undefined || abs.end <= abs.from) continue;\n const mid = abs.from + Math.floor((abs.end - abs.from) / 2);\n const exp = expandTaf(report, atOfAbs(mid), anchor);\n if (change.kind === \"BECMG\") {\n rows.push({\n abs: abs.from,\n row: {\n kind: \"BECMG\",\n from: atOfDisplay(abs.from, anchor.daysIn),\n to: atOfDisplay(abs.end, anchor.daysIn),\n uncertain: true,\n conditions: exp.conditions,\n sourceIndex: idx,\n },\n });\n continue;\n }\n const e = change.elements;\n if (e === undefined) continue;\n rows.push({\n abs: abs.from,\n row: {\n kind: change.kind,\n from: atOfDisplay(abs.from, anchor.daysIn),\n to: atOfDisplay(abs.end, anchor.daysIn),\n uncertain: false,\n conditions: exp.conditions,\n overlay: {\n conditions: {\n ...(e.wind !== undefined ? { wind: e.wind } : {}),\n ...(e.visibility !== undefined ? { visibility: e.visibility } : {}),\n weather: e.nsw !== undefined && e.weather.length === 0 ? [] : e.weather,\n ...(e.clouds !== undefined ? { clouds: e.clouds } : {}),\n cavok: e.cavok !== undefined,\n },\n ...(change.probability !== undefined ? { probability: change.probability } : {}),\n withTempo: change.withTempo === true,\n },\n sourceIndex: idx,\n },\n });\n }\n\n // —— 稳定合并:按窗口起点升序(同刻主导段在前;插入序天然稳定,n 极小无需排序库)\n const sorted: { abs: number; row: TafSegmentRow }[] = [];\n for (const item of rows) {\n let pos = sorted.length;\n while (pos > 0) {\n const prev = sorted[pos - 1];\n if (prev === undefined || prev.abs <= item.abs) break;\n pos -= 1;\n }\n sorted.splice(pos, 0, item);\n }\n return sorted.map((x) => x.row);\n}\n\n/** 基况段 → TrendElements 形态(展开链的统一要素视图) */\nfunction baseElements(report: TafReport): TrendElements | undefined {\n const has =\n report.wind?.kind === \"value\" ||\n report.visibility?.kind === \"value\" ||\n report.weather?.kind === \"value\" ||\n report.clouds !== undefined ||\n report.cavok;\n if (!has) return undefined;\n return {\n ...(report.wind?.kind === \"value\" ? { wind: report.wind.value } : {}),\n ...(report.visibility?.kind === \"value\" ? { visibility: report.visibility.value } : {}),\n weather: report.weather?.kind === \"value\" ? report.weather.value : [],\n ...(report.clouds !== undefined ? { clouds: report.clouds } : {}),\n ...(report.cavok\n ? { cavok: report.cavokSpan !== undefined ? { span: report.cavokSpan } : {} }\n : {}),\n };\n}\n","/**\n * @metweave/parser — 解析层:METAR/SPECI(tolerant)→ IR;TAF(FM 51)自 v0.2 起同入口供给(./taf)。\n * The parsing layer: METAR/SPECI (tolerant mode) → IR; TAF (FM 51) served from the same entry since v0.2 (./taf).\n *\n * v0.1 实现范围:METAR 正文 + 趋势组半结构化 + RMK 认组 + 跑道状态最小形。\n * v0.2 批 1 起:TAF 电头与有效期骨架(基况段/变化组随后续批次),组级纯函数共享层在 ./groups。\n * 纪律:不静默——看不懂的 token 一律进 warnings[](unknown-token,info 级),绝不丢弃;\n * 缺测电码(////、/////KT、//)与不可信值(5 位数 QNH)→ Observed missing + 告警;\n * 单位跟组走;一切产物携带原文 span。strict 模式预留给报文校验场景。\n */\nimport type {\n AltimeterReading,\n CloudCondition,\n CloudElement,\n MetarReport,\n WindShearGroup,\n Observed,\n ParseOptions,\n ParseWarning,\n RemarkGroup,\n ReportKind,\n RunwayStateGroup,\n RunwayVisualRange,\n Span,\n TemperatureReading,\n TrendGroup,\n VisibilityGroup,\n WeatherGroup,\n WindGroup,\n} from \"@metweave/core\";\nimport { MetarParseError } from \"@metweave/core\";\n\n// IR 类型就近供给:本包 API 的返回/告警类型即 core 的 IR 类型(唯一来源在 core,此处仅转发)——\n// 免去消费方猜测「parse 的返回类型去哪 import」(2026-09-16 五方实测评测反馈)\nexport type {\n AltimeterReading,\n CloudCondition,\n CloudElement,\n MetarReport,\n Observed,\n ParseWarning,\n ReportKind,\n RunwayStateGroup,\n RunwayVisualRange,\n Span,\n TafChangeAt,\n TafChangeGroup,\n TafChangeKind,\n TafChangeWindow,\n TafParseOptions,\n TafTemperatureGroup,\n TafReport,\n TafValidityGroup,\n TemperatureReading,\n TrendElements,\n TrendGroup,\n TrendKind,\n VisibilityGroup,\n WeatherGroup,\n WindGroup,\n} from \"@metweave/core\";\n// TAF 解析层(v0.2 批 1 起):parseTaf / tryParseTaf 与其结果类型——与 parse 同入口供给\nexport { parseTaf, tafDurationHours, tryParseTaf } from \"./taf\";\nexport type { TryParseTafResult } from \"./taf\";\n// TAF 时间线展开器(v0.2 批 2.3 起):五步算法的派生层(B4–B7)\nexport { expandTaf, tafSegments } from \"./expand\";\n// TAF 判据校验层(v0.2 补齐批):C2/C3/C5/C7 四判据——解析期移交至此的条文判据收口\nexport { validateTaf } from \"./validate\";\nexport type {\n TafValidateOptions,\n TafValidateStandard,\n TafViolation,\n TafViolationCode,\n} from \"./validate\";\nexport type {\n TafExpandAt,\n TafExpansion,\n TafMonthAnchor,\n TafResolvedConditions,\n TafSegmentRow,\n TafTempoOverlay,\n} from \"./expand\";\nimport {\n TREND_KINDS,\n VIS_V_RANGE,\n TX_TN_PATTERN,\n M_WIND,\n M_VIS,\n M_R,\n M_WEATHER,\n M_CLOUD,\n M_VV,\n M_SKY_CLEAR,\n M_TEMP,\n M_QNH,\n M_ALTIMETER_A,\n M_VIS_RANGE,\n M_DOLLAR,\n M_WS_RWY,\n maskOf,\n isSkyClear,\n tokenize,\n spanOf,\n compactNode,\n tryWeatherToken,\n parseVisibilityToken,\n parseWindToken,\n parseTempDewToken,\n parseRvrToken,\n parseRunwayStateToken,\n warnDuplicateGroup,\n applyAltimeterReading,\n parseQnhToken,\n parseAltimeterAToken,\n validateWindGroup,\n applyVisibilityToken,\n applyTempDewToken,\n warnTrendClose,\n collectTrendSegment,\n buildTrendGroup,\n cloudLayerElementOf,\n verticalVisibilityElementOf,\n parseWindShearSequence,\n applyRvrNoBodyToken,\n warnRvrNoThenValues,\n applyRvrSlashToken,\n observedWeatherOf,\n cavokCrossCheck,\n parseRemarkSegment,\n} from \"./groups\";\nimport type { Token } from \"./groups\";\nexport { TEMP_DEW_PATTERN } from \"./groups\";\n\n/**\n * Parse one METAR/SPECI report (tolerant mode) into the IR — the package's single entry.\n * 解析单条 METAR/SPECI 报文(tolerant)为 IR——本包唯一入口。\n *\n * Throws MetarParseError (stable machine-readable `code`) on whole-report failure\n * (non-string input / missing station / missing time / invalid time / unsupported mode); anything the\n * parser does not recognize lands in `warnings[]` with its span — never dropped.\n * 整体失败(输入非字符串/无站名/无时组/时组越界/未实现模式)抛 MetarParseError(code 稳定契约);\n * 看不懂的组带 span 进 warnings[],绝不丢弃。\n * @param raw - Report text, verbatim (kept on report.raw). 报文原文(原样保真于 report.raw)。\n * @param options - See ParseOptions (kind override, compact spans). 见 ParseOptions(类型位注入、紧凑模式)。\n */\nexport function parse(raw: string, options?: ParseOptions): MetarReport {\n // 紧凑模式(E1):spans === false 时在出口以重建式剥除全部 span(见 compactNode 注释)\n const compact = options?.spans === false;\n const compactIfEnabled = <T>(report: T): T => (compact ? compactNode(report) : report);\n // 输入校验:非字符串走 MetarParseError 稳定契约(code: \"invalid-input\")——code 是\n // 消费方分流的稳定面、EN_MESSAGES 查表英化的键,裸 Error 会同时绕过两者(此前为裸 Error)\n if (typeof raw !== \"string\") {\n throw new MetarParseError(\n \"invalid-input\",\n String(raw),\n `parse 需要一个 METAR/SPECI 报文字符串,收到 ${raw === null ? \"null\" : typeof raw}`,\n );\n }\n if ((options?.mode ?? \"tolerant\") === \"strict\") {\n // 错误面契约:strict 留在类型上(路线图项),但 v0.1 未实现——调用方 catch 不漏接裸 Error\n throw new MetarParseError(\n \"unsupported-mode\",\n raw,\n \"METAR 侧 strict 模式尚未实现(TAF 侧 parseTaf 已支持 strict)——请省略 mode 或显式传 'tolerant'\",\n );\n }\n const warnings: ParseWarning[] = [];\n // 报尾 = 终结符剥离(GTS/AFTN 通路报文行以 = 定界,常粘连末组如 Q1006= / NOSIG=)——\n // 仅剥尾部空白与 =,正文 token 偏移不变,span 仍对应原 raw(raw 保真含 =)。\n // 末字符预判(E2 性能项):语料大头无报尾,尾字符既非 = 也非空白时跳过整串正则——\n // 预判用单字符 \\s 测试(与 [\\s=] 字符类完全同域,行为等价),省一次全文回溯扫描\n const tail = raw.at(-1);\n const body =\n tail === undefined || tail === \"=\" || /\\s/.test(tail) ? raw.replace(/[\\s=]+$/, \"\") : raw;\n const tokens = tokenize(body);\n // 输入规模护栏(只告警不截断——截断破坏 raw 保真与「不丢弃」纪律):语料单行最大 30 token,\n // 上限 128 = 4 倍余量;超限报文照常完整解析,仅以一条聚合告警标记异常输入\n //(span 缺省 = 报文级;整体失败路径不经过此处,失败契约不受影响)\n const TOKEN_COUNT_LIMIT = 128;\n if (tokens.length > TOKEN_COUNT_LIMIT) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `输入 token 数超上限(${tokens.length} > ${TOKEN_COUNT_LIMIT})——按异常输入标记,解析照常完整,原文经 raw 保真`,\n });\n }\n let i = 0;\n const peek = (ahead = 0): Token | undefined => tokens[i + ahead];\n\n const externalKind = options?.kind;\n let kind: ReportKind = externalKind ?? \"metar\";\n let corrected = false;\n let auto = false;\n\n // —— 头部:类型词 / COR(WMO 形态)/ 站名 / 时组 / AUTO / COR(美式时组后形态)\n const head = peek();\n if (head !== undefined && (head.text === \"METAR\" || head.text === \"SPECI\")) {\n if (externalKind === undefined) kind = head.text === \"SPECI\" ? \"speci\" : \"metar\";\n i += 1; // 类型词 token 无论由谁决定 kind 都要消费\n }\n if (peek()?.text === \"COR\") {\n corrected = true;\n i += 1;\n }\n // AMD(修订发布标志,部分 CAA 用于 METAR 标题位,TAF 更常见):标题元数据词,\n // 语义为「本报告取代此前发布」——消费之不进站名位;是否置 corrected 不越权代判\n //(修订 ≠ 更正),IR 无 amended 位故仅放行不标注\n if (peek()?.text === \"AMD\") {\n i += 1;\n }\n const stTok = peek();\n if (stTok === undefined || !/^[A-Z0-9]{4}$/.test(stTok.text)) {\n // 契约:无站名组 = 整体解析失败(不是字段级三态);code 是稳定契约,message 中文为权威\n // 文案——英文经 @metweave/core EN_MESSAGES[code] 查表或渲染层 locale:\"en\" 切换\n throw new MetarParseError(\n \"missing-station\",\n raw,\n `无法识别站名组——输入不是 METAR/SPECI 报文(${stTok?.text ?? \"空输入\"})`,\n );\n }\n const station: string = stTok.text;\n i += 1;\n // CCA/CCB/CCC 与 COR 槽位磨损兜底(站名后/时组前——规范槽位:BBB 系列在时组后(见下方\n // BBB 消费位)、COR 在类型词位(见报头 COR 位)):部分 feed 的更正标记出现在此槽——此前\n // 直接 throw missing-time,「合法更正报整体失败」是最恶性失败模式。后随 token 为合法时组时\n // 消费放行并置 corrected + 出声(槽位漂移本身须可观测——不静默,2026-09-14 独立复评补\n // COR 对称缺口与出声);后随非时组则照旧走 missing-time。已知留案:标记若出现在 AUTO\n // 之前的其他相对序(如 CCA AUTO),AUTO 会落正文 unknown——语料无实证,暂不设防\n const driftTok = peek();\n if (driftTok !== undefined && /^(CC[A-Z]|COR)$/.test(driftTok.text)) {\n const afterDrift = peek(1);\n if (afterDrift !== undefined && /^\\d{2}\\d{2}\\d{2}Z$/.test(afterDrift.text)) {\n corrected = true;\n i += 1;\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `更正标记槽位漂移(${driftTok.text} 出现在站名后/时组前——已消费并置更正标志)`,\n span: spanOf(driftTok),\n });\n }\n }\n const tmTok = peek();\n const tm = tmTok !== undefined ? /^(\\d{2})(\\d{2})(\\d{2})Z$/.exec(tmTok.text) : null;\n if (tmTok === undefined || tm === null) {\n throw new MetarParseError(\n \"missing-time\",\n raw,\n `无法识别时组——输入不是完整的 METAR/SPECI 报文(${tmTok?.text ?? \"时组缺失\"})`,\n );\n }\n const time: MetarReport[\"time\"] = {\n day: Number.parseInt(tm[1] ?? \"0\", 10),\n hour: Number.parseInt(tm[2] ?? \"0\", 10),\n minute: Number.parseInt(tm[3] ?? \"0\", 10),\n };\n // 契约:时组为两态必填(无缺测形态,无 Observed)——数值越界即不可信时组,等同无效时组整体失败,\n // 绝不把假值(日 99、时 24、分 60)留在 IR(同 Q10054 脏 QNH 的「值不可信」纪律,时组无处判缺测故整体失败)\n if (time.day < 1 || time.day > 31 || time.hour > 23 || time.minute > 59) {\n throw new MetarParseError(\n \"invalid-time\",\n raw,\n `时组数值越界(${tmTok.text}:须日 01–31 / 时 00–23 / 分 00–59)——输入不是完整的 METAR/SPECI 报文`,\n );\n }\n i += 1;\n if (peek()?.text === \"AUTO\") {\n auto = true;\n i += 1;\n }\n if (peek()?.text === \"COR\") {\n corrected = true;\n i += 1;\n }\n // RRA/RRB/RRC 迟到报标记(AP-117-TM-01R2 第 21 条:报头时间组后)——标题元数据,消费放行\n if (/^RR[ABC]$/.test(peek()?.text ?? \"\")) {\n i += 1;\n }\n // CCA/CCB/CCC 更正指示符(WMO FM15 §1.3.3 BBB 系列:第一次更正 CCA、第二次 CCB 顺延;\n // 规范槽位即本位——时组后。加拿大 NAV CANADA 明文采用,中国 AFTN 实务沿用;仓库声明的\n // 编码基准含 MANOPS-MET)。语义即更正报——与 COR 同义异位(COR 在类型词位、BBB 在时组后位),\n // 消费并置 corrected;此前落 unknown-token,更正语义丢失(2026-09-14 复评:基准内形态未实现)\n if (/^CC[A-Z]$/.test(peek()?.text ?? \"\")) {\n corrected = true;\n i += 1;\n }\n\n // —— NIL:台站无观测(FM15 代码形注 2 的 NIL 码词;§15.4 是 AUTO 条款)——最小形态:站名/时组凭据保留,正文组不解析(本就无正文),零告警\n if (peek()?.text === \"NIL\") {\n return compactIfEnabled({\n kind,\n raw,\n nil: true,\n station,\n time,\n flags: { auto, corrected },\n cavok: false,\n trends: [],\n runwayStates: [],\n remarks: [],\n warnings,\n });\n }\n\n // —— 正文状态\n let cavok = false;\n let cavokSpan: Span | undefined;\n let wind: Observed<WindGroup> | undefined;\n let visibility: Observed<VisibilityGroup> | undefined;\n // 脱离主导能见度的方向组被按主导收下的局部标记(见正文循环方向组分支注释;非 IR 字段)\n let directionalAsPrimary = false;\n let rvr: Observed<readonly RunwayVisualRange[]> | undefined;\n const rvrList: RunwayVisualRange[] = [];\n // 多组 RVR 的组级 span 首组至末组(与天气组同口径——单组 span 在各自元素上)\n let rvrSpan: Span | undefined;\n let weather: Observed<readonly WeatherGroup[]> | undefined;\n const weatherList: WeatherGroup[] = [];\n const recentList: WeatherGroup[] = [];\n let clouds: CloudCondition | undefined;\n let cloudSeen = false;\n const cloudElements: CloudElement[] = [];\n let clearCode: CloudCondition[\"clear\"];\n let temperature: TemperatureReading | undefined;\n let dewpoint: TemperatureReading | undefined;\n let altimeter: AltimeterReading | undefined;\n // 双气压组口径(tolerant 惯例):末组为准(保持既有 last-wins 行为),重复组追加 info 告警不静默\n let altimeterSeen = false;\n const trends: TrendGroup[] = [];\n const runwayStates: RunwayStateGroup[] = [];\n const remarks: RemarkGroup[] = [];\n // 重复组口径(与双气压组同款 tolerant 惯例):末组为准(保持既有 last-wins 行为),\n // 重复组出声不静默——专用码 duplicate-group(2026-09-15 五角色评测定案:此前借用\n // cross-check-conflict+info,消费方无法按「重复」分流;severity 升 warning)。\n // 前值后值原文都进 message:last-wins 会覆盖 IR 里的前值 span,前值唯一可回溯通道就是这条告警\n // 风切变组累积器(同报多组 WS 合一:runways 连接、span 首组至末组)\n let windShear: WindShearGroup | undefined;\n let wsRunways: string[] | undefined;\n let wsAll = false;\n let wsSpan: Span | undefined;\n\n // —— 正文循环(RMK 交段外处理)\n while (i < tokens.length) {\n const t = tokens[i];\n if (t === undefined) break;\n const text = t.text;\n\n if (text === \"RMK\") {\n i += 1;\n break;\n }\n // RMK 磨损粘连(RMKQFE749/0998 = RMK 与后组丢空格,fuzz 实弹 35/5 万例命中):进 RMK 段\n // 但不跳过 token 本身——由 RMK 段按认组粒度收下(多为 unknown,raw 保真不蒸发)\n if (text.startsWith(\"RMK\")) {\n break;\n }\n\n // 趋势指示组:NOSIG / BECMG / TEMPO(吞到下一个指示组、RMK 或结尾)\n if (TREND_KINDS.has(text)) {\n const kindText = text;\n const collected: Token[] = [t];\n i += 1;\n let period: TrendGroup[\"period\"];\n const periodTok = peek();\n if (\n kindText !== \"NOSIG\" &&\n periodTok !== undefined &&\n // 时段词双形态:AT/TL/FM+DDHH(WMO 306 FM15 §15.14.3)与 DDHH/DDHH 斜杠时段\n //(ICAO Annex 3 模板 / 中国民航主流编法,2026-09-16 五方实测评测发现的缺失形态)\n (/^(?:AT|FM|TL)\\d{4}$/.test(periodTok.text) || /^\\d{4}\\/\\d{4}$/.test(periodTok.text))\n ) {\n period = { text: periodTok.text, span: spanOf(periodTok) };\n collected.push(periodTok);\n i += 1;\n }\n // 收口语义见 isTrendCollectible:仅趋势合法要素族可收,其余收口交回正文(warnTrendClose 出声)\n i = collectTrendSegment(tokens, i, collected);\n warnTrendClose(tokens, i, warnings);\n trends.push(\n buildTrendGroup(\n kindText === \"NOSIG\" ? \"nosig\" : kindText === \"BECMG\" ? \"becmg\" : \"tempo\",\n period,\n collected,\n period !== undefined ? 2 : 1,\n ),\n );\n continue;\n }\n\n // 指示组缺失趋势段两形态——传输磨损所致(WMO 306 FM15 §15.14.3 时段词 AT/TL/FM 不得脱离指示组):\n // ①粘连——指示组与时段词丢空格(BECMGTL0350,IEM 归档实弹 10 次):宽容拆分,语义完整可恢复;\n // ②裸时段词——指示组整组丢失(Q1009 TL0730 …,IEM 归档实弹 128 次):按 kind 'unspecified'\n // 收段(要素组不再散落正文——尤其防趋势风组以 last-wins 覆盖正文真风组),告警标注指示组不可辨。\n // NOSIG 粘连不拆(NOSIG 语义上不配时段词);标准位置的时段词已在上方指示组分支内消费,此处不重复触达。\n if (\n (text.length === 6 &&\n (text.charCodeAt(0) === 65 || text.charCodeAt(0) === 84 || text.charCodeAt(0) === 70)) ||\n text.startsWith(\"BECMG\") ||\n text.startsWith(\"TEMPO\")\n ) {\n const fused = /^(BECMG|TEMPO)((?:AT|TL|FM)\\d{4}|\\d{4}\\/\\d{4})$/.exec(text);\n if (fused !== null) {\n const indicator = fused[1] ?? \"\";\n const collected: Token[] = [t];\n i += 1;\n i = collectTrendSegment(tokens, i, collected);\n warnTrendClose(tokens, i, warnings);\n trends.push(\n buildTrendGroup(\n indicator === \"BECMG\" ? \"becmg\" : \"tempo\",\n {\n text: text.slice(indicator.length),\n span: { start: t.start + indicator.length, end: t.end },\n },\n collected,\n 1,\n ),\n );\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `趋势指示组与时段词粘连(${text}——传输磨损丢空格,BECMG/TEMPO 与 AT/TL/FM 时段语义完整可恢复)`,\n span: spanOf(t),\n });\n continue;\n }\n if (/^(AT|TL|FM)\\d{4}$/.test(text)) {\n const collected: Token[] = [t];\n i += 1;\n i = collectTrendSegment(tokens, i, collected);\n warnTrendClose(tokens, i, warnings);\n trends.push(buildTrendGroup(\"unspecified\", { text, span: spanOf(t) }, collected, 1));\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `趋势时段词缺指示组(${text}——§15.14.3 时段词须随 BECMG/TEMPO 出现)——按指示组缺失的趋势段收下,指示组类型不可辨`,\n span: spanOf(t),\n });\n continue;\n }\n }\n // 裸斜杠时段词(1616/1618——ICAO Annex 3 模板 / 中国民航主流趋势时段编法,指示组缺失):\n // 与 AT/TL/FM 裸词同纪律——kind 'unspecified' 收段出声,要素组不再散落正文\n //(2026-09-16 五方实测评测发现:此前该形态散落正文,趋势能见度以 last-wins 顶掉正文能见度)。\n // 前置守卫(长度 9 + 第 5 字符为斜杠)保正文热路径不为逐 token 正则付费\n if (text.length === 9 && text.charCodeAt(4) === 47 && /^\\d{4}\\/\\d{4}$/.test(text)) {\n const collected: Token[] = [t];\n i += 1;\n i = collectTrendSegment(tokens, i, collected);\n warnTrendClose(tokens, i, warnings);\n trends.push(buildTrendGroup(\"unspecified\", { text, span: spanOf(t) }, collected, 1));\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `趋势时段词缺指示组(${text}——ICAO Annex 3 模板趋势时段须随 BECMG/TEMPO 出现)——按指示组缺失的趋势段收下,指示组类型不可辨`,\n span: spanOf(t),\n });\n continue;\n }\n\n if (text === \"CAVOK\") {\n cavok = true;\n cavokSpan = spanOf(t);\n // 交叉校验(三面:能见度/天气/云,判据见 cavokCrossCheck 注)——CAVOK 语义要求能见度\n // ≥10km、无重要天气、5000ft 以下无云且无 CB/TCU;前序组确定矛盾即出声。\n // 下界语义的编码(9999 ≥10km、P6SM >9.6km)与 CAVOK 相容不告警;M 前缀(小于下界)必矛盾。\n // 让位契约照旧(vis/weather/cloud 三组让位),矛盾仅追加 cross-check-conflict 告警\n cavokCrossCheck(\n { cavokSpan, visibility, weatherList, rvr, cloudElements },\n \"前序\",\n raw,\n warnings,\n );\n // 契约(IR):CAVOK = 能见度 ≥10km + 无低云 + 无天气,前序 vis/weather/cloud 三组让位为 undefined\n // (让位是契约行为不发告警;词位以 cavokSpan 标记,前序组原码仍可从 raw 回溯)\n visibility = undefined;\n directionalAsPrimary = false;\n weather = undefined;\n weatherList.length = 0;\n cloudSeen = false;\n cloudElements.length = 0;\n clearCode = undefined;\n i += 1;\n continue;\n }\n\n // E3 性能项——首字符位掩码分流:每轮按首字符一次 switch 得「可能匹配的分支」位集,\n // 各分支先做一次位测试再进正则——不可能匹配的分支零正则尝试。分支相对顺序与原\n // 全试链完全一致(行为等价由全量语料回放快照锁定)。可达首字符推导:\n // 风 V/数字//;能见度 数字//M/P;RVRNO 与 R 组 R;天气 = 现象/描述符首字母\n // (B D F G H I M P R S T U)+ -/+/V(VC);裸 // 与云 /;云 F/S/B/O//;\n // VV 与 VIS 的 V;晴空词 S/N/C;温露 M/数字//;QNH 的 Q;A 组的 A;维护符 $。\n const mask = maskOf(text.charCodeAt(0));\n\n // 风(含 /////KT 缺测与 260V050 变化组)\n const windParsed = (mask & M_WIND) !== 0 ? parseWindToken(t, peek(1)) : null;\n if (windParsed !== null) {\n if (wind !== undefined) warnDuplicateGroup(raw, warnings, \"风组\", wind.span, spanOf(t));\n if (windParsed === \"missing\") {\n if (wind === undefined) {\n wind = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n // 全缺测 /////KT(自动站假报文形态)与部分缺测(180//KT 风速位缺)同口径出声\n message: t.text.startsWith(\"/////\")\n ? \"风组缺测(/////KT,疑似自动站假报文形态)\"\n : `风组缺测(${t.text},风速位缺测)`,\n span: spanOf(t),\n });\n }\n // 已有风组时:缺测电码不顶替在场值(duplicate-group 已出声)——\n // 零信息量的缺测码按 last-wins 覆盖真实观测是纯信息损失(2026-09-15 五角色评测批)\n i += 1;\n } else {\n // 值域门(NaN 终结防线 / >199 上限 / 越界 findings / 阵风缺测 / VRB 变化组并存)\n // 迁至 validateWindGroup——判据与告警顺序见其注释\n const applied = validateWindGroup(t, windParsed, raw);\n wind = applied.wind;\n warnings.push(...applied.warnings);\n i += windParsed.consumed;\n }\n continue;\n }\n\n // 能见度(//// 显式缺测补 info 告警——对齐风/天气缺测口径;零分母判缺测补超界告警)\n const visParsed = (mask & M_VIS) !== 0 ? parseVisibilityToken(t, peek(1)) : null;\n if (visParsed !== null) {\n // 方向组挂靠/脱离主导、缺测不顶替在场值、零分母判缺测等落位规则迁至 applyVisibilityToken\n const applied = applyVisibilityToken(\n t,\n visParsed,\n { visibility, directionalAsPrimary },\n raw,\n warnings,\n );\n visibility = applied.visibility;\n directionalAsPrimary = applied.directionalAsPrimary;\n i += visParsed.consumed;\n continue;\n }\n\n // RVRNO:RVR 设备存在但明示不可用(显式缺测,区别于组省略)。\n // 正文位与 RMK 位行为统一(2026-09-15 方案一,专业判读定案):一律进 remarks(kind\n // 'rvr-no')——站级状态声明 typed 可见,原正文位不留痕的双标消除;RVRNO 单独出现\n //(此前无值组)仍 = rvr 显式缺测(既有 IR 契约不变)。\n // 值组与 RVRNO 并存 = 自相矛盾形态(规范未定义并存):值组按跑道级明细保留——具体\n // 值组是逐道运行信息、可信度高于无道号的站级状态码(预报员/塔台标准判读;NWS 官方\n // 解码器即「值组 + RVRNO 旗标并存不复算」),矛盾出声、文案描述矛盾本身不预言终态。\n if ((mask & M_R) !== 0 && text === \"RVRNO\") {\n rvr = applyRvrNoBodyToken(t, rvr, raw, warnings, remarks);\n i += 1;\n continue;\n }\n\n // RVR 与跑道状态(同为 R 前缀组,先按 RVR 语法试解、再按跑道状态电码试解)\n if ((mask & M_R) !== 0 && text.startsWith(\"R\") && text.includes(\"/\")) {\n const rvrParsed = parseRvrToken(t);\n if (rvrParsed !== null) {\n // 反向次序对称口径:RVRNO 在前、值组在后同样出声(方案一:可解读为传感器恢复,\n // 值组按明细保留——与正序矛盾并存同一文案口径,见 RVRNO 位注释)\n if (rvr?.kind === \"missing\") {\n warnRvrNoThenValues(t, rvr.span, raw, warnings);\n }\n rvrList.push(rvrParsed);\n const s = spanOf(t);\n rvrSpan = rvrSpan === undefined ? s : { start: rvrSpan.start, end: s.end };\n rvr = { kind: \"value\", value: [...rvrList], span: rvrSpan };\n i += 1;\n continue;\n }\n const runwayState = parseRunwayStateToken(t);\n if (runwayState !== null) {\n runwayStates.push(runwayState.group);\n for (const finding of runwayState.findings) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: finding.message,\n span: finding.span,\n });\n }\n i += 1;\n continue;\n }\n // RVR 全斜杠缺测:R## + / + ////(分离符 + 四位值位斜杠 = 5 斜杠,标准缺测形态)。\n // 4 斜杠(R10////)为磨损短一段——按缺测收下,另附 invalid-format info(tgftp/IEM 实弹均见)\n const rvrMissing = applyRvrSlashToken(t, warnings);\n if (rvrMissing !== null) {\n rvr = rvrMissing;\n i += 1;\n continue;\n }\n }\n\n // 风切变组(WMO 306 FM15 §15.13.3 / ICAO Annex 3 模板):标准形态 WS ALL RWY(全部跑道)\n // 与 WS R##[RLC](WS RDRDR,如 WS R24——IEM 归档实弹 544 次、中国区多发且为近月主流形态)。\n // 中国区实务变体 WS RWY##[RLC](RWY 前缀 + 设计器,教材常用)与 WS RWY ALL(词序倒置)\n // 同样语义无损一等收下——四形态正文组(跑道状态之后、趋势之前)。\n // 低空风切变对起降阶段是重大危害,IR 一等字段不蒸发。\n if ((mask & M_WS_RWY) !== 0 && text === \"WS\") {\n const wsMatch = parseWindShearSequence(t, peek(1), peek(2));\n if (wsMatch !== null) {\n wsRunways ??= [];\n if (wsMatch.runway !== null) wsRunways.push(wsMatch.runway);\n if (wsMatch.all) wsAll = true;\n wsSpan =\n wsSpan === undefined ? wsMatch.span : { start: wsSpan.start, end: wsMatch.span.end };\n windShear = { runways: wsRunways, allRunways: wsAll, span: wsSpan };\n i += wsMatch.consumed;\n continue;\n }\n }\n\n // 温度预告组(TAF TX/TN 混入 METAR 通路,IEM 归档实弹 26 次——中国区 TAF 行混入 METAR 流):\n // TX25/0907Z = 最高 25°C、09 日 07Z 到达(ICAO Annex 3 附录五温度预告组,M 前缀 = 负值)。\n // 认组收下进 remarks(kind 'temperature-forecast',raw 保真)——TAF 语义不属于 METAR 趋势段,\n // 与既有 temp-extrema-6h/24h 同款认组粒度,不解码数值(RemarkGroup 无值槽,数值化留待后续 additive 扩展)\n const txTnMatch = (mask & M_WEATHER) !== 0 && TX_TN_PATTERN.test(text);\n if (txTnMatch) {\n remarks.push({ kind: \"temperature-forecast\", raw: text, span: spanOf(t) });\n i += 1;\n continue;\n }\n\n // 天气组(RE 近期天气一并识别——不参与当前天气三态判定)\n const weatherParsed =\n (mask & M_WEATHER) !== 0 ? tryWeatherToken(t, weatherList, recentList) : false;\n if (weatherParsed !== false) {\n if (weatherParsed.outOfOrder) {\n // 能完整切解但语序反常(描述符在现象之后,如 RATS):按切解结果收下 + invalid-format 告警,\n // 不静默也不拒收;完全无法切解的仍走下方 unknown-token\n warnings.push({\n code: \"invalid-format\",\n severity: \"warning\",\n message: `天气组语序不合电码表(${text}:描述符须先于现象)——已按切解结果收下`,\n span: spanOf(t),\n });\n }\n if (weatherParsed.signWithVc) {\n // 强度符与 VC 并存(-VCTSRA 家族,NWS 自动站实弹):互斥是明文条款(4678 限定槽\n // 四选一、FAA AIM「Intensity and 'VC' will not appear together」),语义可无损恢复\n //(强度+邻近+现象俱全)故容忍切解收下并出声——此前整体落 unknown-token 语义全丢\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message: `强度符与 VC 邻近指示并存(${text}——强度符不与 VC 同组)——已按切解结果收下`,\n span: spanOf(t),\n });\n }\n if (weatherParsed.intensityMisuse === true) {\n warnings.push({\n code: \"invalid-format\",\n severity: \"info\",\n message:\n weatherParsed.kind === \"recent\"\n ? `RE 近期天气组带强度符(${text}——15.13.2.1 RE 组无强度位)——已收下`\n : `强度符超适用面(${text}——表 4678 注 4:-/+ 仅限降水族,非降水唯 +SS/+FC/+DS)——已收下`,\n span: spanOf(t),\n });\n }\n i += 1;\n continue;\n }\n\n // 裸 // 天气缺测组(自动站无法观测天气;IR 口径 = weather missing,绝不捏造也不吞进温度组)\n if ((mask & M_WEATHER) !== 0 && text === \"//\") {\n weather = { kind: \"missing\", span: spanOf(t) };\n warnings.push({\n code: \"missing-expected\",\n severity: \"info\",\n message: \"天气组缺测(//,无法观测天气)\",\n span: spanOf(t),\n });\n i += 1;\n continue;\n }\n\n // 云:云量位 /// 与云高 /// 双缺测形态(绝不捏造)——缺测位告警随构造直出(cloudLayerElementOf)\n const cloudElem = (mask & M_CLOUD) !== 0 ? cloudLayerElementOf(t, warnings) : null;\n if (cloudElem !== null) {\n cloudSeen = true;\n cloudElements.push(cloudElem);\n i += 1;\n continue;\n }\n const vvElem = (mask & M_VV) !== 0 ? verticalVisibilityElementOf(t, warnings) : null;\n if (vvElem !== null) {\n cloudSeen = true;\n cloudElements.push(vvElem);\n i += 1;\n continue;\n }\n if ((mask & M_SKY_CLEAR) !== 0 && isSkyClear(text)) {\n cloudSeen = true;\n clearCode = { code: text, span: spanOf(t) };\n i += 1;\n continue;\n }\n\n // 温度/露点\n const tempParsed = (mask & M_TEMP) !== 0 ? parseTempDewToken(t) : null;\n if (tempParsed !== null) {\n // 重复组/物理极值门/缺测出声/温露倒挂等落位规则迁至 applyTempDewToken\n const applied = applyTempDewToken(t, tempParsed, { temperature, dewpoint }, raw, warnings);\n temperature = applied.temperature;\n dewpoint = applied.dewpoint;\n i += 1;\n continue;\n }\n\n // 气压:Q(hPa)/ A(inHg,隐含小数点);5 位数 QNH 与物理范围外值 = 脏值(Q10054 家族)\n const qnhParsed = (mask & M_QNH) !== 0 ? parseQnhToken(t) : null;\n if (qnhParsed !== null) {\n if (qnhParsed.kind === \"out-of-range\") {\n altimeter = undefined;\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: qnhParsed.message,\n span: qnhParsed.span,\n });\n } else {\n ({ altimeter, altimeterSeen } = applyAltimeterReading(\n altimeter,\n altimeterSeen,\n qnhParsed.reading,\n raw,\n warnings,\n ));\n }\n i += 1;\n continue;\n }\n const altAParsed = (mask & M_ALTIMETER_A) !== 0 ? parseAltimeterAToken(t) : null;\n if (altAParsed !== null) {\n if (altAParsed.kind === \"out-of-range\") {\n altimeter = undefined;\n warnings.push({\n code: \"value-out-of-range\",\n severity: \"warning\",\n message: altAParsed.message,\n span: altAParsed.span,\n });\n } else {\n ({ altimeter, altimeterSeen } = applyAltimeterReading(\n altimeter,\n altimeterSeen,\n altAParsed.reading,\n raw,\n warnings,\n ));\n }\n i += 1;\n continue;\n }\n\n // 变化能见度(FAA 正文位形态:主能见度组后跟「VIS 1/4V1/2」变化区间)——\n // IR 建模为 RemarkKind 'variable-visibility'(不占 visibility 槽),与 RMK 段同族同 kind\n if ((mask & M_VIS_RANGE) !== 0 && text === \"VIS\" && VIS_V_RANGE.test(peek(1)?.text ?? \"\")) {\n const nextTok = peek(1);\n if (nextTok !== undefined) {\n remarks.push({\n kind: \"variable-visibility\",\n raw: `${text} ${nextTok.text}`,\n span: { start: t.start, end: nextTok.end },\n });\n i += 2;\n continue;\n }\n }\n\n // 维护指示符(正文级孤例)\n if ((mask & M_DOLLAR) !== 0 && text === \"$\") {\n remarks.push({ kind: \"maintenance\", raw: \"$\", span: spanOf(t) });\n i += 1;\n continue;\n }\n\n // 不静默:看不懂的 token 进 warnings,绝不丢弃\n warnings.push({\n code: \"unknown-token\",\n severity: \"info\",\n message: `未识别的组(${text})——已如实收下`,\n span: spanOf(t),\n });\n i += 1;\n }\n\n // 当前天气组:仅有实组时给值;RE-only 报文 weather 保持 undefined(组省略 ≠ 缺测)——\n // 组级 span 首组至末组的收口规则迁至 observedWeatherOf\n weather = observedWeatherOf(weatherList) ?? weather;\n if (cloudSeen) {\n clouds = { elements: cloudElements, clear: clearCode };\n }\n\n // CAVOK 词后矛盾校验:词位让位后,其后新出现的能见度/天气/云组若与 CAVOK 语义确定矛盾,\n // 此前静默并存——同三面判据出声(趋势段已被围栏隔离,不会流入此处的正文状态)\n if (cavok) {\n cavokCrossCheck(\n { cavokSpan, visibility, weatherList, rvr, cloudElements },\n \"后续\",\n raw,\n warnings,\n );\n }\n\n // 云组自洽(WMO 15.9.2 / 15.9.1):VV 顶替整个云组、NSC/SKC/NCD/CLR 为无云电码——\n // 与层组并存均互斥矛盾形态,出声不静默(规范外容错照旧收下)\n const hasVvElement = cloudElements.some((e) => e.kind === \"vertical-visibility\");\n const hasLayerElement = cloudElements.some((e) => e.kind === \"layer\");\n if (hasVvElement && hasLayerElement) {\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: \"VV 组与云层组并存(WMO 15.9.2:VV 顶替整个云组)——报文自洽性存疑\",\n span: cloudElements[0]?.span,\n });\n }\n if (clearCode !== undefined && hasLayerElement) {\n warnings.push({\n code: \"cross-check-conflict\",\n severity: \"warning\",\n message: `${clearCode.code}(无云电码)与云层组并存——互斥形态,报文自洽性存疑`,\n span: clearCode.span,\n });\n }\n\n // —— RMK 段(认组粒度;未知 ≠ 错误,不进 warnings)——段循环整体迁至 parseRemarkSegment\n const rmk = parseRemarkSegment(tokens, i, raw, remarks, warnings, rvr);\n rvr = rmk.rvr;\n\n return compactIfEnabled({\n kind,\n raw,\n station,\n time,\n flags: { auto, corrected },\n cavok,\n cavokSpan,\n wind,\n visibility,\n runwayVisualRange: rvr,\n weather,\n recentWeather: recentList.length > 0 ? recentList : undefined,\n clouds,\n temperature,\n dewpoint,\n altimeter,\n seaLevelPressure: undefined,\n trends,\n runwayStates,\n windShear,\n remarks,\n warnings,\n });\n}\n\n/** Result-style parse outcome: never throws for parse-level failures — branch on `ok` instead of try/catch.\n * 结果式解析出口:解析层失败不抛出,按 ok 分流——批量回放/管道消费免 try/catch 控制流。 */\nexport type TryParseResult =\n | { readonly ok: true; readonly report: MetarReport }\n | { readonly ok: false; readonly error: MetarParseError };\n\n/**\n * `parse` 的问题式变体:整体失败返回 `{ ok:false, error }`(MetarParseError,code 契约同 parse),\n * 成功返回 `{ ok:true, report }`。仅编程性意外(非 MetarParseError 的内部异常)原样抛出——\n * 不吞实现缺陷。语义与 parse 完全一致(同一实现,确定性继承)。\n * Result-style variant of `parse`: whole-report failures come back as `{ ok:false, error }`\n * with the same stable `code` contract; unexpected non-MetarParseError exceptions still throw.\n */\nexport function tryParse(raw: string, options?: ParseOptions): TryParseResult {\n try {\n return { ok: true, report: parse(raw, options) };\n } catch (err) {\n if (err instanceof MetarParseError) return { ok: false, error: err };\n throw err;\n }\n}\n"],"mappings":"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"}
|