formal-ai 0.178.0

Formal symbolic AI implementation with OpenAI-compatible APIs
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076
9077
9078
9079
9080
9081
9082
9083
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
9120
9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143
9144
9145
9146
9147
9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211
9212
9213
9214
9215
9216
9217
9218
9219
9220
9221
9222
9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359
9360
9361
9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474
9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
9524
9525
9526
9527
9528
9529
9530
9531
9532
9533
9534
9535
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548
9549
9550
9551
9552
9553
9554
9555
9556
9557
9558
9559
9560
9561
9562
9563
9564
9565
9566
9567
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919
9920
9921
9922
9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
9960
9961
9962
9963
9964
9965
9966
9967
9968
9969
9970
9971
9972
9973
9974
9975
9976
9977
9978
9979
9980
9981
9982
9983
9984
9985
9986
9987
9988
9989
9990
9991
9992
9993
9994
9995
9996
9997
9998
9999
10000
10001
10002
10003
10004
10005
10006
10007
10008
10009
10010
10011
10012
10013
10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130
10131
10132
10133
10134
10135
10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
10207
10208
10209
10210
10211
10212
10213
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254
10255
10256
10257
10258
10259
10260
10261
10262
10263
10264
10265
10266
10267
10268
10269
10270
10271
10272
10273
10274
10275
10276
10277
10278
10279
10280
10281
10282
10283
10284
10285
10286
10287
10288
10289
10290
10291
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309
10310
10311
10312
10313
10314
10315
10316
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330
10331
10332
10333
10334
10335
10336
10337
10338
10339
10340
10341
10342
10343
10344
10345
10346
10347
10348
10349
10350
10351
10352
10353
10354
10355
10356
10357
10358
10359
10360
10361
10362
10363
10364
10365
10366
10367
10368
10369
10370
10371
10372
10373
10374
10375
10376
10377
10378
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417
10418
10419
10420
10421
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481
10482
10483
10484
10485
10486
10487
10488
10489
10490
10491
10492
10493
10494
10495
10496
10497
10498
10499
10500
10501
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
10529
10530
10531
10532
10533
10534
10535
10536
10537
10538
10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551
10552
10553
10554
10555
10556
10557
10558
10559
10560
10561
10562
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584
10585
10586
10587
10588
10589
10590
10591
10592
10593
10594
10595
10596
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606
10607
10608
10609
10610
10611
10612
10613
10614
10615
10616
10617
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634
10635
10636
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646
10647
10648
10649
10650
10651
10652
10653
10654
10655
10656
10657
10658
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680
10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741
10742
10743
10744
10745
10746
10747
10748
10749
10750
10751
10752
10753
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765
10766
10767
10768
10769
10770
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790
10791
10792
10793
10794
10795
10796
10797
10798
10799
10800
10801
10802
10803
10804
10805
10806
10807
10808
10809
10810
10811
10812
10813
10814
10815
10816
10817
10818
10819
10820
10821
10822
10823
10824
10825
10826
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875
10876
10877
10878
10879
10880
10881
10882
10883
10884
10885
10886
10887
10888
10889
10890
10891
10892
10893
10894
10895
10896
10897
10898
10899
10900
10901
10902
10903
10904
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921
10922
10923
10924
10925
10926
10927
10928
10929
10930
10931
10932
10933
10934
10935
10936
10937
10938
10939
10940
10941
10942
10943
10944
10945
10946
10947
10948
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958
10959
10960
10961
10962
10963
10964
10965
10966
10967
10968
10969
10970
10971
10972
10973
10974
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014
11015
11016
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074
11075
11076
11077
11078
11079
11080
11081
11082
11083
11084
11085
11086
11087
11088
11089
11090
11091
11092
11093
11094
11095
11096
11097
11098
11099
11100
11101
11102
11103
11104
11105
11106
11107
11108
11109
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119
11120
11121
11122
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132
11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143
11144
11145
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157
11158
11159
11160
11161
11162
11163
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183
11184
11185
11186
11187
11188
11189
11190
11191
11192
11193
11194
11195
11196
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
11212
11213
11214
11215
11216
11217
11218
11219
11220
11221
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248
11249
11250
11251
11252
11253
11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274
11275
11276
11277
11278
11279
11280
11281
11282
11283
11284
11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349
11350
11351
11352
11353
11354
11355
11356
11357
11358
11359
11360
11361
11362
11363
11364
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
11380
11381
11382
11383
11384
11385
11386
11387
11388
11389
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405
11406
11407
11408
11409
11410
11411
11412
11413
11414
11415
11416
11417
11418
11419
11420
11421
11422
11423
11424
11425
11426
11427
11428
11429
11430
11431
11432
11433
11434
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445
11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456
11457
11458
11459
11460
11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471
11472
11473
11474
11475
11476
11477
11478
11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498
11499
11500
11501
11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519
11520
11521
11522
11523
11524
11525
11526
11527
11528
11529
11530
11531
11532
11533
11534
11535
11536
11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619
11620
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633
11634
11635
11636
11637
11638
11639
11640
11641
11642
11643
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654
11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694
11695
11696
11697
11698
11699
11700
11701
11702
11703
11704
11705
11706
11707
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
11726
11727
11728
11729
11730
11731
11732
11733
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751
11752
11753
11754
11755
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770
11771
11772
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784
11785
11786
11787
11788
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11822
11823
11824
11825
11826
11827
11828
11829
11830
11831
11832
11833
11834
11835
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846
11847
11848
11849
11850
11851
11852
11853
11854
11855
11856
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912
11913
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924
11925
11926
11927
11928
11929
11930
11931
11932
11933
11934
11935
11936
11937
11938
11939
11940
11941
11942
11943
11944
11945
11946
11947
11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
11973
11974
11975
11976
11977
11978
11979
11980
11981
11982
11983
11984
11985
11986
11987
11988
11989
11990
11991
11992
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002
12003
12004
12005
12006
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028
12029
12030
12031
12032
12033
12034
12035
12036
12037
12038
12039
12040
12041
12042
12043
12044
12045
12046
12047
12048
12049
12050
12051
12052
12053
12054
12055
12056
12057
12058
12059
12060
12061
12062
12063
12064
12065
12066
12067
12068
12069
12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148
12149
12150
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207
12208
12209
12210
12211
12212
12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333
12334
12335
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
12400
12401
12402
12403
12404
12405
12406
12407
12408
12409
12410
12411
12412
12413
12414
12415
12416
12417
12418
12419
12420
12421
12422
12423
12424
12425
12426
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483
12484
12485
12486
12487
12488
12489
12490
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501
12502
12503
12504
12505
12506
12507
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518
12519
12520
12521
12522
12523
12524
12525
12526
12527
12528
12529
12530
12531
12532
12533
12534
12535
12536
12537
12538
12539
12540
12541
12542
12543
12544
12545
12546
12547
12548
12549
12550
12551
12552
12553
12554
12555
12556
12557
12558
12559
12560
12561
12562
12563
12564
12565
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
12577
12578
12579
12580
12581
12582
12583
12584
12585
12586
12587
12588
12589
12590
12591
12592
12593
12594
12595
12596
12597
12598
12599
12600
12601
12602
12603
12604
12605
12606
12607
12608
12609
12610
12611
12612
12613
12614
12615
12616
12617
12618
12619
12620
12621
12622
12623
12624
12625
12626
12627
12628
12629
12630
12631
12632
12633
12634
12635
12636
12637
12638
12639
12640
12641
12642
12643
12644
12645
12646
12647
12648
12649
12650
12651
12652
12653
12654
12655
12656
12657
12658
12659
12660
12661
12662
12663
12664
12665
12666
12667
12668
12669
12670
12671
12672
12673
12674
12675
12676
12677
12678
12679
12680
12681
12682
12683
12684
12685
12686
12687
12688
12689
12690
12691
12692
12693
12694
12695
12696
12697
12698
12699
12700
12701
12702
12703
12704
12705
12706
12707
12708
12709
12710
12711
12712
12713
12714
12715
12716
12717
12718
12719
12720
12721
12722
12723
12724
12725
12726
12727
12728
12729
12730
12731
12732
12733
12734
12735
12736
12737
12738
12739
12740
12741
12742
12743
12744
12745
12746
12747
12748
12749
12750
12751
12752
12753
12754
12755
12756
12757
12758
12759
12760
12761
12762
12763
12764
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781
12782
12783
12784
12785
12786
12787
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797
12798
12799
12800
12801
12802
12803
12804
12805
12806
12807
12808
12809
12810
12811
12812
12813
12814
12815
12816
12817
12818
12819
12820
12821
12822
12823
12824
12825
12826
12827
12828
12829
12830
12831
12832
12833
12834
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845
12846
12847
12848
12849
12850
12851
12852
12853
12854
12855
12856
12857
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868
12869
12870
12871
12872
12873
12874
12875
12876
12877
12878
12879
12880
12881
12882
12883
12884
12885
12886
12887
12888
12889
12890
12891
12892
12893
12894
12895
12896
12897
12898
12899
12900
12901
12902
12903
12904
12905
12906
12907
12908
12909
12910
12911
12912
12913
12914
12915
12916
12917
12918
12919
12920
12921
12922
12923
12924
12925
12926
12927
12928
12929
12930
12931
12932
12933
12934
12935
12936
12937
12938
12939
12940
12941
12942
12943
12944
12945
12946
12947
12948
12949
12950
12951
12952
12953
12954
12955
12956
12957
12958
12959
12960
12961
12962
12963
12964
12965
12966
12967
12968
12969
12970
12971
12972
12973
12974
12975
12976
12977
12978
12979
12980
12981
12982
12983
12984
12985
12986
12987
12988
12989
12990
12991
12992
12993
12994
12995
12996
12997
12998
12999
13000
13001
13002
13003
13004
13005
13006
13007
13008
13009
13010
13011
13012
13013
13014
13015
13016
13017
13018
13019
13020
13021
13022
13023
13024
13025
13026
13027
13028
13029
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042
13043
13044
13045
13046
13047
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106
13107
13108
13109
13110
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124
13125
13126
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136
13137
13138
13139
13140
13141
13142
13143
13144
13145
13146
13147
13148
13149
13150
13151
13152
13153
13154
13155
13156
13157
13158
13159
13160
13161
13162
13163
13164
13165
13166
13167
13168
13169
13170
13171
13172
13173
13174
13175
13176
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186
13187
13188
13189
13190
13191
13192
13193
13194
13195
13196
13197
13198
13199
13200
13201
13202
13203
13204
13205
13206
13207
13208
13209
13210
13211
13212
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223
13224
13225
13226
13227
13228
13229
13230
13231
13232
13233
13234
13235
13236
13237
13238
13239
13240
13241
13242
13243
13244
13245
13246
13247
13248
13249
13250
13251
13252
13253
13254
13255
13256
13257
13258
13259
13260
13261
13262
13263
13264
13265
13266
13267
13268
13269
13270
13271
13272
13273
13274
13275
13276
13277
13278
13279
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289
13290
13291
13292
13293
13294
13295
13296
13297
13298
13299
13300
13301
13302
13303
13304
13305
13306
13307
13308
13309
13310
13311
13312
13313
13314
13315
13316
13317
13318
13319
13320
13321
13322
13323
13324
13325
13326
13327
13328
13329
13330
13331
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355
13356
13357
13358
13359
13360
13361
13362
13363
13364
13365
13366
13367
13368
13369
13370
13371
13372
13373
13374
13375
13376
13377
13378
13379
13380
13381
13382
13383
13384
13385
13386
13387
13388
13389
13390
13391
13392
13393
13394
13395
13396
13397
13398
13399
13400
13401
13402
13403
13404
13405
13406
13407
13408
13409
13410
13411
13412
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433
13434
13435
13436
13437
13438
13439
13440
13441
13442
13443
13444
13445
13446
13447
13448
13449
13450
13451
13452
13453
13454
13455
13456
13457
13458
13459
13460
13461
13462
13463
13464
13465
13466
13467
13468
13469
13470
13471
13472
13473
13474
13475
13476
13477
13478
13479
13480
13481
13482
13483
13484
13485
13486
13487
13488
13489
13490
13491
13492
13493
13494
13495
13496
13497
13498
13499
13500
13501
13502
13503
13504
13505
13506
13507
13508
13509
13510
13511
13512
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13529
13530
13531
13532
13533
13534
13535
13536
13537
13538
13539
13540
13541
13542
13543
13544
13545
13546
13547
13548
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561
13562
13563
13564
13565
13566
13567
13568
13569
13570
13571
13572
13573
13574
13575
13576
13577
13578
13579
13580
13581
13582
13583
13584
13585
13586
13587
13588
13589
13590
13591
13592
13593
13594
13595
13596
13597
13598
13599
13600
13601
13602
13603
13604
13605
13606
13607
13608
13609
13610
13611
13612
13613
13614
13615
13616
13617
13618
13619
13620
13621
13622
13623
13624
13625
13626
13627
13628
13629
13630
13631
13632
13633
13634
13635
13636
13637
13638
13639
13640
13641
13642
13643
13644
13645
13646
13647
13648
13649
13650
13651
13652
13653
13654
13655
13656
13657
13658
13659
13660
13661
13662
13663
13664
13665
13666
13667
13668
13669
13670
13671
13672
13673
13674
13675
13676
13677
13678
13679
13680
13681
13682
13683
13684
13685
13686
13687
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697
13698
13699
13700
13701
13702
13703
13704
13705
13706
13707
13708
13709
13710
13711
13712
13713
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748
13749
13750
13751
13752
13753
13754
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765
13766
13767
13768
13769
13770
13771
13772
13773
13774
13775
13776
13777
13778
13779
13780
13781
13782
13783
13784
13785
13786
13787
13788
13789
13790
13791
13792
13793
13794
13795
13796
13797
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810
13811
13812
13813
13814
13815
13816
13817
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837
13838
13839
13840
13841
13842
13843
13844
13845
13846
13847
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859
13860
13861
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874
13875
13876
13877
13878
13879
13880
13881
13882
13883
13884
13885
13886
13887
13888
13889
13890
13891
13892
13893
13894
13895
13896
13897
13898
13899
13900
13901
13902
13903
13904
13905
13906
13907
13908
13909
13910
13911
13912
13913
13914
13915
13916
13917
13918
13919
13920
13921
13922
13923
13924
13925
13926
13927
13928
13929
13930
13931
13932
13933
13934
13935
13936
13937
13938
13939
13940
13941
13942
13943
13944
13945
13946
13947
13948
13949
13950
13951
13952
13953
13954
13955
13956
13957
13958
13959
13960
13961
13962
13963
13964
13965
13966
13967
13968
13969
13970
13971
13972
13973
13974
13975
13976
13977
13978
13979
13980
13981
13982
13983
13984
13985
13986
13987
13988
13989
13990
13991
13992
13993
13994
13995
13996
13997
13998
13999
14000
14001
14002
14003
14004
14005
14006
14007
14008
14009
14010
14011
14012
14013
14014
14015
14016
14017
14018
14019
14020
14021
14022
14023
14024
14025
14026
14027
14028
14029
14030
14031
14032
14033
14034
14035
14036
14037
14038
14039
14040
14041
14042
14043
14044
14045
14046
14047
14048
14049
14050
14051
14052
14053
14054
14055
14056
14057
14058
14059
14060
14061
14062
14063
14064
14065
14066
14067
14068
14069
14070
14071
14072
14073
14074
14075
14076
14077
14078
14079
14080
14081
14082
14083
14084
14085
14086
14087
14088
14089
14090
14091
14092
14093
14094
14095
14096
14097
14098
14099
14100
14101
14102
14103
14104
14105
14106
14107
14108
14109
14110
14111
14112
14113
14114
14115
14116
14117
14118
14119
14120
14121
14122
14123
14124
14125
14126
14127
14128
14129
14130
14131
14132
14133
14134
14135
14136
14137
14138
14139
14140
14141
14142
14143
14144
14145
14146
14147
14148
14149
14150
14151
14152
14153
14154
14155
14156
14157
14158
14159
14160
14161
14162
14163
14164
14165
14166
14167
14168
14169
14170
14171
14172
14173
14174
14175
14176
14177
14178
14179
14180
14181
14182
14183
14184
14185
14186
14187
14188
14189
14190
14191
14192
14193
14194
14195
14196
14197
14198
14199
14200
14201
14202
14203
14204
14205
14206
14207
14208
14209
14210
14211
14212
14213
14214
14215
14216
14217
14218
14219
14220
14221
14222
14223
14224
14225
14226
14227
14228
14229
14230
14231
14232
14233
14234
14235
14236
14237
14238
14239
14240
14241
14242
14243
14244
14245
14246
14247
14248
14249
14250
14251
14252
14253
14254
14255
14256
14257
14258
14259
14260
14261
14262
14263
14264
14265
14266
14267
14268
14269
14270
14271
14272
14273
14274
14275
14276
14277
14278
14279
14280
14281
14282
14283
14284
14285
14286
14287
14288
14289
14290
14291
14292
14293
14294
14295
14296
14297
14298
14299
14300
14301
14302
14303
14304
14305
14306
14307
14308
14309
14310
14311
14312
14313
14314
14315
14316
14317
14318
14319
14320
14321
14322
14323
14324
14325
14326
14327
14328
14329
14330
14331
14332
14333
14334
14335
14336
14337
14338
14339
14340
14341
14342
14343
14344
14345
14346
14347
14348
14349
14350
14351
14352
14353
14354
14355
14356
14357
14358
14359
14360
14361
14362
14363
14364
14365
14366
14367
14368
14369
14370
14371
14372
14373
14374
14375
14376
14377
14378
14379
14380
14381
14382
14383
14384
14385
14386
14387
14388
14389
14390
14391
14392
14393
14394
14395
14396
14397
14398
14399
14400
14401
14402
14403
14404
14405
14406
14407
14408
14409
14410
14411
14412
14413
14414
14415
14416
14417
14418
14419
14420
14421
14422
14423
14424
14425
14426
14427
14428
14429
14430
14431
14432
14433
14434
14435
14436
14437
14438
14439
14440
14441
14442
14443
14444
14445
14446
14447
14448
14449
14450
14451
14452
14453
14454
14455
14456
14457
14458
14459
14460
14461
14462
14463
14464
14465
14466
14467
14468
14469
14470
14471
14472
14473
14474
14475
14476
14477
14478
14479
14480
14481
14482
14483
14484
14485
14486
14487
14488
14489
14490
14491
14492
14493
14494
14495
14496
14497
14498
14499
14500
14501
14502
14503
14504
14505
14506
14507
14508
14509
14510
14511
14512
14513
14514
14515
14516
14517
14518
14519
14520
14521
14522
14523
14524
14525
14526
14527
14528
14529
14530
14531
14532
14533
14534
14535
14536
14537
14538
14539
14540
14541
14542
14543
14544
14545
14546
14547
14548
14549
14550
14551
14552
14553
14554
14555
14556
14557
14558
14559
14560
14561
14562
14563
14564
14565
14566
14567
14568
14569
14570
14571
14572
14573
14574
14575
14576
14577
14578
14579
14580
14581
14582
14583
14584
14585
14586
14587
14588
14589
14590
14591
14592
14593
14594
14595
14596
14597
14598
14599
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619
14620
14621
14622
14623
14624
14625
14626
14627
14628
14629
14630
14631
14632
14633
14634
14635
14636
14637
14638
14639
14640
14641
14642
14643
14644
14645
14646
14647
14648
14649
14650
14651
14652
14653
14654
14655
14656
14657
14658
14659
14660
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670
14671
14672
14673
14674
14675
14676
14677
14678
14679
14680
14681
14682
14683
14684
14685
14686
14687
14688
14689
14690
14691
14692
14693
14694
14695
14696
14697
14698
14699
14700
14701
14702
14703
14704
14705
14706
14707
14708
14709
14710
14711
14712
14713
14714
14715
14716
14717
14718
14719
14720
14721
14722
14723
14724
14725
14726
14727
14728
14729
14730
14731
14732
14733
14734
14735
14736
14737
14738
14739
14740
14741
14742
14743
14744
14745
14746
14747
14748
14749
14750
14751
14752
14753
14754
14755
14756
14757
14758
14759
14760
14761
14762
14763
14764
14765
14766
14767
14768
14769
14770
14771
14772
14773
14774
14775
14776
14777
14778
14779
14780
14781
14782
14783
14784
14785
14786
14787
14788
14789
14790
14791
14792
14793
14794
14795
14796
14797
14798
14799
14800
14801
14802
14803
14804
14805
14806
14807
14808
14809
14810
14811
14812
14813
14814
14815
14816
14817
14818
14819
14820
14821
14822
14823
14824
14825
14826
14827
14828
14829
14830
14831
14832
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14843
14844
14845
14846
14847
14848
14849
14850
14851
14852
14853
14854
14855
14856
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866
14867
14868
14869
14870
14871
14872
14873
14874
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
14889
14890
14891
14892
14893
14894
14895
14896
14897
14898
14899
14900
14901
14902
14903
14904
14905
14906
14907
14908
14909
14910
14911
14912
14913
14914
14915
14916
14917
14918
14919
14920
14921
14922
14923
14924
14925
14926
14927
14928
14929
14930
14931
14932
14933
14934
14935
14936
14937
14938
14939
14940
14941
14942
14943
14944
14945
14946
14947
14948
14949
14950
14951
14952
14953
14954
14955
14956
14957
14958
14959
14960
14961
14962
14963
14964
14965
14966
14967
14968
14969
14970
14971
14972
14973
14974
14975
14976
14977
14978
14979
14980
14981
14982
14983
14984
14985
14986
14987
14988
14989
14990
14991
14992
14993
14994
14995
14996
14997
14998
14999
15000
15001
15002
15003
15004
15005
15006
15007
15008
15009
15010
15011
15012
15013
15014
15015
15016
15017
15018
15019
15020
15021
15022
15023
15024
15025
15026
15027
15028
15029
15030
15031
15032
15033
15034
15035
15036
15037
15038
15039
15040
15041
15042
15043
15044
15045
15046
15047
15048
15049
15050
15051
15052
15053
15054
15055
15056
15057
15058
15059
15060
15061
15062
15063
15064
15065
15066
15067
15068
15069
15070
15071
15072
15073
15074
15075
15076
15077
15078
15079
15080
15081
15082
15083
15084
15085
15086
15087
15088
15089
15090
15091
15092
15093
15094
15095
15096
15097
15098
15099
15100
15101
15102
15103
15104
15105
15106
15107
15108
15109
15110
15111
15112
15113
15114
15115
15116
15117
15118
15119
15120
15121
15122
15123
15124
15125
15126
15127
15128
15129
15130
15131
15132
15133
15134
15135
15136
15137
15138
15139
15140
15141
15142
15143
15144
15145
15146
15147
15148
15149
15150
15151
15152
15153
15154
15155
15156
15157
15158
15159
15160
15161
15162
15163
15164
15165
15166
15167
15168
15169
15170
15171
15172
15173
15174
15175
15176
15177
15178
15179
15180
15181
15182
15183
15184
15185
15186
15187
15188
15189
15190
15191
15192
15193
15194
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205
15206
15207
15208
15209
15210
15211
15212
15213
15214
15215
15216
15217
15218
15219
15220
15221
15222
15223
15224
15225
15226
15227
15228
15229
15230
15231
15232
15233
15234
15235
15236
15237
15238
15239
15240
15241
15242
15243
15244
15245
15246
15247
15248
15249
15250
15251
15252
15253
15254
15255
15256
15257
15258
15259
15260
15261
15262
15263
15264
15265
15266
15267
15268
15269
15270
15271
15272
15273
15274
15275
15276
15277
15278
15279
15280
15281
15282
15283
15284
15285
15286
15287
15288
15289
15290
15291
15292
15293
15294
15295
15296
15297
15298
15299
15300
15301
15302
15303
15304
15305
15306
15307
15308
15309
15310
15311
15312
15313
15314
15315
15316
15317
15318
15319
15320
15321
15322
15323
15324
15325
15326
15327
15328
15329
15330
15331
15332
15333
15334
15335
15336
15337
15338
15339
15340
15341
15342
15343
15344
15345
15346
15347
15348
15349
15350
15351
15352
15353
15354
15355
15356
15357
15358
15359
15360
15361
15362
15363
15364
15365
15366
15367
15368
15369
15370
15371
15372
15373
15374
15375
15376
15377
15378
15379
15380
15381
15382
15383
15384
15385
15386
15387
15388
15389
15390
15391
15392
15393
15394
15395
15396
15397
15398
15399
15400
15401
15402
15403
15404
15405
15406
15407
15408
15409
15410
15411
15412
15413
15414
15415
15416
15417
15418
15419
15420
15421
15422
15423
15424
15425
15426
15427
15428
15429
15430
15431
15432
15433
15434
15435
15436
15437
15438
15439
15440
15441
15442
15443
15444
15445
15446
15447
15448
15449
15450
15451
15452
15453
15454
15455
15456
15457
15458
15459
15460
15461
15462
15463
15464
15465
15466
15467
15468
15469
15470
15471
15472
15473
15474
15475
15476
15477
15478
15479
15480
15481
15482
15483
15484
15485
15486
15487
15488
15489
15490
15491
15492
15493
15494
15495
15496
15497
15498
15499
15500
15501
15502
15503
15504
15505
15506
15507
15508
15509
15510
15511
15512
15513
15514
15515
15516
15517
15518
15519
15520
15521
15522
15523
15524
15525
15526
15527
15528
15529
15530
15531
15532
15533
15534
15535
15536
15537
15538
15539
15540
15541
15542
15543
15544
15545
15546
15547
15548
15549
15550
15551
15552
15553
15554
15555
15556
15557
15558
15559
15560
15561
15562
15563
15564
15565
15566
15567
15568
15569
15570
15571
15572
15573
15574
15575
15576
15577
15578
15579
15580
15581
15582
15583
15584
15585
15586
15587
15588
15589
15590
15591
15592
15593
15594
15595
15596
15597
15598
15599
15600
15601
15602
15603
15604
15605
15606
15607
15608
15609
15610
15611
15612
15613
15614
15615
15616
15617
15618
15619
15620
15621
15622
15623
15624
15625
15626
15627
15628
15629
15630
15631
15632
15633
15634
15635
15636
15637
15638
15639
15640
15641
15642
15643
15644
15645
15646
15647
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657
15658
15659
15660
15661
15662
15663
15664
15665
15666
15667
15668
15669
15670
15671
15672
15673
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684
15685
15686
15687
15688
15689
15690
15691
15692
15693
15694
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704
15705
15706
15707
15708
15709
15710
15711
15712
15713
15714
15715
15716
15717
15718
15719
15720
15721
15722
15723
15724
15725
15726
15727
15728
15729
15730
15731
15732
15733
15734
15735
15736
15737
15738
15739
15740
15741
15742
15743
15744
15745
15746
15747
15748
15749
15750
15751
15752
15753
15754
15755
15756
15757
15758
15759
15760
15761
15762
15763
15764
15765
15766
15767
15768
15769
15770
15771
15772
15773
15774
15775
15776
15777
15778
15779
15780
15781
15782
15783
15784
15785
15786
15787
15788
15789
15790
15791
15792
15793
15794
15795
15796
15797
15798
15799
15800
15801
15802
15803
15804
15805
15806
15807
15808
15809
15810
15811
15812
15813
15814
15815
15816
15817
15818
15819
15820
15821
15822
15823
15824
15825
15826
15827
15828
15829
15830
15831
15832
15833
15834
15835
15836
15837
15838
15839
15840
15841
15842
15843
15844
15845
15846
15847
15848
15849
15850
15851
15852
15853
15854
15855
15856
15857
15858
15859
15860
15861
15862
15863
15864
15865
15866
15867
15868
15869
15870
15871
15872
15873
15874
15875
15876
15877
15878
15879
15880
15881
15882
15883
15884
15885
15886
15887
15888
15889
15890
15891
15892
15893
15894
15895
15896
15897
15898
15899
15900
15901
15902
15903
15904
15905
15906
15907
15908
15909
15910
15911
15912
15913
15914
15915
15916
15917
15918
15919
15920
15921
15922
15923
15924
15925
15926
15927
15928
15929
15930
15931
15932
15933
15934
15935
15936
15937
15938
15939
15940
15941
15942
15943
15944
15945
15946
15947
15948
15949
15950
15951
15952
15953
15954
15955
15956
15957
15958
15959
15960
15961
15962
15963
15964
15965
15966
15967
15968
15969
15970
15971
15972
15973
15974
15975
15976
15977
15978
15979
15980
15981
15982
15983
15984
15985
15986
15987
15988
15989
15990
15991
15992
15993
15994
15995
15996
15997
15998
15999
16000
16001
16002
16003
16004
16005
16006
16007
16008
16009
16010
16011
16012
16013
16014
16015
16016
16017
16018
16019
16020
16021
16022
16023
16024
16025
16026
16027
16028
16029
16030
16031
16032
16033
16034
16035
16036
16037
16038
16039
16040
16041
16042
16043
16044
16045
16046
16047
16048
16049
16050
16051
16052
16053
16054
16055
16056
16057
16058
16059
16060
16061
16062
16063
16064
16065
16066
16067
16068
16069
16070
16071
16072
16073
16074
16075
16076
16077
16078
16079
16080
16081
16082
16083
16084
16085
16086
16087
16088
16089
16090
16091
16092
16093
16094
16095
16096
16097
16098
16099
16100
16101
16102
16103
16104
16105
16106
16107
16108
16109
16110
16111
16112
16113
16114
16115
16116
16117
16118
16119
16120
16121
16122
16123
16124
16125
16126
16127
16128
16129
16130
16131
16132
16133
16134
16135
16136
16137
16138
16139
16140
16141
16142
16143
16144
16145
16146
16147
16148
16149
16150
16151
16152
16153
16154
16155
16156
16157
16158
16159
16160
16161
16162
16163
16164
16165
16166
16167
16168
16169
16170
16171
16172
16173
16174
16175
16176
16177
16178
16179
16180
16181
16182
16183
16184
16185
16186
16187
16188
16189
16190
16191
16192
16193
16194
16195
16196
16197
16198
16199
16200
16201
16202
16203
16204
16205
16206
16207
16208
16209
16210
16211
16212
16213
16214
16215
16216
16217
16218
16219
16220
16221
16222
16223
16224
16225
16226
16227
16228
16229
16230
16231
16232
16233
16234
16235
16236
16237
16238
16239
16240
16241
16242
16243
16244
16245
16246
16247
16248
16249
16250
16251
16252
16253
16254
16255
16256
16257
16258
16259
16260
16261
16262
16263
16264
16265
16266
16267
16268
16269
16270
16271
16272
16273
16274
16275
16276
16277
16278
16279
16280
16281
16282
16283
16284
16285
16286
16287
16288
16289
16290
16291
16292
16293
16294
16295
16296
16297
16298
16299
16300
16301
16302
16303
16304
16305
16306
16307
16308
16309
16310
16311
16312
16313
16314
16315
16316
16317
16318
16319
16320
16321
16322
16323
16324
16325
16326
16327
16328
16329
16330
16331
16332
16333
16334
16335
16336
16337
16338
16339
16340
16341
16342
16343
16344
16345
16346
16347
16348
16349
16350
16351
16352
16353
16354
16355
16356
16357
16358
16359
16360
16361
16362
16363
16364
16365
16366
16367
16368
16369
16370
16371
16372
16373
16374
16375
16376
16377
16378
16379
16380
16381
16382
16383
16384
16385
16386
16387
16388
16389
16390
16391
16392
16393
16394
16395
16396
16397
16398
16399
16400
16401
16402
16403
16404
16405
16406
16407
16408
16409
16410
16411
16412
16413
16414
16415
16416
16417
16418
16419
16420
16421
16422
16423
16424
16425
16426
16427
16428
16429
16430
16431
16432
16433
16434
16435
16436
16437
16438
16439
16440
16441
16442
16443
16444
16445
16446
16447
16448
16449
16450
16451
16452
16453
16454
16455
16456
16457
16458
16459
16460
16461
16462
16463
16464
16465
16466
16467
16468
16469
16470
16471
16472
16473
16474
16475
16476
16477
16478
16479
16480
16481
16482
16483
16484
16485
16486
16487
16488
16489
16490
16491
16492
16493
16494
16495
16496
16497
16498
16499
16500
16501
16502
16503
16504
16505
16506
16507
16508
16509
16510
16511
16512
16513
16514
16515
16516
16517
16518
16519
16520
16521
16522
16523
16524
16525
16526
16527
16528
16529
16530
16531
16532
16533
16534
16535
16536
16537
16538
16539
16540
16541
16542
16543
16544
16545
16546
16547
16548
16549
16550
16551
16552
16553
16554
16555
16556
16557
16558
16559
16560
16561
16562
16563
16564
16565
16566
16567
16568
16569
16570
16571
16572
16573
16574
16575
16576
16577
16578
16579
16580
16581
16582
16583
16584
16585
16586
16587
16588
16589
16590
16591
16592
16593
16594
16595
16596
16597
16598
16599
16600
16601
16602
16603
16604
16605
16606
16607
16608
16609
16610
16611
16612
16613
16614
16615
16616
16617
16618
16619
16620
16621
16622
16623
16624
16625
16626
16627
16628
16629
16630
16631
16632
16633
16634
16635
16636
16637
16638
16639
16640
16641
16642
16643
16644
16645
16646
16647
16648
16649
16650
16651
16652
16653
16654
16655
16656
16657
16658
16659
16660
16661
16662
16663
16664
16665
16666
16667
16668
16669
16670
16671
16672
16673
16674
16675
16676
16677
16678
16679
16680
16681
16682
16683
16684
16685
16686
16687
16688
16689
16690
16691
16692
16693
16694
16695
16696
16697
16698
16699
16700
16701
16702
16703
16704
16705
16706
16707
16708
16709
16710
16711
16712
16713
16714
16715
16716
16717
16718
16719
16720
16721
16722
16723
16724
16725
16726
16727
16728
16729
16730
16731
16732
16733
16734
16735
16736
16737
16738
16739
16740
16741
16742
16743
16744
16745
16746
16747
16748
16749
16750
16751
16752
16753
16754
16755
16756
16757
16758
16759
16760
16761
16762
16763
16764
16765
16766
16767
16768
16769
16770
16771
16772
16773
16774
16775
16776
16777
16778
16779
16780
16781
16782
16783
16784
16785
16786
16787
16788
16789
16790
16791
16792
16793
16794
16795
16796
16797
16798
16799
16800
16801
16802
16803
16804
16805
16806
16807
16808
16809
16810
16811
16812
16813
16814
16815
16816
16817
16818
16819
16820
16821
16822
16823
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833
16834
16835
16836
16837
16838
16839
16840
16841
16842
16843
16844
16845
16846
16847
16848
16849
16850
16851
16852
16853
16854
16855
16856
16857
16858
16859
16860
16861
16862
16863
16864
16865
16866
16867
16868
16869
16870
16871
16872
16873
16874
16875
16876
16877
16878
16879
16880
16881
16882
16883
16884
16885
16886
16887
16888
16889
16890
16891
16892
16893
16894
16895
16896
16897
16898
16899
16900
16901
16902
16903
16904
16905
16906
16907
16908
16909
16910
16911
16912
16913
16914
16915
16916
16917
16918
16919
16920
16921
16922
16923
16924
16925
16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936
16937
16938
16939
16940
16941
16942
16943
16944
16945
16946
16947
16948
16949
16950
16951
16952
16953
16954
16955
16956
16957
16958
16959
16960
16961
16962
16963
16964
16965
16966
16967
16968
16969
16970
16971
16972
16973
16974
16975
16976
16977
16978
16979
16980
16981
16982
16983
16984
16985
16986
16987
16988
16989
16990
16991
16992
16993
16994
16995
16996
16997
16998
16999
17000
17001
17002
17003
17004
17005
17006
17007
17008
17009
17010
17011
17012
17013
17014
17015
17016
17017
17018
17019
17020
17021
17022
17023
17024
17025
17026
17027
17028
17029
17030
17031
17032
17033
17034
17035
17036
17037
17038
17039
17040
17041
17042
17043
17044
17045
17046
17047
17048
17049
17050
17051
17052
17053
17054
17055
17056
17057
17058
17059
17060
17061
17062
17063
17064
17065
17066
17067
17068
17069
17070
17071
17072
17073
17074
17075
17076
17077
17078
17079
17080
17081
17082
17083
17084
17085
17086
17087
17088
17089
17090
17091
17092
17093
17094
17095
17096
17097
17098
17099
17100
17101
17102
17103
17104
17105
17106
17107
17108
17109
17110
17111
17112
17113
17114
17115
17116
17117
17118
17119
17120
17121
17122
17123
17124
17125
17126
17127
17128
17129
17130
17131
17132
17133
17134
17135
17136
17137
17138
17139
17140
17141
17142
17143
17144
17145
17146
17147
17148
17149
17150
17151
17152
17153
17154
17155
17156
17157
17158
17159
17160
17161
17162
17163
17164
17165
17166
17167
17168
17169
17170
17171
17172
17173
17174
17175
17176
17177
17178
17179
17180
17181
17182
17183
17184
17185
17186
17187
17188
17189
17190
17191
17192
17193
17194
17195
17196
17197
17198
17199
17200
17201
17202
17203
17204
17205
17206
17207
17208
17209
17210
17211
17212
17213
17214
17215
17216
17217
17218
17219
17220
17221
17222
17223
17224
17225
17226
17227
17228
17229
17230
17231
17232
17233
17234
17235
17236
17237
17238
17239
17240
17241
17242
17243
17244
17245
17246
17247
17248
17249
17250
17251
17252
17253
17254
17255
17256
17257
17258
17259
17260
17261
17262
17263
17264
17265
17266
17267
17268
17269
17270
17271
17272
17273
17274
17275
17276
17277
17278
17279
17280
17281
17282
17283
17284
17285
17286
17287
17288
17289
17290
17291
17292
17293
17294
17295
17296
17297
17298
17299
17300
17301
17302
17303
17304
17305
17306
17307
17308
17309
17310
17311
17312
17313
17314
17315
17316
17317
17318
17319
17320
17321
17322
17323
17324
17325
17326
17327
17328
17329
17330
17331
17332
17333
17334
17335
17336
17337
17338
17339
17340
17341
17342
17343
17344
17345
17346
17347
17348
17349
17350
17351
17352
17353
17354
17355
17356
17357
17358
17359
17360
17361
17362
17363
17364
17365
17366
17367
17368
17369
17370
17371
17372
17373
17374
17375
17376
17377
17378
17379
17380
17381
17382
17383
17384
17385
17386
17387
17388
17389
17390
17391
17392
17393
17394
17395
17396
17397
17398
17399
17400
17401
17402
17403
17404
17405
17406
17407
17408
17409
17410
17411
17412
17413
17414
17415
17416
17417
17418
17419
17420
17421
17422
17423
17424
17425
17426
17427
17428
17429
17430
17431
17432
17433
17434
17435
17436
17437
17438
17439
17440
17441
17442
17443
17444
17445
17446
17447
17448
17449
17450
17451
17452
17453
17454
17455
17456
17457
17458
17459
17460
17461
17462
17463
17464
17465
17466
17467
17468
17469
17470
17471
17472
17473
17474
17475
17476
17477
17478
17479
17480
17481
17482
17483
17484
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494
17495
17496
17497
17498
17499
17500
17501
17502
17503
17504
17505
17506
17507
17508
17509
17510
17511
17512
17513
17514
17515
17516
17517
17518
17519
17520
17521
17522
17523
17524
17525
17526
17527
17528
17529
17530
17531
17532
17533
17534
17535
17536
17537
17538
17539
17540
17541
17542
17543
17544
17545
17546
17547
17548
17549
17550
17551
17552
17553
17554
17555
17556
17557
17558
17559
17560
17561
17562
17563
17564
17565
17566
17567
17568
17569
17570
17571
17572
17573
17574
17575
17576
17577
17578
17579
17580
17581
17582
17583
17584
17585
17586
17587
17588
17589
17590
17591
17592
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602
17603
17604
17605
17606
17607
17608
17609
17610
17611
17612
17613
17614
17615
17616
17617
17618
17619
17620
17621
17622
17623
17624
17625
17626
17627
17628
17629
17630
17631
17632
17633
17634
17635
17636
17637
17638
17639
17640
17641
17642
17643
17644
17645
17646
17647
17648
17649
17650
17651
17652
17653
17654
17655
17656
17657
17658
17659
17660
17661
17662
17663
17664
17665
17666
17667
17668
17669
17670
17671
17672
17673
17674
17675
17676
17677
17678
17679
17680
17681
17682
17683
17684
17685
17686
17687
17688
17689
17690
17691
17692
17693
17694
17695
17696
17697
17698
17699
17700
17701
17702
17703
17704
17705
17706
17707
17708
17709
17710
17711
17712
17713
17714
17715
17716
17717
17718
17719
17720
17721
17722
17723
17724
17725
17726
17727
17728
17729
17730
17731
17732
17733
17734
17735
17736
17737
17738
17739
17740
17741
17742
17743
17744
17745
17746
17747
17748
17749
17750
17751
17752
17753
17754
17755
17756
17757
17758
17759
17760
17761
17762
17763
17764
17765
17766
17767
17768
17769
17770
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789
17790
17791
17792
17793
17794
17795
17796
17797
17798
17799
17800
17801
17802
17803
17804
17805
17806
17807
17808
17809
17810
17811
17812
17813
17814
17815
17816
17817
17818
17819
17820
17821
17822
17823
17824
17825
17826
17827
17828
17829
17830
17831
17832
17833
17834
17835
17836
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846
17847
17848
17849
17850
17851
17852
17853
17854
17855
17856
17857
17858
17859
17860
17861
17862
17863
17864
17865
17866
17867
17868
17869
17870
17871
17872
17873
17874
17875
17876
17877
17878
17879
17880
17881
17882
17883
17884
17885
17886
17887
17888
17889
17890
17891
17892
17893
17894
17895
17896
17897
17898
17899
17900
17901
17902
17903
17904
17905
17906
17907
17908
17909
17910
17911
17912
17913
17914
17915
17916
17917
17918
17919
17920
17921
17922
17923
17924
17925
17926
17927
17928
17929
17930
17931
17932
17933
17934
17935
17936
17937
17938
17939
17940
17941
17942
17943
17944
17945
17946
17947
17948
17949
17950
17951
17952
17953
17954
17955
17956
17957
17958
17959
17960
17961
17962
17963
17964
17965
17966
17967
17968
17969
17970
17971
17972
17973
17974
17975
17976
17977
17978
17979
17980
17981
17982
17983
17984
17985
17986
17987
17988
17989
17990
17991
17992
17993
17994
17995
17996
17997
17998
17999
18000
18001
18002
18003
18004
18005
18006
18007
18008
18009
18010
18011
18012
18013
18014
18015
18016
18017
18018
18019
18020
18021
18022
18023
18024
18025
18026
18027
18028
18029
18030
18031
18032
18033
18034
18035
18036
18037
18038
18039
18040
18041
18042
18043
18044
18045
18046
18047
18048
18049
18050
18051
18052
18053
18054
18055
18056
18057
18058
18059
18060
18061
18062
18063
18064
18065
18066
18067
18068
18069
18070
18071
18072
18073
18074
18075
18076
18077
18078
18079
18080
18081
18082
18083
18084
18085
18086
18087
18088
18089
18090
18091
18092
18093
18094
18095
18096
18097
18098
18099
18100
18101
18102
18103
18104
18105
18106
18107
18108
18109
18110
18111
18112
18113
18114
18115
18116
18117
18118
18119
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130
18131
18132
18133
18134
18135
18136
18137
18138
18139
18140
18141
18142
18143
18144
18145
18146
18147
18148
18149
18150
18151
18152
18153
18154
18155
18156
18157
18158
18159
18160
18161
18162
18163
18164
18165
18166
18167
18168
18169
18170
18171
18172
18173
18174
18175
18176
18177
18178
18179
18180
18181
18182
18183
18184
18185
18186
18187
18188
18189
18190
18191
18192
18193
18194
18195
18196
18197
18198
18199
18200
18201
18202
18203
18204
18205
18206
18207
18208
18209
18210
18211
18212
18213
18214
18215
18216
18217
18218
18219
18220
18221
18222
18223
18224
18225
18226
18227
18228
18229
18230
18231
18232
18233
18234
18235
18236
18237
18238
18239
18240
18241
18242
18243
18244
18245
18246
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257
18258
18259
18260
18261
18262
18263
18264
18265
18266
18267
18268
18269
18270
18271
18272
18273
18274
18275
18276
18277
18278
18279
18280
18281
18282
18283
18284
18285
18286
18287
18288
18289
18290
18291
18292
18293
18294
18295
18296
18297
18298
18299
18300
18301
18302
18303
18304
18305
18306
18307
18308
18309
18310
18311
18312
18313
18314
18315
18316
18317
18318
18319
18320
18321
18322
18323
18324
18325
18326
18327
18328
18329
18330
18331
18332
18333
18334
18335
18336
18337
18338
18339
18340
18341
18342
18343
18344
18345
18346
18347
18348
18349
18350
18351
18352
18353
18354
18355
18356
18357
18358
18359
18360
18361
18362
18363
18364
18365
18366
18367
18368
18369
18370
18371
18372
18373
18374
18375
18376
18377
18378
18379
18380
18381
18382
18383
18384
18385
18386
18387
18388
18389
18390
18391
18392
18393
18394
18395
18396
18397
18398
18399
18400
18401
18402
18403
18404
18405
18406
18407
18408
18409
18410
18411
18412
18413
18414
18415
18416
18417
18418
18419
18420
18421
18422
18423
18424
18425
18426
18427
18428
18429
18430
18431
18432
18433
18434
18435
18436
18437
18438
18439
18440
18441
18442
18443
18444
18445
18446
18447
18448
18449
18450
18451
18452
18453
18454
18455
18456
18457
18458
18459
18460
18461
18462
18463
18464
18465
18466
18467
18468
18469
18470
18471
18472
18473
18474
18475
18476
18477
18478
18479
18480
18481
18482
18483
18484
18485
18486
18487
18488
18489
18490
18491
18492
18493
18494
18495
18496
18497
18498
18499
18500
18501
18502
18503
18504
18505
18506
18507
18508
18509
18510
18511
18512
18513
18514
18515
18516
18517
18518
18519
18520
18521
18522
18523
18524
18525
18526
18527
18528
18529
18530
18531
18532
18533
18534
18535
18536
18537
18538
18539
18540
18541
18542
18543
18544
18545
18546
18547
18548
18549
18550
18551
18552
18553
18554
18555
18556
18557
18558
18559
18560
18561
18562
18563
18564
18565
18566
18567
18568
18569
18570
18571
18572
18573
18574
18575
18576
18577
18578
18579
18580
18581
18582
18583
18584
18585
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596
18597
18598
18599
18600
18601
18602
18603
18604
18605
18606
18607
18608
18609
18610
18611
18612
18613
18614
18615
18616
18617
18618
18619
18620
18621
18622
18623
18624
18625
18626
18627
18628
18629
18630
18631
18632
18633
18634
18635
18636
18637
18638
18639
18640
18641
18642
18643
18644
18645
18646
18647
18648
18649
18650
18651
18652
18653
18654
18655
18656
18657
18658
18659
18660
18661
18662
18663
18664
18665
18666
18667
18668
18669
18670
18671
18672
18673
18674
18675
18676
18677
18678
18679
18680
18681
18682
18683
18684
18685
18686
18687
18688
18689
18690
18691
18692
18693
18694
18695
18696
18697
18698
18699
18700
18701
18702
18703
18704
18705
18706
18707
18708
18709
18710
18711
18712
18713
18714
18715
18716
18717
18718
18719
18720
18721
18722
18723
18724
18725
18726
18727
18728
18729
18730
18731
18732
18733
18734
18735
18736
18737
18738
18739
18740
18741
18742
18743
18744
18745
18746
18747
18748
18749
18750
18751
18752
18753
18754
18755
18756
18757
18758
18759
18760
18761
18762
18763
18764
18765
18766
18767
18768
18769
18770
18771
18772
18773
18774
18775
18776
18777
18778
18779
18780
18781
18782
18783
18784
18785
18786
18787
18788
18789
18790
18791
18792
18793
18794
18795
18796
18797
18798
18799
18800
18801
18802
18803
18804
18805
18806
18807
18808
18809
18810
18811
18812
18813
18814
18815
18816
18817
18818
18819
18820
18821
18822
18823
18824
18825
18826
18827
18828
18829
18830
18831
18832
18833
18834
18835
18836
18837
18838
18839
18840
18841
18842
18843
18844
18845
18846
18847
18848
18849
18850
18851
18852
18853
18854
18855
18856
18857
18858
18859
18860
18861
18862
18863
18864
18865
18866
18867
18868
18869
18870
18871
18872
18873
18874
18875
18876
18877
18878
18879
18880
18881
18882
18883
18884
18885
18886
18887
18888
18889
18890
18891
18892
18893
18894
18895
18896
18897
18898
18899
18900
18901
18902
18903
18904
18905
18906
18907
18908
18909
18910
18911
18912
18913
18914
18915
18916
18917
18918
18919
18920
18921
18922
18923
18924
18925
18926
18927
18928
18929
18930
18931
18932
18933
18934
18935
18936
18937
18938
18939
18940
18941
18942
18943
18944
18945
18946
18947
18948
18949
18950
18951
18952
18953
18954
18955
18956
18957
18958
18959
18960
18961
18962
18963
18964
18965
18966
18967
18968
18969
18970
18971
18972
18973
18974
18975
18976
18977
18978
18979
18980
18981
18982
18983
18984
18985
18986
18987
18988
18989
18990
18991
18992
18993
18994
18995
18996
18997
18998
18999
19000
19001
19002
19003
19004
19005
19006
19007
19008
19009
19010
19011
19012
19013
19014
19015
19016
19017
19018
19019
19020
19021
19022
19023
19024
19025
19026
19027
19028
19029
19030
19031
19032
19033
19034
19035
19036
19037
19038
19039
19040
19041
19042
19043
19044
19045
19046
19047
19048
19049
19050
19051
19052
19053
19054
19055
19056
19057
19058
19059
19060
19061
19062
19063
19064
19065
19066
19067
19068
19069
19070
19071
19072
19073
19074
19075
19076
19077
19078
19079
19080
19081
19082
19083
19084
19085
19086
19087
19088
19089
19090
19091
19092
19093
19094
19095
19096
19097
19098
19099
19100
19101
19102
19103
19104
19105
19106
19107
19108
19109
19110
19111
19112
19113
19114
19115
19116
19117
19118
19119
19120
19121
19122
19123
19124
19125
19126
19127
19128
19129
19130
19131
19132
19133
19134
19135
19136
19137
19138
19139
19140
19141
19142
19143
19144
19145
19146
19147
19148
19149
19150
19151
19152
19153
19154
19155
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167
19168
19169
19170
19171
19172
19173
19174
19175
19176
19177
19178
19179
19180
19181
19182
19183
19184
19185
19186
19187
19188
19189
19190
19191
19192
19193
19194
19195
19196
19197
19198
19199
19200
19201
19202
19203
19204
19205
19206
19207
19208
19209
19210
19211
19212
19213
19214
19215
19216
19217
19218
19219
19220
19221
19222
19223
19224
19225
19226
19227
19228
19229
19230
19231
19232
19233
19234
19235
19236
19237
19238
19239
19240
19241
19242
19243
19244
19245
19246
19247
19248
19249
19250
19251
19252
19253
19254
19255
19256
19257
19258
19259
19260
19261
19262
19263
19264
19265
19266
19267
19268
19269
19270
19271
19272
19273
19274
19275
19276
19277
19278
19279
19280
19281
19282
19283
19284
19285
19286
19287
19288
19289
19290
19291
19292
19293
19294
19295
19296
19297
19298
19299
19300
19301
19302
19303
19304
19305
19306
19307
19308
19309
19310
19311
19312
19313
19314
19315
19316
19317
19318
19319
19320
19321
19322
19323
19324
19325
19326
19327
19328
19329
19330
19331
19332
19333
19334
19335
19336
19337
19338
19339
19340
19341
19342
19343
19344
19345
19346
19347
19348
19349
19350
19351
19352
19353
19354
19355
19356
19357
19358
19359
19360
19361
19362
19363
19364
19365
19366
19367
19368
19369
19370
19371
19372
19373
19374
19375
19376
19377
19378
19379
19380
19381
19382
19383
19384
19385
19386
19387
19388
19389
19390
19391
19392
19393
19394
19395
19396
19397
19398
19399
19400
19401
19402
19403
19404
19405
19406
19407
19408
19409
19410
19411
19412
19413
19414
19415
19416
19417
19418
19419
19420
19421
19422
19423
19424
19425
19426
19427
19428
19429
19430
19431
19432
19433
19434
19435
19436
19437
19438
19439
19440
19441
19442
19443
19444
19445
19446
19447
19448
19449
19450
19451
19452
19453
19454
19455
19456
19457
19458
19459
19460
19461
19462
19463
19464
19465
19466
19467
19468
19469
19470
19471
19472
19473
19474
19475
19476
19477
19478
19479
19480
19481
19482
19483
19484
19485
19486
19487
19488
19489
19490
19491
19492
19493
19494
19495
19496
19497
19498
19499
19500
19501
19502
19503
19504
19505
19506
19507
19508
19509
19510
19511
19512
19513
19514
19515
19516
19517
19518
19519
19520
19521
19522
19523
19524
19525
19526
19527
19528
19529
19530
19531
19532
19533
19534
19535
19536
19537
19538
19539
19540
19541
19542
19543
19544
19545
19546
19547
19548
19549
19550
19551
19552
19553
19554
19555
19556
19557
19558
19559
19560
19561
19562
19563
19564
19565
19566
19567
19568
19569
19570
19571
19572
19573
19574
19575
19576
19577
19578
19579
19580
19581
19582
19583
19584
19585
19586
19587
19588
19589
19590
19591
19592
19593
19594
19595
19596
19597
19598
19599
19600
19601
19602
19603
19604
19605
19606
19607
19608
19609
19610
19611
19612
19613
19614
19615
19616
19617
19618
19619
19620
19621
19622
19623
19624
19625
19626
19627
19628
19629
19630
19631
19632
19633
19634
19635
19636
19637
19638
19639
19640
19641
19642
19643
19644
19645
19646
19647
19648
19649
19650
19651
19652
19653
19654
19655
19656
19657
19658
19659
19660
19661
19662
19663
19664
19665
19666
19667
19668
19669
19670
19671
19672
19673
19674
19675
19676
19677
19678
19679
19680
19681
19682
19683
19684
19685
19686
19687
19688
19689
19690
19691
19692
19693
19694
19695
19696
19697
19698
19699
19700
19701
19702
19703
19704
19705
19706
19707
19708
19709
19710
19711
19712
19713
19714
19715
19716
19717
19718
19719
19720
19721
19722
19723
19724
19725
19726
19727
19728
19729
19730
19731
19732
19733
19734
19735
19736
19737
19738
19739
19740
19741
19742
19743
19744
19745
19746
19747
19748
19749
19750
19751
19752
19753
19754
19755
19756
19757
19758
19759
19760
19761
19762
19763
19764
19765
19766
19767
19768
19769
19770
19771
19772
19773
19774
19775
19776
19777
19778
19779
19780
19781
19782
19783
19784
19785
19786
19787
19788
19789
19790
19791
19792
19793
19794
19795
19796
19797
19798
19799
19800
19801
19802
19803
19804
19805
19806
19807
19808
19809
19810
19811
19812
19813
19814
19815
19816
19817
19818
19819
19820
19821
19822
19823
19824
19825
19826
19827
19828
19829
19830
19831
19832
19833
19834
19835
19836
19837
19838
19839
19840
19841
19842
19843
19844
19845
19846
19847
19848
19849
19850
19851
19852
19853
19854
19855
19856
19857
19858
19859
19860
19861
19862
19863
19864
19865
19866
19867
19868
19869
19870
19871
19872
19873
19874
19875
19876
19877
19878
19879
19880
19881
19882
19883
19884
19885
19886
19887
19888
19889
19890
19891
19892
19893
19894
19895
19896
19897
19898
19899
19900
19901
19902
19903
19904
19905
19906
19907
19908
19909
19910
19911
19912
19913
19914
19915
19916
19917
19918
19919
19920
19921
19922
19923
19924
19925
19926
19927
19928
19929
19930
19931
19932
19933
19934
19935
19936
19937
19938
19939
19940
19941
19942
19943
19944
19945
19946
19947
19948
19949
19950
19951
19952
19953
19954
19955
19956
19957
19958
19959
19960
19961
19962
19963
19964
19965
19966
19967
19968
19969
19970
19971
19972
19973
19974
19975
19976
19977
19978
19979
19980
19981
19982
19983
19984
19985
19986
19987
19988
19989
19990
19991
19992
19993
19994
19995
19996
19997
19998
19999
20000
20001
20002
20003
20004
20005
20006
20007
20008
20009
20010
20011
20012
20013
20014
20015
20016
20017
20018
20019
20020
20021
20022
20023
20024
20025
20026
20027
20028
20029
20030
20031
20032
20033
20034
20035
20036
20037
20038
20039
20040
20041
20042
20043
20044
20045
20046
20047
20048
20049
20050
20051
20052
20053
20054
20055
20056
20057
20058
20059
20060
20061
20062
20063
20064
20065
20066
20067
20068
20069
20070
20071
20072
20073
20074
20075
20076
20077
20078
20079
20080
20081
20082
20083
20084
20085
20086
20087
20088
20089
20090
20091
20092
20093
20094
20095
20096
20097
20098
20099
20100
20101
20102
20103
20104
20105
20106
20107
20108
20109
20110
20111
20112
20113
20114
20115
20116
20117
20118
20119
20120
20121
20122
20123
20124
20125
20126
20127
20128
20129
20130
20131
20132
20133
20134
20135
20136
20137
20138
20139
20140
20141
20142
20143
20144
20145
20146
20147
20148
20149
20150
20151
20152
20153
20154
20155
20156
20157
20158
20159
20160
20161
20162
20163
20164
20165
20166
20167
20168
20169
20170
20171
20172
20173
20174
20175
20176
20177
20178
20179
20180
20181
20182
20183
20184
20185
20186
20187
20188
20189
20190
20191
20192
20193
20194
20195
20196
20197
20198
20199
20200
20201
20202
20203
20204
20205
20206
20207
20208
20209
20210
20211
20212
20213
20214
20215
20216
20217
20218
20219
20220
20221
20222
20223
20224
20225
20226
20227
20228
20229
20230
20231
20232
20233
20234
20235
20236
20237
20238
20239
20240
20241
20242
20243
20244
20245
20246
20247
20248
20249
20250
20251
20252
20253
20254
20255
20256
20257
20258
20259
20260
20261
20262
20263
20264
20265
20266
20267
20268
20269
20270
20271
20272
20273
20274
20275
20276
20277
20278
20279
20280
20281
20282
20283
20284
20285
20286
20287
20288
20289
20290
20291
20292
20293
20294
20295
20296
20297
20298
20299
20300
20301
20302
20303
20304
20305
20306
20307
20308
20309
20310
20311
20312
20313
20314
20315
20316
20317
20318
20319
20320
20321
20322
20323
20324
20325
20326
20327
20328
20329
20330
20331
20332
20333
20334
20335
20336
20337
20338
20339
20340
20341
20342
20343
20344
20345
20346
20347
20348
20349
20350
20351
20352
20353
20354
20355
20356
20357
20358
20359
20360
20361
20362
20363
20364
20365
20366
20367
20368
20369
20370
20371
20372
20373
20374
20375
20376
20377
20378
20379
20380
20381
20382
20383
20384
20385
20386
20387
20388
20389
20390
20391
20392
20393
20394
20395
20396
20397
20398
20399
20400
20401
20402
20403
20404
20405
20406
20407
20408
20409
20410
20411
20412
20413
20414
20415
20416
20417
20418
20419
20420
20421
20422
20423
20424
20425
20426
20427
20428
20429
20430
20431
20432
20433
20434
20435
20436
20437
20438
20439
20440
20441
20442
20443
20444
20445
20446
20447
20448
20449
20450
20451
20452
20453
20454
20455
20456
20457
20458
20459
20460
20461
20462
20463
20464
20465
20466
20467
20468
20469
20470
20471
20472
20473
20474
20475
20476
20477
20478
20479
20480
20481
20482
20483
20484
20485
20486
20487
20488
20489
20490
20491
20492
20493
20494
20495
20496
20497
20498
20499
20500
20501
20502
20503
20504
20505
20506
20507
20508
20509
20510
20511
20512
20513
20514
20515
20516
20517
20518
20519
20520
20521
20522
20523
20524
20525
20526
20527
20528
20529
20530
20531
20532
20533
20534
20535
20536
20537
20538
20539
20540
20541
20542
20543
20544
20545
20546
20547
20548
20549
20550
20551
20552
20553
20554
20555
20556
20557
20558
20559
20560
20561
20562
20563
20564
20565
20566
20567
20568
20569
20570
20571
20572
20573
20574
20575
20576
20577
20578
20579
20580
20581
20582
20583
20584
20585
20586
20587
20588
20589
20590
20591
20592
20593
20594
20595
20596
20597
20598
20599
20600
20601
20602
20603
20604
20605
20606
20607
20608
20609
20610
20611
20612
20613
20614
20615
20616
20617
20618
20619
20620
20621
20622
20623
20624
20625
20626
20627
20628
20629
20630
20631
20632
20633
20634
20635
20636
20637
20638
20639
20640
20641
20642
20643
20644
20645
20646
20647
20648
20649
20650
20651
20652
20653
20654
20655
20656
20657
20658
20659
20660
20661
20662
20663
20664
20665
20666
20667
20668
20669
20670
20671
20672
20673
20674
20675
20676
20677
20678
20679
20680
20681
20682
20683
20684
20685
20686
20687
20688
20689
20690
20691
20692
20693
20694
20695
20696
20697
20698
20699
20700
20701
20702
20703
20704
20705
20706
20707
20708
20709
20710
20711
20712
20713
20714
20715
20716
20717
20718
20719
20720
20721
20722
20723
20724
20725
20726
20727
20728
20729
20730
20731
20732
20733
20734
20735
20736
20737
20738
20739
20740
20741
20742
20743
20744
20745
20746
20747
20748
20749
20750
20751
20752
20753
20754
20755
20756
20757
20758
20759
20760
20761
20762
20763
20764
20765
20766
20767
20768
20769
20770
20771
20772
20773
20774
20775
20776
20777
20778
20779
20780
20781
20782
20783
20784
20785
20786
20787
20788
20789
20790
20791
20792
20793
20794
20795
20796
20797
20798
20799
20800
20801
20802
20803
20804
20805
20806
20807
20808
20809
20810
20811
20812
20813
20814
20815
20816
20817
20818
20819
20820
20821
20822
20823
20824
20825
20826
20827
20828
20829
20830
20831
20832
20833
20834
20835
20836
20837
20838
20839
20840
20841
20842
20843
20844
20845
20846
20847
20848
20849
20850
20851
20852
20853
20854
20855
20856
20857
20858
20859
20860
20861
20862
20863
20864
20865
20866
20867
20868
20869
20870
20871
20872
20873
20874
20875
20876
20877
20878
20879
20880
20881
20882
20883
20884
20885
20886
20887
20888
20889
20890
20891
20892
20893
20894
20895
20896
20897
20898
20899
20900
20901
20902
20903
20904
20905
20906
20907
20908
20909
20910
20911
20912
20913
20914
20915
20916
20917
20918
20919
20920
20921
20922
20923
20924
20925
20926
20927
20928
20929
20930
20931
20932
20933
20934
20935
20936
20937
20938
20939
20940
20941
20942
20943
20944
20945
20946
20947
20948
20949
20950
20951
20952
20953
20954
20955
20956
20957
20958
20959
20960
20961
20962
20963
20964
20965
20966
20967
20968
20969
20970
20971
20972
20973
20974
20975
20976
20977
20978
20979
20980
20981
20982
20983
20984
20985
20986
20987
20988
20989
20990
20991
20992
20993
20994
20995
20996
20997
20998
20999
21000
21001
21002
21003
21004
21005
21006
21007
21008
21009
21010
21011
21012
21013
21014
21015
21016
21017
21018
21019
21020
21021
21022
21023
21024
21025
21026
21027
21028
21029
21030
21031
21032
21033
21034
21035
21036
21037
21038
21039
21040
21041
21042
21043
21044
21045
21046
21047
21048
21049
21050
21051
21052
21053
21054
21055
21056
21057
21058
21059
21060
21061
21062
21063
21064
21065
21066
21067
21068
21069
21070
21071
21072
21073
21074
21075
21076
21077
21078
21079
21080
21081
21082
21083
21084
21085
21086
21087
21088
21089
21090
21091
21092
21093
21094
21095
21096
21097
21098
21099
21100
21101
21102
21103
21104
21105
21106
21107
21108
21109
21110
21111
21112
21113
21114
21115
21116
21117
21118
21119
21120
21121
21122
21123
21124
21125
21126
21127
21128
21129
21130
21131
21132
21133
21134
21135
21136
21137
21138
21139
21140
21141
21142
21143
21144
21145
21146
21147
21148
21149
21150
21151
21152
21153
21154
21155
21156
21157
21158
21159
21160
21161
21162
21163
21164
21165
21166
21167
21168
21169
21170
21171
21172
21173
21174
21175
21176
21177
21178
21179
21180
21181
21182
21183
21184
21185
21186
21187
21188
21189
21190
21191
21192
21193
21194
21195
21196
21197
21198
21199
21200
21201
21202
21203
21204
21205
21206
21207
21208
21209
21210
21211
21212
21213
21214
21215
21216
21217
21218
21219
21220
21221
21222
21223
21224
21225
21226
21227
21228
21229
21230
21231
21232
21233
21234
21235
21236
21237
21238
21239
21240
21241
21242
21243
21244
21245
21246
21247
21248
21249
21250
21251
21252
21253
21254
21255
21256
21257
21258
21259
21260
21261
21262
21263
21264
21265
21266
21267
21268
21269
21270
21271
21272
21273
21274
21275
21276
21277
21278
21279
21280
21281
21282
21283
21284
21285
21286
21287
21288
21289
21290
21291
21292
21293
21294
21295
21296
21297
21298
21299
21300
21301
21302
21303
21304
21305
21306
21307
21308
21309
21310
21311
21312
21313
21314
21315
21316
21317
21318
21319
21320
21321
21322
21323
21324
21325
21326
21327
21328
21329
21330
21331
21332
21333
21334
21335
21336
21337
21338
21339
21340
21341
21342
21343
21344
21345
21346
21347
21348
21349
21350
21351
21352
21353
21354
21355
21356
21357
21358
21359
21360
21361
21362
21363
21364
21365
21366
21367
21368
21369
21370
21371
21372
21373
21374
21375
21376
21377
21378
21379
21380
21381
21382
21383
21384
21385
21386
21387
21388
21389
21390
21391
21392
21393
21394
21395
21396
21397
21398
21399
21400
21401
21402
21403
21404
21405
21406
21407
21408
21409
21410
21411
21412
21413
21414
21415
21416
21417
21418
21419
21420
21421
21422
21423
21424
21425
21426
21427
21428
21429
21430
21431
21432
21433
21434
21435
21436
21437
21438
21439
21440
21441
21442
21443
21444
21445
21446
21447
21448
21449
21450
21451
21452
21453
21454
21455
21456
21457
21458
21459
21460
21461
21462
21463
21464
21465
21466
21467
21468
21469
21470
21471
21472
21473
21474
21475
21476
21477
21478
21479
21480
21481
21482
21483
21484
21485
21486
21487
21488
21489
21490
21491
21492
21493
21494
21495
21496
21497
21498
21499
21500
21501
21502
21503
21504
21505
21506
21507
21508
21509
21510
21511
21512
21513
21514
21515
21516
21517
21518
21519
21520
21521
21522
21523
21524
21525
21526
21527
21528
21529
21530
21531
21532
21533
21534
21535
21536
21537
21538
21539
21540
21541
21542
21543
21544
21545
21546
21547
21548
21549
21550
21551
21552
21553
21554
21555
21556
21557
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576
21577
21578
21579
21580
21581
21582
21583
21584
21585
21586
21587
21588
21589
21590
21591
21592
21593
21594
21595
21596
21597
21598
21599
21600
21601
21602
21603
21604
21605
21606
21607
21608
21609
21610
21611
21612
21613
21614
21615
21616
21617
21618
21619
21620
21621
21622
21623
21624
21625
21626
21627
21628
21629
21630
21631
21632
21633
21634
21635
21636
21637
21638
21639
21640
21641
21642
21643
21644
21645
21646
21647
21648
21649
21650
21651
21652
21653
21654
21655
21656
21657
21658
21659
21660
21661
21662
21663
21664
21665
21666
21667
21668
21669
21670
21671
21672
21673
21674
21675
21676
21677
21678
21679
21680
21681
21682
21683
21684
21685
21686
21687
21688
21689
21690
21691
21692
21693
21694
21695
21696
21697
21698
21699
21700
21701
21702
21703
21704
21705
21706
21707
21708
21709
21710
21711
21712
21713
21714
21715
21716
21717
21718
21719
21720
21721
21722
21723
21724
21725
21726
21727
21728
21729
21730
21731
21732
21733
21734
21735
21736
21737
21738
21739
21740
21741
21742
21743
21744
21745
21746
21747
21748
21749
21750
21751
21752
21753
21754
21755
21756
21757
21758
21759
21760
21761
21762
21763
21764
21765
21766
21767
21768
21769
21770
21771
21772
21773
21774
21775
21776
21777
21778
21779
21780
21781
21782
21783
21784
21785
21786
21787
21788
21789
21790
21791
21792
21793
21794
21795
21796
21797
21798
21799
21800
21801
21802
21803
21804
21805
21806
21807
21808
21809
21810
21811
21812
21813
21814
21815
21816
21817
21818
21819
21820
21821
21822
21823
21824
21825
21826
21827
21828
21829
21830
21831
21832
21833
21834
21835
21836
21837
21838
21839
21840
21841
21842
21843
21844
21845
21846
21847
21848
21849
21850
21851
21852
21853
21854
21855
21856
21857
21858
21859
21860
21861
21862
21863
21864
21865
21866
21867
21868
21869
21870
21871
21872
21873
21874
21875
21876
21877
21878
21879
21880
21881
21882
21883
21884
21885
21886
21887
21888
21889
21890
21891
21892
21893
21894
21895
21896
21897
21898
21899
21900
21901
21902
21903
21904
21905
21906
21907
21908
21909
21910
21911
21912
21913
21914
21915
21916
21917
21918
21919
21920
21921
21922
21923
21924
21925
21926
21927
21928
21929
21930
21931
21932
21933
21934
21935
21936
21937
21938
21939
21940
21941
21942
21943
21944
21945
21946
21947
21948
21949
21950
21951
21952
21953
21954
21955
21956
21957
21958
21959
21960
21961
21962
21963
21964
21965
21966
21967
21968
21969
21970
21971
21972
21973
21974
21975
21976
21977
21978
21979
21980
21981
21982
21983
21984
21985
21986
21987
21988
21989
21990
21991
21992
21993
21994
21995
21996
21997
21998
21999
22000
22001
22002
22003
22004
22005
22006
22007
22008
22009
22010
22011
22012
22013
22014
22015
22016
22017
22018
22019
22020
22021
22022
22023
22024
22025
22026
22027
22028
22029
22030
22031
22032
22033
22034
22035
22036
22037
22038
22039
22040
22041
22042
22043
22044
22045
22046
22047
22048
22049
22050
22051
22052
22053
22054
22055
22056
22057
22058
22059
22060
22061
22062
22063
22064
22065
22066
22067
22068
22069
22070
22071
22072
22073
22074
22075
22076
22077
22078
22079
22080
22081
22082
22083
22084
22085
22086
22087
22088
22089
22090
22091
22092
22093
22094
22095
22096
22097
22098
22099
22100
22101
22102
22103
22104
22105
22106
22107
22108
22109
22110
22111
22112
22113
22114
22115
22116
22117
22118
22119
22120
22121
22122
22123
22124
22125
22126
22127
22128
22129
22130
22131
22132
22133
22134
22135
22136
22137
22138
22139
22140
22141
22142
22143
22144
22145
22146
22147
22148
22149
22150
22151
22152
22153
22154
22155
22156
22157
22158
22159
22160
22161
22162
22163
22164
22165
22166
22167
22168
22169
22170
22171
22172
22173
22174
22175
22176
22177
22178
22179
22180
22181
22182
22183
22184
22185
22186
22187
22188
22189
22190
22191
22192
22193
22194
22195
22196
22197
22198
22199
22200
22201
22202
22203
22204
22205
22206
22207
22208
22209
22210
22211
22212
22213
22214
22215
22216
22217
22218
22219
22220
22221
22222
22223
22224
22225
22226
22227
22228
22229
22230
22231
22232
22233
22234
22235
22236
22237
22238
22239
22240
22241
22242
22243
22244
22245
22246
22247
22248
22249
22250
22251
22252
22253
22254
22255
22256
22257
22258
22259
22260
22261
22262
22263
22264
22265
22266
22267
22268
22269
22270
22271
22272
22273
22274
22275
22276
22277
22278
22279
22280
22281
22282
22283
22284
22285
22286
22287
22288
22289
22290
22291
22292
22293
22294
22295
22296
22297
22298
22299
22300
22301
22302
22303
22304
22305
22306
22307
22308
22309
22310
22311
22312
22313
22314
22315
22316
22317
22318
22319
22320
22321
22322
22323
22324
22325
22326
22327
22328
22329
22330
22331
22332
22333
22334
22335
22336
22337
22338
22339
22340
22341
22342
22343
22344
22345
22346
22347
22348
22349
22350
22351
22352
22353
22354
22355
22356
22357
22358
22359
22360
22361
22362
22363
22364
22365
22366
22367
22368
22369
22370
22371
22372
22373
22374
22375
22376
22377
22378
22379
22380
22381
22382
22383
22384
22385
22386
22387
22388
22389
22390
22391
22392
22393
22394
22395
22396
22397
22398
22399
22400
22401
22402
22403
22404
22405
22406
22407
22408
22409
22410
22411
22412
22413
22414
22415
22416
22417
22418
22419
22420
22421
22422
22423
22424
22425
22426
22427
22428
22429
22430
22431
22432
22433
22434
22435
22436
22437
22438
22439
22440
22441
22442
22443
22444
22445
22446
22447
22448
22449
22450
22451
22452
22453
22454
22455
22456
22457
22458
22459
22460
22461
22462
22463
22464
22465
22466
22467
22468
22469
22470
22471
22472
22473
22474
22475
22476
22477
22478
22479
22480
22481
22482
22483
22484
22485
22486
22487
22488
22489
22490
22491
22492
22493
22494
22495
22496
22497
22498
22499
22500
22501
22502
22503
22504
22505
22506
22507
22508
22509
22510
22511
22512
22513
22514
22515
22516
22517
22518
22519
22520
22521
22522
22523
22524
22525
22526
22527
22528
22529
22530
22531
22532
22533
22534
22535
22536
22537
22538
22539
22540
22541
22542
22543
22544
22545
22546
22547
22548
22549
22550
22551
22552
22553
22554
22555
22556
22557
22558
22559
22560
22561
22562
22563
22564
22565
22566
22567
22568
22569
22570
22571
22572
22573
22574
22575
22576
22577
22578
22579
22580
22581
22582
22583
22584
22585
22586
22587
22588
22589
22590
22591
22592
22593
22594
22595
22596
22597
22598
22599
22600
22601
22602
22603
22604
22605
22606
22607
22608
22609
22610
22611
22612
22613
22614
22615
22616
22617
22618
22619
22620
22621
22622
22623
22624
22625
22626
22627
22628
22629
22630
22631
22632
22633
22634
22635
22636
22637
22638
22639
22640
22641
22642
22643
22644
22645
22646
22647
22648
22649
22650
22651
22652
22653
22654
22655
22656
22657
22658
22659
22660
22661
22662
22663
22664
22665
22666
22667
22668
22669
22670
22671
22672
22673
22674
22675
22676
22677
22678
22679
22680
22681
22682
22683
22684
22685
22686
22687
22688
22689
22690
22691
22692
22693
22694
22695
22696
22697
22698
22699
22700
22701
22702
22703
22704
22705
22706
22707
22708
22709
22710
22711
22712
22713
22714
22715
22716
22717
22718
22719
22720
22721
22722
22723
22724
22725
22726
22727
22728
22729
22730
22731
22732
22733
22734
22735
22736
22737
22738
22739
22740
22741
22742
22743
22744
22745
22746
22747
22748
22749
22750
22751
22752
22753
22754
22755
22756
22757
22758
22759
22760
22761
22762
22763
22764
22765
22766
22767
22768
22769
22770
22771
22772
22773
22774
22775
22776
22777
22778
22779
22780
22781
22782
22783
22784
22785
22786
22787
22788
22789
22790
22791
22792
22793
22794
22795
22796
22797
22798
22799
22800
22801
22802
22803
22804
22805
22806
22807
22808
22809
22810
22811
22812
22813
22814
22815
22816
22817
22818
22819
22820
22821
22822
22823
22824
22825
22826
22827
22828
22829
22830
22831
22832
22833
22834
22835
22836
22837
22838
22839
22840
22841
22842
22843
22844
22845
22846
22847
22848
22849
22850
22851
22852
22853
22854
22855
22856
22857
22858
22859
22860
22861
22862
22863
22864
22865
22866
22867
22868
22869
22870
22871
22872
22873
22874
22875
22876
22877
22878
22879
22880
22881
22882
22883
22884
22885
22886
22887
22888
22889
22890
22891
22892
22893
22894
22895
22896
22897
22898
22899
22900
22901
22902
22903
22904
22905
22906
22907
22908
22909
22910
22911
22912
22913
22914
22915
22916
22917
22918
22919
22920
22921
22922
22923
22924
22925
22926
22927
22928
22929
22930
22931
22932
22933
22934
22935
22936
22937
22938
22939
22940
22941
22942
22943
22944
22945
22946
22947
22948
22949
22950
22951
22952
22953
22954
22955
22956
22957
22958
22959
22960
22961
22962
22963
22964
22965
22966
22967
22968
22969
22970
22971
22972
22973
22974
22975
22976
22977
22978
22979
22980
22981
22982
22983
22984
22985
22986
22987
22988
22989
22990
22991
22992
22993
22994
22995
22996
22997
22998
22999
23000
23001
23002
23003
23004
23005
23006
23007
23008
23009
23010
23011
23012
23013
23014
23015
23016
23017
23018
23019
23020
23021
23022
23023
23024
23025
23026
23027
23028
23029
23030
23031
23032
23033
23034
23035
23036
23037
23038
23039
23040
23041
23042
23043
23044
23045
23046
23047
23048
23049
23050
23051
23052
23053
23054
23055
23056
23057
23058
23059
23060
23061
23062
23063
23064
23065
23066
23067
23068
23069
23070
23071
23072
23073
23074
23075
23076
23077
23078
23079
23080
23081
23082
23083
23084
23085
23086
23087
23088
23089
23090
23091
23092
23093
23094
23095
23096
23097
23098
23099
23100
23101
23102
23103
23104
23105
23106
23107
23108
23109
23110
23111
23112
23113
23114
23115
23116
23117
23118
23119
23120
23121
23122
23123
23124
23125
23126
23127
23128
23129
23130
23131
23132
23133
23134
23135
23136
23137
23138
23139
23140
23141
23142
23143
23144
23145
23146
23147
23148
23149
23150
23151
23152
23153
23154
23155
23156
23157
23158
23159
23160
23161
23162
23163
23164
23165
23166
23167
23168
23169
23170
23171
23172
23173
23174
23175
23176
23177
23178
23179
23180
23181
23182
23183
23184
23185
23186
23187
23188
23189
23190
23191
23192
23193
23194
23195
23196
23197
23198
23199
23200
23201
23202
23203
23204
23205
23206
23207
23208
23209
23210
23211
23212
23213
23214
23215
23216
23217
23218
23219
23220
23221
23222
23223
23224
23225
23226
23227
23228
23229
23230
23231
23232
23233
23234
23235
23236
23237
23238
23239
23240
23241
23242
23243
23244
23245
23246
23247
23248
23249
23250
23251
23252
23253
23254
23255
23256
23257
23258
23259
23260
23261
23262
23263
23264
23265
23266
23267
23268
23269
23270
23271
23272
23273
23274
23275
23276
23277
23278
23279
23280
23281
23282
23283
23284
23285
23286
23287
23288
23289
23290
23291
23292
23293
23294
23295
23296
23297
23298
23299
23300
23301
23302
23303
23304
23305
23306
23307
23308
23309
23310
23311
23312
23313
23314
23315
23316
23317
23318
23319
23320
23321
23322
23323
23324
23325
23326
23327
23328
23329
23330
23331
23332
23333
23334
23335
23336
23337
23338
23339
23340
23341
23342
23343
23344
23345
23346
23347
23348
23349
23350
23351
23352
23353
23354
23355
23356
23357
23358
23359
23360
23361
23362
23363
23364
23365
23366
23367
23368
23369
23370
23371
23372
23373
23374
23375
23376
23377
23378
23379
23380
23381
23382
23383
23384
23385
23386
23387
23388
23389
23390
23391
23392
23393
23394
23395
23396
23397
23398
23399
23400
23401
23402
23403
23404
23405
23406
23407
23408
23409
23410
23411
23412
23413
23414
23415
23416
23417
23418
23419
23420
23421
23422
23423
23424
23425
23426
23427
23428
23429
23430
23431
23432
23433
23434
23435
23436
23437
23438
23439
23440
23441
23442
23443
23444
23445
23446
23447
23448
23449
23450
23451
23452
23453
23454
23455
23456
23457
23458
23459
23460
23461
23462
23463
23464
23465
23466
23467
23468
23469
23470
23471
23472
23473
23474
23475
23476
23477
23478
23479
23480
23481
23482
23483
23484
23485
23486
23487
23488
23489
23490
23491
23492
23493
23494
23495
23496
23497
23498
23499
23500
23501
23502
23503
23504
23505
23506
23507
23508
23509
23510
23511
23512
23513
23514
23515
23516
23517
23518
23519
23520
23521
23522
23523
23524
23525
23526
23527
23528
23529
23530
23531
23532
23533
23534
23535
23536
23537
23538
23539
23540
23541
23542
23543
23544
23545
23546
23547
23548
23549
23550
23551
23552
23553
23554
23555
23556
23557
23558
23559
23560
23561
23562
23563
23564
23565
23566
23567
23568
23569
23570
23571
23572
23573
23574
23575
23576
23577
23578
23579
23580
23581
23582
23583
23584
23585
23586
23587
23588
23589
23590
23591
23592
23593
23594
23595
23596
23597
23598
23599
23600
23601
23602
23603
23604
23605
23606
23607
23608
23609
23610
23611
23612
23613
23614
23615
23616
23617
23618
23619
23620
23621
23622
23623
23624
23625
23626
23627
23628
23629
23630
23631
23632
23633
23634
23635
23636
23637
23638
23639
23640
23641
23642
23643
23644
23645
23646
23647
23648
23649
23650
23651
23652
23653
23654
23655
23656
23657
23658
23659
23660
23661
23662
23663
23664
23665
23666
23667
23668
23669
23670
23671
23672
23673
23674
23675
23676
23677
23678
23679
23680
23681
23682
23683
23684
23685
23686
23687
23688
23689
23690
23691
23692
23693
23694
23695
23696
23697
23698
23699
23700
23701
23702
23703
23704
23705
23706
23707
23708
23709
23710
23711
23712
23713
23714
23715
23716
23717
23718
23719
23720
23721
23722
23723
23724
23725
23726
23727
23728
23729
23730
23731
23732
23733
23734
23735
23736
23737
23738
23739
23740
23741
23742
23743
23744
23745
23746
23747
23748
23749
23750
23751
23752
23753
23754
23755
23756
23757
23758
23759
23760
23761
23762
23763
23764
23765
23766
23767
23768
23769
23770
23771
23772
23773
23774
23775
23776
23777
23778
23779
23780
23781
23782
23783
23784
23785
23786
23787
23788
23789
23790
23791
23792
23793
23794
23795
23796
23797
23798
23799
23800
23801
23802
23803
23804
23805
23806
23807
23808
23809
23810
23811
23812
23813
23814
23815
23816
23817
23818
23819
23820
23821
23822
23823
23824
23825
23826
23827
23828
23829
23830
23831
23832
23833
23834
23835
23836
23837
23838
23839
23840
23841
23842
23843
23844
23845
23846
23847
23848
23849
23850
23851
23852
23853
23854
23855
23856
23857
23858
23859
23860
23861
23862
23863
23864
23865
23866
23867
23868
23869
23870
23871
23872
23873
23874
23875
23876
23877
23878
23879
23880
23881
23882
23883
23884
23885
23886
23887
23888
23889
23890
23891
23892
23893
23894
23895
23896
23897
23898
23899
23900
23901
23902
23903
23904
23905
23906
23907
23908
23909
23910
23911
23912
23913
23914
23915
23916
23917
23918
23919
23920
23921
23922
23923
23924
23925
23926
23927
23928
23929
23930
23931
23932
23933
23934
23935
23936
23937
23938
23939
23940
23941
23942
23943
23944
23945
23946
23947
23948
23949
23950
23951
23952
23953
23954
23955
23956
23957
23958
23959
23960
23961
23962
23963
23964
23965
23966
23967
23968
23969
23970
23971
23972
23973
23974
23975
23976
23977
23978
23979
23980
23981
23982
23983
23984
23985
23986
23987
23988
23989
23990
23991
23992
23993
23994
23995
23996
23997
23998
23999
24000
24001
24002
24003
24004
24005
24006
24007
24008
24009
24010
24011
24012
24013
24014
24015
24016
24017
24018
24019
24020
24021
24022
24023
24024
24025
24026
24027
24028
24029
24030
24031
24032
24033
24034
24035
24036
24037
24038
24039
24040
24041
24042
24043
24044
24045
24046
24047
24048
24049
24050
24051
24052
24053
24054
24055
24056
24057
24058
24059
24060
24061
24062
24063
24064
24065
24066
24067
24068
24069
24070
24071
24072
24073
24074
24075
24076
24077
24078
24079
24080
24081
24082
24083
24084
24085
24086
24087
24088
24089
24090
24091
24092
24093
24094
24095
24096
24097
24098
24099
24100
24101
24102
24103
24104
24105
24106
24107
24108
24109
24110
24111
24112
24113
24114
24115
24116
24117
24118
24119
24120
24121
24122
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137
24138
24139
24140
24141
24142
24143
24144
24145
24146
24147
24148
24149
24150
24151
24152
24153
24154
24155
24156
24157
24158
24159
24160
24161
24162
24163
24164
24165
24166
24167
24168
24169
24170
24171
24172
24173
24174
24175
24176
24177
24178
24179
24180
24181
24182
24183
24184
24185
24186
24187
24188
24189
24190
24191
24192
24193
24194
24195
24196
24197
24198
24199
24200
24201
24202
24203
24204
24205
24206
24207
24208
24209
24210
24211
24212
24213
24214
24215
24216
24217
24218
24219
24220
24221
24222
24223
24224
24225
24226
24227
24228
24229
24230
24231
24232
24233
24234
24235
24236
24237
24238
24239
24240
24241
24242
24243
24244
24245
24246
24247
24248
24249
24250
24251
24252
24253
24254
24255
24256
24257
24258
24259
24260
24261
24262
24263
24264
24265
24266
24267
24268
24269
24270
24271
24272
24273
24274
24275
24276
24277
24278
24279
24280
24281
24282
24283
24284
24285
24286
24287
24288
24289
24290
24291
24292
24293
24294
24295
24296
24297
24298
24299
24300
24301
24302
24303
24304
24305
24306
24307
24308
24309
24310
24311
24312
24313
24314
24315
24316
24317
24318
24319
24320
24321
24322
24323
24324
24325
24326
24327
24328
24329
24330
24331
24332
24333
24334
24335
24336
24337
24338
24339
24340
24341
24342
24343
24344
24345
24346
24347
24348
24349
24350
24351
24352
24353
24354
24355
24356
24357
24358
24359
24360
24361
24362
24363
24364
24365
24366
24367
24368
24369
24370
24371
24372
24373
24374
24375
24376
24377
24378
24379
24380
24381
24382
24383
24384
24385
24386
24387
24388
24389
24390
24391
24392
24393
24394
24395
24396
24397
24398
24399
24400
24401
24402
24403
24404
24405
24406
24407
24408
24409
24410
24411
24412
24413
24414
24415
24416
24417
24418
24419
24420
24421
24422
24423
24424
24425
24426
24427
24428
24429
24430
24431
24432
24433
24434
24435
24436
24437
24438
24439
24440
24441
24442
24443
24444
24445
24446
24447
24448
24449
24450
24451
24452
24453
24454
24455
24456
24457
24458
24459
24460
24461
24462
24463
24464
24465
24466
24467
24468
24469
24470
24471
24472
24473
24474
24475
24476
24477
24478
24479
24480
24481
24482
24483
24484
24485
24486
24487
24488
24489
24490
24491
24492
24493
24494
24495
24496
24497
24498
24499
24500
24501
24502
24503
24504
24505
24506
24507
24508
24509
24510
24511
24512
24513
24514
24515
24516
24517
24518
24519
24520
24521
24522
24523
24524
24525
24526
24527
24528
24529
24530
24531
24532
24533
24534
24535
24536
24537
24538
24539
24540
24541
24542
24543
24544
24545
24546
24547
24548
24549
24550
24551
24552
24553
24554
24555
24556
24557
24558
24559
24560
24561
24562
24563
24564
24565
24566
24567
24568
24569
24570
24571
24572
24573
24574
24575
24576
24577
24578
24579
24580
24581
24582
24583
24584
24585
24586
24587
24588
24589
24590
24591
24592
24593
24594
24595
24596
24597
24598
24599
24600
24601
24602
24603
24604
24605
24606
24607
24608
24609
24610
24611
24612
24613
24614
24615
24616
24617
24618
24619
24620
24621
24622
24623
24624
24625
24626
24627
24628
24629
24630
24631
24632
24633
24634
24635
24636
24637
24638
24639
24640
24641
24642
24643
24644
24645
24646
24647
24648
24649
24650
24651
24652
24653
24654
24655
24656
24657
24658
24659
24660
24661
24662
24663
24664
24665
24666
24667
24668
24669
24670
24671
24672
24673
24674
24675
24676
24677
24678
24679
24680
24681
24682
24683
24684
24685
24686
24687
24688
24689
24690
24691
24692
24693
24694
24695
24696
24697
24698
24699
24700
24701
24702
24703
24704
24705
24706
24707
24708
24709
24710
24711
24712
24713
24714
24715
24716
24717
24718
24719
24720
24721
24722
24723
24724
24725
24726
24727
24728
24729
24730
24731
24732
24733
24734
24735
24736
24737
24738
24739
24740
24741
24742
24743
24744
24745
24746
24747
24748
24749
24750
24751
24752
24753
24754
24755
24756
24757
24758
24759
24760
24761
24762
24763
24764
24765
24766
24767
24768
24769
24770
24771
24772
24773
24774
24775
24776
24777
24778
24779
24780
24781
24782
24783
24784
24785
24786
24787
24788
24789
24790
24791
24792
24793
24794
24795
24796
24797
24798
24799
24800
24801
24802
24803
24804
24805
24806
24807
24808
24809
24810
24811
24812
24813
24814
24815
24816
24817
24818
24819
24820
24821
24822
24823
24824
24825
24826
24827
24828
24829
24830
24831
24832
24833
24834
24835
24836
24837
24838
24839
24840
24841
24842
24843
24844
24845
24846
24847
24848
24849
24850
24851
24852
24853
24854
24855
24856
24857
24858
24859
24860
24861
24862
24863
24864
24865
24866
24867
24868
24869
24870
24871
24872
24873
24874
24875
24876
24877
24878
24879
24880
24881
24882
24883
24884
24885
24886
24887
24888
24889
24890
24891
24892
24893
24894
24895
24896
24897
24898
24899
24900
24901
24902
24903
24904
24905
24906
24907
24908
24909
24910
24911
24912
24913
24914
24915
24916
24917
24918
24919
24920
24921
24922
24923
24924
24925
24926
24927
24928
24929
24930
24931
24932
24933
24934
24935
24936
24937
24938
24939
24940
24941
24942
24943
24944
24945
24946
24947
24948
24949
24950
24951
24952
24953
24954
24955
24956
24957
24958
24959
24960
24961
24962
24963
24964
24965
24966
24967
24968
24969
24970
24971
24972
24973
24974
24975
24976
24977
24978
24979
24980
24981
24982
24983
24984
24985
24986
24987
24988
24989
24990
24991
24992
24993
24994
24995
24996
24997
24998
24999
25000
25001
25002
25003
25004
25005
25006
25007
25008
25009
25010
25011
25012
25013
25014
25015
25016
25017
25018
25019
25020
25021
25022
25023
25024
25025
25026
25027
25028
25029
25030
25031
25032
25033
25034
25035
25036
25037
25038
25039
25040
25041
25042
25043
25044
25045
25046
25047
25048
25049
25050
25051
25052
25053
25054
25055
25056
25057
25058
25059
25060
25061
25062
25063
25064
25065
25066
25067
25068
25069
25070
25071
25072
25073
25074
25075
25076
25077
25078
25079
25080
25081
25082
25083
25084
25085
25086
25087
25088
25089
25090
25091
25092
25093
25094
25095
25096
25097
25098
25099
25100
25101
25102
25103
25104
25105
25106
25107
25108
25109
25110
25111
25112
25113
25114
25115
25116
25117
25118
25119
25120
25121
25122
25123
25124
25125
25126
25127
25128
25129
25130
25131
25132
25133
25134
25135
25136
25137
25138
25139
25140
25141
25142
25143
25144
25145
25146
25147
25148
25149
25150
25151
25152
25153
25154
25155
25156
25157
25158
25159
25160
25161
25162
25163
25164
25165
25166
25167
25168
25169
25170
25171
25172
25173
25174
25175
25176
25177
25178
25179
25180
25181
25182
25183
25184
25185
25186
25187
25188
25189
25190
25191
25192
25193
25194
25195
25196
25197
25198
25199
25200
25201
25202
25203
25204
25205
25206
25207
25208
25209
25210
25211
25212
25213
25214
25215
25216
25217
25218
25219
25220
25221
25222
25223
25224
25225
25226
25227
25228
25229
25230
25231
25232
25233
25234
25235
25236
25237
25238
25239
25240
25241
25242
25243
25244
25245
25246
25247
25248
25249
25250
25251
25252
25253
25254
25255
25256
25257
25258
25259
25260
25261
25262
25263
25264
25265
25266
25267
25268
25269
25270
25271
25272
25273
25274
25275
25276
25277
25278
25279
25280
25281
25282
25283
25284
25285
25286
25287
25288
25289
25290
25291
25292
25293
25294
25295
25296
25297
25298
25299
25300
25301
25302
25303
25304
25305
25306
25307
25308
25309
25310
25311
25312
25313
25314
25315
25316
25317
25318
25319
25320
25321
25322
25323
25324
25325
25326
25327
25328
25329
25330
25331
25332
25333
25334
25335
25336
25337
25338
25339
25340
25341
25342
25343
25344
25345
25346
25347
25348
25349
25350
25351
25352
25353
25354
25355
25356
25357
25358
25359
25360
25361
25362
25363
25364
25365
25366
25367
25368
25369
25370
25371
25372
25373
25374
25375
25376
25377
25378
25379
25380
25381
25382
25383
25384
25385
25386
25387
25388
25389
25390
25391
25392
25393
25394
25395
25396
25397
25398
25399
25400
25401
25402
25403
25404
25405
25406
25407
25408
25409
25410
25411
25412
25413
25414
25415
25416
25417
25418
25419
25420
25421
25422
25423
25424
25425
25426
25427
25428
25429
25430
25431
25432
25433
25434
25435
25436
25437
25438
25439
25440
25441
25442
25443
25444
25445
25446
25447
25448
25449
25450
25451
25452
25453
25454
25455
25456
25457
25458
25459
25460
25461
25462
25463
25464
25465
25466
25467
25468
25469
25470
25471
25472
25473
25474
25475
25476
25477
25478
25479
25480
25481
25482
25483
25484
25485
25486
25487
25488
25489
25490
25491
25492
25493
25494
25495
25496
25497
25498
25499
25500
25501
25502
25503
25504
25505
25506
25507
25508
25509
25510
25511
25512
25513
25514
25515
25516
25517
25518
25519
25520
25521
25522
25523
25524
25525
25526
25527
25528
25529
25530
25531
25532
25533
25534
25535
25536
25537
25538
25539
25540
25541
25542
25543
25544
25545
25546
25547
25548
25549
25550
25551
25552
25553
25554
25555
25556
25557
25558
25559
25560
25561
25562
25563
25564
25565
25566
25567
25568
25569
25570
25571
25572
25573
25574
25575
25576
25577
25578
25579
25580
25581
25582
25583
25584
25585
25586
25587
25588
25589
25590
25591
25592
25593
25594
25595
25596
25597
25598
25599
25600
25601
25602
25603
25604
25605
25606
25607
25608
25609
25610
25611
25612
25613
25614
25615
25616
25617
25618
25619
25620
25621
25622
25623
25624
25625
25626
25627
25628
25629
25630
25631
25632
25633
25634
25635
25636
25637
25638
25639
25640
25641
25642
25643
25644
25645
25646
25647
25648
25649
25650
25651
25652
25653
25654
25655
25656
25657
25658
25659
25660
25661
25662
25663
25664
25665
25666
25667
25668
25669
25670
25671
25672
25673
25674
25675
25676
25677
25678
25679
25680
25681
25682
25683
25684
25685
25686
25687
25688
25689
25690
25691
25692
25693
25694
25695
25696
25697
25698
25699
25700
25701
25702
25703
25704
25705
25706
25707
25708
25709
25710
25711
25712
25713
25714
25715
25716
25717
25718
25719
25720
25721
25722
25723
25724
25725
25726
25727
25728
25729
25730
25731
25732
25733
25734
25735
25736
25737
25738
25739
25740
25741
25742
25743
25744
25745
25746
25747
25748
25749
25750
25751
25752
25753
25754
25755
25756
25757
25758
25759
25760
25761
25762
25763
25764
25765
25766
25767
25768
25769
25770
25771
25772
25773
25774
25775
25776
25777
25778
25779
25780
25781
25782
25783
25784
25785
25786
25787
25788
25789
25790
25791
25792
25793
25794
25795
25796
25797
25798
25799
25800
25801
25802
25803
25804
25805
25806
25807
25808
25809
25810
25811
25812
25813
25814
25815
25816
25817
25818
25819
25820
25821
25822
25823
25824
25825
25826
25827
25828
25829
25830
25831
25832
25833
25834
25835
25836
25837
25838
25839
25840
25841
25842
25843
25844
25845
25846
25847
25848
25849
25850
25851
25852
25853
25854
25855
25856
25857
25858
25859
25860
25861
25862
25863
25864
25865
25866
25867
25868
25869
25870
25871
25872
25873
25874
25875
25876
25877
25878
25879
25880
25881
25882
25883
25884
25885
25886
25887
25888
25889
25890
25891
25892
25893
25894
25895
25896
25897
25898
25899
25900
25901
25902
25903
25904
25905
25906
25907
25908
25909
25910
25911
25912
25913
25914
25915
25916
25917
25918
25919
25920
25921
25922
25923
25924
25925
25926
25927
25928
25929
25930
25931
25932
25933
25934
25935
25936
25937
25938
25939
25940
25941
25942
25943
25944
25945
25946
25947
25948
25949
25950
25951
25952
25953
25954
25955
25956
25957
25958
25959
25960
25961
25962
25963
25964
25965
25966
25967
25968
25969
25970
25971
25972
25973
25974
25975
25976
25977
25978
25979
25980
25981
25982
25983
25984
25985
25986
25987
25988
25989
25990
25991
25992
25993
25994
25995
25996
25997
25998
25999
26000
26001
26002
26003
26004
26005
26006
26007
26008
26009
26010
26011
26012
26013
26014
26015
26016
26017
26018
26019
26020
26021
26022
26023
26024
26025
26026
26027
26028
26029
26030
26031
26032
26033
26034
26035
26036
26037
26038
26039
26040
26041
26042
26043
26044
26045
26046
26047
26048
26049
26050
26051
26052
26053
26054
26055
26056
26057
26058
26059
26060
26061
26062
26063
26064
26065
26066
26067
26068
26069
26070
26071
26072
26073
26074
26075
26076
26077
26078
26079
26080
26081
26082
26083
26084
26085
26086
26087
26088
26089
26090
26091
26092
26093
26094
26095
26096
26097
26098
26099
26100
26101
26102
26103
26104
26105
26106
26107
26108
26109
26110
26111
26112
26113
26114
26115
26116
26117
26118
26119
26120
26121
26122
26123
26124
26125
26126
26127
26128
26129
26130
26131
26132
26133
26134
26135
26136
26137
26138
26139
26140
26141
26142
26143
26144
26145
26146
26147
26148
26149
26150
26151
26152
26153
26154
26155
26156
26157
26158
26159
26160
26161
26162
26163
26164
26165
26166
26167
26168
26169
26170
26171
26172
26173
26174
26175
26176
26177
26178
26179
26180
26181
26182
26183
26184
26185
26186
26187
26188
26189
26190
26191
26192
26193
26194
26195
26196
26197
26198
26199
26200
26201
26202
26203
26204
26205
26206
26207
26208
26209
26210
26211
26212
26213
26214
26215
26216
26217
26218
26219
26220
26221
26222
26223
26224
26225
26226
26227
26228
26229
26230
26231
26232
26233
26234
26235
26236
26237
26238
26239
26240
26241
26242
26243
26244
26245
26246
26247
26248
26249
26250
26251
26252
26253
26254
26255
26256
26257
26258
26259
26260
26261
26262
26263
26264
26265
26266
26267
26268
26269
26270
26271
26272
26273
26274
26275
26276
26277
26278
26279
26280
26281
26282
26283
26284
26285
26286
26287
26288
26289
26290
26291
26292
26293
26294
26295
26296
26297
26298
26299
26300
26301
26302
26303
26304
26305
26306
26307
26308
26309
26310
26311
26312
26313
26314
26315
26316
26317
26318
26319
26320
26321
26322
26323
26324
26325
26326
26327
26328
26329
26330
26331
26332
26333
26334
26335
26336
26337
26338
26339
26340
26341
26342
26343
26344
26345
26346
26347
26348
26349
26350
26351
26352
26353
26354
26355
26356
26357
26358
26359
26360
26361
26362
26363
26364
26365
26366
26367
26368
26369
26370
26371
26372
26373
26374
26375
26376
26377
26378
26379
26380
26381
26382
26383
26384
26385
26386
26387
26388
26389
26390
26391
26392
26393
26394
26395
26396
26397
26398
26399
26400
26401
26402
26403
26404
26405
26406
26407
26408
26409
26410
26411
26412
26413
26414
26415
26416
26417
26418
26419
26420
26421
26422
26423
26424
26425
26426
26427
26428
26429
26430
26431
26432
26433
26434
26435
26436
26437
26438
26439
26440
26441
26442
26443
26444
26445
26446
26447
26448
26449
26450
26451
26452
26453
26454
26455
26456
26457
26458
26459
26460
26461
26462
26463
26464
26465
26466
26467
26468
26469
26470
26471
26472
26473
26474
26475
26476
26477
26478
26479
26480
26481
26482
26483
26484
26485
26486
26487
26488
26489
26490
26491
26492
26493
26494
26495
26496
26497
26498
26499
26500
26501
26502
26503
26504
26505
26506
26507
26508
26509
26510
26511
26512
26513
26514
26515
26516
26517
26518
26519
26520
26521
26522
26523
26524
26525
26526
26527
26528
26529
26530
26531
26532
26533
26534
26535
26536
26537
26538
26539
26540
26541
26542
26543
26544
26545
26546
26547
26548
26549
26550
26551
26552
26553
26554
26555
26556
26557
26558
26559
26560
26561
26562
26563
26564
26565
26566
26567
26568
26569
26570
26571
26572
26573
26574
26575
26576
26577
26578
26579
26580
26581
26582
26583
26584
26585
26586
26587
26588
26589
26590
26591
26592
26593
26594
26595
26596
26597
26598
26599
26600
26601
26602
26603
26604
26605
26606
26607
26608
26609
26610
26611
26612
26613
26614
26615
26616
26617
26618
26619
26620
26621
26622
26623
26624
26625
26626
26627
26628
26629
26630
26631
26632
26633
26634
26635
26636
26637
26638
26639
26640
26641
26642
26643
26644
26645
26646
26647
26648
26649
26650
26651
26652
26653
26654
26655
26656
26657
26658
26659
26660
26661
26662
26663
26664
26665
26666
26667
26668
26669
26670
26671
26672
26673
26674
26675
26676
26677
26678
26679
26680
26681
26682
26683
26684
26685
26686
26687
26688
26689
26690
26691
26692
26693
26694
26695
26696
26697
26698
26699
26700
26701
26702
26703
26704
26705
26706
26707
26708
26709
26710
26711
26712
26713
26714
26715
26716
26717
26718
26719
26720
26721
26722
26723
26724
26725
26726
26727
26728
26729
26730
26731
26732
26733
26734
26735
26736
26737
26738
26739
26740
26741
26742
26743
26744
26745
26746
26747
26748
26749
26750
26751
26752
26753
26754
26755
26756
26757
26758
26759
26760
26761
26762
26763
26764
26765
26766
26767
26768
26769
26770
26771
26772
26773
26774
26775
26776
26777
26778
26779
26780
26781
26782
26783
26784
26785
26786
26787
26788
26789
26790
26791
26792
26793
26794
26795
26796
26797
26798
26799
26800
26801
26802
26803
26804
26805
26806
26807
26808
26809
26810
26811
26812
26813
26814
26815
26816
26817
26818
26819
26820
26821
26822
26823
26824
26825
26826
26827
26828
26829
26830
26831
26832
26833
26834
26835
26836
26837
26838
26839
26840
26841
26842
26843
26844
26845
26846
26847
26848
26849
26850
26851
26852
26853
26854
26855
26856
26857
26858
26859
26860
26861
26862
26863
26864
26865
26866
26867
26868
26869
26870
26871
26872
26873
26874
26875
26876
26877
26878
26879
26880
26881
26882
26883
26884
26885
26886
26887
26888
26889
26890
26891
26892
26893
26894
26895
26896
26897
26898
26899
26900
26901
26902
26903
26904
26905
26906
26907
26908
26909
26910
26911
26912
26913
26914
26915
26916
26917
26918
26919
26920
26921
26922
26923
26924
26925
26926
26927
26928
26929
26930
26931
26932
26933
26934
26935
26936
26937
26938
26939
26940
26941
26942
26943
26944
26945
26946
26947
26948
26949
26950
26951
26952
26953
26954
26955
26956
26957
26958
26959
26960
26961
26962
26963
26964
26965
26966
26967
26968
26969
26970
26971
26972
26973
26974
26975
26976
26977
26978
26979
26980
26981
26982
26983
26984
26985
26986
26987
26988
26989
26990
26991
26992
26993
26994
26995
26996
26997
26998
26999
27000
27001
27002
27003
27004
27005
27006
27007
27008
27009
27010
27011
27012
27013
27014
27015
27016
27017
27018
27019
27020
27021
27022
27023
27024
27025
27026
27027
27028
27029
27030
27031
27032
27033
27034
27035
27036
27037
27038
27039
27040
27041
27042
27043
27044
27045
27046
27047
27048
27049
27050
27051
27052
27053
27054
27055
27056
27057
27058
27059
27060
27061
27062
27063
27064
27065
27066
27067
27068
27069
27070
27071
27072
27073
27074
27075
27076
27077
27078
27079
27080
27081
27082
27083
27084
27085
27086
27087
27088
27089
27090
27091
27092
27093
27094
27095
27096
27097
27098
27099
27100
27101
27102
27103
27104
27105
27106
27107
27108
27109
27110
27111
27112
27113
27114
27115
27116
27117
27118
27119
27120
27121
27122
27123
27124
27125
27126
27127
27128
27129
27130
27131
27132
27133
27134
27135
27136
27137
27138
27139
27140
27141
27142
27143
27144
27145
27146
27147
27148
27149
27150
27151
27152
27153
27154
27155
27156
27157
27158
27159
27160
27161
27162
27163
27164
27165
27166
27167
27168
27169
27170
27171
27172
27173
27174
27175
27176
27177
27178
27179
27180
27181
27182
27183
27184
27185
27186
27187
27188
27189
27190
27191
27192
27193
27194
27195
27196
27197
27198
27199
27200
27201
27202
27203
27204
27205
27206
27207
27208
27209
27210
27211
27212
27213
27214
27215
27216
27217
27218
27219
27220
27221
27222
27223
27224
27225
27226
27227
27228
27229
27230
27231
27232
27233
27234
27235
27236
27237
27238
27239
27240
27241
27242
27243
27244
27245
27246
27247
27248
27249
27250
27251
27252
27253
27254
27255
27256
27257
27258
27259
27260
27261
27262
27263
27264
27265
27266
27267
27268
27269
27270
27271
27272
27273
27274
27275
27276
27277
27278
27279
27280
27281
27282
27283
27284
27285
27286
27287
27288
27289
27290
27291
27292
27293
27294
27295
27296
27297
27298
27299
27300
27301
27302
27303
27304
27305
27306
27307
27308
27309
27310
27311
27312
27313
27314
27315
27316
27317
27318
27319
27320
27321
27322
27323
27324
27325
27326
27327
27328
27329
27330
27331
27332
27333
27334
27335
27336
27337
27338
27339
27340
27341
27342
27343
27344
27345
27346
27347
27348
27349
27350
27351
27352
27353
27354
27355
27356
27357
27358
27359
27360
27361
27362
27363
27364
27365
27366
27367
27368
27369
27370
27371
27372
27373
27374
27375
27376
27377
27378
27379
27380
27381
27382
27383
27384
27385
27386
27387
27388
27389
27390
27391
27392
27393
27394
27395
27396
27397
27398
27399
27400
27401
27402
27403
27404
27405
27406
27407
27408
27409
27410
27411
27412
27413
27414
27415
27416
27417
27418
27419
27420
27421
27422
27423
27424
27425
27426
27427
27428
27429
27430
27431
27432
27433
27434
27435
27436
27437
27438
27439
27440
27441
27442
27443
27444
27445
27446
27447
27448
27449
27450
27451
27452
27453
27454
27455
27456
27457
27458
27459
27460
27461
27462
27463
27464
27465
27466
27467
27468
27469
27470
27471
27472
27473
27474
27475
27476
27477
27478
27479
27480
27481
27482
27483
27484
27485
27486
27487
27488
27489
27490
27491
27492
27493
27494
27495
27496
27497
27498
27499
27500
27501
27502
27503
27504
27505
27506
27507
27508
27509
27510
27511
27512
27513
27514
27515
27516
27517
27518
27519
27520
27521
27522
27523
27524
27525
27526
27527
27528
27529
27530
27531
27532
27533
27534
27535
27536
27537
27538
27539
27540
27541
27542
27543
27544
27545
27546
27547
27548
27549
27550
27551
27552
27553
27554
27555
27556
27557
27558
27559
27560
27561
27562
27563
27564
27565
27566
27567
27568
27569
27570
27571
27572
27573
27574
27575
27576
27577
27578
27579
27580
27581
27582
27583
27584
27585
27586
27587
27588
27589
27590
27591
27592
27593
27594
27595
27596
27597
27598
27599
27600
27601
27602
27603
27604
27605
27606
27607
27608
27609
27610
27611
27612
27613
27614
27615
27616
27617
27618
27619
27620
27621
27622
27623
27624
27625
27626
27627
27628
27629
27630
27631
27632
27633
27634
27635
27636
27637
27638
27639
27640
27641
27642
27643
27644
27645
27646
27647
27648
27649
27650
27651
27652
27653
27654
27655
27656
27657
27658
27659
27660
27661
27662
27663
27664
27665
27666
27667
27668
27669
27670
27671
27672
27673
27674
27675
27676
27677
27678
27679
27680
27681
27682
27683
27684
27685
27686
27687
27688
27689
27690
27691
27692
27693
27694
27695
27696
27697
27698
27699
27700
27701
27702
27703
27704
27705
27706
27707
27708
27709
27710
27711
27712
27713
27714
27715
27716
27717
27718
27719
27720
27721
27722
27723
27724
27725
27726
27727
27728
27729
27730
27731
27732
27733
27734
27735
27736
27737
27738
27739
27740
27741
27742
27743
27744
27745
27746
27747
27748
27749
27750
27751
27752
27753
27754
27755
27756
27757
27758
27759
27760
27761
27762
27763
27764
27765
27766
27767
27768
27769
27770
27771
27772
27773
27774
27775
27776
27777
27778
27779
27780
27781
27782
27783
27784
27785
27786
27787
27788
27789
27790
27791
27792
27793
27794
27795
27796
27797
27798
27799
27800
27801
27802
27803
27804
27805
27806
27807
27808
27809
27810
27811
27812
27813
27814
27815
27816
27817
27818
27819
27820
27821
27822
27823
27824
27825
27826
27827
27828
27829
27830
27831
27832
27833
27834
27835
27836
27837
27838
27839
27840
27841
27842
27843
27844
27845
27846
27847
27848
27849
27850
27851
27852
27853
27854
27855
27856
27857
27858
27859
27860
27861
27862
27863
27864
27865
27866
27867
27868
27869
27870
27871
27872
27873
27874
27875
27876
27877
27878
27879
27880
27881
27882
27883
27884
27885
27886
27887
27888
27889
27890
27891
27892
27893
27894
27895
27896
27897
27898
27899
27900
27901
27902
27903
27904
27905
27906
27907
27908
27909
27910
27911
27912
27913
27914
27915
27916
27917
27918
27919
27920
27921
27922
27923
27924
27925
27926
27927
27928
27929
27930
27931
27932
27933
27934
27935
27936
27937
27938
27939
27940
27941
27942
27943
27944
27945
27946
27947
27948
27949
27950
27951
27952
27953
27954
27955
27956
27957
27958
27959
27960
27961
27962
27963
27964
27965
27966
27967
27968
27969
27970
27971
27972
27973
27974
27975
27976
27977
27978
27979
27980
27981
27982
27983
27984
27985
27986
27987
27988
27989
27990
27991
27992
27993
27994
27995
27996
27997
27998
27999
28000
28001
28002
28003
28004
28005
28006
28007
28008
28009
28010
28011
28012
28013
28014
28015
28016
28017
28018
28019
28020
28021
28022
28023
28024
28025
28026
28027
28028
28029
28030
28031
28032
28033
28034
28035
28036
28037
28038
28039
28040
28041
28042
28043
28044
28045
28046
28047
28048
28049
28050
28051
28052
28053
28054
28055
28056
28057
28058
28059
28060
28061
28062
28063
28064
28065
28066
28067
28068
28069
28070
28071
28072
28073
28074
28075
28076
28077
28078
28079
28080
28081
28082
28083
28084
28085
28086
28087
28088
28089
28090
28091
28092
28093
28094
28095
28096
28097
28098
28099
28100
28101
28102
28103
28104
28105
28106
28107
28108
28109
28110
28111
28112
28113
28114
28115
28116
28117
28118
28119
28120
28121
28122
28123
28124
28125
28126
28127
28128
28129
28130
28131
28132
28133
28134
28135
28136
28137
28138
28139
28140
28141
28142
28143
28144
28145
28146
28147
28148
28149
28150
28151
28152
28153
28154
28155
28156
28157
28158
28159
28160
28161
28162
28163
28164
28165
28166
28167
28168
28169
28170
28171
28172
28173
28174
28175
28176
28177
28178
28179
28180
28181
28182
28183
28184
28185
28186
28187
28188
28189
28190
28191
28192
28193
28194
28195
28196
28197
28198
28199
28200
28201
28202
28203
28204
28205
28206
28207
28208
28209
28210
28211
28212
28213
28214
28215
28216
28217
28218
28219
28220
28221
28222
28223
28224
28225
28226
28227
28228
28229
28230
28231
28232
28233
28234
28235
28236
28237
28238
28239
28240
28241
28242
28243
28244
28245
28246
28247
28248
28249
28250
28251
28252
28253
28254
28255
28256
28257
28258
28259
28260
28261
28262
28263
28264
28265
28266
28267
28268
28269
28270
28271
28272
28273
28274
28275
28276
28277
28278
28279
28280
28281
28282
28283
28284
28285
28286
28287
28288
28289
28290
28291
28292
28293
28294
28295
28296
28297
28298
28299
28300
28301
28302
28303
28304
28305
28306
28307
28308
28309
28310
28311
28312
28313
28314
28315
28316
28317
28318
28319
28320
28321
28322
28323
28324
28325
28326
28327
28328
28329
28330
28331
28332
28333
28334
28335
28336
28337
28338
28339
28340
28341
28342
28343
28344
28345
28346
28347
28348
28349
28350
28351
28352
28353
28354
28355
28356
28357
28358
28359
28360
28361
28362
28363
28364
28365
28366
28367
28368
28369
28370
28371
28372
28373
28374
28375
28376
28377
28378
28379
28380
28381
28382
28383
28384
28385
28386
28387
28388
28389
28390
28391
28392
28393
28394
28395
28396
28397
28398
28399
28400
28401
28402
28403
28404
28405
28406
28407
28408
28409
28410
28411
28412
28413
28414
28415
28416
28417
28418
28419
28420
28421
28422
28423
28424
28425
28426
28427
28428
28429
28430
28431
28432
28433
28434
28435
28436
28437
28438
28439
28440
28441
28442
28443
28444
28445
28446
28447
28448
28449
28450
28451
28452
28453
28454
28455
28456
28457
28458
28459
28460
28461
28462
28463
28464
28465
28466
28467
28468
28469
28470
28471
28472
28473
28474
28475
28476
28477
28478
28479
28480
28481
28482
28483
28484
28485
28486
28487
28488
28489
28490
28491
28492
28493
28494
28495
28496
28497
28498
28499
28500
28501
28502
28503
28504
28505
28506
28507
28508
28509
28510
28511
28512
28513
28514
28515
28516
28517
28518
28519
28520
28521
28522
28523
28524
28525
28526
28527
28528
28529
28530
28531
28532
28533
28534
28535
28536
28537
28538
28539
28540
28541
28542
28543
28544
28545
28546
28547
28548
28549
28550
28551
28552
28553
28554
28555
28556
28557
28558
28559
28560
28561
28562
28563
28564
28565
28566
28567
28568
28569
28570
28571
28572
28573
28574
28575
28576
28577
28578
28579
28580
28581
28582
28583
28584
28585
28586
28587
28588
28589
28590
28591
28592
28593
28594
28595
28596
28597
28598
28599
28600
28601
28602
28603
28604
28605
28606
28607
28608
28609
28610
28611
28612
28613
28614
28615
28616
28617
28618
28619
28620
28621
28622
28623
28624
28625
28626
28627
28628
28629
28630
28631
28632
28633
28634
28635
28636
28637
28638
28639
28640
28641
28642
28643
28644
28645
28646
28647
28648
28649
28650
28651
28652
28653
28654
28655
28656
28657
28658
28659
28660
28661
28662
28663
28664
28665
28666
28667
28668
28669
28670
28671
28672
28673
28674
28675
28676
28677
28678
28679
28680
28681
28682
28683
28684
28685
28686
28687
28688
28689
28690
28691
28692
28693
28694
28695
28696
28697
28698
28699
28700
28701
28702
28703
28704
28705
28706
28707
28708
28709
28710
28711
28712
28713
28714
28715
28716
28717
28718
28719
28720
28721
28722
28723
28724
28725
28726
28727
28728
28729
28730
28731
28732
28733
28734
28735
28736
28737
28738
28739
28740
28741
28742
28743
28744
28745
28746
28747
28748
28749
28750
28751
28752
28753
28754
28755
28756
28757
28758
28759
28760
28761
28762
28763
28764
28765
28766
28767
28768
28769
28770
28771
28772
28773
28774
28775
28776
28777
28778
28779
28780
28781
28782
28783
28784
28785
28786
28787
28788
28789
28790
28791
28792
28793
28794
28795
28796
28797
28798
28799
28800
28801
28802
28803
28804
28805
28806
28807
28808
28809
28810
28811
28812
28813
28814
28815
28816
28817
28818
28819
28820
28821
28822
28823
28824
28825
28826
28827
28828
28829
28830
28831
28832
28833
28834
28835
28836
28837
28838
28839
28840
28841
28842
28843
28844
28845
28846
28847
28848
28849
28850
28851
28852
28853
28854
28855
28856
28857
28858
28859
28860
28861
28862
28863
28864
28865
28866
28867
28868
28869
28870
28871
28872
28873
28874
28875
28876
28877
28878
28879
28880
28881
28882
28883
28884
28885
28886
28887
28888
28889
28890
28891
28892
28893
28894
28895
28896
28897
28898
28899
28900
28901
28902
28903
28904
28905
28906
28907
28908
28909
28910
28911
28912
28913
28914
28915
28916
28917
28918
28919
28920
28921
28922
28923
28924
28925
28926
28927
28928
28929
28930
28931
28932
28933
28934
28935
28936
28937
28938
28939
28940
28941
28942
28943
28944
28945
28946
28947
28948
28949
28950
28951
28952
28953
28954
28955
28956
28957
28958
28959
28960
28961
28962
28963
28964
28965
28966
28967
28968
28969
28970
28971
28972
28973
28974
28975
28976
28977
28978
28979
28980
28981
28982
28983
28984
28985
28986
28987
28988
28989
28990
28991
28992
28993
28994
28995
28996
28997
28998
28999
29000
29001
29002
29003
29004
29005
29006
29007
29008
29009
29010
29011
29012
29013
29014
29015
29016
29017
29018
29019
29020
29021
29022
29023
29024
29025
29026
29027
29028
29029
29030
29031
29032
29033
29034
29035
29036
29037
29038
29039
29040
29041
29042
29043
29044
29045
29046
29047
29048
29049
29050
29051
29052
29053
29054
29055
29056
29057
29058
29059
29060
29061
29062
29063
29064
29065
29066
29067
29068
29069
29070
29071
29072
29073
29074
29075
29076
29077
29078
29079
29080
29081
29082
29083
29084
29085
29086
29087
29088
29089
29090
29091
29092
29093
29094
29095
29096
29097
29098
29099
29100
29101
29102
29103
29104
29105
29106
29107
29108
29109
29110
29111
29112
29113
29114
29115
29116
29117
29118
29119
29120
29121
29122
29123
29124
29125
29126
29127
29128
29129
29130
29131
29132
29133
29134
29135
29136
29137
29138
29139
29140
29141
29142
29143
29144
29145
29146
29147
29148
29149
29150
29151
29152
29153
29154
29155
29156
29157
29158
29159
29160
29161
29162
29163
29164
29165
29166
29167
29168
29169
29170
29171
29172
29173
29174
29175
29176
29177
29178
29179
29180
29181
29182
29183
29184
29185
29186
29187
29188
29189
29190
29191
29192
29193
29194
29195
29196
29197
29198
29199
29200
29201
29202
29203
29204
29205
29206
29207
29208
29209
29210
29211
29212
29213
29214
29215
29216
29217
29218
29219
29220
29221
29222
29223
29224
29225
29226
29227
29228
29229
29230
29231
29232
29233
29234
29235
29236
29237
29238
29239
29240
29241
29242
29243
29244
29245
29246
29247
29248
29249
29250
29251
29252
29253
29254
29255
29256
29257
29258
29259
29260
29261
29262
29263
29264
29265
29266
29267
29268
29269
29270
29271
29272
29273
29274
29275
29276
29277
29278
29279
29280
29281
29282
29283
29284
29285
29286
29287
29288
29289
29290
29291
29292
29293
29294
29295
29296
29297
29298
29299
29300
29301
29302
29303
29304
29305
29306
29307
29308
29309
29310
29311
29312
29313
29314
29315
29316
29317
29318
29319
29320
29321
29322
29323
29324
29325
29326
29327
29328
29329
29330
29331
29332
29333
29334
29335
29336
29337
29338
29339
29340
29341
29342
29343
29344
29345
29346
29347
29348
29349
29350
29351
29352
29353
29354
29355
29356
29357
29358
29359
29360
29361
29362
29363
29364
29365
29366
29367
29368
29369
29370
29371
29372
29373
29374
29375
29376
29377
29378
29379
29380
29381
29382
29383
29384
29385
29386
29387
29388
29389
29390
29391
29392
29393
29394
29395
29396
29397
29398
29399
29400
29401
29402
29403
29404
29405
29406
29407
29408
29409
29410
29411
29412
29413
29414
29415
29416
29417
29418
29419
29420
29421
29422
29423
29424
29425
29426
29427
29428
29429
29430
29431
29432
29433
29434
29435
29436
29437
29438
29439
29440
29441
29442
29443
29444
29445
29446
29447
29448
29449
29450
29451
29452
29453
29454
29455
29456
29457
29458
29459
29460
29461
29462
29463
29464
29465
29466
29467
29468
29469
29470
29471
29472
29473
29474
29475
29476
29477
29478
29479
29480
29481
29482
29483
29484
29485
29486
29487
29488
29489
29490
29491
29492
29493
29494
29495
29496
29497
29498
29499
29500
29501
29502
29503
29504
29505
29506
29507
29508
29509
29510
29511
29512
29513
29514
29515
29516
29517
29518
29519
29520
29521
29522
29523
29524
29525
29526
29527
29528
29529
29530
29531
29532
29533
29534
29535
29536
29537
29538
29539
29540
29541
29542
29543
29544
29545
29546
29547
29548
29549
29550
29551
29552
29553
29554
29555
29556
29557
29558
29559
29560
29561
29562
29563
29564
29565
29566
29567
29568
29569
29570
29571
29572
29573
29574
29575
29576
29577
29578
29579
29580
29581
29582
29583
29584
29585
29586
29587
29588
29589
29590
29591
29592
29593
29594
29595
29596
29597
29598
29599
29600
29601
29602
29603
29604
29605
29606
29607
29608
29609
29610
29611
29612
29613
29614
29615
29616
29617
29618
29619
29620
29621
29622
29623
29624
29625
29626
29627
29628
29629
29630
29631
29632
29633
29634
29635
29636
29637
29638
29639
29640
29641
29642
29643
29644
29645
29646
29647
29648
29649
29650
29651
29652
29653
29654
29655
29656
29657
29658
29659
29660
29661
29662
29663
29664
29665
29666
29667
29668
29669
29670
29671
29672
29673
29674
29675
29676
29677
29678
29679
29680
29681
29682
29683
29684
29685
29686
29687
29688
29689
29690
29691
29692
29693
29694
29695
29696
29697
29698
29699
29700
29701
29702
29703
29704
29705
29706
29707
29708
29709
29710
29711
29712
29713
29714
29715
29716
29717
29718
29719
29720
29721
29722
29723
29724
29725
29726
29727
29728
29729
29730
29731
29732
29733
29734
29735
29736
29737
29738
29739
29740
29741
29742
29743
29744
29745
29746
29747
29748
29749
29750
29751
29752
29753
29754
29755
29756
29757
29758
29759
29760
29761
29762
29763
29764
29765
29766
29767
29768
29769
29770
29771
29772
29773
29774
29775
29776
29777
29778
29779
29780
29781
29782
29783
29784
29785
29786
29787
29788
29789
29790
29791
29792
29793
29794
29795
29796
29797
29798
29799
29800
29801
29802
29803
29804
29805
29806
29807
29808
29809
29810
29811
29812
29813
29814
29815
29816
29817
29818
29819
29820
29821
29822
29823
29824
29825
29826
29827
29828
29829
29830
29831
29832
29833
29834
29835
29836
29837
29838
29839
29840
29841
29842
29843
29844
29845
29846
29847
29848
29849
29850
29851
29852
29853
29854
29855
29856
29857
29858
29859
29860
29861
29862
29863
29864
29865
29866
29867
29868
29869
29870
29871
29872
29873
29874
29875
29876
29877
29878
29879
29880
29881
29882
29883
29884
29885
29886
29887
29888
29889
29890
29891
29892
29893
29894
29895
29896
29897
29898
29899
29900
29901
29902
29903
29904
29905
29906
29907
29908
29909
29910
29911
29912
29913
29914
29915
29916
29917
29918
29919
29920
29921
29922
29923
29924
29925
29926
29927
29928
29929
29930
29931
29932
29933
29934
29935
29936
29937
29938
29939
29940
29941
29942
29943
29944
29945
29946
29947
29948
29949
29950
29951
29952
29953
29954
29955
29956
29957
29958
29959
29960
29961
29962
29963
29964
29965
29966
29967
29968
29969
29970
29971
29972
29973
29974
29975
29976
29977
29978
29979
29980
29981
29982
29983
29984
29985
29986
29987
29988
29989
29990
29991
29992
29993
29994
29995
29996
29997
29998
29999
30000
30001
30002
30003
30004
30005
30006
30007
30008
30009
30010
30011
30012
30013
30014
30015
30016
30017
30018
30019
30020
30021
30022
30023
30024
30025
30026
30027
30028
30029
30030
30031
30032
30033
30034
30035
30036
30037
30038
30039
30040
30041
30042
30043
30044
30045
30046
30047
30048
30049
30050
30051
30052
30053
30054
30055
30056
30057
30058
30059
30060
30061
30062
30063
30064
30065
30066
30067
30068
30069
30070
30071
30072
30073
30074
30075
30076
30077
30078
30079
30080
30081
30082
30083
30084
30085
30086
30087
30088
30089
30090
30091
30092
30093
30094
30095
30096
30097
30098
30099
30100
30101
30102
30103
30104
30105
30106
30107
30108
30109
30110
30111
30112
30113
30114
30115
30116
30117
30118
30119
30120
30121
30122
30123
30124
30125
30126
30127
30128
30129
30130
30131
30132
30133
30134
30135
30136
30137
30138
30139
30140
30141
30142
30143
30144
30145
30146
30147
30148
30149
30150
30151
30152
30153
30154
30155
30156
30157
30158
30159
30160
30161
30162
30163
30164
30165
30166
30167
30168
30169
30170
30171
30172
30173
30174
30175
30176
30177
30178
30179
30180
30181
30182
30183
30184
30185
30186
30187
30188
30189
30190
30191
30192
30193
30194
30195
30196
30197
30198
30199
30200
30201
30202
30203
30204
30205
30206
30207
30208
30209
30210
30211
30212
30213
30214
30215
30216
30217
30218
30219
30220
30221
30222
30223
30224
30225
30226
30227
30228
30229
30230
30231
30232
30233
30234
30235
30236
30237
30238
30239
30240
30241
30242
30243
30244
30245
30246
30247
30248
30249
30250
30251
30252
30253
30254
30255
30256
30257
30258
30259
30260
30261
30262
30263
30264
30265
30266
30267
30268
30269
30270
30271
30272
30273
30274
30275
30276
30277
30278
30279
30280
30281
30282
30283
30284
30285
30286
30287
30288
30289
30290
30291
30292
30293
30294
30295
30296
30297
30298
30299
30300
30301
30302
30303
30304
30305
30306
30307
30308
30309
30310
30311
30312
30313
30314
30315
30316
30317
30318
30319
30320
30321
30322
30323
30324
30325
30326
30327
30328
30329
30330
30331
30332
30333
30334
30335
30336
30337
30338
30339
30340
30341
30342
30343
30344
30345
30346
30347
30348
30349
30350
30351
30352
30353
30354
30355
30356
30357
30358
30359
30360
30361
30362
30363
30364
30365
30366
30367
30368
30369
30370
30371
30372
30373
30374
30375
30376
30377
30378
30379
30380
30381
30382
30383
30384
30385
30386
30387
30388
30389
30390
30391
30392
30393
30394
30395
30396
30397
30398
30399
30400
30401
30402
30403
30404
30405
30406
30407
30408
30409
30410
30411
30412
30413
30414
30415
30416
30417
30418
30419
30420
30421
30422
30423
30424
30425
30426
30427
30428
30429
30430
30431
30432
30433
30434
30435
30436
30437
30438
30439
30440
30441
30442
30443
30444
30445
30446
30447
30448
30449
30450
30451
30452
30453
30454
30455
30456
30457
30458
30459
30460
30461
30462
30463
30464
30465
30466
30467
30468
30469
30470
30471
30472
30473
30474
30475
30476
30477
30478
30479
30480
30481
30482
30483
30484
30485
30486
30487
30488
30489
30490
30491
30492
30493
30494
30495
30496
30497
30498
30499
30500
30501
30502
30503
30504
30505
30506
30507
30508
30509
30510
30511
30512
30513
30514
30515
30516
30517
30518
30519
30520
30521
30522
30523
30524
30525
30526
30527
30528
30529
30530
30531
30532
30533
30534
30535
30536
30537
30538
30539
30540
30541
30542
30543
30544
30545
30546
30547
30548
30549
30550
30551
30552
30553
30554
30555
30556
30557
30558
30559
30560
30561
30562
30563
30564
30565
30566
30567
30568
30569
30570
30571
30572
30573
30574
30575
30576
30577
30578
30579
30580
30581
30582
30583
30584
30585
30586
30587
30588
30589
30590
30591
30592
30593
30594
30595
30596
30597
30598
30599
30600
30601
30602
30603
30604
30605
30606
30607
30608
30609
30610
30611
30612
30613
30614
30615
30616
30617
30618
30619
30620
30621
30622
30623
30624
30625
30626
30627
30628
30629
30630
30631
30632
30633
30634
30635
30636
30637
30638
30639
30640
30641
30642
30643
30644
30645
30646
30647
30648
30649
30650
30651
30652
30653
30654
30655
30656
30657
30658
30659
30660
30661
30662
30663
30664
30665
30666
30667
30668
30669
30670
30671
30672
30673
30674
30675
30676
30677
30678
30679
30680
30681
30682
30683
30684
30685
30686
30687
30688
30689
30690
30691
30692
30693
30694
30695
30696
30697
30698
30699
30700
30701
30702
30703
30704
30705
30706
30707
30708
30709
30710
30711
30712
30713
30714
30715
30716
30717
30718
30719
30720
30721
30722
30723
30724
30725
30726
30727
30728
30729
30730
30731
30732
30733
30734
30735
30736
30737
30738
30739
30740
30741
30742
30743
30744
30745
30746
30747
30748
30749
30750
30751
30752
30753
30754
30755
30756
30757
30758
30759
30760
30761
30762
30763
30764
30765
30766
30767
30768
30769
30770
30771
30772
30773
30774
30775
30776
30777
30778
30779
30780
30781
30782
30783
30784
30785
30786
30787
30788
30789
30790
30791
30792
30793
30794
30795
30796
30797
30798
30799
30800
30801
30802
30803
30804
30805
30806
30807
30808
30809
30810
30811
30812
30813
30814
30815
30816
30817
30818
30819
30820
30821
30822
30823
30824
30825
30826
30827
30828
30829
30830
30831
30832
30833
30834
30835
30836
30837
30838
30839
30840
30841
30842
30843
30844
30845
30846
30847
30848
30849
30850
30851
30852
30853
30854
30855
30856
30857
30858
30859
30860
30861
30862
30863
30864
30865
30866
30867
30868
30869
30870
30871
30872
30873
30874
30875
30876
30877
30878
30879
30880
30881
30882
30883
30884
30885
30886
30887
30888
30889
30890
30891
30892
30893
30894
30895
30896
30897
30898
30899
30900
30901
30902
30903
30904
30905
30906
30907
30908
30909
30910
30911
30912
30913
30914
30915
30916
30917
30918
30919
30920
30921
30922
30923
30924
30925
30926
30927
30928
30929
30930
30931
30932
30933
30934
30935
30936
30937
30938
30939
30940
30941
30942
30943
30944
30945
30946
30947
30948
30949
30950
30951
30952
30953
30954
30955
30956
30957
30958
30959
30960
30961
30962
30963
30964
30965
30966
30967
30968
30969
30970
30971
30972
30973
30974
30975
30976
30977
30978
30979
30980
30981
30982
30983
30984
30985
30986
30987
30988
30989
30990
30991
30992
30993
30994
30995
30996
30997
30998
30999
31000
31001
31002
31003
31004
31005
31006
31007
31008
31009
31010
31011
31012
31013
31014
31015
31016
31017
31018
31019
31020
31021
31022
31023
31024
31025
31026
31027
31028
31029
31030
31031
31032
31033
31034
31035
31036
31037
31038
31039
31040
31041
31042
31043
31044
31045
31046
31047
31048
31049
31050
31051
31052
31053
31054
31055
31056
31057
31058
31059
31060
31061
31062
31063
31064
31065
31066
31067
31068
31069
31070
31071
31072
31073
31074
31075
31076
31077
31078
31079
31080
31081
31082
31083
31084
31085
31086
31087
31088
31089
31090
31091
31092
31093
31094
31095
31096
31097
31098
31099
31100
31101
31102
31103
31104
31105
31106
31107
31108
31109
31110
31111
31112
31113
31114
31115
31116
31117
31118
31119
31120
31121
31122
31123
31124
31125
31126
31127
31128
31129
31130
31131
31132
31133
31134
31135
31136
31137
31138
31139
31140
31141
31142
31143
31144
31145
31146
31147
31148
31149
31150
31151
31152
31153
31154
31155
31156
31157
31158
31159
31160
31161
31162
31163
31164
31165
31166
31167
31168
31169
31170
31171
31172
31173
31174
31175
31176
31177
31178
31179
31180
31181
31182
31183
31184
31185
31186
31187
31188
31189
31190
31191
31192
31193
31194
31195
31196
31197
31198
31199
31200
31201
31202
31203
31204
31205
31206
31207
31208
31209
31210
31211
31212
31213
31214
31215
31216
31217
31218
31219
31220
31221
31222
31223
31224
31225
31226
31227
31228
31229
31230
31231
31232
31233
31234
31235
31236
31237
31238
31239
31240
31241
31242
31243
31244
31245
31246
31247
31248
31249
31250
31251
31252
31253
31254
31255
31256
31257
31258
31259
31260
31261
31262
31263
31264
31265
31266
31267
31268
31269
31270
31271
31272
31273
31274
31275
31276
31277
31278
31279
31280
31281
31282
31283
31284
31285
31286
31287
31288
31289
31290
31291
31292
31293
31294
31295
31296
31297
31298
31299
31300
31301
31302
31303
31304
31305
31306
31307
31308
31309
31310
31311
31312
31313
31314
31315
31316
31317
31318
31319
31320
31321
31322
31323
31324
31325
31326
31327
31328
31329
31330
31331
31332
31333
31334
31335
31336
31337
31338
31339
31340
31341
31342
31343
31344
31345
31346
31347
31348
31349
31350
31351
31352
31353
31354
31355
31356
31357
31358
31359
31360
31361
31362
31363
31364
31365
31366
31367
31368
31369
31370
31371
31372
31373
31374
31375
31376
31377
31378
31379
31380
31381
31382
31383
31384
31385
31386
31387
31388
31389
31390
31391
31392
31393
31394
31395
31396
31397
31398
31399
31400
31401
31402
31403
31404
31405
31406
31407
31408
31409
31410
31411
31412
31413
31414
31415
31416
31417
31418
31419
31420
31421
31422
31423
31424
31425
31426
31427
31428
31429
31430
31431
31432
31433
31434
31435
31436
31437
31438
31439
31440
31441
31442
31443
31444
31445
31446
31447
31448
31449
31450
31451
31452
31453
31454
31455
31456
31457
31458
31459
31460
31461
31462
31463
31464
31465
31466
31467
31468
31469
31470
31471
31472
31473
31474
31475
31476
31477
31478
31479
31480
31481
31482
31483
31484
31485
31486
31487
31488
31489
31490
31491
31492
31493
31494
31495
31496
31497
31498
31499
31500
31501
31502
31503
31504
31505
31506
31507
31508
31509
31510
31511
31512
31513
31514
31515
31516
31517
31518
31519
31520
31521
31522
31523
31524
31525
31526
31527
31528
31529
31530
31531
31532
31533
31534
31535
31536
31537
31538
31539
31540
31541
31542
31543
31544
31545
31546
31547
31548
31549
31550
31551
31552
31553
31554
31555
31556
31557
31558
31559
31560
31561
31562
31563
31564
31565
31566
31567
31568
31569
31570
31571
31572
31573
31574
31575
31576
31577
31578
31579
31580
31581
31582
31583
31584
31585
31586
31587
31588
31589
31590
31591
31592
31593
31594
31595
31596
31597
31598
31599
31600
31601
31602
31603
31604
31605
31606
31607
31608
31609
31610
31611
31612
31613
31614
31615
31616
31617
31618
31619
31620
31621
31622
31623
31624
31625
31626
31627
31628
31629
31630
31631
31632
31633
31634
31635
31636
31637
31638
31639
31640
31641
31642
31643
31644
31645
31646
31647
31648
31649
31650
31651
31652
31653
31654
31655
31656
31657
31658
31659
31660
31661
31662
31663
31664
31665
31666
31667
31668
31669
31670
31671
31672
31673
31674
31675
31676
31677
31678
31679
31680
31681
31682
31683
31684
31685
31686
31687
31688
31689
31690
31691
31692
31693
31694
31695
31696
31697
31698
31699
31700
31701
31702
31703
31704
31705
31706
31707
31708
31709
31710
31711
31712
31713
31714
31715
31716
31717
31718
31719
31720
31721
31722
31723
31724
31725
31726
31727
31728
31729
31730
31731
31732
31733
31734
31735
31736
31737
31738
31739
31740
31741
31742
31743
31744
31745
31746
31747
31748
31749
31750
31751
31752
31753
31754
31755
31756
31757
31758
31759
31760
31761
31762
31763
31764
31765
31766
31767
31768
31769
31770
31771
31772
31773
31774
31775
31776
31777
31778
31779
31780
31781
31782
31783
31784
31785
31786
31787
31788
31789
31790
31791
31792
31793
31794
31795
31796
31797
31798
31799
31800
31801
31802
31803
31804
31805
31806
31807
31808
31809
31810
31811
31812
31813
31814
31815
31816
31817
31818
31819
31820
31821
31822
31823
31824
31825
31826
31827
31828
31829
31830
31831
31832
31833
31834
31835
31836
31837
31838
31839
31840
31841
31842
31843
31844
31845
31846
31847
31848
31849
31850
31851
31852
31853
31854
31855
31856
31857
31858
31859
31860
31861
31862
31863
31864
31865
31866
31867
31868
31869
31870
31871
31872
31873
31874
31875
31876
31877
31878
31879
31880
31881
31882
31883
31884
31885
31886
31887
31888
31889
31890
31891
31892
31893
31894
31895
31896
31897
31898
31899
31900
31901
31902
31903
31904
31905
31906
31907
31908
31909
31910
31911
31912
31913
31914
31915
31916
31917
31918
31919
31920
31921
31922
31923
31924
31925
31926
31927
31928
31929
31930
31931
31932
31933
31934
31935
31936
31937
31938
31939
31940
31941
31942
31943
31944
31945
31946
31947
31948
31949
31950
31951
31952
31953
31954
31955
31956
31957
31958
31959
31960
31961
31962
31963
31964
31965
31966
31967
31968
31969
31970
31971
31972
31973
31974
31975
31976
31977
31978
31979
31980
31981
31982
31983
31984
31985
31986
31987
31988
31989
31990
31991
31992
31993
31994
31995
31996
31997
31998
31999
32000
32001
32002
32003
32004
32005
32006
32007
32008
32009
32010
32011
32012
32013
32014
32015
32016
32017
32018
32019
32020
32021
32022
32023
32024
32025
32026
32027
32028
32029
32030
32031
32032
32033
32034
32035
32036
32037
32038
32039
32040
32041
32042
32043
32044
32045
32046
32047
32048
32049
32050
32051
32052
32053
32054
32055
32056
32057
32058
32059
32060
32061
32062
32063
32064
32065
32066
32067
32068
32069
32070
32071
32072
32073
32074
32075
32076
32077
32078
32079
32080
32081
32082
32083
32084
32085
// Universal solver implementation for the demo worker.
//
// Every reasoning path here mirrors the Rust `FormalAiEngine` in
// `src/solver.rs` so the website, CLI, Telegram bot, library, and HTTP server
// all produce the same answers for the same prompts. The answer the user
// sees is always a projection of an append-only event log — there is no
// hardcoded prompt→answer table.
//
// All multilingual phrases, concept summaries, and the tool registry are
// loaded from `seed/*.lino` files at startup via `seed_loader.js`. Editing a
// `.lino` file is enough to retune the agent — no JavaScript change required.

function currentAssetVersion() {
  try {
    const search = self.location && self.location.search;
    const match = search && /[?&]v=([^&]+)/.exec(search);
    return match ? decodeURIComponent(match[1].replace(/\+/g, " ")) : "";
  } catch (_error) {
    return "";
  }
}

function withAssetVersion(url) {
  const version = currentAssetVersion();
  if (!version) return url;
  return `${url}${url.includes("?") ? "&" : "?"}v=${encodeURIComponent(
    version,
  )}`;
}

try {
  importScripts(withAssetVersion("seed_loader.js"));
} catch (_error) {
  // Seed loader is optional: tests that mock the worker may exclude it.
}

let wasm;
let mode = "wasm worker";

// Hard-coded fallbacks. These are only used if `seed/*.lino` fails to load,
// e.g. when the worker runs from a `file://` URL. The shipped GitHub Pages
// build always fetches the seed successfully.
const FALLBACK_IDENTITY_ANSWER =
  "I am formal-ai, a deterministic symbolic AI implementation that answers from local Links Notation rules and OpenAI-compatible API shapes. I do not perform neural inference in this demo.";

const FALLBACK_ASSISTANT_NAME_ANSWER =
  "I'm formal AI, and currently I don't have a name. But you can name me as you like.";

const FALLBACK_GREETING_ANSWER = "Hi, how may I help you?";

const FALLBACK_TEST_STATUS_ANSWER = "Test passed. I'm here.";
const FALLBACK_COURTESY_RESPONSE_ANSWER =
  "Glad to hear it. What would you like to do next?";
const FALLBACK_COURTESY_ACKNOWLEDGEMENTS = [
  "Glad to hear it.",
  "You're welcome.",
];
const FALLBACK_COURTESY_FOLLOW_UPS = [
  "What would you like to do next?",
  "Do you want to discuss something else?",
];

const FALLBACK_UNKNOWN_ANSWER =
  "I don't know how to answer that yet. I cannot answer that from local Links Notation rules yet. To inspect what I can do, send `List behavior rules`, then `Show behavior rule unknown`. To teach this dialog a response, send: When I say `your prompt`, answer `your answer`. If this still needs a shared Links Notation seed fact or rule after those checks, use Report issue with the reasoning trace, or export memory to keep a dialog-local rule durable.";

const FALLBACK_CLARIFICATION_ANSWER =
  "I'm sorry for the confusion. I am formal-ai, a deterministic symbolic AI. I can answer greetings, identity questions, concept lookups (what is X?), arithmetic, and parameterized program templates. If you'd like to ask about something specific, try one of those or add a fact in Links Notation.";

// Mutable runtime tables — populated from seed at init(). Each entry is
// `{ text, variants }` so the worker can return either the canonical phrase
// (for deterministic tests and tool calls) or a random variant (for greeting
// randomisation introduced in issue #27). Courtesy responses can also carry
// separated acknowledgement and follow-up fragments for issue #160.
let MULTILINGUAL_ANSWERS = {
  greeting: {
    en: { text: FALLBACK_GREETING_ANSWER, variants: [FALLBACK_GREETING_ANSWER] },
  },
  farewell: {
    en: { text: "Goodbye! Feel free to return any time.", variants: ["Goodbye! Feel free to return any time."] },
  },
  test_status: {
    en: { text: FALLBACK_TEST_STATUS_ANSWER, variants: [FALLBACK_TEST_STATUS_ANSWER] },
  },
  courtesy_response: {
    en: {
      text: FALLBACK_COURTESY_RESPONSE_ANSWER,
      variants: [FALLBACK_COURTESY_RESPONSE_ANSWER],
      acknowledgements: FALLBACK_COURTESY_ACKNOWLEDGEMENTS,
      followUps: FALLBACK_COURTESY_FOLLOW_UPS,
    },
  },
  identity: {
    en: { text: FALLBACK_IDENTITY_ANSWER, variants: [FALLBACK_IDENTITY_ANSWER] },
  },
  assistant_name: {
    en: {
      text: FALLBACK_ASSISTANT_NAME_ANSWER,
      variants: [FALLBACK_ASSISTANT_NAME_ANSWER],
    },
  },
  clarification: {
    en: {
      text: FALLBACK_CLARIFICATION_ANSWER,
      variants: [FALLBACK_CLARIFICATION_ANSWER],
    },
  },
  unknown: {
    en: { text: FALLBACK_UNKNOWN_ANSWER, variants: [FALLBACK_UNKNOWN_ANSWER] },
  },
};
let CONCEPTS = [];
let CONCEPT_CONTEXTS = [];
let FACTS = [];
let PROJECTS = [];
let BRAINSTORM_SEEDS = {
  triggers: [
    "brainstorm",
    "give me five ideas",
    "give me 5 ideas",
    "give me ten ideas",
    "give me 10 ideas",
    "suggest five",
    "suggest 5",
    "suggest ten",
    "suggest 10",
  ],
  categories: [
    {
      slug: "project_ideas",
      intent: "brainstorm_project_ideas",
      detectionKeywords: [],
      items: [
        "A local Links Notation notebook with searchable traces.",
        "A deterministic code-review checklist generator.",
        "A multilingual prompt-variation test corpus.",
        "A CLI that converts issue requirements into traceable tests.",
        "A source-cache inspector for reproducible agent runs.",
        "A changelog-fragment consistency checker.",
        "A prompt-matrix generator for four-language smoke tests.",
        "A Wikidata anchor verifier for local seed records.",
        "A trace viewer that groups events by solver phase.",
        "A small offline issue-to-test planning tool.",
      ],
    },
  ],
};
let PERSONA_SEEDS = {
  triggers: ["pretend you are", "act as", "roleplay", "explain like you are"],
  defaultPersona: "requested persona",
  bodyTemplate:
    "Roleplay frame recorded for <persona>. I will keep the persona explicit and factual: <body>",
  fallbackBody:
    "relativity says measurements of space and time depend on the observer's motion, while the laws of physics stay consistent.",
  personas: [
    { displayName: "Albert Einstein", aliases: ["einstein"], wikidata: "Q937" },
    { displayName: "Ada Lovelace", aliases: ["ada lovelace"], wikidata: "Q7259" },
    { displayName: "teacher", aliases: ["teacher"], wikidata: "" },
  ],
  topics: [
    {
      slug: "algorithm",
      detectionKeywords: ["algorithm", "algorithms"],
      body:
        "an algorithm is a precise sequence of steps, so a reliable explanation names the inputs, the ordered operations, and the expected result.",
    },
    {
      slug: "time_dilation",
      detectionKeywords: ["time dilation"],
      body:
        "time dilation means clocks can measure different elapsed times when observers move differently or sit in different gravitational fields.",
    },
  ],
};
let TOOLS = [];
let SEED_RAW = {};
let AGENT_INFO = {};
let LANGUAGE_RULES = [
  { language: "ru", start: 0x0400, end: 0x04ff },
  { language: "hi", start: 0x0900, end: 0x097f },
  { language: "zh", start: 0x4e00, end: 0x9fff },
];
let PROMPT_PATTERNS = [];
// Intent routing rules loaded from `seed/intent-routing.lino` at init time.
// `intents` mirror `seed::IntentRoute` from the Rust crate, so the browser
// and the Rust solver behave identically when classifying prompts. The
// fallback below mirrors the contents of `data/seed/intent-routing.lino`
// so the worker remains functional even when the `.lino` fetch fails (for
// example when the demo is opened from `file://`).
let INTENT_ROUTING = {
  intents: [
    {
      id: "intent_greeting",
      slug: "greeting",
      responseLink: "response:greeting",
      keywords: [
        "hi",
        "hello",
        "hey",
        "привет",
        "здравствуйте",
        "шалом",
        "नमस्ते",
        "नमस्कार",
        "सलाम",
        "हाय",
        "你好",
        "您好",
        "嗨",
        "哈喽",
      ],
      phrases: [
        "how are you",
        "how are you doing",
        "how do you do",
        "how is it going",
        "how s it going",
        "how are things",
        "шабат шалом",
        "как дела",
        "как твои дела",
        "как ваши дела",
        "как у тебя дела",
        "как у вас дела",
        "привет как дела",
        "здравствуйте как ваши дела",
        "как поживаешь",
        "как вы поживаете",
        "राम राम",
        "कैसे हो",
        "आप कैसे हैं",
        "तुम कैसे हो",
        "क्या हाल है",
        "आपका क्या हाल है",
        "सब कैसा चल रहा है",
        "早上好",
        "早安",
        "你好吗",
        "你还好吗",
        "你怎么样",
        "您怎么样",
        "最近怎么样",
        "过得怎么样",
      ],
      tokens: ["greet"],
      combos: [],
    },
    {
      id: "intent_farewell",
      slug: "farewell",
      responseLink: "response:farewell",
      keywords: [
        "bye",
        "goodbye",
        "пока",
        "ciao",
        "tschüss",
        "再见",
        "拜拜",
        "回见",
        "अलविदा",
        "विदा",
        "बाय",
        "टाटा",
      ],
      phrases: ["до свидания", "досвидания", "改天见", "后会有期", "फिर मिलेंगे"],
      tokens: [],
      combos: [],
    },
    {
      id: "intent_courtesy_response",
      slug: "courtesy_response",
      responseLink: "response:courtesy_response",
      keywords: ["thanks", "спасибо", "благодарю", "धन्यवाद", "शुक्रिया", "谢谢"],
      phrases: [
        "thank you",
        "i am fine thank you",
        "i am fine thanks",
        "i m fine thank you",
        "i m fine thanks",
        "i am good thank you",
        "i am good thanks",
        "i m good thank you",
        "i m good thanks",
        "fine thank you",
        "fine thanks",
        "good thank you",
        "good thanks",
        "doing well thank you",
        "doing well thanks",
        "у меня все хорошо спасибо",
        "у меня всё хорошо спасибо",
        "все хорошо спасибо",
        "всё хорошо спасибо",
        "хорошо спасибо",
        "нормально спасибо",
        "ого чето начал соображать",
        "ого чёто начал соображать",
        "ого чё то начал соображать",
        "ого что то начал соображать",
        "मैं ठीक हूँ धन्यवाद",
        "ठीक हूँ धन्यवाद",
        "मैं अच्छा हूँ धन्यवाद",
        "我很好谢谢",
        "我很好 谢谢",
        "好的谢谢",
        "好的 谢谢",
      ],
      tokens: [],
      combos: [],
    },
    {
      id: "intent_test_status",
      slug: "test_status",
      responseLink: "response:test_status",
      keywords: [
        "test",
        "ping",
        "pong",
        "testing",
        "тест",
        "пинг",
        "टेस्ट",
        "परीक्षण",
        "测试",
        "測試",
      ],
      phrases: [
        "test passed",
        "testing 123",
        "are you there",
        "you there",
        "i m here",
        "i am here",
        "я здесь",
        "тест пройден",
        "ты здесь",
        "вы здесь",
        "परीक्षण सफल रहा",
        "मैं यहाँ हूँ",
        "मैं यहां हूं",
        "क्या आप वहाँ हैं",
        "क्या आप वहां हैं",
        "测试通过",
        "測試通過",
        "我在这里",
        "我在這裡",
        "你在吗",
        "您在吗",
        "你在嗎",
        "您在嗎",
      ],
      tokens: [],
      combos: [
        ["test", "passed"],
        ["test", "here"],
        ["testing", "123"],
        ["ping", "test"],
        ["тест", "пройден"],
        ["тест", "здесь"],
        ["परीक्षण", "सफल"],
      ],
    },
    {
      id: "intent_assistant_name",
      slug: "assistant_name",
      responseLink: "response:assistant_name",
      keywords: [],
      phrases: [
        "what is your name",
        "what s your name",
        "what's your name",
        "do you have a name",
        "what should i call you",
        "как твое имя",
        "как твоё имя",
        "как тебя зовут",
        "у тебя есть имя",
        "आपका नाम क्या है",
        "तुम्हारा नाम क्या है",
        "你叫什么名字",
        "您叫什么名字",
        "你的名字是什么",
        "你有名字吗",
      ],
      tokens: [],
      combos: [
        ["what", "your", "name"],
        ["you", "have", "name"],
        ["call", "you"],
        ["как", "тебя", "зовут"],
      ],
    },
    {
      id: "intent_identity",
      slug: "identity",
      responseLink: "response:identity",
      keywords: [],
      phrases: [
        "who are you",
        "what are you",
        "who is formal ai",
        "what is formal ai",
        "who is formalai",
        "what is formalai",
        "tell me about yourself",
        "introduce yourself",
        "let s get acquainted",
        "lets get acquainted",
        "let us get acquainted",
        "let s get to know each other",
        "кто ты",
        "что ты",
        "расскажи о себе",
        "расскажи мне о себе",
        "расскажи про себя",
        "опиши себя",
        "представься",
        "давай знакомиться",
        "давай познакомимся",
        "давайте познакомимся",
        "तुम कौन हो",
        "तू कौन है",
        "आप कौन हैं",
        "अपना परिचय दो",
        "अपने बारे में बताओ",
        "चलो परिचय करते हैं",
        "आइए परिचय करें",
        "चलो एक दूसरे को जानें",
        "你是谁",
        "您是谁",
        "你是什么",
        "介绍一下你自己",
        "告诉我你自己",
        "你是誰",
        "我们认识一下吧",
        "认识一下吧",
        "让我们认识一下",
      ],
      tokens: [],
      combos: [
        ["who", "you"],
        ["what", "you"],
        ["tell", "yourself"],
        ["introduce", "yourself"],
        ["let", "s", "acquainted"],
        ["lets", "acquainted"],
        ["let", "us", "acquainted"],
        ["know", "each", "other"],
        ["кто", "ты"],
        ["что", "ты"],
        ["расскажи", "себе"],
        ["опиши", "себя"],
        ["давай", "знакомиться"],
        ["давай", "познакомимся"],
        ["давайте", "познакомимся"],
        ["चलो", "परिचय"],
        ["आइए", "परिचय"],
        ["who", "formal", "ai"],
        ["what", "formal", "ai"],
      ],
    },
  ],
  articlePrefixes: ["the ", "a ", "an "],
  tracePrefixes: ["answer_", "trace_"],
};

function fallbackEntry(intent) {
  if (intent === "greeting") {
    return { text: FALLBACK_GREETING_ANSWER, variants: [FALLBACK_GREETING_ANSWER] };
  }
  if (intent === "courtesy_response") {
    return {
      text: FALLBACK_COURTESY_RESPONSE_ANSWER,
      variants: [FALLBACK_COURTESY_RESPONSE_ANSWER],
      acknowledgements: FALLBACK_COURTESY_ACKNOWLEDGEMENTS,
      followUps: FALLBACK_COURTESY_FOLLOW_UPS,
    };
  }
  if (intent === "identity") {
    return { text: FALLBACK_IDENTITY_ANSWER, variants: [FALLBACK_IDENTITY_ANSWER] };
  }
  if (intent === "assistant_name") {
    return {
      text: FALLBACK_ASSISTANT_NAME_ANSWER,
      variants: [FALLBACK_ASSISTANT_NAME_ANSWER],
    };
  }
  if (intent === "test_status") {
    return { text: FALLBACK_TEST_STATUS_ANSWER, variants: [FALLBACK_TEST_STATUS_ANSWER] };
  }
  if (intent === "clarification") {
    return {
      text: FALLBACK_CLARIFICATION_ANSWER,
      variants: [FALLBACK_CLARIFICATION_ANSWER],
    };
  }
  return { text: FALLBACK_UNKNOWN_ANSWER, variants: [FALLBACK_UNKNOWN_ANSWER] };
}

function normalizeEntry(value, intent) {
  if (value && typeof value === "object" && typeof value.text === "string") {
    const variants =
      Array.isArray(value.variants) && value.variants.length > 0
        ? value.variants
        : [value.text];
    const acknowledgements = Array.isArray(value.acknowledgements)
      ? value.acknowledgements.filter(Boolean)
      : [];
    const followUps = Array.isArray(value.followUps)
      ? value.followUps.filter(Boolean)
      : [];
    return {
      text: value.text,
      variants: variants,
      acknowledgements: acknowledgements,
      followUps: followUps,
    };
  }
  if (typeof value === "string") {
    return {
      text: value,
      variants: [value],
      acknowledgements: [],
      followUps: [],
    };
  }
  return fallbackEntry(intent);
}

function responseEntryFor(intent, language) {
  const table = MULTILINGUAL_ANSWERS[intent] || {};
  const raw = table[language] || table.en || fallbackEntry(intent);
  return normalizeEntry(raw, intent);
}

function answerFor(intent, language, options) {
  const opts = options || {};
  const entry = responseEntryFor(intent, language);
  if (opts.randomize && Array.isArray(entry.variants) && entry.variants.length > 1) {
    const idx = Math.floor(Math.random() * entry.variants.length);
    return entry.variants[idx] || entry.text;
  }
  return entry.text;
}

function normalizeAssistantNamePreference(value) {
  return String(value || "")
    .replace(/[\r\n\t]+/g, " ")
    .replace(/\s+/g, " ")
    .trim()
    .replace(/^[`"']+|[`"']+$/g, "")
    .trim()
    .slice(0, 64);
}

function assistantNameAnswer(language, preferences) {
  const name = normalizeAssistantNamePreference(
    preferences && preferences.assistantName,
  );
  if (!name) return answerFor("assistant_name", language);
  if (language === "ru") {
    return `Меня зовут ${name}. Я formal AI.`;
  }
  if (language === "hi") {
    return `मेरा नाम ${name} है। मैं formal AI हूँ।`;
  }
  if (language === "zh") {
    return `我的名字是 ${name}。我是 formal AI。`;
  }
  return `My name is ${name}. I'm formal AI.`;
}

// Mirrors `src/engine.rs::UNKNOWN_OPENERS_*`. The first entry of each pool
// equals the opener already embedded in the seed text so the "with-variations"
// answer is a strict superset of the seed. Different prompts get different
// openers; the same prompt always picks the same one (FNV-1a hash, mirrored
// from `stableBehaviorRuleId`).
const UNKNOWN_OPENERS_BY_LANGUAGE = {
  en: [
    "I don't know how to answer that yet.",
    "I didn't understand you.",
    "I'm not sure how to respond to that yet.",
    "I haven't learned to answer that yet.",
    "That one is new to me.",
  ],
  ru: [
    "Я пока не знаю, как ответить на это.",
    "Я тебя не понял.",
    "Я не уверен, как на это ответить.",
    "Я ещё не научился отвечать на это.",
    "Это для меня новое.",
  ],
  hi: [
    "मुझे अभी इसका उत्तर देना नहीं आता।",
    "मैं समझ नहीं पाया।",
    "मुझे यकीन नहीं है कि कैसे उत्तर दूँ।",
    "मैंने अभी तक यह उत्तर देना नहीं सीखा।",
    "यह मेरे लिए नया है।",
  ],
  zh: [
    "我还不知道如何回答这个问题。",
    "我不太明白你说的意思。",
    "我不确定该如何回答。",
    "我还没有学会回答这个问题。",
    "这对我来说是新的。",
  ],
};

function unknownOpenersFor(language) {
  return UNKNOWN_OPENERS_BY_LANGUAGE[language] || UNKNOWN_OPENERS_BY_LANGUAGE.en;
}

function selectUnknownOpener(prompt, language) {
  const fromWasm = wasmSelectUnknownOpener(prompt, language);
  if (fromWasm) return fromWasm;
  const pool = unknownOpenersFor(language);
  const trimmed = String(prompt || "").trim();
  if (trimmed === "") return pool[0];
  const id = stableBehaviorRuleId("unknown_opener", trimmed);
  const hex = id.split("_").pop() || "0";
  let value;
  try {
    value = BigInt(`0x${hex}`);
  } catch (_err) {
    value = 0n;
  }
  const index = Number(value % BigInt(pool.length));
  return pool[index] || pool[0];
}

function stripLeadingUnknownOpener(text, language) {
  const trimmed = String(text || "").trimStart();
  const openers = unknownOpenersFor(language);
  for (const known of openers) {
    if (trimmed.startsWith(known)) {
      return trimmed.slice(known.length).trimStart();
    }
  }
  for (const separator of [". ", "。", "। "]) {
    const idx = trimmed.indexOf(separator);
    if (idx >= 0) {
      return trimmed.slice(idx + separator.length).trimStart();
    }
  }
  return trimmed;
}

function unknownAnswerWithVariation(prompt, language) {
  const seedText = answerFor("unknown", language);
  const opener = selectUnknownOpener(prompt, language);
  const body = stripLeadingUnknownOpener(seedText, language);
  if (!body) return opener;
  return `${opener} ${body}`;
}

function numericPreference(value, fallback, min, max) {
  const parsed = Number(value);
  if (!Number.isFinite(parsed)) return fallback;
  return Math.min(max, Math.max(min, parsed));
}

function pickVariant(values, randomize) {
  if (!Array.isArray(values) || values.length === 0) return "";
  if (!randomize || values.length === 1) return values[0];
  return values[Math.floor(Math.random() * values.length)] || values[0];
}

function includeFollowUpQuestion(probability, randomize) {
  if (probability <= 0) return false;
  if (probability >= 1) return true;
  if (!randomize) return probability >= 0.5;
  return Math.random() < probability;
}

function courtesyResponseFor(language, preferences) {
  const prefs = preferences || {};
  const entry = responseEntryFor("courtesy_response", language);
  const temperature = numericPreference(prefs.temperature, 0.7, 0, 1);
  const followUpProbability = numericPreference(
    prefs.followUpProbability,
    0.75,
    0,
    1,
  );
  const randomize = temperature > 0;
  const acknowledgements =
    entry.acknowledgements.length > 0 ? entry.acknowledgements : [entry.text];
  const followUps = entry.followUps;
  const acknowledgement = pickVariant(acknowledgements, randomize);
  const includeFollowUp =
    followUps.length > 0 &&
    includeFollowUpQuestion(followUpProbability, randomize);
  return {
    content: includeFollowUp
      ? `${acknowledgement} ${pickVariant(followUps, randomize)}`
      : acknowledgement,
    temperature: temperature,
    randomize: randomize,
    followUpProbability: followUpProbability,
    followUpIncluded: includeFollowUp,
  };
}

function definitionFusionByDefault(preferences) {
  const value = preferences && preferences.definitionFusion;
  if (value === true) return true;
  if (value === false) return false;
  const normalized = String(value || "").trim().toLowerCase();
  return ["auto", "on", "true", "1", "merge", "fusion"].includes(normalized);
}

// Language detection and prompt normalization are owned by the Rust core
// (`src/web_engine_core.rs`) and exposed to the worker through the WASM
// exports `engine_detect_language` and `engine_normalize_prompt`. The JS
// branches below are pre-WASM fallbacks used during init() and on browsers
// that could not instantiate the worker — they must stay byte-for-byte
// compatible with the Rust path so the offline trace and the live answer
// agree (PR #134 feedback 4489651616).
function detectLanguage(prompt) {
  const text = String(prompt || "");
  const fromWasm = wasmDetectLanguage(text);
  if (fromWasm !== null) {
    if (fromWasm === "unknown") {
      return AGENT_INFO.default_language || "en";
    }
    return fromWasm;
  }
  for (const ch of text) {
    const code = ch.codePointAt(0);
    for (const rule of LANGUAGE_RULES) {
      if (
        rule.language !== "en" &&
        code >= rule.start &&
        code <= rule.end
      ) {
        return rule.language;
      }
    }
  }
  if (/[a-zA-Z]/.test(text)) return "en";
  return AGENT_INFO.default_language || "en";
}

// Issue #324: the user can choose which language drives responses. The default
// ("last_message") answers in the detected language of the current message
// (fixing the Russian-prompt/English-answer bug). "preferred" pins responses to
// an explicitly selected language and "ui" follows the UI-language preference.
// Both fall back to the detected language when their source is "auto"/unset so
// the deterministic default behavior is never lost.
const RESPONSE_LANGUAGE_MODES = ["last_message", "preferred", "ui"];

function isKnownResponseLanguage(slug) {
  return slug === "en" || slug === "ru" || slug === "hi" || slug === "zh";
}

function responseLanguageFor(detected, preferences, userContext) {
  const prefs = preferences || {};
  const mode = RESPONSE_LANGUAGE_MODES.includes(prefs.responseLanguage)
    ? prefs.responseLanguage
    : "last_message";
  if (mode === "preferred" && isKnownResponseLanguage(prefs.preferredLanguage)) {
    return prefs.preferredLanguage;
  }
  if (mode === "ui") {
    if (isKnownResponseLanguage(prefs.uiLanguage)) return prefs.uiLanguage;
    // "auto" UI language follows the browser; fall back to the detected
    // message language when no concrete browser language is supplied.
    // `browserLanguages` may arrive as an array or a comma-joined string
    // (see `collectUserContext` in app.js).
    const raw = userContext ? userContext.browserLanguages : null;
    const browser = Array.isArray(raw)
      ? raw
      : typeof raw === "string"
        ? raw.split(",")
        : [];
    for (const tag of browser) {
      const slug = String(tag || "").slice(0, 2).toLowerCase();
      if (isKnownResponseLanguage(slug)) return slug;
    }
  }
  return detected;
}

// CONCEPTS is populated from `seed/concepts.lino` at init() time.

function normalizePrompt(prompt) {
  const text = String(prompt || "");
  const fromWasm = wasmNormalizePrompt(text);
  if (fromWasm !== null) return fromWasm;
  // Keep letters, numbers and every Unicode mark (category M): Devanagari
  // matras, the nukta and the virama are marks, so a bare \p{L}\p{N} filter
  // would strip them and corrupt Hindi words (issue #312). Mark-awareness via
  // \p{M} mirrors the Rust `normalize_prompt`, which keeps `is_alphanumeric()`
  // characters plus its script-combining-mark ranges. Crucially it does NOT
  // keep the whole U+0900–U+097F block: Indic punctuation such as the danda
  // "।" (U+0964) is category Po, so both sides collapse it to a space. The
  // boundary-aware role matcher (issue #386) depends on that parity — a
  // retained danda would defeat the whole-token match for phrases like
  // "अपना परिचय दो।".
  return text
    .toLowerCase()
    .replace(/[^\p{L}\p{N}\p{M}]+/gu, " ")
    .trim();
}

function normalizeConceptTerm(value) {
  let lower = String(value || "").toLowerCase();
  for (const prefix of ["the ", "a ", "an "]) {
    if (lower.startsWith(prefix)) {
      lower = lower.slice(prefix.length);
      break;
    }
  }
  return lower.trim().replace(/[?.!,;:]+$/g, "").trim();
}

function recordMatchesTerm(record, normalized) {
  return (
    normalizeConceptTerm(record.term) === normalized ||
    normalizeConceptTerm(record.slug) === normalized ||
    (Array.isArray(record.aliases) &&
      record.aliases.some(
        (alias) => normalizeConceptTerm(alias) === normalized,
      ))
  );
}

function recordMatchesQueryTerm(record, normalized, contextNormalized) {
  if (recordMatchesTerm(record, normalized)) return true;
  if (!contextNormalized) return false;
  return recordMatchesTerm(record, `${normalized} ${contextNormalized}`);
}

function contextRecordMatches(contextRecord, contextNormalized) {
  if (!contextRecord) return false;
  if (
    Array.isArray(contextRecord.aliases) &&
    contextRecord.aliases.some(
      (alias) => normalizeConceptTerm(alias) === contextNormalized,
    )
  ) {
    return true;
  }
  return (
    Array.isArray(contextRecord.labels) &&
    contextRecord.labels.some(
      (label) => normalizeConceptTerm(label.text) === contextNormalized,
    )
  );
}

function resolveContextRecord(contextNormalized) {
  if (!contextNormalized) return null;
  for (const record of CONCEPT_CONTEXTS) {
    if (contextRecordMatches(record, contextNormalized)) return record;
  }
  return null;
}

function recordHasContext(record, contextNormalized) {
  if (
    Array.isArray(record.contexts) &&
    record.contexts.some(
      (candidate) => normalizeConceptTerm(candidate) === contextNormalized,
    )
  ) {
    return true;
  }
  // Registry fallback: resolve the user-supplied context through the
  // concept-contexts registry and see whether the resolved record's slug is
  // referenced by the concept's `contextLinks` list. Matches the Rust
  // ranker (src/concepts.rs::record_has_context).
  const contextRecord = resolveContextRecord(contextNormalized);
  if (contextRecord && Array.isArray(record.contextLinks)) {
    return record.contextLinks.some(
      (slug) => String(slug).trim() === contextRecord.slug,
    );
  }
  return false;
}

function localizedConceptFor(record, language) {
  if (!record || !Array.isArray(record.localized)) return null;
  return (
    record.localized.find((loc) => loc && loc.language === language) ||
    record.localized.find((loc) => loc && loc.language === "en") ||
    null
  );
}

function contextLabelFor(contextRecord, language) {
  if (!contextRecord || !Array.isArray(contextRecord.labels)) {
    return null;
  }
  const exact = contextRecord.labels.find(
    (label) => label && label.language === language,
  );
  if (exact && exact.text) return exact.text;
  const english = contextRecord.labels.find(
    (label) => label && label.language === "en",
  );
  if (english && english.text) return english.text;
  return contextRecord.slug || null;
}

function rankConceptForPair(termRaw, contextRaw) {
  const normalized = normalizeConceptTerm(termRaw);
  if (!normalized) return null;
  const contextNormalized = contextRaw ? normalizeConceptTerm(contextRaw) : "";

  const termMatches = CONCEPTS.filter((record) =>
    recordMatchesQueryTerm(record, normalized, contextNormalized),
  );
  if (termMatches.length === 0) return null;

  if (contextNormalized) {
    const ctxHit = termMatches.find((record) =>
      recordHasContext(record, contextNormalized),
    );
    if (ctxHit) {
      return {
        record: ctxHit,
        contextMatch: true,
        context: contextNormalized,
      };
    }
  }

  // No context match: prefer records with no contexts declared.
  termMatches.sort((a, b) => {
    const ac = (Array.isArray(a.contexts) && a.contexts.length > 0) ? 1 : 0;
    const bc = (Array.isArray(b.contexts) && b.contexts.length > 0) ? 1 : 0;
    return ac - bc;
  });
  return {
    record: termMatches[0],
    contextMatch: false,
    context: contextNormalized || null,
  };
}

function lookupConceptQuery(query) {
  if (!query) return null;
  const direct = rankConceptForPair(query.term, query.context);
  if (query.context) {
    const reversed = rankConceptForPair(query.context, query.term);
    if (reversed && (!direct || (!direct.contextMatch && reversed.contextMatch))) {
      return reversed;
    }
  }
  return direct || null;
}

function lookupConcept(term) {
  const hit = lookupConceptQuery({ term: term, context: null });
  return hit ? hit.record : null;
}

// Default concept-lookup patterns when seed/prompt-patterns.lino is missing.
// Sorted longest-first so "what is a " beats "what is " when both match.
const DEFAULT_CONCEPT_SUFFIXES = [
  " का अर्थ बताओ",
  " क्या होता है",
  " क्या है",
  " कौन हैं",
  " कौन है",
  "的意思是什么",
  "是什么意思",
  "是甚麼",
  "是什么",
  "是誰",
  "是谁",
];
const DEFAULT_CONCEPT_PREFIXES = [
  "what is a ",
  "what is an ",
  "what is the ",
  "what is ",
  "what's a ",
  "what's an ",
  "what's the ",
  "what's ",
  "what do ",
  "what does ",
  "tell me about ",
  "tell me what ",
  "define ",
  "explain ",
  "describe ",
  "who is ",
  "who was ",
  "что такое ",
  "что это ",
  "что означает слово ",
  "кто такой ",
  "кто такая ",
  "кто это ",
  "расскажи о ",
  "расскажи про ",
  "назови ",
  "опиши ",
  "объясни ",
  "什么是",
  "甚麼是",
  "请解释",
  "请说说",
  "介绍一下",
];

function conceptPatternsByKind(kind) {
  const matches = PROMPT_PATTERNS.filter(
    (p) => p && p.intent === "concept_lookup" && p.kind === kind && p.text,
  ).map((p) => p.text);
  // Sort longest-first so more specific patterns win.
  matches.sort((a, b) => b.length - a.length);
  if (matches.length > 0) return matches;
  if (kind === "suffix") return DEFAULT_CONCEPT_SUFFIXES;
  if (kind === "prefix") return DEFAULT_CONCEPT_PREFIXES;
  return [];
}

function splitTermAndContext(bodyOriginal, bodyLower) {
  const delimiters = conceptPatternsByKind("context_delimiter");
  for (const delimiter of delimiters) {
    const idx = bodyLower.indexOf(delimiter);
    if (idx >= 0) {
      const term = bodyLower.slice(0, idx).trim();
      const context = bodyLower.slice(idx + delimiter.length).trim();
      const termOriginal = bodyOriginal.slice(0, idx).trim();
      const contextOriginal = bodyOriginal
        .slice(idx + delimiter.length)
        .trim();
      if (term && context) {
        return {
          term: term,
          context: context,
          termOriginal: termOriginal || term,
          contextOriginal: contextOriginal || context,
        };
      }
    }
  }
  return {
    term: bodyLower,
    context: null,
    termOriginal: bodyOriginal || bodyLower,
    contextOriginal: null,
  };
}

function stripLeadingRequest(input) {
  const lower = input.toLowerCase();
  const prefixes = [
    "please tell me,",
    "please tell me",
    "tell me,",
    "tell me",
  ];
  const questionStarts = ["who ", "what ", "what's ", "who's "];
  for (const prefix of prefixes) {
    if (!lower.startsWith(prefix)) continue;
    const rest = input.slice(prefix.length).trimStart();
    const restLower = rest.toLowerCase();
    if (
      questionStarts.some((questionStart) =>
        restLower.startsWith(questionStart),
      )
    ) {
      return rest;
    }
  }
  return input;
}

function extractInvertedWhoIs(input, lower) {
  if (!lower.startsWith("who ") || !lower.endsWith(" is")) return null;
  const body = input.slice("who ".length, input.length - " is".length).trim();
  if (!body) return null;
  const normalized = body.toLowerCase();
  if (["is", "was", "are"].includes(normalized)) return null;
  return body;
}

function cleanMechanismFragment(value) {
  return String(value || "")
    .trim()
    .replace(/^[`"'«»<>()\[\]{}]+/u, "")
    .replace(/[`"'«»<>()\[\]{}]+$/u, "")
    .replace(/[??。.!,,;:]+$/u, "")
    .trim();
}

// Trim optional detail/politeness modifiers from a candidate subject and reject
// it outright when it is a non-referential subject. The modifier tails carry
// ROLE_DETAIL_MODIFIER (suffix surfaces, stripped in declaration order); the
// rejection set carries ROLE_NON_REFERENTIAL_SUBJECT (bare surfaces match the
// whole candidate, prefix surfaces match a candidate that begins with the
// literal before the … slot). Mirrors clean_mechanism_subject in
// src/solver_handler_how.rs — no per-language modifier or pronoun array here.
function cleanMechanismSubject(value) {
  let clean = cleanMechanismFragment(value);
  for (const form of roleWordForms(ROLE_DETAIL_MODIFIER)) {
    const suffix = form.after;
    const lower = clean.toLowerCase();
    if (lower.endsWith(suffix)) {
      clean = cleanMechanismFragment(clean.slice(0, clean.length - suffix.length));
    }
  }
  const lower = clean.toLowerCase();
  const nonReferential = roleWordForms(ROLE_NON_REFERENTIAL_SUBJECT).some((form) => {
    if (form.slot === "bare") return lower === form.text;
    if (form.slot === "prefix") return lower.startsWith(form.before);
    return false;
  });
  if (!clean || nonReferential) {
    return null;
  }
  return clean;
}

// Strip a trailing mechanism predicate so a prefix match such as "how does X
// work" yields the bare subject "X". The predicate tails carry
// ROLE_MECHANISM_PREDICATE (suffix surfaces); they are tried in declaration
// order and the first match wins. Mirrors strip_mechanism_tail in
// src/solver_handler_how.rs — no per-language tail array here.
function stripMechanismTail(subject) {
  let clean = cleanMechanismSubject(subject);
  if (!clean) return null;
  const lower = clean.toLowerCase();
  for (const form of roleWordForms(ROLE_MECHANISM_PREDICATE)) {
    const suffix = form.after;
    if (lower.endsWith(suffix)) {
      clean = cleanMechanismSubject(clean.slice(0, clean.length - suffix.length));
      break;
    }
  }
  return clean;
}

function mechanismSubjectAfterPrefix(original, lower, prefix) {
  if (!lower.startsWith(prefix)) return null;
  return cleanMechanismSubject(original.slice(prefix.length));
}

function mechanismSubjectBeforeSuffix(original, lower, suffix) {
  if (!lower.endsWith(suffix)) return null;
  return cleanMechanismSubject(original.slice(0, -suffix.length));
}

function mechanismSubjectBetween(original, lower, prefix, suffixes) {
  if (!lower.startsWith(prefix)) return null;
  for (const suffix of suffixes) {
    if (!lower.endsWith(suffix)) continue;
    const end = original.length - suffix.length;
    if (end <= prefix.length) return null;
    return cleanMechanismSubject(original.slice(prefix.length, end));
  }
  return null;
}

function extractHowItWorksSubject(input, lowerInput) {
  const original = cleanMechanismFragment(input);
  if (!original) return null;
  const lower = cleanMechanismFragment(lowerInput || original.toLowerCase())
    .toLowerCase();

  // The affixes are the slot-marked surface forms of the mechanism_inquiry
  // meaning (data/seed/meanings-how.lino, embedded in MEANINGS_LINO): the
  // position of the … marker classifies each form, so the matching strategy is
  // derived from the data, not from a hardcoded per-language list. Bucket order
  // — prefix, then circumfix, then suffix — and within-bucket declaration order
  // mirror extract_how_it_works_subject in src/solver_handler_how.rs (#386).
  // Suffix surfaces are end-anchored and script-disjoint across languages, so
  // the cross-language declaration order does not change which one matches.
  const forms = roleWordForms(ROLE_MECHANISM_INQUIRY);

  for (const form of forms) {
    if (form.slot !== "prefix") continue;
    const subject = mechanismSubjectAfterPrefix(original, lower, form.before);
    if (subject) return stripMechanismTail(subject);
  }

  for (const form of forms) {
    if (form.slot !== "circumfix") continue;
    const subject = mechanismSubjectBetween(original, lower, form.before, [
      form.after,
    ]);
    if (subject) return subject;
  }

  for (const form of forms) {
    if (form.slot !== "suffix") continue;
    const subject = mechanismSubjectBeforeSuffix(original, lower, form.after);
    if (subject) return subject;
  }

  return null;
}

function cleanMeaningCandidate(value) {
  const cleaned = String(value || "")
    .trim()
    .replace(/^[«»"“”‘’'`]+|[«»"“”‘’'`]+$/gu, "")
    .trim();
  if (!cleaned) return null;
  if (/^(?:it|that|this|word|the word|mean|means|meaning|i)$/iu.test(cleaned)) {
    return null;
  }
  return cleaned;
}

function extractMeaningQuestionBody(original, lower) {
  for (const prefix of [
    "what is the meaning of ",
    "what's the meaning of ",
    "what is meaning of ",
    "meaning of ",
  ]) {
    if (lower.startsWith(prefix)) {
      return cleanMeaningCandidate(original.slice(prefix.length));
    }
  }

  for (const suffix of [" mean", " means", " meaning"]) {
    if (!lower.endsWith(suffix)) continue;
    const stem = original.slice(0, -suffix.length).trim();
    const stemLower = stem.toLowerCase();
    for (const prefix of [
      "what does the word ",
      "what does ",
      "what do ",
      "what did ",
      "what is the word ",
      "what is ",
      "what's ",
      "what i ",
    ]) {
      if (stemLower.startsWith(prefix)) {
        return cleanMeaningCandidate(stem.slice(prefix.length));
      }
    }
  }

  return null;
}

function extractConceptQuery(prompt) {
  let trimmedRaw = String(prompt || "")
    .trim()
    .replace(/[?。.!!,,;:]+$/g, "")
    .trim();
  if (!trimmedRaw) return null;
  trimmedRaw = stripLeadingRequest(trimmedRaw);

  const suffixes = conceptPatternsByKind("suffix");
  for (const suffix of suffixes) {
    if (trimmedRaw.endsWith(suffix)) {
      return finalizeConceptBody(
        trimmedRaw.slice(0, -suffix.length).trim(),
      );
    }
  }

  const lower = trimmedRaw.toLowerCase();
  const meaningBody = extractMeaningQuestionBody(trimmedRaw, lower);
  if (meaningBody) return finalizeConceptBody(meaningBody);

  const invertedWhoBody = extractInvertedWhoIs(trimmedRaw, lower);
  if (invertedWhoBody) return finalizeConceptBody(invertedWhoBody);

  const howItWorksSubject = extractHowItWorksSubject(trimmedRaw, lower);
  if (howItWorksSubject) return finalizeConceptBody(howItWorksSubject);

  const prefixes = conceptPatternsByKind("prefix");
  let body = null;
  for (const prefix of prefixes) {
    if (lower.startsWith(prefix)) {
      body = trimmedRaw.slice(prefix.length);
      break;
    }
  }
  if (!body) return null;
  return finalizeConceptBody(body);
}

function extractConceptTerm(prompt) {
  const query = extractConceptQuery(prompt);
  return query ? query.term : null;
}

function cleanWikipediaArticleQuestionTerm(value) {
  return String(value || "")
    .trim()
    .replace(/^[«»"“”‘’'`「」『』]+|[«»"“”‘’'`「」『』]+$/gu, "")
    .replace(/[?!.。!?।]+$/gu, "")
    .replace(/\s+/g, " ")
    .trim();
}

function hasWikipediaArticleQuestionShape(value) {
  const lower = String(value || "").toLowerCase();
  if (!/(?:wikipedia|wiki|википед|维基百科|維基百科|विकिपीडिया)/u.test(lower)) return false;
  const hasArticleWord = /(?:article|page|стать[ьяеию]|страниц|条目|條目|页面|頁面|文章|लेख|पृष्ठ)/u.test(lower);
  if (!hasArticleWord) return false;
  return /(?:is there|does .*have|exist|available|есть|существ|имеет|найд|назв|有|存在|有没有|是否有|吗|嗎|क्या|है|मौजूद)/u.test(lower);
}

function extractWikipediaArticleQuestionTerm(prompt) {
  const raw = cleanWikipediaArticleQuestionTerm(prompt);
  if (!raw || !hasWikipediaArticleQuestionShape(raw)) return null;

  const dashMatch = raw.match(/^(.+?)\s+[-—–:]\s+(.+)$/u);
  if (dashMatch && hasWikipediaArticleQuestionShape(dashMatch[2])) {
    return cleanWikipediaArticleQuestionTerm(dashMatch[1]);
  }

  for (const pattern of [
    /^(?:is|are)\s+there\s+(?:an?\s+)?(?:wikipedia|wiki)\s+(?:article|page)\s+(?:about|on|for)\s+(.+)$/iu,
    /^does\s+(?:wikipedia|wiki)\s+have\s+(?:an?\s+)?(?:article|page)\s+(?:about|on|for)\s+(.+)$/iu,
    /^(?:есть|существует|имеется)\s+(?:ли\s+)?(?:в\s+)?(?:русскоязычной\s+)?википедии\s+(?:отдельная\s+)?(?:статья|страница)\s+(?:о|об|про|с\s+названием)\s+(.+)$/iu,
    /^(?:есть|существует|имеется)\s+(?:ли\s+)?(?:отдельная\s+)?(?:статья|страница)\s+(?:в\s+)?(?:русскоязычной\s+)?википедии\s+(?:о|об|про|с\s+названием)\s+(.+)$/iu,
    /^(?:维基百科|維基百科)(?:上)?(?:有|存在)(?:关于|關於|名为|名為)?\s*(.+?)\s*(?:的)?(?:条目|條目|文章|页面|頁面)(?:吗|嗎)?$/iu,
    /^(.+?)\s*(?:在)?(?:维基百科|維基百科)(?:上)?(?:有|存在)(?:这样(?:的)?|這樣(?:的)?|一篇)?(?:条目|條目|文章|页面|頁面)(?:吗|嗎)?$/iu,
    /^(?:क्या\s+)?(?:विकिपीडिया|wiki)\s+(?:पर|में)\s+(.+?)\s+(?:के\s+बारे\s+में\s+)?(?:लेख|पृष्ठ)\s+(?:है|मौजूद\s+है)$/iu,
    /^(?:क्या\s+)?(.+?)\s+(?:के\s+बारे\s+में\s+)?(?:विकिपीडिया|wiki)\s+(?:पर|में)\s+(?:ऐसा\s+)?(?:लेख|पृष्ठ)\s+(?:है|मौजूद\s+है)$/iu,
  ]) {
    const match = raw.match(pattern);
    if (match) return cleanWikipediaArticleQuestionTerm(match[1]);
  }

  const trailingRussian = raw.match(/^(.+?)\s+(?:есть|существует|имеется)\s+(?:ли\s+)?(?:такая\s+)?(?:статья|страница)\s+(?:в\s+)?(?:русскоязычной\s+)?википедии$/iu);
  if (trailingRussian) return cleanWikipediaArticleQuestionTerm(trailingRussian[1]);
  const trailingHindi = raw.match(/^(.+?)\s+(?:के\s+बारे\s+में\s+)?(?:विकिपीडिया|wiki)\s+(?:पर|में)\s+(?:ऐसा\s+)?(?:लेख|पृष्ठ)\s+(?:है|मौजूद\s+है)$/iu);
  if (trailingHindi) return cleanWikipediaArticleQuestionTerm(trailingHindi[1]);
  const trailingChinese = raw.match(/^(.+?)\s*(?:在)?(?:维基百科|維基百科)(?:上)?(?:有|存在)(?:这样(?:的)?|這樣(?:的)?|一篇)?(?:条目|條目|文章|页面|頁面)(?:吗|嗎)?$/iu);
  if (trailingChinese) return cleanWikipediaArticleQuestionTerm(trailingChinese[1]);

  return null;
}

function refineWikipediaArticleQuestionLookup(term, language) {
  const exactTerm = cleanWikipediaArticleQuestionTerm(term);
  const query = {
    exactTerm,
    lookupTerm: exactTerm,
    contextOriginal: "",
  };
  const lower = exactTerm.toLowerCase();
  if (
    (language === "ru" || /[а-яё]/iu.test(exactTerm)) &&
    /\s(?:в|на)\s+(?:предложени[еяию]|предложениях|словосочетани[еяию]|словосочетаниях)$/iu.test(lower)
  ) {
    query.lookupTerm = cleanWikipediaArticleQuestionTerm(
      exactTerm.replace(/\s(?:в|на)\s+(?:предложени[еяию]|предложениях|словосочетани[еяию]|словосочетаниях)$/iu, ""),
    );
    query.contextOriginal = "грамматика";
  }
  if (
    (language === "en" || /^[\p{ASCII}\s]+$/u.test(exactTerm)) &&
    /\s+in\s+(?:a\s+)?sentences?$/iu.test(lower)
  ) {
    query.lookupTerm = cleanWikipediaArticleQuestionTerm(
      exactTerm.replace(/\s+in\s+(?:a\s+)?sentences?$/iu, ""),
    );
    query.contextOriginal = "grammar";
  }
  if (language === "hi" || /[\u0900-\u097f]/u.test(exactTerm)) {
    const prefix = exactTerm.match(/^(?:वाक्य|वाक्यों)\s+में\s+(.+)$/u);
    const suffix = exactTerm.match(/^(.+?)\s+(?:वाक्य|वाक्यों)\s+में$/u);
    const match = prefix || suffix;
    if (match) {
      query.lookupTerm = cleanWikipediaArticleQuestionTerm(match[1]);
      query.contextOriginal = "व्याकरण";
    }
  }
  if (language === "zh" || /[\u3400-\u9fff]/u.test(exactTerm)) {
    const prefix = exactTerm.match(/^(?:句子中(?:的)?|句子里(?:的)?|句中的)(.+)$/u);
    const suffix = exactTerm.match(/^(.+?)(?:在)?句子(?:中|里)$/u);
    const match = prefix || suffix;
    if (match) {
      query.lookupTerm = cleanWikipediaArticleQuestionTerm(match[1]);
      query.contextOriginal = "语法";
    }
  }
  return query;
}

// Issue #21: render a percent-encoded URL in its readable IRI form for
// display, while leaving the original encoded form available as the href.
// `decodeURI` keeps reserved URI delimiters (`; / ? : @ & = + $ , #`) intact,
// so query strings are preserved; malformed escapes fall back to the original
// string.
function humanizeUrl(url) {
  if (typeof url !== "string" || url.length === 0) return url;
  if (!url.includes("%")) return url;
  try {
    return decodeURI(url);
  } catch (_error) {
    return url;
  }
}

// Render a source URL as a Markdown link [human](encoded) when humanization
// changes anything, or the bare URL otherwise.
function renderSourceLink(source) {
  const human = humanizeUrl(source);
  return human === source ? source : `[${human}](${source})`;
}

function finalizeConceptBody(body) {
  let originalBase = String(body || "")
    .trim()
    .replace(/[?。.!!,,;:]+$/g, "")
    .trim();
  if (!originalBase) return null;
  let original = originalBase;
  let lower = original.toLowerCase();
  // Strip trailing "mean"/"stand for" markers shared across English idioms.
  // The lowercased view drives matching while the original-case view is kept
  // so downstream Wikipedia URL lookups preserve Cyrillic capitalization
  // (see docs/case-studies/issue-27/README.md).
  for (const suffix of [" mean", " stand for"]) {
    if (lower.endsWith(suffix)) {
      original = original.slice(0, -suffix.length).trim();
      lower = lower.slice(0, -suffix.length).trim();
      break;
    }
  }
  if (!lower) return null;
  return splitTermAndContext(original, lower);
}

function tokenizeArithmetic(input) {
  const tokens = [];
  let i = 0;
  while (i < input.length) {
    const ch = input[i];
    if (ch === " " || ch === "\t" || ch === "_" || ch === ",") {
      i += 1;
      continue;
    }
    if (ch === "+") {
      tokens.push({ kind: "+" });
      i += 1;
    } else if (ch === "-" || ch === "−") {
      tokens.push({ kind: "-" });
      i += 1;
    } else if (ch === "*" || ch === "×" || ch === "·") {
      tokens.push({ kind: "*" });
      i += 1;
    } else if (ch === "/" || ch === "÷") {
      tokens.push({ kind: "/" });
      i += 1;
    } else if (ch === "%") {
      tokens.push({ kind: "%" });
      i += 1;
    } else if (ch === "^") {
      tokens.push({ kind: "^" });
      i += 1;
    } else if (ch === "(") {
      tokens.push({ kind: "(" });
      i += 1;
    } else if (ch === ")") {
      tokens.push({ kind: ")" });
      i += 1;
    } else if ((ch >= "0" && ch <= "9") || ch === ".") {
      let j = i;
      while (
        j < input.length &&
        ((input[j] >= "0" && input[j] <= "9") || input[j] === ".")
      ) {
        j += 1;
      }
      const slice = input.slice(i, j);
      const value = Number(slice);
      if (Number.isNaN(value)) {
        throw new Error("unparseable");
      }
      tokens.push({ kind: "num", value });
      i = j;
    } else {
      throw new Error("unparseable");
    }
  }
  return tokens;
}

// Issue #386: the spelled-operator and cardinal-number vocabularies are no
// longer literal arrays here. They live in the seed meanings — the
// arithmetic_operation operators (addition, subtraction, multiplication,
// division, modulo) and the cardinal_number digits (zero, один, 三, …) — and
// are read by role through the lexicon, exactly as the Rust solver does
// (contains_word_operator / contains_spelled_arithmetic in src/calculation.rs).
// These role names mirror the constants in src/seed/roles.rs.
const ROLE_ARITHMETIC_OPERATOR_WORD = "arithmetic_operator_word";
const ROLE_CARDINAL_NUMBER_WORD = "cardinal_number_word";
const ROLE_CALCULATION_REQUEST_CUE = "calculation_request_cue";
const ROLE_CALCULATION_RESULT_QUERY_CUE = "calculation_result_query_cue";
const ROLE_POLITENESS_CUE = "politeness_cue";
const ROLE_QUANTITY_CONVERSION_CUE = "quantity_conversion_cue";
const ROLE_CALCULATION_DOMAIN_TERM = "calculation_domain_term";
const ROLE_MATH_FUNCTION_NAME = "math_function_name";

// Issue #386: the spelled digit/operator → value normalization tables, derived
// from the seed at runtime exactly as the Rust solver derives them
// (Lexicon::arithmetic_normalization_tables in src/seed/meanings.rs, materialized
// into src/arithmetic_word_tables.rs for the no_std wasm worker). A cardinal or
// operator meaning carries its script-independent value surface as the one word
// form with no alphabetic character — the numeral "2", the symbol "+" — and every
// spelled surface (any language) maps onto it. Multi-word surfaces ("divided by",
// "разделить на") are returned as `phrases`, rewritten before tokenization and
// ordered longest-first so a phrase applies before any shorter phrase it
// contains; single words ("two", "плюс") are returned as `tokens`, mapped after
// the whitespace split. Cached because the lexicon never changes at runtime.
let cachedArithmeticTables = null;
function arithmeticNormalizationTables() {
  if (cachedArithmeticTables) return cachedArithmeticTables;
  const isValueSurface = (word) => !/\p{Alphabetic}/u.test(word);
  const tokens = [];
  const phrases = [];
  for (const role of [ROLE_CARDINAL_NUMBER_WORD, ROLE_ARITHMETIC_OPERATOR_WORD]) {
    for (const meaning of meaningsWithRole(role)) {
      // The value surface is the one word form with no alphabetic character: the
      // numeral for a cardinal, the symbol for an operator. Spelled surfaces in
      // every language map onto it.
      const value = meaning.words.find((word) => isValueSurface(word));
      if (value === undefined) continue;
      for (const word of meaning.words) {
        if (word === value || isValueSurface(word)) continue;
        const entry = [word, value];
        if (/\s/u.test(word)) phrases.push(entry);
        else tokens.push(entry);
      }
    }
  }
  const cmpStr = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
  const dedupe = (pairs) =>
    pairs.filter(
      (pair, index) =>
        index === 0 ||
        pair[0] !== pairs[index - 1][0] ||
        pair[1] !== pairs[index - 1][1],
    );
  // tokens.sort() in Rust orders tuples by surface then value; phrases sort by
  // descending code-point count (longest first), then surface ascending.
  tokens.sort((a, b) => cmpStr(a[0], b[0]) || cmpStr(a[1], b[1]));
  phrases.sort(
    (a, b) => [...b[0]].length - [...a[0]].length || cmpStr(a[0], b[0]),
  );
  cachedArithmeticTables = { tokens: dedupe(tokens), phrases: dedupe(phrases) };
  return cachedArithmeticTables;
}

const PERCENT_OF_CURRENCY_CODES = new Map([
  ["$", "USD"],
  ["€", "EUR"],
  ["¥", "JPY"],
  ["₹", "INR"],
  ["₽", "RUB"],
]);

const DEFAULT_CURRENCY_RATES = new Map([
  ["USD:EUR", 0.92],
  ["USD:GBP", 0.79],
  ["USD:JPY", 148.5],
  ["USD:CHF", 0.88],
  ["USD:CNY", 7.25],
  ["USD:RUB", 89.5],
  ["USD:INR", 86.5],
  ["USD:CLF", 0.022],
  ["USD:VND", 25810.0],
  ["USD:KZT", 470.0],
  ["EUR:USD", 1.087],
  ["EUR:GBP", 0.86],
  ["EUR:JPY", 161.5],
  ["EUR:CHF", 0.96],
  ["GBP:USD", 1.27],
  ["GBP:EUR", 1.16],
]);

const USD_RUB_RATE_EXPRESSION = "1 USD in RUB";

// Issue #386: the canonical ISO 4217 code is the recognizer's output, so it
// stays in code; only the recognition vocabulary lives in the seed. Mirrors the
// role -> code mapping the Rust calculator handlers resolve from the same roles.
function currencyCodeForRole(role) {
  if (role === ROLE_CURRENCY_USD_REFERENCE) return "USD";
  if (role === ROLE_CURRENCY_EUR_REFERENCE) return "EUR";
  if (role === ROLE_CURRENCY_RUB_REFERENCE) return "RUB";
  return "";
}

// Issue #386: currency vocabulary is seed data, not a hardcoded declension list.
// Walk the three currency reference roles (USD, then EUR, then RUB — the
// original recognizer's priority) and return the ISO code of the first role a
// surface matches. The matching strategy follows the surface's script, the same
// split surfacePresent already makes: Latin surfaces (the ISO codes and English
// terms, enumerated singular and plural) and CJK/Devanagari surfaces match the
// whole token exactly, so unrelated words like "rubbish" are rejected just as
// the original exact-match list rejected them; Cyrillic surfaces are stems
// matched by prefix, so every Russian declension (доллар… , руб…) is caught
// from доллар / руб without listing each inflected form. The calculator regexes
// only ever feed this Latin or Cyrillic tokens.
function currencyCodeFromWord(value) {
  const lower = String(value || "").toLowerCase();
  if (!lower) return "";
  for (const role of [
    ROLE_CURRENCY_USD_REFERENCE,
    ROLE_CURRENCY_EUR_REFERENCE,
    ROLE_CURRENCY_RUB_REFERENCE,
  ]) {
    for (const word of wordsForRole(role)) {
      if (!word) continue;
      // Cyrillic block is U+0400-U+04FF; Latin sorts below it and CJK/Devanagari
      // above, so the first codepoint tells us which matching strategy to use.
      const head = word.charCodeAt(0);
      const isCyrillic = head >= 0x0400 && head <= 0x04ff;
      if (isCyrillic ? lower.startsWith(word) : lower === word) {
        return currencyCodeForRole(role);
      }
    }
  }
  return "";
}

function defaultCurrencyRate(from, to) {
  if (from === to) return 1;
  const direct = DEFAULT_CURRENCY_RATES.get(`${from}:${to}`);
  if (direct) return direct;
  const inverse = DEFAULT_CURRENCY_RATES.get(`${to}:${from}`);
  if (inverse) return 1 / inverse;
  if (from !== "USD" && to !== "USD") {
    const fromUsd = defaultCurrencyRate(from, "USD");
    const usdTo = defaultCurrencyRate("USD", to);
    if (fromUsd && usdTo) return fromUsd * usdTo;
  }
  return null;
}

// Issue #386: the trailing currency word in an "N% of M <currency>" expression
// is seed data, not a hardcoded English list. Build the alternation from the
// same three currency reference roles currencyCodeFromWord resolves, so the
// recognizer captures exactly what the resolver understands — the ISO codes,
// the English singular/plural forms, and the Cyrillic/CJK/Devanagari names all
// come straight from the seed instead of the old usd|eur|rub|dollars?… literal.
// Longest-first under the trailing `$` anchor so "dollars" is preferred over
// "dollar"; each surface is regex-escaped. Cached because the seed is immutable
// for the worker's lifetime (matching the lazy, post-init access pattern
// currencyCodeFromWord uses, which keeps the ROLE_* consts out of the TDZ).
let percentOfExpressionRegexCache = null;
function percentOfExpressionRegex() {
  if (percentOfExpressionRegexCache) return percentOfExpressionRegexCache;
  const surfaces = [];
  const seen = new Set();
  for (const role of [
    ROLE_CURRENCY_USD_REFERENCE,
    ROLE_CURRENCY_EUR_REFERENCE,
    ROLE_CURRENCY_RUB_REFERENCE,
  ]) {
    for (const word of wordsForRole(role)) {
      const surface = String(word || "").toLowerCase();
      if (!surface || seen.has(surface)) continue;
      seen.add(surface);
      surfaces.push(surface);
    }
  }
  surfaces.sort((a, b) => b.length - a.length || (a < b ? -1 : a > b ? 1 : 0));
  const alternation = surfaces
    .map((surface) => surface.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
    .join("|");
  percentOfExpressionRegexCache = new RegExp(
    `^([+-]?\\d+(?:\\.\\d+)?)\\s*%\\s+of\\s+([$€¥₹₽])?\\s*([+-]?\\d+(?:\\.\\d+)?)(?:\\s*(${alternation}))?$`,
    "i",
  );
  return percentOfExpressionRegexCache;
}

function evaluatePercentOfExpression(expression) {
  const match = String(expression || "")
    .trim()
    .match(percentOfExpressionRegex());
  if (!match) return null;
  const percent = Number(match[1]);
  const amount = Number(match[3]);
  if (!Number.isFinite(percent) || !Number.isFinite(amount)) return null;
  const currency =
    PERCENT_OF_CURRENCY_CODES.get(match[2] || "") ||
    currencyCodeFromWord(match[4]);
  const result = formatArithmeticResult((amount * percent) / 100);
  return currency ? `${result} ${currency}` : result;
}

function evaluateCurrencyConversionExpression(expression) {
  const match = String(expression || "")
    .trim()
    .match(
      /^([+-]?\d+(?:[.,]\d+)?)\s+(.+?)\s+(?:in|as|to|в|во|к)\s+(.+)$/iu,
    );
  if (!match) return null;
  const amount = Number(match[1].replace(",", "."));
  if (!Number.isFinite(amount)) return null;
  const from = currencyCodeFromWord(match[2].trim());
  const to = currencyCodeFromWord(match[3].trim());
  if (!from || !to) return null;
  const rate = defaultCurrencyRate(from, to);
  if (!rate) return null;
  return `${formatArithmeticResult(amount * rate)} ${to}`;
}

function usdRubRateDetail() {
  const rate = defaultCurrencyRate("USD", "RUB");
  if (!rate) return "";
  return `Exchange rate: 1 USD = ${formatArithmeticResult(rate)} RUB (source: default (hardcoded), date: unknown)`;
}

function evaluateUsdRubRateBasis() {
  const wasmResult = wasmEvaluateArithmetic(USD_RUB_RATE_EXPRESSION);
  if (wasmResult && wasmResult.ok) {
    return {
      formatted: wasmResult.value,
      backend: "wasm",
      detail: usdRubRateDetail(),
    };
  }
  const currencyConversionResult = evaluateCurrencyConversionExpression(
    USD_RUB_RATE_EXPRESSION,
  );
  if (currencyConversionResult === null) return null;
  return {
    formatted: currencyConversionResult,
    backend: "js-currency",
    detail: usdRubRateDetail(),
  };
}

// Issue #386: recognise the USD/RUB rate-basis question by *meaning*, not by a
// hardcoded per-language word list. The surface forms live once in
// data/seed/meanings-calculator.lino and are queried by semantic role, matched
// as raw substrings — the JS mirror of mentions_role_raw and of
// asks_for_usd_rate_basis in src/solver_handlers/calculator_rate.rs.
//
// A prompt references US dollars (an exchange_rate between currencies AND the
// us_dollar currency) when both currency roles are present.
function mentionsUsdRate(normalized) {
  return (
    lexiconMentionsRoleSubstring(ROLE_EXCHANGE_RATE_REFERENCE, normalized) &&
    lexiconMentionsRoleSubstring(ROLE_CURRENCY_USD_REFERENCE, normalized)
  );
}

// A prompt asks what the assistant uses as the basis for a calculation when the
// calculation_basis role is present (the question side of "which rate do you
// use for calculations").
function mentionsRateCalculationBasis(normalized) {
  return lexiconMentionsRoleSubstring(ROLE_CALCULATION_BASIS_REFERENCE, normalized);
}

function tryCalculatorRateBasis(normalized, language) {
  if (!mentionsUsdRate(normalized) || !mentionsRateCalculationBasis(normalized)) {
    return null;
  }
  const evaluation = evaluateUsdRubRateBasis();
  if (!evaluation) {
    const content =
      language === "ru"
        ? "Я распознал вопрос о курсе USD/RUB для расчетов, но калькулятор не смог его вычислить."
        : "I recognized this as a question about the USD/RUB rate used for calculations, but the calculator could not evaluate it.";
    return {
      intent: "calculation_error",
      content,
      confidence: 0.3,
      evidence: ["calculation_error:USD/RUB"],
    };
  }
  const calculationBody = `${USD_RUB_RATE_EXPRESSION} = ${evaluation.formatted}`;
  let content;
  if (language === "ru") {
    content = `При расчетах валюты я использую link-calculator. Для USD/RUB он возвращает: ${calculationBody}.`;
  } else if (language === "hi") {
    content = `मुद्रा गणनाओं के लिए मैं link-calculator का उपयोग करता हूं। USD/RUB के लिए वह लौटाता है: ${calculationBody}.`;
  } else if (language === "zh") {
    content = `货币计算时我使用 link-calculator。USD/RUB 返回: ${calculationBody}.`;
  } else {
    content = `For currency calculations I use link-calculator. For USD/RUB it returns: ${calculationBody}.`;
  }
  if (evaluation.detail) {
    let details = "Calculator rate details";
    if (language === "ru") {
      details = "Детали курса от калькулятора";
    } else if (language === "hi") {
      details = "कैलकुलेटर दर विवरण";
    } else if (language === "zh") {
      details = "计算器汇率详情";
    }
    content += `\n\n${details}: ${evaluation.detail}`;
  }
  return {
    intent: "calculation",
    content,
    confidence: 1.0,
    evidence: [
      `calculation:${calculationBody}`,
      `calculation_backend:${evaluation.backend}`,
      "calculation_rate_basis:USD/RUB",
    ],
  };
}

// Rewrite "N% of M" percentage-of phrases into explicit arithmetic the parser
// can evaluate: "8% of 500" -> "( 8 * 500 / 100 )". Mirrors the Rust
// `rewrite_percent_of` helper so the JS fallback agrees with the WASM worker:
// "55 * 8% of 500" evaluates to 2200 (issue #334). A bare `%` not followed by
// "of" is left untouched so it still parses as the modulo operator.
function rewritePercentOf(expression) {
  const isNumber = (token) => token.length > 0 && /^[0-9.]+$/.test(token);
  const tokens = String(expression).split(/\s+/).filter(Boolean);
  const out = [];
  let index = 0;
  while (index < tokens.length) {
    let percent = null;
    let consumed = 0;
    const token = tokens[index];
    if (token.endsWith("%") && isNumber(token.slice(0, -1))) {
      percent = token.slice(0, -1);
      consumed = 1;
    } else if (isNumber(token) && tokens[index + 1] === "%") {
      percent = token;
      consumed = 2;
    }
    const after = index + consumed;
    if (
      percent !== null &&
      tokens[after] === "of" &&
      tokens[after + 1] !== undefined &&
      isNumber(tokens[after + 1])
    ) {
      out.push("(", percent, "*", tokens[after + 1], "/", "100", ")");
      index = after + 2;
      continue;
    }
    out.push(token);
    index += 1;
  }
  return out.join(" ");
}

function normalizeArithmeticWords(expression) {
  const { tokens, phrases } = arithmeticNormalizationTables();
  const lower = String(expression).toLowerCase();
  // Multi-word operator phrases first, longest-first (the table is pre-sorted),
  // each padded with spaces so it only rewrites on a token boundary — exactly as
  // the Rust normalize_expression does before it splits on whitespace.
  let padded = ` ${lower} `;
  for (const [phrase, value] of phrases) {
    padded = padded.replaceAll(` ${phrase} `, ` ${value} `);
  }
  const tokenMap = new Map(tokens);
  const mapped = padded
    .split(/\s+/)
    .filter(Boolean)
    .map((token) => tokenMap.get(token) || token)
    .join(" ");
  return rewritePercentOf(mapped);
}

function evaluateArithmetic(expression) {
  const normalized = normalizeArithmeticWords(expression);
  const tokens = tokenizeArithmetic(normalized);
  if (tokens.length === 0) {
    throw new Error("empty");
  }
  let cursor = 0;
  const peek = () => tokens[cursor];
  const advance = () => tokens[cursor++];
  function parsePrimary() {
    const tok = advance();
    if (!tok) throw new Error("unparseable");
    if (tok.kind === "num") return tok.value;
    if (tok.kind === "(") {
      const inner = parseAdditive();
      const close = advance();
      if (!close || close.kind !== ")") throw new Error("unbalanced");
      return inner;
    }
    throw new Error("unparseable");
  }
  function parsePower() {
    let left = parsePrimary();
    const tok = peek();
    if (tok && tok.kind === "^") {
      advance();
      left = Math.pow(left, parseUnary());
      if (!Number.isFinite(left)) throw new Error("overflow");
    }
    return left;
  }
  function parseUnary() {
    const tok = peek();
    if (tok && tok.kind === "-") {
      advance();
      return -parseUnary();
    }
    if (tok && tok.kind === "+") {
      advance();
      return parseUnary();
    }
    return parsePower();
  }
  function parseMultiplicative() {
    let left = parseUnary();
    while (true) {
      const tok = peek();
      if (!tok || (tok.kind !== "*" && tok.kind !== "/" && tok.kind !== "%")) {
        break;
      }
      const op = tok.kind;
      advance();
      const right = parseUnary();
      if (op === "*") {
        left = left * right;
      } else if (right === 0) {
        throw new Error("division by zero");
      } else if (op === "/") {
        left = left / right;
      } else {
        left = left % right;
      }
      if (!Number.isFinite(left)) throw new Error("overflow");
    }
    return left;
  }
  function parseAdditive() {
    let left = parseMultiplicative();
    while (true) {
      const tok = peek();
      if (!tok || (tok.kind !== "+" && tok.kind !== "-")) break;
      const isPlus = tok.kind === "+";
      advance();
      const right = parseMultiplicative();
      left = isPlus ? left + right : left - right;
      if (!Number.isFinite(left)) throw new Error("overflow");
    }
    return left;
  }
  const value = parseAdditive();
  if (cursor !== tokens.length) {
    throw new Error("unparseable");
  }
  return value;
}

function formatArithmeticResult(value) {
  if (!Number.isFinite(value)) return "non-finite";
  if (Math.abs(value % 1) === 0 && Math.abs(value) < 1e15) {
    return value.toFixed(0);
  }
  const rendered = value.toFixed(10);
  const trimmed = rendered.replace(/0+$/, "").replace(/\.$/, "");
  return trimmed === "" || trimmed === "-" ? "0" : trimmed;
}

function parseLinearExpression(input) {
  let position = 0;
  let variable = null;

  function peek() {
    return input[position] || "";
  }

  function skipWhitespace() {
    while (/\s/.test(peek())) position += 1;
  }

  function consume(expected) {
    if (peek() === expected) {
      position += 1;
      return true;
    }
    return false;
  }

  function constant(value) {
    return { coefficient: 0, constant: value };
  }

  function variableValue() {
    return { coefficient: 1, constant: 0 };
  }

  function hasVariable(value) {
    return Math.abs(value.coefficient) > Number.EPSILON;
  }

  function add(left, right) {
    return {
      coefficient: left.coefficient + right.coefficient,
      constant: left.constant + right.constant,
    };
  }

  function subtract(left, right) {
    return {
      coefficient: left.coefficient - right.coefficient,
      constant: left.constant - right.constant,
    };
  }

  function multiply(left, right) {
    if (hasVariable(left) && hasVariable(right)) {
      throw new Error("non-linear equation");
    }
    if (hasVariable(left)) {
      return {
        coefficient: left.coefficient * right.constant,
        constant: left.constant * right.constant,
      };
    }
    if (hasVariable(right)) {
      return {
        coefficient: right.coefficient * left.constant,
        constant: right.constant * left.constant,
      };
    }
    return constant(left.constant * right.constant);
  }

  function divide(left, right) {
    if (hasVariable(right)) throw new Error("variable denominator");
    if (Math.abs(right.constant) <= Number.EPSILON) throw new Error("division by zero");
    return {
      coefficient: left.coefficient / right.constant,
      constant: left.constant / right.constant,
    };
  }

  function parseExpression() {
    let value = parseTerm();
    while (true) {
      skipWhitespace();
      if (consume("+")) {
        value = add(value, parseTerm());
      } else if (consume("-") || consume("−")) {
        value = subtract(value, parseTerm());
      } else {
        return value;
      }
    }
  }

  function parseTerm() {
    let value = parseFactor();
    while (true) {
      skipWhitespace();
      if (consume("*") || consume("×") || consume("·")) {
        value = multiply(value, parseFactor());
      } else if (consume("/") || consume("÷")) {
        value = divide(value, parseFactor());
      } else {
        return value;
      }
    }
  }

  function parseFactor() {
    skipWhitespace();
    if (consume("+")) return parseFactor();
    if (consume("-") || consume("−")) {
      const value = parseFactor();
      return { coefficient: -value.coefficient, constant: -value.constant };
    }
    if (consume("(")) {
      const value = parseExpression();
      skipWhitespace();
      if (!consume(")")) throw new Error("unbalanced parentheses");
      return value;
    }
    if (/[0-9.]/.test(peek())) return parseNumber();
    if (/\p{L}/u.test(peek())) return parseVariable();
    throw new Error("expression could not be parsed");
  }

  function parseNumber() {
    const start = position;
    let hasDigit = false;
    let hasDot = false;
    while (/[0-9.]/.test(peek())) {
      if (peek() === ".") {
        if (hasDot) break;
        hasDot = true;
      } else {
        hasDigit = true;
      }
      position += 1;
    }
    if (!hasDigit) throw new Error("expression could not be parsed");
    const value = Number(input.slice(start, position));
    if (!Number.isFinite(value)) throw new Error("expression could not be parsed");
    return constant(value);
  }

  function parseVariable() {
    const start = position;
    while (/[\p{L}_]/u.test(peek())) position += 1;
    const name = input.slice(start, position);
    if (!name) throw new Error("expression could not be parsed");
    if (variable && variable !== name) throw new Error("multiple variables");
    variable = name;
    return variableValue();
  }

  const value = parseExpression();
  skipWhitespace();
  if (position !== input.length) throw new Error("expression could not be parsed");
  return { value, variable };
}

function solveLinearEquation(expression) {
  const parts = String(expression).split("=");
  if (parts.length !== 2) throw new Error("expression could not be parsed");
  const left = parseLinearExpression(parts[0]);
  const right = parseLinearExpression(parts[1]);
  const variable = left.variable || right.variable;
  if (!variable || (left.variable && right.variable && left.variable !== right.variable)) {
    throw new Error("expression could not be parsed");
  }
  const coefficient = left.value.coefficient - right.value.coefficient;
  if (Math.abs(coefficient) <= Number.EPSILON) {
    throw new Error("expression could not be parsed");
  }
  const value = (right.value.constant - left.value.constant) / coefficient;
  return `${variable} = ${formatArithmeticResult(value)}`;
}

function hasArithmeticWordOperator(expression) {
  // Issue #386: the spelled operators come from the arithmetic_operation
  // meanings (addition, subtraction, multiplication, division, modulo) by
  // role, not a literal array. Each surface is matched as a whole token — CJK
  // surfaces as a substring — the boundary contract the former space-padded
  // `.includes` checks enforced. The match goes through the *spelled* query so
  // a meaning's value surface (the operator symbol "+") stays neutral here and
  // is caught by the symbol parser instead, mirroring contains_word_operator in
  // src/calculation.rs.
  return lexiconMentionsRoleSpelled(
    ROLE_ARITHMETIC_OPERATOR_WORD,
    String(expression).toLowerCase(),
  );
}

function hasSpelledArithmetic(expression) {
  // Issue #386: the cardinal number words come from the cardinal_number
  // meanings by role, not a literal array. Pure-numeral surfaces ("10") are
  // skipped — a bare digit run is handled by the numeric parser — and each
  // spelled surface is matched as a space-bounded whole token, mirroring
  // contains_spelled_arithmetic in src/calculation.rs.
  const lower = ` ${String(expression).toLowerCase()} `;
  const hasNumberWord = roleWordForms(ROLE_CARDINAL_NUMBER_WORD).some((form) => {
    if (
      [...form.text].every(
        (character) => character >= "0" && character <= "9",
      )
    ) {
      return false;
    }
    return lower.includes(` ${form.text} `);
  });
  return hasNumberWord && hasArithmeticWordOperator(expression);
}

// Issue #334 step 2: the website demo's second agent step was "calculate the
// 10th Fibonacci number and multiply it by 8% of 500. Show me the code and the
// final result." It is not a calculator expression, but it reduces to one once
// the symbolic Fibonacci reference is resolved (F(10) = 55), the spelled-out
// operator is rewritten to `*`, and the trailing instruction sentence is
// dropped — yielding `55 * 8% of 500` = 2200. The helpers below mirror
// `fibonacci_value`, `parse_ordinal`, `bare_word`, `resolve_fibonacci_references`,
// `split_sentences` and `normalize_word_problem` in `src/calculation.rs`.
function fibonacciValue(n) {
  if (n === 0) return 0;
  let previous = 0;
  let current = 1;
  for (let step = 1; step < n; step += 1) {
    const next = previous + current;
    previous = current;
    current = next;
  }
  return current;
}

const ORDINAL_WORDS = {
  first: 1,
  second: 2,
  third: 3,
  fourth: 4,
  fifth: 5,
  sixth: 6,
  seventh: 7,
  eighth: 8,
  ninth: 9,
  tenth: 10,
};

// Lowercased, punctuation-trimmed view of a token for keyword comparisons.
function trimNonAlnum(token) {
  return String(token || "")
    .replace(/^[^\p{L}\p{N}]+/u, "")
    .replace(/[^\p{L}\p{N}]+$/u, "");
}

function bareWord(token) {
  return trimNonAlnum(token).toLowerCase();
}

// Parse a leading ordinal/cardinal token such as "10th", "10", "3rd" or the
// spelled-out "tenth" into its numeric value. Returns null for anything else.
function parseOrdinal(token) {
  const trimmed = trimNonAlnum(token);
  if (!trimmed) return null;
  const digits = (trimmed.match(/^[0-9]+/) || [""])[0];
  if (digits) {
    const suffix = trimmed.slice(digits.length);
    if (suffix === "" || ["st", "nd", "rd", "th"].includes(suffix)) {
      return Number.parseInt(digits, 10);
    }
    return null;
  }
  const value = ORDINAL_WORDS[trimmed.toLowerCase()];
  return value === undefined ? null : value;
}

// Replace "(the) N-th Fibonacci number" references with their numeric value.
function resolveFibonacciReferences(text) {
  if (!text.toLowerCase().includes("fibonacci")) return text;
  const tokens = text.split(/\s+/).filter(Boolean);
  const out = [];
  let index = 0;
  while (index < tokens.length) {
    const n = parseOrdinal(tokens[index]);
    if (
      n !== null &&
      tokens[index + 1] !== undefined &&
      bareWord(tokens[index + 1]) === "fibonacci"
    ) {
      // Drop a determiner we already emitted ("the 10th" -> "55").
      if (out.length > 0 && bareWord(out[out.length - 1]) === "the") {
        out.pop();
      }
      out.push(String(fibonacciValue(n)));
      index += 2;
      // Absorb a trailing "number" / "term" / "sequence" noun.
      const noun = tokens[index] !== undefined ? bareWord(tokens[index]) : "";
      if (noun === "number" || noun === "term" || noun === "sequence") {
        index += 1;
      }
      continue;
    }
    out.push(tokens[index]);
    index += 1;
  }
  return out.join(" ");
}

// Split text into sentences on a period that ends a sentence (followed by
// whitespace or the end of the string). A period flanked by digits ("3.14") is
// kept inside its sentence so decimals are never broken apart.
function splitSentences(text) {
  const chars = Array.from(String(text || ""));
  const sentences = [];
  let current = "";
  for (let i = 0; i < chars.length; i += 1) {
    const ch = chars[i];
    const next = chars[i + 1];
    if (ch === "." && (next === undefined || /\s/.test(next))) {
      const sentence = current.trim();
      if (sentence) sentences.push(sentence);
      current = "";
      continue;
    }
    current += ch;
  }
  const last = current.trim();
  if (last) sentences.push(last);
  return sentences;
}

function wordProblemWords(sentence) {
  return String(sentence || "")
    .split(/[^\p{L}\p{N}]+/u)
    .filter(Boolean)
    .map((token) => token.toLowerCase());
}

function parseWordProblemInteger(token) {
  const text = String(token || "").toLowerCase();
  if (/^[+-]?\d+$/.test(text)) return Number.parseInt(text, 10);
  const numbers = {
    zero: 0,
    one: 1,
    a: 1,
    an: 1,
    two: 2,
    three: 3,
    four: 4,
    five: 5,
    six: 6,
    seven: 7,
    eight: 8,
    nine: 9,
    ten: 10,
    eleven: 11,
    twelve: 12,
    thirteen: 13,
    fourteen: 14,
    fifteen: 15,
    sixteen: 16,
    seventeen: 17,
    eighteen: 18,
    nineteen: 19,
    twenty: 20,
  };
  return Object.prototype.hasOwnProperty.call(numbers, text) ? numbers[text] : null;
}

function canonicalBoxId(token) {
  const cleaned = trimNonAlnum(token).toUpperCase();
  return cleaned && cleaned.length <= 3 ? cleaned : "";
}

function parseDeclaredBoxCount(words) {
  if (
    words.length >= 4 &&
    words[0] === "i" &&
    words[1] === "have" &&
    (words[3] === "box" || words[3] === "boxes")
  ) {
    const count = parseWordProblemInteger(words[2]);
    return Number.isInteger(count) ? count : null;
  }
  return null;
}

function parseBoxRule(words) {
  let index = words[0] === "if" ? 1 : 0;
  if (words[index] !== "box" || words[index + 2] !== "has") return null;
  const target = canonicalBoxId(words[index + 1]);
  if (!target) return null;
  index += 3;

  if (
    words[index] === "twice" &&
    words[index + 1] === "as" &&
    words[index + 2] === "many" &&
    words[index + 4] === "as" &&
    words[index + 5] === "box"
  ) {
    const source = canonicalBoxId(words[index + 6]);
    if (!source) return null;
    return {
      target,
      rule: { kind: "multiple", factor: 2, source },
      item: words[index + 3] || "",
    };
  }

  const value = parseWordProblemInteger(words[index]);
  if (!Number.isInteger(value)) return null;
  if (
    words[index + 1] === "more" &&
    words[index + 3] === "than" &&
    words[index + 4] === "box"
  ) {
    const source = canonicalBoxId(words[index + 5]);
    if (!source) return null;
    return {
      target,
      rule: { kind: "add", source, addend: value },
      item: words[index + 2] || "",
    };
  }

  return {
    target,
    rule: { kind: "known", value },
    item: words[index + 1] || "",
  };
}

function resolveBoxValue(id, rules, memo, stack, reasoningSteps, resultLabel) {
  if (memo.has(id)) return memo.get(id);
  if (stack.includes(id)) return null;
  const rule = rules.get(id);
  if (!rule) return null;
  stack.push(id);
  let value = null;
  if (rule.kind === "known") {
    value = rule.value;
    reasoningSteps.push(`Box ${id} = ${value} ${resultLabel}.`);
  } else if (rule.kind === "multiple") {
    const sourceValue = resolveBoxValue(
      rule.source,
      rules,
      memo,
      stack,
      reasoningSteps,
      resultLabel,
    );
    if (!Number.isFinite(sourceValue)) return null;
    value = sourceValue * rule.factor;
    reasoningSteps.push(
      `Box ${id} = ${rule.factor} * ${sourceValue} = ${value} ${resultLabel}.`,
    );
  } else if (rule.kind === "add") {
    const sourceValue = resolveBoxValue(
      rule.source,
      rules,
      memo,
      stack,
      reasoningSteps,
      resultLabel,
    );
    if (!Number.isFinite(sourceValue)) return null;
    value = sourceValue + rule.addend;
    reasoningSteps.push(
      `Box ${id} = ${sourceValue} + ${rule.addend} = ${value} ${resultLabel}.`,
    );
  }
  stack.pop();
  if (!Number.isFinite(value)) return null;
  memo.set(id, value);
  return value;
}

function normalizeBoxTotalProblem(text) {
  const lower = String(text || "").toLowerCase();
  if (
    !lower.includes("box") ||
    !lower.includes("how many") ||
    !lower.includes("total") ||
    (!lower.includes("twice as many") &&
      !(lower.includes("more") && lower.includes("than")))
  ) {
    return null;
  }

  let declaredCount = null;
  let resultLabel = "";
  const rules = new Map();
  for (const sentence of splitSentences(text)) {
    const words = wordProblemWords(sentence);
    if (words.length === 0) continue;
    if (declaredCount === null) {
      declaredCount = parseDeclaredBoxCount(words);
    }
    const parsed = parseBoxRule(words);
    if (!parsed) continue;
    if (parsed.item && parsed.item !== "box" && parsed.item !== "boxes") {
      resultLabel = parsed.item;
    }
    rules.set(parsed.target, parsed.rule);
  }
  if (rules.size < 2) return null;
  if (declaredCount !== null && rules.size < declaredCount) return null;

  const label = resultLabel || "items";
  const memo = new Map();
  const reasoningSteps = [];
  const ids = Array.from(rules.keys()).sort();
  for (const id of ids) {
    if (
      !Number.isFinite(
        resolveBoxValue(id, rules, memo, [], reasoningSteps, label),
      )
    ) {
      return null;
    }
  }
  const values = ids.map((id) => memo.get(id));
  if (values.some((value) => !Number.isFinite(value))) return null;
  const expression = values.join(" + ");
  reasoningSteps.push(`Total = ${expression} ${label}.`);
  return { expression, reasoningSteps, resultLabel: label };
}

// Rewrite a natural-language "word problem" into a calculator expression, or
// return null when no rewrite applies so callers fall through unchanged.
function normalizeWordProblemDetailed(expression) {
  const trimmed = String(expression || "").trim();
  if (!trimmed) return null;
  const boxProblem = normalizeBoxTotalProblem(trimmed);
  if (boxProblem) return boxProblem;
  // Keep only sentence fragments that carry arithmetic content, dropping pure
  // instruction clauses such as "Show me the code and the final result".
  const arithmetic = splitSentences(trimmed).filter(
    (sentence) => sentence && (/[0-9]/.test(sentence) || sentence.includes("%")),
  );
  if (arithmetic.length === 0) return null;
  let working = resolveFibonacciReferences(arithmetic.join(". "));
  // Rewrite spelled-out operators the calculator does not accept. Longer phrases
  // come first so "and multiply it by" wins over "multiply by".
  const operatorPhrases = [
    [" and multiply it by ", " * "],
    [" and multiply by ", " * "],
    [" multiply it by ", " * "],
    [" multiplied by ", " * "],
    [" multiply by ", " * "],
    [" and divide it by ", " / "],
    [" and divide by ", " / "],
    [" divide it by ", " / "],
    [" divided by ", " / "],
    [" divide by ", " / "],
  ];
  for (const [phrase, symbol] of operatorPhrases) {
    const position = working.toLowerCase().indexOf(phrase);
    if (position !== -1) {
      working =
        working.slice(0, position) + symbol + working.slice(position + phrase.length);
    }
  }
  working = working.split(/\s+/).filter(Boolean).join(" ");
  if (!working || working.toLowerCase() === trimmed.toLowerCase()) return null;
  return { expression: working, reasoningSteps: [], resultLabel: "" };
}

// Issue #386: the calculator-domain signal set is rebuilt from three seed roles
// instead of a 62-entry literal array, so the router reasons over the same
// self-describing lexicon every other handler reads. Each surface is shaped into
// a match pattern by its script and role, mirroring calculator_domain_signals in
// src/calculation.rs:
//
// - math_function_name ("sqrt", "sin", "логарифм", "对数", …): an ASCII name gains
//   only a leading space so it still fires when glued to its argument's
//   parenthesis ("sqrt(16)"); a non-ASCII name matches as a raw substring because
//   those scripts have no inter-word spaces.
// - calculation_domain_term (currencies and measurement units: "usd", "kg",
//   "ms", "доллар", "公斤", "месяцев", …): an ASCII surface matches as a whole
//   token (leading and trailing space) so a short code like "ms" never fires
//   inside "items" nor "mb" inside "number"; a non-ASCII surface matches as a raw
//   substring.
// - quantity_conversion_cue, CJK members only ("换成", …): the Chinese conversion
//   verbs match as raw substrings; the Latin cues ("to", "into") are excluded
//   here because they are far too common to mark a calculation on their own.
//
// The caller pads the lowercased expression with surrounding spaces and tests
// includes against each signal, so the set — not its order — decides.
function calculatorDomainSignals() {
  const signals = [];
  for (const surface of wordsForRole(ROLE_MATH_FUNCTION_NAME)) {
    signals.push(isAsciiText(surface) ? ` ${surface}` : surface);
  }
  for (const surface of wordsForRole(ROLE_CALCULATION_DOMAIN_TERM)) {
    signals.push(isAsciiText(surface) ? ` ${surface} ` : surface);
  }
  for (const surface of wordsForRole(ROLE_QUANTITY_CONVERSION_CUE)) {
    if (containsCjk(surface)) {
      signals.push(surface);
    }
  }
  return signals;
}

function extractArithmeticExpression(prompt) {
  const trimmed = String(prompt || "").trim();
  if (!trimmed) return null;
  const interpretations = [];
  // Issue #386: the leading calculation cues come from the calculation_request
  // meaning by role, not a literal array. Each bare surface is rebuilt into a
  // strip prefix following its script — space-delimited scripts gain a trailing
  // space so a cue strips only on a word boundary ("calculate" never eats the
  // start of "calculated"), while CJK surfaces strip as-is because those
  // scripts have no inter-word spaces. wordsForRole preserves declaration
  // order, and the Chinese cues are stored longest first, so a more specific
  // cue strips before a shorter one it contains. Mirrors
  // strip_calculation_wrappers in src/calculation.rs.
  const prefixes = wordsForRole(ROLE_CALCULATION_REQUEST_CUE).map((surface) =>
    containsCjk(surface) ? surface : `${surface} `,
  );
  let working = trimmed;
  let changed = true;
  while (changed) {
    changed = false;
    const stripped = stripKnownPrefix(working, prefixes);
    if (stripped) {
      working = stripped.value;
      if (stripped.interpretation) interpretations.push(stripped.interpretation);
      changed = true;
    }
  }
  working = working.replace(/[?.!]+$/g, "").trim();
  // Issue #386: the trailing calculation cues come from the
  // calculation_result_query and politeness meanings by role, not a literal
  // array of regexes. Each surface is rebuilt into a strip suffix following its
  // script — CJK surfaces strip as-is because those scripts have no inter-word
  // spaces; a pure-symbol surface like the equals sign strips both bare and on a
  // word boundary (so a compact "2*2+2=" is recognised); every other surface
  // gains a leading space so the cue strips only on a word boundary. Mirrors
  // calculation_wrapper_suffixes in src/calculation.rs.
  const suffixes = [];
  for (const role of [ROLE_CALCULATION_RESULT_QUERY_CUE, ROLE_POLITENESS_CUE]) {
    for (const surface of wordsForRole(role)) {
      if (containsCjk(surface)) {
        suffixes.push(surface);
      } else if (!/\p{L}/u.test(surface)) {
        suffixes.push(` ${surface}`);
        suffixes.push(surface);
      } else {
        suffixes.push(` ${surface}`);
      }
    }
  }
  changed = true;
  while (changed) {
    changed = false;
    for (const suffix of suffixes) {
      // Mirror strip_suffix_case_insensitive in src/calculation.rs: a
      // case-insensitive endsWith followed by trimming the trailing whitespace.
      if (working.toLowerCase().endsWith(suffix)) {
        working = working.slice(0, working.length - suffix.length).trim();
        changed = true;
        break;
      }
    }
  }
  if (!working) return null;
  // Issue #334 step 2: rewrite a natural-language word problem into a calculator
  // expression ("the 10th Fibonacci number and multiply it by 8% of 500. Show me
  // the code ..." -> "55 * 8% of 500") before the symbolic checks below run.
  const wordProblem = normalizeWordProblemDetailed(working);
  let reasoningSteps = [];
  let resultLabel = "";
  if (wordProblem) {
    working = wordProblem.expression;
    reasoningSteps = Array.isArray(wordProblem.reasoningSteps)
      ? wordProblem.reasoningSteps
      : [];
    resultLabel = wordProblem.resultLabel || "";
  }
  const workingLower = working.toLowerCase();
  const hasLetter = /\p{L}/u.test(working);
  const hasSymbolic = /[+*/%^=×·÷−$€¥₹₽]/.test(working) || (!hasLetter && /-/.test(working));
  const hasWordOperator = hasArithmeticWordOperator(working);
  const hasSpelled = hasSpelledArithmetic(working);
  const hasPercentOf = evaluatePercentOfExpression(working) !== null;
  const hasWord =
    hasWordOperator ||
    calculatorDomainSignals().some((signal) => ` ${workingLower} `.includes(signal));
  const hasDigit = /[0-9]/.test(working);
  if (!hasDigit && !hasSpelled) return null;
  if (!hasSymbolic && !hasWord && hasLetter) return null;
  const extracted = { expression: working, interpretations, reasoningSteps, resultLabel };
  if (hasPercentOf) return extracted;
  if (evaluateCurrencyConversionExpression(working) !== null) {
    return extracted;
  }
  const allowed = /^[0-9+\-*/%().=\s_×·÷−,a-zA-Z]+$/;
  if (!allowed.test(working) && !hasWordOperator) return null;
  return extracted;
}

function extractFencedBlock(text, languages) {
  const fence = "```";
  let cursor = 0;
  while (true) {
    const open = text.indexOf(fence, cursor);
    if (open === -1) return null;
    const infoStart = open + fence.length;
    const newlineRel = text.indexOf("\n", infoStart);
    const infoEnd = newlineRel === -1 ? text.length : newlineRel;
    const info = text.slice(infoStart, infoEnd).trim().toLowerCase();
    const bodyStart = Math.min(infoEnd + 1, text.length);
    const closeRel = text.indexOf(fence, bodyStart);
    if (closeRel === -1) return null;
    const body = text.slice(bodyStart, closeRel).replace(/\n+$/, "");
    if (info === "" || languages.some((lang) => info === lang)) {
      return body;
    }
    cursor = closeRel + fence.length;
  }
}

function extractJavaScriptProgram(prompt) {
  const lower = String(prompt || "").toLowerCase();
  const asksToRun =
    lower.includes("run this javascript") ||
    lower.includes("run this js") ||
    lower.includes("execute this javascript") ||
    lower.includes("execute this js") ||
    lower.includes("run the following javascript") ||
    lower.includes("run the following js") ||
    lower.includes("evaluate this javascript") ||
    lower.includes("evaluate this js");
  if (!asksToRun) return null;
  const fenced = extractFencedBlock(prompt, ["javascript", "js"]);
  if (fenced !== null) return fenced;
  const backticks = prompt.match(/`([^`]+)`/);
  if (backticks) return backticks[1];
  const quoted = prompt.match(/"([^"]+)"/);
  return quoted ? quoted[1] : null;
}

// Look up an intent route by id (e.g. "intent_greeting"). Returns `null`
// when the routing table is empty (no `.lino` seed) so callers can decide
// whether to fall back to legacy hardcoded matching.
function findIntentRoute(id) {
  if (!INTENT_ROUTING || !Array.isArray(INTENT_ROUTING.intents)) return null;
  for (const route of INTENT_ROUTING.intents) {
    if (route && route.id === id) return route;
  }
  return null;
}

function tokensOf(normalized) {
  return normalized ? normalized.split(/\s+/).filter(Boolean) : [];
}

function tokenContains(normalized, expected) {
  return tokensOf(normalized).includes(String(expected || ""));
}

// Match a normalized prompt against an intent route using the same
// semantics as `src/engine.rs::matches_intent_route`:
//   - `keywords` / `phrases`: exact whole-prompt match
//   - `tokens`: any whitespace-separated token equals the value
//   - `combos`: every combo entry must appear as a token
function matchesIntentRoute(normalized, rawPrompt, id) {
  const route = findIntentRoute(id);
  if (!route) return false;
  const fromWasm = wasmMatchIntentRoute(normalized, rawPrompt, route);
  if (fromWasm !== null) return fromWasm;
  const raw = String(rawPrompt || "")
    .toLowerCase()
    .replace(/[?。.!!,,;:]+$/g, "")
    .trim();
  if (route.keywords && route.keywords.some((kw) => kw === normalized || kw === raw)) {
    return true;
  }
  if (route.phrases && route.phrases.some((ph) => ph === normalized || ph === raw)) {
    return true;
  }
  if (route.tokens && route.tokens.some((tok) => tokenContains(normalized, tok))) {
    return true;
  }
  if (
    route.combos &&
    route.combos.some(
      (combo) =>
        Array.isArray(combo) &&
        combo.length > 0 &&
        combo.every((tok) => tokenContains(normalized, tok)),
    )
  ) {
    return true;
  }
  return false;
}

function isIdentityPrompt(normalized, rawPrompt) {
  if (repositoryFromPrompt(rawPrompt)) return false;
  return matchesIntentRoute(normalized, rawPrompt, "intent_identity");
}

function isAssistantNamePrompt(normalized, rawPrompt) {
  return matchesIntentRoute(normalized, rawPrompt, "intent_assistant_name");
}

function isGreetingPrompt(normalized, rawPrompt) {
  return matchesIntentRoute(normalized, rawPrompt, "intent_greeting");
}

function isFarewellPrompt(normalized, rawPrompt) {
  return matchesIntentRoute(normalized, rawPrompt, "intent_farewell");
}

function isTestStatusPrompt(normalized, rawPrompt) {
  return matchesIntentRoute(normalized, rawPrompt, "intent_test_status");
}

function isCourtesyResponsePrompt(normalized, rawPrompt) {
  return matchesIntentRoute(normalized, rawPrompt, "intent_courtesy_response");
}

function isPunctuationOnlyPrompt(prompt) {
  const trimmed = String(prompt || "").trim();
  return /^[.!?…。?!]+$/.test(trimmed);
}

function stableBehaviorRuleId(prefix, value) {
  const fromWasm = wasmStableId(prefix, value);
  if (fromWasm) return fromWasm;
  let hash = 0xcbf29ce484222325n;
  const sourceBytes = new TextEncoder().encode(String(value || ""));
  for (const byte of sourceBytes) {
    hash ^= BigInt(byte);
    hash = BigInt.asUintN(64, hash * 0x100000001b3n);
  }
  return `${prefix}_${hash.toString(16).padStart(16, "0")}`;
}

function extractQuotedPhrase(text) {
  const source = String(text || "");
  const pairs = [
    ['"', '"'],
    ["'", "'"],
    ["`", "`"],
    ["«", "»"],
  ];
  for (const [open, close] of pairs) {
    const start = source.indexOf(open);
    if (start === -1) continue;
    const end = source.indexOf(close, start + open.length);
    if (end !== -1) return source.slice(start + open.length, end);
  }
  return null;
}

// Issue #386 translation roles — mirror the ROLE_TRANSLATION_* constants in
// src/seed/roles.rs. Each role's slot-marked surface words live in
// data/seed/meanings-translation.lino (embedded in MEANINGS_LINO above); the
// detection and extraction helpers ask the lexicon for those forms by meaning,
// slot, and script instead of hardcoding a per-language phrase list. This is
// the JS mirror of src/translation/language_markers.rs and
// src/translation/prompt.rs.
const ROLE_TRANSLATION_SOURCE_MARKER = "translation_source_marker";
const ROLE_TRANSLATION_TARGET_MARKER = "translation_target_marker";
const ROLE_TRANSLATION_TARGET_DIRECTION = "translation_target_direction";
const ROLE_TRANSLATION_UNQUOTED_FRAME = "translation_unquoted_frame";
const ROLE_TRANSLATION_INTO_MARKER = "translation_into_marker";
const ROLE_TRANSLATION_OBJECT_MARKER = "translation_object_marker";

// The ISO 639-1 code of the language_* meaning that defines a marker. Mirrors
// language_code in src/translation/language_markers.rs: the surface *names* of
// each language live in the seed; only this slug -> code bridge stays in code.
function translationLanguageCode(meaning) {
  for (const slug of meaning.definedBy) {
    if (slug === "language_english") return "en";
    if (slug === "language_russian") return "ru";
    if (slug === "language_hindi") return "hi";
    if (slug === "language_chinese") return "zh";
  }
  return null;
}

// The first marker meaning of `role` (in declaration order) any of whose
// surface words is a substring of `normalized` reports its language. Plain
// substring matching — not the boundary-aware surfacePresent — is intentional
// and mirrors detect_marker_language in src/translation/language_markers.rs: a
// CJK marker like 从中文 has no word spaces, and a Cyrillic marker like
// "с английского" must match inside a longer sentence.
function detectTranslationMarkerLanguage(role, normalized) {
  for (const meaning of meaningsWithRole(role)) {
    if (meaning.words.some((word) => normalized.includes(word))) {
      const code = translationLanguageCode(meaning);
      if (code) return code;
    }
  }
  return null;
}

let cachedTranslationMarkers = null;
// Project the translation-extraction markers out of the meaning lexicon, once.
// Each field is a semantic role narrowed to the slot and script its strategy
// needs, in declaration order — the code names a role and a shape, never a
// surface word. Mirrors markers() in src/translation/prompt.rs.
function translationMarkers() {
  if (cachedTranslationMarkers) return cachedTranslationMarkers;
  const scriptForms = (role, script) =>
    roleWordForms(role)
      .filter((form) => script(form.text))
      .map((form) => form.text);
  const bareScriptForms = (role, script) =>
    roleWordForms(role)
      .filter((form) => form.slot === "bare" && script(form.text))
      .map((form) => form.before);
  cachedTranslationMarkers = {
    circumfixFrames: roleWordForms(ROLE_TRANSLATION_UNQUOTED_FRAME)
      .filter((form) => form.slot === "circumfix")
      .map((form) => [form.before, form.after]),
    hindiVerbStems: bareScriptForms(
      ROLE_TRANSLATION_UNQUOTED_FRAME,
      containsDevanagari,
    ),
    hindiTargetMarkers: scriptForms(
      ROLE_TRANSLATION_INTO_MARKER,
      containsDevanagari,
    ),
    hindiObjectMarkers: scriptForms(
      ROLE_TRANSLATION_OBJECT_MARKER,
      containsDevanagari,
    ),
    chineseCommandPrefixes: scriptForms(
      ROLE_TRANSLATION_OBJECT_MARKER,
      containsCjk,
    ),
    chineseCommandMarkers: scriptForms(
      ROLE_TRANSLATION_INTO_MARKER,
      containsCjk,
    ),
    chineseTranslatePrefixes: bareScriptForms(
      ROLE_TRANSLATION_UNQUOTED_FRAME,
      containsCjk,
    ),
    chineseTargetMarkers: scriptForms(
      ROLE_TRANSLATION_TARGET_DIRECTION,
      containsCjk,
    ),
  };
  return cachedTranslationMarkers;
}

// Issue #216: extract the surface from unquoted translation prompts such as
// `translate apple to russian`, `переведи яблоко на английский`,
// `apple का हिंदी में अनुवाद करो`, or `把 apple 翻译成中文`. Returns null when
// the prompt already contains a quoted fragment or does not match a supported
// verb + target-marker pattern. Issue #386: every marker is now projected from
// the lexicon by role/slot/script — translationMarkers() above — so this code
// names the *shape* of each frame, never its words.
function extractUnquotedTranslationSurface(text) {
  const source = String(text || "").trim();
  const trimmed = source.replace(/[.!?。]+$/u, "");
  const lower = trimmed.toLowerCase();
  const markers = translationMarkers();

  for (const [prefix, marker] of markers.circumfixFrames) {
    const extracted = extractBetweenPrefixAndMarker(
      trimmed,
      lower,
      prefix,
      marker,
    );
    if (extracted) return extracted;
  }

  const hindi = extractHindiUnquotedTranslationSurface(trimmed, lower);
  if (hindi) return hindi;
  return extractChineseUnquotedTranslationSurface(trimmed, lower);
}

// The surface that sits between a circumfix frame's prefix and its trailing
// marker (e.g. "translate " … " to "). Mirrors extract_between_prefix_and_marker
// in src/translation/prompt.rs.
function extractBetweenPrefixAndMarker(original, lower, prefix, marker) {
  if (!lower.startsWith(prefix)) return null;
  const afterPrefix = lower.slice(prefix.length);
  const markerIndex = afterPrefix.indexOf(marker);
  if (markerIndex === -1) return null;
  return cleanUnquotedTranslationSurface(
    original.slice(prefix.length, prefix.length + markerIndex),
  );
}

function cleanUnquotedTranslationSurface(candidate) {
  const cleaned = String(candidate || "").trim();
  if (!cleaned || /["'«»`“”‘’]/u.test(cleaned)) return null;
  return cleaned;
}

// Head-final Hindi: "<surface> <object-marker> <target> में अनुवाद". Gated on a
// Devanagari translate stem (अनुवाद); the target markers and object markers are
// the Devanagari forms of the into-marker and object-marker roles. Mirrors
// extract_hindi_unquoted_surface in src/translation/prompt.rs.
function extractHindiUnquotedTranslationSurface(original, lower) {
  const markers = translationMarkers();
  if (!markers.hindiVerbStems.some((stem) => lower.includes(stem))) return null;
  for (const targetMarker of markers.hindiTargetMarkers) {
    const targetIndex = lower.indexOf(targetMarker);
    if (targetIndex === -1) continue;
    const beforeTarget = lower.slice(0, targetIndex);
    for (const surfaceMarker of markers.hindiObjectMarkers) {
      const surfaceEnd = beforeTarget.lastIndexOf(surfaceMarker);
      if (surfaceEnd !== -1) {
        return cleanUnquotedTranslationSurface(original.slice(0, surfaceEnd));
      }
    }
  }
  return null;
}

function firstMarkerOffset(text, markers) {
  let best = null;
  for (const marker of markers) {
    const offset = text.indexOf(marker);
    if (offset !== -1 && (best === null || offset < best)) best = offset;
  }
  return best;
}

// Head-initial Chinese: a command prefix (把/将) + command marker (翻译成 …), or a
// bare translate stem (翻译/翻譯) + target marker (成/为/到). Both prefix sets and
// marker sets are the Han forms of the object-marker / into-marker / unquoted-
// frame / target-direction roles. Mirrors extract_chinese_unquoted_surface in
// src/translation/prompt.rs.
function extractChineseUnquotedTranslationSurface(original, lower) {
  const markers = translationMarkers();
  for (const prefix of markers.chineseCommandPrefixes) {
    if (!lower.startsWith(prefix)) continue;
    const rest = lower.slice(prefix.length);
    const markerIndex = firstMarkerOffset(rest, markers.chineseCommandMarkers);
    if (markerIndex !== null) {
      return cleanUnquotedTranslationSurface(
        original.slice(prefix.length, prefix.length + markerIndex),
      );
    }
  }

  for (const prefix of markers.chineseTranslatePrefixes) {
    if (!lower.startsWith(prefix)) continue;
    const rest = lower.slice(prefix.length);
    const markerIndex = firstMarkerOffset(rest, markers.chineseTargetMarkers);
    if (markerIndex !== null) {
      return cleanUnquotedTranslationSurface(
        original.slice(prefix.length, prefix.length + markerIndex),
      );
    }
  }
  return null;
}

function escapeBehaviorRuleValue(value) {
  return String(value || "")
    .replaceAll("\\", "\\\\")
    .replaceAll('"', '\\"')
    .replaceAll("\n", "\\n");
}

function behaviorRuleRecords() {
  const greeting = answerFor("greeting", "en");
  const farewell = answerFor("farewell", "en");
  const identity = answerFor("identity", "en");
  const assistantName = answerFor("assistant_name", "en");
  return [
    {
      id: "rule_greeting",
      topic: "greetings",
      intent: "greeting",
      label: "Greeting rule",
      matches: "`Hi`, `Hello`, `Hey`, and multilingual greeting seed phrases",
      response: greeting,
      source: "data/seed/intent-routing.lino + multilingual responses",
      whenThen: `When the user says \`Hi\`, \`Hello\`, or \`Hey\` then respond with \`${greeting}\`.`,
    },
    {
      id: "rule_farewell",
      topic: "farewells",
      intent: "farewell",
      label: "Farewell rule",
      matches: "`bye`, `goodbye`, `poka`, and multilingual farewell seed phrases",
      response: farewell,
      source: "data/seed/intent-routing.lino + multilingual responses",
      whenThen: `When the user says \`bye\`, \`goodbye\`, or \`пока\` then respond with \`${farewell}\`.`,
    },
    {
      id: "rule_identity",
      topic: "identity",
      intent: "identity",
      label: "Identity rule",
      matches: "`Who are you?`, `Кто ты?`, and equivalent identity prompts",
      response: identity,
      source: "data/seed/identity.lino + multilingual responses",
      whenThen: `When the user asks \`Who are you?\` or \`Кто ты?\` then respond with \`${identity}\`.`,
    },
    {
      id: "rule_assistant_name",
      topic: "assistant_name",
      intent: "assistant_name",
      label: "Assistant name rule",
      matches: "`What is your name?`, `Как твое имя?`, and equivalent name prompts",
      response: assistantName,
      source: "data/seed/intent-routing.lino + multilingual responses",
      whenThen: `When the user asks \`What is your name?\` or \`Как твое имя?\` then respond with \`${assistantName}\`, unless the assistant name setting is configured.`,
    },
    {
      id: "rule_capabilities",
      topic: "capabilities",
      intent: "capabilities",
      label: "Capabilities rule",
      matches: "`What can you do?`, `Что ты умеешь?`, and equivalent capability prompts",
      response: "Lists the supported symbolic chat capabilities.",
      source: "src/solver_handlers/user_intent.rs",
      whenThen:
        "When the user asks `What can you do?` or `Что ты умеешь?` then respond with the multilingual capability listing.",
    },
    {
      id: "rule_write_program",
      topic: "write_program",
      intent: "write_program",
      label: "Program template rule",
      // Built from the live catalog so the advertised tasks stay in lock-step
      // with `WRITE_PROGRAM_TASKS` (mirrors `supported_program_tasks` on the
      // Rust side, issue #330).
      matches:
        "`write_program(language, task)` with languages " +
        `${Object.keys(WRITE_PROGRAM_LANGUAGES).join(", ")} and tasks ` +
        `${Object.keys(WRITE_PROGRAM_TASKS).join(", ")}`,
      response: "Returns a minimal program from the parameterized template catalog.",
      source: "data/seed/hello-world-programs.lino + src/coding/catalog.rs",
      whenThen:
        "When the user requests a program with supported `language` and `task` parameters then respond with the matching template through the single `write_program` intent.",
    },
    {
      id: "rule_unknown",
      topic: "unknown_fallback",
      intent: "unknown",
      label: "Unknown fallback rule",
      matches: "Any prompt that no earlier rule or handler can answer",
      response: answerFor("unknown", "en"),
      source: "data/seed/multilingual-responses.lino",
      whenThen:
        "When no earlier rule or handler matches the prompt then respond with the multilingual unknown-intent guide (`List behavior rules`, `Show behavior rule`, `When I say … answer …`, `Report issue`, `Export memory`).",
    },
  ];
}

const BEHAVIOR_RULE_TOPIC_ORDER = [
  "greetings",
  "farewells",
  "identity",
  "assistant_name",
  "capabilities",
  "write_program",
  "unknown_fallback",
];

function localizedText(language, values) {
  return values[language] || values.en;
}

function behaviorRuleTopicLabel(topic, language) {
  switch (topic) {
    case "greetings":
      return localizedText(language, {
        en: "Greetings",
        ru: "Приветствия",
        hi: "अभिवादन",
        zh: "问候",
      });
    case "farewells":
      return localizedText(language, {
        en: "Farewells",
        ru: "Прощания",
        hi: "विदाई",
        zh: "告别",
      });
    case "identity":
      return localizedText(language, {
        en: "Identity",
        ru: "Идентичность",
        hi: "पहचान",
        zh: "身份",
      });
    case "assistant_name":
      return localizedText(language, {
        en: "Assistant name",
        ru: "Имя ассистента",
        hi: "सहायक का नाम",
        zh: "助手名称",
      });
    case "capabilities":
      return localizedText(language, {
        en: "Capabilities",
        ru: "Возможности",
        hi: "क्षमताएँ",
        zh: "能力",
      });
    case "write_program":
      return localizedText(language, {
        en: "Program templates",
        ru: "Шаблоны программ",
        hi: "Program templates",
        zh: "程序模板",
      });
    case "unknown_fallback":
      return localizedText(language, {
        en: "Unknown fallback",
        ru: "Резервный ответ",
        hi: "अज्ञात अनुरोध का वैकल्पिक उत्तर",
        zh: "未知请求回退",
      });
    default:
      return localizedText(language, {
        en: "Other",
        ru: "Другое",
        hi: "अन्य",
        zh: "其他",
      });
  }
}

function behaviorRuleTopicOrder(topic) {
  const index = BEHAVIOR_RULE_TOPIC_ORDER.indexOf(topic);
  return index === -1 ? BEHAVIOR_RULE_TOPIC_ORDER.length : index;
}

function behaviorRuleListIntro(language) {
  return localizedText(language, {
    en: "Behavior rules I can inspect in this dialog (grouped by topic, each shown as a `When X then Y` statement):",
    ru: "Правила поведения, которые я могу показать в этом диалоге (сгруппированы по темам; каждое показано как инструкция `Когда X тогда Y`):",
    hi: "व्यवहार नियम जिन्हें मैं इस संवाद में दिखा सकता हूँ (विषय के अनुसार समूहित; हर नियम `जब X तब Y` कथन के रूप में है):",
    zh: "我可以查看的行为规则(按主题分组;每条都显示为 `当 X 时 Y` 语句):",
  });
}

function runtimeRulesHeading(language) {
  return localizedText(language, {
    en: "Dialog-local rules taught in this conversation",
    ru: "Правила, изученные в этом диалоге",
    hi: "इस संवाद में सिखाए गए स्थानीय नियम",
    zh: "本对话中学到的局部规则",
  });
}

function behaviorRuleListFooter(language) {
  if (language === "ru") {
    return [
      "",
      "Прочитать одно правило можно командой `Покажи правило unknown` или `Покажи правило rule_greeting`.",
      "Научить этот диалог можно так: ``Когда `ваш запрос` тогда `ваш ответ` ``. Другие формы: ``Когда я скажу `ваш запрос`, ответь `ваш ответ` ``; ``Если я спрошу `ваш запрос`, ответь `ваш ответ` ``; ``Когда `ваш запрос` делай `ваш ответ` ``.",
      "Многоязычные формы: английская ``When `X` then `Y` ``, хинди ``जब `X` तब `Y` ``, китайская ``当 `X` 时 `Y` ``.",
      "Запись добавляется только в конец: экспортируйте память, чтобы сохранить сообщение с правилом вместе с диалогом.",
    ];
  }
  if (language === "hi") {
    return [
      "",
      "एक नियम पढ़ने के लिए `Show behavior rule unknown` या `Show behavior rule rule_greeting` भेजें.",
      "इस संवाद को सिखाएँ: ``जब `आपका प्रश्न` तब `आपका उत्तर` ``. अन्य रूप: ``When I say `your prompt`, answer `your answer` ``; ``If I ask `your prompt`, reply `your answer` ``; ``जब `आपका प्रश्न` तो `आपका उत्तर` ``.",
      "बहुभाषी रूप: रूसी ``Когда `X` тогда `Y` ``, अंग्रेज़ी ``When `X` then `Y` ``, चीनी ``当 `X` 时 `Y` ``.",
      "लेखन केवल append-only है: नियम संदेश को संवाद के साथ रखने के लिए memory export करें.",
    ];
  }
  if (language === "zh") {
    return [
      "",
      "要读取一条规则,请发送 `Show behavior rule unknown` 或 `Show behavior rule rule_greeting`。",
      "可以这样教当前对话:``当 `你的提示` 时 `你的回答` ``。等价形式:``When I say `your prompt`, answer `your answer` ``;``If I ask `your prompt`, reply `your answer` ``;``当 `你的提示` 则 `你的回答` ``。",
      "多语言形式:俄语 ``Когда `X` тогда `Y` ``,印地语 ``जब `X` तब `Y` ``,英语 ``When `X` then `Y` ``。",
      "写入是 append-only:导出 memory 可把这条规则消息随对话一起保存。",
    ];
  }
  return [
    "",
    "Read one with `Show behavior rule unknown` or `Show behavior rule rule_greeting`.",
    "Teach this dialog with: ``When `your prompt` then `your answer` ``. Equivalent forms: ``When I say `your prompt`, answer `your answer` ``; ``If I ask `your prompt`, reply `your answer` ``; ``When `your prompt` do `your answer` ``.",
    "Multilingual forms: Russian ``Когда `X` тогда `Y` `` / ``Когда `X` делай `Y` ``, Hindi ``जब `X` तब `Y` ``, Chinese ``当 `X` 时 `Y` ``.",
    "The write is append-only: export memory to preserve the rule message with the dialog.",
  ];
}

function localizedRuleResponse(rule, language) {
  if (rule.id === "rule_write_program") {
    return localizedText(language, {
      en: "Returns a minimal program from the parameterized template catalog.",
      ru: "Возвращает минимальную программу из параметризованного каталога шаблонов.",
      hi: "parameterized template catalog से minimal program लौटाता है.",
      zh: "从参数化模板目录返回一个最小程序。",
    });
  }
  switch (rule.id) {
    case "rule_greeting":
      return answerFor("greeting", language);
    case "rule_farewell":
      return answerFor("farewell", language);
    case "rule_identity":
      return answerFor("identity", language);
    case "rule_assistant_name":
      return localizedText(language, {
        en: "Returns the assistant-name answer; browser surfaces can override it from the assistant name setting.",
        ru: "Возвращает ответ об имени ассистента; браузерные поверхности могут переопределить его настройкой имени ассистента.",
        hi: "assistant-name उत्तर लौटाता है; browser surfaces assistant name setting से इसे बदल सकते हैं.",
        zh: "返回助手名称回答;浏览器界面可通过助手名称设置覆盖它。",
      });
    case "rule_capabilities":
      return localizedText(language, {
        en: "Lists the supported symbolic chat capabilities.",
        ru: "Перечисляет поддерживаемые возможности символьного чата.",
        hi: "समर्थित symbolic chat क्षमताओं को सूचीबद्ध करता है.",
        zh: "列出支持的符号聊天能力。",
      });
    case "rule_unknown":
      return answerFor("unknown", language);
    default:
      return rule.response;
  }
}

function localizedRuleLabel(rule, language) {
  if (rule.id === "rule_write_program") {
    return localizedText(language, {
      en: "Program template rule",
      ru: "Правило шаблона программы",
      hi: "Program template rule",
      zh: "程序模板规则",
    });
  }
  const labels = {
    rule_greeting: {
      en: "Greeting rule",
      ru: "Правило приветствия",
      hi: "अभिवादन नियम",
      zh: "问候规则",
    },
    rule_farewell: {
      en: "Farewell rule",
      ru: "Правило прощания",
      hi: "विदाई नियम",
      zh: "告别规则",
    },
    rule_identity: {
      en: "Identity rule",
      ru: "Правило идентичности",
      hi: "पहचान नियम",
      zh: "身份规则",
    },
    rule_assistant_name: {
      en: "Assistant name rule",
      ru: "Правило имени ассистента",
      hi: "सहायक नाम नियम",
      zh: "助手名称规则",
    },
    rule_capabilities: {
      en: "Capabilities rule",
      ru: "Правило возможностей",
      hi: "क्षमता नियम",
      zh: "能力规则",
    },
    rule_unknown: {
      en: "Unknown fallback rule",
      ru: "Резервное правило для неизвестного запроса",
      hi: "अज्ञात अनुरोध का वैकल्पिक नियम",
      zh: "未知请求回退规则",
    },
  };
  return labels[rule.id] ? localizedText(language, labels[rule.id]) : rule.label;
}

function localizedRuleMatches(rule, language) {
  if (rule.id === "rule_write_program") {
    return localizedText(language, {
      en: "`write_program(language, task)` with supported languages and tasks",
      ru: "`write_program(language, task)` с поддерживаемыми языками и задачами",
      hi: "supported languages और tasks वाला `write_program(language, task)`",
      zh: "带受支持语言和任务的 `write_program(language, task)`",
    });
  }
  const matches = {
    rule_greeting: {
      en: "`Hi`, `Hello`, `Hey`, and multilingual greeting seed phrases",
      ru: "`Hi`, `Hello`, `Hey` и многоязычные seed-фразы приветствия",
      hi: "`Hi`, `Hello`, `Hey` और बहुभाषी greeting seed phrases",
      zh: "`Hi`、`Hello`、`Hey` 以及多语言问候 seed 短语",
    },
    rule_farewell: {
      en: "`bye`, `goodbye`, `poka`, and multilingual farewell seed phrases",
      ru: "`bye`, `goodbye`, `poka` и многоязычные seed-фразы прощания",
      hi: "`bye`, `goodbye`, `poka` और बहुभाषी farewell seed phrases",
      zh: "`bye`、`goodbye`、`poka` 以及多语言告别 seed 短语",
    },
    rule_identity: {
      en: "`Who are you?`, `Кто ты?`, and equivalent identity prompts",
      ru: "`Who are you?`, `Кто ты?` и равнозначные вопросы об идентичности",
      hi: "`Who are you?`, `Кто ты?` और समान identity prompts",
      zh: "`Who are you?`、`Кто ты?` 以及等价身份提示",
    },
    rule_assistant_name: {
      en: "`What is your name?`, `Как тебя зовут?`, and equivalent name prompts",
      ru: "`What is your name?`, `Как тебя зовут?` и равнозначные вопросы об имени",
      hi: "`What is your name?`, `Как тебя зовут?` और समान name prompts",
      zh: "`What is your name?`、`Как тебя зовут?` 以及等价名称提示",
    },
    rule_capabilities: {
      en: "`What can you do?`, `Что ты умеешь?`, and equivalent capability prompts",
      ru: "`What can you do?`, `Что ты умеешь?` и равнозначные вопросы о возможностях",
      hi: "`What can you do?`, `Что ты умеешь?` और समान capability prompts",
      zh: "`What can you do?`、`Что ты умеешь?` 以及等价能力提示",
    },
    rule_unknown: {
      en: "Any prompt that no earlier rule or handler can answer",
      ru: "Любой запрос, на который не ответило более раннее правило или обработчик",
      hi: "कोई भी prompt जिसका उत्तर पहले का rule या handler नहीं दे सकता",
      zh: "任何前面的规则或处理器无法回答的提示",
    },
  };
  return matches[rule.id] ? localizedText(language, matches[rule.id]) : rule.matches;
}

function localizedRuleWhenThen(rule, language) {
  if (rule.id === "rule_write_program") {
    if (language === "ru") {
      return "Когда пользователь просит программу с поддерживаемыми параметрами `language` и `task`, ответь соответствующим шаблоном через единое намерение `write_program`.";
    }
    if (language === "hi") {
      return "जब उपयोगकर्ता supported `language` और `task` parameters वाला program माँगे, तब single `write_program` intent से matching template दें.";
    }
    if (language === "zh") {
      return "当用户请求带受支持 `language` 和 `task` 参数的程序时,通过单个 `write_program` 意图选择匹配模板。";
    }
    return rule.whenThen;
  }
  const response = localizedRuleResponse(rule, language);
  if (rule.id === "rule_greeting") {
    if (language === "ru") return `Когда пользователь говорит \`Hi\`, \`Hello\`, \`Hey\` или многоязычную фразу приветствия, ответь \`${response}\`.`;
    if (language === "hi") return `जब उपयोगकर्ता \`Hi\`, \`Hello\`, \`Hey\` या बहुभाषी greeting phrase कहे, तब \`${response}\` उत्तर दें.`;
    if (language === "zh") return `当用户说 \`Hi\`、\`Hello\`、\`Hey\` 或多语言问候短语时,回答 \`${response}\`。`;
  }
  if (rule.id === "rule_farewell") {
    if (language === "ru") return `Когда пользователь говорит \`bye\`, \`goodbye\`, \`poka\` или многоязычную фразу прощания, ответь \`${response}\`.`;
    if (language === "hi") return `जब उपयोगकर्ता \`bye\`, \`goodbye\`, \`poka\` या बहुभाषी farewell phrase कहे, तब \`${response}\` उत्तर दें.`;
    if (language === "zh") return `当用户说 \`bye\`、\`goodbye\`、\`poka\` 或多语言告别短语时,回答 \`${response}\`。`;
  }
  if (rule.id === "rule_identity") {
    if (language === "ru") return `Когда пользователь спрашивает \`Who are you?\` или \`Кто ты?\`, ответь \`${response}\`.`;
    if (language === "hi") return `जब उपयोगकर्ता \`Who are you?\` या \`Кто ты?\` पूछे, तब \`${response}\` उत्तर दें.`;
    if (language === "zh") return `当用户问 \`Who are you?\` 或 \`Кто ты?\` 时,回答 \`${response}\`。`;
  }
  if (rule.id === "rule_assistant_name") {
    if (language === "ru") return "Когда пользователь спрашивает `What is your name?` или `Как тебя зовут?`, ответь сообщением об имени ассистента; если поверхность поддерживает настройку имени, включи настроенное имя.";
    if (language === "hi") return "जब उपयोगकर्ता `What is your name?` या `Как тебя зовут?` पूछे, तब assistant-name उत्तर दें; अगर surface में assistant-name setting है, तो configured name शामिल करें.";
    if (language === "zh") return "当用户问 `What is your name?` 或 `Как тебя зовут?` 时,回答助手名称;如果界面有助手名称设置,则包含配置的名称。";
  }
  if (rule.id === "rule_capabilities") {
    if (language === "ru") return "Когда пользователь спрашивает `What can you do?` или `Что ты умеешь?`, ответь многоязычным списком возможностей.";
    if (language === "hi") return "जब उपयोगकर्ता `What can you do?` या `Что ты умеешь?` पूछे, तब बहुभाषी capability listing दें.";
    if (language === "zh") return "当用户问 `What can you do?` 或 `Что ты умеешь?` 时,回答多语言能力列表。";
  }
  if (rule.id === "rule_unknown") {
    if (language === "ru") return "Когда ни одно более раннее правило или обработчик не подходит к запросу, ответь многоязычной подсказкой для неизвестного намерения (`Покажи правила`, `Покажи правило`, `Когда ... тогда ...`, `Сообщить о проблеме`, `Экспорт памяти`).";
    if (language === "hi") return "जब कोई पहले का rule या handler prompt से मेल न खाए, तब unknown-intent guide दें (`नियम दिखाएँ`, `rule दिखाएँ`, `जब ... तब ...`, `Report issue`, `Export memory`).";
    if (language === "zh") return "当前面的规则或处理器都不匹配提示时,回答未知意图指南(`显示规则`、`显示规则详情`、`当 ... 时 ...`、`报告问题`、`导出 memory`)。";
  }
  return rule.whenThen;
}

function runtimeRuleWhenThen(rule, language) {
  if (language === "ru") {
    return `Когда пользователь говорит \`${rule.trigger}\`, ответь \`${rule.answer}\`.`;
  }
  if (language === "hi") {
    return `जब उपयोगकर्ता \`${rule.trigger}\` कहे, तब \`${rule.answer}\` उत्तर दें.`;
  }
  if (language === "zh") {
    return `当用户说 \`${rule.trigger}\` 时,回答 \`${rule.answer}\`。`;
  }
  return `When the user says \`${rule.trigger}\` then respond with \`${rule.answer}\`.`;
}

function renderBehaviorRuleList(runtimeRules, language = "en") {
  const lines = [behaviorRuleListIntro(language), ""];
  const groups = new Map();
  for (const rule of behaviorRuleRecords()) {
    const order = behaviorRuleTopicOrder(rule.topic);
    if (!groups.has(order)) {
      groups.set(order, { label: behaviorRuleTopicLabel(rule.topic, language), rules: [] });
    }
    groups.get(order).rules.push(rule);
  }
  const ordered = Array.from(groups.entries()).sort((a, b) => a[0] - b[0]);
  ordered.forEach(([, group], index) => {
    lines.push(`### ${group.label}`);
    for (const rule of group.rules) {
      lines.push(`- \`${rule.id}\` -> ${localizedRuleWhenThen(rule, language)}`);
    }
    if (index + 1 < ordered.length) lines.push("");
  });
  if (Array.isArray(runtimeRules) && runtimeRules.length > 0) {
    lines.push("", `### ${runtimeRulesHeading(language)}`);
    for (const rule of runtimeRules) {
      lines.push(
        `- \`${rule.id}\` -> ${runtimeRuleWhenThen(rule, language)}`,
      );
    }
  }
  lines.push(...behaviorRuleListFooter(language));
  return lines.join("\n");
}

function renderBehaviorRuleDetail(rule, language = "en") {
  const label = localizedRuleLabel(rule, language);
  const whenThen = localizedRuleWhenThen(rule, language);
  const matches = localizedRuleMatches(rule, language);
  const response = localizedRuleResponse(rule, language);
  const changeHint = localizedText(language, {
    en: "To change this behavior in the current dialog, send: ``When `your prompt` then `your answer` ``. Equivalent: ``When I say `your prompt`, answer `your answer` ``.",
    ru: "Чтобы изменить это поведение в текущем диалоге, отправьте: ``Когда `ваш запрос` тогда `ваш ответ` ``. Также можно: ``Когда я скажу `ваш запрос`, ответь `ваш ответ` ``.",
    hi: "इस व्यवहार को वर्तमान संवाद में बदलने के लिए भेजें: ``जब `आपका प्रश्न` तब `आपका उत्तर` ``. दूसरा रूप: ``When I say `your prompt`, answer `your answer` ``.",
    zh: "要在当前对话中改变此行为,请发送:``当 `你的提示` 时 `你的回答` ``。也可以发送:``When I say `your prompt`, answer `your answer` ``。",
  });
  return [
    label,
    "",
    whenThen,
    "",
    "```links",
    rule.id,
    `  topic "${escapeBehaviorRuleValue(rule.topic)}"`,
    `  intent "${escapeBehaviorRuleValue(rule.intent)}"`,
    `  matches "${escapeBehaviorRuleValue(matches)}"`,
    `  response "${escapeBehaviorRuleValue(response)}"`,
    `  source "${escapeBehaviorRuleValue(rule.source)}"`,
    `  when_then "${escapeBehaviorRuleValue(whenThen)}"`,
    "```",
    "",
    changeHint,
  ].join("\n");
}

function assistantNameStatus(preferences) {
  const name = normalizeAssistantNamePreference(
    preferences && preferences.assistantName,
  );
  return name ? `configured:${name}` : "browser_preference_when_set_else_not_configured";
}

const BROWSER_SURFACE = {
  slug: "browser",
  label: "browser demo with JavaScript and WebAssembly worker",
  runtime: "JavaScript UI plus a WebAssembly worker mirror of the solver",
  memory: "browser IndexedDB/local storage plus worker state and imported memory",
  webSearch: "available through browser CORS-readable providers when online and not blocked",
  limits: "browser settings, import/export controls, and IndexedDB-backed memory belong to this surface",
};

function modeStatus(enabled) {
  return enabled ? "enabled" : "disabled";
}

function definitionFusionStatus(preferences) {
  return preferences && preferences.definitionFusion === "auto"
    ? "enabled_by_default"
    : "explicit_only";
}

function blueprintCompositionStatus(preferences) {
  return normalizeBlueprintComposition(
    preferences && preferences.blueprintComposition,
  );
}

function renderSelfFacts(preferences) {
  const assistantName = assistantNameStatus(preferences);
  const surface = BROWSER_SURFACE;
  return [
    "Facts I know about myself in this environment:",
    "",
    `- **Execution surface**: ${surface.label} (\`${surface.slug}\`).`,
    `- **Runtime**: ${surface.runtime}.`,
    `- **Memory**: ${surface.memory}.`,
    `- **Web search**: ${surface.webSearch}.`,
    `- **Surface limits**: ${surface.limits}.`,
    "- **Local rules**: local Links Notation rules and seed facts are checked first.",
    "",
    "```links",
    "self_fact_model",
    '  subject "formal-ai"',
    '  relation "model"',
    `  object "${escapeBehaviorRuleValue(AGENT_INFO.model || "formal-symbolic-production")}"`,
    "self_fact_policy",
    '  subject "formal-ai"',
    '  relation "policy"',
    '  object "deterministic symbolic AI; no neural network inference"',
    "self_fact_environment",
    '  subject "formal-ai"',
    '  relation "execution_surface"',
    `  object "${surface.slug}"`,
    "self_fact_runtime",
    '  subject "formal-ai"',
    '  relation "runtime"',
    `  object "${escapeBehaviorRuleValue(surface.runtime)}"`,
    "self_fact_memory",
    '  subject "formal-ai"',
    '  relation "memory"',
    `  object "${escapeBehaviorRuleValue(surface.memory)}"`,
    "self_fact_web_search",
    '  subject "formal-ai"',
    '  relation "web_search"',
    `  object "${escapeBehaviorRuleValue(surface.webSearch)}"`,
    "self_fact_assistant_name",
    '  subject "formal-ai"',
    '  relation "assistant_name"',
    `  object "${escapeBehaviorRuleValue(assistantName)}"`,
    "self_fact_agent_mode",
    '  subject "formal-ai"',
    '  relation "agent_mode"',
    `  object "${modeStatus(preferences && preferences.agentMode)}"`,
    "self_fact_diagnostics",
    '  subject "formal-ai"',
    '  relation "diagnostic_mode"',
    `  object "${modeStatus(preferences && preferences.diagnosticsMode)}"`,
    "self_fact_definition_fusion",
    '  subject "formal-ai"',
    '  relation "definition_fusion"',
    `  object "${definitionFusionStatus(preferences)}"`,
    "self_fact_blueprint_composition",
    '  subject "formal-ai"',
    '  relation "blueprint_composition"',
    `  object "${blueprintCompositionStatus(preferences)}"`,
    "```",
    "",
    "Read behavior with `List behavior rules`; teach one with When `prompt` then `answer` (or When I say `prompt`, answer `answer`).",
  ].join("\n");
}

function renderKnownFacts(language, preferences) {
  const surface = BROWSER_SURFACE;
  const assistantName = assistantNameStatus(preferences);
  const links = [
    "```links",
    "known_fact_local_seed",
    '  source "local_links_notation_seed"',
    '  scope "built-in rules, concepts, facts, tools, and response templates"',
    "known_fact_internet",
    '  source "environment_aware_web_search"',
    `  scope "${escapeBehaviorRuleValue(surface.webSearch)}"`,
    "known_fact_memory",
    '  source "conversation_memory"',
    `  scope "${escapeBehaviorRuleValue(surface.memory)}"`,
    "known_fact_environment",
    '  subject "formal-ai"',
    '  relation "execution_surface"',
    `  object "${surface.slug}"`,
    "known_fact_self",
    '  subject "formal-ai"',
    '  relation "model"',
    `  object "${escapeBehaviorRuleValue(AGENT_INFO.model || "formal-symbolic-production")}"`,
    "known_fact_assistant_name",
    '  subject "formal-ai"',
    '  relation "assistant_name_setting"',
    `  object "${escapeBehaviorRuleValue(assistantName)}"`,
    "known_fact_surface_limits",
    '  source "environment_directory"',
    `  scope "${escapeBehaviorRuleValue(surface.limits)}"`,
    "```",
  ].join("\n");
  if (language === "ru") {
    return [
      `Я могу использовать несколько классов фактов в текущей среде \`${surface.slug}\`:`,
      "",
      "- **Локальные факты и правила**: встроенный seed Links Notation, включая правила, понятия, инструменты и ответы.",
      `- **Интернет**: ${surface.webSearch}; это не означает, что весь интернет предзагружен в локальную память.`,
      `- **Память диалога**: ${surface.memory}.`,
      "- **Факты о себе**: модель `formal-symbolic-production`, политика исполнения, поверхность и источники ответов.",
      `- **Ограничения среды**: ${surface.limits}.`,
      "",
      links,
      "",
      "Для конкретного факта задайте прямой вопрос; порядок проверки: локальные правила, память, затем веб-поиск, если он доступен в этой среде.",
    ].join("\n");
  }
  if (language === "hi") {
    return [
      `मैं current \`${surface.slug}\` environment में इन fact sources का उपयोग कर सकता हूँ:`,
      "",
      "- **Local facts and rules**: Links Notation seed में rules, concepts, tools और response templates.",
      `- **Internet**: ${surface.webSearch}; पूरा internet local memory में preload नहीं है.`,
      `- **Conversation memory**: ${surface.memory}.`,
      "- **Self facts**: model `formal-symbolic-production`, execution surface और answer sources.",
      `- **Surface limits**: ${surface.limits}.`,
      "",
      links,
      "",
      "किसी खास fact के लिए सीधे पूछें; मैं local rules और memory पहले देखता हूँ, फिर environment अनुमति दे तो web search इस्तेमाल करता हूँ.",
    ].join("\n");
  }
  if (language === "zh") {
    return [
      `在当前 \`${surface.slug}\` 环境中, 我可以使用这些事实来源:`,
      "",
      "- **本地事实和规则**: Links Notation seed 中的规则、概念、工具和回复模板。",
      `- **Internet**: ${surface.webSearch}; 整个互联网不会预加载到本地记忆中。`,
      `- **Conversation memory**: ${surface.memory}。`,
      "- **Self facts**: model `formal-symbolic-production`, execution surface 和 answer sources。",
      `- **Surface limits**: ${surface.limits}。`,
      "",
      links,
      "",
      "如果需要某个具体事实, 请直接提问; 我会先检查本地规则和记忆, 环境允许时再使用 web search。",
    ].join("\n");
  }
  return [
    `I can use several classes of facts in the current \`${surface.slug}\` environment:`,
    "",
    "- **Local facts and rules**: built-in Links Notation seed data, including rules, concepts, tools, and response templates.",
    `- **Internet**: ${surface.webSearch}; the whole internet is not preloaded into local memory.`,
    `- **Conversation memory**: ${surface.memory}.`,
    "- **Self facts**: model `formal-symbolic-production`, execution policy, active surface, and answer sources.",
    `- **Surface limits**: ${surface.limits}.`,
    "",
    links,
    "",
    "Ask for a specific fact directly; I check local rules and memory first, then use web search only when this environment allows it.",
  ].join("\n");
}

function renderRuntimeRuleUpdate(rule, language = "en") {
  const whenThenText = runtimeRuleWhenThen(rule, language);
  const title = localizedText(language, {
    en: "Behavior rule recorded for this dialog.",
    ru: "Правило поведения записано для этого диалога.",
    hi: "इस संवाद के लिए व्यवहार नियम record किया गया.",
    zh: "已为本对话记录行为规则。",
  });
  const sendHint =
    language === "ru"
      ? `Отправьте \`${rule.trigger}\` сейчас, и я отвечу настроенным ответом. Экспортируйте память, чтобы сохранить это правило вместе с диалогом.`
      : language === "hi"
        ? `\`${rule.trigger}\` अभी भेजें और मैं configured response से उत्तर दूँगा. इस rule message को dialog के साथ रखने के लिए memory export करें.`
        : language === "zh"
          ? `现在发送 \`${rule.trigger}\`,我会使用配置的回答。导出 memory 可把这条规则消息随对话一起保存。`
          : `Send \`${rule.trigger}\` now and I will answer with the configured response. Export memory to keep this rule message with the dialog.`;
  return [
    title,
    "",
    whenThenText,
    "",
    "```links",
    rule.id,
    '  type "behavior_rule_runtime"',
    `  match_prompt "${escapeBehaviorRuleValue(rule.trigger)}"`,
    `  answer "${escapeBehaviorRuleValue(rule.answer)}"`,
    `  when_then "${escapeBehaviorRuleValue(whenThenText)}"`,
    '  source "user_message"',
    "```",
    "",
    sendHint,
  ].join("\n");
}

// Issue #386: recognise a request to list the assistant's behavior rules by
// *meaning*, not a hardcoded per-language phrase list. The standalone phrases
// (role rule_listing_phrase) and the three compositional dimensions
// (rule_listing_subject / rule_listing_request / rule_listing_scope) live in
// data/seed/meanings-behavior-rules.lino. Mirror of is_behavior_rules_list in
// src/solver_handlers/behavior_rules.rs.
function isBehaviorRulesList(normalized) {
  return (
    matchesBehaviorRulesListSeedPattern(normalized) ||
    lexiconMentionsRoleSubstring(ROLE_RULE_LISTING_PHRASE, normalized) ||
    isSupportedLanguageBehaviorRulesListQuery(normalized)
  );
}

function matchesBehaviorRulesListSeedPattern(normalized) {
  return PROMPT_PATTERNS.some((pattern) => {
    if (!pattern || pattern.intent !== "behavior_rules_list" || !pattern.text) {
      return false;
    }
    const text = normalizePrompt(pattern.text);
    if (!text) return false;
    switch (pattern.kind) {
      case "keyword":
      case "phrase":
        return normalized === text || normalized.includes(text);
      case "prefix":
        return normalized.startsWith(text);
      case "suffix":
        return normalized.endsWith(text);
      default:
        return false;
    }
  });
}

// True when the prompt, within one supported language's vocabulary, names the
// rule subject, asks to enumerate it, and scopes the request to the assistant's
// own behavior. The three dimensions are read from the meaning lexicon
// (rule_listing_subject / rule_listing_request / rule_listing_scope) rather than
// hardcoded per-language word lists. The per-language AND is preserved: every
// dimension must be evidenced within the SAME language (wordsForRoleInLanguages),
// matched as a raw substring to keep the legacy stem match byte-for-byte. Mirror
// of is_supported_language_behavior_rules_list_query in
// src/solver_handlers/behavior_rules.rs.
function isSupportedLanguageBehaviorRulesListQuery(normalized) {
  const present = (role, language) =>
    wordsForRoleInLanguages(role, [language]).some((word) =>
      normalized.includes(word),
    );
  return ["en", "ru", "hi", "zh"].some(
    (language) =>
      present(ROLE_RULE_LISTING_SUBJECT, language) &&
      present(ROLE_RULE_LISTING_REQUEST, language) &&
      present(ROLE_RULE_LISTING_SCOPE, language),
  );
}

// Issue #386: recognise a request to list the assistant's own facts by
// *meaning*, not a hardcoded per-language phrase list. The self_fact_query role
// gathers every surface from data/seed/meanings-intent.lino; mirror of
// is_self_fact_query in src/solver_handlers/self_awareness.rs. The prompt is
// re-normalized first because some call sites pass a merely-lowercased string
// (trailing "?" intact) and the boundary-aware matcher expects punctuation
// already collapsed to spaces.
function isSelfFactQuery(normalized) {
  return lexiconMentionsRole(ROLE_SELF_FACT_QUERY, normalizePrompt(normalized));
}

// Issue #386: recognise "introduce yourself" / "расскажи о себе" /
// "अपना परिचय दो" / "介绍一下你自己" by the self_introduction_request meaning
// role. The pre-check is preserved verbatim: an empty prompt, or one that is
// really a self-fact query, must not be treated as an introduction request, so
// "list all facts you know about yourself" still routes to the self-fact
// branch. Mirror of is_self_introduction_query in
// src/solver_handlers/self_awareness.rs.
function isSelfIntroductionQuery(normalized) {
  const cleaned = normalizePrompt(normalized);
  if (!cleaned || isSelfFactQuery(cleaned)) return false;
  return lexiconMentionsRole(ROLE_SELF_INTRODUCTION_REQUEST, cleaned);
}

function selfAwarenessLanguage(prompt, normalized) {
  // Issue #386: language is detected purely by Unicode script ranges. The
  // Cyrillic range below already subsumes the former second-person pronoun
  // list (ty/tebya/tvoy/vy/...), every member of which is Cyrillic, so no raw
  // word list is needed -- the script range is the universal signal. Mirror of
  // self_awareness_language in src/solver_handlers/self_awareness.rs.
  const text = `${String(prompt || "").toLowerCase()} ${String(normalized || "")}`;
  if (/[\u0400-\u04ff]/u.test(text)) return "ru";
  if (/[\u0900-\u097f]/u.test(text)) return "hi";
  if (/[\u4e00-\u9fff]/u.test(text)) return "zh";
  return detectLanguage(prompt);
}

function selfIntroductionContent(language, preferences) {
  const identity = answerFor("identity", language);
  const name = normalizeAssistantNamePreference(
    preferences && preferences.assistantName,
  );
  if (!name) return identity;
  if (language === "ru") return `Меня зовут ${name}. ${identity}`;
  if (language === "hi") return `मेरा नाम ${name} है। ${identity}`;
  if (language === "zh") return `我的名字是 ${name}。${identity}`;
  return `My name is ${name}. ${identity}`;
}

function cleanConversationTopic(raw) {
  return String(raw || "")
    .trim()
    .replace(/^[`"':._,\-\s!?]+|[`"':._,\-\s!?]+$/gu, "");
}

function conversationTopic(prompt, normalized) {
  // Recognized surfaces — the let-us-talk-about-X phrasings in every supported
  // language — carry the conversation_topic_opener role; each is a prefix whose
  // text before the … slot is the matchable opener, in declaration order. A
  // form whose action is "scan" is also matched anywhere in the prompt, not only
  // at the start, so an opener that follows a greeting is still found. No
  // per-language opener list lives here — only the concept. Mirrors
  // conversation_topic in src/solver_handlers/benchmark_prompts.rs (issue #386).
  const forms = roleWordForms(ROLE_CONVERSATION_TOPIC_OPENER);
  for (const form of forms) {
    if (normalized.startsWith(form.before)) {
      return cleanConversationTopic(normalized.slice(form.before.length));
    }
  }
  const lower = String(prompt || "").toLowerCase();
  for (const form of forms) {
    if (form.action !== "scan") continue;
    const index = lower.indexOf(form.before);
    if (index >= 0) {
      return cleanConversationTopic(lower.slice(index + form.before.length));
    }
  }
  return "";
}

function conversationTopicContent(topic, language) {
  if (language === "ru") {
    return `Можем. Тема: ${topic}. Я могу начать с краткого определения, контекста или конкретного вопроса; если веб-поиск доступен, публичные факты можно уточнить через внешний источник.`;
  }
  if (language === "hi") {
    return `हम बात कर सकते हैं. विषय: ${topic}. मैं छोटी परिभाषा, संदर्भ, या किसी конкрет प्रश्न से शुरू कर सकता हूँ; web search उपलब्ध हो तो public facts बाहरी स्रोत से जाँचे जा सकते हैं.`;
  }
  if (language === "zh") {
    return `可以聊。主题: ${topic}。我可以从简短定义、上下文或具体问题开始; 如果 web search 可用, 公开事实可以通过外部来源核对。`;
  }
  return `We can talk about ${topic}. I can start with a short definition, context, or a specific question; when web search is available, public facts can be checked against an external source.`;
}

// Issue #386: a known-facts inventory query is recognised by composing meaning
// roles, not by matching raw words per language. The universal algorithm is
// identical for every language: the prompt either names the knowledge `fact`
// noun together with an enumerating interrogative and a second-person
// attribution of knowing, or it matches one of the complete standalone
// phrasings that ask what the assistant knows even without the noun. The
// prompt is re-normalised first so the boundary-aware matcher sees punctuation
// collapsed to spaces. Mirror of is_known_fact_query in
// src/solver_handlers/self_awareness.rs.
function isKnownFactQuery(normalized) {
  if (isSelfFactQuery(normalized)) return false;
  const cleaned = normalizePrompt(normalized);
  const composed =
    lexiconMentionsRole(ROLE_KNOWLEDGE_INVENTORY_NOUN, cleaned) &&
    lexiconMentionsRole(ROLE_KNOWLEDGE_INVENTORY_INTERROGATIVE, cleaned) &&
    lexiconMentionsRole(ROLE_KNOWLEDGE_POSSESSION, cleaned);
  return (
    composed || lexiconMentionsRole(ROLE_KNOWLEDGE_INVENTORY_PHRASE, cleaned)
  );
}

function cleanRuleQuery(raw) {
  return String(raw || "")
    .trim()
    .replace(/^[\s`"':._,\-?!]+|[\s`"':._,\-?!]+$/g, "")
    .toLowerCase();
}

function detailQuery(prompt) {
  const lower = String(prompt || "").toLowerCase();
  const prefixes = [
    "show behavior rule",
    "read behavior rule",
    "describe behavior rule",
    "show rule",
    "read rule",
    "details for rule",
    "детали правила",
    "покажи правило",
    "прочитай правило",
  ];
  for (const prefix of prefixes) {
    if (lower.startsWith(prefix)) {
      return cleanRuleQuery(String(prompt || "").slice(prefix.length));
    }
  }
  if (lower.includes("rule_unknown")) return "unknown";
  return "";
}

function findBehaviorRule(query) {
  const cleaned = cleanRuleQuery(query);
  const withoutPrefix = cleaned.startsWith("rule_") ? cleaned.slice(5) : cleaned;
  return behaviorRuleRecords().find(
    (rule) =>
      rule.id === cleaned ||
      rule.id === `rule_${withoutPrefix}` ||
      rule.intent === cleaned ||
      rule.intent === withoutPrefix ||
      rule.label.toLowerCase().includes(withoutPrefix),
  );
}

function codeSpans(text) {
  return String(text || "")
    .split("`")
    .map((part, index) => (index % 2 === 1 ? part.trim() : ""))
    .filter(Boolean);
}

// Issue #144 / #386: recognize behavior-rule updates expressed as `When X then
// Y` (and translations) in addition to the explicit `When I say … answer …`
// grammar. No keyword is named here any more — every surface lives in the
// embedded meaning lexicon (data/seed/meanings-skill-compiler.lino) and is read
// by semantic role, mirroring explicit_teaching_form + looks_like_skill_description
// in src/skill_compiler.rs:
//   * a teaching trigger lead that co-occurs with a teaching response verb, or a
//     standalone behaviour-rule edit directive (the explicit teaching form); and
//   * a when-then frame whose circumfix surface brackets the trigger and answer —
//     the literal before the … (U+2026) is the head, the literal after it is the
//     link; both must appear, head before link, with at least one backtick on
//     each side so the runtime extractor can pull the trigger and answer
//     deterministically.
const ROLE_SKILL_TEACHING_TRIGGER_LEAD = "skill_teaching_trigger_lead";
const ROLE_SKILL_TEACHING_RESPONSE_VERB = "skill_teaching_response_verb";
const ROLE_BEHAVIOR_RULE_EDIT_DIRECTIVE = "behavior_rule_edit_directive";
const ROLE_SKILL_WHEN_THEN_PAIR = "skill_when_then_pair";

function looksLikeRuntimeRuleUpdate(text) {
  const raw = String(text || "");
  const lower = raw.toLowerCase();
  if (
    (lexiconMentionsRoleSubstring(ROLE_SKILL_TEACHING_TRIGGER_LEAD, lower) &&
      lexiconMentionsRoleSubstring(ROLE_SKILL_TEACHING_RESPONSE_VERB, lower)) ||
    lexiconMentionsRoleSubstring(ROLE_BEHAVIOR_RULE_EDIT_DIRECTIVE, lower)
  ) {
    return true;
  }
  for (const form of roleWordForms(ROLE_SKILL_WHEN_THEN_PAIR)) {
    if (form.slot !== "circumfix") continue;
    const head = form.before;
    const link = form.after;
    const headPos = lower.indexOf(head);
    if (headPos === -1) continue;
    const tail = lower.slice(headPos + head.length);
    const linkPos = tail.indexOf(link);
    if (linkPos === -1) continue;
    const absoluteLinkPos = headPos + head.length + linkPos;
    const beforeLink = raw.slice(headPos, absoluteLinkPos);
    const afterLink = raw.slice(absoluteLinkPos + link.length);
    if (beforeLink.includes("`") && afterLink.includes("`")) return true;
  }
  return false;
}

function runtimeRuleFromText(text) {
  if (!looksLikeRuntimeRuleUpdate(text)) return null;
  const spans = codeSpans(text);
  if (spans.length < 2) return null;
  const trigger = spans[0].trim();
  const answer = spans[1].trim();
  if (!trigger || !answer) return null;
  return {
    id: stableBehaviorRuleId("behavior_rule_runtime", `${trigger}\n${answer}`),
    trigger,
    answer,
  };
}

function runtimeRuleForPrompt(prompt, history) {
  const normalizedPrompt = normalizePrompt(prompt);
  const turns = Array.isArray(history) ? history : [];
  for (let index = turns.length - 1; index >= 0; index -= 1) {
    const turn = turns[index] || {};
    if (String(turn.role || "").toLowerCase() !== "user") continue;
    const rule = runtimeRuleFromText(turn.content);
    if (rule && normalizePrompt(rule.trigger) === normalizedPrompt) {
      return rule;
    }
  }
  return null;
}

function collectRuntimeRules(history) {
  const turns = Array.isArray(history) ? history : [];
  const seen = new Set();
  const rules = [];
  for (const turn of turns) {
    const role = String((turn || {}).role || "").toLowerCase();
    if (role !== "user") continue;
    const rule = runtimeRuleFromText((turn || {}).content);
    if (rule && !seen.has(rule.id)) {
      seen.add(rule.id);
      rules.push(rule);
    }
  }
  return rules;
}

function tryBehaviorRules(prompt, normalized, history, preferences) {
  const language = detectLanguage(prompt);
  const updateRule = runtimeRuleFromText(prompt);
  if (updateRule) {
    return {
      intent: "behavior_rule_update",
      content: renderRuntimeRuleUpdate(updateRule, language),
      confidence: 1.0,
      evidence: ["behavior_rule:update", updateRule.id],
    };
  }

  if (isBehaviorRulesList(normalized)) {
    return {
      intent: "behavior_rules_list",
      content: renderBehaviorRuleList(collectRuntimeRules(history), language),
      confidence: 1.0,
      evidence: ["behavior_rules:list", "all"],
    };
  }

  const query = detailQuery(prompt);
  if (query) {
    const rule = findBehaviorRule(query);
    if (rule) {
      return {
        intent: "behavior_rule_detail",
        content: renderBehaviorRuleDetail(rule, language),
        confidence: 1.0,
        evidence: ["behavior_rule:read", rule.id],
      };
    }
  }

  if (isSelfIntroductionQuery(normalized)) {
    const language = selfAwarenessLanguage(prompt, normalized);
    return {
      intent: "identity",
      content: selfIntroductionContent(language, preferences),
      confidence: 1.0,
      evidence: [
        "identity:self_introduction",
        `language:${language}`,
        `assistant_name:${assistantNameStatus(preferences)}`,
      ],
    };
  }

  if (isArchitectureQuestion(normalized)) {
    const language = architectureLanguage(prompt, normalized);
    return {
      intent: "meta_explanation",
      content: architectureExplanationContent(language),
      confidence: 1.0,
      evidence: [
        "response:meta_explanation",
        "meta_explanation:self_awareness",
        `language:${language}`,
      ],
    };
  }

  if (isSelfFactQuery(normalized)) {
    return {
      intent: "self_facts",
      content: renderSelfFacts(preferences),
      confidence: 1.0,
      evidence: ["self_facts:list", "formal-ai"],
    };
  }

  if (isKnownFactQuery(normalized)) {
    const language = selfAwarenessLanguage(prompt, normalized);
    return {
      intent: "known_facts",
      content: renderKnownFacts(language, preferences),
      confidence: 1.0,
      evidence: ["known_facts:list", "formal-ai", `language:${language}`],
    };
  }

  const topic = conversationTopic(prompt, normalized);
  if (topic) {
    const language = selfAwarenessLanguage(prompt, normalized);
    return {
      intent: "conversation_topic",
      content: conversationTopicContent(topic, language),
      confidence: 0.75,
      evidence: [`conversation_topic:${topic}`, `language:${language}`],
    };
  }

  const runtimeRule = runtimeRuleForPrompt(prompt, history);
  if (runtimeRule) {
    return {
      intent: "behavior_rule_custom",
      content: runtimeRule.answer,
      confidence: 1.0,
      evidence: ["behavior_rule:match", runtimeRule.id],
    };
  }

  return null;
}

function containsAny(normalized, values) {
  if (!normalized || !Array.isArray(values)) return false;
  return values.some((value) => value && normalized.includes(String(value).toLowerCase()));
}

// Issue #386 feature-capability roles — mirror the ROLE_FEATURE_* consts in
// src/seed/roles.rs. Their surface forms live in
// data/seed/meanings-feature-capability.lino (embedded in MEANINGS_LINO above).
// detectFeatureCapability walks the `feature_capability_alias` meanings in seed
// declaration order (= the historical FEATURE_CAPABILITIES priority) and takes
// the first whose multilingual aliases occur as a raw substring; the question
// gate and the two action gates reference the other roles. No surface word is
// named here — they all live in the data.
const ROLE_FEATURE_CAPABILITY_ALIAS = "feature_capability_alias";
const ROLE_FEATURE_CAPABILITY_QUESTION = "feature_capability_question";
const ROLE_FEATURE_ACTION_ARITHMETIC = "feature_action_arithmetic";
const ROLE_FEATURE_ACTION_PLANNING = "feature_action_planning";

const FEATURE_CAPABILITIES = [
  {
    slug: "web_search",
    state: "web_search",
    labels: { en: "web search", ru: "веб-поиск", hi: "web search", zh: "web search" },
    examples: {
      en: "Search the web for Nikola Tesla",
      ru: "Найди в интернете Никола Тесла",
      hi: "Search the web for Nikola Tesla",
      zh: "Search the web for Nikola Tesla",
    },
  },
  {
    slug: "diagnostics",
    state: "diagnostics",
    labels: { en: "diagnostics", ru: "диагностика", hi: "diagnostics", zh: "诊断" },
    examples: {
      en: "Turn on diagnostics",
      ru: "Включи диагностику",
      hi: "Turn on diagnostics",
      zh: "开启诊断",
    },
  },
  {
    slug: "agent_mode",
    state: "agent_mode",
    labels: { en: "agent mode", ru: "agent mode", hi: "agent mode", zh: "agent mode" },
    examples: {
      en: "Turn on agent mode",
      ru: "Включи agent mode",
      hi: "Turn on agent mode",
      zh: "开启 agent mode",
    },
  },
  {
    slug: "definition_fusion",
    state: "definition_fusion",
    labels: {
      en: "automatic definition fusion",
      ru: "автоматическое слияние определений",
      hi: "automatic definition fusion",
      zh: "自动 definition fusion",
    },
    examples: {
      en: "Turn on definition fusion",
      ru: "Включи слияние определений",
      hi: "Turn on definition fusion",
      zh: "开启 definition fusion",
    },
  },
  {
    slug: "configuration",
    state: "always",
    labels: {
      en: "message-driven configuration",
      ru: "настройка через сообщения",
      hi: "message-driven configuration",
      zh: "消息驱动设置",
    },
    examples: {
      en: "Switch to dark theme",
      ru: "Переключи тему на темную",
      hi: "Switch to dark theme",
      zh: "切换到深色主题",
    },
  },
  {
    slug: "memory_actions",
    state: "always",
    labels: {
      en: "memory import/export",
      ru: "импорт и экспорт памяти",
      hi: "memory import/export",
      zh: "记忆导入/导出",
    },
    examples: {
      en: "Export memory",
      ru: "Экспортируй память",
      hi: "Export memory",
      zh: "导出记忆",
    },
  },
  {
    slug: "greeting",
    state: "always",
    labels: { en: "greetings", ru: "приветствия", hi: "अभिवादन", zh: "问候" },
    examples: { en: "Hello", ru: "Привет", hi: "नमस्ते", zh: "你好" },
  },
  {
    slug: "write_program",
    state: "always",
    labels: {
      en: "program template generation",
      ru: "генерация программ",
      hi: "program template generation",
      zh: "程序生成",
    },
    examples: {
      en: "Write a Python program that counts to three",
      ru: "Напиши hello world на Rust",
      hi: "Write a Python program that counts to three",
      zh: "Write a Python program that counts to three",
    },
  },
  {
    slug: "concept_lookup",
    state: "always",
    labels: { en: "concept lookup", ru: "поиск понятий", hi: "concept lookup", zh: "概念查找" },
    examples: {
      en: "What is Wikipedia?",
      ru: "Что такое Википедия?",
      hi: "विकिपीडिया क्या है?",
      zh: "什么是维基百科?",
    },
  },
  {
    slug: "arithmetic",
    state: "always",
    labels: { en: "arithmetic", ru: "арифметика", hi: "अंकगणित", zh: "算术" },
    examples: {
      en: "What is 2 + 2?",
      ru: "Сколько будет 2 + 2?",
      hi: "2 + 2 क्या है?",
      zh: "2 + 2 等于多少?",
    },
  },
  {
    slug: "translation",
    state: "always",
    labels: { en: "translation", ru: "перевод", hi: "अनुवाद", zh: "翻译" },
    examples: {
      en: 'Translate "hello" to Russian',
      ru: 'Переведи "hello" на русский',
      hi: 'Translate "hello" to Hindi',
      zh: 'Translate "hello" to Chinese',
    },
  },
  {
    slug: "memory",
    state: "always",
    labels: {
      en: "conversation memory",
      ru: "память разговора",
      hi: "conversation memory",
      zh: "会话记忆",
    },
    examples: {
      en: "My name is Ada. What is my name?",
      ru: "Меня зовут Ада. Как меня зовут?",
      hi: "My name is Ada. What is my name?",
      zh: "My name is Ada. What is my name?",
    },
  },
  {
    slug: "demo_mode",
    state: "always",
    labels: { en: "demo mode", ru: "демо-режим", hi: "demo mode", zh: "演示模式" },
    examples: { en: "Turn off demo mode", ru: "Выключи демо", hi: "Turn off demo mode", zh: "关闭演示" },
  },
  {
    slug: "http_url",
    state: "always",
    labels: {
      en: "URL fetch/navigation",
      ru: "HTTP-запросы и переходы по URL",
      hi: "URL fetch/navigation",
      zh: "URL fetch/navigation",
    },
    examples: {
      en: "Navigate to example.com",
      ru: "Перейди на example.com",
      hi: "Navigate to example.com",
      zh: "Navigate to example.com",
    },
  },
  {
    slug: "javascript_execution",
    state: "always",
    labels: {
      en: "JavaScript execution",
      ru: "выполнение JavaScript",
      hi: "JavaScript execution",
      zh: "JavaScript execution",
    },
    examples: {
      en: "Run JavaScript: 1 + 1",
      ru: "Выполни JavaScript: 1 + 1",
      hi: "Run JavaScript: 1 + 1",
      zh: "Run JavaScript: 1 + 1",
    },
  },
  {
    slug: "planning",
    state: "always",
    labels: {
      en: "summaries, brainstorming, roleplay, and project planning",
      ru: "резюме, брейншторминг, роли и планирование проектов",
      hi: "summaries, brainstorming, roleplay, and project planning",
      zh: "总结、头脑风暴、角色扮演和项目计划",
    },
    examples: {
      en: "Brainstorm 5 project ideas",
      ru: "Предложи 5 идей проекта",
      hi: "Brainstorm 5 project ideas",
      zh: "Brainstorm 5 project ideas",
    },
  },
];

function localizedValue(record, language) {
  if (!record || typeof record !== "object") return "";
  return record[language] || record.en || "";
}

// Walk the `feature_capability_alias` meanings in seed declaration order — the
// historical FEATURE_CAPABILITIES priority — and return the first capability
// whose multilingual forms occur as a raw substring of `normalized`, checked in
// the prompt's own language plus English (English prompts check English only).
// The matched meaning's slug, minus its `feature_capability_` prefix, keys
// FEATURE_CAPABILITIES, so no surface alias is named here. Mirrors
// detect_feature_capability in src/solver_handlers/feature_capability.rs (#386).
function detectFeatureCapability(normalized, language) {
  const languages = language === "en" ? ["en"] : [language, "en"];
  const meaning = firstRoleMatchInLanguagesRaw(
    ROLE_FEATURE_CAPABILITY_ALIAS,
    normalized,
    languages,
  );
  if (!meaning) return null;
  const prefix = "feature_capability_";
  if (!meaning.slug.startsWith(prefix)) return null;
  const slug = meaning.slug.slice(prefix.length);
  return FEATURE_CAPABILITIES.find((feature) => feature.slug === slug) || null;
}

// A prompt is a capability question when one of the `feature_capability_question`
// interrogative cues occurs as a raw substring, checked in the prompt's own
// detected language only. English prompts additionally accept a grammatical
// "is/are ... enabled/available" frame computed in code. Mirrors
// is_feature_capability_question in
// src/solver_handlers/feature_capability.rs (#386).
function isFeatureCapabilityQuestion(normalized, language) {
  const mentions = (lang) =>
    mentionsRoleInLanguagesRaw(ROLE_FEATURE_CAPABILITY_QUESTION, normalized, [lang]);
  if (language === "ru") return mentions("ru");
  if (language === "zh") return mentions("zh");
  if (language === "hi") return mentions("hi");
  return mentions("en") || isEnglishAvailabilityQuestion(normalized);
}

// English-only grammatical "is/are ... enabled/available" availability frame —
// a grammatical pattern (not a vocabulary list), so it stays in code. Mirrors
// is_english_availability_question in
// src/solver_handlers/feature_capability.rs (#386).
function isEnglishAvailabilityQuestion(normalized) {
  return /\b(?:is|are)\s+(?:your\s+|the\s+|this\s+|formal-ai\s+)?[\w\s/-]{1,80}\s+(?:enabled|available)\b/.test(
    normalized,
  );
}

// True when a detected capability question is actually an action request that a
// dedicated handler should answer. The English action frames live in the
// `feature_action_arithmetic` / `feature_action_planning` meanings; they are
// read through wordsForRoleInLanguages restricted to English and reconstructed
// as space-padded forms (prefix for arithmetic, anywhere for planning), so no
// frame is named here. Mirrors is_feature_action_request in
// src/solver_handlers/feature_capability.rs (#386).
function isFeatureActionRequest(normalized, feature) {
  if (!feature) return false;
  if (feature.slug === "arithmetic") {
    return wordsForRoleInLanguages(ROLE_FEATURE_ACTION_ARITHMETIC, ["en"]).some(
      (frame) => normalized.startsWith(`${frame} `),
    );
  }
  if (feature.slug === "planning") {
    return wordsForRoleInLanguages(ROLE_FEATURE_ACTION_PLANNING, ["en"]).some(
      (frame) => normalized.includes(`${frame} `),
    );
  }
  return false;
}

function webSearchStatusContent(language, available, providers) {
  const providerList = providers || "none";
  const rrfK = webSearchRrfK();
  if (language === "ru") {
    return available
      ? `Да. В этой конфигурации веб-поиск включен: я могу использовать DuckDuckGo Instant Answer по умолчанию и доступные CORS-провайдеры (\`${providerList}\`) для явных запросов вроде \`Найди в интернете Никола Тесла\`. Результаты из top-10 по каждому провайдеру объединяются через reciprocal rank fusion (k = ${rrfK}). Если провайдеры отключены или заблокированы в браузерной сессии, я сообщу об этом вместо ответа "да".`
      : "Нет. В этой браузерной сессии веб-поиск сейчас недоступен: браузер offline или все CORS-readable поисковые провайдеры отключены после ошибок. Я могу отвечать по локальным правилам и кэшу, но не буду обращаться к поисковым системам.";
  }
  if (language === "zh") {
    return available
      ? `可以。当前配置启用了 web search:我会默认使用 DuckDuckGo Instant Answer,并可使用这些 CORS-readable provider(\`${providerList}\`)处理明确的搜索请求,例如 \`Search the web for Nikola Tesla\`。每个 provider 的 top-10 结果会用 reciprocal rank fusion 合并(k = ${rrfK})。如果浏览器会话中所有 provider 被禁用或阻止,我会说明不可用,而不是回答可以。`
      : "不可以。当前浏览器会话中 web search 不可用:浏览器 offline,或所有 CORS-readable 搜索 provider 都因错误被禁用。我仍可使用本地规则和缓存回答,但不会调用搜索引擎。";
  }
  if (language === "hi") {
    return available
      ? `हाँ। इस configuration में web search enabled है: मैं default रूप से DuckDuckGo Instant Answer और उपलब्ध CORS-readable providers (\`${providerList}\`) का उपयोग explicit prompts जैसे \`Search the web for Nikola Tesla\` के लिए कर सकता हूँ। हर provider के top-10 results reciprocal rank fusion (k = ${rrfK}) से merge होते हैं। अगर browser session में providers disabled या blocked हों, तो मैं "हाँ" कहने के बजाय स्थिति बताऊँगा।`
      : "नहीं। इस browser session में web search अभी available नहीं है: browser offline है या सभी CORS-readable search providers errors के बाद disabled हैं। मैं local rules और cache से जवाब दे सकता हूँ, लेकिन search engines को call नहीं करूँगा।";
  }
  return available
    ? `Yes. Web search is enabled in this configuration: I can use DuckDuckGo Instant Answer by default plus the configured CORS-readable providers (\`${providerList}\`) for explicit prompts such as \`Search the web for Nikola Tesla\`. The top-10 results from each provider are merged with reciprocal rank fusion (k = ${rrfK}). If the browser session disables or blocks every provider, I will say that instead of claiming search is available.`
    : "No. Web search is unavailable in this browser session: the browser is offline or every CORS-readable search provider has been disabled after errors. I can still answer from local rules and cache, but I will not call search engines.";
}

function featureAvailability(feature, preferences) {
  if (!feature) return { available: false, reason: "unknown" };
  if (feature.state === "web_search") {
    const providers = WEB_SEARCH_PROVIDERS.filter((provider) => !webSearchIsDisabled(provider.id));
    const online = typeof navigator === "undefined" || navigator.onLine !== false;
    return {
      available: online && providers.length > 0,
      reason: online && providers.length > 0 ? "none" : "offline_or_no_providers",
      providers,
    };
  }
  if (feature.state === "diagnostics") {
    const available = Boolean(preferences && preferences.diagnosticsMode);
    return { available, reason: available ? "none" : "diagnostics_off" };
  }
  if (feature.state === "agent_mode") {
    const available = Boolean(preferences && preferences.agentMode);
    return { available, reason: available ? "none" : "agent_mode_off" };
  }
  if (feature.state === "definition_fusion") {
    const available = definitionFusionByDefault(preferences || {});
    return { available, reason: available ? "none" : "definition_fusion_explicit" };
  }
  return { available: true, reason: "none" };
}

function unavailableReasonText(reason, language) {
  const reasons = {
    offline_or_no_providers: {
      en: "the browser is offline or no search providers are available",
      ru: "браузер offline или нет доступных поисковых провайдеров",
      hi: "browser offline है या कोई search provider available नहीं है",
      zh: "浏览器 offline,或没有可用搜索 provider",
    },
    diagnostics_off: {
      en: "diagnostics are off; enable them to show traces",
      ru: "диагностика выключена; включите ее, чтобы видеть трассировку",
      hi: "diagnostics off है; trace दिखाने के लिए इसे enable करें",
      zh: "诊断已关闭;开启后才会显示 trace",
    },
    agent_mode_off: {
      en: "agent mode is off; multi-step actions require explicit opt-in",
      ru: "agent mode выключен; для многошаговых действий нужен явный opt-in",
      hi: "agent mode off है; multi-step actions के लिए explicit opt-in चाहिए",
      zh: "agent mode 已关闭;多步骤操作需要显式启用",
    },
    definition_fusion_explicit: {
      en: "automatic definition fusion is set to explicit-only",
      ru: "автоматическое слияние определений работает только после включения режима auto",
      hi: "automatic definition fusion के लिए auto mode enable करना होगा",
      zh: "自动 definition fusion 需要切换到 auto 模式",
    },
  };
  return localizedValue(reasons[reason] || { en: "not available" }, language);
}

function featureCapabilityContent(feature, language, availability) {
  if (feature.slug === "web_search") {
    const providers = availability.providers || [];
    return webSearchStatusContent(
      language,
      availability.available,
      providers.map((provider) => provider.id).join(", "),
    );
  }
  const label = localizedValue(feature.labels, language);
  const example = localizedValue(feature.examples, language);
  if (availability.available) {
    if (language === "ru") {
      return `Да. Возможность «${label}» доступна в этой конфигурации. Пример сообщения: \`${example}\`.`;
    }
    if (language === "zh") {
      return `可以。当前配置中「${label}」可用。示例消息:\`${example}\`。`;
    }
    if (language === "hi") {
      return `हाँ। इस configuration में \`${label}\` available है। Example message: \`${example}\`.`;
    }
    return `Yes. ${label} is available in this configuration. Example message: \`${example}\`.`;
  }
  const reason = unavailableReasonText(availability.reason, language);
  if (language === "ru") {
    return `Нет. Возможность «${label}» сейчас недоступна в этой конфигурации: ${reason}. Пример сообщения после включения: \`${example}\`.`;
  }
  if (language === "zh") {
    return `不可以。当前配置中「${label}」不可用:${reason}。启用后的示例消息:\`${example}\`。`;
  }
  if (language === "hi") {
    return `नहीं। इस configuration में \`${label}\` अभी available नहीं है: ${reason}. Enable करने के बाद example message: \`${example}\`.`;
  }
  return `No. ${label} is not available in this configuration: ${reason}. Example message after enabling it: \`${example}\`.`;
}

function tryFeatureCapabilityStatus(prompt, normalized, language, preferences) {
  if (!isFeatureCapabilityQuestion(normalized, language)) return null;
  const feature = detectFeatureCapability(normalized, language);
  if (!feature) return null;
  if (isFeatureActionRequest(normalized, feature)) return null;
  const availability = featureAvailability(feature, preferences || {});
  const providers = WEB_SEARCH_PROVIDERS.filter((provider) => !webSearchIsDisabled(provider.id));
  return {
    intent: "capabilities",
    content: featureCapabilityContent(feature, language, availability),
    confidence: availability.available ? 0.95 : 0.6,
    evidence: [
      "handler:capabilities",
      `feature:question:${feature.slug}`,
      availability.available
        ? `feature:available:${feature.slug}`
        : `feature:unavailable:${feature.slug}:${availability.reason}`,
      ...(feature.slug === "web_search" ? providers.map((provider) => `web_search:provider:${provider.id}`) : []),
      `language:${language}`,
    ],
  };
}

// Issue #386: recognise "what else can you do" / "что ещё ты умеешь" /
// "और क्या कर सकते" / "你还能做什么" by the capability_query_more meaning role
// rather than a hardcoded per-language phrase list. Recognition is
// language-agnostic because the surface words are script-specific; the response
// body is still chosen by the caller from detectLanguage. The prompt is
// re-normalised so trailing punctuation collapses to the canonical spacing the
// seed stores. Mirror of is_more_capabilities_prompt in
// src/solver_handlers/user_intent.rs.
function isMoreCapabilitiesPrompt(normalized) {
  return lexiconMentionsRole(ROLE_CAPABILITY_QUERY_MORE, normalizePrompt(normalized));
}

// Issue #386: recognise "what can you do" / "что ты умеешь" / "что за дичь" /
// "आप क्या कर सकते" / "你能做什么" by the capability_query meaning role — plus
// its follow-up capability_query_more, so "what else can you do" still counts —
// rather than a hardcoded per-language phrase list. Mirror of
// is_capability_query in src/solver_handlers/user_intent.rs.
function isCapabilityQuery(normalized) {
  const cleaned = normalizePrompt(normalized);
  return (
    lexiconMentionsRole(ROLE_CAPABILITY_QUERY, cleaned) ||
    lexiconMentionsRole(ROLE_CAPABILITY_QUERY_MORE, cleaned)
  );
}

function historyMentionsWebSearch(history) {
  if (!Array.isArray(history)) return false;
  return history.some((turn) => {
    const content = String(turn && turn.content ? turn.content : "").toLowerCase();
    return lexiconMentionsRoleSubstring(ROLE_WEB_SEARCH_HISTORY_SIGNAL, content);
  });
}

function additionalCapabilitiesContent(language) {
  if (language === "ru") {
    return "Кроме уже названных возможностей, могу ещё:\n\n- **Арифметика**: вычислять выражения вроде «Сколько будет 2 + 2?»\n- **Перевод**: переводить короткие фразы между поддерживаемыми языками.\n- **Поиск понятий**: объяснять термины, например «Что такое Википедия?»\n- **Hello World**: генерировать минимальные программы на Rust, Python, JavaScript, Go, C и других языках.\n- **Память диалога**: использовать предыдущие сообщения текущей сессии.\n- **Правила поведения**: показывать встроенные правила через `List behavior rules` и `Show behavior rule unknown`.\n- **Настройки и действия**: включать диагностику/демо/agent mode, менять тему, язык, стиль чата, экспортировать и импортировать память.";
  }
  return "Beyond the capability already discussed, I can also:\n\n- **Arithmetic**: evaluate expressions like `2 + 2`.\n- **Translation**: translate short phrases between supported languages.\n- **Concept lookup**: explain terms such as `What is Wikipedia?`.\n- **Hello World**: generate small programs in Rust, Python, JavaScript, Go, C, and more.\n- **Conversation memory**: use earlier messages from the current session.\n- **Behavior rules**: show built-in rules with `List behavior rules` and `Show behavior rule unknown`.\n- **Settings and actions**: configure diagnostics, demo mode, agent mode, theme, language, chat style, and memory import/export.";
}

// True when the prompt asks how the assistant itself is built rather than
// requesting a task. Decomposes exactly like the Rust is_architecture_question:
// the prompt must address the assistant — carry an assistant_self_reference
// surface — and name an architecture_concept such as a language model, neural
// network, or the project's local rules. Both are matched as raw substrings
// across all four languages; no architecture word is hardcoded here.
function isArchitectureQuestion(normalized) {
  if (!lexiconMentionsRoleSubstring(ROLE_ASSISTANT_SELF_REFERENCE, normalized)) {
    return false;
  }
  return lexiconMentionsRoleSubstring(ROLE_ARCHITECTURE_CONCEPT, normalized);
}

function architectureLanguage(prompt, normalized) {
  return selfAwarenessLanguage(prompt, normalized);
}

function architectureExplanationContent(language) {
  const surface = BROWSER_SURFACE;
  if (language === "ru") {
    return `Я не LLM-рантайм и не выполняю нейросетевой инференс. Текущая среда: ${surface.label} (\`${surface.slug}\`). Рантайм: ${surface.runtime}. У проекта есть OpenAI-совместимые API-форматы, но ответы строит детерминированный solver: сначала он проверяет локальный seed Links Notation, правила и память (${surface.memory}); затем веб-поиск используется только с учетом среды: ${surface.webSearch}. Весь интернет не загружен в локальные правила целиком.`;
  }
  if (language === "hi") {
    return `मैं LLM runtime नहीं हूँ और neural inference नहीं चलाता. Current environment: ${surface.label} (\`${surface.slug}\`). Runtime: ${surface.runtime}. Project OpenAI-compatible API shapes देता है, लेकिन जवाब deterministic solver बनाता है: पहले local Links Notation seed, rules और memory (${surface.memory}) देखता है; फिर web search केवल environment अनुमति दे तो उपयोग करता है: ${surface.webSearch}. पूरा internet local rules में preload नहीं है.`;
  }
  if (language === "zh") {
    return `我不是 LLM runtime, 也不执行神经网络推理。当前环境: ${surface.label} (\`${surface.slug}\`)。Runtime: ${surface.runtime}。项目提供 OpenAI-compatible API 形状, 但回答由确定性的 solver 生成: 先检查本地 Links Notation seed、规则和记忆 (${surface.memory}); 然后只在当前环境允许时使用 web search: ${surface.webSearch}。整个互联网不会预加载到本地规则中。`;
  }
  return `I am not an LLM runtime and I do not perform neural inference. Current environment: ${surface.label} (\`${surface.slug}\`). Runtime: ${surface.runtime}. The project exposes OpenAI-compatible API shapes, but answers come from a deterministic solver: it checks the local Links Notation seed, rules, and memory (${surface.memory}) first; web search is used only when this environment allows it: ${surface.webSearch}. The whole internet is not preloaded into local rules.`;
}

function tryArchitectureExplanation(prompt, normalized) {
  if (!isArchitectureQuestion(normalized)) return null;
  const language = architectureLanguage(prompt, normalized);
  return {
    intent: "meta_explanation",
    content: architectureExplanationContent(language),
    confidence: 1.0,
    evidence: ["response:meta_explanation", "meta_explanation:architecture", `language:${language}`],
  };
}

function tryCapabilities(prompt, normalized, preferences, history) {
  const language = detectLanguage(prompt);
  const featureStatus = tryFeatureCapabilityStatus(prompt, normalized, language, preferences);
  if (featureStatus) return featureStatus;
  const moreCapabilities = isMoreCapabilitiesPrompt(normalized);
  if (!isCapabilityQuery(normalized)) return null;
  if (moreCapabilities) {
    const priorSearch = historyMentionsWebSearch(history);
    return {
      intent: "capabilities",
      content: additionalCapabilitiesContent(language),
      confidence: 1.0,
      evidence: [
        "handler:capabilities",
        "capabilities:follow_up",
        ...(priorSearch ? ["capabilities:history:prior_web_search"] : []),
        `language:${language}`,
      ],
    };
  }
  const content =
    language === "ru"
      ? "Я formal-ai — детерминированный символьный ИИ. Вот что я умею:\n\n- **Приветствия**: отвечаю на «Привет», «Здравствуйте» и т.п.\n- **Hello World**: генерирую программы на Rust, Python, JavaScript, Go, C и других языках.\n- **Веб-поиск**: ищу в интернете через DuckDuckGo, Wikipedia и Wikidata, когда поиск доступен.\n- **Поиск понятий**: объясняю термины — попробуйте «Что такое Википедия?»\n- **Арифметика**: вычисляю выражения — например, «Сколько будет 2 + 2?»\n- **Перевод**: перевожу фразы между языками.\n- **Память**: помню контекст разговора в рамках сессии.\n- **Настройки и действия**: через сообщения можно включать диагностику/демо/agent mode, менять тему, язык, стиль чата и экспортировать или импортировать память.\n\nЯ работаю на основе локальных символьных правил, без нейросетевого инференса."
      : language === "zh"
        ? "我是 formal-ai —— 一个确定性的符号化 AI。以下是我的功能:\n\n- **问候**:回应「你好」等问候语。\n- **Hello World**:生成 Rust、Python、JavaScript、Go、C 等语言的示例程序。\n- **Web search**:在可用时通过 DuckDuckGo、Wikipedia 和 Wikidata 搜索互联网。\n- **概念查找**:解释术语,例如「什么是维基百科?」\n- **算术**:计算表达式,例如「2 + 2 等于多少?」\n- **翻译**:在语言之间翻译短语。\n- **记忆**:在会话中记住上下文。\n- **设置和操作**:可通过消息开启诊断、演示、agent mode,切换主题、语言、聊天样式,并导出或导入记忆。\n\n我基于本地符号规则运行,不进行神经网络推理。"
        : language === "hi"
          ? "मैं formal-ai हूँ — एक नियतात्मक प्रतीकात्मक AI। मैं यह कर सकता हूँ:\n\n- **अभिवादन**: «नमस्ते» आदि का जवाब देना।\n- **Hello World**: Rust, Python, JavaScript, Go, C आदि में प्रोग्राम बनाना।\n- **Web search**: उपलब्ध होने पर DuckDuckGo, Wikipedia, और Wikidata से इंटरनेट में खोजना।\n- **अवधारणा खोज**: शब्दों को समझाना — जैसे «विकिपीडिया क्या है?»\n- **अंकगणित**: गणनाएँ — जैसे «2 + 2 क्या है?»\n- **अनुवाद**: भाषाओं के बीच अनुवाद।\n- **स्मृति**: सत्र में संदर्भ याद रखना।\n- **Settings और actions**: messages से diagnostics/demo/agent mode बदलना, theme/language/chat style बदलना, और memory export/import करना।\n\nमैं स्थानीय प्रतीकात्मक नियमों पर चलता हूँ, कोई न्यूरल इन्फेरेन्स नहीं।"
          : "I am formal-ai, a deterministic symbolic AI. Here is what I can do:\n\n- **Greetings**: respond to «Hi», «Hello», and similar.\n- **Hello World**: generate programs in Rust, Python, JavaScript, Go, C, and more.\n- **Web search**: search the internet through DuckDuckGo, Wikipedia, and Wikidata when available.\n- **Concept lookup**: explain terms — try «What is Wikipedia?»\n- **Arithmetic**: evaluate expressions — try «What is 2 + 2?»\n- **Translation**: translate phrases between languages.\n- **Memory**: recall context within the current session.\n- **Settings and actions**: configure diagnostics, demo mode, agent mode, theme, language, chat style, and memory import/export from messages.\n\nI run on local symbolic rules, without any neural network inference.";
  return {
    intent: "capabilities",
    content,
    confidence: 1.0,
    evidence: ["handler:capabilities", `language:${language}`],
  };
}

// Issue #386: the source/target language of a translation prompt is read from
// the lexicon, not a hardcoded per-language phrase ladder. Each translation
// source/target marker meaning enumerates its surfaces across all four
// languages and is defined_by the language_* meaning it names; detection walks
// those meanings in declaration order (en, ru, hi, zh) and resolves the code
// through defined_by. Mirrors detect_source_language / detect_target_language
// in src/translation/language_markers.rs.
function detectTranslationSourceLanguage(normalized) {
  return detectTranslationMarkerLanguage(
    ROLE_TRANSLATION_SOURCE_MARKER,
    normalized,
  );
}

function detectTranslationTargetLanguage(normalized) {
  return detectTranslationMarkerLanguage(
    ROLE_TRANSLATION_TARGET_MARKER,
    normalized,
  );
}

// Offline meaning registry for the browser worker.
//
// The Rust pipeline (`src/translation/pipeline.rs`) resolves any pair
// of surfaces through Wiktionary + Wikidata using cached HTTP
// responses. The worker mirrors that with a live `liveWiktionaryTranslate`
// fallback below (MediaWiki action API is CORS-friendly via
// `origin=*`), but keeps this small in-memory registry of greetings and
// stock phrases so the demo stays snappy when the network is slow.
// `primary` is the canonical form deformalization renders; `aliases` is a
// list of normalized alternative surfaces used during formalization.
const TRANSLATION_MEANING_REGISTRY = [
  {
    token: "greeting",
    primary: { en: "Hello", ru: "Привет", hi: "नमस्ते", zh: "你好" },
    aliases: {
      en: ["hello", "hi", "hey"],
      ru: ["привет", "здравствуйте", "здравствуй"],
      hi: ["नमस्ते", "नमस्कार"],
      zh: ["你好", "您好"],
    },
  },
  {
    token: "greeting_how_are_you",
    primary: {
      en: "How are you?",
      ru: "Как у тебя дела?",
      hi: "आप कैसे हैं?",
      zh: "你好吗?",
    },
    aliases: {
      en: ["howareyou", "hellohowareyou", "hihowareyou"],
      ru: [
        "какдела",
        "какутебядела",
        "какувасдела",
        "какваши дела",
        "какватидела",
        "какваши",
        "приветкакдела",
        "здравствуйтекаквашидела",
      ],
      hi: ["आपकैसेहैं", "तुमकैसेहो"],
      zh: ["你好吗", "你怎么样"],
    },
  },
  {
    token: "thank_you",
    primary: { en: "Thank you", ru: "Спасибо", hi: "धन्यवाद", zh: "谢谢" },
    aliases: {
      en: ["thanks", "thankyou", "thankyouverymuch"],
      ru: ["спасибо", "благодарю", "большоеспасибо"],
      hi: ["धन्यवाद", "शुक्रिया"],
      zh: ["谢谢", "多谢", "感谢"],
    },
  },
  {
    token: "you_are_welcome",
    primary: {
      en: "You are welcome",
      ru: "Пожалуйста",
      hi: "आपका स्वागत है",
      zh: "不客气",
    },
    aliases: {
      en: ["youarewelcome", "yourewelcome", "nottoworry"],
      ru: ["пожалуйста", "незачто"],
      hi: ["आपकास्वागतहै", "कोईबातनहीं"],
      zh: ["不客气", "不用谢"],
    },
  },
  {
    token: "goodbye",
    primary: { en: "Goodbye", ru: "До свидания", hi: "अलविदा", zh: "再见" },
    aliases: {
      en: ["goodbye", "bye", "seeyou", "byebye"],
      ru: ["досвидания", "пока", "прощай"],
      hi: ["अलविदा", "फिरमिलेंगे"],
      zh: ["再见", "拜拜"],
    },
  },
  {
    token: "good_morning",
    primary: { en: "Good morning", ru: "Доброе утро", hi: "सुप्रभात", zh: "早上好" },
    aliases: {
      en: ["goodmorning"],
      ru: ["доброеутро"],
      hi: ["सुप्रभात", "शुभप्रभात"],
      zh: ["早上好", "早安"],
    },
  },
  {
    token: "good_evening",
    primary: { en: "Good evening", ru: "Добрый вечер", hi: "शुभ संध्या", zh: "晚上好" },
    aliases: {
      en: ["goodevening"],
      ru: ["добрыйвечер"],
      hi: ["शुभसंध्या"],
      zh: ["晚上好", "晚安"],
    },
  },
  {
    token: "what_is_your_name",
    primary: {
      en: "What is your name?",
      ru: "Как тебя зовут?",
      hi: "तुम्हारा नाम क्या है?",
      zh: "你叫什么名字?",
    },
    aliases: {
      en: ["whatisyourname", "whatsyourname"],
      ru: ["кактебязовут", "каквасзовут"],
      hi: ["तुम्हारानामक्याहै", "आपकानामक्याहै"],
      zh: ["你叫什么名字", "您叫什么名字"],
    },
  },
  {
    token: "who_are_you",
    primary: {
      en: "Who are you?",
      ru: "Кто ты такой?",
      hi: "तुम कौन हो?",
      zh: "你是谁?",
    },
    aliases: {
      en: ["whoareyou"],
      ru: ["ктоты", "ктотытакой", "ктотытакая", "ктовы", "ктовытакой", "ктовытакая"],
      hi: ["तुमकौनहो", "आपकौनहैं"],
      zh: ["你是谁", "您是谁"],
    },
  },
  {
    token: "what_is_this",
    primary: {
      en: "What is this?",
      ru: "Что это такое?",
      hi: "यह क्या है?",
      zh: "这是什么?",
    },
    aliases: {
      en: ["whatisthis", "whatisit"],
      ru: ["чтоэто", "чтоэтотакое"],
      hi: ["यहक्याहै", "येक्याहै"],
      zh: ["这是什么", "這是什麼"],
    },
  },
  {
    token: "i_am_fine",
    primary: { en: "I am fine", ru: "У меня всё хорошо", hi: "मैं ठीक हूँ", zh: "我很好" },
    aliases: {
      en: ["iamfine", "imfine", "imdoingfine", "imdoingwell"],
      ru: ["уменявсёхорошо", "уменявсехорошо", "всёхорошо"],
      hi: ["मैंठीकहूँ", "मैंठीकहूं"],
      zh: ["我很好", "我挺好的"],
    },
  },
  {
    token: "yes",
    primary: { en: "Yes", ru: "Да", hi: "हाँ", zh: "是" },
    aliases: {
      en: ["yes", "yeah", "yep", "aye"],
      ru: ["да", "ага", "конечно"],
      hi: ["हाँ", "हां", "जी"],
      zh: ["是", "是的", "对"],
    },
  },
  {
    token: "no",
    primary: { en: "No", ru: "Нет", hi: "नहीं", zh: "不" },
    aliases: {
      en: ["no", "nope", "nah"],
      ru: ["нет", "неа"],
      hi: ["नहीं", "ना"],
      zh: ["不", "不是"],
    },
  },
  // Issue #216 / #217: the apple noun must be translatable in both
  // directions from the browser demo, including unquoted prompts.
  {
    token: "apple",
    primary: { en: "apple", ru: "яблоко", hi: "सेब", zh: "苹果" },
    aliases: {
      en: ["apple", "apples"],
      ru: [
        "яблоко",
        "яблока",
        "яблоку",
        "яблоком",
        "яблоке",
        "яблоки",
        "яблок",
        "яблокам",
        "яблоками",
        "яблоках",
      ],
      hi: ["सेब"],
      zh: ["苹果"],
    },
  },
];

const TRANSLATION_TERMINAL_PUNCTUATION = ["?", "!", ".", "。", "?", "!", "."];

function normalizeTranslationAlias(surface) {
  return Array.from(String(surface || "").toLowerCase())
    .filter((character) => /[\p{L}\p{N}]/u.test(character))
    .join("");
}

function formalizeSurface(surface, source) {
  const normalized = normalizeTranslationAlias(surface);
  if (!normalized) return null;
  for (const entry of TRANSLATION_MEANING_REGISTRY) {
    const aliases = (entry.aliases && entry.aliases[source]) || [];
    if (aliases.some((alias) => normalizeTranslationAlias(alias) === normalized)) {
      return entry.token;
    }
    const primary = entry.primary && entry.primary[source];
    if (primary && normalizeTranslationAlias(primary) === normalized) {
      return entry.token;
    }
  }
  return null;
}

function deformalizeMeaning(token, target) {
  for (const entry of TRANSLATION_MEANING_REGISTRY) {
    if (entry.token !== token) continue;
    const primary = entry.primary && entry.primary[target];
    return primary || null;
  }
  return null;
}

function canonicalTokenForNormalized(normalized) {
  if (!normalized) return null;
  for (const entry of TRANSLATION_MEANING_REGISTRY) {
    const aliasesByLang = entry.aliases || {};
    for (const lang of Object.keys(aliasesByLang)) {
      const aliases = aliasesByLang[lang] || [];
      if (aliases.some((alias) => normalizeTranslationAlias(alias) === normalized)) {
        return entry.token;
      }
    }
    const primaryByLang = entry.primary || {};
    for (const lang of Object.keys(primaryByLang)) {
      if (normalizeTranslationAlias(primaryByLang[lang]) === normalized) {
        return entry.token;
      }
    }
  }
  return null;
}

function canonicalMeaningToken(raw) {
  return canonicalTokenForNormalized(raw) || raw;
}

function normalizeMeaningText(surface) {
  const raw = normalizeTranslationAlias(surface);
  return canonicalMeaningToken(raw);
}

function matchSourceFormatting(target, source) {
  const targetTrimmed = String(target || "").trim();
  if (!targetTrimmed) return "";
  const sourceTrimmed = String(source || "").trim();

  let sourceTerminal = null;
  if (sourceTrimmed.length > 0) {
    const lastChar = Array.from(sourceTrimmed).pop();
    if (TRANSLATION_TERMINAL_PUNCTUATION.includes(lastChar)) sourceTerminal = lastChar;
  }
  let targetNoTerminal = targetTrimmed;
  while (
    targetNoTerminal.length > 0 &&
    TRANSLATION_TERMINAL_PUNCTUATION.includes(Array.from(targetNoTerminal).pop())
  ) {
    const lastChar = Array.from(targetNoTerminal).pop();
    targetNoTerminal = targetNoTerminal.slice(0, targetNoTerminal.length - lastChar.length);
  }
  const withTerminal = sourceTerminal ? targetNoTerminal + sourceTerminal : targetNoTerminal;

  const sourceFirstLetter = Array.from(sourceTrimmed).find((character) =>
    /\p{L}/u.test(character),
  );
  if (!sourceFirstLetter) return withTerminal;
  const targetChars = Array.from(withTerminal);
  const targetFirstIdx = targetChars.findIndex((character) => /\p{L}/u.test(character));
  if (targetFirstIdx === -1) return withTerminal;
  const targetFirstLetter = targetChars[targetFirstIdx];
  const sourceLower = sourceFirstLetter.toLowerCase() === sourceFirstLetter
    && sourceFirstLetter.toUpperCase() !== sourceFirstLetter;
  const sourceUpper = sourceFirstLetter.toUpperCase() === sourceFirstLetter
    && sourceFirstLetter.toLowerCase() !== sourceFirstLetter;
  const targetLower = targetFirstLetter.toLowerCase() === targetFirstLetter
    && targetFirstLetter.toUpperCase() !== targetFirstLetter;
  const targetUpper = targetFirstLetter.toUpperCase() === targetFirstLetter
    && targetFirstLetter.toLowerCase() !== targetFirstLetter;
  if (sourceLower && targetUpper) {
    targetChars[targetFirstIdx] = targetFirstLetter.toLowerCase();
    return targetChars.join("");
  }
  if (sourceUpper && targetLower) {
    targetChars[targetFirstIdx] = targetFirstLetter.toUpperCase();
    return targetChars.join("");
  }
  return withTerminal;
}

function normalizeComposableSurface(surface) {
  return String(surface || "")
    .trim()
    .replace(/[?!.。?!.]+$/u, "")
    .toLowerCase()
    .split(/\s+/u)
    .filter(Boolean)
    .join(" ");
}

// Issue #386 compositional-translation roles — mirror ROLE_COMPOSITIONAL_LEMMA,
// ROLE_COMPOSITIONAL_PHRASE and ROLE_COMPOSITIONAL_GENITIVE_HEAD in
// src/seed/roles.rs. The per-word lemma fallbacks, fixed phrases, genitive-
// governing heads and the single genitive-tagged complement that used to be
// hardcoded here all live in the embedded MEANINGS_LINO
// (data/seed/meanings-translation.lino); the functions below name only the
// semantic roles and the ru→en language pair, never the surface words. The
// query helpers (roleSurfaceTranslation, roleListsSurface,
// roleActionSurfaceTranslation, wordIn) are defined alongside meaningLexicon.
const ROLE_COMPOSITIONAL_LEMMA = "compositional_lemma";
const ROLE_COMPOSITIONAL_PHRASE = "compositional_phrase";
const ROLE_COMPOSITIONAL_GENITIVE_HEAD = "compositional_genitive_head";

function capitalizeAsciiFirst(surface) {
  const text = String(surface || "");
  if (!text) return "";
  return text[0].toUpperCase() + text.slice(1);
}

function translateRussianWordSequence(words) {
  const translated = [];
  for (let index = 0; index < words.length; index += 1) {
    const word = words[index];
    const next = words[index + 1];
    if (
      next &&
      roleListsSurface(ROLE_COMPOSITIONAL_GENITIVE_HEAD, "ru", word) &&
      roleActionSurfaceTranslation(ROLE_COMPOSITIONAL_LEMMA, "genitive", "ru", "en", next)
    ) {
      translated.push(
        roleSurfaceTranslation(ROLE_COMPOSITIONAL_LEMMA, "ru", "en", word),
        "of",
        roleActionSurfaceTranslation(ROLE_COMPOSITIONAL_LEMMA, "genitive", "ru", "en", next),
      );
      index += 1;
      continue;
    }
    const surface = roleSurfaceTranslation(ROLE_COMPOSITIONAL_LEMMA, "ru", "en", word);
    if (!surface) return null;
    translated.push(surface);
  }
  return capitalizeAsciiFirst(translated.join(" "));
}

function translateCompositionalSurface(surface, source, target) {
  if (source !== "ru" || target !== "en") return null;
  const normalized = normalizeComposableSurface(surface);
  const phrase = roleSurfaceTranslation(ROLE_COMPOSITIONAL_PHRASE, "ru", "en", normalized);
  if (phrase) return phrase;

  const words = normalized.split(/\s+/u).filter(Boolean);
  if (words.length < 2 || words.length > 8) return null;
  return translateRussianWordSequence(words);
}

function detectLanguageSlug(text) {
  let latin = 0;
  let cyrillic = 0;
  let devanagari = 0;
  let cjk = 0;
  let other = 0;
  for (const character of String(text || "")) {
    const code = character.codePointAt(0);
    if (/[a-z]/i.test(character)) latin += 1;
    else if (code >= 0x0400 && code <= 0x04ff) cyrillic += 1;
    else if (code >= 0x0900 && code <= 0x097f) devanagari += 1;
    else if (code >= 0x4e00 && code <= 0x9fff) cjk += 1;
    else if (/\p{L}/u.test(character)) other += 1;
  }
  const total = latin + cyrillic + devanagari + cjk + other;
  if (total === 0) return "en";
  if (other > latin && other >= cyrillic && other >= devanagari && other >= cjk) {
    return "unknown";
  }
  if (cyrillic >= Math.max(latin, devanagari, cjk) && cyrillic > 0) return "ru";
  if (devanagari >= Math.max(latin, cyrillic, cjk) && devanagari > 0) return "hi";
  if (cjk >= Math.max(latin, cyrillic, devanagari) && cjk > 0) return "zh";
  return "en";
}

function inferTranslationSource(prompt) {
  const lower = String(prompt || "").toLowerCase();
  const surface = extractQuotedPhrase(prompt) || extractUnquotedTranslationSurface(prompt);
  if (surface) {
    const detected = detectLanguageSlug(surface);
    if (detected !== "unknown") return detected;
  }
  // Issue #386: the source language of an un-annotated request is the language
  // the user issued the *translation command* in. Ask the lexicon which
  // language's command verb the prompt carries — the stems live once in the
  // embedded translate meaning; this code knows only the concept and the
  // language-code bridge. English is the default when no command verb is present.
  return (
    firstRoleLanguage(ROLE_TRANSLATION_ACTION, lower, ["ru", "hi", "zh"]) || "en"
  );
}

// Live Wiktionary fallback (issue #221). When the offline meaning
// registry above does not cover `surface`, fetch the Wiktionary page
// for `source` and pull the first `{{tt+|<target>|...}}` (or `{{t+}}` /
// `{{t}}`) entry. Mirrors the Rust pipeline's Stage 1a in
// `src/translation/pipeline.rs`: if the main page delegates noun
// translations via `{{see translation subpage|...}}`, fetch the
// subpage and search it first. Keeps the worker mobile-friendly: no
// offline dictionary bundled, just a single CORS-safe HTTP call.
async function fetchWiktionaryWikitext(pageTitle, language) {
  if (typeof fetch !== "function" || !pageTitle) return null;
  const host = WIKTIONARY_SEARCH_HOSTS[language] || WIKTIONARY_SEARCH_HOSTS.en;
  const url = `${host}?action=parse&page=${encodeURIComponent(
    pageTitle,
  )}&prop=wikitext&format=json&origin=*`;
  try {
    const response = await fetch(url, {
      headers: {
        accept: "application/json",
        "api-user-agent":
          "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
      },
    });
    if (!response || !response.ok) return null;
    const data = await response.json();
    return (data && data.parse && data.parse.wikitext && data.parse.wikitext["*"]) || null;
  } catch (_error) {
    return null;
  }
}

function stripCombiningMarks(value) {
  // Russian Wiktionary entries are stored with combining stress marks
  // (U+0301) so readers can see where the accent falls. The surface
  // form must drop them so the result matches the lemma (помидо́р →
  // помидор) and downstream substring assertions still hit.
  return typeof value === "string" && value.normalize
    ? value.normalize("NFD").replace(/[̀-ͯ]/g, "").normalize("NFC")
    : value;
}

function extractWiktionaryTranslation(wikitext, targetLang) {
  if (!wikitext || !targetLang) return null;
  // English-edition templates: {{t|<lang>|...}}, {{t+|<lang>|...}},
  // {{tt|<lang>|...}}, {{tt+|<lang>|...}}.
  const enPattern = new RegExp(
    `\\{\\{tt?\\+?\\|${targetLang}\\|([^|}\\n]+)`,
    "i",
  );
  const enMatch = enPattern.exec(wikitext);
  if (enMatch) {
    const surface = stripCombiningMarks(String(enMatch[1] || "").trim());
    if (surface) return surface;
  }
  // Russian-edition translation blocks: `{{перев-блок|...|<lang>=[[surface]]\n|...}}`.
  // The language code may appear at the very start (no leading newline)
  // or after `\n|`; the surface can be inside `[[...]]`, optionally
  // followed by transliteration in parentheses we drop.
  const ruPattern = new RegExp(
    `[|\\n]${targetLang}\\s*=\\s*(?:\\[\\[([^\\]|]+)(?:\\|[^\\]]+)?\\]\\]|([^\\n|}]+))`,
    "i",
  );
  const ruMatch = ruPattern.exec(wikitext);
  if (ruMatch) {
    const raw = (ruMatch[1] || ruMatch[2] || "").trim();
    const surface = stripCombiningMarks(raw.replace(/\s*\([^)]*\)\s*$/, "").trim());
    if (surface) return surface;
  }
  return null;
}

async function resolveWiktionaryLemma(surface, language) {
  // Inflected forms (e.g. Russian plural `помидоры`) are not always stored
  // as separate pages on the source-language Wiktionary. OpenSearch returns
  // the closest matching titles; the first hit is the dictionary lemma
  // (`помидор`) we want to look up next.
  if (typeof fetch !== "function" || !surface) return null;
  const host = WIKTIONARY_SEARCH_HOSTS[language] || WIKTIONARY_SEARCH_HOSTS.en;
  const url = `${host}?action=opensearch&search=${encodeURIComponent(
    surface,
  )}&limit=1&format=json&origin=*`;
  try {
    const response = await fetch(url, {
      headers: {
        accept: "application/json",
        "api-user-agent":
          "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
      },
    });
    if (!response || !response.ok) return null;
    const data = await response.json();
    const titles = Array.isArray(data) && Array.isArray(data[1]) ? data[1] : [];
    const lemma = titles[0];
    if (typeof lemma !== "string" || !lemma || lemma === surface) return null;
    return lemma;
  } catch (_error) {
    return null;
  }
}

async function liveWiktionaryTranslate(surface, source, target) {
  // Run the direct page fetch and the OpenSearch lemma resolution in
  // parallel. For inflected forms (e.g. `помидоры`) the direct fetch
  // 404s, and chaining the lemma lookup sequentially after it added a
  // third sequential round-trip that pushed CI past the 5s expect cap.
  const [direct, lemma] = await Promise.all([
    fetchWiktionaryWikitext(surface, source),
    resolveWiktionaryLemma(surface, source),
  ]);
  let main = direct;
  if (!main && lemma) {
    main = await fetchWiktionaryWikitext(lemma, source);
  }
  if (!main) return null;
  let wikitext = main;
  if (/\{\{see translation subpage\|/i.test(main)) {
    const subpage = await fetchWiktionaryWikitext(`${surface}/translations`, source);
    if (subpage) wikitext = `${subpage}\n${main}`;
  }
  return extractWiktionaryTranslation(wikitext, target);
}

async function translateSurface(surface, source, target) {
  if (source === target) {
    return { surface: String(surface || ""), gap: false };
  }
  const token = formalizeSurface(surface, source);
  if (token) {
    const primary = deformalizeMeaning(token, target);
    if (primary) return { surface: primary, gap: false };
  }
  if (surface) {
    const live = await liveWiktionaryTranslate(surface, source, target);
    if (live) return { surface: live, gap: false };
  }
  const compositional = translateCompositionalSurface(surface, source, target);
  if (compositional) return { surface: compositional, gap: false };
  return { surface: null, gap: true };
}

function renderTranslationGap(surface, source, target) {
  const trimmed = String(surface || "").trim();
  if (!trimmed) {
    return `I could not identify a source phrase to translate from ${source} to ${target}.`;
  }
  return `I could not translate "${trimmed}" from ${source} to ${target} with the available formalization data. I recorded this as a translation gap for follow-up.`;
}

async function tryTranslation(prompt, normalized) {
  const targetHint = detectTranslationTargetLanguage(normalized);
  // Issue #386: recognise a translation command by *meaning*, not by hardcoded
  // verbs. The command stems live once in the embedded translate meaning; this
  // code knows the concept and the head-initial/head-final typology. Clause-
  // initial English/Russian commands are matched as a prefix; head-final
  // Hindi/Chinese place the verb later, so they are matched anywhere but gated
  // by a target marker to avoid firing on an incidental verb noun.
  const headInitialCommand = wordsForRoleInLanguages(ROLE_TRANSLATION_ACTION, [
    "en",
    "ru",
  ]).some((stem) => normalized.startsWith(stem));
  const headFinalCommand =
    Boolean(targetHint) &&
    wordsForRoleInLanguages(ROLE_TRANSLATION_ACTION, ["hi", "zh"]).some((stem) =>
      normalized.includes(stem),
    );
  const isTranslationRequest = headInitialCommand || headFinalCommand;
  if (!isTranslationRequest) return null;

  // Issue #216: fall back to an unquoted surface (`translate apple to
  // russian`) when no quoted fragment is present so the offline registry
  // can still resolve a meaning token.
  const surface =
    extractQuotedPhrase(prompt) || extractUnquotedTranslationSurface(prompt) || "";
  const surfaceMeaning = surface || prompt;
  const source = detectTranslationSourceLanguage(normalized) || inferTranslationSource(prompt);
  const target = targetHint || "en";
  const meaningId = stableBehaviorRuleId("meaning", normalizeMeaningText(surfaceMeaning));
  const translation = await translateSurface(surface, source, target);
  let content;
  if (translation.gap) {
    content = renderTranslationGap(surface, source, target);
  } else {
    const translatedSurface = matchSourceFormatting(translation.surface || "", surface);
    content = surface ? `"${translatedSurface}"` : translatedSurface;
  }
  const evidence = [
    "handler:translation",
    `language_from:${source}`,
    `language_to:${target}`,
    `meaning:${meaningId}`,
  ];
  if (translation.gap && surface) evidence.push(`translation_gap:${surface}`);
  return {
    intent: `translate_${source}_to_${target}`,
    content,
    confidence: 1.0,
    evidence,
  };
}

// The number of brainstorm items returned when the prompt names no count.
const DEFAULT_BRAINSTORM_COUNT = 5;

// Read the integer value of a cardinal-number meaning from its own data. Each
// cardinal carries a numeral word form (e.g. "10") — the script-independent
// surface that spells the value — so the count is derived from the seed rather
// than restated as a literal. Mirrors cardinal_value in
// src/solver_handlers/benchmark_prompts.rs (issue #386).
function cardinalValue(meaning) {
  if (!meaning || !Array.isArray(meaning.words)) return null;
  const numeral = meaning.words.find((word) => /^[0-9]+$/.test(word));
  if (numeral === undefined) return null;
  const value = Number.parseInt(numeral, 10);
  return Number.isNaN(value) ? null : value;
}

// Parse the number of items the user asked for, defaulting to
// DEFAULT_BRAINSTORM_COUNT when no explicit count is present. The only
// non-default count the brainstorm prompts exercise is ten, so the recogniser
// asks the seed whether the `ten` cardinal is evidenced in the prompt (in any
// supported language) and reads the value from that cardinal's own numeral
// surface. Mirrors requested_brainstorm_count in
// src/solver_handlers/benchmark_prompts.rs (issue #386).
function requestedBrainstormCount(normalized) {
  const ten = findMeaning("ten");
  if (ten && meaningEvidencedIn(ten, normalized)) {
    const value = cardinalValue(ten);
    if (value !== null) return value;
  }
  return DEFAULT_BRAINSTORM_COUNT;
}

function numbered(items, count) {
  return items
    .slice(0, count)
    .map((item, index) => `${index + 1}. ${item}`)
    .join("\n");
}

function tryBrainstormingRequest(prompt, normalized) {
  const seeds = BRAINSTORM_SEEDS || {};
  if (!containsAny(normalized, seeds.triggers)) return null;
  const categories = Array.isArray(seeds.categories) ? seeds.categories : [];
  const category =
    categories.find((entry) => containsAny(normalized, entry.detectionKeywords)) ||
    categories.find((entry) => !entry.detectionKeywords || entry.detectionKeywords.length === 0);
  if (!category || !Array.isArray(category.items) || category.items.length === 0) {
    return null;
  }
  const count = requestedBrainstormCount(normalized);
  return {
    intent: category.intent || "brainstorm_project_ideas",
    content: numbered(category.items, count),
    confidence: 0.8,
    evidence: [`brainstorm:category:${category.slug || "project_ideas"}`],
  };
}

function localizedFactFor(record, language) {
  const localized = Array.isArray(record.localized) ? record.localized : [];
  return (
    localized.find((entry) => entry && entry.language === language) ||
    localized.find((entry) => entry && entry.language === "en") ||
    null
  );
}

function tryFactLookup(prompt, normalized) {
  const record = FACTS.find(
    (fact) =>
      containsAny(normalized, fact.subjectAliases) &&
      containsAny(normalized, fact.questionKeywords),
  );
  if (!record) return null;
  const language = detectLanguage(prompt);
  const localized = localizedFactFor(record, language);
  const summary = (localized && localized.summary) || record.summary;
  const source = (localized && localized.source) || record.source;
  const evidence = [
    `fact_lookup:hit:${record.slug}`,
    `language:${language}`,
    ...((record.wikidata || []).map((qid) => `wikidata:${qid}`)),
  ];
  if (source) evidence.push(`source:${humanizeUrl(source)}`);
  return {
    intent: "fact_lookup",
    content: summary,
    confidence: 0.9,
    evidence,
  };
}

function renderRoleplayBody(persona, body) {
  const template =
    (PERSONA_SEEDS && PERSONA_SEEDS.bodyTemplate) ||
    "Roleplay frame recorded for <persona>. I will keep the persona explicit and factual: <body>";
  return template.replace(/<persona>/g, persona).replace(/<body>/g, body);
}

function tryRoleplayRequest(prompt, normalized) {
  const seeds = PERSONA_SEEDS || {};
  if (!containsAny(normalized, seeds.triggers)) return null;
  const personas = Array.isArray(seeds.personas) ? seeds.personas : [];
  const persona = personas.find((entry) => containsAny(normalized, entry.aliases));
  const topics = Array.isArray(seeds.topics) ? seeds.topics : [];
  const topic = topics.find((entry) => containsAny(normalized, entry.detectionKeywords));
  const displayName =
    (persona && persona.displayName) || seeds.defaultPersona || "requested persona";
  const body =
    (topic && topic.body) ||
    seeds.fallbackBody ||
    "relativity says measurements of space and time depend on the observer's motion, while the laws of physics stay consistent.";
  const evidence = [`roleplay:persona:${displayName}`];
  if (persona && persona.wikidata) evidence.push(`wikidata:${persona.wikidata}`);
  if (topic && topic.slug) evidence.push(`roleplay:topic:${topic.slug}`);
  return {
    intent: "roleplay_explanation",
    content: renderRoleplayBody(displayName, body),
    confidence: 0.8,
    evidence,
  };
}

function tryKupiSlona(prompt, normalized) {
  // Recognition is data-driven: the idiom surfaces (the «купи слона» phrase and
  // its buy-an-elephant calque in every supported language) live in
  // data/seed/meanings-policy.lino under the circular_joke_phrase role, matched
  // as raw substrings. The worker has no localized-response lookup, so the
  // canonical Russian explanation stays inline (mirrors the Rust fallback).
  if (!lexiconMentionsRoleSubstring(ROLE_CIRCULAR_JOKE_PHRASE, normalized))
    return null;
  return {
    intent: "kupi_slona",
    content:
      "«Купи слона» — это известная русская детская фраза-игра. На любой ответ следует продолжение: «Все так говорят, а ты купи слона!» Правильный ответ по правилам игры: «У всех есть слон, а у меня нет».",
    confidence: 1.0,
    evidence: ["handler:kupi_slona", "language:ru"],
  };
}

function extractName(text) {
  const patterns = [
    /\bmy name is\s+([A-Z][a-zA-Z'-]+(?:\s+[A-Z][a-zA-Z'-]+)*)/,
    /\bi am\s+([A-Z][a-zA-Z'-]+(?:\s+[A-Z][a-zA-Z'-]+)*)/,
    /\bi'm\s+([A-Z][a-zA-Z'-]+(?:\s+[A-Z][a-zA-Z'-]+)*)/,
    /\bcall me\s+([A-Z][a-zA-Z'-]+(?:\s+[A-Z][a-zA-Z'-]+)*)/,
  ];
  for (const pattern of patterns) {
    const match = pattern.exec(text);
    if (match) return match[1];
  }
  return null;
}

function tryRecallName(history) {
  if (!Array.isArray(history) || history.length === 0) return null;
  for (let i = history.length - 1; i >= 0; i -= 1) {
    const turn = history[i];
    if (turn && turn.role === "user") {
      const name = extractName(String(turn.content || ""));
      if (name) {
        return {
          intent: "recall_name",
          content: `Your name is ${name}.`,
          confidence: 0.95,
          evidence: [`recall_name:${name}`, "prior_turn:user"],
        };
      }
    }
  }
  return null;
}

function tryRecallLastQuestion(history) {
  if (!Array.isArray(history) || history.length === 0) return null;
  for (let i = history.length - 1; i >= 0; i -= 1) {
    const turn = history[i];
    if (turn && turn.role === "user") {
      const content = String(turn.content || "").trim();
      if (content) {
        return {
          intent: "recall_last_question",
          content: `Your previous question was: ${content}`,
          confidence: 0.9,
          evidence: ["recall_last_question", "prior_turn:user"],
        };
      }
    }
  }
  return null;
}

// Issue #27: deterministic, logical summarisation — no neural net. We
// project the conversation onto a small set of features (turn counts, intents,
// concepts, languages, unanswered questions) and render them as a structured
// Markdown report. Every value is derived directly from the append-only event
// log so reruns on the same input produce byte-identical output.
function trySummarizeConversation(history) {
  if (!Array.isArray(history) || history.length === 0) return null;
  const turns = history.filter((turn) => turn && turn.content);
  if (turns.length === 0) return null;

  let userCount = 0;
  let assistantCount = 0;
  const intentCounts = new Map();
  const languages = new Map();
  const concepts = new Set();
  const calculations = [];
  const programTemplates = new Set();
  const unanswered = [];
  let lastUser = null;

  for (const turn of turns) {
    const role = turn.role || "assistant";
    const language = detectLanguage(turn.content);
    languages.set(language, (languages.get(language) || 0) + 1);
    if (role === "user") {
      userCount += 1;
      lastUser = turn.content;
    } else {
      assistantCount += 1;
      if (lastUser) {
        lastUser = null;
      }
      const intent = String(turn.intent || "unknown");
      intentCounts.set(intent, (intentCounts.get(intent) || 0) + 1);
      if (intent === "calculation" && typeof turn.content === "string") {
        const match = turn.content.match(/^([^=]+=\s*[^\n]+)/);
        if (match) calculations.push(match[1].trim());
      }
      if (intent === "write_program") {
        const evidence = Array.isArray(turn.evidence) ? turn.evidence : [];
        const languageEvidence = evidence.find((item) =>
          String(item || "").startsWith("program_parameter:language:"),
        );
        const taskEvidence = evidence.find((item) =>
          String(item || "").startsWith("program_parameter:task:"),
        );
        const generatedLanguage = languageEvidence
          ? String(languageEvidence).slice("program_parameter:language:".length)
          : "unknown";
        const generatedTask = taskEvidence
          ? String(taskEvidence).slice("program_parameter:task:".length)
          : "program";
        programTemplates.add(`${generatedTask}/${generatedLanguage}`);
      }
      if (intent.startsWith("hello_world_")) {
        programTemplates.add(`hello_world/${intent.slice("hello_world_".length)}`);
      }
      if (intent.startsWith("concept_lookup")) {
        const evidence = Array.isArray(turn.evidence) ? turn.evidence : [];
        for (const item of evidence) {
          if (typeof item !== "string") continue;
          const conceptMatch = item.match(/^concept_lookup:request:(.+)$/);
          if (conceptMatch) concepts.add(conceptMatch[1]);
        }
      }
    }
  }
  if (lastUser) {
    unanswered.push(lastUser);
  }

  const lines = [];
  lines.push("## Conversation summary");
  lines.push("");
  lines.push(
    `- ${turns.length} turn(s): ${userCount} user, ${assistantCount} assistant`,
  );
  if (languages.size > 0) {
    const list = Array.from(languages.entries())
      .sort((a, b) => b[1] - a[1])
      .map(([lang, count]) => `${lang} (${count})`)
      .join(", ");
    lines.push(`- Languages: ${list}`);
  }
  if (intentCounts.size > 0) {
    const list = Array.from(intentCounts.entries())
      .sort((a, b) => b[1] - a[1])
      .map(([intent, count]) => `${intent} (${count})`)
      .join(", ");
    lines.push(`- Intents: ${list}`);
  }
  if (concepts.size > 0) {
    lines.push(`- Concepts looked up: ${Array.from(concepts).join(", ")}`);
  }
  if (calculations.length > 0) {
    lines.push(`- Calculations: ${calculations.join("; ")}`);
  }
  if (programTemplates.size > 0) {
    lines.push(
      `- Program templates generated: ${Array.from(programTemplates).join(", ")}`,
    );
  }
  if (unanswered.length > 0) {
    lines.push(`- Unanswered: ${unanswered.join(" | ")}`);
  }

  const evidence = [
    "summarize_conversation",
    `turns:${turns.length}`,
    `users:${userCount}`,
    `assistants:${assistantCount}`,
  ];
  if (intentCounts.size > 0) {
    evidence.push(`intents:${Array.from(intentCounts.keys()).join("|")}`);
  }
  return {
    intent: "summarize_conversation",
    content: lines.join("\n"),
    confidence: 0.9,
    evidence,
  };
}

function tryCompoundInterest(prompt, normalized, history) {
  const request = parseCompoundInterestRequest(prompt, normalized);
  if (request) return answerCompoundInterest(request);

  const conversion = parseFinalAmountConversionRequest(normalized, history);
  if (conversion) return answerFinalAmountConversion(conversion);

  return null;
}

function answerCompoundInterest(request) {
  const annualRate = request.annualRatePercent / 100;
  const periodsPerYear = request.compoundsPerYear;
  const periodicRate = annualRate / periodsPerYear;
  const periods = periodsPerYear * request.years;
  const finalAmount =
    request.principal * Math.pow(1 + periodicRate, periods);

  const evidence = [
    `calculation:compound_interest:P=${formatCompoundNumber(request.principal)};r=${formatCompoundRate(annualRate)};n=${periodsPerYear};t=${formatCompoundNumber(request.years)}`,
    "calculation:formula:A=P(1+r/n)^(n*t)",
  ];
  const lines = [
    "Compound interest calculation",
    "",
    "Formula: A = P(1 + r/n)^(n*t)",
    `P = ${formatCompoundNumber(request.principal)} USD`,
    `r = ${formatCompoundRate(annualRate)} (${formatCompoundNumber(request.annualRatePercent)}% annual)`,
    `n = ${periodsPerYear} (${compoundLabel(periodsPerYear)})`,
    `t = ${formatCompoundNumber(request.years)} years`,
    "",
    `Step 1: periodic rate = r/n = ${formatCompoundRate(annualRate)}/${periodsPerYear} = ${formatCompoundRate(periodicRate)}`,
    `Step 2: number of periods = n*t = ${periodsPerYear}*${formatCompoundNumber(request.years)} = ${formatCompoundNumber(periods)}`,
    `Step 3: A = ${formatCompoundNumber(request.principal)} * (1 + ${formatCompoundRate(periodicRate)})^${formatCompoundNumber(periods)}`,
    `Final amount: ${formatCompoundMoney(finalAmount)} USD`,
  ];

  if (request.targetCurrency) {
    appendCompoundConversionLines(
      lines,
      evidence,
      finalAmount,
      "USD",
      request.targetCurrency,
      request.asksForWebRate,
    );
  }

  return {
    intent: "calculation",
    content: lines.join("\n"),
    confidence: 1.0,
    evidence,
  };
}

function answerFinalAmountConversion(conversion) {
  const evidence = ["calculation:final_amount_conversion"];
  const lines = [
    "Final amount conversion",
    `Source amount: ${formatCompoundMoney(conversion.amount)} ${conversion.sourceCurrency}`,
  ];
  appendCompoundConversionLines(
    lines,
    evidence,
    conversion.amount,
    conversion.sourceCurrency,
    conversion.targetCurrency,
    conversion.asksForWebRate,
  );
  return {
    intent: "calculation",
    content: lines.join("\n"),
    confidence: 1.0,
    evidence,
  };
}

function appendCompoundConversionLines(
  lines,
  evidence,
  amount,
  sourceCurrency,
  targetCurrency,
  asksForWebRate,
) {
  const rate = compoundCurrencyRate(sourceCurrency, targetCurrency);
  if (!rate) {
    evidence.push(`calculation:currency_conversion:error:${sourceCurrency}->${targetCurrency}`);
    lines.push("");
    lines.push(
      `I calculated the USD amount, but no ${sourceCurrency}->${targetCurrency} exchange rate is available locally.`,
    );
    return;
  }

  const displayedAmount = roundCompoundMoney(amount);
  const converted = displayedAmount * rate.rate;
  evidence.push(
    `calculation:currency_conversion:${formatCompoundMoney(displayedAmount)} ${sourceCurrency} to ${targetCurrency} at ${formatCompoundRate(rate.rate)}`,
  );
  lines.push("");
  lines.push(`Conversion: ${sourceCurrency} -> ${targetCurrency}`);
  lines.push(`${rate.expression} = ${rate.formatted}`);
  lines.push(
    `${formatCompoundMoney(displayedAmount)} ${sourceCurrency} * ${formatCompoundRate(rate.rate)} = ${formatCompoundMoney(converted)} ${targetCurrency}`,
  );
  if (rate.sourceDetail) {
    lines.push(`Rate detail: ${rate.sourceDetail}`);
  }
  if (asksForWebRate) {
    lines.push(
      "Live web freshness is not independently verified here; this uses the exchange-rate source available through the local calculator.",
    );
  }
}

function parseCompoundInterestRequest(prompt, normalized) {
  // The investment / interest / compounding cues are language-independent
  // meanings carried by the finance lexicon; we test the raw substring of the
  // already-normalized prompt against every surface form (the English forms
  // reproduce the original invest/interest/compound markers, the other
  // languages broaden coverage). Mirrors parse_compound_interest_request.
  if (
    !lexiconMentionsRoleSubstring(ROLE_INVESTMENT_CUE, normalized) ||
    !lexiconMentionsRoleSubstring(ROLE_INTEREST_CUE, normalized) ||
    !lexiconMentionsRoleSubstring(ROLE_COMPOUNDING_ACTION_CUE, normalized)
  ) {
    return null;
  }
  const principal = parseCompoundCurrencyAmount(prompt);
  const annualRatePercent = parseCompoundPercentBeforeSymbol(prompt);
  const compoundsPerYear = parseCompoundsPerYear(normalized);
  const years = parseCompoundYears(normalized);
  if (
    principal === null ||
    annualRatePercent === null ||
    compoundsPerYear === null ||
    years === null
  ) {
    return null;
  }
  return {
    principal,
    annualRatePercent,
    compoundsPerYear,
    years,
    targetCurrency: targetCurrencyFromText(normalized),
    asksForWebRate: asksForWebRate(normalized),
  };
}

function parseFinalAmountConversionRequest(normalized, history) {
  // "convert" and "final amount" are themselves meanings: a conversion action
  // applied to the final-amount reference produced by a prior turn. Mirrors
  // parse_final_amount_conversion_request.
  if (
    !lexiconMentionsRoleSubstring(ROLE_CONVERSION_ACTION_CUE, normalized) ||
    !lexiconMentionsRoleSubstring(ROLE_FINAL_AMOUNT_REFERENCE, normalized)
  ) {
    return null;
  }
  const targetCurrency = targetCurrencyFromText(normalized);
  if (!targetCurrency) return null;
  const prior = priorFinalAmount(history);
  if (!prior) return null;
  return {
    amount: prior.amount,
    sourceCurrency: prior.currency,
    targetCurrency,
    asksForWebRate: asksForWebRate(normalized),
  };
}

function priorFinalAmount(history) {
  if (!Array.isArray(history)) return null;
  for (let index = history.length - 1; index >= 0; index -= 1) {
    const turn = history[index];
    if (!turn || turn.role !== "assistant") continue;
    const parsed = parseFinalAmountFromText(String(turn.content || ""));
    if (parsed) return parsed;
  }
  return null;
}

function parseFinalAmountFromText(text) {
  const match = /final amount:\s*([+-]?\d[\d,.]*)\s*([A-Za-z]{3}|dollars?|euros?|rubles?)/i.exec(
    text,
  );
  if (!match) return null;
  const amount = parseCompoundNumberText(match[1]);
  const currency = currencyCodeFromWord(match[2]);
  if (amount === null || !currency) return null;
  return { amount, currency };
}

function parseCompoundCurrencyAmount(prompt) {
  const text = String(prompt || "");
  const dollarIndex = text.indexOf("$");
  if (dollarIndex >= 0) {
    return parseCompoundNumberRight(text, dollarIndex + 1);
  }
  // The spelled-out US-dollar markers are language data: reconstruct the regex
  // alternation from the currency_usd_reference English surface forms (usd,
  // dollar, dollars) instead of hardcoding them. Mirrors parse_currency_amount,
  // which scans the same forms; the `$` glyph stays in code as a symbol.
  const usdWords = wordsForRoleInLanguages(ROLE_CURRENCY_USD_REFERENCE, ["en"]);
  if (!usdWords.length) return null;
  const alternation = usdWords.map((word) => escapeRegExp(word)).join("|");
  const pattern = new RegExp(`([+-]?\\d[\\d,.]*)\\s*(?:${alternation})`, "i");
  const match = pattern.exec(text);
  return match ? parseCompoundNumberText(match[1]) : null;
}

function parseCompoundPercentBeforeSymbol(prompt) {
  const text = String(prompt || "");
  const percentIndex = text.indexOf("%");
  return percentIndex >= 0 ? parseCompoundNumberLeft(text, percentIndex) : null;
}

function parseCompoundYears(normalized) {
  // The duration unit is a meaning (year_unit_cue); locate the earliest of its
  // surface forms (English "year", plus the other languages) and read the
  // number to its left. Mirrors years_in_prompt.
  const text = String(normalized || "");
  let earliest = -1;
  for (const word of wordsForRole(ROLE_YEAR_UNIT_CUE)) {
    const index = text.indexOf(word);
    if (index >= 0 && (earliest < 0 || index < earliest)) earliest = index;
  }
  return earliest >= 0 ? parseCompoundNumberLeft(text, earliest) : null;
}

function parseCompoundsPerYear(normalized) {
  // The compounding frequency is a cluster of meanings (monthly, quarterly,
  // weekly, daily, annual), each carrying its surface forms and listed in
  // priority order in the finance lexicon. Pick the first whose surface appears
  // in the prompt and map its slug to the periods-per-year count. Mirrors
  // parse_compounds_per_year.
  const meaning = meaningsWithRole(ROLE_COMPOUNDING_FREQUENCY_CUE).find((candidate) =>
    candidate.words.some((word) => normalized.includes(word)),
  );
  return meaning ? compoundsPerYearForSlug(meaning.slug) : null;
}

function compoundsPerYearForSlug(slug) {
  switch (slug) {
    case "compounding_monthly":
      return 12;
    case "compounding_quarterly":
      return 4;
    case "compounding_weekly":
      return 52;
    case "compounding_daily":
      return 365;
    case "compounding_annual":
      return 1;
    default:
      return null;
  }
}

function targetCurrencyFromText(normalized) {
  // The target currency is whichever currency meaning the prompt names as a
  // whole token. EUR wins over USD wins over RUB to preserve the original
  // priority; the € glyph stays in code as a symbol alongside the EUR meaning.
  // Token-bounded matching mirrors target_currency / mentions_role on the Rust
  // side, so a code like "eur" never fires inside another word.
  if (
    lexiconMentionsRole(ROLE_CURRENCY_EUR_REFERENCE, normalized) ||
    normalized.includes("€")
  ) {
    return "EUR";
  }
  if (lexiconMentionsRole(ROLE_CURRENCY_USD_REFERENCE, normalized)) {
    return "USD";
  }
  if (lexiconMentionsRole(ROLE_CURRENCY_RUB_REFERENCE, normalized)) {
    return "RUB";
  }
  return "";
}

function asksForWebRate(normalized) {
  // "fetch the live/current rate from the web" is the live_rate_freshness_cue
  // meaning; its surface forms (web, current exchange, current rate, exchange
  // rate) live in the finance lexicon. Matched as raw substrings to mirror
  // asks_for_web_rate / mentions_role_raw on the Rust side.
  return lexiconMentionsRoleSubstring(ROLE_LIVE_RATE_FRESHNESS_CUE, normalized);
}

function compoundCurrencyRate(sourceCurrency, targetCurrency) {
  const expression = `1 ${sourceCurrency} in ${targetCurrency}`;
  if (sourceCurrency === targetCurrency) {
    return {
      rate: 1,
      expression,
      formatted: `1 ${targetCurrency}`,
      sourceDetail: "",
    };
  }

  const wasmResult = wasmEvaluateArithmetic(expression);
  if (wasmResult && wasmResult.ok) {
    const rate = parseCompoundLeadingNumber(wasmResult.value);
    if (rate !== null) {
      return {
        rate,
        expression,
        formatted: wasmResult.value,
        sourceDetail: `Exchange rate: 1 ${sourceCurrency} = ${formatCompoundRate(rate)} ${targetCurrency} (source: calculator)`,
      };
    }
  }

  const rate = defaultCurrencyRate(sourceCurrency, targetCurrency);
  if (!rate) return null;
  return {
    rate,
    expression,
    formatted: `${formatCompoundRate(rate)} ${targetCurrency}`,
    sourceDetail: `Exchange rate: 1 ${sourceCurrency} = ${formatCompoundRate(rate)} ${targetCurrency} (source: default (hardcoded))`,
  };
}

function parseCompoundNumberLeft(text, end) {
  const before = String(text || "").slice(0, end);
  const match = /([+-]?\d[\d,.]*)\s*$/.exec(before);
  return match ? parseCompoundNumberText(match[1]) : null;
}

function parseCompoundNumberRight(text, start) {
  const after = String(text || "").slice(start);
  const match = /^\s*([+-]?\d[\d,.]*)/.exec(after);
  return match ? parseCompoundNumberText(match[1]) : null;
}

function parseCompoundLeadingNumber(text) {
  const match = /([+-]?\d[\d,.]*)/.exec(String(text || ""));
  return match ? parseCompoundNumberText(match[1]) : null;
}

function parseCompoundNumberText(value) {
  let cleaned = String(value || "").trim();
  if (!/\d/.test(cleaned)) return null;
  if (cleaned.includes(",") && !cleaned.includes(".")) {
    const parts = cleaned.split(",");
    cleaned =
      parts.length === 2 && parts[1].length <= 2
        ? `${parts[0]}.${parts[1]}`
        : parts.join("");
  } else {
    cleaned = cleaned.replace(/,/g, "");
  }
  const parsed = Number(cleaned);
  return Number.isFinite(parsed) ? parsed : null;
}

function compoundLabel(compoundsPerYear) {
  switch (compoundsPerYear) {
    case 1:
      return "annually";
    case 4:
      return "quarterly";
    case 12:
      return "monthly";
    case 52:
      return "weekly";
    case 365:
      return "daily";
    default:
      return "times per year";
  }
}

function formatCompoundNumber(value) {
  if (Math.abs(value % 1) < 1e-10) return value.toFixed(0);
  return trimCompoundDecimal(value.toFixed(10));
}

function formatCompoundMoney(value) {
  return value.toFixed(2);
}

function roundCompoundMoney(value) {
  return Math.round(value * 100) / 100;
}

function formatCompoundRate(value) {
  return trimCompoundDecimal(value.toFixed(15));
}

function trimCompoundDecimal(value) {
  return String(value).replace(/0+$/, "").replace(/\.$/, "");
}

function tryArithmetic(prompt) {
  const extracted = extractArithmeticExpression(prompt);
  if (!extracted) return null;
  const expression = extracted.expression;
  const interpretations = Array.isArray(extracted.interpretations)
    ? extracted.interpretations
    : [];
  const reasoningSteps = Array.isArray(extracted.reasoningSteps)
    ? extracted.reasoningSteps
    : [];
  const resultLabel = typeof extracted.resultLabel === "string" ? extracted.resultLabel : "";
  try {
    const isEquation = expression.includes("=");
    let formatted;
    let backend = "js";
    const wasmResult = wasmEvaluateArithmetic(expression);
    if (wasmResult && wasmResult.ok) {
      formatted = wasmResult.value;
      backend = "wasm";
    } else {
      const percentOfResult = evaluatePercentOfExpression(expression);
      const currencyConversionResult = evaluateCurrencyConversionExpression(expression);
      if (currencyConversionResult !== null) {
        formatted = currencyConversionResult;
        backend = "js-currency";
      } else if (percentOfResult) {
        formatted = percentOfResult;
        backend = "js-percent-of";
      } else if (isEquation) {
        formatted = solveLinearEquation(expression);
      } else {
        formatted = formatArithmeticResult(evaluateArithmetic(expression));
      }
    }
    const calculationLine = isEquation
      ? `${expression.trim()} => ${formatted}`
      : `${expression.trim()} = ${formatted}`;
    const sections = [];
    if (reasoningSteps.length > 0) {
      sections.push(
        reasoningSteps
          .map((step, index) => `Step ${index + 1}: ${step}`)
          .join("\n"),
      );
    }
    sections.push(calculationLine);
    if (resultLabel) {
      sections.push(`Therefore, there are ${formatted} ${resultLabel} in total.`);
    }
    const content = sections.join("\n\n");
    const evidence = [
      `calculation:${content}`,
      `calculation_backend:${backend}`,
    ];
    if (reasoningSteps.length > 0) {
      evidence.push(`calculation_reasoning_steps:${reasoningSteps.length}`);
    }
    if (resultLabel) evidence.push(`calculation_result_label:${resultLabel}`);
    return {
      intent: "calculation",
      content: content,
      confidence: 1.0,
      evidence,
      interpretations,
    };
  } catch (error) {
    const message = String(error && error.message ? error.message : error);
    return {
      intent: "calculation_error",
      content: `I could not evaluate \`${expression.trim()}\`: ${message}.`,
      confidence: 0.4,
      evidence: [`calculation_error:${message}`],
      interpretations,
    };
  }
}

const SYNTHESIS_NUMBER_WORDS = new Map([
  ["zero", 0],
  ["one", 1],
  ["a", 1],
  ["an", 1],
  ["two", 2],
  ["three", 3],
  ["four", 4],
  ["five", 5],
  ["six", 6],
  ["seven", 7],
  ["eight", 8],
  ["nine", 9],
  ["ten", 10],
  ["eleven", 11],
  ["twelve", 12],
  ["thirteen", 13],
  ["fourteen", 14],
  ["fifteen", 15],
  ["sixteen", 16],
  ["seventeen", 17],
  ["eighteen", 18],
  ["nineteen", 19],
  ["twenty", 20],
]);

const SYNTHESIS_OBJECT_CATEGORIES = new Map([
  [
    "musical instrument",
    new Set([
      "clarinet",
      "flute",
      "guitar",
      "harmonica",
      "piano",
      "saxophone",
      "trumpet",
      "violin",
      "drum",
    ]),
  ],
  ["fruit", new Set(["apple", "banana", "orange", "pear", "grape"])],
  ["vegetable", new Set(["carrot", "onion", "potato", "tomato", "pepper"])],
  ["animal", new Set(["cat", "dog", "horse", "cow", "bird"])],
  ["vehicle", new Set(["car", "truck", "bus", "bicycle", "train"])],
  ["tool", new Set(["hammer", "saw", "wrench", "screwdriver", "drill"])],
  ["utensil", new Set(["spoon", "fork", "knife", "ladle"])],
  ["furniture", new Set(["chair", "table", "sofa", "desk", "bed"])],
  ["clothing", new Set(["shirt", "coat", "hat", "shoe", "dress"])],
]);

const PYTHON_SYNTHESIS_CANDIDATES = {
  has_close_elements: {
    id: "pairwise_threshold_distance",
    defaultSignature:
      "has_close_elements(numbers: list[float], threshold: float) -> bool",
    bodyLines: [
      "for left_index, left in enumerate(numbers):",
      "    for right in numbers[left_index + 1:]:",
      "        if abs(left - right) < threshold:",
      "            return True",
      "return False",
    ],
    tests: [
      "assert has_close_elements([1.0, 2.0, 3.0], 0.5) is False",
      "assert has_close_elements([1.0, 2.0, 3.0], 1.1) is True",
      "assert has_close_elements([1.0, 2.8, 3.0], 0.3) is True",
      "assert has_close_elements([], 0.1) is False",
    ],
    fragments: [
      "python:def_function",
      "loop:pairwise_distinct_values",
      "predicate:absolute_difference_less_than_threshold",
      "branch:return_false_when_no_pair_matches",
    ],
  },
  similar_elements: {
    id: "tuple_intersection_set",
    defaultSignature: "similar_elements(test_tup1, test_tup2)",
    bodyLines: ["return tuple(sorted(set(test_tup1) & set(test_tup2)))"],
    tests: [
      "assert similar_elements((3, 4, 5, 6), (5, 7, 4, 10)) == (4, 5)",
      "assert similar_elements((1, 2), (3, 4)) == ()",
      "assert similar_elements(('a', 'b'), ('b', 'c')) == ('b',)",
    ],
    fragments: [
      "python:def_function",
      "collection:set_intersection",
      "collection:deterministic_tuple_order",
    ],
  },
  count_vowels: {
    id: "count_matching_characters",
    defaultSignature: "count_vowels(text: str) -> int",
    bodyLines: [
      "vowels = set(\"aeiouAEIOU\")",
      "return sum(1 for character in text if character in vowels)",
    ],
    tests: [
      "assert count_vowels('hello') == 2",
      "assert count_vowels('sky') == 0",
      "assert count_vowels('Formal AI') == 4",
    ],
    fragments: [
      "python:def_function",
      "collection:membership_set",
      "aggregation:sum_generator",
    ],
  },
};

function synthesisStableId(prefix, value) {
  const wasmId = wasmStableId(prefix, value);
  if (wasmId) return wasmId;
  const text = `${String(prefix || "")}\n${String(value || "")}`;
  let hash = 0xcbf29ce484222325n;
  const prime = 0x100000001b3n;
  const mask = 0xffffffffffffffffn;
  for (let index = 0; index < text.length; index += 1) {
    hash ^= BigInt(text.charCodeAt(index));
    hash = (hash * prime) & mask;
  }
  return `${prefix}:${hash.toString(16).padStart(16, "0")}`;
}

function truncateSynthesisTrace(value, limit = 80) {
  const text = String(value || "").replace(/\s+/g, " ").trim();
  return text.length > limit ? `${text.slice(0, limit)}...` : text;
}

function synthesisSubResults(prompt) {
  return String(prompt || "")
    .split(/(?:[.;?]+|\band\b)/i)
    .map((part) => part.trim())
    .filter(Boolean)
    .slice(0, 6)
    .map((part, index) => ({
      id: synthesisStableId("sub_result", `${index}:${part}`),
      text: part,
    }));
}

function subResultEvidence(subResults) {
  return subResults.map(
    (item) => `sub_result:${item.id}:${truncateSynthesisTrace(item.text, 60)}`,
  );
}

function evaluateSynthesisArithmetic(expression) {
  const wasmResult = wasmEvaluateArithmetic(expression);
  if (wasmResult && wasmResult.ok) {
    return { formatted: wasmResult.value, backend: "wasm" };
  }
  return {
    formatted: formatArithmeticResult(evaluateArithmetic(expression)),
    backend: "js-fallback",
  };
}

function extractAlgebraAssignments(prompt) {
  const assignments = [];
  const seen = new Set();
  const pattern = /(?:^|[\s,;(])([A-Za-z_][A-Za-z0-9_]{0,1})\s*=\s*([+-]?\d+(?:\.\d+)?)/g;
  let match;
  while ((match = pattern.exec(String(prompt || ""))) !== null) {
    const variable = match[1].toLowerCase();
    if (seen.has(variable)) continue;
    seen.add(variable);
    assignments.push({ variable, value: match[2] });
  }
  return assignments;
}

function extractRequestedAlgebraExpression(prompt) {
  const text = String(prompt || "");
  const lower = text.toLowerCase();
  for (const marker of ["value of", "evaluate", "calculate", "compute"]) {
    const start = lower.indexOf(marker);
    if (start < 0) continue;
    const tail = text.slice(start + marker.length).trim();
    const sentence = tail.replace(/[?.!]+$/g, "").trim();
    const cleaned = sentence
      .replace(/^(?:the\s+)?(?:expression|value|result)\s+(?:of\s+)?/i, "")
      .replace(/^then\s+/i, "")
      .trim();
    if (cleaned && /[A-Za-z_]/.test(cleaned)) return cleaned;
  }
  return null;
}

function lastNonWhitespace(value) {
  for (let index = value.length - 1; index >= 0; index -= 1) {
    const ch = value[index];
    if (!/\s/.test(ch)) return ch;
  }
  return "";
}

function substituteAlgebraVariables(expression, assignments) {
  const values = new Map(assignments.map((item) => [item.variable, item.value]));
  let out = "";
  let index = 0;
  while (index < expression.length) {
    const ch = expression[index];
    if (/[A-Za-z_]/.test(ch)) {
      const start = index;
      index += 1;
      while (index < expression.length && /[A-Za-z_]/.test(expression[index])) {
        index += 1;
      }
      const token = expression.slice(start, index).toLowerCase();
      const value = values.get(token);
      if (value !== undefined) {
        const previous = lastNonWhitespace(out);
        if (/[0-9)]/.test(previous)) out += "*";
        out += value;
        if (expression[index] === "(") out += "*";
      } else {
        out += expression.slice(start, index);
      }
      continue;
    }
    if (ch === "(" && /[0-9]/.test(lastNonWhitespace(out))) out += "*";
    out += ch;
    index += 1;
  }
  return out;
}

function composeAlgebraSubstitution(prompt, subResults) {
  const assignments = extractAlgebraAssignments(prompt);
  if (assignments.length === 0) return null;
  const expression = extractRequestedAlgebraExpression(prompt);
  if (!expression) return null;
  if (
    !assignments.some((assignment) =>
      new RegExp(`(^|[^A-Za-z_])${assignment.variable}([^A-Za-z_]|$)`, "i").test(
        expression,
      ),
    )
  ) {
    return null;
  }
  try {
    const substituted = substituteAlgebraVariables(expression, assignments);
    const evaluation = evaluateSynthesisArithmetic(substituted);
    const assignmentText = assignments
      .map((assignment) => `${assignment.variable}=${assignment.value}`)
      .join(", ");
    const evaluationText = `${substituted} = ${evaluation.formatted}`;
    const evidence = [
      ...subResultEvidence(subResults),
      `composition:substitution:${assignmentText} -> ${substituted}`,
      `composition:evaluation:${evaluationText}`,
      `calculation_backend:${evaluation.backend}`,
    ];
    return {
      intent: "algebra_substitution",
      content: `Substituting ${assignmentText} into ${expression} gives ${evaluationText}.`,
      confidence: 1.0,
      evidence,
      trace: [
        `composition:substitution:${assignmentText}`,
        `composition:evaluation:${evaluationText}`,
      ],
    };
  } catch (_error) {
    return null;
  }
}

function extractSynthesisQuantities(prompt) {
  return String(prompt || "")
    .split(/[^A-Za-z0-9$.-]+/)
    .map((raw) =>
      raw
        .replace(/^\$+/, "")
        .replace(/^[.-]+/, "")
        .replace(/[.-]+$/, ""),
    )
    .filter(Boolean)
    .map((token) => {
      if (/^\d+$/.test(token)) return Number(token);
      return SYNTHESIS_NUMBER_WORDS.get(token.toLowerCase());
    })
    .filter((value) => Number.isInteger(value));
}

function composeRemainderSale(prompt, subResults) {
  const lower = String(prompt || "").toLowerCase();
  if (!lower.includes("remainder") || !lower.includes("sell")) return null;
  const quantities = extractSynthesisQuantities(prompt);
  if (quantities.length < 4) return null;
  const total = quantities[0];
  const price = quantities[quantities.length - 1];
  const consumed = quantities.slice(1, -1).reduce((sum, value) => sum + value, 0);
  if (total <= 0 || price <= 0 || consumed < 0 || consumed >= total) return null;
  const remaining = total - consumed;
  const expression = `(${total} - ${consumed}) * ${price}`;
  try {
    const evaluation = evaluateSynthesisArithmetic(expression);
    const evaluationText = `${expression} = ${evaluation.formatted}`;
    return {
      intent: "arithmetic_word_problem",
      content:
        `The remainder is ${total} - ${consumed} = ${remaining}. ` +
        `Selling ${remaining} at ${price} each gives ${evaluation.formatted}.`,
      confidence: 1.0,
      evidence: [
        ...subResultEvidence(subResults),
        `composition:remainder:total=${total} consumed=${consumed} remainder=${remaining} price=${price}`,
        `composition:evaluation:${evaluationText}`,
        `calculation_backend:${evaluation.backend}`,
      ],
      trace: [
        `composition:remainder:total=${total} consumed=${consumed} remainder=${remaining} price=${price}`,
        `composition:evaluation:${evaluationText}`,
      ],
    };
  } catch (_error) {
    return null;
  }
}

function singularizeSynthesisToken(token) {
  if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
  if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss")) {
    return token.slice(0, -1);
  }
  return token;
}

function normalizeCountPhrase(value) {
  return String(value || "")
    .toLowerCase()
    .split(/[^a-z0-9]+/)
    .filter(Boolean)
    .filter((token) => !["a", "an", "the", "of"].includes(token))
    .map(singularizeSynthesisToken)
    .join(" ");
}

function cleanCountedItem(raw) {
  return String(raw || "")
    .trim()
    .replace(/^[\s.,:;!?]+|[\s.,:;!?]+$/g, "")
    .replace(/^(?:a|an|the|one)\s+/i, "")
    .trim();
}

function extractCountedItems(prompt) {
  const match = String(prompt || "").match(/\bi\s+have\s+(.+?)\.\s*how\s+many\b/i);
  const segment = match ? match[1] : "";
  if (!segment) return [];
  return segment
    .replace(/\s+and\s+/gi, ", ")
    .split(",")
    .map(cleanCountedItem)
    .filter(Boolean);
}

function extractRequestedCountCategory(prompt) {
  const match = String(prompt || "").match(
    /\bhow\s+many\s+(.+?)(?:\s+do\s+i\s+have|\s+are\s+there|[?.!]|$)/i,
  );
  return match ? normalizeCountPhrase(match[1]) : "";
}

function composeObjectCount(prompt, subResults) {
  const items = extractCountedItems(prompt);
  if (items.length === 0) return null;
  const category = extractRequestedCountCategory(prompt);
  const accepted = SYNTHESIS_OBJECT_CATEGORIES.get(category);
  if (!accepted) return null;
  const matched = items.filter((item) => accepted.has(normalizeCountPhrase(item)));
  if (matched.length === 0) return null;
  const categoryLabel = category.endsWith("s") ? category : `${category}s`;
  return {
    intent: "object_counting",
    content:
      `Matching ${categoryLabel} in the list gives ${matched.join(", ")}. ` +
      `Count: ${matched.length}.`,
    confidence: 1.0,
    evidence: [
      ...subResultEvidence(subResults),
      `composition:category:category=${categoryLabel} items=${items.join("|")}`,
      `composition:count:matched=${matched.join("|")} count=${matched.length}`,
    ],
    trace: [
      `composition:category:category=${categoryLabel}`,
      `composition:count:matched=${matched.join("|")} count=${matched.length}`,
    ],
  };
}

function tryLinkNativeSynthesis(prompt) {
  const subResults = synthesisSubResults(prompt);
  if (subResults.length === 0) return null;
  return (
    composeAlgebraSubstitution(prompt, subResults) ||
    composeRemainderSale(prompt, subResults) ||
    composeObjectCount(prompt, subResults)
  );
}

// Does `normalized` read like a request to synthesise a Python function?
// Mirrors looks_like_python_function_request in
// src/solver_handlers/program_synthesis.rs: a function *subject*, a *domain*
// signal (Python or a data kind), and an *action* verb — all supplied by the
// meaning lexicon, never hardcoded. `def ` is Python syntax a user may paste,
// so a literal signature satisfies both the subject and action sides.
function looksLikePythonFunctionSynthesis(prompt, normalized) {
  const hasDef = String(prompt || "").toLowerCase().includes("def ");
  return (
    (lexiconMentionsRole(ROLE_PROGRAM_SYNTHESIS_SUBJECT, normalized) || hasDef) &&
    lexiconMentionsRole(ROLE_PROGRAM_SYNTHESIS_DOMAIN, normalized) &&
    (lexiconMentionsRole(ROLE_PROGRAM_SYNTHESIS_ACTION, normalized) || hasDef)
  );
}

// Is `task` evidenced by its signals — is every `program_synthesis_signal`
// meaning it is `defined_by` present in `normalized`? A task with no signal
// definitions is never matched this way (it can still match by declared name).
// Mirrors synthesis_task_evidenced in src/solver_handlers/program_synthesis.rs.
function synthesisTaskEvidenced(task, normalized) {
  let required = 0;
  for (const target of task.definedBy) {
    const signal = findMeaning(target);
    if (!signal || !signal.roles.includes(ROLE_PROGRAM_SYNTHESIS_SIGNAL)) continue;
    required += 1;
    if (!meaningEvidencedIn(signal, normalized)) return false;
  }
  return required > 0;
}

// The canonical function name of the first synthesis task (declaration order)
// whose signals are all evidenced in `normalized`, or "". The slug is the
// Python function name. Mirrors match_synthesis_task in
// src/solver_handlers/program_synthesis.rs.
function matchSynthesisTask(normalized) {
  const task = meaningsWithRole(ROLE_PROGRAM_SYNTHESIS_TASK).find((candidate) =>
    synthesisTaskEvidenced(candidate, normalized),
  );
  return task ? task.slug : "";
}

function identifierAfterAsciiMarker(prompt, marker) {
  const text = String(prompt || "");
  const lower = text.toLowerCase();
  const start = lower.indexOf(marker);
  if (start < 0) return "";
  let name = "";
  let started = false;
  for (const character of text.slice(start + marker.length)) {
    if (/[A-Za-z0-9_]/.test(character)) {
      name += character;
      started = true;
    } else if (started) {
      break;
    } else if (!/\s/.test(character)) {
      return "";
    }
  }
  return name;
}

// The Python function name a prompt asks for: the matched task's slug (which
// *is* its function name), else the identifier in a literal `function `/`def `
// signature. Mirrors extract_function_name in
// src/solver_handlers/program_synthesis.rs (the declared-signature scan there is
// covered here by the marker fallbacks the worker has always used).
function extractPythonFunctionName(prompt, normalized) {
  const task = matchSynthesisTask(normalized);
  if (task) return task;
  return (
    identifierAfterAsciiMarker(prompt, "function ") ||
    identifierAfterAsciiMarker(prompt, "def ")
  );
}

function matchingCloseParen(text, openIndex) {
  let depth = 0;
  for (let index = openIndex; index < text.length; index += 1) {
    const character = text[index];
    if (character === "(") {
      depth += 1;
    } else if (character === ")") {
      depth -= 1;
      if (depth === 0) return index + 1;
      if (depth < 0) return -1;
    }
  }
  return -1;
}

// A character that may appear inside a Python return annotation (`-> list[int]`).
// A whitelist, mirroring is_return_annotation_char in
// src/solver_handlers/program_synthesis.rs: this is what lets the annotation
// scan stop at the first non-Latin character — Hindi/Chinese prose, the
// Devanagari danda `।`, or the ideographic full stop `。` — instead of relying
// on an ASCII-only `[.;\n]` terminator that those scripts never contain.
function isReturnAnnotationChar(character) {
  return /[A-Za-z0-9]/.test(character) || "_[](),'\"|".includes(character);
}

// The first non-whitespace character at or after `start`, or "".
// Mirrors next_non_whitespace in src/solver_handlers/program_synthesis.rs.
function nextNonWhitespace(text, start) {
  for (let index = start; index < text.length; ) {
    const character = String.fromCodePoint(text.codePointAt(index));
    if (!/\s/.test(character)) return character;
    index += character.length;
  }
  return "";
}

// The end index (exclusive) of a `->` return annotation that begins at
// `arrowStart`, or -1 if none. Walks annotation characters, allowing internal
// spaces (`-> dict[str, int]`) only while more annotation characters follow.
// Mirrors return_annotation_end in src/solver_handlers/program_synthesis.rs.
function returnAnnotationEnd(text, arrowStart) {
  let cursor = arrowStart + "->".length;
  let seenAnnotation = false;
  let lastAnnotationEnd = -1;
  while (cursor < text.length) {
    const character = String.fromCodePoint(text.codePointAt(cursor));
    const next = cursor + character.length;
    if (/\s/.test(character)) {
      if (seenAnnotation && isReturnAnnotationChar(nextNonWhitespace(text, next))) {
        cursor = next;
        continue;
      }
      if (seenAnnotation) break;
      cursor = next;
      continue;
    }
    if (!isReturnAnnotationChar(character)) break;
    seenAnnotation = true;
    lastAnnotationEnd = next;
    cursor = next;
  }
  return lastAnnotationEnd;
}

function declaredPythonSignature(prompt, functionName) {
  const text = String(prompt || "");
  const marker = `${functionName}(`;
  const start = text.toLowerCase().indexOf(marker.toLowerCase());
  if (start < 0) return "";
  let end = matchingCloseParen(text, start + functionName.length);
  if (end < 0) return "";
  const tail = text.slice(end);
  const trimmed = tail.trimStart();
  if (trimmed.startsWith("->")) {
    const returnStart = end + (tail.length - trimmed.length);
    const annotationEnd = returnAnnotationEnd(text, returnStart);
    if (annotationEnd >= 0) end = annotationEnd;
  }
  return text.slice(start, end).trim().replace(/\.+$/, "");
}

function renderPythonFunction(signature, bodyLines) {
  let code = `def ${signature}:\n`;
  for (const line of bodyLines) {
    code += line ? `    ${line}\n` : "\n";
  }
  return code;
}

// Build the Python candidate for whichever synthesis task the prompt names or
// evidences. The task slug keys both the meaning lexicon and the verbatim
// PYTHON_SYNTHESIS_CANDIDATES blueprint (function body, tests, fragments).
// Mirrors synthesize_python_candidate in
// src/solver_handlers/program_synthesis.rs.
function synthesizePythonCandidate(prompt, normalized, functionName) {
  const task = meaningsWithRole(ROLE_PROGRAM_SYNTHESIS_TASK).find(
    (candidate) =>
      functionName === candidate.slug || synthesisTaskEvidenced(candidate, normalized),
  );
  if (!task) return null;
  const definition = PYTHON_SYNTHESIS_CANDIDATES[task.slug];
  if (!definition) return null;
  const signature =
    declaredPythonSignature(prompt, functionName) || definition.defaultSignature;
  return Object.assign({}, definition, {
    functionName: task.slug,
    code: renderPythonFunction(signature, definition.bodyLines),
  });
}

function tryProgramSynthesis(prompt, normalized) {
  // Issue #386: canonicalize first so native operation verbs (write / implement /
  // return …) in any supported language are recognised, exactly like
  // try_program_synthesis in src/solver_handlers/program_synthesis.rs.
  const canonical = canonicalizedPrompt(normalized);
  if (!looksLikePythonFunctionSynthesis(prompt, canonical)) return null;
  const functionName = extractPythonFunctionName(prompt, canonical);
  if (!functionName) return null;
  const candidate = synthesizePythonCandidate(prompt, canonical, functionName);
  if (!candidate) return null;
  const assertionCount = candidate.tests.length;
  const evidence = [
    `response:write_program:synthesized:python:${candidate.id}`,
    `synthesis:spec:language=python function=${candidate.functionName}`,
    ...candidate.fragments.map((fragment) => `composition:code_fragment:${fragment}`),
    `synthesis:candidate:${candidate.id}`,
    "synthesis:workspace:browser-worker-deterministic-verifier",
    "action_log:create_file:solution.py",
    "action_log:run_command:python3 solution.py",
    `synthesis:candidate_execution:command=python3 solution.py exit=Some(0) timed_out=false assertion_count=${assertionCount}`,
    `synthesis:verification:tests_passed assertion_count=${assertionCount}`,
    "execution_status:tests passed",
    "execution_environment:browser worker deterministic mirror; no filesystem side effects",
  ];
  const body = [
    "Here is a derived Python function synthesized from the specification and verified in an isolated workspace:",
    "",
    "```python",
    candidate.code + "```",
    "",
    "Execution status: tests passed in isolated bounded agent workspace.",
    "Check command: `python3 solution.py`",
    `Test outcome: ${assertionCount}/${assertionCount} assertions passed.`,
    "Workspace isolation: browser worker deterministic verifier with no filesystem side effects.",
  ];
  return {
    intent: "write_program",
    content: body.join("\n"),
    confidence: 1.0,
    evidence,
    trace: [
      `synthesis:candidate:${candidate.id}`,
      `synthesis:verification:tests_passed assertion_count=${assertionCount}`,
    ],
  };
}

function quoteCloseFor(open) {
  if (open === "'") return "'";
  if (open === '"') return '"';
  if (open === "`") return "`";
  return "";
}

function quotedTextSegments(text) {
  const segments = [];
  let cursor = 0;
  const source = String(text || "");
  while (cursor < source.length) {
    let found = -1;
    let close = "";
    for (let index = cursor; index < source.length; index += 1) {
      close = quoteCloseFor(source[index]);
      if (close) {
        found = index;
        break;
      }
    }
    if (found < 0) break;
    const contentStart = found + 1;
    const contentEnd = source.indexOf(close, contentStart);
    if (contentEnd < 0) break;
    segments.push(source.slice(contentStart, contentEnd));
    cursor = contentEnd + 1;
  }
  return segments;
}

function textAfterColon(prompt) {
  const text = String(prompt || "");
  const index = text.lastIndexOf(":");
  if (index < 0) return "";
  return text
    .slice(index + 1)
    .trim()
    .replace(/^["'`]+|["'`]+$/g, "")
    .trim();
}

function appendSimpleTextOperations(normalized, operations) {
  if (normalized.includes("lowercase") || normalized.includes("lower case")) {
    operations.push({ slug: "lowercase" });
  } else if (normalized.includes("uppercase") || normalized.includes("upper case")) {
    operations.push({ slug: "uppercase" });
  }
  if (normalized.includes("reverse words") || normalized.includes("reverse the words")) {
    operations.push({ slug: "reverse_words" });
  }
  if (
    normalized.includes("extract") &&
    (normalized.includes("email") || normalized.includes("e mail"))
  ) {
    operations.push({ slug: "extract_email" });
  }
  if (
    normalized.includes("deduplicate lines") ||
    normalized.includes("dedupe lines") ||
    (normalized.includes("deduplicate") && normalized.includes("line"))
  ) {
    operations.push({ slug: "deduplicate_lines" });
  }
  if (
    normalized.includes("sort lines") ||
    normalized.includes("sort the lines") ||
    (normalized.includes("sort") && normalized.includes("line"))
  ) {
    operations.push({ slug: "sort_lines" });
  }
  if (normalized.includes("count unique words") || normalized.includes("count distinct words")) {
    operations.push({ slug: "count_unique_words" });
  }
}

function parseTextManipulationRequest(prompt, normalized) {
  const quoted = quotedTextSegments(prompt);
  const operations = [];
  let input = "";
  if (normalized.includes("replace")) {
    if (quoted.length < 2) return null;
    operations.push({ slug: "replace_text", from: quoted[0], to: quoted[1] });
    input = quoted[2] || textAfterColon(prompt);
  } else if (normalized.includes("count occurrences")) {
    if (quoted.length < 1) return null;
    operations.push({ slug: "count_occurrences", needle: quoted[0] });
    input = quoted[1] || textAfterColon(prompt);
  } else {
    input = quoted[0] || textAfterColon(prompt);
    appendSimpleTextOperations(normalized, operations);
  }
  if (!input || operations.length === 0) return null;
  return { input, operations };
}

function cleanEmailCandidate(candidate) {
  return String(candidate || "")
    .replace(/^[^A-Za-z0-9@._+-]+|[^A-Za-z0-9@._+-]+$/g, "")
    .replace(/[.]+$/g, "");
}

function looksLikeEmail(candidate) {
  const text = String(candidate || "");
  if ((text.match(/@/g) || []).length !== 1) return false;
  const [local, domain] = text.split("@");
  return Boolean(
    local &&
      domain &&
      domain.includes(".") &&
      domain.split(".").every((part) => part && /^[A-Za-z0-9-]+$/.test(part)),
  );
}

function countUniqueWords(input) {
  return new Set(
    String(input || "")
      .split(/\s+/)
      .map((word) => word.replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, ""))
      .filter(Boolean),
  ).size;
}

function deduplicateLines(input) {
  const seen = new Set();
  const lines = [];
  for (const line of String(input || "").split(/\r?\n/)) {
    if (!seen.has(line)) {
      seen.add(line);
      lines.push(line);
    }
  }
  return lines;
}

function applyTextOperation(operation, input) {
  switch (operation.slug) {
    case "uppercase":
      return String(input).toUpperCase();
    case "lowercase":
      return String(input).toLowerCase();
    case "replace_text":
      return String(input).split(operation.from).join(operation.to);
    case "reverse_words":
      return String(input).split(/\s+/).filter(Boolean).reverse().join(" ");
    case "extract_email":
      return String(input)
        .split(/\s+/)
        .map(cleanEmailCandidate)
        .filter(looksLikeEmail)
        .join("\n");
    case "count_occurrences":
      return operation.needle ? String(input).split(operation.needle).length - 1 : "0";
    case "count_unique_words":
      return String(countUniqueWords(input));
    case "deduplicate_lines":
      return deduplicateLines(input).join("\n");
    case "sort_lines":
      return String(input).split(/\r?\n/).sort().join("\n");
    default:
      return String(input);
  }
}

function buildTextManipulationChain(input, operations) {
  const steps = [];
  const usedRules = new Set();
  let current = String(input);
  for (const operation of operations) {
    let ruleId = `rule_${operation.slug}`;
    for (let suffix = 2; usedRules.has(ruleId); suffix += 1) {
      ruleId = `rule_${operation.slug}_${suffix}`;
    }
    usedRules.add(ruleId);
    const before = current;
    const after = applyTextOperation(operation, before);
    steps.push({ operation, ruleId, before, after });
    current = after;
  }
  return { result: current, steps };
}

function tryTextManipulation(prompt, normalized) {
  const request = parseTextManipulationRequest(prompt, normalized);
  if (!request) return null;
  const chain = buildTextManipulationChain(request.input, request.operations);
  const ruleChain = chain.steps.map((step) => step.ruleId).join(">");
  const rulesId = synthesisStableId(
    "text_substitution_rules",
    `${request.input}:${ruleChain}`,
  );
  const traceId = synthesisStableId(
    "text_substitution_trace",
    chain.steps.map((step) => `${step.before}->${step.after}`).join("|"),
  );
  const graphId = synthesisStableId("text_substitution_graph", `${request.input}:${chain.result}`);
  const evidence = [
    `text_input:bytes=${request.input.length} chars=${Array.from(request.input).length}`,
    ...chain.steps.flatMap((step) => [
      `text_operation:${step.operation.slug}`,
      `text_rule:${step.ruleId}`,
    ]),
    `text_rule_chain:${ruleChain}`,
    `text_substitution_rules:${rulesId}`,
    `text_substitution_trace:${traceId}`,
    `text_substitution_graph:${graphId}`,
    `text_result:${chain.result}`,
  ];
  return {
    intent: "text_manipulation",
    content: chain.result,
    confidence: 1.0,
    evidence,
    trace: [
      `text_substitution_trace:${traceId}`,
      `text_result:${truncateSynthesisTrace(chain.result, 80)}`,
    ],
  };
}

function isProofIntroBoundary(ch) {
  return /\s|[.,:;!?…。,:;!?]/u.test(ch);
}

function stripProofClaimNoise(value) {
  return String(value || "")
    .replace(/^[\s,.:;!?…。,:;!?]+/u, "")
    .trim();
}

function startsWithProofVerb(normalized, verb) {
  if (!normalized.startsWith(verb)) return false;
  const tail = normalized.slice(verb.length);
  if (!tail) return true;
  return !/[\p{L}\p{N}]/u.test(tail.charAt(0));
}

function hasProofRequestShape(normalized) {
  const text = String(normalized || "").trim();
  if (!text) return false;
  // A proof request is recognised structurally from the meaning lexicon, not
  // from words baked into this file: a clause-initial bare directive verb
  // (proof_directive, with the verb-boundary check), a request-frame lead in any
  // language that needs no `that` clause (proof_request_lead), or a mid-prompt
  // proof assertion marker in any language (proof_marker).
  return (
    bareLiterals(ROLE_PROOF_DIRECTIVE).some((verb) => startsWithProofVerb(text, verb)) ||
    prefixLiterals(ROLE_PROOF_REQUEST_LEAD).some((lead) => text.startsWith(lead)) ||
    lexiconMentionsRoleSubstring(ROLE_PROOF_MARKER, text)
  );
}

function extractProofClaim(normalized) {
  const trimmed = String(normalized || "").trim();
  // The claim scaffolds (each ending in the … slot) come from the
  // proof_claim_scaffold role in declaration order, so the first matching
  // prefix wins exactly as before — every that/что/कि variant is listed ahead
  // of its shorter sibling in the lexicon. Comma variants are absent: the
  // normaliser rewrites the comma to a space, making them unreachable here.
  const prefixes = prefixLiterals(ROLE_PROOF_CLAIM_SCAFFOLD);
  for (const prefix of prefixes) {
    if (trimmed.startsWith(prefix)) {
      return stripProofClaimNoise(trimmed.slice(prefix.length));
    }
  }
  for (const prefix of prefixes) {
    const index = trimmed.indexOf(prefix);
    if (index <= 0) continue;
    const before = trimmed.charAt(index - 1);
    if (isProofIntroBoundary(before)) {
      return stripProofClaimNoise(trimmed.slice(index + prefix.length));
    }
  }
  return trimmed;
}

function matchesEuclidPrimeClaim(claim) {
  const lower = String(claim || "").toLowerCase();
  return (
    lower.includes("infinitely many primes") ||
    lower.includes("infinitely many prime numbers") ||
    lower.includes("infinitude of primes") ||
    lower.includes("prime numbers are infinite") ||
    lower.includes("euclid") ||
    lower.includes("евклид") ||
    (lower.includes("прост") && lower.includes("бесконеч")) ||
    lower.includes("अनंत अभाज्य") ||
    lower.includes("अनन्त अभाज्य") ||
    lower.includes("अभाज्य संख्याएँ अनंत") ||
    lower.includes("अभाज्य संख्याएं अनंत") ||
    lower.includes("अभाज्य संख्याएँ अनन्त") ||
    lower.includes("अभाज्य संख्याएं अनन्त") ||
    lower.includes("无穷多素数") ||
    lower.includes("无穷多个素数") ||
    lower.includes("素数有无穷") ||
    lower.includes("素数无穷") ||
    lower.includes("無窮多素數") ||
    lower.includes("素數有無窮") ||
    lower.includes("素數無窮") ||
    lower.includes("欧几里得")
  );
}

function euclidPrimeProofBody(language) {
  if (language === "ru") {
    return [
      "Как я понял запрос: трактуем запрос как формальное утверждение «Простых чисел бесконечно много.» и доказываем методом «от противного» в relative-meta-logic.",
      "",
      "Доказательство (метод: от противного).",
      "",
      "Утверждение: Простых чисел бесконечно много.",
      "1. Работаем в элементарной теории чисел, формализуемой в арифметике Пеано (PA): простое число — это целое число больше 1, положительные делители которого только 1 и оно само. В доказательстве используется теорема PA: у каждого целого числа больше 1 есть простой делитель; это формальный контекст для тактики от противного в relative-meta-logic.",
      "2. Предположим противное: простых чисел конечное число; обозначим их p₁, p₂, …, pₙ.",
      "3. Рассмотрим число N = p₁·p₂·…·pₙ + 1. Это целое число, большее единицы.",
      "4. По основной теореме арифметики у N есть простой делитель q. Если q = pᵢ для некоторого i, то pᵢ делит и p₁·p₂·…·pₙ, и N, а значит делит их разность, равную 1 — противоречие.",
      "5. Значит, q — простое число, не входящее в список p₁, …, pₙ, что противоречит предположению о полноте списка.",
      "",
      "Предположение несостоятельно, следовательно простых чисел бесконечно много. ∎",
    ].join("\n");
  }
  if (language === "hi") {
    return [
      "मैंने प्रश्न को कैसे समझा: प्रश्न को औपचारिक कथन \"अभाज्य संख्याएँ अनंत हैं।\" मानकर relative-meta-logic में \"विरोधाभास\" विधि से प्रमाणित कर रहे हैं।",
      "",
      "प्रमाण (विधि: विरोधाभास)।",
      "",
      "कथन: अभाज्य संख्याएँ अनंत हैं।",
      "1. हम प्राथमिक संख्या-सिद्धांत में काम करते हैं, जिसे Peano arithmetic (PA) में औपचारिक किया जा सकता है: अभाज्य वह पूर्णांक है जो 1 से बड़ा है और जिसके धनात्मक भाजक केवल 1 और वही संख्या हैं। प्रमाण PA के इस प्रमेय का उपयोग करता है कि 1 से बड़े हर पूर्णांक का कोई अभाज्य भाजक होता है; यही relative-meta-logic की contradiction युक्ति का औपचारिक संदर्भ है।",
      "2. विरोधाभास हेतु मान लीजिए कि अभाज्य संख्याएँ केवल सीमित संख्या में हैं: p₁, p₂, …, pₙ।",
      "3. संख्या N = p₁·p₂·…·pₙ + 1 लीजिए। N एक से बड़ा पूर्णांक है।",
      "4. अंकगणित की मूल प्रमेय से N का कोई अभाज्य भाजक q है। यदि किसी i के लिए q = pᵢ हो, तो pᵢ संख्या p₁·p₂·…·pₙ और N दोनों को विभाजित करेगा, अर्थात उनका अंतर 1 भी विभाजित करेगा — असंभव।",
      "5. अतः q एक ऐसा अभाज्य है जो सूची p₁, …, pₙ में नहीं है, जो सूची के पूर्ण होने की परिकल्पना का खंडन करता है।",
      "",
      "अतः परिकल्पना असत्य है और अभाज्य संख्याएँ अनंत हैं। ∎",
    ].join("\n");
  }
  if (language === "zh") {
    return [
      "对问题的理解: 把问题视为形式命题“素数有无穷多个。”, 在 relative-meta-logic 中用“反证法”方法证明。",
      "",
      "证明 (方法: 反证法)。",
      "",
      "命题: 素数有无穷多个。",
      "1. 在可由 Peano arithmetic (PA) 形式化的初等数论中工作: 素数是大于 1 的整数, 其正因数只有 1 和自身。证明使用 PA 中的定理: 每个大于 1 的整数都有素因数; 这就是 relative-meta-logic 反证策略的形式上下文。",
      "2. 假设素数仅有有限多个, 记为 p₁、p₂、…、pₙ。",
      "3. 构造数 N = p₁·p₂·…·pₙ + 1。N 是大于 1 的整数。",
      "4. 由算术基本定理, N 有一个素因数 q。若 q = pᵢ, 则 pᵢ 同时整除 p₁·p₂·…·pₙ 与 N, 因而整除二者之差 1, 矛盾。",
      "5. 因此 q 是不在 p₁, …, pₙ 中的素数, 与假设矛盾。",
      "",
      "假设不成立, 故素数有无穷多个。∎",
    ].join("\n");
  }
  return [
    "How I interpreted the request: treating the request as the formal claim \"There are infinitely many prime numbers.\" and discharging it by contradiction inside relative-meta-logic.",
    "",
    "Proof (method: contradiction).",
    "",
    "Statement: There are infinitely many prime numbers.",
    "1. Work in elementary number theory, formalizable in Peano arithmetic (PA): a prime is an integer greater than 1 whose only positive divisors are 1 and itself. The proof uses the PA theorem that every integer greater than 1 has a prime divisor; this is the formal context for the relative-meta-logic contradiction tactic.",
    "2. Assume for contradiction that only finitely many primes exist; call them p₁, p₂, …, pₙ.",
    "3. Form the number N = p₁·p₂·…·pₙ + 1. Then N is an integer greater than 1.",
    "4. By the fundamental theorem of arithmetic, N has a prime divisor q. If q = pᵢ for some i, then pᵢ divides both p₁·p₂·…·pₙ and N, so pᵢ divides their difference, which is 1 — impossible.",
    "5. Hence q is a prime not in the list p₁, …, pₙ, contradicting the assumption that the list was complete.",
    "",
    "The assumption fails, so there are infinitely many primes. ∎",
  ].join("\n");
}

function genericProofPlanBody(prompt, language) {
  if (language === "ru") {
    return [
      "Как я понял запрос: утверждение нужно доказать, но для финального исполнения не хватает выбранной формальной системы.",
      "",
      "План доказательства (метод: формализация и проверка).",
      "",
      `Утверждение: ${String(prompt || "").trim()}`,
      "1. Зафиксировать систему аксиом, например PA для арифметики, ZFC для теории множеств или конкретную теорию предметной области.",
      "2. Перевести утверждение в закрытую формулу этой системы.",
      "3. Выбрать тактику relative-meta-logic: rewrite, induction, contradiction или поиск контрпримера.",
      "4. Проверить каждый шаг и вернуть либо сертификат доказательства, либо контрпример.",
      "",
      "Чтобы выполнить доказательство полностью, нужен явный набор аксиом и точная формулировка утверждения.",
    ].join("\n");
  }
  if (language === "hi") {
    return [
      "मैंने प्रश्न को कैसे समझा: यह प्रमाण का अनुरोध है, पर अंतिम निष्पादन के लिए चुनी हुई औपचारिक प्रणाली चाहिए।",
      "",
      "प्रमाण योजना (विधि: औपचारिकरण और सत्यापन)।",
      "",
      `कथन: ${String(prompt || "").trim()}`,
      "1. कोई अभिगृहीत प्रणाली चुनें, जैसे arithmetic के लिए PA, set theory के लिए ZFC, या किसी क्षेत्र-विशेष की theory।",
      "2. कथन को उस प्रणाली के बंद सूत्र में अनुवादित करें।",
      "3. relative-meta-logic की tactic चुनें: rewrite, induction, contradiction, या counterexample search।",
      "4. प्रत्येक चरण जाँचें और proof certificate या counterexample लौटाएँ।",
      "",
      "प्रमाण पूरा करने के लिए सटीक axiom set और closed statement चाहिए।",
    ].join("\n");
  }
  if (language === "zh") {
    return [
      "对问题的理解: 该提示要求证明, 但最终执行需要选定的形式系统。",
      "",
      "证明计划 (方法: 形式化与验证)。",
      "",
      `命题: ${String(prompt || "").trim()}`,
      "1. 固定一个公理系统, 例如 arithmetic 用 PA, set theory 用 ZFC, 或某个领域专用理论。",
      "2. 将命题翻译成该系统中的闭公式。",
      "3. 选择 relative-meta-logic 策略: rewrite、induction、contradiction 或 counterexample search。",
      "4. 检查每一步, 并返回证明证书或反例。",
      "",
      "要完成证明, 需要精确的 axiom set 和 closed statement。",
    ].join("\n");
  }
  return [
    "How I interpreted the request: the prompt asks for a proof, but final execution needs a chosen formal system.",
    "",
    "Proof plan (method: formalization and verification).",
    "",
    `Statement: ${String(prompt || "").trim()}`,
    "1. Fix an axiom system, for example PA for arithmetic, ZFC for set theory, or a domain-specific theory.",
    "2. Translate the claim into a closed formula in that system.",
    "3. Choose a relative-meta-logic tactic: rewrite, induction, contradiction, or counterexample search.",
    "4. Check each step and return either a proof certificate or a counterexample.",
    "",
    "To finish the proof, provide the exact axiom set and a closed statement.",
  ].join("\n");
}

function tryProofRequest(prompt, normalized, language) {
  if (!hasProofRequestShape(normalized)) return null;
  const claim = extractProofClaim(normalized);
  if (matchesEuclidPrimeClaim(claim)) {
    return {
      intent: "proof_request",
      content: euclidPrimeProofBody(language),
      confidence: 0.85,
      evidence: [
        "policy:proof_request",
        "pipeline:planned:relative-meta-logic",
        "proof_outcome:proven",
        "proof_method:contradiction",
        `language:${language}`,
      ],
    };
  }
  return {
    intent: "proof_request",
    content: genericProofPlanBody(prompt, language),
    confidence: 0.6,
    evidence: [
      "policy:proof_request",
      "pipeline:planned:relative-meta-logic",
      "proof_outcome:partial_plan",
      `language:${language}`,
    ],
  };
}

// WEEKDAY_CYCLE keeps only the rendering surfaces (display names + Russian
// case forms) used to phrase an answer. Issue #386: the *recognition* words
// (the former `aliases`, plus the next/previous/today/day/question markers)
// are no longer hardcoded here — they live as self-describing meanings in
// data/seed/meanings-calendar.lino under the `calendar_*` roles, embedded
// below in MEANINGS_LINO. The detection functions query the lexicon by role
// and map a matched weekday slug back to its cycle entry; mirrors
// src/solver_handlers/calendar.rs.
const WEEKDAY_CYCLE = [
  {
    slug: "monday",
    en: "Monday",
    ru: "понедельник",
    hi: "सोमवार",
    zh: "星期一",
    ruGenitive: "понедельника",
    ruInstrumental: "понедельником",
  },
  {
    slug: "tuesday",
    en: "Tuesday",
    ru: "вторник",
    hi: "मंगलवार",
    zh: "星期二",
    ruGenitive: "вторника",
    ruInstrumental: "вторником",
  },
  {
    slug: "wednesday",
    en: "Wednesday",
    ru: "среда",
    hi: "बुधवार",
    zh: "星期三",
    ruGenitive: "среды",
    ruInstrumental: "средой",
  },
  {
    slug: "thursday",
    en: "Thursday",
    ru: "четверг",
    hi: "गुरुवार",
    zh: "星期四",
    ruGenitive: "четверга",
    ruInstrumental: "четвергом",
  },
  {
    slug: "friday",
    en: "Friday",
    ru: "пятница",
    hi: "शुक्रवार",
    zh: "星期五",
    ruGenitive: "пятницы",
    ruInstrumental: "пятницей",
  },
  {
    slug: "saturday",
    en: "Saturday",
    ru: "суббота",
    hi: "शनिवार",
    zh: "星期六",
    ruGenitive: "субботы",
    ruInstrumental: "субботой",
  },
  {
    slug: "sunday",
    en: "Sunday",
    ru: "воскресенье",
    hi: "रविवार",
    zh: "星期日",
    ruGenitive: "воскресенья",
    ruInstrumental: "воскресеньем",
  },
];

function hasCalendarCjkCharacter(term) {
  return /[\u4e00-\u9fff]/u.test(term);
}

function isCalendarWordCharacter(character) {
  return /[\p{L}\p{N}_]/u.test(character);
}

function containsCalendarTerm(text, term) {
  if (hasCalendarCjkCharacter(term)) {
    return String(text || "").includes(term);
  }
  let index = String(text || "").indexOf(term);
  while (index !== -1) {
    const before = index > 0 ? Array.from(text.slice(0, index)).pop() : "";
    const after = Array.from(text.slice(index + term.length))[0] || "";
    if (
      (!before || !isCalendarWordCharacter(before)) &&
      (!after || !isCalendarWordCharacter(after))
    ) {
      return true;
    }
    index = text.indexOf(term, index + term.length);
  }
  return false;
}

// Issue #386: calendar recognition is driven entirely by the self-describing
// `calendar_*` meanings (see data/seed/meanings-calendar.lino, embedded in
// MEANINGS_LINO). day-reference / today / weekday words match with the
// boundary-aware containsCalendarTerm; direction and question words match as
// loose substrings (parity with raw `str::contains` in calendar.rs). The
// boundary vs. substring split per role mirrors the Rust handler exactly.
function mentionsWeekdayContext(normalized) {
  return wordsForRole(ROLE_CALENDAR_DAY_REFERENCE).some((word) =>
    containsCalendarTerm(normalized, word),
  );
}

function mentionsCurrentDayQuestion(normalized) {
  const mentionsToday = wordsForRole(ROLE_CALENDAR_TODAY).some((word) =>
    containsCalendarTerm(normalized, word),
  );
  if (!mentionsToday) return false;
  const asksForDay = wordsForRole(ROLE_CALENDAR_DAY_REFERENCE).some((word) =>
    containsCalendarTerm(normalized, word),
  );
  const questionLike = wordsForRole(ROLE_CALENDAR_QUESTION).some((word) =>
    normalized.includes(word),
  );
  return asksForDay && questionLike;
}

function detectWeekdayOperation(normalized) {
  const hasNext = wordsForRole(ROLE_CALENDAR_DIRECTION_NEXT).some((marker) =>
    normalized.includes(marker),
  );
  const hasPrevious = wordsForRole(ROLE_CALENDAR_DIRECTION_PREVIOUS).some(
    (marker) => normalized.includes(marker),
  );
  if (hasNext && !hasPrevious) return "next";
  if (hasPrevious && !hasNext) return "previous";
  return null;
}

function detectWeekday(normalized) {
  for (const meaning of meaningsWithRole(ROLE_CALENDAR_WEEKDAY)) {
    if (meaning.words.some((word) => containsCalendarTerm(normalized, word))) {
      const entry = WEEKDAY_CYCLE.find((weekday) => weekday.slug === meaning.slug);
      if (entry) return entry;
    }
  }
  return null;
}

function shiftWeekday(weekday, operation) {
  const index = WEEKDAY_CYCLE.indexOf(weekday);
  const offset = operation === "next" ? 1 : -1;
  return WEEKDAY_CYCLE[(index + offset + WEEKDAY_CYCLE.length) % WEEKDAY_CYCLE.length];
}

function validCalendarTimeZone(candidate) {
  const timeZone = cleanContextValue(candidate);
  if (!timeZone) return "";
  try {
    new Intl.DateTimeFormat("en-US", { timeZone }).format(new Date(0));
    return timeZone;
  } catch (_error) {
    return "";
  }
}

function resolvedCalendarTimeZone(userContext) {
  const fromContext = validCalendarTimeZone(userContext && userContext.timeZone);
  if (fromContext) return fromContext;
  try {
    return Intl.DateTimeFormat().resolvedOptions().timeZone || "";
  } catch (_error) {
    return "";
  }
}

function calendarDateInTimeZone(date, timeZone) {
  const options = {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  };
  if (timeZone) options.timeZone = timeZone;
  const parts = new Intl.DateTimeFormat("en-CA", options).formatToParts(date);
  const value = (type) => parts.find((part) => part.type === type)?.value || "";
  const year = Number(value("year"));
  const month = Number(value("month"));
  const day = Number(value("day"));
  if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) {
    return null;
  }
  const iso = `${String(year).padStart(4, "0")}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
  const dayIndex = new Date(Date.UTC(year, month - 1, day)).getUTCDay();
  const weekday = WEEKDAY_CYCLE[(dayIndex + 6) % 7];
  return { iso, weekday };
}

function currentCalendarDate(userContext) {
  const reference = new Date();
  const timeZone = resolvedCalendarTimeZone(userContext);
  return {
    timeZone: timeZone || "local",
    date: calendarDateInTimeZone(reference, timeZone),
  };
}

function renderCurrentDay(language, weekday, isoDate, timeZone) {
  if (language === "ru") {
    return `Сегодня ${weekday.ru}, ${isoDate} (${timeZone}).`;
  }
  if (language === "hi") {
    return `आज ${weekday.hi} है, ${isoDate} (${timeZone}).`;
  }
  if (language === "zh") {
    return `今天是${weekday.zh},${isoDate}(${timeZone})。`;
  }
  return `Today is ${weekday.en}, ${isoDate} (${timeZone}).`;
}

function renderWeekdayRelation(language, operation, source, result) {
  const delta = operation === "next" ? "+1" : "-1";
  if (language === "ru") {
    if (operation === "next") {
      return `После ${source.ruGenitive} наступает ${result.ru}. Я сдвинул ${source.ru} на ${delta} в семидневном календарном цикле.`;
    }
    return `Перед ${source.ruInstrumental} идёт ${result.ru}. Я сдвинул ${source.ru} на ${delta} в семидневном календарном цикле.`;
  }
  if (language === "hi") {
    if (operation === "next") {
      return `${source.hi} के बाद ${result.hi} आता है। मैं सात दिनों के कैलेंडर चक्र में ${source.hi} को ${delta} दिन सरकाता हूँ।`;
    }
    return `${source.hi} से पहले ${result.hi} आता है। मैं सात दिनों के कैलेंडर चक्र में ${source.hi} को ${delta} दिन सरकाता हूँ।`;
  }
  if (language === "zh") {
    if (operation === "next") {
      return `${source.zh}之后是${result.zh}。我在七天的日历循环中将${source.zh}移动${delta}天。`;
    }
    return `${source.zh}之前是${result.zh}。我在七天的日历循环中将${source.zh}移动${delta}天。`;
  }
  if (operation === "next") {
    return `The day after ${source.en} is ${result.en}. I move ${source.en} by ${delta} in the seven-day calendar cycle.`;
  }
  return `The day before ${source.en} is ${result.en}. I move ${source.en} by ${delta} in the seven-day calendar cycle.`;
}

function tryCalendarReasoning(prompt, normalized, userContext = {}) {
  if (mentionsCurrentDayQuestion(normalized)) {
    const language = detectLanguage(prompt);
    const resolved = currentCalendarDate(userContext);
    if (!resolved.date) return null;
    return {
      intent: "calendar_current_day",
      content: renderCurrentDay(
        language,
        resolved.date.weekday,
        resolved.date.iso,
        resolved.timeZone,
      ),
      confidence: 1.0,
      evidence: [
        "calendar:clock:browser",
        `calendar:today:${resolved.date.iso}`,
        `calendar:weekday:${resolved.date.weekday.slug}`,
        `calendar:time_zone:${resolved.timeZone}`,
        `language:${language}`,
      ],
    };
  }
  if (!mentionsWeekdayContext(normalized)) return null;
  const operation = detectWeekdayOperation(normalized);
  if (!operation) return null;
  const source = detectWeekday(normalized);
  if (!source) return null;
  const result = shiftWeekday(source, operation);
  const language = detectLanguage(prompt);
  return {
    intent: "calendar_weekday_relation",
    content: renderWeekdayRelation(language, operation, source, result),
    confidence: 1.0,
    evidence: [
      "calendar:cycle:monday,tuesday,wednesday,thursday,friday,saturday,sunday",
      `calendar:subject_weekday:${source.slug}`,
      `calendar:operation:${operation}:${source.slug}`,
      `calendar:result_weekday:${result.slug}`,
      `language:${language}`,
    ],
  };
}

function renderConceptInContext(language, context, record) {
  const contextNormalized = normalizeConceptTerm(context);
  const contextRecord = resolveContextRecord(contextNormalized);
  const contextLabel =
    (contextRecord && contextLabelFor(contextRecord, language)) || context;
  const sameAsLabel =
    String(contextLabel).trim().toLowerCase() ===
    String(context).trim().toLowerCase();
  const intentVariant = sameAsLabel
    ? "concept_lookup_in_context_no_alias"
    : "concept_lookup_in_context";
  const variantTable = MULTILINGUAL_ANSWERS[intentVariant] || {};
  const baseTable = MULTILINGUAL_ANSWERS.concept_lookup_in_context || {};
  const templateEntry =
    variantTable[language] ||
    variantTable.en ||
    baseTable[language] ||
    baseTable.en ||
    null;
  const template = templateEntry
    ? (typeof templateEntry === "string" ? templateEntry : templateEntry.text)
    : "In the context of {context} ({context_label}), {term} ({category}) means: {summary}\n\nSource: {source} ({source_kind}).";
  const localized = localizedConceptFor(record, language);
  const term = (localized && localized.term) || record.term;
  const summary = (localized && localized.summary) || record.summary;
  const source = (localized && localized.source) || record.source;
  const sourceKind =
    (localized && localized.sourceKind) || record.sourceKind;
  const sourceMarkup = renderSourceLink(source);
  return template
    .replace(/\{context_label\}/g, contextLabel)
    .replace(/\{context\}/g, context)
    .replace(/\{term\}/g, term)
    .replace(/\{category\}/g, record.category)
    .replace(/\{summary\}/g, summary)
    .replace(/\{source\}/g, sourceMarkup)
    .replace(/\{source_kind\}/g, sourceKind);
}

function renderConceptPlain(language, record) {
  const localized = localizedConceptFor(record, language);
  const term = (localized && localized.term) || record.term;
  const summary = (localized && localized.summary) || record.summary;
  const source = (localized && localized.source) || record.source;
  const sourceKind =
    (localized && localized.sourceKind) || record.sourceKind;
  const sourceMarkup = renderSourceLink(source);
  return `${term} (${record.category}): ${summary}\n\nSource: ${sourceMarkup} (${sourceKind}).`;
}

function tryConceptLookup(prompt) {
  const query = extractConceptQuery(prompt);
  if (!query) return null;
  const evidence = [`concept_lookup:request:${query.term}`];
  if (query.context) {
    evidence.push(`concept_lookup:context:${query.context}`);
  }
  const lookup = lookupConceptQuery(query);
  if (!lookup) {
    // Surface the miss in evidence so the demo's trace panel can show why
    // the handler declined the prompt. Returning null lets later handlers
    // (Wikipedia lookup, fallback) still get a chance.
    return null;
  }
  const record = lookup.record;
  const language = detectLanguage(prompt);
  const localized = localizedConceptFor(record, language);
  const effectiveSource = (localized && localized.source) || record.source;
  // Issue #21: emit the percent-decoded IRI form for the trace panel.
  const humanSource = humanizeUrl(effectiveSource);
  evidence.push(`concept_lookup:hit:${record.slug}`);
  evidence.push(`source:${humanSource}`);
  if (record.wikidata) {
    evidence.push(`wikidata:${record.wikidata}`);
  }
  if (lookup.contextMatch && lookup.context) {
    evidence.push(`concept_lookup:context-match:${lookup.context}`);
    const body = renderConceptInContext(language, lookup.context, record);
    return {
      intent: "concept_lookup_in_context",
      content: body,
      confidence: 0.9,
      evidence,
    };
  }
  if (lookup.context) {
    evidence.push(`concept_lookup:context-mismatch:${lookup.context}`);
  }
  const body = renderConceptPlain(language, record);
  return {
    intent: "concept_lookup",
    content: body,
    confidence: 0.9,
    evidence,
  };
}

function extractDefinitionMergeTerm(prompt, allowPlainConcept) {
  // The intent is two meanings together: a definition_merge_action ("merge",
  // "combine", "fuse", …) applied to a definition_artifact_request
  // ("definition", "translation", "wikipedia", …). Both are matched as raw
  // substrings of the normalized prompt, so inflected forms in every supported
  // language are caught with no per-word list in code. Mirrors
  // extract_definition_merge_term in src/solver_handlers/definition_merge.rs.
  const text = String(prompt || "");
  const normalized = normalizePrompt(text);
  const asksMerge = lexiconMentionsRoleSubstring(ROLE_DEFINITION_MERGE_ACTION, normalized);
  const asksDefinition = lexiconMentionsRoleSubstring(
    ROLE_DEFINITION_ARTIFACT_REQUEST,
    normalized,
  );
  if (!asksMerge || !asksDefinition) {
    if (allowPlainConcept) {
      const query = extractConceptQuery(text);
      if (query && !query.context) return query.term;
    }
    return null;
  }

  // The introducing phrases ("definitions of", "translation for", …) are
  // definition_merge_marker prefix word forms; the literal before each slot
  // marker is the phrase to locate. They are declared in the lexicon in the
  // original priority order, so the first prefix that appears in the prompt
  // wins and the text after it becomes the term.
  const lower = text.toLowerCase();
  for (const form of roleWordForms(ROLE_DEFINITION_MERGE_MARKER)) {
    if (form.slot !== "prefix") continue;
    const marker = form.before;
    const index = lower.indexOf(marker);
    if (index < 0) continue;
    const candidate = trimDefinitionMergeTail(text.slice(index + marker.length));
    if (candidate) return candidate.toLowerCase();
  }
  const query = extractConceptQuery(text);
  return query ? query.term : null;
}

function trimDefinitionMergeTail(value) {
  // The boundary words that end the term ("from", "using", "with", …) are
  // definition_merge_tail_boundary meanings; we reconstruct each as a
  // space-padded token and cut at the earliest one we find. Only the English
  // surface forms are consulted here: this is an English-frame heuristic, and
  // the term itself may be in any language (e.g. the Russian preposition "в" is
  // part of the term "реклама в Telegram", not a boundary). The other languages
  // remain in the seed so the meaning stays fully self-describing. The quote and
  // punctuation trim sets are typographic and stay in code. Mirrors
  // trim_definition_merge_tail in src/solver_handlers/definition_merge.rs.
  const text = String(value || "");
  const lower = text.toLowerCase();
  let end = text.length;
  for (const word of wordsForRoleInLanguages(ROLE_DEFINITION_MERGE_TAIL_BOUNDARY, ["en"])) {
    const index = lower.indexOf(` ${word} `);
    if (index >= 0) end = Math.min(end, index);
  }
  return text
    .slice(0, end)
    .trim()
    .replace(/^['"`“”«»]+|['"`“”«»]+$/g, "")
    .replace(/[?。.!,;:]+$/g, "")
    .trim();
}

function inferredSourceLanguage(source) {
  const value = String(source || "");
  if (value.includes("://ru.wikipedia.org/")) return "ru";
  if (value.includes("://hi.wikipedia.org/")) return "hi";
  if (value.includes("://zh.wikipedia.org/")) return "zh";
  return "en";
}

function normalizeDefinitionFact(value) {
  return String(value || "")
    .toLocaleLowerCase()
    .replace(/[^\p{L}\p{N}]+/gu, "");
}

function pushDefinitionFragment(fragments, language, summary, source, sourceKind) {
  const cleanSummary = String(summary || "").trim();
  if (!cleanSummary) return;
  const duplicate = fragments.some(
    (fragment) =>
      fragment.language === language &&
      normalizeDefinitionFact(fragment.summary) === normalizeDefinitionFact(cleanSummary),
  );
  if (duplicate) return;
  fragments.push({
    language: String(language || "en"),
    summary: cleanSummary,
    source: String(source || "").trim(),
    sourceKind: String(sourceKind || "").trim(),
  });
}

function definitionFragments(record) {
  const fragments = [];
  pushDefinitionFragment(
    fragments,
    inferredSourceLanguage(record && record.source),
    record && record.summary,
    record && record.source,
    record && record.sourceKind,
  );
  for (const localized of Array.isArray(record && record.localized) ? record.localized : []) {
    pushDefinitionFragment(
      fragments,
      localized && localized.language,
      localized && localized.summary,
      localized && localized.source,
      localized && localized.sourceKind,
    );
  }
  return fragments;
}

function sourceLanguages(fragments) {
  const languages = [];
  for (const fragment of fragments) {
    if (!languages.includes(fragment.language)) languages.push(fragment.language);
  }
  return languages;
}

function sourceUrls(fragments) {
  const sources = [];
  for (const fragment of fragments) {
    if (!fragment.source || sources.includes(fragment.source)) continue;
    sources.push(fragment.source);
  }
  return sources;
}

function splitDefinitionSentences(summary) {
  const sentences = [];
  let current = "";
  for (const character of String(summary || "")) {
    current += character;
    if ([".", "!", "?", "।", "。"].includes(character)) {
      const sentence = current.trim();
      if (sentence) sentences.push(sentence);
      current = "";
    }
  }
  const tail = current.trim();
  if (tail) sentences.push(tail);
  return sentences;
}

function mergedDefinitionFacts(fragments) {
  const facts = [];
  const seen = new Set();
  for (const fragment of fragments) {
    for (const sentence of splitDefinitionSentences(fragment.summary)) {
      const key = normalizeDefinitionFact(sentence);
      if (!key || seen.has(key)) continue;
      seen.add(key);
      facts.push({ language: fragment.language, text: sentence });
    }
  }
  return facts;
}

function uniqueSourceFragments(fragments) {
  const unique = [];
  const seen = new Set();
  for (const fragment of fragments) {
    if (!fragment.source) continue;
    const key = `${fragment.language}\n${fragment.source}`;
    if (seen.has(key)) continue;
    seen.add(key);
    unique.push(fragment);
  }
  return unique;
}

function renderDefinitionMerge(record, fragments, facts) {
  const english = localizedConceptFor(record, "en");
  const displayTerm = (english && english.term) || record.term;
  const anchor = record.wikidata ? ` [${record.wikidata}]` : "";
  const lines = [
    `Merged definition of ${displayTerm}${anchor}`,
    `Source languages: ${sourceLanguages(fragments).join(", ")}`,
    "",
    "Facts:",
  ];
  for (const fact of facts) {
    lines.push(`- [${fact.language}] ${fact.text}`);
  }
  lines.push("Sources:");
  for (const fragment of uniqueSourceFragments(fragments)) {
    lines.push(
      `- [${fragment.language}] ${renderSourceLink(fragment.source)} (${fragment.sourceKind})`,
    );
  }
  return lines.join("\n");
}

function tryDefinitionMerge(prompt, options) {
  const opts = options || {};
  const term = extractDefinitionMergeTerm(prompt, Boolean(opts.allowPlainConcept));
  if (!term) return null;
  const evidence = [`definition_merge:request:${term}`];
  if (opts.allowPlainConcept) evidence.push("definition_merge:mode:auto");
  const lookup = lookupConceptQuery({ term, context: null });
  if (!lookup) return null;
  const record = lookup.record;
  const fragments = definitionFragments(record);
  if (fragments.length === 0) return null;
  evidence.push(`definition_merge:hit:${record.slug}`);
  if (record.wikidata) evidence.push(`wikidata:${record.wikidata}`);
  for (const language of sourceLanguages(fragments)) {
    evidence.push(`definition_merge:language:${language}`);
  }
  for (const source of sourceUrls(fragments)) {
    evidence.push(`source:${humanizeUrl(source)}`);
  }
  const facts = mergedDefinitionFacts(fragments);
  evidence.push(`definition_merge:facts:${facts.length}`);
  return {
    intent: "definition_merge",
    content: renderDefinitionMerge(record, fragments, facts),
    confidence: 0.9,
    evidence,
  };
}

// Known person name corrections for typo suggestions. Each entry maps a
// canonical name to a list of common misspellings (all lowercase).
const KNOWN_PERSON_VARIANTS = [
  { canonical: "Elon Musk", variants: ["elon musk", "elon mask", "elon muск"] },
  { canonical: "Donald Trump", variants: ["donald trump", "donald tramp", "donald tromp"] },
  { canonical: "Joe Biden", variants: ["joe biden", "joe bidan", "joe bidon"] },
  { canonical: "Barack Obama", variants: ["barack obama", "barak obama", "barrack obama"] },
  { canonical: "Vladimir Putin", variants: ["vladimir putin", "vladimir puting", "vladmir putin"] },
  { canonical: "Albert Einstein", variants: ["albert einstein", "albert einstien", "albert enstien"] },
  { canonical: "Isaac Newton", variants: ["isaac newton", "isaak newton", "issac newton"] },
  { canonical: "Nikola Tesla", variants: ["nikola tesla", "nicolas tesla", "nikolai tesla"] },
];

function editDistance(a, b) {
  const left = Array.from(String(a || ""));
  const right = Array.from(String(b || ""));
  const m = left.length, n = right.length;
  const dp = Array.from({ length: m + 1 }, (_, i) =>
    Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0))
  );
  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      dp[i][j] = left[i - 1] === right[j - 1]
        ? dp[i - 1][j - 1]
        : 1 + Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]);
      if (
        i > 1 &&
        j > 1 &&
        left[i - 1] === right[j - 2] &&
        left[i - 2] === right[j - 1]
      ) {
        dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + 1);
      }
    }
  }
  return dp[m][n];
}

function isCloseTokenTypo(actual, expected) {
  const left = String(actual || "").toLowerCase();
  const right = String(expected || "").toLowerCase();
  const leftLength = Array.from(left).length;
  const rightLength = Array.from(right).length;
  return Math.min(leftLength, rightLength) >= 4 && editDistance(left, right) === 1;
}

function leadingTokenSpans(value, limit) {
  const text = String(value || "");
  const spans = [];
  const pattern = /\S+/gu;
  let match;
  while ((match = pattern.exec(text)) !== null && spans.length < limit) {
    spans.push({
      start: match.index,
      end: match.index + match[0].length,
      text: match[0],
    });
  }
  return spans;
}

function fuzzyPrefixMatch(value, prefix) {
  const words = String(prefix || "").trim().split(/\s+/u).filter(Boolean);
  if (words.length === 0) return null;
  const spans = leadingTokenSpans(value, words.length);
  if (spans.length !== words.length) return null;
  let typoCount = 0;
  for (let i = 0; i < words.length; i += 1) {
    const actual = spans[i].text;
    const expected = words[i];
    if (actual.toLowerCase() === expected.toLowerCase()) continue;
    if (!isCloseTokenTypo(actual, expected)) return null;
    typoCount += 1;
  }
  if (typoCount !== 1) return null;
  const end = spans[spans.length - 1].end;
  return {
    typoCount,
    end,
    interpretation: {
      original: String(value || "").slice(0, end),
      corrected: String(prefix || "").trim(),
    },
  };
}

function stripKnownPrefix(value, prefixes) {
  const text = String(value || "");
  const lower = text.toLowerCase();
  for (const prefix of prefixes) {
    if (lower.startsWith(prefix)) {
      return { value: text.slice(prefix.length).trimStart(), interpretation: null };
    }
  }
  const matches = prefixes
    .map((prefix) => fuzzyPrefixMatch(text, prefix))
    .filter(Boolean)
    .sort((left, right) =>
      left.typoCount - right.typoCount || right.end - left.end,
    );
  const best = matches[0];
  if (!best) return null;
  const next = matches[1];
  if (next && next.typoCount === best.typoCount && next.end === best.end) {
    return null;
  }
  return {
    value: text.slice(best.end).trimStart(),
    interpretation: best.interpretation,
  };
}

function suggestNameCorrection(term) {
  const lower = term.toLowerCase();
  for (const { canonical, variants } of KNOWN_PERSON_VARIANTS) {
    if (variants.includes(lower)) return canonical;
  }
  for (const { canonical, variants } of KNOWN_PERSON_VARIANTS) {
    const canonicalLower = canonical.toLowerCase();
    if (
      variants.some((v) => editDistance(lower, v) === 1) ||
      editDistance(lower, canonicalLower) === 1
    ) {
      return canonical;
    }
  }
  return null;
}

function isWhoIsPrompt(normalized) {
  // "who is …" detection reasons over the who_question meaning: a language
  // whose marker leads the name occupies the who_question_lead prefix slot
  // (English who is …, Russian кто такой …), while one whose marker trails it
  // occupies the who_question_tail suffix slot (Hindi … कौन है, Chinese …是谁).
  return (
    prefixLiterals(ROLE_WHO_QUESTION_LEAD).some((lead) => normalized.startsWith(lead)) ||
    suffixLiterals(ROLE_WHO_QUESTION_TAIL).some((tail) => normalized.endsWith(tail))
  );
}

function tryWhoIsQuestion(prompt) {
  const normalized = prompt.toLowerCase().trim();
  if (!isWhoIsPrompt(normalized)) return null;
  const query = extractConceptQuery(prompt);
  if (!query) return null;
  const term = query.term;
  const suggestion = suggestNameCorrection(term);
  const content = suggestion
    ? `I don't have a Links Notation fact for "${term}" yet. Did you mean "${suggestion}"? Add a fact or rule in Links Notation and run the request again.`
    : `I don't have a Links Notation fact for "${term}" yet. Add a fact or rule in Links Notation and run the request again.`;
  return {
    intent: "who_is_question",
    content,
    confidence: 0.5,
    evidence: [`concept_lookup:miss:${term}`, "response:who_is_question"],
  };
}

// Wikipedia REST summary endpoint per language. Browser-friendly: CORS is
// enabled by Wikimedia for these summary endpoints, so the worker can fetch
// without a proxy from GitHub Pages.
const WIKIPEDIA_HOSTS = {
  en: "https://en.wikipedia.org/api/rest_v1/page/summary",
  ru: "https://ru.wikipedia.org/api/rest_v1/page/summary",
  hi: "https://hi.wikipedia.org/api/rest_v1/page/summary",
  zh: "https://zh.wikipedia.org/api/rest_v1/page/summary",
};

// Wikipedia full-text page search endpoint per language (CORS-enabled). Returns
// ranked page results matching a free-text query — more effective than the
// title-only search for context-aware disambiguation because the ranker scores
// body content, not just the title.
const WIKIPEDIA_SEARCH_HOSTS = {
  en: "https://en.wikipedia.org/w/rest.php/v1/search/page",
  ru: "https://ru.wikipedia.org/w/rest.php/v1/search/page",
  hi: "https://hi.wikipedia.org/w/rest.php/v1/search/page",
  zh: "https://zh.wikipedia.org/w/rest.php/v1/search/page",
};

const WIKIPEDIA_ACTION_API_HOSTS = {
  en: "https://en.wikipedia.org/w/api.php",
  ru: "https://ru.wikipedia.org/w/api.php",
  hi: "https://hi.wikipedia.org/w/api.php",
  zh: "https://zh.wikipedia.org/w/api.php",
};

const WIKTIONARY_SEARCH_HOSTS = {
  en: "https://en.wiktionary.org/w/api.php",
  ru: "https://ru.wiktionary.org/w/api.php",
  hi: "https://hi.wiktionary.org/w/api.php",
  zh: "https://zh.wiktionary.org/w/api.php",
};

function wikipediaHostsFor(language) {
  // Try the detected language first, then fall back to English so a Russian
  // query for an English-only article still returns a definition.
  const ordered = [language, "en"].filter(
    (value, index, array) => value && array.indexOf(value) === index,
  );
  return ordered.map((lang) => ({
    language: lang,
    url: WIKIPEDIA_HOSTS[lang] || WIKIPEDIA_HOSTS.en,
  }));
}

function capitalizeWords(term) {
  return term
    .split(/(\s+)/)
    .map((part) =>
      /\S/.test(part) ? part.charAt(0).toUpperCase() + part.slice(1) : part,
    )
    .join("");
}

function wikipediaTermVariants(term) {
  const seen = new Set();
  const variants = [];
  const push = (value) => {
    if (!value) return;
    const slug = String(value)
      .trim()
      .replace(/\s+/g, "_")
      .replace(/_+/g, "_");
    if (!slug || seen.has(slug)) return;
    seen.add(slug);
    variants.push(slug);
  };
  const trimmed = String(term || "").trim();
  push(trimmed);
  push(capitalizeWords(trimmed));
  push(capitalizeWords(trimmed.toLowerCase()));
  push(trimmed.toLowerCase());
  // Biography titles on Wikipedia (notably ru.wikipedia.org) use the
  // "Surname, Given names" form: querying "Илон Маск" 404s, but "Маск, Илон"
  // resolves. For two-word terms try the swap in both original and
  // capitalized casing so other language hosts can match too.
  const words = trimmed.split(/\s+/).filter(Boolean);
  if (words.length === 2) {
    const swapped = `${words[1]}, ${words[0]}`;
    push(swapped);
    push(capitalizeWords(swapped.toLowerCase()));
  }
  return variants;
}

function normalizeLookupText(value) {
  return String(value || "")
    .normalize("NFKD")
    .toLowerCase()
    .replace(/\p{M}/gu, "")
    .replace(/[^\p{L}\p{N}]+/gu, " ")
    .trim();
}

function compactLookupText(value) {
  return normalizeLookupText(value).replace(/\s+/g, "");
}

function boundedEditDistance(left, right, limit) {
  if (Math.abs(left.length - right.length) > limit) return limit + 1;
  let previous = Array.from({ length: right.length + 1 }, (_, index) => index);
  for (let i = 1; i <= left.length; i += 1) {
    const current = [i];
    let rowMin = current[0];
    for (let j = 1; j <= right.length; j += 1) {
      const cost = left[i - 1] === right[j - 1] ? 0 : 1;
      const next = Math.min(
        previous[j] + 1,
        current[j - 1] + 1,
        previous[j - 1] + cost,
      );
      current[j] = next;
      rowMin = Math.min(rowMin, next);
    }
    if (rowMin > limit) return limit + 1;
    previous = current;
  }
  return previous[right.length];
}

function isNearLookupText(left, right) {
  const a = compactLookupText(left);
  const b = compactLookupText(right);
  if (!a || !b) return false;
  const maxLength = Math.max(a.length, b.length);
  const limit = maxLength <= 8 ? 1 : 2;
  return boundedEditDistance(a, b, limit) <= limit;
}

function isPlausibleWikipediaSearchMatch(summary, term) {
  if (
    !summary ||
    (summary.matchKind !== "search" && summary.matchKind !== "context_search")
  ) {
    return true;
  }
  const termNormalized = normalizeLookupText(term);
  if (!termNormalized) return true;
  const termTokens = termNormalized.split(/\s+/).filter(Boolean);
  const candidates = [
    summary.title,
    summary.matchedTitle,
    String(summary.matchedSlug || "").replace(/_/g, " "),
    summary.extract,
  ];
  for (const candidate of candidates) {
    const normalized = normalizeLookupText(candidate);
    if (!normalized) continue;
    if (normalized === termNormalized) return true;
    const candidateTokens = new Set(normalized.split(/\s+/).filter(Boolean));
    if (
      termTokens.length > 0 &&
      termTokens.every((token) => candidateTokens.has(token))
    ) {
      return true;
    }
    if (isNearLookupText(termNormalized, normalized)) return true;
  }
  return false;
}

const LOOKUP_STEM_STOPWORDS = new Set([
  "a",
  "an",
  "and",
  "for",
  "in",
  "of",
  "on",
  "the",
  "to",
  "about",
  "sentence",
  "sentences",
  "в",
  "во",
  "и",
  "или",
  "на",
  "о",
  "об",
  "про",
]);

function hasSharedLookupStem(summary, term) {
  const normalizedTerm = normalizeLookupText(term);
  if (!normalizedTerm) return false;
  const content = normalizeLookupText(
    [
      summary && summary.title,
      summary && summary.matchedTitle,
      summary && String(summary.matchedSlug || "").replace(/_/g, " "),
      summary && summary.extract,
    ]
      .filter(Boolean)
      .join(" "),
  );
  if (!content) return false;
  const contentTokens = content.split(/\s+/).filter(Boolean);
  for (const token of normalizedTerm.split(/\s+/).filter(Boolean)) {
    if (LOOKUP_STEM_STOPWORDS.has(token) || token.length < 7) continue;
    const stemLength = Math.min(8, token.length - 2);
    const stem = token.slice(0, stemLength);
    if (stem.length >= 5 && contentTokens.some((candidate) => candidate.startsWith(stem))) {
      return true;
    }
  }
  return false;
}

function isArticleQuestionWikipediaMatch(summary, query) {
  if (!summary) return false;
  if (summary.matchKind === "direct") return true;
  if (isPlausibleWikipediaSearchMatch(summary, query.exactTerm)) return true;
  if (query.lookupTerm !== query.exactTerm && isPlausibleWikipediaSearchMatch(summary, query.lookupTerm)) {
    return true;
  }
  if (!hasSharedLookupStem(summary, query.lookupTerm || query.exactTerm)) {
    return false;
  }
  return !query.contextOriginal || hasSharedLookupStem(summary, query.contextOriginal);
}

// Resolve a context-qualified term to a Wikipedia page slug via full-text page
// search. Tries multiple query formulations (uppercase term, mixed case) on the
// detected language host then on English, returning the first match found.
// This helps disambiguate short acronyms like "KISS" or "DRY" when the user
// provides a programming/domain context.
async function searchWikipediaSlug(term, context, language) {
  if (typeof fetch !== "function") return null;
  const apiHeaders = {
    accept: "application/json",
    "api-user-agent":
      "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
  };
  const upper = term.toUpperCase();
  // Build candidate queries in preference order: uppercase term with context is
  // most discriminating; plain term with context is the fallback.
  const queries = [];
  if (upper !== term) queries.push(`${upper} ${context}`.trim());
  queries.push(`${term} ${context}`.trim());
  const ordered = [language, "en"].filter(
    (value, index, array) => value && array.indexOf(value) === index,
  );
  for (const lang of ordered) {
    const base = WIKIPEDIA_SEARCH_HOSTS[lang] || WIKIPEDIA_SEARCH_HOSTS.en;
    for (const query of queries) {
      const url = `${base}?q=${encodeURIComponent(query)}&limit=5`;
      try {
        const response = await fetch(url, { headers: apiHeaders });
        if (!response || !response.ok) continue;
        const data = await response.json();
        if (!data || !Array.isArray(data.pages) || data.pages.length === 0)
          continue;
        // Return the key of the top result; callers will fetch the full summary.
        const page = data.pages[0];
        return {
          slug: page.key,
          title: page.title || page.key,
          language: lang,
          query,
        };
      } catch (_error) {
        // Ignore and try next query / language host.
      }
    }
  }
  return null;
}

function decodeHtmlEntities(value) {
  const named = {
    amp: "&",
    apos: "'",
    mdash: "—",
    ndash: "–",
    gt: ">",
    lt: "<",
    nbsp: " ",
    quot: '"',
  };
  return String(value || "")
    .replace(/&#x([0-9a-f]+);/giu, (_match, code) => {
      const parsed = Number.parseInt(code, 16);
      return Number.isFinite(parsed) ? String.fromCodePoint(parsed) : "";
    })
    .replace(/&#(\d+);/gu, (_match, code) => {
      const parsed = Number.parseInt(code, 10);
      return Number.isFinite(parsed) ? String.fromCodePoint(parsed) : "";
    })
    .replace(/&([a-z]+);/giu, (match, name) => named[name.toLowerCase()] || match);
}

function stripHtmlToText(html) {
  return decodeHtmlEntities(
    String(html || "")
      .replace(/<style\b[\s\S]*?<\/style>/giu, " ")
      .replace(/<script\b[\s\S]*?<\/script>/giu, " ")
      .replace(/<sup\b[\s\S]*?<\/sup>/giu, " ")
      .replace(/<[^>]+>/gu, " "),
  )
    .replace(/\s+([,.;:!?])/gu, "$1")
    .replace(/\s+/gu, " ")
    .trim();
}

function truncateDisambiguationHtml(html) {
  const text = String(html || "");
  let end = text.length;
  for (const marker of [
    /<h[1-6]\b[^>]*id=["'](?:См\._также|See_also|Примечания|References|Notes)["']/iu,
    /<div\b[^>]*id=["']disambig["']/iu,
  ]) {
    const match = marker.exec(text);
    if (match && match.index > 0) end = Math.min(end, match.index);
  }
  return text.slice(0, end);
}

function deduplicateTextList(values) {
  const out = [];
  const seen = new Set();
  for (const value of values) {
    const text = String(value || "").trim();
    if (!text) continue;
    const key = normalizeLookupText(text);
    if (!key || seen.has(key)) continue;
    seen.add(key);
    out.push(text);
  }
  return out;
}

function extractDisambiguationEntriesFromHtml(html) {
  const scoped = truncateDisambiguationHtml(html);
  const entries = [];
  const itemPattern = /<li\b[^>]*>([\s\S]*?)<\/li>/giu;
  let match;
  while ((match = itemPattern.exec(scoped)) !== null) {
    const text = stripHtmlToText(match[1]);
    if (!text || text.startsWith("↑")) continue;
    entries.push(text);
  }
  return deduplicateTextList(entries).slice(0, 12);
}

function extractDisambiguationEntriesFromSummary(summary) {
  const title = normalizeLookupText(summary && summary.title);
  const raw = String((summary && summary.extract) || "");
  const extract = raw.replace(
    /^([^:\n]{1,80}):\s*([«»"'“”„]?[^\n]{1,80}[»"'“”„]?\s[—–-]\s)/u,
    "$1:\n$2",
  );
  const lines = extract
    .split(/\n+/u)
    .map((line) => line.trim())
    .filter(Boolean)
    .filter((line) => {
      const normalized = normalizeLookupText(line.replace(/:$/u, ""));
      return normalized && normalized !== title;
    });
  return deduplicateTextList(lines);
}

function definitionPrefixForDisambiguationEntry(entry) {
  const text = String(entry || "").trim();
  const dash = text.search(/\s[—–-]\s/u);
  if (dash <= 0) return "";
  return normalizeLookupText(
    text
      .slice(0, dash)
      .trim()
      .replace(/^[«»"'“”„]+|[«»"'“”„]+$/gu, ""),
  );
}

function isDefinitionStyleDisambiguation(summary, requestedTerm, entries) {
  const targets = [requestedTerm, summary && summary.title]
    .map((value) => normalizeLookupText(value))
    .filter(Boolean);
  if (targets.length === 0) return false;
  return entries.some((entry) => {
    const prefix = definitionPrefixForDisambiguationEntry(entry);
    return prefix && targets.includes(prefix);
  });
}

async function fetchWikipediaDisambiguationEntries(summary) {
  if (typeof fetch !== "function" || !summary) return [];
  const base =
    WIKIPEDIA_ACTION_API_HOSTS[summary.language] || WIKIPEDIA_ACTION_API_HOSTS.en;
  const page = summary.matchedSlug || summary.title;
  if (!page) return [];
  const url = `${base}?action=parse&page=${encodeURIComponent(
    page,
  )}&prop=text&format=json&formatversion=2&redirects=1&origin=*`;
  try {
    const response = await fetch(url, {
      headers: {
        accept: "application/json",
        "api-user-agent":
          "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
      },
    });
    if (!response || !response.ok) return [];
    const data = await response.json();
    const text = data && data.parse ? data.parse.text : "";
    let html = "";
    if (typeof text === "string") {
      html = text;
    } else if (text && typeof text === "object" && text["*"]) {
      html = text["*"];
    }
    return extractDisambiguationEntriesFromHtml(html);
  } catch (_error) {
    return [];
  }
}

async function buildDefinitionStyleDisambiguationSummary(
  data,
  term,
  language,
  matchedSlug,
  requestUrl,
) {
  const title = String(data.title || term);
  const pageUrl =
    (data.content_urls &&
      data.content_urls.desktop &&
      data.content_urls.desktop.page) ||
    requestUrl;
  const summary = {
    title,
    extract: String(data.extract || "").trim(),
    url: pageUrl,
    language,
    matchKind: "disambiguation",
    matchedSlug,
  };
  const summaryEntries = extractDisambiguationEntriesFromSummary(summary);
  if (!isDefinitionStyleDisambiguation(summary, term, summaryEntries)) {
    return null;
  }
  const parsedEntries = await fetchWikipediaDisambiguationEntries(summary);
  const entries = parsedEntries.length > 0 ? parsedEntries : summaryEntries;
  return {
    ...summary,
    extract: entries.join("\n"),
    disambiguationEntries: entries,
  };
}

async function fetchWikipediaSummary(term, language, context, options) {
  if (typeof fetch !== "function") return null;
  const includeDefinitionDisambiguation = Boolean(
    options && options.includeDefinitionDisambiguation,
  );
  const apiHeaders = {
    accept: "application/json",
    "api-user-agent":
      "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
  };

  // When context is provided, first try a title-search to find the most
  // relevant article slug (e.g. "Kiss" + "рамках програмирования" → "KISS
  // principle"). This prevents ambiguous short terms from matching the wrong
  // article (e.g. the rock band instead of the software design principle).
  if (context) {
    const found = await searchWikipediaSlug(term, context, language);
    if (found) {
      const summaryBase =
        WIKIPEDIA_HOSTS[found.language] || WIKIPEDIA_HOSTS.en;
      const url = `${summaryBase}/${encodeURIComponent(found.slug)}`;
      try {
        const response = await fetch(url, { headers: apiHeaders });
        if (response && response.ok) {
          const data = await response.json();
          if (
            data &&
            typeof data === "object" &&
            data.type !== "disambiguation"
          ) {
            const extract = String(data.extract || "").trim();
            if (extract) {
              const title = String(data.title || term);
              const pageUrl =
                (data.content_urls &&
                  data.content_urls.desktop &&
                  data.content_urls.desktop.page) ||
                url;
              return {
                title,
                extract,
                url: pageUrl,
                language: found.language,
                matchKind: "context_search",
                matchedSlug: found.slug,
                matchedTitle: found.title || title,
                searchQuery: found.query || "",
              };
            }
          }
        }
      } catch (_error) {
        // Fall through to bare-term lookup below.
      }
    }
  }

  // Bare-term fallback: try direct slug variants without context.
  const hosts = wikipediaHostsFor(language);
  const variants = wikipediaTermVariants(term);
  for (const host of hosts) {
    for (const slug of variants) {
      const url = `${host.url}/${encodeURIComponent(slug)}`;
      try {
        const response = await fetch(url, { headers: apiHeaders });
        if (!response || !response.ok) continue;
        const data = await response.json();
        if (!data || typeof data !== "object") continue;
        if (data.type === "disambiguation") {
          if (includeDefinitionDisambiguation && !context) {
            const disambiguation = await buildDefinitionStyleDisambiguationSummary(
              data,
              term,
              host.language,
              slug,
              url,
            );
            if (disambiguation) return disambiguation;
          }
          continue;
        }
        const extract = String(data.extract || "").trim();
        if (!extract) continue;
        const title = String(data.title || term);
        const pageUrl =
          (data.content_urls &&
            data.content_urls.desktop &&
            data.content_urls.desktop.page) ||
          url;
        return {
          title,
          extract,
          url: pageUrl,
          language: host.language,
          matchKind: "direct",
          matchedSlug: slug,
        };
      } catch (_error) {
        // Swallow network/parse errors and continue to the next variant.
      }
    }
  }
  // All direct slug variants were disambiguation pages or not found. Use the
  // full-text search endpoint to find the top-ranked article for the term
  // (e.g. "tesla" → "Tesla, Inc." instead of the disambiguation page).
  const found = await searchWikipediaSlug(term, "", language);
  if (found) {
    const summaryBase = WIKIPEDIA_HOSTS[found.language] || WIKIPEDIA_HOSTS.en;
    const url = `${summaryBase}/${encodeURIComponent(found.slug)}`;
    try {
      const response = await fetch(url, { headers: apiHeaders });
      if (response && response.ok) {
        const data = await response.json();
        if (
          data &&
          typeof data === "object" &&
          data.type !== "disambiguation"
        ) {
          const extract = String(data.extract || "").trim();
          if (extract) {
            const title = String(data.title || term);
            const pageUrl =
              (data.content_urls &&
                data.content_urls.desktop &&
                data.content_urls.desktop.page) ||
              url;
            return {
              title,
              extract,
              url: pageUrl,
              language: found.language,
              matchKind: "search",
              matchedSlug: found.slug,
              matchedTitle: found.title || title,
              searchQuery: found.query || "",
            };
          }
        }
      }
    } catch (_error) {
      // Search-based fallback failed; return null below.
    }
  }
  return null;
}

function isClosestWikipediaMatch(summary) {
  return summary && summary.matchKind === "search";
}

function closestMatchNote(summary, language) {
  const title = summary && summary.title ? summary.title : "the top result";
  if (language === "ru") {
    return `Ближайшее совпадение по поиску Wikipedia: «${title}». Если это не то, уточните запрос.`;
  }
  if (language === "zh") {
    return `Wikipedia 搜索的最接近匹配是“${title}”。如果这不是你的意思,请进一步说明。`;
  }
  if (language === "hi") {
    return `Wikipedia खोज में सबसे नज़दीकी मिलान "${title}" है। अगर आपका मतलब यह नहीं था, तो कृपया स्पष्ट करें।`;
  }
  return `Closest match from Wikipedia search: "${title}". If that is not what you meant, clarify the prompt.`;
}

function wikipediaClarificationMessage(summary, language) {
  const title = summary && summary.title ? summary.title : "the top result";
  if (language === "ru") {
    return `Похоже, вы имели в виду «${title}». Уточните, отвечать по этой статье Wikipedia?`;
  }
  if (language === "zh") {
    return `你是指“${title}”吗?请确认后我再根据这篇 Wikipedia 文章回答。`;
  }
  if (language === "hi") {
    return `क्या आपका मतलब "${title}" था? Wikipedia के इस लेख से उत्तर देने से पहले कृपया स्पष्ट करें।`;
  }
  return `Did you mean "${title}"? Please clarify before I answer from that Wikipedia article.`;
}

function wikipediaDisambiguationMessage(summary, language) {
  const humanUrl = humanizeUrl(summary.url);
  const entries = Array.isArray(summary.disambiguationEntries)
    ? summary.disambiguationEntries
    : String(summary.extract || "")
        .split(/\n+/u)
        .map((line) => line.trim())
        .filter(Boolean);
  const list = entries.map((entry) => `- ${entry}`).join("\n");
  if (language === "ru") {
    return `На странице Wikipedia «${summary.title}» перечислены значения:\n\n${list}\n\nИсточник: [${humanUrl}](${summary.url}) (wikipedia).`;
  }
  if (language === "zh") {
    return `Wikipedia “${summary.title}”页面列出以下含义:\n\n${list}\n\n来源:[${humanUrl}](${summary.url}) (wikipedia).`;
  }
  if (language === "hi") {
    return `Wikipedia पृष्ठ "${summary.title}" ये अर्थ सूचीबद्ध करता है:\n\n${list}\n\nस्रोत: [${humanUrl}](${summary.url}) (wikipedia).`;
  }
  return `Wikipedia's "${summary.title}" page lists these meanings:\n\n${list}\n\nSource: [${humanUrl}](${summary.url}) (wikipedia).`;
}

function wikipediaArticleQuestionMessage(summary, query, language, exactMatch) {
  const humanUrl = humanizeUrl(summary.url);
  const source = `Source: [${humanUrl}](${summary.url}) (wikipedia).`;
  if (language === "ru") {
    const wikipediaName =
      summary.language === "ru" ? "русскоязычной Википедии" : "Wikipedia";
    if (exactMatch) {
      return `В Wikipedia есть статья «${summary.title}»: ${summary.extract}\n\nИсточник: [${humanUrl}](${summary.url}) (wikipedia).`;
    }
    return [
      `В ${wikipediaName} я не нашёл отдельной статьи с названием «${query.exactTerm}», но ближайшая подходящая страница — «${summary.title}»: ${summary.extract}`,
      `Источник: [${humanUrl}](${summary.url}) (wikipedia).`,
    ].join("\n\n");
  }
  if (language === "zh") {
    const zhSource = `来源:[${humanUrl}](${summary.url}) (wikipedia).`;
    if (exactMatch) {
      return `Wikipedia 有一篇“${summary.title}”条目:${summary.extract}\n\n${zhSource}`;
    }
    return `我没有找到标题为“${query.exactTerm}”的 Wikipedia 条目,但最接近的有用页面是“${summary.title}”:${summary.extract}\n\n${zhSource}`;
  }
  if (language === "hi") {
    const hiSource = `स्रोत: [${humanUrl}](${summary.url}) (wikipedia).`;
    if (exactMatch) {
      return `Wikipedia पर "${summary.title}" लेख है: ${summary.extract}\n\n${hiSource}`;
    }
    return `मुझे Wikipedia पर "${query.exactTerm}" शीर्षक वाला अलग लेख नहीं मिला, लेकिन सबसे नज़दीकी उपयोगी पृष्ठ "${summary.title}" है: ${summary.extract}\n\n${hiSource}`;
  }
  if (exactMatch) {
    return `Wikipedia has an article titled "${summary.title}": ${summary.extract}\n\n${source}`;
  }
  return `I did not find an exact Wikipedia article titled "${query.exactTerm}", but the closest useful page is "${summary.title}": ${summary.extract}\n\n${source}`;
}

// ---------------------------------------------------------------------------
// Wikidata-backed fact reasoning pipeline (issue #127).
//
// Rather than matching against hardcoded summaries in `data/seed/facts.lino`,
// fact questions ("what is the capital of X?", "столица X", "X की राजधानी",
// "X的首都") are parsed into a structured query
// `{ relation, subjectTerm, language, forceFresh }`. The query is then
// resolved against:
//
//   1. An in-memory cache (1-week TTL) keyed by `relation:subject:language`.
//      The cache is pre-warmed from the seed `FACTS` entries so the test
//      matrix stays deterministic offline.
//   2. Wikidata `wbsearchentities` to resolve the subject term to a Q-ID.
//   3. Wikidata `wbgetentities` to fetch the property claim (P36 = capital,
//      P1082 = population, P38 = currency, P37 = official language, P30 =
//      continent, P2046 = area, P35 = head of state, P6 = head of government).
//   4. Wikidata `wbgetentities` again to resolve the target Q-ID to a label
//      in the user's prevailing language (and to a Wikipedia sitelink).
//
// Every step is recorded as a `fact_query:*` event so the reasoning trace
// shows the structured query, the cache decision, the Wikidata round-trips,
// and the final resolved answer. A user can force a fresh resolution by
// adding markers like "fresh", "no cache", "не из кэша", "без кеша",
// "ताज़ा", or "刷新" to the prompt.
// ---------------------------------------------------------------------------

const WIKIDATA_API = "https://www.wikidata.org/w/api.php";

const FACT_RELATIONS = [
  {
    relation: "capital",
    property: "P36",
    valueType: "entity",
  },
  {
    relation: "population",
    property: "P1082",
    valueType: "quantity",
  },
  {
    relation: "currency",
    property: "P38",
    valueType: "entity",
  },
  {
    relation: "official_language",
    property: "P37",
    valueType: "entity",
  },
  {
    relation: "continent",
    property: "P30",
    valueType: "entity",
  },
  {
    relation: "area",
    property: "P2046",
    valueType: "quantity",
  },
  {
    relation: "head_of_state",
    property: "P35",
    valueType: "entity",
  },
  {
    relation: "head_of_government",
    property: "P6",
    valueType: "entity",
  },
];

function relationConfig(relation) {
  return FACT_RELATIONS.find((entry) => entry.relation === relation) || null;
}

// Markers that flag the user wants a fresh (uncached) result. Detected in all
// four supported languages plus a couple of common English phrasings.
const FORCE_FRESH_MARKERS = [
  "fresh",
  "no cache",
  "no-cache",
  "without cache",
  "skip cache",
  "ignore cache",
  "refresh",
  "не из кэша",
  "не из кеша",
  "без кэша",
  "без кеша",
  "обнови",
  "свежий ответ",
  "свежие данные",
  "ताज़ा",
  "ताज़े",
  "बिना कैश",
  "नया जवाब",
  "刷新",
  "新鲜",
  "不要缓存",
  "不用缓存",
];

function shouldForceFresh(normalized, prompt) {
  const lowerPrompt = String(prompt || "").toLowerCase();
  return FORCE_FRESH_MARKERS.some(
    (marker) => normalized.includes(marker) || lowerPrompt.includes(marker),
  );
}

// Multilingual relation patterns. Each entry has a list of triggers that, when
// present in the normalized prompt, identify the relation. Subject extraction
// uses the `extract` regexes which capture the subject term verbatim from the
// original (un-normalized) prompt — that preserves Cyrillic/Devanagari/CJK
// scripts that the normalizer otherwise strips.
const FACT_QUESTION_PATTERNS = [
  {
    relation: "capital",
    // English
    extract: [
      /\bcapital\s+(?:city\s+)?of\s+(?:the\s+)?([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /\b([^?.!,;:]+?)['’]s\s+capital\b/i,
      /\bwhich\s+city\s+is\s+(?:the\s+)?capital\s+of\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /\bwhich\s+city\s+is\s+([^?.!,;:]+?)['’]s\s+capital\b/i,
      // Russian: "столица России", "какова столица России",
      // "столицей какой страны является Москва" — only the first form is
      // resolved; the inverted form falls through to other handlers.
      /столица\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /какова\s+столица\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /какая\s+столица\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      // Hindi: "X की राजधानी क्या है"
      /([^?.!,;:]+?)\s+की\s+राजधानी(?:\s+क्या\s+है)?(?:[?.!,;:]|$)/i,
      // Chinese: "X的首都" / "X的首都是什么"
      /([^?。.!!,,;:、]+?)的首都(?:是什么|是哪里|是哪个城市)?(?:[?。.!!,,;:、]|$)/i,
    ],
  },
  {
    relation: "population",
    extract: [
      /\bpopulation\s+of\s+(?:the\s+)?([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /\bhow\s+many\s+people\s+(?:live|are\s+there)\s+in\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /\b([^?.!,;:]+?)['’]s\s+population\b/i,
      /население\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /какое\s+население\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /([^?.!,;:]+?)\s+की\s+(?:जनसंख्या|आबादी)(?:[?.!,;:]|$)/i,
      /([^?。.!!,,;:、]+?)的人口(?:是多少|有多少)?(?:[?。.!!,,;:、]|$)/i,
    ],
  },
  {
    relation: "currency",
    extract: [
      /\bcurrency\s+of\s+(?:the\s+)?([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /\b([^?.!,;:]+?)['’]s\s+currency\b/i,
      /валюта\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /какая\s+валюта\s+в\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /([^?.!,;:]+?)\s+की\s+मुद्रा(?:[?.!,;:]|$)/i,
      /([^?。.!!,,;:、]+?)的(?:货币|貨幣)(?:是什么|是哪种)?(?:[?。.!!,,;:、]|$)/i,
    ],
  },
  {
    relation: "official_language",
    extract: [
      /\bofficial\s+language\s+of\s+(?:the\s+)?([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /\bwhat\s+language\s+(?:do\s+they\s+speak|is\s+spoken)\s+in\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /государственный\s+язык\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /официальный\s+язык\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /([^?.!,;:]+?)\s+की\s+(?:राजभाषा|आधिकारिक\s+भाषा)(?:[?.!,;:]|$)/i,
      /([^?。.!!,,;:、]+?)的(?:官方语言|官方語言)(?:[?。.!!,,;:、]|$)/i,
    ],
  },
  {
    relation: "continent",
    extract: [
      /\bcontinent\s+(?:is\s+)?([^?.!,;:]+?)\s+(?:on|in)\b/i,
      /\bwhich\s+continent\s+is\s+([^?.!,;:]+?)\s+(?:on|in)\b/i,
      /на\s+каком\s+континенте\s+(?:находится|расположена|расположен)\s+([^?.!,;:]+?)(?:[?.!,;:]|$)/i,
      /([^?.!,;:]+?)\s+किस\s+महाद्वीप\s+में\s+है(?:[?.!,;:]|$)/i,
      /([^?。.!!,,;:、]+?)在哪个(?:大洲|洲)(?:[?。.!!,,;:、]|$)/i,
    ],
  },
];

// Words/phrases that should be stripped from a captured subject before we
// hand it off to Wikidata. These are not part of the entity name — they leak
// from question prefixes the regex didn't consume (e.g. "the country called
// France" → "France"). Order matters: longer prefixes first.
const SUBJECT_TRIM_PREFIXES = [
  "the country called ",
  "the country ",
  "country ",
  "the city of ",
  "the city ",
  "city of ",
  "country called ",
  "republic of ",
  "kingdom of ",
  "is ",
  "in ",
  "of the ",
  "of ",
  "страна ",
  "страны ",
  "стране ",
  "страну ",
];

function trimSubjectTerm(raw) {
  let value = String(raw || "")
    .replace(/[«»"'`“”„‟‹›]+/g, "")
    .replace(/\s+/g, " ")
    .trim();
  let changed = true;
  while (changed) {
    changed = false;
    const lower = value.toLowerCase();
    for (const prefix of SUBJECT_TRIM_PREFIXES) {
      if (lower.startsWith(prefix)) {
        value = value.slice(prefix.length).trim();
        changed = true;
        break;
      }
    }
  }
  return value;
}

function parseFactQuestion(prompt, normalized) {
  const text = String(prompt || "");
  if (!text.trim()) return null;
  for (const pattern of FACT_QUESTION_PATTERNS) {
    for (const regex of pattern.extract) {
      const match = regex.exec(text);
      if (!match) continue;
      const subjectTerm = trimSubjectTerm(match[1]);
      if (!subjectTerm) continue;
      // Reject single-letter or pure-punctuation captures so we don't fire
      // on noise like "x." or "?".
      if (subjectTerm.length < 2 && !/[Ѐ-鿿]/.test(subjectTerm)) {
        continue;
      }
      return {
        relation: pattern.relation,
        subjectTerm,
        language: detectLanguage(prompt),
        forceFresh: shouldForceFresh(normalized, prompt),
      };
    }
  }
  return null;
}

// In-memory cache. Keyed by `relation:subject_normalized:language`. The TTL
// matches the user-requested 1 week. Pre-warmed from FACTS at init() so the
// offline test matrix sees the same starting cache the Rust solver does.
const FACT_QUERY_CACHE = new Map();
const FACT_QUERY_TTL_MS = 7 * 24 * 60 * 60 * 1000;

function factCacheKey(relation, subjectTerm, language) {
  return [
    String(relation || "").toLowerCase(),
    String(subjectTerm || "")
      .toLowerCase()
      .replace(/\s+/g, " ")
      .trim(),
    String(language || "en").toLowerCase(),
  ].join(":");
}

function factCacheGet(relation, subjectTerm, language) {
  const key = factCacheKey(relation, subjectTerm, language);
  const entry = FACT_QUERY_CACHE.get(key);
  if (!entry) return null;
  if (
    entry.expiresAt &&
    typeof entry.expiresAt === "number" &&
    entry.expiresAt < Date.now()
  ) {
    FACT_QUERY_CACHE.delete(key);
    return null;
  }
  return entry;
}

function factCachePut(relation, subjectTerm, language, value) {
  const key = factCacheKey(relation, subjectTerm, language);
  const ttl = typeof value.ttlMs === "number" ? value.ttlMs : FACT_QUERY_TTL_MS;
  const entry = Object.assign({}, value, {
    expiresAt: Date.now() + ttl,
  });
  FACT_QUERY_CACHE.set(key, entry);
  return entry;
}

// Pre-warm the runtime cache from the seed `facts.lino`. Each seed record can
// optionally declare `relation`, `subjectQid`, `valueQid`, plus per-language
// `subjectLabel`/`valueLabel`/`valueText` overrides — those are the structured
// cache anchors. The legacy fields (`summary`, `subjectAliases`,
// `questionKeywords`) remain in place for the `tryFactLookup` substring path.
function warmFactCacheFromSeed() {
  if (!Array.isArray(FACTS)) return;
  const languages = ["en", "ru", "hi", "zh"];
  for (const record of FACTS) {
    if (!record || !record.relation || !record.subjectAliases) continue;
    const localizedMap = new Map();
    if (Array.isArray(record.localized)) {
      for (const loc of record.localized) {
        if (loc && loc.language) localizedMap.set(loc.language, loc);
      }
    }
    for (const lang of languages) {
      const loc = localizedMap.get(lang) || localizedMap.get("en") || {};
      const summary =
        (loc && loc.summary) || record.summary || "";
      const source = (loc && loc.source) || record.source || "";
      const sourceKind =
        (loc && loc.sourceKind) || record.sourceKind || "wikipedia";
      const valueLabel = (loc && loc.valueLabel) || record.valueLabel || "";
      const subjectLabel =
        (loc && loc.subjectLabel) || record.subjectLabel || "";
      // The aliases for the subject language drive cache key lookup. For each
      // alias (already lowercased by seed_loader.js), pre-seed a cache entry.
      const aliases = Array.isArray(record.subjectAliases)
        ? record.subjectAliases
        : [];
      for (const alias of aliases) {
        if (!alias) continue;
        factCachePut(record.relation, alias, lang, {
          relation: record.relation,
          subjectTerm: alias,
          subjectLabel: subjectLabel || alias,
          subjectQid: record.subjectQid || "",
          valueLabel,
          valueQid: record.valueQid || "",
          summary,
          source,
          sourceKind,
          language: lang,
          fromSeed: true,
          ttlMs: FACT_QUERY_TTL_MS,
        });
      }
    }
  }
}

async function wikidataSearchEntity(term, language) {
  if (typeof fetch !== "function") return null;
  // Wikidata supports per-language search; English fallback ensures broad
  // recall even for non-Latin scripts.
  const ordered = [language, "en"].filter(
    (value, index, array) => value && array.indexOf(value) === index,
  );
  for (const lang of ordered) {
    const url = `${WIKIDATA_API}?action=wbsearchentities&format=json&origin=*&type=item&limit=5&language=${encodeURIComponent(
      lang,
    )}&search=${encodeURIComponent(term)}`;
    try {
      const response = await fetch(url, {
        headers: {
          accept: "application/json",
          "api-user-agent":
            "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
        },
      });
      if (!response || !response.ok) continue;
      const data = await response.json();
      if (data && Array.isArray(data.search) && data.search.length > 0) {
        const hit = data.search[0];
        return {
          qid: hit.id,
          label: hit.label || term,
          description: hit.description || "",
          language: lang,
        };
      }
    } catch (_error) {
      // Try the next language.
    }
  }
  return null;
}

function wikidataConceptUrl(hit) {
  const id = hit && hit.id ? String(hit.id) : "";
  if (id) return `https://www.wikidata.org/wiki/${encodeURIComponent(id)}`;
  const conceptUri = hit && hit.concepturi ? String(hit.concepturi) : "";
  const qid = conceptUri.match(/Q\d+/);
  if (qid) return `https://www.wikidata.org/wiki/${qid[0]}`;
  return "https://www.wikidata.org/wiki/Wikidata:Main_Page";
}

function wikidataHitMatchesTerm(hit, term) {
  const target = normalizeLookupText(term);
  if (!target || !hit) return false;
  const candidates = [
    hit.label,
    hit.title,
    hit.match && hit.match.text,
    hit.display && hit.display.label && hit.display.label.value,
  ];
  if (Array.isArray(hit.aliases)) {
    candidates.push(...hit.aliases);
  }
  return candidates.some((candidate) => normalizeLookupText(candidate) === target);
}

async function fetchWikidataConceptSummary(term, language) {
  if (typeof fetch !== "function") return null;
  const ordered = [language, "en"].filter(
    (value, index, array) => value && array.indexOf(value) === index,
  );
  for (const lang of ordered) {
    const url = `${WIKIDATA_API}?action=wbsearchentities&format=json&origin=*&type=item&limit=5&language=${encodeURIComponent(
      lang,
    )}&search=${encodeURIComponent(term)}`;
    try {
      const response = await fetch(url, {
        headers: {
          accept: "application/json",
          "api-user-agent":
            "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
        },
      });
      if (!response || !response.ok) continue;
      const data = await response.json();
      const hits = data && Array.isArray(data.search) ? data.search : [];
      const hit = hits.find((candidate) =>
        wikidataHitMatchesTerm(candidate, term),
      );
      if (!hit) continue;
      const display = hit.display || {};
      return {
        sourceKind: "wikidata",
        qid: hit.id || "",
        title:
          (display.label && display.label.value) ||
          hit.label ||
          (hit.match && hit.match.text) ||
          term,
        description:
          (display.description && display.description.value) ||
          hit.description ||
          "",
        url: wikidataConceptUrl(hit),
        language: lang,
      };
    } catch (_error) {
      // Try the next Wikidata language.
    }
  }
  return null;
}

function wiktionaryFallbackDescription(title, language) {
  if (language === "ru") {
    return `В Wiktionary есть словарная статья «${title}».`;
  }
  if (language === "zh") {
    return `Wiktionary 有“${title}”这个词条。`;
  }
  if (language === "hi") {
    return `Wiktionary में "${title}" के लिए शब्दकोश प्रविष्टि है।`;
  }
  return `Wiktionary has a dictionary entry for "${title}".`;
}

async function fetchWiktionaryEntry(term, language) {
  if (typeof fetch !== "function") return null;
  const ordered = [language, "en"].filter(
    (value, index, array) => value && array.indexOf(value) === index,
  );
  const target = normalizeLookupText(term);
  for (const lang of ordered) {
    const base = WIKTIONARY_SEARCH_HOSTS[lang] || WIKTIONARY_SEARCH_HOSTS.en;
    const url = `${base}?action=opensearch&search=${encodeURIComponent(
      term,
    )}&limit=5&format=json&origin=*`;
    try {
      const response = await fetch(url, {
        headers: {
          accept: "application/json",
          "api-user-agent":
            "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
        },
      });
      if (!response || !response.ok) continue;
      const data = await response.json();
      if (!Array.isArray(data) || !Array.isArray(data[1])) continue;
      const titles = data[1];
      const descriptions = Array.isArray(data[2]) ? data[2] : [];
      const urls = Array.isArray(data[3]) ? data[3] : [];
      const index = titles.findIndex(
        (title) => normalizeLookupText(title) === target,
      );
      if (index < 0) continue;
      const title = titles[index] || term;
      return {
        sourceKind: "wiktionary",
        title,
        description:
          descriptions[index] || wiktionaryFallbackDescription(title, lang),
        url:
          urls[index] ||
          `https://${lang}.wiktionary.org/wiki/${encodeURIComponent(title)}`,
        language: lang,
      };
    } catch (_error) {
      // Try the next Wiktionary language.
    }
  }
  return null;
}

function renderExternalLookupContent(result, requestedTerm) {
  const humanUrl = humanizeUrl(result.url);
  const title = result.title || requestedTerm;
  const heading =
    requestedTerm && normalizeLookupText(requestedTerm) !== normalizeLookupText(title)
      ? `${requestedTerm}: ${title}`
      : title;
  const description = String(result.description || "").trim();
  const body = description ? `${heading}: ${description}` : `${heading}.`;
  return `${body}\n\nSource: [${humanUrl}](${result.url}) (${result.sourceKind}).`;
}

function externalLookupResponse(result, requestedTerm, rejectedSummary) {
  const humanUrl = humanizeUrl(result.url);
  const evidence = [
    `${result.sourceKind}_lookup:${result.qid || result.title}`,
    `source:${humanUrl}`,
    `language:${result.language}`,
  ];
  if (result.qid) evidence.push(`wikidata:${result.qid}`);
  if (rejectedSummary && rejectedSummary.title) {
    evidence.push(`wikipedia_lookup:rejected:${rejectedSummary.title}`);
  }
  return {
    intent: `${result.sourceKind}_lookup`,
    content: renderExternalLookupContent(result, requestedTerm),
    confidence: result.sourceKind === "wikidata" ? 0.82 : 0.75,
    evidence,
  };
}

async function tryTermKnowledgeFallback(term, language, rejectedSummary) {
  const wikidata = await fetchWikidataConceptSummary(term, language);
  if (wikidata) {
    return externalLookupResponse(wikidata, term, rejectedSummary);
  }
  const wiktionary = await fetchWiktionaryEntry(term, language);
  if (wiktionary) {
    return externalLookupResponse(wiktionary, term, rejectedSummary);
  }
  return null;
}

async function wikidataFetchEntityClaim(qid, property, language) {
  if (typeof fetch !== "function") return null;
  const url = `${WIKIDATA_API}?action=wbgetentities&format=json&origin=*&ids=${encodeURIComponent(
    qid,
  )}&props=claims%7Clabels%7Csitelinks&languages=${encodeURIComponent(
    language,
  )}%7Cen`;
  try {
    const response = await fetch(url, {
      headers: {
        accept: "application/json",
        "api-user-agent":
          "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
      },
    });
    if (!response || !response.ok) return null;
    const data = await response.json();
    if (!data || !data.entities) return null;
    const entity = data.entities[qid];
    if (!entity) return null;
    const claims = (entity.claims || {})[property] || [];
    const subjectLabel =
      (entity.labels && (entity.labels[language] || entity.labels.en) || {})
        .value || "";
    const sitelinks = entity.sitelinks || {};
    return { claims, subjectLabel, sitelinks };
  } catch (_error) {
    return null;
  }
}

async function wikidataResolveLabel(qid, language) {
  if (typeof fetch !== "function") return null;
  const url = `${WIKIDATA_API}?action=wbgetentities&format=json&origin=*&ids=${encodeURIComponent(
    qid,
  )}&props=labels%7Csitelinks&languages=${encodeURIComponent(language)}%7Cen`;
  try {
    const response = await fetch(url, {
      headers: {
        accept: "application/json",
        "api-user-agent":
          "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
      },
    });
    if (!response || !response.ok) return null;
    const data = await response.json();
    if (!data || !data.entities) return null;
    const entity = data.entities[qid];
    if (!entity) return null;
    const label =
      (entity.labels && (entity.labels[language] || entity.labels.en) || {})
        .value || "";
    const sitelinks = entity.sitelinks || {};
    return { label, sitelinks };
  } catch (_error) {
    return null;
  }
}

function wikipediaSitelinkUrl(sitelinks, language) {
  if (!sitelinks || typeof sitelinks !== "object") return "";
  const key = `${language}wiki`;
  const fallback = "enwiki";
  const entry = sitelinks[key] || sitelinks[fallback];
  if (!entry) return "";
  if (entry.url) return entry.url;
  if (entry.title) {
    const lang = sitelinks[key] ? language : "en";
    return `https://${lang}.wikipedia.org/wiki/${encodeURIComponent(
      String(entry.title).replace(/\s+/g, "_"),
    ).replace(/%2F/gi, "/")}`;
  }
  return "";
}

// Localized templates for rendering the final answer. The seed value is
// inserted via `{value}`; the subject is inserted via `{subject}`.
const FACT_RESPONSE_TEMPLATES = {
  capital: {
    en: "The capital of {subject} is {value}.",
    ru: "Столица {subject} — {value}.",
    hi: "{subject} की राजधानी {value} है।",
    zh: "{subject}的首都是{value}。",
  },
  population: {
    en: "The population of {subject} is approximately {value}.",
    ru: "Население {subject} составляет примерно {value}.",
    hi: "{subject} की जनसंख्या लगभग {value} है।",
    zh: "{subject}的人口约为 {value}。",
  },
  currency: {
    en: "The currency of {subject} is the {value}.",
    ru: "Валюта {subject} — {value}.",
    hi: "{subject} की मुद्रा {value} है।",
    zh: "{subject}的货币是{value}。",
  },
  official_language: {
    en: "The official language of {subject} is {value}.",
    ru: "Государственный язык {subject} — {value}.",
    hi: "{subject} की राजभाषा {value} है।",
    zh: "{subject}的官方语言是{value}。",
  },
  continent: {
    en: "{subject} is located on the continent of {value}.",
    ru: "{subject} расположена на континенте {value}.",
    hi: "{subject} {value} महाद्वीप पर स्थित है।",
    zh: "{subject}位于{value}。",
  },
  area: {
    en: "The area of {subject} is approximately {value}.",
    ru: "Площадь {subject} составляет примерно {value}.",
    hi: "{subject} का क्षेत्रफल लगभग {value} है।",
    zh: "{subject}的面积约为 {value}。",
  },
  head_of_state: {
    en: "The head of state of {subject} is {value}.",
    ru: "Глава государства {subject} — {value}.",
    hi: "{subject} के राष्ट्राध्यक्ष {value} हैं।",
    zh: "{subject}的国家元首是{value}。",
  },
  head_of_government: {
    en: "The head of government of {subject} is {value}.",
    ru: "Глава правительства {subject} — {value}.",
    hi: "{subject} के सरकार के प्रमुख {value} हैं।",
    zh: "{subject}的政府首脑是{value}。",
  },
};

function renderFactSummary(relation, subjectLabel, valueLabel, language) {
  const templates =
    FACT_RESPONSE_TEMPLATES[relation] || FACT_RESPONSE_TEMPLATES.capital;
  const template = templates[language] || templates.en;
  return template
    .replace("{subject}", subjectLabel || "")
    .replace("{value}", valueLabel || "");
}

function factQueryEvidence(record, language) {
  const evidence = [
    `fact_query:relation:${record.relation}`,
    `fact_query:subject:${record.subjectLabel || record.subjectTerm}`,
    `language:${language}`,
  ];
  if (record.subjectQid) evidence.push(`wikidata:${record.subjectQid}`);
  if (record.valueQid) evidence.push(`wikidata:${record.valueQid}`);
  if (record.source) evidence.push(`source:${humanizeUrl(record.source)}`);
  if (record.fromSeed) evidence.push("fact_query:cache:seed");
  else if (record.fromCache) evidence.push("fact_query:cache:hit");
  else evidence.push("fact_query:cache:miss");
  return evidence;
}

async function resolveFactQueryViaWikidata(query, log) {
  // Stage 1: subject resolution via wbsearchentities.
  if (log) log.push(`fact_query:wbsearchentities:request:${query.subjectTerm}`);
  const subject = await wikidataSearchEntity(query.subjectTerm, query.language);
  if (!subject) {
    if (log) log.push("fact_query:wbsearchentities:miss");
    return null;
  }
  if (log) log.push(`fact_query:wbsearchentities:resolved:${subject.qid}`);

  const config = relationConfig(query.relation);
  if (!config) return null;

  // Stage 2: claim fetch via wbgetentities.
  if (log) log.push(`fact_query:wbgetentities:request:${config.property}`);
  const claimData = await wikidataFetchEntityClaim(
    subject.qid,
    config.property,
    query.language,
  );
  if (!claimData || !claimData.claims || claimData.claims.length === 0) {
    if (log) log.push("fact_query:wbgetentities:no_claim");
    return null;
  }
  const claim = claimData.claims[0];
  const mainsnak = claim && claim.mainsnak;
  if (!mainsnak || !mainsnak.datavalue) {
    if (log) log.push("fact_query:wbgetentities:no_datavalue");
    return null;
  }

  // Stage 3: value resolution.
  let valueLabel = "";
  let valueQid = "";
  if (config.valueType === "entity") {
    const value = mainsnak.datavalue.value || {};
    valueQid = value.id || "";
    if (!valueQid) {
      if (log) log.push("fact_query:wbgetentities:value_not_entity");
      return null;
    }
    if (log) log.push(`fact_query:label_resolve:request:${valueQid}`);
    const labelResult = await wikidataResolveLabel(valueQid, query.language);
    if (!labelResult || !labelResult.label) {
      if (log) log.push("fact_query:label_resolve:miss");
      return null;
    }
    valueLabel = labelResult.label;
    if (log) log.push(`fact_query:label_resolve:${valueLabel}`);
    // Capture the Wikipedia sitelink for the value entity as the canonical
    // evidence source — that's the human-readable artifact users can verify.
    const url =
      wikipediaSitelinkUrl(labelResult.sitelinks, query.language) ||
      wikipediaSitelinkUrl(claimData.sitelinks, query.language);
    return {
      relation: query.relation,
      subjectTerm: query.subjectTerm,
      subjectLabel: claimData.subjectLabel || subject.label,
      subjectQid: subject.qid,
      valueLabel,
      valueQid,
      summary: renderFactSummary(
        query.relation,
        claimData.subjectLabel || subject.label,
        valueLabel,
        query.language,
      ),
      source: url,
      sourceKind: "wikidata",
      language: query.language,
      fromCache: false,
      fromSeed: false,
    };
  }

  // Quantity values (population, area) are not Q-IDs.
  const value = mainsnak.datavalue.value || {};
  const rawAmount = String(value.amount || "").replace(/^\+/, "");
  if (!rawAmount) {
    if (log) log.push("fact_query:wbgetentities:value_empty");
    return null;
  }
  valueLabel = rawAmount;
  if (log) log.push(`fact_query:quantity:${valueLabel}`);
  const url = wikipediaSitelinkUrl(claimData.sitelinks, query.language);
  return {
    relation: query.relation,
    subjectTerm: query.subjectTerm,
    subjectLabel: claimData.subjectLabel || subject.label,
    subjectQid: subject.qid,
    valueLabel,
    valueQid: "",
    summary: renderFactSummary(
      query.relation,
      claimData.subjectLabel || subject.label,
      valueLabel,
      query.language,
    ),
    source: url,
    sourceKind: "wikidata",
    language: query.language,
    fromCache: false,
    fromSeed: false,
  };
}

async function tryFactQuery(prompt, normalized, preferences) {
  const query = parseFactQuestion(prompt, normalized);
  if (!query) return null;

  // Trace events: every step of the reasoning pipeline is recorded so the
  // browser memory log shows the structured query, the cache decision, and
  // any Wikidata calls.
  const trace = [];
  trace.push(`fact_query:request:${prompt}`);
  trace.push(`fact_query:relation:${query.relation}`);
  trace.push(`fact_query:subject:${query.subjectTerm}`);
  trace.push(`fact_query:language:${query.language}`);
  if (query.forceFresh) trace.push("fact_query:force_fresh");

  // Stage 1: cache check (skipped when the user asked for fresh data).
  if (!query.forceFresh) {
    trace.push("fact_query:cache:check");
    const cached = factCacheGet(
      query.relation,
      query.subjectTerm,
      query.language,
    );
    if (cached) {
      trace.push(`fact_query:cache:hit:${cached.fromSeed ? "seed" : "runtime"}`);
      const evidence = factQueryEvidence(
        Object.assign({}, cached, { fromCache: true }),
        query.language,
      );
      return {
        intent: "fact_query",
        content: cached.summary,
        confidence: 0.92,
        evidence,
        trace,
        formalizedObject: cached.subjectQid || "",
      };
    }
    trace.push("fact_query:cache:miss");
  } else {
    trace.push("fact_query:cache:bypass");
  }

  // Stage 2: Wikidata resolution.
  const resolved = await resolveFactQueryViaWikidata(query, trace);
  if (!resolved) {
    trace.push("fact_query:wikidata:no_match");
    return null;
  }

  // Stage 3: cache the resolution.
  factCachePut(query.relation, query.subjectTerm, query.language, resolved);
  trace.push(`fact_query:cache:store:${factCacheKey(
    query.relation,
    query.subjectTerm,
    query.language,
  )}`);

  trace.push(`fact_query:response:${resolved.summary}`);
  return {
    intent: "fact_query",
    content: resolved.summary,
    confidence: 0.92,
    evidence: factQueryEvidence(resolved, query.language),
    trace,
    formalizedObject: resolved.subjectQid || "",
  };
}

async function tryWikipediaLookup(prompt, language, preferences) {
  const query = extractConceptQuery(prompt);
  if (!query) return null;
  // Avoid hitting the network for terms that already resolved in CONCEPTS;
  // that path is handled by `tryConceptLookup`. We try the full
  // `(term, context)` query first so that "what is iir in ml" doesn't waste
  // a network call when a context-aware record exists.
  if (lookupConceptQuery(query)) return null;
  // Pass the original-case term to Wikipedia: non-Latin scripts (e.g. Cyrillic
  // for "Илон Маск") require correct capitalization in the REST URL because
  // ru.wikipedia.org does not redirect the all-lowercase slug.
  const wikiTerm = query.termOriginal || query.term;
  const wikiContext = query.contextOriginal || query.context;
  const summary = await fetchWikipediaSummary(wikiTerm, language, wikiContext, {
    includeDefinitionDisambiguation: !wikiContext,
  });
  if (!summary) {
    return tryTermKnowledgeFallback(wikiTerm, language, null);
  }
  const isClosestMatch = isClosestWikipediaMatch(summary);
  const requiresPlausibleSearchMatch =
    isClosestMatch || summary.matchKind === "context_search";
  if (
    requiresPlausibleSearchMatch &&
    !isPlausibleWikipediaSearchMatch(summary, wikiTerm)
  ) {
    const fallback = await tryTermKnowledgeFallback(wikiTerm, language, summary);
    if (fallback) return fallback;
    return null;
  }
  const guessProbability = numericPreference(
    preferences && preferences.guessProbability,
    0.8,
    0,
    1,
  );
  const humanUrl = humanizeUrl(summary.url);
  const evidence = [
    `wikipedia_lookup:${summary.title}`,
    `source:${humanUrl}`,
    `language:${summary.language}`,
  ];
  if (wikiContext) evidence.push(`wikipedia_lookup:context:${wikiContext}`);
  if (isClosestMatch) {
    evidence.push(`wikipedia_lookup:closest_match:${summary.title}`);
  }
  if (summary.matchKind === "disambiguation") {
    const entryCount = Array.isArray(summary.disambiguationEntries)
      ? summary.disambiguationEntries.length
      : 0;
    evidence.push(`wikipedia_lookup:disambiguation:${summary.title}`);
    evidence.push(`wikipedia_lookup:disambiguation_entries:${entryCount}`);
    return {
      intent: "wikipedia_lookup",
      content: wikipediaDisambiguationMessage(summary, language),
      confidence: 0.84,
      evidence,
    };
  }
  if (isClosestMatch && guessProbability < 0.5) {
    evidence.push("ambiguity:ask");
    return {
      intent: "clarification",
      content: wikipediaClarificationMessage(summary, language),
      confidence: 0.65,
      evidence,
    };
  }
  const bodyLines = [
    `${summary.title}: ${summary.extract}\n\n` +
      `Source: [${humanUrl}](${summary.url}) (wikipedia).`,
  ];
  if (isClosestMatch) {
    bodyLines.push(closestMatchNote(summary, language));
    evidence.push("ambiguity:guess");
  }
  return {
    intent: "wikipedia_lookup",
    content: bodyLines.join("\n\n"),
    confidence: 0.85,
    evidence,
  };
}

async function tryWikipediaArticleQuestion(prompt, language, preferences) {
  const term = extractWikipediaArticleQuestionTerm(prompt);
  if (!term) return null;
  const query = refineWikipediaArticleQuestionLookup(term, language);
  if (!query.exactTerm) return null;

  const exactSummary = await fetchWikipediaSummary(query.exactTerm, language, null);
  let summary = exactSummary;
  const exactMatch = exactSummary && exactSummary.matchKind === "direct";
  if (!exactMatch && (query.lookupTerm !== query.exactTerm || query.contextOriginal)) {
    const refinedSummary = await fetchWikipediaSummary(
      query.lookupTerm,
      language,
      query.contextOriginal,
    );
    if (refinedSummary) summary = refinedSummary;
  }
  if (!summary) {
    return tryTermKnowledgeFallback(query.exactTerm, language, null);
  }
  if (!exactMatch && !isArticleQuestionWikipediaMatch(summary, query)) {
    const fallback = await tryTermKnowledgeFallback(
      query.exactTerm,
      language,
      summary,
    );
    if (fallback) return fallback;
    return null;
  }

  const guessProbability = numericPreference(
    preferences && preferences.guessProbability,
    0.8,
    0,
    1,
  );
  const humanUrl = humanizeUrl(summary.url);
  const evidence = [
    `wikipedia_article_question:${query.exactTerm}`,
    `source:${humanUrl}`,
    `language:${summary.language}`,
  ];
  if (query.lookupTerm !== query.exactTerm) {
    evidence.push(`wikipedia_article_question:lookup:${query.lookupTerm}`);
  }
  if (query.contextOriginal) {
    evidence.push(`wikipedia_article_question:context:${query.contextOriginal}`);
  }
  if (exactMatch) {
    evidence.push("wikipedia_article_question:exact");
  } else {
    evidence.push(`wikipedia_article_question:closest_match:${summary.title}`);
  }
  if (!exactMatch && guessProbability < 0.5) {
    evidence.push("ambiguity:ask");
    return {
      intent: "wikipedia_article_question",
      content: wikipediaClarificationMessage(summary, language),
      confidence: 0.65,
      evidence,
    };
  }
  if (!exactMatch) evidence.push("ambiguity:guess");
  return {
    intent: "wikipedia_article_question",
    content: wikipediaArticleQuestionMessage(summary, query, language, exactMatch),
    confidence: exactMatch ? 0.88 : 0.82,
    evidence,
    query: query.exactTerm,
    formalizedObject: summary.title,
  };
}

// Issue #386 software-authoring roles — mirror ROLE_SOFTWARE_AUTHORING_ACTION
// and ROLE_SOFTWARE_ARTIFACT_KIND in src/seed/meanings.rs. The surface words (in
// every supported language) live in data/seed/meanings.lino and
// data/seed/meanings-software-project.lino (embedded in MEANINGS_LINO below);
// this module names no word in any single language.
const ROLE_SOFTWARE_AUTHORING_ACTION = "software_authoring_action";
const ROLE_SOFTWARE_ARTIFACT_KIND = "software_artifact_kind";
const ROLE_SOFTWARE_REQUIREMENT_CATEGORY = "software_requirement_category";
// Issue #386 software-delivery / language / game-tracker / approval roles —
// mirror the matching ROLE_* consts in src/seed/meanings.rs. Their surface
// words (every supported language) live in
// data/seed/meanings-software-project.lino (embedded in MEANINGS_LINO below);
// this module names no word in any single language.
const ROLE_SOFTWARE_FEATURE = "software_feature";
const ROLE_SOFTWARE_DELIVERY_MODE = "software_delivery_mode";
const ROLE_SOFTWARE_IMPLEMENTATION_LANGUAGE = "software_implementation_language";
const ROLE_GAME_TRACKER_DOMAIN = "game_tracker_domain";
const ROLE_GAME_TRACKER_MECHANIC = "game_tracker_mechanic";
const ROLE_SOFTWARE_STEP_GRANULARITY = "software_step_granularity";
const ROLE_SOFTWARE_BASH_COMMAND = "software_bash_command";
const ROLE_SOFTWARE_APPROVAL_TRIGGER = "software_approval_trigger";

// Map a software-requirement-category meaning slug to its canonical category
// label. Mirrors requirement_category_label in
// src/solver_handlers/software_project.rs: recognition words live in the
// lexicon; the canonical category label lives here. A slug absent here is
// skipped rather than mislabelled.
const SOFTWARE_REQUIREMENT_CATEGORY_LABELS = {
  requirement_state_tracking: "state_tracking",
  requirement_data_exchange: "data_exchange",
  requirement_automation: "automation",
  requirement_validation: "validation",
  requirement_integration: "integration",
  requirement_user_interface: "user_interface",
  requirement_project_behavior: "project_behavior",
};

// Map a software_delivery_mode meaning slug to its canonical delivery-mode
// label. Mirrors DeliveryMode::from_slug in
// src/solver_handlers/software_project.rs: the lexicon owns the surface words;
// this resolver owns the slug→label mapping. The default (code_generation) has
// no slug — it is the fallback when no mode meaning is evidenced.
const SOFTWARE_DELIVERY_MODE_LABELS = {
  delivery_manual_instructions: "manual_instructions",
  delivery_immediate_execution: "immediate_execution",
  delivery_script_generation: "script_generation",
};

// Map a software_implementation_language meaning slug to its canonical target
// label. Mirrors implementation_language_from_slug in
// src/solver_handlers/software_project.rs. The default (typescript) has no slug.
const SOFTWARE_IMPLEMENTATION_LANGUAGE_LABELS = {
  language_python: "python",
  language_rust: "rust",
  language_javascript: "javascript",
};

// Map a software-artifact-kind meaning slug to its canonical English label.
// Mirrors artifact_label in src/solver_handlers/software_project.rs: the lexicon
// owns the surface words a prompt is matched against (every language); this
// resolver owns only the stable slug→label mapping. A slug absent here is
// skipped rather than mislabelled.
const SOFTWARE_ARTIFACT_LABELS = {
  artifact_browser_extension: "browser extension",
  artifact_command_line_tool: "command-line tool",
  artifact_github_action: "action",
  artifact_mobile_app: "mobile app",
  artifact_web_app: "web app",
  artifact_application: "application",
  artifact_extension: "extension",
  artifact_dashboard: "dashboard",
  artifact_scraper: "scraper",
  artifact_library: "library",
  artifact_website: "website",
  artifact_plugin: "plugin",
  artifact_service: "service",
  artifact_bot: "bot",
  artifact_app: "app",
  artifact_api: "API",
  artifact_sdk: "SDK",
  artifact_tool: "tool",
  artifact_mod: "mod",
};

// [surface, label] recognition table, sourced from the lexicon in declaration
// order. Mirrors artifact_surface_table in
// src/solver_handlers/software_project.rs.
function softwareArtifactTable() {
  const table = [];
  for (const meaning of meaningsWithRole(ROLE_SOFTWARE_ARTIFACT_KIND)) {
    const label = SOFTWARE_ARTIFACT_LABELS[meaning.slug];
    if (!label) continue;
    for (const surface of meaning.words) table.push([surface, label]);
  }
  return table;
}

// [surface, action-slug] recognition table for software-authoring verbs. The
// matched slug is stored verbatim as the request's `action`, so the verb is
// recognised in every language it is lexicalised in. Mirrors
// action_surface_table in src/solver_handlers/software_project.rs.
function softwareActionTable() {
  const table = [];
  for (const meaning of meaningsWithRole(ROLE_SOFTWARE_AUTHORING_ACTION)) {
    for (const surface of meaning.words) table.push([surface, meaning.slug]);
  }
  return table;
}

// Whether `character` is a "word character" for the recognition scan:
// alphanumeric but not CJK. Mirrors is_word_character in
// src/solver_handlers/software_project.rs — CJK scripts have no inter-word
// spaces so they match as substrings, while Latin/Cyrillic/Devanagari keep
// whole-token boundaries so a short surface like `апи` never matches inside
// `напиши`.
function isSoftwareWordCharacter(character) {
  return /[\p{Alphabetic}\p{Number}]/u.test(character) && !containsCjk(character);
}

function isSoftwareStartBoundary(value, index) {
  if (index === 0) return true;
  return !isSoftwareWordCharacter(value[index - 1]);
}

function isSoftwareEndBoundary(value, index) {
  if (index >= value.length) return true;
  return !isSoftwareWordCharacter(value[index]);
}

// Position-major scan: the surface appearing earliest in `normalized` wins,
// ties at one position broken by table order (prefix collisions like app vs
// application are resolved by the end-boundary check, not order). Returns the
// matched { surface, payload } or null. Mirrors scan_match in
// src/solver_handlers/software_project.rs.
function scanSoftwareSurface(normalized, table) {
  const text = String(normalized || "");
  for (let index = 0; index < text.length; index += 1) {
    if (!isSoftwareStartBoundary(text, index)) continue;
    for (const [surface, payload] of table) {
      if (surface && text.startsWith(surface, index)) {
        if (isSoftwareEndBoundary(text, index + surface.length)) {
          return { surface, payload };
        }
      }
    }
  }
  return null;
}

// Lowercased union of every surface word (all languages) of the meanings that
// carry ROLE_SOFTWARE_REQUIREMENT_CATEGORY. A clause containing any of them
// states a feature requirement. Mirrors requirement_marker_words in
// src/solver_handlers/software_project.rs — no hardcoded marker list; the
// vocabulary lives in data/seed/meanings-software-project.lino.
function requirementMarkerWords() {
  return wordsForRole(ROLE_SOFTWARE_REQUIREMENT_CATEGORY)
    .filter((word) => word.length > 0)
    .map((word) => word.toLowerCase());
}

const GAME_TRACKER_TYPESCRIPT = `type Cooldown = {
  name: string;
  remainingRounds: number;
};

type UnitState = {
  id: string;
  name: string;
  hp: number;
  maxHp: number;
  protection: number;
  resistance: number;
  cooldowns: Cooldown[];
};

type DamageResult = {
  damageTaken: number;
  prevented: number;
  unit: UnitState;
};

export function mitigateDamage(unit: UnitState, rawDamage: number): DamageResult {
  const prevented = Math.max(0, unit.protection) + Math.max(0, unit.resistance);
  const damageTaken = Math.max(0, rawDamage - prevented);
  return {
    damageTaken,
    prevented,
    unit: { ...unit, hp: Math.max(0, unit.hp - damageTaken) },
  };
}

export function setStacks(
  unit: UnitState,
  protection: number,
  resistance: number,
): UnitState {
  return {
    ...unit,
    protection: Math.max(0, protection),
    resistance: Math.max(0, resistance),
  };
}

export function tickCooldowns(unit: UnitState): UnitState {
  return {
    ...unit,
    cooldowns: unit.cooldowns
      .map((cooldown) => ({
        ...cooldown,
        remainingRounds: Math.max(0, cooldown.remainingRounds - 1),
      }))
      .filter((cooldown) => cooldown.remainingRounds > 0),
  };
}`;

const GENERIC_PROJECT_TYPESCRIPT = `type ProjectRecord = {
  id: string;
  title: string;
  status: "open" | "done";
  notes: string[];
};

type ProjectCommand =
  | { type: "add"; id: string; title: string }
  | { type: "note"; id: string; note: string }
  | { type: "complete"; id: string };

export function applyCommand(
  records: ProjectRecord[],
  command: ProjectCommand,
): ProjectRecord[] {
  switch (command.type) {
    case "add":
      return [
        ...records,
        { id: command.id, title: command.title, status: "open", notes: [] },
      ];
    case "note":
      return records.map((record) =>
        record.id === command.id
          ? { ...record, notes: [...record.notes, command.note] }
          : record,
      );
    case "complete":
      return records.map((record) =>
        record.id === command.id ? { ...record, status: "done" } : record,
      );
  }
}`;

const GENERIC_PROJECT_JAVASCRIPT = `export function applyCommand(records, command) {
  switch (command.type) {
    case "add":
      return [...records, { id: command.id, title: command.title, status: "open", notes: [] }];
    case "note":
      return records.map((record) =>
        record.id === command.id
          ? { ...record, notes: [...record.notes, command.note] }
          : record,
      );
    case "complete":
      return records.map((record) =>
        record.id === command.id ? { ...record, status: "done" } : record,
      );
    default:
      throw new Error("Unknown command: " + command.type);
  }
}`;

const GENERIC_PROJECT_PYTHON = `from dataclasses import dataclass, field


@dataclass(frozen=True)
class ProjectRecord:
    id: str
    title: str
    status: str = "open"
    notes: tuple[str, ...] = field(default_factory=tuple)


def apply_command(records: tuple[ProjectRecord, ...], command: dict) -> tuple[ProjectRecord, ...]:
    if command["type"] == "add":
        return (*records, ProjectRecord(id=command["id"], title=command["title"]))
    if command["type"] == "note":
        return tuple(
            ProjectRecord(r.id, r.title, r.status, (*r.notes, command["note"]))
            if r.id == command["id"] else r
            for r in records
        )
    if command["type"] == "complete":
        return tuple(
            ProjectRecord(r.id, r.title, "done", r.notes)
            if r.id == command["id"] else r
            for r in records
        )
    raise ValueError(f"Unknown command: {command['type']}")
`;

const GENERIC_PROJECT_RUST = `#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectRecord {
    pub id: String,
    pub title: String,
    pub status: ProjectStatus,
    pub notes: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ProjectStatus {
    Open,
    Done,
}

pub enum ProjectCommand {
    Add { id: String, title: String },
    Note { id: String, note: String },
    Complete { id: String },
}

pub fn apply_command(mut records: Vec<ProjectRecord>, command: ProjectCommand) -> Vec<ProjectRecord> {
    match command {
        ProjectCommand::Add { id, title } => records.push(ProjectRecord {
            id,
            title,
            status: ProjectStatus::Open,
            notes: Vec::new(),
        }),
        ProjectCommand::Note { id, note } => {
            for record in &mut records {
                if record.id == id {
                    record.notes.push(note.clone());
                }
            }
        }
        ProjectCommand::Complete { id } => {
            for record in &mut records {
                if record.id == id {
                    record.status = ProjectStatus::Done;
                }
            }
        }
    }
    records
}`;

const PLAYWRIGHT_DOCS_URL = "https://playwright.dev/docs/writing-tests";
const PLAYWRIGHT_STARTER_TYPESCRIPT = `import { test, expect } from '@playwright/test';

test('opens the Playwright docs', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await expect(page).toHaveTitle(/Playwright/);

  await page.getByRole('link', { name: 'Docs' }).click();
  await expect(page.getByRole('heading', { name: /Playwright/ })).toBeVisible();
});`;

function containsAnySubstring(value, needles) {
  return needles.some((needle) => value.includes(needle));
}

function containsToken(normalized, token) {
  return String(normalized || "").split(/\s+/).includes(token);
}

// Issue #386 Playwright roles — mirror ROLE_PLAYWRIGHT_TOOL_NAME and
// ROLE_PLAYWRIGHT_SCRIPT_CUE in src/seed/roles.rs. The tool name (with its
// 'playright' misspelling, whose `action` names the canonical spelling) and the
// script-authoring cues live in data/seed/meanings-playwright.lino (embedded in
// MEANINGS_LINO above). isPlaywrightScriptRequest matches both roles as raw
// substrings across every language, exactly like the Rust recogniser.
const ROLE_PLAYWRIGHT_TOOL_NAME = "playwright_tool_name";
const ROLE_PLAYWRIGHT_SCRIPT_CUE = "playwright_script_cue";

function isPlaywrightScriptRequest(normalized) {
  return (
    lexiconMentionsRoleSubstring(ROLE_PLAYWRIGHT_TOOL_NAME, normalized) &&
    lexiconMentionsRoleSubstring(ROLE_PLAYWRIGHT_SCRIPT_CUE, normalized)
  );
}

// True when the prompt contains a misspelled form of the Playwright name — any
// playwright_tool_name form whose `action` names the canonical spelling. The
// misspelling and its correction live in the seed data, so the handler reports
// the fix without naming either form here. Mirrors
// mentions_playwright_misspelling in src/solver_handlers/playwright_script.rs.
function mentionsPlaywrightMisspelling(normalized) {
  return roleWordForms(ROLE_PLAYWRIGHT_TOOL_NAME)
    .filter((form) => form.action)
    .some((form) => normalized.includes(form.text));
}

function renderPlaywrightClarification(language) {
  if (language === "ru") {
    return [
      "Я могу написать Playwright-скрипт. Уточните URL страницы, действия и ожидаемую проверку.",
      "Если нужен пример по умолчанию, я могу взять стартовый сценарий из документации Playwright.",
    ].join(" ");
  }
  return [
    "I can write a Playwright script. Please provide the page URL, the actions to perform, and the expected assertion.",
    "If you want a default example, I can use the starter scenario from the Playwright docs.",
  ].join(" ");
}

function renderPlaywrightStarter(language, correctedSpelling) {
  const lines = [];
  if (language === "ru" && correctedSpelling) {
    lines.push(
      "Я трактую `Playright` как `Playwright` и даю стартовый TypeScript-пример по документации Playwright.",
    );
  } else if (language === "ru") {
    lines.push("Даю стартовый TypeScript-пример по документации Playwright.");
  } else if (correctedSpelling) {
    lines.push(
      "I interpret `Playright` as `Playwright` and will use a starter TypeScript example based on the Playwright docs.",
    );
  } else {
    lines.push(
      "I will use a starter TypeScript example based on the Playwright docs.",
    );
  }
  lines.push("");
  lines.push(`Source: ${PLAYWRIGHT_DOCS_URL}`);
  lines.push("");
  lines.push("```typescript");
  lines.push(PLAYWRIGHT_STARTER_TYPESCRIPT);
  lines.push("```");
  lines.push("");
  if (language === "ru") {
    lines.push("Проверка:");
    lines.push("1. `npm init playwright@latest`");
    lines.push("2. `npx playwright test`");
    lines.push("");
    lines.push("Уточните URL, действия и ожидаемый результат, если нужен сценарий под конкретный сайт.");
  } else {
    lines.push("Check it with:");
    lines.push("1. `npm init playwright@latest`");
    lines.push("2. `npx playwright test`");
    lines.push("");
    lines.push("Provide the URL, actions, and expected result if you want a site-specific script.");
  }
  return lines.join("\n");
}

function tryPlaywrightScript(prompt, preferences = {}, language = "en") {
  const normalized = normalizePrompt(prompt);
  if (!isPlaywrightScriptRequest(normalized)) return null;
  const guessProbability = numericPreference(
    preferences && preferences.guessProbability,
    0.8,
    0,
    1,
  );
  const evidence = [
    "script_framework:playwright",
    `source:${PLAYWRIGHT_DOCS_URL}`,
    `guess_probability:${guessProbability.toFixed(2)}`,
  ];
  const correctedSpelling = mentionsPlaywrightMisspelling(normalized);
  if (correctedSpelling) {
    evidence.push("spelling_correction:Playright->Playwright");
  }
  if (guessProbability < 0.5) {
    return {
      intent: "playwright_script_clarification",
      content: renderPlaywrightClarification(language),
      confidence: 0.64,
      evidence,
    };
  }
  return {
    intent: "playwright_script",
    content: renderPlaywrightStarter(language, correctedSpelling),
    confidence: 0.82,
    evidence,
  };
}

function detectSoftwareAction(normalized) {
  const match = scanSoftwareSurface(normalized, softwareActionTable());
  return match ? match.payload : null;
}

function detectSoftwareArtifact(normalized) {
  const match = scanSoftwareSurface(normalized, softwareArtifactTable());
  return match ? { surface: match.surface, label: match.payload } : null;
}

function extractSoftwareTarget(prompt, artifact) {
  const markers = [
    `${artifact.surface} for `,
    `${artifact.surface} to `,
    `${artifact.label} for `,
    `${artifact.label} to `,
    " for ",
    " to ",
  ];
  for (const marker of markers) {
    const target = extractAfterMarker(prompt, marker);
    if (target) return target;
  }
  return "the requested environment";
}

function extractAfterMarker(prompt, marker) {
  const source = String(prompt || "");
  const lower = source.toLowerCase();
  const lowerMarker = marker.toLowerCase();
  const start = lower.indexOf(lowerMarker);
  if (start < 0) return null;
  const tail = source.slice(start + lowerMarker.length);
  const stopMatch = /[?.,;\n]/.exec(tail);
  const stop = stopMatch ? stopMatch.index : tail.length;
  const raw = tail
    .slice(0, stop)
    .split(" with ")[0]
    .split(" that ")[0]
    .split(" and ")[0]
    .trim();
  if (!raw) return null;
  return capitalizeShortTarget(raw);
}

function capitalizeShortTarget(raw) {
  const compact = String(raw || "").trim().split(/\s+/).slice(0, 5).join(" ");
  if (!compact) return compact;
  if (/[A-ZА-Я]/.test(compact)) return compact;
  return compact.charAt(0).toUpperCase() + compact.slice(1);
}

function sentenceCase(raw) {
  const trimmed = String(raw || "").trim().replace(/^[-* ]+|[-* ]+$/g, "");
  if (!trimmed) return "";
  return trimmed.charAt(0).toUpperCase() + trimmed.slice(1);
}

function extractSoftwareFeatures(prompt) {
  const markers = requirementMarkerWords();
  const features = [];
  const segments = String(prompt || "").split(/[.;\n]/);
  for (const segment of segments) {
    for (const clause of segment.split(",")) {
      const cleaned = clause.trim();
      if (!cleaned) continue;
      const lower = cleaned.toLowerCase();
      if (!containsAnySubstring(lower, markers)) continue;
      const feature = sentenceCase(cleaned);
      if (feature && !features.includes(feature)) features.push(feature);
    }
  }
  if (features.length === 0) {
    features.push("Capture state, user commands, persistence, validation, and tests.");
  }
  return features;
}

// A request is a game-unit tracker only when it pairs a game domain with a
// combat mechanic — both the game_tracker_domain and game_tracker_mechanic
// roles must be evidenced. Mirrors is_game_unit_tracker in
// src/solver_handlers/software_project.rs; the decomposition lives in the
// lexicon, so the code knows only "a tracker needs both a domain and a mechanic".
function isGameUnitTracker(normalized) {
  return (
    lexiconMentionsRole(ROLE_GAME_TRACKER_DOMAIN, normalized) &&
    lexiconMentionsRole(ROLE_GAME_TRACKER_MECHANIC, normalized)
  );
}

function classifySoftwareRequirement(requirement, gameTracker) {
  const lower = String(requirement || "").toLowerCase();
  // A game unit tracker is state by construction, regardless of wording.
  if (gameTracker) {
    return "state_tracking";
  }
  // Walk the requirement-category meanings in declaration order; the first
  // whose surface word appears classifies the clause. Mirrors
  // classify_requirement in src/solver_handlers/software_project.rs. The
  // catch-all project_behavior comes last, so it acts as the default.
  for (const meaning of meaningsWithRole(ROLE_SOFTWARE_REQUIREMENT_CATEGORY)) {
    const label = SOFTWARE_REQUIREMENT_CATEGORY_LABELS[meaning.slug];
    if (!label) continue;
    if (meaning.words.some((word) => lower.includes(word.toLowerCase()))) {
      return label;
    }
  }
  return "project_behavior";
}

function softwareSubtaskTitle(category, requirement) {
  switch (category) {
    case "state_tracking":
      return `Model state fields and pure transitions for ${requirement}`;
    case "data_exchange":
      return `Define parsers, serializers, and backup flow for ${requirement}`;
    case "automation":
      return `Schedule deterministic jobs and delivery checks for ${requirement}`;
    case "validation":
      return `Encode validation rules and failure messages for ${requirement}`;
    case "integration":
      return `Isolate host API boundaries and mocks for ${requirement}`;
    case "user_interface":
      return `Design focused views and state updates for ${requirement}`;
    default:
      return `Implement and test the smallest behavior for ${requirement}`;
  }
}

function deriveSoftwareSubtasks(requirements, gameTracker) {
  return requirements.map((requirement, index) => {
    const category = classifySoftwareRequirement(requirement, gameTracker);
    return {
      requirementId: `R${index + 1}`,
      category,
      title: softwareSubtaskTitle(category, requirement),
    };
  });
}

// Pick the delivery mode by walking the software_delivery_mode meanings in
// declaration order (manual instructions → immediate execution → script
// generation — the order encodes priority) and taking the first one evidenced
// in the request; the default is generated code. Mirrors detect_delivery_mode
// in src/solver_handlers/software_project.rs — the surface words live in the
// lexicon, so the code knows only "a request can ask for a delivery mode".
function detectSoftwareDeliveryMode(normalized) {
  const meaning = firstRoleMatch(ROLE_SOFTWARE_DELIVERY_MODE, normalized);
  return (meaning && SOFTWARE_DELIVERY_MODE_LABELS[meaning.slug]) || "code_generation";
}

// Resolve the target language by walking the software_implementation_language
// meanings in declaration order (python → rust → javascript) and taking the
// first one named in the request; the default is TypeScript. Mirrors
// detect_implementation_language in src/solver_handlers/software_project.rs.
function detectSoftwareImplementationLanguage(normalized) {
  const meaning = firstRoleMatch(ROLE_SOFTWARE_IMPLEMENTATION_LANGUAGE, normalized);
  return (meaning && SOFTWARE_IMPLEMENTATION_LANGUAGE_LABELS[meaning.slug]) || "typescript";
}

// Mirrors approval_gates in src/solver_handlers/software_project.rs: the feature,
// step-granularity, and bash-command gates are added when the lexicon evidences
// the matching role, so the gate vocabulary lives once in data.
function softwareApprovalGates(normalized, deliveryMode) {
  const gates = ["task_formalization", "implementation_plan"];
  if (lexiconMentionsRole(ROLE_SOFTWARE_FEATURE, normalized)) gates.push("requirements");
  if (lexiconMentionsRole(ROLE_SOFTWARE_STEP_GRANULARITY, normalized)) gates.push("each_step");
  if (deliveryMode === "code_generation") {
    gates.push("generated_code");
  } else if (deliveryMode === "manual_instructions") {
    gates.push("manual_instructions");
  } else {
    gates.push("generated_script");
    gates.push("bash_command");
  }
  if (lexiconMentionsRole(ROLE_SOFTWARE_BASH_COMMAND, normalized)) {
    gates.push("bash_command");
  }
  return [...new Set(gates)].sort();
}

function softwareImplementationCode(meaning) {
  if (meaning.gameTracker) {
    return {
      label: "TypeScript",
      fence: "typescript",
      body: GAME_TRACKER_TYPESCRIPT,
    };
  }
  if (meaning.implementationLanguage === "python") {
    return { label: "Python", fence: "python", body: GENERIC_PROJECT_PYTHON };
  }
  if (meaning.implementationLanguage === "rust") {
    return { label: "Rust", fence: "rust", body: GENERIC_PROJECT_RUST };
  }
  if (meaning.implementationLanguage === "javascript") {
    return { label: "JavaScript", fence: "javascript", body: GENERIC_PROJECT_JAVASCRIPT };
  }
  return { label: "TypeScript", fence: "typescript", body: GENERIC_PROJECT_TYPESCRIPT };
}

function softwareDomainLabel(meaning) {
  return meaning.gameTracker ? "tabletop_game_unit_tracker" : "software_project";
}

function softwareApprovalLabel(approved) {
  return approved ? "approved" : "proposed";
}

function linoString(value) {
  return `"${String(value || "")
    .replace(/\\/g, "\\\\")
    .replace(/"/g, '\\"')
    .replace(/\n/g, "\\n")
    .replace(/\r/g, "\\r")}"`;
}

function softwareMeaningLino(meaning, approved) {
  const lines = ["software_project_request"];
  lines.push(`  action ${linoString(meaning.action)}`);
  lines.push(`  artifact ${linoString(meaning.artifact)}`);
  lines.push(`  artifact_surface ${linoString(meaning.artifactSurface)}`);
  lines.push(`  target ${linoString(meaning.target)}`);
  lines.push(`  domain ${linoString(softwareDomainLabel(meaning))}`);
  lines.push(`  delivery_mode ${meaning.deliveryMode}`);
  lines.push(`  implementation_language ${linoString(meaning.implementationLanguage)}`);
  lines.push(`  approval_state ${softwareApprovalLabel(approved)}`);
  lines.push("  approval_required true");
  for (const gate of meaning.approvalGates) {
    lines.push(`  approval_gate ${linoString(gate)}`);
  }
  for (const requirement of meaning.requirements) {
    lines.push(`  requirement ${linoString(requirement)}`);
    lines.push(
      `  requirement_category ${linoString(
        classifySoftwareRequirement(requirement, meaning.gameTracker),
      )}`,
    );
  }
  for (const subtask of meaning.subtasks) {
    lines.push(
      `  subtask ${linoString(
        `${subtask.requirementId} [${subtask.category}] ${subtask.title}`,
      )}`,
    );
  }
  if (meaning.gameTracker) {
    lines.push('  state_model "unit_state"');
    lines.push('  command "apply_damage"');
    lines.push('  command "set_stacks"');
    lines.push('  command "tick_cooldowns"');
    lines.push('  validation "damage_mitigation_floor_at_zero"');
    lines.push('  validation "cooldowns_decrement_without_negative_rounds"');
  } else {
    lines.push('  state_model "project_records"');
    lines.push('  command "create_record"');
    lines.push('  command "update_record"');
    lines.push('  command "export_state"');
    lines.push('  validation "pure_state_transitions_before_host_api"');
  }
  return lines.join("\n") + "\n";
}

function softwareMeaningKey(meaning) {
  return [
    `action=${meaning.action}`,
    `artifact=${meaning.artifact}`,
    `target=${meaning.target}`,
    `game_tracker=${meaning.gameTracker}`,
    `delivery_mode=${meaning.deliveryMode}`,
    `implementation_language=${meaning.implementationLanguage}`,
    ...meaning.requirements.map((requirement) => `requirement=${requirement}`),
    ...meaning.subtasks.map((subtask) => `subtask=${subtask.category}:${subtask.title}`),
  ].join(";");
}

function stableSoftwareMeaningId(meaning) {
  let hash = 0xcbf29ce484222325n;
  const source = softwareMeaningKey(meaning);
  for (let index = 0; index < source.length; index += 1) {
    hash ^= BigInt(source.charCodeAt(index));
    hash = BigInt.asUintN(64, hash * 0x100000001b3n);
  }
  return `software_project_request_${hash.toString(16)}`;
}

function formalizeSoftwareProjectRequest(prompt) {
  const normalized = normalizePrompt(prompt);
  if (normalized.includes("hello") && normalized.includes("world")) return null;
  const action = detectSoftwareAction(normalized);
  const artifact = detectSoftwareArtifact(normalized);
  if (!action || !artifact) return null;
  const requirements = extractSoftwareFeatures(prompt);
  const gameTracker = isGameUnitTracker(normalized);
  const deliveryMode = detectSoftwareDeliveryMode(normalized);
  return {
    action,
    artifactSurface: artifact.surface,
    artifact: artifact.label,
    target: extractSoftwareTarget(prompt, artifact),
    requirements,
    subtasks: deriveSoftwareSubtasks(requirements, gameTracker),
    deliveryMode,
    implementationLanguage: detectSoftwareImplementationLanguage(normalized),
    approvalGates: softwareApprovalGates(normalized, deliveryMode),
    gameTracker,
  };
}

function softwareReasoningSteps(meaning) {
  const steps = [
    `Classify the impulse as a request to ${meaning.action} a ${meaning.artifact} instead of a fact lookup.`,
    `Bind the target environment to ${meaning.target} and keep the first response reviewable.`,
    `Extract ${meaning.requirements.length} requirement(s) into the meaning record before planning.`,
    `Decompose the requirement graph into ${meaning.subtasks.length} implementation subtask(s) with category labels.`,
    `Select delivery mode ${meaning.deliveryMode} and approval gates: ${meaning.approvalGates.join(", ")}.`,
  ];
  if (meaning.gameTracker) {
    steps.push(
      "Map HP, Protection, Resistance, damage, and cooldown phrases to a unit-state domain model.",
    );
  }
  steps.push("Ask for approval before producing code, scripts, manual instructions, or execution steps.");
  return steps;
}

function softwarePlanSteps(meaning) {
  const steps = [
    "Review the formalized task, requirement graph, approval gates, and delivery mode with the user.",
  ];
  if (meaning.gameTracker) {
    steps.push(
      `Confirm the ${meaning.target} storage and selected-token API boundaries.`,
      "Define `UnitState` with HP, max HP, Protection, Resistance, and cooldowns.",
      "Write pure transition functions for damage mitigation, stack edits, and round ticks.",
      "Add tests for zero damage, overkill damage, stack changes, and cooldown expiry.",
      "Wire the tested core into the extension panel and host persistence.",
    );
    return steps;
  }
  steps.push(
    `Confirm the host API and data boundaries for ${meaning.target}.`,
    "Define the smallest serializable state records for the requirements.",
  );
  for (const subtask of meaning.subtasks) {
    steps.push(`Implement ${subtask.category}: ${subtask.title}.`);
  }
  steps.push(
    `Generate a ${meaning.implementationLanguage} starter core plus language-appropriate repository initialization and checks.`,
  );
  steps.push("Keep shell, Docker, or WebVM commands behind the configured approval gates.");
  return steps;
}

function softwareEvidence(meaning, approved) {
  const evidence = [
    "formalization:text_to_links_notation",
    `meaning:${stableSoftwareMeaningId(meaning)}`,
    `software_project:action:${meaning.action}`,
    `software_project:artifact:${meaning.artifact}`,
    `software_project:target:${meaning.target}`,
    `software_project:domain:${softwareDomainLabel(meaning)}`,
    `software_project:delivery_mode:${meaning.deliveryMode}`,
    `software_project:implementation_language:${meaning.implementationLanguage}`,
    `approval_state:${softwareApprovalLabel(approved)}`,
    `software_project:strategy:${meaning.gameTracker ? "game_unit_tracker" : "bounded_project_plan"}`,
  ];
  for (const gate of meaning.approvalGates) {
    evidence.push(`approval_gate:${gate}`);
  }
  for (const requirement of meaning.requirements) {
    evidence.push(`requirement:${requirement}`);
    evidence.push(`requirement_category:${classifySoftwareRequirement(requirement, meaning.gameTracker)}`);
  }
  for (const subtask of meaning.subtasks) {
    evidence.push(`software_project:subtask:${subtask.requirementId}:${subtask.category}:${subtask.title}`);
  }
  return evidence;
}

function renderSoftwareProjectPlan(meaning) {
  const lines = [];
  lines.push(
    `Implementation plan pending approval for a ${meaning.artifact} targeting ${meaning.target}.`,
  );
  lines.push("");
  lines.push("Formalized meaning:");
  lines.push("```lino");
  lines.push(softwareMeaningLino(meaning, false).trimEnd());
  lines.push("```");
  lines.push("");
  lines.push("Reasoning steps:");
  softwareReasoningSteps(meaning).forEach((step, index) => {
    lines.push(`${index + 1}. ${step}`);
  });
  lines.push("");
  lines.push("Requirement model:");
  meaning.requirements.forEach((requirement, index) => {
    const category = classifySoftwareRequirement(requirement, meaning.gameTracker);
    lines.push(`${index + 1}. [${category}] ${requirement}`);
  });
  lines.push("");
  lines.push("Subtasks:");
  meaning.subtasks.forEach((subtask, index) => {
    lines.push(`${index + 1}. ${subtask.requirementId} -> ${subtask.title}`);
  });
  lines.push("");
  lines.push("Approval gates:");
  meaning.approvalGates.forEach((gate) => {
    lines.push(`- ${gate}`);
  });
  lines.push("");
  lines.push("Proposed plan:");
  softwarePlanSteps(meaning).forEach((step, index) => {
    lines.push(`${index + 1}. ${step}`);
  });
  lines.push("");
  lines.push(
    "Reply `approve plan` to generate the starter implementation, or describe what to change.",
  );
  return lines.join("\n");
}

function renderSoftwareProjectImplementation(meaning) {
  const lines = [];
  lines.push(
    `Approved implementation starter for a ${meaning.artifact} targeting ${meaning.target}.`,
  );
  lines.push("");
  lines.push("Formalized meaning:");
  lines.push("```lino");
  lines.push(softwareMeaningLino(meaning, true).trimEnd());
  lines.push("```");
  lines.push("");
  lines.push("Implementation steps:");
  softwarePlanSteps(meaning).forEach((step, index) => {
    lines.push(`${index + 1}. ${step}`);
  });
  lines.push("");
  const code = softwareImplementationCode(meaning);
  lines.push(`Starter ${code.label} core:`);
  lines.push("");
  lines.push(`\`\`\`${code.fence}`);
  lines.push(code.body);
  lines.push("```");
  lines.push("");
  lines.push("Generated code checks:");
  lines.push(`1. Initialize a ${code.label} project in an isolated workspace.`);
  lines.push("2. Run the language-native syntax/type check before host integration.");
  return lines.join("\n");
}

// Mirror is_approval_prompt in src/solver_handlers/software_project.rs: strip
// leading/trailing non-alphanumerics (Unicode-aware, so a non-Latin go-ahead
// compacts the same way), drop interior sentence punctuation, then match the
// whole compacted prompt against any approval-trigger surface word. The words
// live in data/seed/meanings-software-project.lino, not in code.
function isSoftwareApprovalPrompt(normalized) {
  const compact = String(normalized || "")
    .trim()
    .replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, "")
    .replace(/[.!,]/g, "");
  return meaningsWithRole(ROLE_SOFTWARE_APPROVAL_TRIGGER).some((meaning) =>
    meaning.words.some((word) => compact === word),
  );
}

function lastHistoryTurn(history, role) {
  if (!Array.isArray(history)) return null;
  for (let index = history.length - 1; index >= 0; index -= 1) {
    const turn = history[index];
    if (turn && turn.role === role && turn.content) return String(turn.content);
  }
  return null;
}

function priorSoftwareProjectMeaning(history) {
  const assistant = lastHistoryTurn(history, "assistant");
  if (
    !assistant ||
    !assistant.includes("software_project_request") ||
    !assistant.includes("approve plan")
  ) {
    return null;
  }
  const user = lastHistoryTurn(history, "user");
  return user ? formalizeSoftwareProjectRequest(user) : null;
}

function trySoftwareProjectRequest(prompt, history = []) {
  const normalized = normalizePrompt(prompt);
  if (isSoftwareApprovalPrompt(normalized)) {
    const prior = priorSoftwareProjectMeaning(history);
    if (prior) {
      return {
        intent: "software_project_implementation",
        content: renderSoftwareProjectImplementation(prior),
        confidence: 0.82,
        evidence: softwareEvidence(prior, true),
      };
    }
  }

  const meaning = formalizeSoftwareProjectRequest(prompt);
  if (!meaning) return null;

  return {
    intent: "software_project_plan",
    content: renderSoftwareProjectPlan(meaning),
    confidence: 0.78,
    evidence: softwareEvidence(meaning, false),
  };
}

// Maps a follow-up kind to the imperative verb used when rendering it. Mirrors
// `FollowUpKind::action` in src/solver_handlers/software_project_followup.rs.
// The surface words that *recognise* each kind no longer live here — they are
// self-describing meanings in data/seed/meanings-software-project.lino, queried
// by detectSoftwareFollowUp via the software_followup_* roles (issue #386).
const SOFTWARE_FOLLOW_UP_ACTIONS = {
  verification: "test",
  execution: "run",
  demonstration: "show",
};

const SOFTWARE_FOLLOW_UP_GATES = ["generated_code", "test_execution", "network_access"];

// Recover the active software-project dialogue from history regardless of
// whether the plan was approved. Mirrors `prior_software_project_dialogue`.
function priorSoftwareProjectDialogue(history) {
  const assistant = lastHistoryTurn(history, "assistant");
  if (!assistant || !assistant.includes("software_project_request")) {
    return null;
  }
  const approved = assistant.includes("approval_state approved");
  const user = lastHistoryTurn(history, "user");
  const meaning = user ? formalizeSoftwareProjectRequest(user) : null;
  return meaning ? { meaning, approved } : null;
}

// Pull the first domain-like token (e.g. `wikipedia.org`) out of the prompt.
function extractFollowUpTargetSite(prompt) {
  for (const raw of String(prompt || "").split(/\s+/)) {
    const token = raw.replace(/^[^A-Za-z0-9]+|[^A-Za-z0-9]+$/g, "");
    if (!token.includes(".")) continue;
    const lastDot = token.lastIndexOf(".");
    const host = token.slice(0, lastDot);
    const tld = token.slice(lastDot + 1);
    if (
      tld.length >= 2 &&
      /^[A-Za-z]+$/.test(tld) &&
      /[A-Za-z]/.test(host)
    ) {
      return token.toLowerCase();
    }
  }
  return null;
}

// Capture the clause after "show me"/"show"/"print"/"display" (capped at 12
// words) so the follow-up records what the user wants surfaced.
function extractFollowUpExpectedOutput(prompt) {
  const source = String(prompt || "");
  const lower = source.toLowerCase();
  for (const marker of ["show me ", "show ", "print ", "display "]) {
    const found = lower.indexOf(marker);
    if (found < 0) continue;
    const start = found + marker.length;
    const tail = source.slice(start);
    const stopMatch = tail.match(/[.?\n;]/);
    const stop = stopMatch ? stopMatch.index : tail.length;
    const clause = tail
      .slice(0, stop)
      .split(/\s+/)
      .filter(Boolean)
      .slice(0, 12)
      .join(" ");
    if (clause) return clause;
  }
  return null;
}

// Recognise which follow-up a prompt evidences by *meaning*, not a hardcoded
// per-language marker table (issue #386). Each follow-up kind is a
// self-describing meaning in data/seed/meanings-software-project.lino; its
// surface words (every supported language) live there, while this code knows
// only the concepts and their precedence — verification outranks execution
// outranks demonstration, so a combined "test it and run it" records the
// stronger goal. Mirrors follow_up_kind in
// src/solver_handlers/software_project_followup.rs.
function detectSoftwareFollowUp(prompt, normalized) {
  let kind = null;
  for (const [role, candidate] of [
    [ROLE_SOFTWARE_FOLLOWUP_VERIFICATION, "verification"],
    [ROLE_SOFTWARE_FOLLOWUP_EXECUTION, "execution"],
    [ROLE_SOFTWARE_FOLLOWUP_DEMONSTRATION, "demonstration"],
  ]) {
    if (lexiconMentionsRoleSubstring(role, normalized)) {
      kind = candidate;
      break;
    }
  }
  if (!kind) return null;
  return {
    kind,
    action: SOFTWARE_FOLLOW_UP_ACTIONS[kind],
    targetSite: extractFollowUpTargetSite(prompt),
    expectedOutput: extractFollowUpExpectedOutput(prompt),
  };
}

function followUpMeaningId(meaning, followUp) {
  const key = [
    `parent=${stableSoftwareMeaningId(meaning)}`,
    `kind=${followUp.kind}`,
    `site=${followUp.targetSite || ""}`,
    `output=${followUp.expectedOutput || ""}`,
  ].join(";");
  return stableBehaviorRuleId("software_project_followup", key);
}

function followUpReasoningSteps(meaning, followUp) {
  const steps = [
    `Recognize "${followUp.action}" as a ${followUp.kind} request that exercises the ${meaning.artifact} from the active plan, not a fact lookup.`,
  ];
  if (followUp.targetSite) {
    steps.push(
      `Bind the test target to ${followUp.targetSite} and keep live fetches behind the network_access gate.`,
    );
  }
  if (followUp.expectedOutput) {
    steps.push(
      `Record the expected output as "${followUp.expectedOutput}" so the test harness can assert it.`,
    );
  }
  steps.push(
    "Drive the artifact through a deterministic fixture before any host API or network call.",
  );
  steps.push(
    "Keep code execution behind approval gates because the sandbox cannot run untrusted code.",
  );
  return steps;
}

function followUpPlanSteps(meaning, followUp) {
  const site = followUp.targetSite || "the requested target";
  const steps = [
    `Generate the ${meaning.artifact} core plus a deterministic test harness with a captured ${site} fixture.`,
    "Assert each requirement (parsing, extraction, counting, summary) against the fixture.",
  ];
  if (followUp.expectedOutput) {
    steps.push(`Surface ${followUp.expectedOutput} from the fixture run.`);
  }
  steps.push(
    `Run the ${meaning.implementationLanguage} test command once the generated_code gate is approved.`,
  );
  steps.push(
    `Promote the run to live ${site} only after the test_execution and network_access gates pass.`,
  );
  return steps;
}

function followUpEvidence(meaning, followUp, approved) {
  const evidence = [
    "formalization:text_to_links_notation",
    `meaning:${followUpMeaningId(meaning, followUp)}`,
    `software_project:parent:${stableSoftwareMeaningId(meaning)}`,
    `software_project:follow_up_kind:${followUp.kind}`,
  ];
  if (followUp.targetSite) {
    evidence.push(`software_project:target_site:${followUp.targetSite}`);
  }
  if (followUp.expectedOutput) {
    evidence.push(`software_project:expected_output:${followUp.expectedOutput}`);
  }
  evidence.push(`approval_state:${softwareApprovalLabel(approved)}`);
  for (const gate of SOFTWARE_FOLLOW_UP_GATES) {
    evidence.push(`approval_gate:${gate}`);
  }
  return evidence;
}

function renderSoftwareProjectFollowUp(meaning, followUp, approved) {
  const lines = [];
  lines.push(
    `Recorded a ${followUp.kind} follow-up for the ${meaning.artifact} from the active plan.`,
  );
  lines.push("");
  lines.push("Formalized meaning:");
  lines.push("```lino");
  lines.push("software_project_followup");
  lines.push(`  parent_request ${linoString(stableSoftwareMeaningId(meaning))}`);
  lines.push(`  parent_artifact ${linoString(meaning.artifact)}`);
  lines.push(`  action ${linoString(followUp.action)}`);
  lines.push(`  follow_up_kind ${followUp.kind}`);
  if (followUp.targetSite) {
    lines.push(`  target_site ${linoString(followUp.targetSite)}`);
  }
  if (followUp.expectedOutput) {
    lines.push(`  expected_output ${linoString(followUp.expectedOutput)}`);
  }
  lines.push(`  delivery_mode ${meaning.deliveryMode}`);
  lines.push(`  implementation_language ${linoString(meaning.implementationLanguage)}`);
  lines.push(`  approval_state ${softwareApprovalLabel(approved)}`);
  lines.push("  approval_required true");
  for (const gate of SOFTWARE_FOLLOW_UP_GATES) {
    lines.push(`  approval_gate ${linoString(gate)}`);
  }
  lines.push("```");
  lines.push("");
  lines.push("Reasoning steps:");
  followUpReasoningSteps(meaning, followUp).forEach((step, index) => {
    lines.push(`${index + 1}. ${step}`);
  });
  lines.push("");
  lines.push("Verification plan:");
  followUpPlanSteps(meaning, followUp).forEach((step, index) => {
    lines.push(`${index + 1}. ${step}`);
  });
  lines.push("");
  if (approved) {
    lines.push(
      "The plan is approved, so the generated starter already includes this test harness. " +
        "Running it live needs the test_execution and network_access gates.",
    );
  } else {
    lines.push(
      "Reply `approve plan` to generate the artifact plus this test harness. Running it live " +
        "against the target needs the test_execution and network_access gates.",
    );
  }
  return lines.join("\n");
}

// Follow-up handler for an active software-project dialogue (issue #341). Runs
// before `tryConceptLookup` so a decomposed step like "test it by scraping
// wikipedia.org and show me the top 10 most frequent words" stays bound to the
// project instead of resolving the `wikipedia` concept or falling to the
// unknown opener. Mirrors `try_software_project_followup` in the Rust solver.
function trySoftwareProjectFollowup(prompt, history = []) {
  const normalized = normalizePrompt(prompt);
  // Approval prompts stay with the main request handler, which advances to the
  // implementation starter.
  if (isSoftwareApprovalPrompt(normalized)) return null;
  const dialogue = priorSoftwareProjectDialogue(history);
  if (!dialogue) return null;
  const followUp = detectSoftwareFollowUp(prompt, normalized);
  if (!followUp) return null;
  return {
    intent: "software_project_followup",
    content: renderSoftwareProjectFollowUp(dialogue.meaning, followUp, dialogue.approved),
    confidence: 0.74,
    evidence: followUpEvidence(dialogue.meaning, followUp, dialogue.approved),
  };
}

function tryJavaScriptExecution(prompt) {
  const program = extractJavaScriptProgram(prompt);
  if (program === null) return null;
  const logs = [];
  const captureConsole = {
    log: (...args) =>
      logs.push(
        args
          .map((value) =>
            typeof value === "string" ? value : JSON.stringify(value),
          )
          .join(" "),
      ),
  };
  let result;
  let error = null;
  try {
    const runner = new Function(
      "console",
      `"use strict"; return (function(){ ${program}\n })();`,
    );
    result = runner(captureConsole);
  } catch (err) {
    error = err;
  }
  const lines = [];
  lines.push("Execution status: ran in the demo's Web Worker sandbox.");
  lines.push("Source:");
  lines.push("```javascript");
  lines.push(program);
  lines.push("```");
  if (error) {
    lines.push("");
    lines.push(`Error: ${error.message || String(error)}`);
  } else {
    if (logs.length > 0) {
      lines.push("");
      lines.push("Output:");
      lines.push("```text");
      lines.push(logs.join("\n"));
      lines.push("```");
    }
    if (result !== undefined) {
      lines.push("");
      lines.push(`Returned: \`${String(result)}\``);
    }
    if (logs.length === 0 && result === undefined) {
      lines.push("");
      lines.push("Program completed without output or return value.");
    }
  }
  lines.push("");
  lines.push(
    "Note: the browser worker has no DOM or network access, so side effects are limited.",
  );
  return {
    intent: error ? "javascript_execution_error" : "javascript_execution",
    content: lines.join("\n"),
    confidence: error ? 0.5 : 0.95,
    evidence: [
      `execution_status:javascript:${error ? "error" : "ran"}`,
      "language:javascript",
    ],
  };
}

// `saveAs`, `setupHint`, `runCommand` and `checkCommand` mirror the same fields
// on `coding::catalog::ProgramLanguage` so the demo's novice "How to test it
// yourself" steps match the Rust engine exactly (issue #330). No entry carries
// its alias surfaces inline: the words a prompt must contain to resolve a
// language live in the `program_language_<slug>` meaning (role
// `program_language_alias`) and `programLanguageFromPrompt` reads them by slug
// (issue #386), matching the Rust catalog byte-for-byte through the shared seed.
const WRITE_PROGRAM_LANGUAGES = {
  rust: {
    name: "Rust",
    fence: "rust",
    saveAs: "main.rs",
    setupHint: "the Rust toolchain from https://rustup.rs",
    checkCommand: "rustc main.rs -o main",
    runCommand: "./main",
  },
  python: {
    name: "Python",
    fence: "python",
    saveAs: "main.py",
    setupHint: "Python 3 from https://www.python.org/downloads/",
    checkCommand: "python3 -m py_compile main.py",
    runCommand: "python3 main.py",
  },
  javascript: {
    name: "JavaScript",
    fence: "javascript",
    saveAs: "main.js",
    setupHint: "Node.js from https://nodejs.org/",
    checkCommand: "node --check main.js",
    runCommand: "node main.js",
  },
  typescript: {
    name: "TypeScript",
    fence: "typescript",
    saveAs: "hello.ts",
    setupHint:
      "Node.js from https://nodejs.org/ plus TypeScript via `npm install -g typescript`",
    checkCommand: "tsc hello.ts",
    runCommand: "node hello.js",
  },
  go: {
    name: "Go",
    fence: "go",
    saveAs: "main.go",
    setupHint: "Go from https://go.dev/dl/",
    checkCommand: null,
    runCommand: "go run main.go",
  },
  c: {
    name: "C",
    fence: "c",
    saveAs: "main.c",
    setupHint:
      "a C compiler such as GCC from https://gcc.gnu.org/ or your package manager",
    checkCommand: "gcc main.c -o main",
    runCommand: "./main",
  },
  cpp: {
    name: "C++",
    fence: "cpp",
    saveAs: "main.cpp",
    setupHint:
      "a C++ compiler such as g++ from https://gcc.gnu.org/ or your package manager",
    checkCommand: "g++ main.cpp -o main",
    runCommand: "./main",
  },
  java: {
    name: "Java",
    fence: "java",
    saveAs: "Main.java",
    setupHint: "a JDK from https://adoptium.net/",
    checkCommand: "javac Main.java",
    runCommand: "java Main",
  },
  csharp: {
    name: "C#",
    fence: "csharp",
    saveAs: "Program.cs",
    setupHint: "the .NET SDK from https://dotnet.microsoft.com/download",
    checkCommand: "dotnet build",
    runCommand: "dotnet run",
  },
  ruby: {
    name: "Ruby",
    fence: "ruby",
    saveAs: "main.rb",
    setupHint: "Ruby from https://www.ruby-lang.org/en/downloads/",
    checkCommand: "ruby -c main.rb",
    runCommand: "ruby main.rb",
  },
};

const WRITE_PROGRAM_TASKS = {
  hello_world: {
    label: "hello world",
    output: "Hello, world!",
  },
  count_to_three: {
    label: "count to three",
    output: "1\n2\n3",
  },
  list_files: {
    label: "list files in the current directory",
    // Verified output for the documented sample directory containing exactly
    // `Cargo.toml`, `README.md`, and `main.rs`. Every template sorts names in
    // byte order, so the output is identical across languages (issue #312).
    output: "Cargo.toml\nREADME.md\nmain.rs",
  },
  list_files_arg: {
    label: "list files in the directory given as a path argument",
    // Issue #324 follow-up: "Сделай так, чтобы программа принимала путь как
    // аргумент" (make the program accept a path as an argument). This is the
    // path-argument variant of `list_files`; conversation context maps a bare
    // "accept a path argument" modification onto it through the program-plan
    // rules. Mirrors the Rust `list_files_arg` task.
    output: "Cargo.toml\nREADME.md\nmain.rs",
  },
  list_files_reverse_sort: {
    label: "list files in the current directory in reverse-sorted order",
    output: "main.rs\nREADME.md\nCargo.toml",
  },
  list_files_arg_reverse_sort: {
    label: "list files from a path argument in reverse-sorted order",
    output: "main.rs\nREADME.md\nCargo.toml",
  },
  // Issue #330: classic branching/looping exercise over 1..=15. Mirrors the Rust
  // `fizzbuzz` task; fixed range so the output is deterministic and verifiable.
  fizzbuzz: {
    label: "FizzBuzz",
    output: "1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz",
  },
  // Issue #330: fixed to 5! = 120 so the verified output is unambiguous (the
  // aliases require the number 5). Mirrors the Rust `factorial` task.
  factorial: {
    label: "factorial of 5",
    output: "120",
  },
  // Issue #330: reverses the literal string "hello" -> "olleh". Mirrors the Rust
  // `reverse_string` task; fixed input keeps the output verifiable.
  reverse_string: {
    label: "string reversal",
    output: "olleh",
  },
  // Issue #330: sums 1..=10 -> 55. Mirrors the Rust `sum_to_ten` task.
  sum_to_ten: {
    label: "sum from 1 to 10",
    output: "55",
  },
  // Issue #334: a recursive `fibonacci` function evaluated at the 10th term
  // (F(1)=F(2)=1 -> F(10)=55). Mirrors the Rust `fibonacci` task; fixed index so
  // the output is verifiable.
  fibonacci: {
    label: "recursive Fibonacci",
    output: "55",
  },
};

const WRITE_PROGRAM_TEMPLATES = {
  hello_world: {
    rust: 'fn main() {\n    println!("Hello, world!");\n}',
    python: 'print("Hello, world!")',
    javascript: 'console.log("Hello, world!");',
    typescript: 'console.log("Hello, world!");',
    go: 'package main\n\nimport "fmt"\n\nfunc main() {\n    fmt.Println("Hello, world!")\n}',
    c: '#include <stdio.h>\n\nint main(void) {\n    puts("Hello, world!");\n    return 0;\n}',
    cpp: '#include <iostream>\n\nint main() {\n    std::cout << "Hello, world!" << std::endl;\n    return 0;\n}',
    java: 'public class Main {\n    public static void main(String[] args) {\n        System.out.println("Hello, world!");\n    }\n}',
    csharp:
      'using System;\n\nclass Program {\n    static void Main() {\n        Console.WriteLine("Hello, world!");\n    }\n}',
    ruby: 'puts "Hello, world!"',
  },
  count_to_three: {
    rust:
      'fn main() {\n    for number in 1..=3 {\n        println!("{number}");\n    }\n}',
    python: "for number in range(1, 4):\n    print(number)",
    javascript:
      "for (let number = 1; number <= 3; number += 1) {\n    console.log(number);\n}",
    typescript:
      "for (let number = 1; number <= 3; number += 1) {\n    console.log(number);\n}",
    go:
      'package main\n\nimport "fmt"\n\nfunc main() {\n    for number := 1; number <= 3; number++ {\n        fmt.Println(number)\n    }\n}',
    c:
      '#include <stdio.h>\n\nint main(void) {\n    for (int number = 1; number <= 3; number++) {\n        printf("%d\\n", number);\n    }\n    return 0;\n}',
  },
  list_files: {
    rust:
      'use std::fs;\n\nfn main() -> std::io::Result<()> {\n    let mut names: Vec<String> = fs::read_dir(".")?\n        .filter_map(Result::ok)\n        .filter(|entry| entry.path().is_file())\n        .map(|entry| entry.file_name().to_string_lossy().into_owned())\n        .collect();\n    names.sort();\n    for name in names {\n        println!("{name}");\n    }\n    Ok(())\n}',
    python:
      'import os\n\nnames = sorted(name for name in os.listdir(".") if os.path.isfile(name))\nfor name in names:\n    print(name)',
    javascript:
      'const fs = require("fs");\n\nconst names = fs\n  .readdirSync(".")\n  .filter((name) => fs.statSync(name).isFile())\n  .sort();\n\nfor (const name of names) {\n  console.log(name);\n}',
    typescript:
      'import * as fs from "fs";\n\nconst names: string[] = fs\n  .readdirSync(".")\n  .filter((name) => fs.statSync(name).isFile())\n  .sort();\n\nfor (const name of names) {\n  console.log(name);\n}',
    go:
      'package main\n\nimport (\n    "fmt"\n    "os"\n    "sort"\n)\n\nfunc main() {\n    entries, err := os.ReadDir(".")\n    if err != nil {\n        panic(err)\n    }\n    var names []string\n    for _, entry := range entries {\n        if !entry.IsDir() {\n            names = append(names, entry.Name())\n        }\n    }\n    sort.Strings(names)\n    for _, name := range names {\n        fmt.Println(name)\n    }\n}',
    c:
      '#include <dirent.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\nstatic int compare(const void *a, const void *b) {\n    return strcmp(*(const char *const *)a, *(const char *const *)b);\n}\n\nint main(void) {\n    DIR *dir = opendir(".");\n    if (dir == NULL) {\n        return 1;\n    }\n    char *names[1024];\n    size_t count = 0;\n    struct dirent *entry;\n    while ((entry = readdir(dir)) != NULL && count < 1024) {\n        struct stat info;\n        if (stat(entry->d_name, &info) == 0 && S_ISREG(info.st_mode)) {\n            names[count++] = strdup(entry->d_name);\n        }\n    }\n    closedir(dir);\n    qsort(names, count, sizeof(char *), compare);\n    for (size_t i = 0; i < count; i++) {\n        printf("%s\\n", names[i]);\n        free(names[i]);\n    }\n    return 0;\n}',
    cpp:
      "#include <algorithm>\n#include <filesystem>\n#include <iostream>\n#include <string>\n#include <vector>\n\nint main() {\n    namespace fs = std::filesystem;\n    std::vector<std::string> names;\n    for (const auto &entry : fs::directory_iterator(\".\")) {\n        if (entry.is_regular_file()) {\n            names.push_back(entry.path().filename().string());\n        }\n    }\n    std::sort(names.begin(), names.end());\n    for (const auto &name : names) {\n        std::cout << name << '\\n';\n    }\n}",
    java:
      'import java.io.File;\nimport java.util.Arrays;\n\npublic class Main {\n    public static void main(String[] args) {\n        File[] entries = new File(".").listFiles();\n        if (entries == null) {\n            return;\n        }\n        String[] names = Arrays.stream(entries)\n            .filter(File::isFile)\n            .map(File::getName)\n            .sorted()\n            .toArray(String[]::new);\n        for (String name : names) {\n            System.out.println(name);\n        }\n    }\n}',
    csharp:
      'using System;\nusing System.IO;\nusing System.Linq;\n\nclass Program {\n    static void Main() {\n        var names = Directory.GetFiles(".")\n            .Select(Path.GetFileName)\n            .OrderBy(name => name, StringComparer.Ordinal);\n        foreach (var name in names) {\n            Console.WriteLine(name);\n        }\n    }\n}',
    ruby:
      'names = Dir.entries(".").select { |name| File.file?(name) }.sort\nnames.each { |name| puts name }',
  },
  // Issue #324 follow-up: list files in the directory passed as the first
  // command-line argument, defaulting to "." when none is supplied. Mirrors the
  // Rust `list_files_arg` templates.
  list_files_arg: {
    rust:
      'use std::env;\nuse std::fs;\n\nfn main() {\n    let path = env::args().nth(1).unwrap_or_else(|| String::from("."));\n    let mut names: Vec<String> = fs::read_dir(&path)\n        .expect("failed to read directory")\n        .filter_map(|entry| entry.ok())\n        .filter(|entry| entry.path().is_file())\n        .map(|entry| entry.file_name().to_string_lossy().into_owned())\n        .collect();\n    names.sort();\n    for name in names {\n        println!("{name}");\n    }\n}',
    python:
      'import os\nimport sys\n\npath = sys.argv[1] if len(sys.argv) > 1 else "."\nnames = sorted(\n    name for name in os.listdir(path) if os.path.isfile(os.path.join(path, name))\n)\nfor name in names:\n    print(name)',
    javascript:
      'const fs = require("fs");\nconst path = require("path");\n\nconst dir = process.argv[2] || ".";\nconst names = fs\n  .readdirSync(dir)\n  .filter((name) => fs.statSync(path.join(dir, name)).isFile())\n  .sort();\n\nfor (const name of names) {\n  console.log(name);\n}',
    typescript:
      'import * as fs from "fs";\nimport * as path from "path";\n\nconst dir: string = process.argv[2] ?? ".";\nconst names: string[] = fs\n  .readdirSync(dir)\n  .filter((name) => fs.statSync(path.join(dir, name)).isFile())\n  .sort();\n\nfor (const name of names) {\n  console.log(name);\n}',
    go:
      'package main\n\nimport (\n    "fmt"\n    "os"\n    "sort"\n)\n\nfunc main() {\n    dir := "."\n    if len(os.Args) > 1 {\n        dir = os.Args[1]\n    }\n    entries, err := os.ReadDir(dir)\n    if err != nil {\n        panic(err)\n    }\n    var names []string\n    for _, entry := range entries {\n        if !entry.IsDir() {\n            names = append(names, entry.Name())\n        }\n    }\n    sort.Strings(names)\n    for _, name := range names {\n        fmt.Println(name)\n    }\n}',
    c:
      '#include <dirent.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\nstatic int compare(const void *a, const void *b) {\n    return strcmp(*(const char *const *)a, *(const char *const *)b);\n}\n\nint main(int argc, char *argv[]) {\n    const char *path = argc > 1 ? argv[1] : ".";\n    DIR *dir = opendir(path);\n    if (dir == NULL) {\n        return 1;\n    }\n    char *names[1024];\n    size_t count = 0;\n    struct dirent *entry;\n    while ((entry = readdir(dir)) != NULL && count < 1024) {\n        char full[4096];\n        snprintf(full, sizeof(full), "%s/%s", path, entry->d_name);\n        struct stat info;\n        if (stat(full, &info) == 0 && S_ISREG(info.st_mode)) {\n            names[count++] = strdup(entry->d_name);\n        }\n    }\n    closedir(dir);\n    qsort(names, count, sizeof(char *), compare);\n    for (size_t i = 0; i < count; i++) {\n        printf("%s\\n", names[i]);\n        free(names[i]);\n    }\n    return 0;\n}',
    cpp:
      "#include <algorithm>\n#include <filesystem>\n#include <iostream>\n#include <string>\n#include <vector>\n\nint main(int argc, char *argv[]) {\n    namespace fs = std::filesystem;\n    std::string path = argc > 1 ? argv[1] : \".\";\n    std::vector<std::string> names;\n    for (const auto &entry : fs::directory_iterator(path)) {\n        if (entry.is_regular_file()) {\n            names.push_back(entry.path().filename().string());\n        }\n    }\n    std::sort(names.begin(), names.end());\n    for (const auto &name : names) {\n        std::cout << name << '\\n';\n    }\n}",
    java:
      'import java.io.File;\nimport java.util.Arrays;\n\npublic class Main {\n    public static void main(String[] args) {\n        String path = args.length > 0 ? args[0] : ".";\n        File[] entries = new File(path).listFiles();\n        if (entries == null) {\n            return;\n        }\n        String[] names = Arrays.stream(entries)\n            .filter(File::isFile)\n            .map(File::getName)\n            .sorted()\n            .toArray(String[]::new);\n        for (String name : names) {\n            System.out.println(name);\n        }\n    }\n}',
    csharp:
      'using System;\nusing System.IO;\nusing System.Linq;\n\nclass Program {\n    static void Main(string[] args) {\n        var path = args.Length > 0 ? args[0] : ".";\n        var names = Directory.GetFiles(path)\n            .Select(Path.GetFileName)\n            .OrderBy(name => name, StringComparer.Ordinal);\n        foreach (var name in names) {\n            Console.WriteLine(name);\n        }\n    }\n}',
    ruby:
      'path = ARGV[0] || "."\nnames = Dir.entries(path).select { |name| File.file?(File.join(path, name)) }.sort\nnames.each { |name| puts name }',
  },
  list_files_reverse_sort: {
    rust:
      'use std::fs;\n\nfn main() -> std::io::Result<()> {\n    let mut names: Vec<String> = fs::read_dir(".")?\n        .filter_map(Result::ok)\n        .filter(|entry| entry.path().is_file())\n        .map(|entry| entry.file_name().to_string_lossy().into_owned())\n        .collect();\n    names.sort_by(|a, b| b.cmp(a));\n    for name in names {\n        println!("{name}");\n    }\n    Ok(())\n}',
    python:
      'import os\n\nnames = sorted(\n    (name for name in os.listdir(".") if os.path.isfile(name)),\n    reverse=True,\n)\nfor name in names:\n    print(name)',
    javascript:
      'const fs = require("fs");\n\nconst names = fs\n  .readdirSync(".")\n  .filter((name) => fs.statSync(name).isFile())\n  .sort()\n  .reverse();\n\nfor (const name of names) {\n  console.log(name);\n}',
    typescript:
      'import * as fs from "fs";\n\nconst names: string[] = fs\n  .readdirSync(".")\n  .filter((name) => fs.statSync(name).isFile())\n  .sort()\n  .reverse();\n\nfor (const name of names) {\n  console.log(name);\n}',
    go:
      'package main\n\nimport (\n    "fmt"\n    "os"\n    "sort"\n)\n\nfunc main() {\n    entries, err := os.ReadDir(".")\n    if err != nil {\n        panic(err)\n    }\n    var names []string\n    for _, entry := range entries {\n        if !entry.IsDir() {\n            names = append(names, entry.Name())\n        }\n    }\n    sort.Sort(sort.Reverse(sort.StringSlice(names)))\n    for _, name := range names {\n        fmt.Println(name)\n    }\n}',
    c:
      '#include <dirent.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\nstatic int compare_desc(const void *a, const void *b) {\n    return strcmp(*(const char *const *)b, *(const char *const *)a);\n}\n\nint main(void) {\n    DIR *dir = opendir(".");\n    if (dir == NULL) {\n        return 1;\n    }\n    char *names[1024];\n    size_t count = 0;\n    struct dirent *entry;\n    while ((entry = readdir(dir)) != NULL && count < 1024) {\n        struct stat info;\n        if (stat(entry->d_name, &info) == 0 && S_ISREG(info.st_mode)) {\n            names[count++] = strdup(entry->d_name);\n        }\n    }\n    closedir(dir);\n    qsort(names, count, sizeof(char *), compare_desc);\n    for (size_t i = 0; i < count; i++) {\n        printf("%s\\n", names[i]);\n        free(names[i]);\n    }\n    return 0;\n}',
    cpp:
      "#include <algorithm>\n#include <filesystem>\n#include <iostream>\n#include <string>\n#include <vector>\n\nint main() {\n    namespace fs = std::filesystem;\n    std::vector<std::string> names;\n    for (const auto &entry : fs::directory_iterator(\".\")) {\n        if (entry.is_regular_file()) {\n            names.push_back(entry.path().filename().string());\n        }\n    }\n    std::sort(names.rbegin(), names.rend());\n    for (const auto &name : names) {\n        std::cout << name << '\\n';\n    }\n}",
    java:
      'import java.io.File;\nimport java.util.Arrays;\nimport java.util.Comparator;\n\npublic class Main {\n    public static void main(String[] args) {\n        File[] entries = new File(".").listFiles();\n        if (entries == null) {\n            return;\n        }\n        String[] names = Arrays.stream(entries)\n            .filter(File::isFile)\n            .map(File::getName)\n            .sorted(Comparator.reverseOrder())\n            .toArray(String[]::new);\n        for (String name : names) {\n            System.out.println(name);\n        }\n    }\n}',
    csharp:
      'using System;\nusing System.IO;\nusing System.Linq;\n\nclass Program {\n    static void Main() {\n        var names = Directory.GetFiles(".")\n            .Select(Path.GetFileName)\n            .OrderByDescending(name => name, StringComparer.Ordinal);\n        foreach (var name in names) {\n            Console.WriteLine(name);\n        }\n    }\n}',
    ruby:
      'names = Dir.entries(".").select { |name| File.file?(name) }.sort.reverse\nnames.each { |name| puts name }',
  },
  list_files_arg_reverse_sort: {
    rust:
      'use std::env;\nuse std::fs;\n\nfn main() {\n    let path = env::args().nth(1).unwrap_or_else(|| String::from("."));\n    let mut names: Vec<String> = fs::read_dir(&path)\n        .expect("failed to read directory")\n        .filter_map(|entry| entry.ok())\n        .filter(|entry| entry.path().is_file())\n        .map(|entry| entry.file_name().to_string_lossy().into_owned())\n        .collect();\n    names.sort_by(|a, b| b.cmp(a));\n    for name in names {\n        println!("{name}");\n    }\n}',
    python:
      'import os\nimport sys\n\npath = sys.argv[1] if len(sys.argv) > 1 else "."\nnames = sorted(\n    (\n        name\n        for name in os.listdir(path)\n        if os.path.isfile(os.path.join(path, name))\n    ),\n    reverse=True,\n)\nfor name in names:\n    print(name)',
    javascript:
      'const fs = require("fs");\nconst path = require("path");\n\nconst dir = process.argv[2] || ".";\nconst names = fs\n  .readdirSync(dir)\n  .filter((name) => fs.statSync(path.join(dir, name)).isFile())\n  .sort()\n  .reverse();\n\nfor (const name of names) {\n  console.log(name);\n}',
    typescript:
      'import * as fs from "fs";\nimport * as path from "path";\n\nconst dir: string = process.argv[2] ?? ".";\nconst names: string[] = fs\n  .readdirSync(dir)\n  .filter((name) => fs.statSync(path.join(dir, name)).isFile())\n  .sort()\n  .reverse();\n\nfor (const name of names) {\n  console.log(name);\n}',
    go:
      'package main\n\nimport (\n    "fmt"\n    "os"\n    "sort"\n)\n\nfunc main() {\n    dir := "."\n    if len(os.Args) > 1 {\n        dir = os.Args[1]\n    }\n    entries, err := os.ReadDir(dir)\n    if err != nil {\n        panic(err)\n    }\n    var names []string\n    for _, entry := range entries {\n        if !entry.IsDir() {\n            names = append(names, entry.Name())\n        }\n    }\n    sort.Sort(sort.Reverse(sort.StringSlice(names)))\n    for _, name := range names {\n        fmt.Println(name)\n    }\n}',
    c:
      '#include <dirent.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\nstatic int compare_desc(const void *a, const void *b) {\n    return strcmp(*(const char *const *)b, *(const char *const *)a);\n}\n\nint main(int argc, char *argv[]) {\n    const char *path = argc > 1 ? argv[1] : ".";\n    DIR *dir = opendir(path);\n    if (dir == NULL) {\n        return 1;\n    }\n    char *names[1024];\n    size_t count = 0;\n    struct dirent *entry;\n    while ((entry = readdir(dir)) != NULL && count < 1024) {\n        char full[4096];\n        snprintf(full, sizeof(full), "%s/%s", path, entry->d_name);\n        struct stat info;\n        if (stat(full, &info) == 0 && S_ISREG(info.st_mode)) {\n            names[count++] = strdup(entry->d_name);\n        }\n    }\n    closedir(dir);\n    qsort(names, count, sizeof(char *), compare_desc);\n    for (size_t i = 0; i < count; i++) {\n        printf("%s\\n", names[i]);\n        free(names[i]);\n    }\n    return 0;\n}',
    cpp:
      "#include <algorithm>\n#include <filesystem>\n#include <iostream>\n#include <string>\n#include <vector>\n\nint main(int argc, char *argv[]) {\n    namespace fs = std::filesystem;\n    std::string path = argc > 1 ? argv[1] : \".\";\n    std::vector<std::string> names;\n    for (const auto &entry : fs::directory_iterator(path)) {\n        if (entry.is_regular_file()) {\n            names.push_back(entry.path().filename().string());\n        }\n    }\n    std::sort(names.rbegin(), names.rend());\n    for (const auto &name : names) {\n        std::cout << name << '\\n';\n    }\n}",
    java:
      'import java.io.File;\nimport java.util.Arrays;\nimport java.util.Comparator;\n\npublic class Main {\n    public static void main(String[] args) {\n        String path = args.length > 0 ? args[0] : ".";\n        File[] entries = new File(path).listFiles();\n        if (entries == null) {\n            return;\n        }\n        String[] names = Arrays.stream(entries)\n            .filter(File::isFile)\n            .map(File::getName)\n            .sorted(Comparator.reverseOrder())\n            .toArray(String[]::new);\n        for (String name : names) {\n            System.out.println(name);\n        }\n    }\n}',
    csharp:
      'using System;\nusing System.IO;\nusing System.Linq;\n\nclass Program {\n    static void Main(string[] args) {\n        var path = args.Length > 0 ? args[0] : ".";\n        var names = Directory.GetFiles(path)\n            .Select(Path.GetFileName)\n            .OrderByDescending(name => name, StringComparer.Ordinal);\n        foreach (var name in names) {\n            Console.WriteLine(name);\n        }\n    }\n}',
    ruby:
      'path = ARGV[0] || "."\nnames = Dir.entries(path).select { |name| File.file?(File.join(path, name)) }.sort.reverse\nnames.each { |name| puts name }',
  },
  fizzbuzz: {
    rust:
      "fn main() {\n    for number in 1..=15 {\n        if number % 15 == 0 {\n            println!(\"FizzBuzz\");\n        } else if number % 3 == 0 {\n            println!(\"Fizz\");\n        } else if number % 5 == 0 {\n            println!(\"Buzz\");\n        } else {\n            println!(\"{number}\");\n        }\n    }\n}",
    python:
      "for number in range(1, 16):\n    if number % 15 == 0:\n        print(\"FizzBuzz\")\n    elif number % 3 == 0:\n        print(\"Fizz\")\n    elif number % 5 == 0:\n        print(\"Buzz\")\n    else:\n        print(number)",
    javascript:
      "for (let number = 1; number <= 15; number += 1) {\n  if (number % 15 === 0) {\n    console.log(\"FizzBuzz\");\n  } else if (number % 3 === 0) {\n    console.log(\"Fizz\");\n  } else if (number % 5 === 0) {\n    console.log(\"Buzz\");\n  } else {\n    console.log(number);\n  }\n}",
    typescript:
      "for (let number = 1; number <= 15; number += 1) {\n  if (number % 15 === 0) {\n    console.log(\"FizzBuzz\");\n  } else if (number % 3 === 0) {\n    console.log(\"Fizz\");\n  } else if (number % 5 === 0) {\n    console.log(\"Buzz\");\n  } else {\n    console.log(number);\n  }\n}",
    go:
      "package main\n\nimport \"fmt\"\n\nfunc main() {\n    for number := 1; number <= 15; number++ {\n        switch {\n        case number%15 == 0:\n            fmt.Println(\"FizzBuzz\")\n        case number%3 == 0:\n            fmt.Println(\"Fizz\")\n        case number%5 == 0:\n            fmt.Println(\"Buzz\")\n        default:\n            fmt.Println(number)\n        }\n    }\n}",
    c:
      "#include <stdio.h>\n\nint main(void) {\n    for (int number = 1; number <= 15; number++) {\n        if (number % 15 == 0) {\n            puts(\"FizzBuzz\");\n        } else if (number % 3 == 0) {\n            puts(\"Fizz\");\n        } else if (number % 5 == 0) {\n            puts(\"Buzz\");\n        } else {\n            printf(\"%d\\n\", number);\n        }\n    }\n    return 0;\n}",
    cpp:
      "#include <iostream>\n\nint main() {\n    for (int number = 1; number <= 15; number++) {\n        if (number % 15 == 0) {\n            std::cout << \"FizzBuzz\\n\";\n        } else if (number % 3 == 0) {\n            std::cout << \"Fizz\\n\";\n        } else if (number % 5 == 0) {\n            std::cout << \"Buzz\\n\";\n        } else {\n            std::cout << number << '\\n';\n        }\n    }\n}",
    java:
      "public class Main {\n    public static void main(String[] args) {\n        for (int number = 1; number <= 15; number++) {\n            if (number % 15 == 0) {\n                System.out.println(\"FizzBuzz\");\n            } else if (number % 3 == 0) {\n                System.out.println(\"Fizz\");\n            } else if (number % 5 == 0) {\n                System.out.println(\"Buzz\");\n            } else {\n                System.out.println(number);\n            }\n        }\n    }\n}",
    csharp:
      "using System;\n\nclass Program {\n    static void Main() {\n        for (int number = 1; number <= 15; number++) {\n            if (number % 15 == 0) {\n                Console.WriteLine(\"FizzBuzz\");\n            } else if (number % 3 == 0) {\n                Console.WriteLine(\"Fizz\");\n            } else if (number % 5 == 0) {\n                Console.WriteLine(\"Buzz\");\n            } else {\n                Console.WriteLine(number);\n            }\n        }\n    }\n}",
    ruby:
      "(1..15).each do |number|\n  if (number % 15).zero?\n    puts \"FizzBuzz\"\n  elsif (number % 3).zero?\n    puts \"Fizz\"\n  elsif (number % 5).zero?\n    puts \"Buzz\"\n  else\n    puts number\n  end\nend",
  },
  factorial: {
    rust:
      "fn main() {\n    let mut result: u64 = 1;\n    for number in 1..=5 {\n        result *= number;\n    }\n    println!(\"{result}\");\n}",
    python:
      "result = 1\nfor number in range(1, 6):\n    result *= number\nprint(result)",
    javascript:
      "let result = 1;\nfor (let number = 1; number <= 5; number += 1) {\n  result *= number;\n}\nconsole.log(result);",
    typescript:
      "let result = 1;\nfor (let number = 1; number <= 5; number += 1) {\n  result *= number;\n}\nconsole.log(result);",
    go:
      "package main\n\nimport \"fmt\"\n\nfunc main() {\n    result := 1\n    for number := 1; number <= 5; number++ {\n        result *= number\n    }\n    fmt.Println(result)\n}",
    c:
      "#include <stdio.h>\n\nint main(void) {\n    unsigned long long result = 1;\n    for (int number = 1; number <= 5; number++) {\n        result *= number;\n    }\n    printf(\"%llu\\n\", result);\n    return 0;\n}",
    cpp:
      "#include <iostream>\n\nint main() {\n    unsigned long long result = 1;\n    for (int number = 1; number <= 5; number++) {\n        result *= number;\n    }\n    std::cout << result << '\\n';\n}",
    java:
      "public class Main {\n    public static void main(String[] args) {\n        long result = 1;\n        for (int number = 1; number <= 5; number++) {\n            result *= number;\n        }\n        System.out.println(result);\n    }\n}",
    csharp:
      "using System;\n\nclass Program {\n    static void Main() {\n        long result = 1;\n        for (int number = 1; number <= 5; number++) {\n            result *= number;\n        }\n        Console.WriteLine(result);\n    }\n}",
    ruby:
      "result = (1..5).reduce(1, :*)\nputs result",
  },
  reverse_string: {
    rust:
      "fn main() {\n    let text = \"hello\";\n    let reversed: String = text.chars().rev().collect();\n    println!(\"{reversed}\");\n}",
    python:
      "text = \"hello\"\nprint(text[::-1])",
    javascript:
      "const text = \"hello\";\nconsole.log(text.split(\"\").reverse().join(\"\"));",
    typescript:
      "const text: string = \"hello\";\nconsole.log(text.split(\"\").reverse().join(\"\"));",
    go:
      "package main\n\nimport \"fmt\"\n\nfunc main() {\n    text := \"hello\"\n    runes := []rune(text)\n    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {\n        runes[i], runes[j] = runes[j], runes[i]\n    }\n    fmt.Println(string(runes))\n}",
    c:
      "#include <stdio.h>\n#include <string.h>\n\nint main(void) {\n    char text[] = \"hello\";\n    size_t length = strlen(text);\n    for (size_t i = 0; i < length / 2; i++) {\n        char temp = text[i];\n        text[i] = text[length - 1 - i];\n        text[length - 1 - i] = temp;\n    }\n    puts(text);\n    return 0;\n}",
    cpp:
      "#include <algorithm>\n#include <iostream>\n#include <string>\n\nint main() {\n    std::string text = \"hello\";\n    std::reverse(text.begin(), text.end());\n    std::cout << text << '\\n';\n}",
    java:
      "public class Main {\n    public static void main(String[] args) {\n        String text = \"hello\";\n        System.out.println(new StringBuilder(text).reverse().toString());\n    }\n}",
    csharp:
      "using System;\n\nclass Program {\n    static void Main() {\n        var text = \"hello\".ToCharArray();\n        Array.Reverse(text);\n        Console.WriteLine(new string(text));\n    }\n}",
    ruby:
      "text = \"hello\"\nputs text.reverse",
  },
  sum_to_ten: {
    rust:
      "fn main() {\n    let total: u32 = (1..=10).sum();\n    println!(\"{total}\");\n}",
    python:
      "total = sum(range(1, 11))\nprint(total)",
    javascript:
      "let total = 0;\nfor (let number = 1; number <= 10; number += 1) {\n  total += number;\n}\nconsole.log(total);",
    typescript:
      "let total = 0;\nfor (let number = 1; number <= 10; number += 1) {\n  total += number;\n}\nconsole.log(total);",
    go:
      "package main\n\nimport \"fmt\"\n\nfunc main() {\n    total := 0\n    for number := 1; number <= 10; number++ {\n        total += number\n    }\n    fmt.Println(total)\n}",
    c:
      "#include <stdio.h>\n\nint main(void) {\n    int total = 0;\n    for (int number = 1; number <= 10; number++) {\n        total += number;\n    }\n    printf(\"%d\\n\", total);\n    return 0;\n}",
    cpp:
      "#include <iostream>\n\nint main() {\n    int total = 0;\n    for (int number = 1; number <= 10; number++) {\n        total += number;\n    }\n    std::cout << total << '\\n';\n}",
    java:
      "public class Main {\n    public static void main(String[] args) {\n        int total = 0;\n        for (int number = 1; number <= 10; number++) {\n            total += number;\n        }\n        System.out.println(total);\n    }\n}",
    csharp:
      "using System;\n\nclass Program {\n    static void Main() {\n        int total = 0;\n        for (int number = 1; number <= 10; number++) {\n            total += number;\n        }\n        Console.WriteLine(total);\n    }\n}",
    ruby:
      "total = (1..10).sum\nputs total",
  },
  // Issue #334: recursive `fibonacci` function evaluated at the 10th term (55).
  fibonacci: {
    rust:
      "fn fibonacci(n: u64) -> u64 {\n    if n <= 2 {\n        1\n    } else {\n        fibonacci(n - 1) + fibonacci(n - 2)\n    }\n}\n\nfn main() {\n    println!(\"{}\", fibonacci(10));\n}",
    python:
      "def fibonacci(n):\n    if n <= 2:\n        return 1\n    return fibonacci(n - 1) + fibonacci(n - 2)\n\n\nprint(fibonacci(10))",
    javascript:
      "function fibonacci(n) {\n  if (n <= 2) {\n    return 1;\n  }\n  return fibonacci(n - 1) + fibonacci(n - 2);\n}\n\nconsole.log(fibonacci(10));",
    typescript:
      "function fibonacci(n: number): number {\n  if (n <= 2) {\n    return 1;\n  }\n  return fibonacci(n - 1) + fibonacci(n - 2);\n}\n\nconsole.log(fibonacci(10));",
    go:
      "package main\n\nimport \"fmt\"\n\nfunc fibonacci(n int) int {\n    if n <= 2 {\n        return 1\n    }\n    return fibonacci(n-1) + fibonacci(n-2)\n}\n\nfunc main() {\n    fmt.Println(fibonacci(10))\n}",
    c:
      "#include <stdio.h>\n\nunsigned long long fibonacci(int n) {\n    if (n <= 2) {\n        return 1;\n    }\n    return fibonacci(n - 1) + fibonacci(n - 2);\n}\n\nint main(void) {\n    printf(\"%llu\\n\", fibonacci(10));\n    return 0;\n}",
    cpp:
      "#include <iostream>\n\nunsigned long long fibonacci(int n) {\n    if (n <= 2) {\n        return 1;\n    }\n    return fibonacci(n - 1) + fibonacci(n - 2);\n}\n\nint main() {\n    std::cout << fibonacci(10) << '\\n';\n}",
    java:
      "public class Main {\n    static long fibonacci(int n) {\n        if (n <= 2) {\n            return 1;\n        }\n        return fibonacci(n - 1) + fibonacci(n - 2);\n    }\n\n    public static void main(String[] args) {\n        System.out.println(fibonacci(10));\n    }\n}",
    csharp:
      "using System;\n\nclass Program {\n    static long Fibonacci(int n) {\n        if (n <= 2) {\n            return 1;\n        }\n        return Fibonacci(n - 1) + Fibonacci(n - 2);\n    }\n\n    static void Main() {\n        Console.WriteLine(Fibonacci(10));\n    }\n}",
    ruby:
      "def fibonacci(n)\n  return 1 if n <= 2\n\n  fibonacci(n - 1) + fibonacci(n - 2)\nend\n\nputs fibonacci(10)",
  },
};

function normalizeProgramPrompt(prompt) {
  return normalizePrompt(String(prompt || "").replace(/c\+\+/gi, " cpp ").replace(/c#/gi, " csharp "));
}

// CJK scripts have no inter-word spaces, so the whitespace-based phrase/token
// matchers never isolate a CJK word. When the expected alias itself contains a
// CJK ideograph we fall back to a substring test (issue #312). Mirrors
// `coding::catalog::contains_cjk` on the Rust side.
function containsCjk(text) {
  return /[㐀-䶿一-鿿豈-﫿぀-ヿ㄀-ㄯ]/.test(
    String(text || ""),
  );
}

// Devanagari (Hindi, …) is written without spaces between words, so the
// whitespace-based phrase/token matchers never isolate a Devanagari word —
// exactly as for CJK above. Mirrors `coding::catalog::contains_devanagari` on
// the Rust side (range U+0900–U+097F): lets a handler split a role's word forms
// by script (Devanagari vs. Han) straight from the seed, so the head-final
// Hindi and Chinese extraction strategies never name a raw word (issue #386).
function containsDevanagari(text) {
  return /[ऀ-ॿ]/.test(String(text || ""));
}

// Whether every character of `text` is ASCII. Mirrors Rust's `str::is_ascii`:
// the calculator-domain signal builder shapes a surface differently by script,
// matching an ASCII code on a word boundary but a non-ASCII surface as a raw
// substring (issue #386).
function isAsciiText(text) {
  return /^[\x00-\x7f]*$/.test(String(text || ""));
}

function containsProgramToken(normalized, token) {
  if (containsCjk(token)) return String(normalized || "").includes(token);
  return String(normalized || "")
    .split(/\s+/)
    .includes(token);
}

function containsProgramPhrase(normalized, phrase) {
  if (containsCjk(phrase)) return normalized.includes(phrase);
  return (
    normalized === phrase ||
    normalized.startsWith(`${phrase} `) ||
    normalized.endsWith(` ${phrase}`) ||
    normalized.includes(` ${phrase} `)
  );
}

function programTaskFromPrompt(normalized) {
  // The request phrasings live in each task's `program_task_<slug>` meaning, not
  // inline on WRITE_PROGRAM_TASKS — read them by slug (issue #386). Declaration
  // order (Object.keys) is the catalog priority order, identical to Rust.
  return (
    Object.keys(WRITE_PROGRAM_TASKS).find((slug) =>
      wordsForMeaning(`program_task_${slug}`).some((alias) =>
        containsProgramPhrase(normalized, alias),
      ),
    ) || null
  );
}

// Issue #386: the function words that introduce an *unknown* implementation
// language ("write a program in <name>", "на языке <name>") are seed data, not
// literals baked into the worker. Mirror src/intent_formalization.rs by sourcing
// the head-initial English/Russian surfaces of the target-preposition and
// "language" noun roles from the lexicon. The WRITE_PROGRAM_LANGUAGES catalog
// scan below already resolves every *known* language across all four supported
// languages; this fallback only reads the bare name trailing the marker, so it
// consults the two head-initial languages whose name follows the marker (the
// head-final Hindi/Chinese surfaces are carried in the seed for coverage but
// place the name before the marker, which this scan does not chase).
const ROLE_IMPLEMENTATION_LANGUAGE_PREPOSITION =
  "implementation_language_preposition";
const ROLE_IMPLEMENTATION_LANGUAGE_NOUN = "implementation_language_noun";

function programLanguageFromPrompt(normalized) {
  const tokens = normalized.split(/\s+/).filter(Boolean);
  // Each language's alias surfaces live in its `program_language_<slug>` meaning,
  // not inline on WRITE_PROGRAM_LANGUAGES — read them by slug (issue #386). Names
  // are single tokens, matched on whitespace boundaries exactly as in Rust.
  for (const slug of Object.keys(WRITE_PROGRAM_LANGUAGES)) {
    const surfaces = wordsForMeaning(`program_language_${slug}`);
    if (surfaces.some((alias) => tokens.includes(alias))) return slug;
  }
  const prepositionSurfaces = wordsForRoleInLanguages(
    ROLE_IMPLEMENTATION_LANGUAGE_PREPOSITION,
    ["en", "ru"],
  );
  const languageNounSurfaces = wordsForRoleInLanguages(
    ROLE_IMPLEMENTATION_LANGUAGE_NOUN,
    ["en", "ru"],
  );
  for (let index = 0; index < tokens.length - 1; index += 1) {
    if (!prepositionSurfaces.includes(tokens[index])) continue;
    if (languageNounSurfaces.includes(tokens[index + 1])) {
      return tokens[index + 2] || null;
    }
    return tokens[index + 1];
  }
  return null;
}

// ---------------------------------------------------------------------------
// Issue #324 R4/R7: the program-modification step as a data-driven Links
// Notation substitution pipeline. This mirrors `src/program_plan.rs` (the
// pipeline) and `src/substitution.rs` (the engine). The rule text below is
// byte-identical to `data/seed/program-plan-rules.lino`; the parity experiment
// (`experiments/issue-324-js-worker.mjs`) keeps the two copies in lockstep.
//
// Adding a new modifier transform is rule data; recognition is constrained by
// the operation slugs declared in that rule data.
// ---------------------------------------------------------------------------

const PROGRAM_PLAN_RULES_LINO = [
  "substitution_rules",
  '  id "program_plan_rules"',
  '  rule "path_argument_list_files"',
  '    order "10"',
  '    event "manual"',
  '    when "request:modifier -> path_argument"',
  '    replace "request:task -> list_files"',
  '      with "request:task -> list_files_arg"',
  '  rule "path_argument_list_files_reverse_sort"',
  '    order "10"',
  '    event "manual"',
  '    when "request:modifier -> path_argument"',
  '    replace "request:task -> list_files_reverse_sort"',
  '      with "request:task -> list_files_arg_reverse_sort"',
  '  rule "reverse_sort_list_files"',
  '    order "20"',
  '    event "manual"',
  '    when "request:modifier -> reverse_sort"',
  '    replace "request:task -> list_files"',
  '      with "request:task -> list_files_reverse_sort"',
  '  rule "reverse_sort_list_files_arg"',
  '    order "20"',
  '    event "manual"',
  '    when "request:modifier -> reverse_sort"',
  '    replace "request:task -> list_files_arg"',
  '      with "request:task -> list_files_arg_reverse_sort"',
  "",
].join("\n");

const TASK_NODE = "request:task";
const MODIFIER_NODE = "request:modifier";

// Issue #386: the FULL multilingual operation vocabulary, embedded inline and
// byte-identical to data/seed/operation-vocabulary.lino (regenerated by
// experiments/issue-386-sync-worker-lexicon.mjs). The JS mirror of
// OperationVocabulary in src/seed/operation_vocabulary.rs: the CODE matches
// canonical concept tokens (write / function / similar_elements / reverse_sort …),
// while the per-language surface phrases live once here in the seed data — never
// a hardcoded per-language word list in code.
const OPERATION_VOCABULARY_LINO = [
  "operation_vocabulary",
  '  operation "uppercase"',
  '    language "en"',
  '      phrase "uppercase"',
  '      phrase "upper case"',
  '    language "ru"',
  '      phrase "верхний регистр"',
  '      phrase "заглавными буквами"',
  '      phrase "прописными буквами"',
  '      combo "верхний+регистр"',
  '    language "hi"',
  '      phrase "बड़े अक्षर"',
  '      phrase "अपरकेस"',
  '    language "zh"',
  '      phrase "大写"',
  '  operation "lowercase"',
  '    language "en"',
  '      phrase "lowercase"',
  '      phrase "lower case"',
  '    language "ru"',
  '      phrase "нижний регистр"',
  '      phrase "строчными буквами"',
  '      combo "нижний+регистр"',
  '    language "hi"',
  '      phrase "छोटे अक्षर"',
  '      phrase "लोअरकेस"',
  '    language "zh"',
  '      phrase "小写"',
  '  operation "replace"',
  '    language "en"',
  '      phrase "replace"',
  '    language "ru"',
  '      phrase "замен"',
  '    language "hi"',
  '      phrase "बदल"',
  '    language "zh"',
  '      phrase "替换"',
  '  operation "reverse_words"',
  '    language "en"',
  '      phrase "reverse words"',
  '      phrase "reverse the words"',
  '    language "ru"',
  '      phrase "обратный порядок слов"',
  '      combo "переверни+слова"',
  '      combo "обрати+слова"',
  '      combo "разверни+слова"',
  '    language "hi"',
  '      phrase "शब्दों को उल्टा"',
  '      combo "शब्द+उल्टा"',
  '    language "zh"',
  '      phrase "反转单词"',
  '      phrase "倒转单词"',
  '      phrase "颠倒单词"',
  '  operation "extract_email"',
  '    language "en"',
  '      combo "extract+email"',
  '      combo "extract+e-mail"',
  '    language "ru"',
  '      combo "извлеки+имейл"',
  '      combo "извлеки+почт"',
  '      combo "извлечь+имейл"',
  '      combo "найди+имейл"',
  '    language "hi"',
  '      combo "ईमेल+निकाल"',
  '    language "zh"',
  '      phrase "提取邮箱"',
  '      phrase "提取电子邮件"',
  '      phrase "提取邮件"',
  '  operation "count_occurrences"',
  '    language "en"',
  '      phrase "count occurrences"',
  '    language "ru"',
  '      phrase "количество вхождений"',
  '      combo "посчитай+вхождени"',
  '      combo "подсчитай+вхождени"',
  '      combo "сколько+раз"',
  '    language "hi"',
  '      phrase "कितनी बार"',
  '      combo "बार+गिन"',
  '    language "zh"',
  '      phrase "出现次数"',
  '      phrase "统计出现"',
  '      phrase "计算出现"',
  '  operation "count_unique_words"',
  '    language "en"',
  '      phrase "count unique words"',
  '      phrase "count distinct words"',
  '    language "ru"',
  '      phrase "количество уникальных слов"',
  '      combo "уникальн+слов"',
  '      combo "различн+слов"',
  '    language "hi"',
  '      combo "अद्वितीय+शब्द"',
  '      combo "विशिष्ट+शब्द"',
  '    language "zh"',
  '      phrase "唯一单词"',
  '      phrase "不同单词"',
  '      phrase "统计唯一"',
  '  operation "deduplicate_lines"',
  '    language "en"',
  '      phrase "deduplicate lines"',
  '      phrase "dedupe lines"',
  '      combo "deduplicate+line"',
  '    language "ru"',
  '      combo "дубликат+строк"',
  '      combo "дедупликац+строк"',
  '    language "hi"',
  '      combo "डुप्लिकेट+लाइन"',
  '      combo "दोहराव+लाइन"',
  '    language "zh"',
  '      phrase "去重行"',
  '      phrase "行去重"',
  '      phrase "删除重复行"',
  '  operation "sort_lines"',
  '    language "en"',
  '      phrase "sort lines"',
  '      phrase "sort the lines"',
  '      combo "sort+line"',
  '    language "ru"',
  '      combo "сортир+строк"',
  '    language "hi"',
  '      combo "लाइन+क्रमबद्ध"',
  '      combo "लाइनों+क्रमबद्ध"',
  '    language "zh"',
  '      phrase "排序行"',
  '      phrase "行排序"',
  '      phrase "对行排序"',
  '  operation "path_argument"',
  '    language "en"',
  '      phrase "path argument"',
  '      phrase "path as an argument"',
  '      combo "path+argument"',
  '    language "ru"',
  '      combo "путь+аргумент"',
  '      combo "путь+аргумента"',
  '      combo "путь+аргументом"',
  '    language "hi"',
  '      phrase "पथ को तर्क"',
  '      combo "पथ+तर्क"',
  '    language "zh"',
  '      phrase "路径作为参数"',
  '      combo "路径+参数"',
  '  operation "reverse_sort"',
  '    language "en"',
  '      phrase "reverse sort"',
  '      phrase "reverse sorted"',
  '      phrase "sort in reverse order"',
  '      phrase "sort the results in reverse order"',
  '      phrase "reverse order"',
  '      phrase "descending order"',
  '      combo "sort+reverse"',
  '      combo "sort+descending"',
  '    language "ru"',
  '      phrase "в обратном порядке"',
  '      combo "сортиров+обратн"',
  '      combo "отсортир+обратн"',
  '    language "hi"',
  '      phrase "उल्टे क्रम"',
  '      combo "क्रमबद्ध+उल्टे"',
  '      combo "क्रमबद्ध+उल्टा"',
  '    language "zh"',
  '      phrase "相反顺序排序"',
  '      combo "排序+相反"',
  '      combo "排序+反向"',
  '      combo "排序+倒序"',
  '  operation "cancel_reverse_sort"',
  '    inverse "reverse_sort"',
  '    language "en"',
  '      phrase "cancel sort"',
  '      phrase "cancel the sort"',
  '      phrase "cancel sorting"',
  '      phrase "cancel the sorting"',
  '      phrase "undo sort"',
  '      phrase "undo the sort"',
  '      phrase "undo sorting"',
  '      phrase "undo the sorting"',
  '      phrase "remove sort"',
  '      phrase "remove the sort"',
  '      phrase "remove sorting"',
  '      phrase "remove the sorting"',
  '      phrase "no sorting"',
  '      phrase "without sorting"',
  '      combo "cancel+sort"',
  '      combo "undo+sort"',
  '      combo "remove+sort"',
  '    language "ru"',
  '      phrase "отмени сортировку"',
  '      phrase "отмените сортировку"',
  '      phrase "убери сортировку"',
  '      phrase "уберите сортировку"',
  '      phrase "без сортировки"',
  '      combo "отмени+сортиров"',
  '      combo "отмените+сортиров"',
  '      combo "отменить+сортиров"',
  '      combo "убери+сортиров"',
  '      combo "уберите+сортиров"',
  '      combo "убрать+сортиров"',
  '      combo "без+сортиров"',
  '    language "hi"',
  '      phrase "सॉर्ट हटाओ"',
  '      phrase "क्रम हटाओ"',
  '      phrase "सॉर्ट रद्द करो"',
  '      combo "सॉर्ट+हटा"',
  '      combo "क्रमबद्ध+हटा"',
  '      combo "सॉर्ट+रद्द"',
  '    language "zh"',
  '      phrase "取消排序"',
  '      phrase "撤销排序"',
  '      phrase "去掉排序"',
  '      phrase "取消排序顺序"',
  '      combo "取消+排序"',
  '      combo "撤销+排序"',
  '  operation "function"',
  '    language "en"',
  '      phrase "function"',
  '    language "ru"',
  '      phrase "функция"',
  '      phrase "функцию"',
  '      phrase "функции"',
  '    language "hi"',
  '      phrase "फ़ंक्शन"',
  '      phrase "फंक्शन"',
  '    language "zh"',
  '      phrase "函数"',
  '  operation "implement"',
  '    language "en"',
  '      phrase "implement"',
  '    language "ru"',
  '      phrase "реализуй"',
  '      phrase "реализовать"',
  '      phrase "реализуйте"',
  '    language "hi"',
  '      phrase "लागू करें"',
  '      phrase "लागू करो"',
  '    language "zh"',
  '      phrase "实现"',
  '  operation "write"',
  '    language "en"',
  '      phrase "write"',
  '    language "ru"',
  '      phrase "напиши"',
  '      phrase "напишите"',
  '      phrase "написать"',
  '    language "hi"',
  '      phrase "लिखें"',
  '      phrase "लिखो"',
  '    language "zh"',
  '      phrase "编写"',
  '      phrase "写"',
  '  operation "return"',
  '    language "en"',
  '      phrase "return"',
  '    language "ru"',
  '      phrase "верни"',
  '      phrase "верните"',
  '      phrase "возвращает"',
  '    language "hi"',
  '      phrase "लौटाएँ"',
  '      phrase "लौटाएं"',
  '      phrase "वापस करें"',
  '    language "zh"',
  '      phrase "返回"',
  '  operation "tuple"',
  '    language "en"',
  '      phrase "tuple"',
  '    language "ru"',
  '      phrase "кортеж"',
  '    language "hi"',
  '      phrase "टपल"',
  '    language "zh"',
  '      phrase "元组"',
  '  operation "numbers"',
  '    language "en"',
  '      phrase "numbers"',
  '      phrase "number"',
  '    language "ru"',
  '      phrase "числа"',
  '      phrase "чисел"',
  '    language "hi"',
  '      phrase "संख्याएँ"',
  '      phrase "संख्याएं"',
  '      phrase "संख्या"',
  '    language "zh"',
  '      phrase "数字"',
  '      phrase "数值"',
  '  operation "vowels"',
  '    language "en"',
  '      phrase "vowels"',
  '      phrase "vowel"',
  '    language "ru"',
  '      phrase "гласные"',
  '      phrase "гласных"',
  '    language "hi"',
  '      phrase "स्वर"',
  '      phrase "स्वरों"',
  '    language "zh"',
  '      phrase "元音"',
  '  operation "count_vowels"',
  '    language "en"',
  '      phrase "count vowels"',
  '      phrase "number of vowels"',
  '      phrase "count_vowels"',
  '    language "ru"',
  '      phrase "посчитай гласные"',
  '      phrase "количество гласных"',
  '    language "hi"',
  '      phrase "स्वर गिनें"',
  '      phrase "स्वरों की संख्या"',
  '    language "zh"',
  '      phrase "统计元音"',
  '      phrase "元音数量"',
  '  operation "similar_elements"',
  '    language "en"',
  '      phrase "similar elements"',
  '      phrase "similar_elements"',
  '    language "ru"',
  '      phrase "общие элементы"',
  '      phrase "похожие элементы"',
  '    language "hi"',
  '      phrase "समान तत्व"',
  '    language "zh"',
  '      phrase "相同元素"',
  '      phrase "相似元素"',
  '  operation "distinct_numbers"',
  '    language "en"',
  '      phrase "distinct numbers"',
  '    language "ru"',
  '      phrase "различные числа"',
  '      phrase "разных числа"',
  '    language "hi"',
  '      phrase "अलग संख्याएँ"',
  '      phrase "अलग संख्याएं"',
  '    language "zh"',
  '      phrase "不同数字"',
  '      phrase "不同数值"',
  '  operation "differ"',
  '    language "en"',
  '      phrase "differ"',
  '    language "ru"',
  '      phrase "отличаются"',
  '      phrase "разница"',
  '    language "hi"',
  '      phrase "अंतर"',
  '    language "zh"',
  '      phrase "相差"',
  '      phrase "差"',
  '  operation "threshold"',
  '    language "en"',
  '      phrase "threshold"',
  '    language "ru"',
  '      phrase "порог"',
  '      phrase "порога"',
  '    language "hi"',
  '      phrase "सीमा"',
  '    language "zh"',
  '      phrase "阈值"',
].join("\n");

let cachedOperationVocabulary = null;
// Parse the embedded operation vocabulary into language-pooled triggers
// ({ slug, phrases, combos, inverse? }). Mirrors operation_vocabulary() in
// src/seed/operation_vocabulary.rs; phrases/combos are pooled across every
// language because operationFormMatches (below) is language-agnostic.
function operationVocabulary() {
  if (cachedOperationVocabulary) return cachedOperationVocabulary;
  const root = parseLinoTree(OPERATION_VOCABULARY_LINO);
  const container =
    root.children.find((child) => child.name === "operation_vocabulary") || root;
  const operations = [];
  for (const operationNode of container.children) {
    if (operationNode.name !== "operation") continue;
    const phrases = [];
    const combos = [];
    let inverse = null;
    for (const child of operationNode.children) {
      if (child.name === "inverse") inverse = child.value;
      else if (child.name === "language") {
        for (const form of child.children) {
          if (form.name === "phrase") phrases.push(form.value);
          else if (form.name === "combo") {
            combos.push(
              form.value
                .split("+")
                .map((token) => token.trim())
                .filter(Boolean),
            );
          }
        }
      }
    }
    const operation = { slug: operationNode.value, phrases, combos };
    if (inverse) operation.inverse = inverse;
    operations.push(operation);
  }
  cachedOperationVocabulary = operations;
  return cachedOperationVocabulary;
}

let cachedProgramModifierSlugs = null;
function literalPatternValue(node) {
  return node && node.kind === "literal" ? node.value : null;
}

function programModifierSlugs() {
  if (cachedProgramModifierSlugs) return cachedProgramModifierSlugs;
  const slugs = new Set();
  for (const rule of programPlanRules().rules) {
    for (const condition of rule.conditions || []) {
      const from = literalPatternValue(condition.from);
      const to = literalPatternValue(condition.to);
      if (from === MODIFIER_NODE && to) slugs.add(to);
    }
  }
  cachedProgramModifierSlugs = slugs;
  return slugs;
}

function operationFormMatches(normalized, operation) {
  const source = String(normalized || "");
  return (
    (operation.phrases || []).some((phrase) => source.includes(phrase)) ||
    (operation.combos || []).some((combo) =>
      combo.every((token) => source.includes(String(token || ""))),
    )
  );
}

// Issue #386: every canonical operation token whose phrasing appears in
// `normalized`, in declaration order. Mirrors OperationVocabulary::detect in
// src/seed/operation_vocabulary.rs (substring match, so a native verb still
// matches when punctuation such as the danda `।` is glued to it).
function detectOperations(normalized) {
  const detected = [];
  for (const operation of operationVocabulary()) {
    if (operationFormMatches(normalized, operation)) detected.push(operation.slug);
  }
  return detected;
}

// Issue #386: append canonical English operation tokens to a normalized prompt so
// handlers keep matching canonical concepts while accepting native verbs from
// data/seed/operation-vocabulary.lino. Mirrors
// OperationVocabulary::canonicalized_prompt — additive (never removes text), so
// English prompts are unchanged and multilingual prompts gain boundary-matchable
// tokens (e.g. a Hindi "लिखें।" yields an appended " write").
function canonicalizedPrompt(normalized) {
  const detected = detectOperations(normalized);
  if (!detected.length) return String(normalized || "");
  let out = String(normalized || "");
  for (const canonical of detected) {
    out += ` ${canonical}`;
    const phrase = canonical.replace(/_/g, " ");
    if (phrase !== canonical) out += ` ${phrase}`;
  }
  return out;
}

// Issue #386: the language-independent *meaning* lexicon — the JS mirror of
// `data/seed/meanings.lino` and `src/seed/meanings.rs`. Recognition references
// semantic *roles* (which surface words evidence a program artifact / a program
// modification, in any language), never a hardcoded per-language word list. This
// is an inline, byte-identical copy of the canonical seed (the same convention
// as PROGRAM_PLAN_RULES_LINO) so the worker stays self-contained when no seed has
// been fetched; parity is guarded by `experiments/issue-386-js-cancel-sort.mjs`.
const MEANINGS_LINO = [
  "meanings",
  '  meaning "result"',
  '    gloss "the value or data a computation produces"',
  '    wiktionary "result"',
  '    defined_by "output"',
  '    role "program_artifact"',
  '    lexeme "en"',
  '      word "result"',
  '        description "English noun for the value or data a computation produces; the lemma surface for the result concept."',
  '      word "results"',
  '        description "English noun, the plural form of result, for several values a computation produces."',
  '    lexeme "ru"',
  '      word "результат"',
  '        description "Russian noun (romanized rezultat) in the nominative for a computation result; the lemma surface for the result concept."',
  '      word "результата"',
  '        description "Russian noun (romanized rezultata), the genitive singular of result, naming the same computation result."',
  '      word "результаты"',
  '        description "Russian noun (romanized rezultaty), the nominative plural of result, for several computation results."',
  '      word "результатов"',
  '        description "Russian noun (romanized rezultatov), the genitive plural of result, for several computation results."',
  '    lexeme "hi"',
  '      word "परिणाम"',
  '        description "Hindi noun (romanized parinaam) for the value or data a computation produces; the lemma surface for the result concept."',
  '      word "परिणामों"',
  '        description "Hindi noun (romanized parinaamon), an oblique plural of result, for several computation results."',
  '      word "नतीजा"',
  '        description "Hindi noun (romanized nateeja) for an outcome or result; an alternative Hindi surface for the result concept."',
  '      word "नतीजे"',
  '        description "Hindi noun (romanized nateeje), the plural or oblique of nateeja, for outcomes or results."',
  '    lexeme "zh"',
  '      word "结果"',
  '        description "Chinese noun (pinyin jieguo) for the value or outcome a computation produces; the Chinese surface for the result concept."',
  '  meaning "output"',
  '    gloss "what a program emits — prints or returns — when it runs"',
  '    wiktionary "output"',
  '    defined_by "result"',
  '    defined_by "program"',
  '    role "program_artifact"',
  '    lexeme "en"',
  '      word "output"',
  '        description "English noun for what a program emits or returns when it runs; the lemma surface for the output concept."',
  '    lexeme "ru"',
  '      word "вывод"',
  '        description "Russian noun (romanized vyvod) for the output a program emits; the Russian surface for the output concept."',
  '    lexeme "hi"',
  '      word "आउटपुट"',
  '        description "Hindi noun (romanized aautaput, a loanword from English output) for what a program emits; the Hindi surface for the output concept."',
  '    lexeme "zh"',
  '      word "输出"',
  '        description "Chinese noun and verb (pinyin shuchu) for the output a program emits; the Chinese surface for the output concept."',
  '  meaning "program"',
  "    gloss \"a set of instructions a computer executes — the broad program genus. Beyond naming a program artifact and a program kind, it carries program_genus: the script-authoring recogniser reads that role to step aside whenever a prompt names a whole program, so a 'write a program' request keeps its richer parametric formalization instead of collapsing into a bare script.\"",
  '    wiktionary "program"',
  '    defined_by "code"',
  '    defined_by "entity"',
  '    role "program_artifact"',
  '    role "program_kind"',
  '    role "program_genus"',
  '    lexeme "en"',
  '      word "program"',
  '        description "English noun for a set of instructions a computer executes; the lemma surface for the program concept."',
  '      word "programme"',
  '        description "English noun, the British spelling of program, for the same set of executable instructions."',
  '    lexeme "ru"',
  '      word "программа"',
  '        description "Russian noun (romanized programma) in the nominative for a computer program; the lemma surface for the program concept."',
  '      word "программу"',
  '        description "Russian noun (romanized programmu), the accusative singular of program, naming the same computer program."',
  '      word "программе"',
  '        description "Russian noun (romanized programme), the dative or prepositional singular of program, naming the same computer program."',
  '      word "программы"',
  '        description "Russian noun (romanized programmy), the genitive singular or nominative plural of program, naming computer programs."',
  '      word "программку"',
  '        description "Russian noun (romanized programmku), the accusative of a diminutive of program, for a little program."',
  '    lexeme "hi"',
  '      word "प्रोग्राम"',
  '        description "Hindi noun (romanized program, a loanword) for a set of instructions a computer executes; the Hindi surface for the program concept."',
  '    lexeme "zh"',
  '      word "程序"',
  '        description "Chinese noun (pinyin chengxu) for a computer program or procedure; the Chinese surface for the program concept."',
  '  meaning "script"',
  "    gloss \"a short program, usually interpreted rather than compiled. It carries program_artifact and program_kind like any authorable artifact, and additionally script_or_code_artifact — the narrow noun side of 'write a script', the role the script-authoring recogniser pairs with an author verb to route a bare script request (as opposed to a whole program).\"",
  '    wiktionary "script"',
  '    defined_by "program"',
  '    defined_by "code"',
  '    role "program_artifact"',
  '    role "program_kind"',
  '    role "script_or_code_artifact"',
  '    lexeme "en"',
  '      word "script"',
  '        description "English noun for a short program that is usually interpreted rather than compiled; the lemma surface for the script concept."',
  '    lexeme "ru"',
  '      word "скрипт"',
  '        description "Russian noun (romanized skript) for a script or short program; the Russian surface for the script concept."',
  '    lexeme "hi"',
  '      word "स्क्रिप्ट"',
  '        description "Hindi noun (romanized skript, a loanword) for a short interpreted program; the Hindi surface for the script concept."',
  '    lexeme "zh"',
  '      word "脚本"',
  '        description "Chinese noun (pinyin jiaoben) for a script or short program; the Chinese surface for the script concept."',
  '  meaning "code"',
  "    gloss \"the text of a program, written in a programming language. Like script it carries program_artifact, program_kind, and script_or_code_artifact — so 'write me some code' pairs the same narrow artifact role with an author verb and routes a bare script request rather than a whole-program formalization.\"",
  '    wiktionary "code"',
  '    defined_by "program"',
  '    role "program_artifact"',
  '    role "program_kind"',
  '    role "script_or_code_artifact"',
  '    lexeme "en"',
  '      word "code"',
  '        description "English noun for the text of a program written in a programming language; the lemma surface for the code concept."',
  '    lexeme "ru"',
  '      word "код"',
  '        description "Russian noun (romanized kod) in the nominative for program code; the lemma surface for the code concept."',
  '      word "кода"',
  '        description "Russian noun (romanized koda), the genitive singular of code, naming the same program code."',
  '      word "коде"',
  '        description "Russian noun (romanized kode), the prepositional singular of code, naming the same program code."',
  '    lexeme "hi"',
  '      word "कोड"',
  '        description "Hindi noun (romanized kod, a loanword from English code) for the text of a program; the Hindi surface for the code concept."',
  '    lexeme "zh"',
  '      word "代码"',
  '        description "Chinese noun (pinyin daima) for program code; the Chinese surface for the code concept."',
  '  meaning "hello_world"',
  "    gloss \"the canonical hello-world archetype: the codebase's minimal first program, whose only job is to print the greeting 'hello world'. It is defined_by program (the smallest whole program) and code (its few lines of source), and carries hello_world_reference — the role the script-authoring recogniser reads to step aside, so naming the hello-world example routes through the dedicated program-synthesis path rather than the bare script route. Surface forms are the adjacent two-word greeting in each language, matched as a phrase (substring in CJK) so a stray 'hello' or 'world' alone never fires it.\"",
  '    wiktionary "hello world"',
  '    defined_by "program"',
  '    defined_by "code"',
  '    role "hello_world_reference"',
  '    lexeme "en"',
  '      word "hello world"',
  "        description \"English two-word phrase naming the archetypal first-program output; matched as a phrase so it fires only on the adjacent greeting, not a stray 'hello' or 'world'.\"",
  '    lexeme "ru"',
  '      word "привет мир"',
  '        description "Russian phrase (romanized privet mir, hello world) naming the archetypal first-program output."',
  '      word "хелло ворлд"',
  "        description \"Russian transliteration (romanized khello vorld) of the English 'hello world', as commonly written in programming tutorials.\"",
  '    lexeme "hi"',
  '      word "नमस्ते दुनिया"',
  '        description "Hindi phrase (romanized namaste duniya, hello world) naming the archetypal first-program output."',
  '      word "हैलो वर्ल्ड"',
  "        description \"Hindi transliteration (romanized hailo varld) of the English 'hello world', as commonly written in programming tutorials.\"",
  '    lexeme "zh"',
  '      word "你好世界"',
  '        description "Chinese phrase (pinyin nihao shijie, hello world) naming the archetypal first-program output; matched as a substring."',
  '      word "你好,世界"',
  '        description "Chinese phrase (pinyin nihao, shijie) with the conventional comma, the form often shown in programming tutorials."',
  '  meaning "sort"',
  '    gloss "to arrange items into an order; the resulting arrangement"',
  '    wiktionary "sort"',
  '    defined_by "order"',
  '    defined_by "action"',
  '    role "program_artifact"',
  '    role "program_modification"',
  '    lexeme "en"',
  '      word "sort"',
  '        description "English verb to arrange items into an order, and the noun for the resulting arrangement; the lemma surface for the sort concept."',
  '      word "sorts"',
  '        description "English verb, the third-person singular present of sort, for arranging items into an order."',
  '      word "sorting"',
  '        description "English gerund or present participle of sort, naming the act of arranging items into an order."',
  '      word "sorted"',
  '        description "English verb, the past tense or past participle of sort, for items that have been arranged into an order."',
  '    lexeme "ru"',
  '      word "сортировка"',
  '        description "Russian noun (romanized sortirovka) in the nominative for a sort or sorting; the lemma surface for the sort concept."',
  '      word "сортировку"',
  '        description "Russian noun (romanized sortirovku), the accusative singular of sorting, naming the same sort operation."',
  '      word "сортировки"',
  '        description "Russian noun (romanized sortirovki), the genitive singular or plural of sorting, naming sort operations."',
  '      word "сортировке"',
  '        description "Russian noun (romanized sortirovke), the dative or prepositional singular of sorting, naming the same sort operation."',
  '      word "сортировкой"',
  '        description "Russian noun (romanized sortirovkoy), the instrumental singular of sorting, naming the same sort operation."',
  '      word "сортировать"',
  '        description "Russian verb (romanized sortirovat), the imperfective infinitive, meaning to sort or arrange items into an order."',
  '      word "отсортируй"',
  '        description "Russian verb (romanized otsortiruy), the perfective informal imperative, commanding to sort the items."',
  '      word "отсортируйте"',
  '        description "Russian verb (romanized otsortiruyte), the perfective polite or plural imperative, commanding to sort the items."',
  '      word "отсортировать"',
  '        description "Russian verb (romanized otsortirovat), the perfective infinitive, meaning to sort or arrange items into an order."',
  '    lexeme "hi"',
  '      word "सॉर्ट"',
  '        description "Hindi verb or noun (romanized sort, a loanword) for sorting or arranging items into an order; the Hindi surface for the sort concept."',
  '      word "क्रमबद्ध"',
  '        description "Hindi adjective (romanized kramabaddh) meaning ordered or sorted; the native Hindi surface for arranged into an order."',
  '    lexeme "zh"',
  '      word "排序"',
  '        description "Chinese verb and noun (pinyin paixu) for sorting or arranging items into an order; the Chinese surface for the sort concept."',
  '  meaning "order"',
  '    gloss "an arrangement that follows a rule; to arrange so"',
  '    wiktionary "order"',
  '    defined_by "sort"',
  '    role "program_artifact"',
  '    role "program_modification"',
  '    lexeme "en"',
  '      word "order"',
  '        description "English noun for an arrangement that follows a rule, and the verb to arrange so; the lemma surface for the order concept."',
  '      word "ordering"',
  '        description "English gerund or present participle of order, naming the act or result of arranging items."',
  '      word "reorder"',
  '        description "English verb meaning to order again or rearrange; a re- prefixed surface for the order concept."',
  '    lexeme "ru"',
  '      word "порядок"',
  '        description "Russian noun (romanized poryadok) for an order or arrangement; the lemma surface for the order concept."',
  '      word "упорядочи"',
  '        description "Russian verb (romanized uporyadochi), the informal imperative, commanding to put items into order."',
  '    lexeme "hi"',
  '      word "क्रम"',
  '        description "Hindi noun (romanized kram) for an order, sequence, or arrangement; the Hindi surface for the order concept."',
  '    lexeme "zh"',
  '      word "顺序"',
  '        description "Chinese noun (pinyin shunxu) for order or sequence; the Chinese surface for the order concept."',
  '  meaning "reverse"',
  '    gloss "to put into the opposite order"',
  '    wiktionary "reverse"',
  '    defined_by "order"',
  '    role "program_modification"',
  '    lexeme "en"',
  '      word "reverse"',
  '        description "English verb meaning to put into the opposite order; the lemma surface for the reverse concept."',
  '      word "reversed"',
  '        description "English verb, the past tense or past participle of reverse, for items put into the opposite order."',
  '    lexeme "ru"',
  '      word "обратный"',
  '        description "Russian adjective (romanized obratny) in the nominative masculine meaning reverse or opposite; the lemma surface for the reverse concept."',
  '      word "обратном"',
  '        description "Russian adjective (romanized obratnom), the prepositional masculine or neuter of reverse, meaning opposite (as in reverse order)."',
  '      word "обратную"',
  '        description "Russian adjective (romanized obratnuyu), the accusative feminine of reverse, meaning opposite (as in reverse order)."',
  '      word "обратного"',
  '        description "Russian adjective (romanized obratnogo), the genitive masculine or neuter of reverse, meaning opposite."',
  '    lexeme "hi"',
  '      word "उल्टा"',
  '        description "Hindi adjective (romanized ulta) meaning reverse, opposite, or inverted; the lemma surface for the reverse concept."',
  '      word "उल्टे"',
  '        description "Hindi adjective (romanized ulte), the oblique or plural form of ulta, meaning reverse or inverted."',
  '    lexeme "zh"',
  '      word "反向"',
  '        description "Chinese adjective and verb (pinyin fanxiang) meaning reverse or opposite direction; the Chinese surface for the reverse concept."',
  '      word "相反"',
  '        description "Chinese adjective (pinyin xiangfan) meaning opposite or contrary; an alternative Chinese surface for the reverse concept."',
  '      word "倒序"',
  '        description "Chinese noun and verb (pinyin daoxu) meaning reverse order; a Chinese surface for putting items into the opposite order."',
  '  meaning "cancel"',
  '    gloss "to undo or remove a previously applied modification"',
  '    wiktionary "cancel"',
  '    defined_by "reverse"',
  '    defined_by "modify"',
  '    role "program_modification"',
  '    lexeme "en"',
  '      word "cancel"',
  '        description "English verb meaning to undo or remove a previously applied modification; the lemma surface for the cancel concept."',
  '      word "undo"',
  '        description "English verb meaning to reverse a previous action; a synonym surface for the cancel concept."',
  '      word "remove"',
  '        description "English verb meaning to take away or delete; a synonym surface for cancelling a modification."',
  '      word "revert"',
  '        description "English verb meaning to return to a previous state; a synonym surface for the cancel concept."',
  '    lexeme "ru"',
  '      word "отмени"',
  '        description "Russian verb (romanized otmeni), the informal imperative, commanding to cancel or undo a modification."',
  '      word "отмените"',
  '        description "Russian verb (romanized otmenite), the polite or plural imperative, commanding to cancel or undo a modification."',
  '      word "отменить"',
  '        description "Russian verb (romanized otmenit), the perfective infinitive, meaning to cancel or undo a modification."',
  '      word "убери"',
  '        description "Russian verb (romanized uberi), the informal imperative, commanding to remove or take away something."',
  '      word "уберите"',
  '        description "Russian verb (romanized uberite), the polite or plural imperative, commanding to remove or take away something."',
  '      word "убрать"',
  '        description "Russian verb (romanized ubrat), the perfective infinitive, meaning to remove or take away something."',
  '    lexeme "hi"',
  '      word "रद्द"',
  '        description "Hindi adjective and verb stem (romanized radd) meaning cancelled or to cancel; the lemma surface for the cancel concept."',
  '      word "हटाओ"',
  '        description "Hindi verb (romanized hatao), the informal imperative, commanding to remove or take away something."',
  '      word "हटाएं"',
  '        description "Hindi verb (romanized hataen), the polite imperative, commanding to remove or take away something."',
  '      word "हटा"',
  '        description "Hindi verb (romanized hata), a stem or past form of remove, meaning removed or take away."',
  '    lexeme "zh"',
  '      word "取消"',
  '        description "Chinese verb (pinyin quxiao) meaning to cancel or call off; the lemma surface for the cancel concept."',
  '      word "撤销"',
  '        description "Chinese verb (pinyin chexiao) meaning to revoke or undo; an alternative Chinese surface for the cancel concept."',
  '      word "去掉"',
  '        description "Chinese verb (pinyin qudiao) meaning to remove or get rid of; a Chinese surface for removing a modification."',
  '      word "去除"',
  '        description "Chinese verb (pinyin quchu) meaning to remove or eliminate; a Chinese surface for removing a modification."',
  '  meaning "modify"',
  '    gloss "to change an existing thing into a different state"',
  '    wiktionary "modify"',
  '    defined_by "update"',
  '    defined_by "action"',
  '    role "program_modification"',
  '    lexeme "en"',
  '      word "change"',
  '        description "English verb meaning to make something different; a synonym surface for the modify concept."',
  '      word "modify"',
  '        description "English verb meaning to change an existing thing into a different state; the lemma surface for the modify concept."',
  '      word "alter"',
  '        description "English verb meaning to change or adjust; a synonym surface for the modify concept."',
  '    lexeme "ru"',
  '      word "измени"',
  '        description "Russian verb (romanized izmeni), the informal imperative, commanding to change or modify something."',
  '      word "изменить"',
  '        description "Russian verb (romanized izmenit), the perfective infinitive, meaning to change or modify something."',
  '      word "измените"',
  '        description "Russian verb (romanized izmenite), the polite or plural imperative, commanding to change or modify something."',
  '    lexeme "hi"',
  '      word "बदलें"',
  '        description "Hindi verb (romanized badlen), the polite imperative, commanding to change or modify something."',
  '      word "बदलो"',
  '        description "Hindi verb (romanized badlo), the informal imperative, commanding to change or modify something."',
  '    lexeme "zh"',
  '      word "修改"',
  '        description "Chinese verb (pinyin xiugai) meaning to modify or revise; the lemma surface for the modify concept."',
  '      word "改"',
  '        description "Chinese verb (pinyin gai) meaning to change or alter; a shorter Chinese surface for the modify concept."',
  '  meaning "update"',
  '    gloss "to bring something to a newer state"',
  '    wiktionary "update"',
  '    defined_by "modify"',
  '    role "program_modification"',
  '    lexeme "en"',
  '      word "update"',
  '        description "English verb meaning to bring something to a newer state; the lemma surface for the update concept."',
  '    lexeme "ru"',
  '      word "обнови"',
  '        description "Russian verb (romanized obnovi), the informal imperative, commanding to update or bring something to a newer state."',
  '      word "обновить"',
  '        description "Russian verb (romanized obnovit), the perfective infinitive, meaning to update or bring something to a newer state."',
  '      word "обновите"',
  '        description "Russian verb (romanized obnovite), the polite or plural imperative, commanding to update something."',
  '    lexeme "hi"',
  '      word "अपडेट"',
  '        description "Hindi verb or noun (romanized apadet, a loanword from English update) for updating to a newer state; the Hindi surface for the update concept."',
  '    lexeme "zh"',
  '      word "更新"',
  '        description "Chinese verb and noun (pinyin gengxin) meaning to update or renew; the Chinese surface for the update concept."',
  '  meaning "make"',
  '    gloss "to produce or build a program or its output"',
  '    wiktionary "make"',
  '    defined_by "program"',
  '    defined_by "output"',
  '    role "program_modification"',
  '    role "program_request"',
  '    role "software_authoring_action"',
  '    lexeme "en"',
  '      word "make"',
  '        description "English verb meaning to produce or build a program or its output; the lemma surface for the make concept."',
  '    lexeme "ru"',
  '      word "сделай"',
  '        description "Russian verb (romanized sdelay), the perfective informal imperative, commanding to make or produce something."',
  '      word "сделайте"',
  '        description "Russian verb (romanized sdelayte), the perfective polite or plural imperative, commanding to make or produce something."',
  '      word "сделать"',
  '        description "Russian verb (romanized sdelat), the perfective infinitive, meaning to make or produce something."',
  '    lexeme "hi"',
  '      word "बनाओ"',
  '        description "Hindi verb (romanized banao), the informal imperative, commanding to make or build something."',
  '      word "बनाएं"',
  '        description "Hindi verb (romanized banaen), the polite imperative, commanding to make or build something."',
  '    lexeme "zh"',
  '      word "制作"',
  '        description "Chinese verb (pinyin zhizuo) meaning to make or produce; the Chinese surface for the make concept."',
  '  meaning "function"',
  '    gloss "a named, reusable block of program code that performs a task"',
  '    wiktionary "function"',
  '    defined_by "code"',
  '    defined_by "program"',
  '    role "program_artifact"',
  '    role "program_kind"',
  '    lexeme "en"',
  '      word "function"',
  '        description "English noun for a named, reusable block of program code that performs a task; the lemma surface for the function concept."',
  '      word "func"',
  '        description "English noun, a common abbreviation of function, for the same reusable block of code."',
  '    lexeme "ru"',
  '      word "функция"',
  '        description "Russian noun (romanized funktsiya) in the nominative for a code function; the lemma surface for the function concept."',
  '      word "функцию"',
  '        description "Russian noun (romanized funktsiyu), the accusative singular of function, naming the same code function."',
  '    lexeme "hi"',
  '      word "फ़ंक्शन"',
  '        description "Hindi noun (romanized funkshan, a loanword) for a reusable block of code; the Hindi surface for the function concept."',
  '      word "फंक्शन"',
  '        description "Hindi noun (romanized funkshan), a spelling variant without the nuqta, for the same code function."',
  '    lexeme "zh"',
  '      word "函数"',
  '        description "Chinese noun (pinyin hanshu) for a function in code or mathematics; the Chinese surface for the function concept."',
  '  meaning "write"',
  "    gloss \"to author a program or its code. It carries program_request (the general verb side of 'write a <kind>') and software_authoring_action, and additionally script_authoring_verb — the narrow verb the script-authoring recogniser pairs with a script-or-code artifact noun. That role lives on write alone, not on create/show/generate, so only an explicit author verb can route a bare script request.\"",
  '    wiktionary "write"',
  '    defined_by "code"',
  '    defined_by "program"',
  '    role "program_request"',
  '    role "software_authoring_action"',
  '    role "script_authoring_verb"',
  '    lexeme "en"',
  '      word "write"',
  '        description "English verb meaning to author a program or its code; the lemma surface for the write concept."',
  '    lexeme "ru"',
  '      word "напиши"',
  '        description "Russian verb (romanized napishi), the perfective informal imperative, commanding to write or author code."',
  '      word "напишите"',
  '        description "Russian verb (romanized napishite), the perfective polite or plural imperative, commanding to write or author code."',
  '      word "написать"',
  "        description \"Russian verb (romanized napisat'), the perfective infinitive, naming the act of writing or authoring code (as in 'написать скрипт', to write a script).\"",
  '    lexeme "hi"',
  '      word "लिखो"',
  '        description "Hindi verb (romanized likho), the informal imperative, commanding to write or author something."',
  '      word "लिखें"',
  '        description "Hindi verb (romanized likhen), the polite imperative, commanding to write or author something."',
  '    lexeme "zh"',
  '      word "编写"',
  '        description "Chinese verb (pinyin bianxie) meaning to write or compose code; the lemma surface for the write concept."',
  '      word "写"',
  '        description "Chinese verb (pinyin xie) meaning to write; a shorter Chinese surface for the write concept."',
  '  meaning "create"',
  '    gloss "to bring a program or its artifact into existence"',
  '    wiktionary "create"',
  '    defined_by "make"',
  '    defined_by "program"',
  '    role "program_request"',
  '    role "software_authoring_action"',
  '    lexeme "en"',
  '      word "create"',
  '        description "English verb meaning to bring a program or its artifact into existence; the lemma surface for the create concept."',
  '    lexeme "ru"',
  '      word "создай"',
  '        description "Russian verb (romanized sozday), the perfective informal imperative, commanding to create or bring something into existence."',
  '      word "создайте"',
  '        description "Russian verb (romanized sozdayte), the perfective polite or plural imperative, commanding to create something."',
  '    lexeme "hi"',
  '      word "बनाओ"',
  '        description "Hindi verb (romanized banao), the informal imperative, commanding to create or make something."',
  '      word "बनाएं"',
  '        description "Hindi verb (romanized banaen), the polite imperative, commanding to create or make something."',
  '    lexeme "zh"',
  '      word "创建"',
  '        description "Chinese verb (pinyin chuangjian) meaning to create or establish; the Chinese surface for the create concept."',
  '  meaning "show"',
  "    gloss \"to display a program's output or result\"",
  '    wiktionary "show"',
  '    defined_by "output"',
  '    defined_by "result"',
  '    role "program_request"',
  '    lexeme "en"',
  '      word "show"',
  "        description \"English verb meaning to display a program's output or result; the lemma surface for the show concept.\"",
  '    lexeme "ru"',
  '      word "покажи"',
  '        description "Russian verb (romanized pokazhi), the perfective informal imperative, commanding to show or display something."',
  '      word "покажите"',
  '        description "Russian verb (romanized pokazhite), the perfective polite or plural imperative, commanding to show or display something."',
  '    lexeme "hi"',
  '      word "दिखाओ"',
  '        description "Hindi verb (romanized dikhao), the informal imperative, commanding to show or display something."',
  '      word "दिखाएं"',
  '        description "Hindi verb (romanized dikhaen), the polite imperative, commanding to show or display something."',
  '    lexeme "zh"',
  '      word "显示"',
  '        description "Chinese verb (pinyin xianshi) meaning to display or show; the Chinese surface for the show concept."',
  '  meaning "generate"',
  '    gloss "to produce a program or output mechanically"',
  '    wiktionary "generate"',
  '    defined_by "output"',
  '    defined_by "program"',
  '    role "program_request"',
  '    role "software_authoring_action"',
  '    lexeme "en"',
  '      word "generate"',
  '        description "English verb meaning to produce a program or output mechanically; the lemma surface for the generate concept."',
  '    lexeme "ru"',
  '      word "сгенерируй"',
  '        description "Russian verb (romanized sgeneriruy), the perfective informal imperative, commanding to generate or produce something."',
  '      word "сгенерируйте"',
  '        description "Russian verb (romanized sgeneriruyte), the perfective polite or plural imperative, commanding to generate something."',
  '    lexeme "hi"',
  '      word "उत्पन्न"',
  '        description "Hindi verb stem and adjective (romanized utpann) meaning generated or to produce; the native Hindi surface for the generate concept."',
  '      word "जनरेट"',
  '        description "Hindi verb (romanized janaret, a loanword from English generate) for generating something; the Hindi surface for the generate concept."',
  '    lexeme "zh"',
  '      word "生成"',
  '        description "Chinese verb (pinyin shengcheng) meaning to generate or produce; the Chinese surface for the generate concept."',
  '  meaning "build"',
  '    gloss "to assemble a program from its parts"',
  '    wiktionary "build"',
  '    defined_by "make"',
  '    defined_by "program"',
  '    role "program_request"',
  '    role "software_authoring_action"',
  '    lexeme "en"',
  '      word "build"',
  '        description "English verb meaning to assemble a program from its parts; the lemma surface for the build concept."',
  '    lexeme "ru"',
  '      word "построй"',
  '        description "Russian verb (romanized postroy), the perfective informal imperative, commanding to build or construct something."',
  '      word "собери"',
  '        description "Russian verb (romanized soberi), the perfective informal imperative, commanding to assemble or build something from parts."',
  '    lexeme "hi"',
  '      word "बनाओ"',
  '        description "Hindi verb (romanized banao), the informal imperative, commanding to build or make something."',
  '      word "बनाएं"',
  '        description "Hindi verb (romanized banaen), the polite imperative, commanding to build or make something."',
  '    lexeme "zh"',
  '      word "构建"',
  '        description "Chinese verb (pinyin goujian) meaning to build or construct; the Chinese surface for the build concept."',
  "meanings",
  '  meaning "quantity"',
  '    gloss "an amount of something that can be measured or counted"',
  '    wiktionary "quantity"',
  '    defined_by "unit"',
  '    defined_by "property"',
  '    role "measurement_concept"',
  '    lexeme "en"',
  '      word "quantity"',
  '        description "English noun for an amount of something that can be measured or counted; the general measurement concept."',
  '    lexeme "ru"',
  '      word "количество"',
  '        description "Russian noun (romanized kolichestvo) for an amount or quantity; the Russian surface for the quantity concept."',
  '    lexeme "hi"',
  '      word "मात्रा"',
  '        description "Hindi noun (romanized matra) for an amount or quantity; the Hindi surface for the quantity concept."',
  '    lexeme "zh"',
  '      word "数量"',
  '        description "Chinese noun (pinyin shuliang) for an amount or quantity; the Chinese surface for the quantity concept."',
  '  meaning "unit"',
  '    gloss "a standard amount used to measure a quantity"',
  '    wiktionary "unit"',
  '    defined_by "quantity"',
  '    role "measurement_concept"',
  '    lexeme "en"',
  '      word "unit"',
  '        description "English noun for a standard amount used to measure a quantity; the general unit concept."',
  '    lexeme "ru"',
  '      word "единица"',
  '        description "Russian noun (romanized edinitsa) for a unit; the Russian surface for the unit concept."',
  '    lexeme "hi"',
  '      word "इकाई"',
  '        description "Hindi noun (romanized ikai) for a unit; the Hindi surface for the unit concept."',
  '    lexeme "zh"',
  '      word "单位"',
  '        description "Chinese noun (pinyin danwei) for a unit; the Chinese surface for the unit concept."',
  '  meaning "cardinal_number"',
  '    gloss "a number used to count how many things there are: zero, one, two, three, and so on. The genus of the individual counting numbers, each defined as a kind of cardinal number rather than listed in code."',
  '    wiktionary "cardinal number"',
  '    defined_by "quantity"',
  '    role "numeric_concept"',
  '    lexeme "en"',
  '      word "cardinal number"',
  "        description \"English term for a counting number that answers the question 'how many'; the genus of the individual cardinals.\"",
  '      word "number"',
  '        description "English noun for a number used in counting; the everyday surface for the counting-number concept."',
  '    lexeme "ru"',
  '      word "количественное число"',
  '        description "Russian term (romanized kolichestvennoe chislo) for a cardinal counting number; the Russian surface for the cardinal-number concept."',
  '    lexeme "hi"',
  '      word "गणन संख्या"',
  '        description "Hindi term (romanized ganan sankhya) for a cardinal counting number; the Hindi surface for the cardinal-number concept."',
  '    lexeme "zh"',
  '      word "基数"',
  '        description "Chinese term (pinyin jishu) for a cardinal counting number; the Chinese surface for the cardinal-number concept."',
  '  meaning "zero"',
  '    gloss "the cardinal number zero (0), the count of an empty collection."',
  '    wiktionary "zero"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "zero"',
  '        description "English spelled form of the cardinal number zero."',
  '      word "0"',
  "        description \"Western Arabic numeral for zero; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "ноль"',
  "        description \"Russian spelled form (romanized nol') of the cardinal number zero.\"",
  '      word "нуль"',
  "        description \"Russian spelled form (romanized nul'), a variant spelling, of the cardinal number zero.\"",
  '    lexeme "hi"',
  '      word "शून्य"',
  '        description "Hindi spelled form (romanized shunya) of the cardinal number zero."',
  '    lexeme "zh"',
  '      word "零"',
  '        description "Chinese spelled form (pinyin ling) of the cardinal number zero."',
  '  meaning "one"',
  '    gloss "the cardinal number one (1), one more than zero."',
  '    wiktionary "one"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "one"',
  '        description "English spelled form of the cardinal number one."',
  '      word "1"',
  "        description \"Western Arabic numeral for one; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "один"',
  '        description "Russian spelled form (romanized odin), masculine, of the cardinal number one."',
  '      word "одна"',
  '        description "Russian spelled form (romanized odna), feminine, of the cardinal number one."',
  '      word "одно"',
  '        description "Russian spelled form (romanized odno), neuter, of the cardinal number one."',
  '    lexeme "hi"',
  '      word "एक"',
  '        description "Hindi spelled form (romanized ek) of the cardinal number one."',
  '    lexeme "zh"',
  '      word "一"',
  '        description "Chinese spelled form (pinyin yi) of the cardinal number one."',
  '  meaning "two"',
  '    gloss "the cardinal number two (2), one more than one."',
  '    wiktionary "two"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "two"',
  '        description "English spelled form of the cardinal number two."',
  '      word "2"',
  "        description \"Western Arabic numeral for two; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "два"',
  '        description "Russian spelled form (romanized dva), masculine and neuter, of the cardinal number two."',
  '      word "две"',
  '        description "Russian spelled form (romanized dve), feminine, of the cardinal number two."',
  '    lexeme "hi"',
  '      word "दो"',
  '        description "Hindi spelled form (romanized do) of the cardinal number two."',
  '    lexeme "zh"',
  '      word "二"',
  '        description "Chinese spelled form (pinyin er) of the cardinal number two."',
  '  meaning "three"',
  '    gloss "the cardinal number three (3), one more than two."',
  '    wiktionary "three"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "three"',
  '        description "English spelled form of the cardinal number three."',
  '      word "3"',
  "        description \"Western Arabic numeral for three; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "три"',
  '        description "Russian spelled form (romanized tri) of the cardinal number three."',
  '    lexeme "hi"',
  '      word "तीन"',
  '        description "Hindi spelled form (romanized teen) of the cardinal number three."',
  '    lexeme "zh"',
  '      word "三"',
  '        description "Chinese spelled form (pinyin san) of the cardinal number three."',
  '  meaning "four"',
  '    gloss "the cardinal number four (4), one more than three."',
  '    wiktionary "four"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "four"',
  '        description "English spelled form of the cardinal number four."',
  '      word "4"',
  "        description \"Western Arabic numeral for four; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "четыре"',
  '        description "Russian spelled form (romanized chetyre) of the cardinal number four."',
  '    lexeme "hi"',
  '      word "चार"',
  '        description "Hindi spelled form (romanized char) of the cardinal number four."',
  '    lexeme "zh"',
  '      word "四"',
  '        description "Chinese spelled form (pinyin si) of the cardinal number four."',
  '  meaning "five"',
  '    gloss "the cardinal number five (5), one more than four."',
  '    wiktionary "five"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "five"',
  '        description "English spelled form of the cardinal number five."',
  '      word "5"',
  "        description \"Western Arabic numeral for five; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "пять"',
  "        description \"Russian spelled form (romanized pyat') of the cardinal number five.\"",
  '    lexeme "hi"',
  '      word "पाँच"',
  '        description "Hindi spelled form (romanized panch) of the cardinal number five."',
  '    lexeme "zh"',
  '      word "五"',
  '        description "Chinese spelled form (pinyin wu) of the cardinal number five."',
  '  meaning "six"',
  '    gloss "the cardinal number six (6), one more than five."',
  '    wiktionary "six"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "six"',
  '        description "English spelled form of the cardinal number six."',
  '      word "6"',
  "        description \"Western Arabic numeral for six; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "шесть"',
  "        description \"Russian spelled form (romanized shest') of the cardinal number six.\"",
  '    lexeme "hi"',
  '      word "छह"',
  '        description "Hindi spelled form (romanized chhah) of the cardinal number six."',
  '    lexeme "zh"',
  '      word "六"',
  '        description "Chinese spelled form (pinyin liu) of the cardinal number six."',
  '  meaning "seven"',
  '    gloss "the cardinal number seven (7), one more than six."',
  '    wiktionary "seven"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "seven"',
  '        description "English spelled form of the cardinal number seven."',
  '      word "7"',
  "        description \"Western Arabic numeral for seven; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "семь"',
  "        description \"Russian spelled form (romanized sem') of the cardinal number seven.\"",
  '    lexeme "hi"',
  '      word "सात"',
  '        description "Hindi spelled form (romanized saat) of the cardinal number seven."',
  '    lexeme "zh"',
  '      word "七"',
  '        description "Chinese spelled form (pinyin qi) of the cardinal number seven."',
  '  meaning "eight"',
  '    gloss "the cardinal number eight (8), one more than seven."',
  '    wiktionary "eight"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "eight"',
  '        description "English spelled form of the cardinal number eight."',
  '      word "8"',
  "        description \"Western Arabic numeral for eight; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "восемь"',
  "        description \"Russian spelled form (romanized vosem') of the cardinal number eight.\"",
  '    lexeme "hi"',
  '      word "आठ"',
  '        description "Hindi spelled form (romanized aath) of the cardinal number eight."',
  '    lexeme "zh"',
  '      word "八"',
  '        description "Chinese spelled form (pinyin ba) of the cardinal number eight."',
  '  meaning "nine"',
  '    gloss "the cardinal number nine (9), one more than eight."',
  '    wiktionary "nine"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "nine"',
  '        description "English spelled form of the cardinal number nine."',
  '      word "9"',
  "        description \"Western Arabic numeral for nine; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "девять"',
  "        description \"Russian spelled form (romanized devyat') of the cardinal number nine.\"",
  '    lexeme "hi"',
  '      word "नौ"',
  '        description "Hindi spelled form (romanized nau) of the cardinal number nine."',
  '    lexeme "zh"',
  '      word "九"',
  '        description "Chinese spelled form (pinyin jiu) of the cardinal number nine."',
  '  meaning "ten"',
  '    gloss "the cardinal number ten (10), one more than nine."',
  '    wiktionary "ten"',
  '    defined_by "cardinal_number"',
  '    role "cardinal_number_word"',
  '    lexeme "en"',
  '      word "ten"',
  '        description "English spelled form of the cardinal number ten."',
  '      word "10"',
  "        description \"Western Arabic numeral for ten; the script-independent numeral surface, from which the cardinal's integer value is read.\"",
  '    lexeme "ru"',
  '      word "десять"',
  "        description \"Russian spelled form (romanized desyat') of the cardinal number ten.\"",
  '    lexeme "hi"',
  '      word "दस"',
  '        description "Hindi spelled form (romanized das) of the cardinal number ten."',
  '    lexeme "zh"',
  '      word "十"',
  '        description "Chinese spelled form (pinyin shi) of the cardinal number ten."',
  '  meaning "length"',
  '    gloss "the physical dimension of distance or extent"',
  '    wiktionary "length"',
  '    defined_by "quantity"',
  '    role "physical_dimension"',
  '    lexeme "en"',
  '      word "length"',
  '        description "English noun for the physical dimension of distance or extent; the length dimension."',
  '    lexeme "ru"',
  '      word "длина"',
  '        description "Russian noun (romanized dlina) for length; the Russian surface for the length dimension."',
  '    lexeme "hi"',
  '      word "लंबाई"',
  '        description "Hindi noun (romanized lambai) for length; the Hindi surface for the length dimension."',
  '    lexeme "zh"',
  '      word "长度"',
  '        description "Chinese noun (pinyin changdu) for length; the Chinese surface for the length dimension."',
  '  meaning "data_storage"',
  '    gloss "the physical dimension of how much information is stored"',
  '    wiktionary "data"',
  '    defined_by "quantity"',
  '    role "physical_dimension"',
  '    lexeme "en"',
  '      word "data storage"',
  '        description "English noun phrase for the dimension of how much information is stored; the data-storage dimension."',
  '    lexeme "ru"',
  '      word "хранение данных"',
  '        description "Russian noun phrase (romanized khranenie dannykh) for data storage; the Russian surface for the data-storage dimension."',
  '    lexeme "hi"',
  '      word "डेटा भंडारण"',
  '        description "Hindi noun phrase (romanized deta bhandaran) for data storage; the Hindi surface for the data-storage dimension."',
  '    lexeme "zh"',
  '      word "数据存储"',
  '        description "Chinese noun phrase (pinyin shuju cunchu) for data storage; the Chinese surface for the data-storage dimension."',
  '  meaning "mass"',
  '    gloss "the physical dimension of how much matter an object contains"',
  '    wiktionary "mass"',
  '    defined_by "quantity"',
  '    role "physical_dimension"',
  '    lexeme "en"',
  '      word "mass"',
  '        description "English noun for the dimension of how much matter an object contains; the mass dimension."',
  '    lexeme "ru"',
  '      word "масса"',
  '        description "Russian noun (romanized massa) for mass; the Russian surface for the mass dimension."',
  '    lexeme "hi"',
  '      word "द्रव्यमान"',
  '        description "Hindi noun (romanized dravyaman) for mass; the Hindi surface for the mass dimension."',
  '    lexeme "zh"',
  '      word "质量"',
  '        description "Chinese noun (pinyin zhiliang) for mass; the Chinese surface for the mass dimension."',
  '  meaning "time"',
  '    gloss "the physical dimension of duration"',
  '    wiktionary "time"',
  '    defined_by "quantity"',
  '    role "physical_dimension"',
  '    lexeme "en"',
  '      word "time"',
  '        description "English noun for the physical dimension of duration; the time dimension."',
  '    lexeme "ru"',
  '      word "время"',
  '        description "Russian noun (romanized vremya) for time; the Russian surface for the time dimension."',
  '    lexeme "hi"',
  '      word "समय"',
  '        description "Hindi noun (romanized samay) for time; the Hindi surface for the time dimension."',
  '    lexeme "zh"',
  '      word "时间"',
  '        description "Chinese noun (pinyin shijian) for time; the Chinese surface for the time dimension."',
  '  meaning "temperature"',
  '    gloss "the physical dimension of thermal energy"',
  '    wiktionary "temperature"',
  '    defined_by "quantity"',
  '    role "physical_dimension"',
  '    lexeme "en"',
  '      word "temperature"',
  '        description "English noun for the physical dimension of thermal energy; the temperature dimension."',
  '    lexeme "ru"',
  '      word "температура"',
  '        description "Russian noun (romanized temperatura) for temperature; the Russian surface for the temperature dimension."',
  '    lexeme "hi"',
  '      word "तापमान"',
  '        description "Hindi noun (romanized tapman) for temperature; the Hindi surface for the temperature dimension."',
  '    lexeme "zh"',
  '      word "温度"',
  '        description "Chinese noun (pinyin wendu) for temperature; the Chinese surface for the temperature dimension."',
  '  meaning "meter"',
  '    gloss "the base unit of length"',
  '    wiktionary "metre"',
  '    defined_by "length"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "meter"',
  '        description "English noun for the base unit of length (American spelling); a full-word form of the metre."',
  '      word "metre"',
  '        description "English noun for the base unit of length (British spelling); a full-word form of the metre."',
  '      word "meters"',
  '        description "English noun, the plural of meter; the base unit of length in the length dimension."',
  '      word "metres"',
  '        description "English noun, the plural of metre; the base unit of length in the length dimension."',
  '    lexeme "ru"',
  '      word "метр"',
  '        description "Russian noun (romanized metr) for the metre, the base unit of length; the Russian surface for the meter."',
  '      word "метра"',
  '        description "Russian noun (romanized metra), an inflected genitive form of metre; a case form of the base unit of length."',
  '      word "метров"',
  '        description "Russian noun (romanized metrov), the genitive plural of metre; a case form of the base unit of length."',
  '    lexeme "hi"',
  '      word "मीटर"',
  '        description "Hindi noun (romanized mitar) for the metre, the base unit of length; the Hindi surface for the meter."',
  '    lexeme "zh"',
  '      word "米"',
  '        description "Chinese noun (pinyin mi) for the metre, the base unit of length; the Chinese surface for the meter."',
  '  meaning "kilometer"',
  '    gloss "a unit of length equal to one thousand metres"',
  '    wiktionary "kilometre"',
  '    defined_by "length"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "km"',
  '        description "English abbreviation, the symbol for kilometre, a unit of length equal to one thousand metres."',
  '      word "kilometer"',
  '        description "English noun for a unit of length of one thousand metres (American spelling); a full-word form."',
  '      word "kilometre"',
  '        description "English noun for a unit of length of one thousand metres (British spelling); a full-word form."',
  '      word "kilometers"',
  '        description "English noun, the plural of kilometer; a unit of length equal to one thousand metres."',
  '      word "kilometres"',
  '        description "English noun, the plural of kilometre; a unit of length equal to one thousand metres."',
  '    lexeme "ru"',
  '      word "километр"',
  '        description "Russian noun (romanized kilometr) for the kilometre, a unit of length of one thousand metres."',
  '      word "километра"',
  '        description "Russian noun (romanized kilometra), an inflected genitive form of kilometre; a case form of the unit of length."',
  '      word "километров"',
  '        description "Russian noun (romanized kilometrov), the genitive plural of kilometre; a case form of the unit of length."',
  '    lexeme "hi"',
  '      word "किलोमीटर"',
  '        description "Hindi noun (romanized kilomitar) for the kilometre, a unit of length of one thousand metres."',
  '    lexeme "zh"',
  '      word "千米"',
  '        description "Chinese noun (pinyin qianmi) for the kilometre, a unit of length of one thousand metres."',
  '      word "公里"',
  '        description "Chinese noun (pinyin gongli) for the kilometre; a common alternative surface for the unit of length."',
  '  meaning "centimeter"',
  '    gloss "a unit of length equal to one hundredth of a metre"',
  '    wiktionary "centimetre"',
  '    defined_by "length"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "cm"',
  '        description "English abbreviation, the symbol for centimetre, a unit of length equal to one hundredth of a metre."',
  '      word "centimeter"',
  '        description "English noun for a unit of length of one hundredth of a metre (American spelling); a full-word form."',
  '      word "centimetre"',
  '        description "English noun for a unit of length of one hundredth of a metre (British spelling); a full-word form."',
  '    lexeme "ru"',
  '      word "сантиметр"',
  '        description "Russian noun (romanized santimetr) for the centimetre, a unit of length of one hundredth of a metre."',
  '    lexeme "hi"',
  '      word "सेंटीमीटर"',
  '        description "Hindi noun (romanized sentimitar) for the centimetre, a unit of length of one hundredth of a metre."',
  '    lexeme "zh"',
  '      word "厘米"',
  '        description "Chinese noun (pinyin limi) for the centimetre, a unit of length of one hundredth of a metre."',
  '  meaning "millimeter"',
  '    gloss "a unit of length equal to one thousandth of a metre"',
  '    wiktionary "millimetre"',
  '    defined_by "length"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "mm"',
  '        description "English abbreviation, the symbol for millimetre, a unit of length equal to one thousandth of a metre."',
  '      word "millimeter"',
  '        description "English noun for a unit of length of one thousandth of a metre (American spelling); a full-word form."',
  '      word "millimetre"',
  '        description "English noun for a unit of length of one thousandth of a metre (British spelling); a full-word form."',
  '    lexeme "ru"',
  '      word "миллиметр"',
  '        description "Russian noun (romanized millimetr) for the millimetre, a unit of length of one thousandth of a metre."',
  '    lexeme "hi"',
  '      word "मिलीमीटर"',
  '        description "Hindi noun (romanized millimitar) for the millimetre, a unit of length of one thousandth of a metre."',
  '    lexeme "zh"',
  '      word "毫米"',
  '        description "Chinese noun (pinyin haomi) for the millimetre, a unit of length of one thousandth of a metre."',
  '  meaning "byte"',
  '    gloss "a unit of digital information, eight bits"',
  '    wiktionary "byte"',
  '    defined_by "data_storage"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "byte"',
  '        description "English noun for a unit of digital information of eight bits; the base unit of data storage."',
  '      word "bytes"',
  '        description "English noun, the plural of byte; units of digital information of eight bits each."',
  '    lexeme "ru"',
  '      word "байт"',
  '        description "Russian noun (romanized bait) for the byte, a unit of digital information of eight bits."',
  '      word "байта"',
  '        description "Russian noun (romanized baita), an inflected genitive form of byte; a case form of the data-storage unit."',
  '      word "байтов"',
  '        description "Russian noun (romanized baitov), the genitive plural of byte; a case form of the data-storage unit."',
  '    lexeme "hi"',
  '      word "बाइट"',
  '        description "Hindi noun (romanized bait) for the byte, a unit of digital information of eight bits."',
  '    lexeme "zh"',
  '      word "字节"',
  '        description "Chinese noun (pinyin zijie) for the byte, a unit of digital information of eight bits."',
  '  meaning "kilobyte"',
  '    gloss "a unit of digital information of about one thousand bytes. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "kilobyte"',
  '    defined_by "data_storage"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "kb"',
  '        description "English abbreviation, the symbol for kilobyte, a unit of digital information of about one thousand bytes."',
  '      word "kilobyte"',
  '        description "English noun for a unit of digital information of about one thousand bytes; a full-word form."',
  '      word "kilobytes"',
  '        description "English noun, the plural of kilobyte; units of digital information of about one thousand bytes each."',
  '    lexeme "ru"',
  '      word "килобайт"',
  '        description "Russian noun (romanized kilobait) for the kilobyte, a unit of digital information of about one thousand bytes."',
  '    lexeme "hi"',
  '      word "किलोबाइट"',
  '        description "Hindi noun (romanized kilobait) for the kilobyte, a unit of digital information of about one thousand bytes."',
  '    lexeme "zh"',
  '      word "千字节"',
  '        description "Chinese noun (pinyin qian zijie) for the kilobyte, a unit of digital information of about one thousand bytes."',
  '  meaning "megabyte"',
  '    gloss "a unit of digital information of about one million bytes. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "megabyte"',
  '    defined_by "data_storage"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "mb"',
  '        description "English abbreviation, the symbol for megabyte, a unit of digital information of about one million bytes."',
  '      word "megabyte"',
  '        description "English noun for a unit of digital information of about one million bytes; a full-word form."',
  '      word "megabytes"',
  '        description "English noun, the plural of megabyte; units of digital information of about one million bytes each."',
  '    lexeme "ru"',
  '      word "мегабайт"',
  '        description "Russian noun (romanized megabait) for the megabyte, a unit of digital information of about one million bytes."',
  '    lexeme "hi"',
  '      word "मेगाबाइट"',
  '        description "Hindi noun (romanized megabait) for the megabyte, a unit of digital information of about one million bytes."',
  '    lexeme "zh"',
  '      word "兆字节"',
  '        description "Chinese noun (pinyin zhao zijie) for the megabyte, a unit of digital information of about one million bytes."',
  '  meaning "gigabyte"',
  '    gloss "a unit of digital information of about one billion bytes"',
  '    wiktionary "gigabyte"',
  '    defined_by "data_storage"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "gb"',
  '        description "English abbreviation, the symbol for gigabyte, a unit of digital information of about one billion bytes."',
  '      word "gigabyte"',
  '        description "English noun for a unit of digital information of about one billion bytes; a full-word form."',
  '      word "gigabytes"',
  '        description "English noun, the plural of gigabyte; units of digital information of about one billion bytes each."',
  '    lexeme "ru"',
  '      word "гигабайт"',
  '        description "Russian noun (romanized gigabait) for the gigabyte, a unit of digital information of about one billion bytes."',
  '    lexeme "hi"',
  '      word "गीगाबाइट"',
  '        description "Hindi noun (romanized gigabait) for the gigabyte, a unit of digital information of about one billion bytes."',
  '    lexeme "zh"',
  '      word "吉字节"',
  '        description "Chinese noun (pinyin ji zijie) for the gigabyte, a unit of digital information of about one billion bytes."',
  '  meaning "terabyte"',
  '    gloss "a unit of digital information of about one trillion bytes"',
  '    wiktionary "terabyte"',
  '    defined_by "data_storage"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "tb"',
  '        description "English abbreviation, the symbol for terabyte, a unit of digital information of about one trillion bytes."',
  '      word "terabyte"',
  '        description "English noun for a unit of digital information of about one trillion bytes; a full-word form."',
  '      word "terabytes"',
  '        description "English noun, the plural of terabyte; units of digital information of about one trillion bytes each."',
  '    lexeme "ru"',
  '      word "терабайт"',
  '        description "Russian noun (romanized terabait) for the terabyte, a unit of digital information of about one trillion bytes."',
  '    lexeme "hi"',
  '      word "टेराबाइट"',
  '        description "Hindi noun (romanized terabait) for the terabyte, a unit of digital information of about one trillion bytes."',
  '    lexeme "zh"',
  '      word "太字节"',
  '        description "Chinese noun (pinyin tai zijie) for the terabyte, a unit of digital information of about one trillion bytes."',
  '  meaning "bit"',
  '    gloss "the smallest unit of digital information"',
  '    wiktionary "bit"',
  '    defined_by "data_storage"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "bit"',
  '        description "English noun for the smallest unit of digital information; the base binary digit of data storage."',
  '      word "bits"',
  '        description "English noun, the plural of bit; the smallest units of digital information."',
  '    lexeme "ru"',
  '      word "бит"',
  '        description "Russian noun (romanized bit) for the bit, the smallest unit of digital information."',
  '      word "бита"',
  '        description "Russian noun (romanized bita), an inflected genitive form of bit; a case form of the smallest data-storage unit."',
  '      word "битов"',
  '        description "Russian noun (romanized bitov), the genitive plural of bit; a case form of the smallest data-storage unit."',
  '    lexeme "hi"',
  '      word "बिट"',
  '        description "Hindi noun (romanized bit) for the bit, the smallest unit of digital information."',
  '    lexeme "zh"',
  '      word "比特"',
  '        description "Chinese noun (pinyin bite) for the bit, the smallest unit of digital information."',
  '  meaning "kilogram"',
  '    gloss "the base unit of mass. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "kilogram"',
  '    defined_by "mass"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "kg"',
  '        description "English abbreviation, the symbol for kilogram, the base unit of mass; a calculation_domain_term matched whole-token."',
  '      word "kilogram"',
  '        description "English noun for the base unit of mass (American spelling); a full-word form of the kilogram."',
  '      word "kilograms"',
  '        description "English noun, the plural of kilogram; the base unit of mass in the mass dimension."',
  '    lexeme "ru"',
  '      word "кг"',
  '        description "Russian abbreviation (romanized kg), the symbol for kilogram, the base unit of mass; a calculation_domain_term matched as a raw substring."',
  '      word "килограмм"',
  '        description "Russian noun (romanized kilogramm) for the kilogram, the base unit of mass."',
  '    lexeme "hi"',
  '      word "किलोग्राम"',
  '        description "Hindi noun (romanized kilogram) for the kilogram, the base unit of mass."',
  '    lexeme "zh"',
  '      word "千克"',
  '        description "Chinese noun (pinyin qianke) for the kilogram, the base unit of mass."',
  '      word "公斤"',
  '        description "Chinese noun (pinyin gongjin) for the kilogram; a common alternative surface for the base unit of mass."',
  '  meaning "gram"',
  '    gloss "a unit of mass equal to one thousandth of a kilogram. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "gram"',
  '    defined_by "mass"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "gram"',
  '        description "English noun for a unit of mass equal to one thousandth of a kilogram; a full-word form."',
  '      word "grams"',
  '        description "English noun, the plural of gram; units of mass of one thousandth of a kilogram each."',
  '    lexeme "ru"',
  '      word "грамм"',
  '        description "Russian noun (romanized gramm) for the gram, a unit of mass of one thousandth of a kilogram."',
  '    lexeme "hi"',
  '      word "ग्राम"',
  '        description "Hindi noun (romanized gram) for the gram, a unit of mass of one thousandth of a kilogram."',
  '    lexeme "zh"',
  '      word "克"',
  '        description "Chinese noun (pinyin ke) for the gram, a unit of mass of one thousandth of a kilogram."',
  '  meaning "pound"',
  '    gloss "a unit of mass used in imperial measure"',
  '    wiktionary "pound"',
  '    defined_by "mass"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "pound"',
  '        description "English noun for a unit of mass used in imperial measure; a mass unit in the mass dimension."',
  '      word "pounds"',
  '        description "English noun, the plural of pound; units of mass used in imperial measure."',
  '    lexeme "ru"',
  '      word "фунт"',
  '        description "Russian noun (romanized funt) for the pound, a unit of mass used in imperial measure."',
  '    lexeme "hi"',
  '      word "पाउंड"',
  '        description "Hindi noun (romanized paund) for the pound, a unit of mass used in imperial measure."',
  '    lexeme "zh"',
  '      word "磅"',
  '        description "Chinese noun (pinyin bang) for the pound, a unit of mass used in imperial measure."',
  '  meaning "ton"',
  '    gloss "a unit of mass equal to one thousand kilograms. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "tonne"',
  '    defined_by "mass"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "ton"',
  '        description "English noun for a unit of mass equal to one thousand kilograms; a calculation_domain_term matched whole-token."',
  '      word "tons"',
  '        description "English noun, the plural of ton; units of mass of one thousand kilograms each."',
  '      word "tonne"',
  '        description "English noun, the metric spelling of ton; a unit of mass of one thousand kilograms."',
  '    lexeme "ru"',
  '      word "тонна"',
  '        description "Russian noun (romanized tonna) for the ton, a unit of mass of one thousand kilograms; a calculation_domain_term matched as a raw substring."',
  '      word "тонны"',
  '        description "Russian noun (romanized tonny), an inflected form of ton; a case form of the unit of mass, matched as a raw substring."',
  '      word "тонн"',
  '        description "Russian noun (romanized tonn), the genitive plural of ton; a case form of the unit of mass, matched as a raw substring."',
  '    lexeme "hi"',
  '      word "टन"',
  '        description "Hindi noun (romanized tan) for the ton, a unit of mass of one thousand kilograms; a calculation_domain_term matched as a raw substring."',
  '    lexeme "zh"',
  '      word "吨"',
  '        description "Chinese noun (pinyin dun) for the ton, a unit of mass of one thousand kilograms; a calculation_domain_term matched as a raw substring."',
  '  meaning "second"',
  '    gloss "the base unit of time. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "second"',
  '    defined_by "time"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "second"',
  '        description "English noun for the base unit of time; the base unit in the time dimension."',
  '      word "seconds"',
  '        description "English noun, the plural of second; the base units of time."',
  '    lexeme "ru"',
  '      word "секунда"',
  '        description "Russian noun (romanized sekunda) for the second, the base unit of time."',
  '      word "секунды"',
  '        description "Russian noun (romanized sekundy), an inflected form of second; a case form of the base unit of time."',
  '      word "секунд"',
  '        description "Russian noun (romanized sekund), the genitive plural of second; a case form of the base unit of time."',
  '    lexeme "hi"',
  '      word "सेकंड"',
  '        description "Hindi noun (romanized sekand) for the second, the base unit of time."',
  '    lexeme "zh"',
  '      word "秒"',
  '        description "Chinese noun (pinyin miao) for the second, the base unit of time."',
  '  meaning "minute"',
  '    gloss "a unit of time equal to sixty seconds. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "minute"',
  '    defined_by "time"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "minute"',
  '        description "English noun for a unit of time equal to sixty seconds; a time unit in the time dimension."',
  '      word "minutes"',
  '        description "English noun, the plural of minute; units of time of sixty seconds each."',
  '    lexeme "ru"',
  '      word "минута"',
  '        description "Russian noun (romanized minuta) for the minute, a unit of time equal to sixty seconds."',
  '      word "минуты"',
  '        description "Russian noun (romanized minuty), an inflected form of minute; a case form of the unit of time."',
  '      word "минут"',
  '        description "Russian noun (romanized minut), the genitive plural of minute; a case form of the unit of time."',
  '    lexeme "hi"',
  '      word "मिनट"',
  '        description "Hindi noun (romanized minat) for the minute, a unit of time equal to sixty seconds."',
  '    lexeme "zh"',
  '      word "分钟"',
  '        description "Chinese noun (pinyin fenzhong) for the minute, a unit of time equal to sixty seconds."',
  '  meaning "hour"',
  '    gloss "a unit of time equal to sixty minutes. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "hour"',
  '    defined_by "time"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "hour"',
  '        description "English noun for a unit of time equal to sixty minutes; a time unit in the time dimension."',
  '      word "hours"',
  '        description "English noun, the plural of hour; units of time of sixty minutes each."',
  '    lexeme "ru"',
  '      word "час"',
  '        description "Russian noun (romanized chas) for the hour, a unit of time equal to sixty minutes."',
  '      word "часа"',
  '        description "Russian noun (romanized chasa), an inflected genitive form of hour; a case form of the unit of time."',
  '      word "часов"',
  '        description "Russian noun (romanized chasov), the genitive plural of hour; a case form of the unit of time."',
  '    lexeme "hi"',
  '      word "घंटा"',
  '        description "Hindi noun (romanized ghanta) for the hour, a unit of time equal to sixty minutes."',
  '    lexeme "zh"',
  '      word "小时"',
  '        description "Chinese noun (pinyin xiaoshi) for the hour, a unit of time equal to sixty minutes."',
  '  meaning "millisecond"',
  '    gloss "a unit of time equal to one thousandth of a second. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "millisecond"',
  '    defined_by "time"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "ms"',
  '        description "English abbreviation, the symbol for millisecond, a unit of time of one thousandth of a second; a calculation_domain_term matched whole-token."',
  '      word "millisecond"',
  '        description "English noun for a unit of time equal to one thousandth of a second; a full-word form."',
  '      word "milliseconds"',
  '        description "English noun, the plural of millisecond; units of time of one thousandth of a second each."',
  '    lexeme "ru"',
  '      word "миллисекунда"',
  '        description "Russian noun (romanized millisekunda) for the millisecond, a unit of time of one thousandth of a second; matched as a raw substring."',
  '      word "миллисекунд"',
  '        description "Russian noun (romanized millisekund), the genitive plural of millisecond; a case form of the unit of time, matched as a raw substring."',
  '    lexeme "hi"',
  '      word "मिलीसेकंड"',
  '        description "Hindi noun (romanized milisekand) for the millisecond, a unit of time of one thousandth of a second; matched as a raw substring."',
  '    lexeme "zh"',
  '      word "毫秒"',
  '        description "Chinese noun (pinyin haomiao) for the millisecond, a unit of time of one thousandth of a second; matched as a raw substring."',
  '  meaning "day"',
  '    gloss "a unit of time equal to twenty-four hours. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "day"',
  '    defined_by "time"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "day"',
  '        description "English noun for a unit of time equal to twenty-four hours; a calculation_domain_term matched whole-token."',
  '      word "days"',
  '        description "English noun, the plural of day; units of time of twenty-four hours each."',
  '    lexeme "ru"',
  '      word "день"',
  '        description "Russian noun (romanized den) for the day, a unit of time of twenty-four hours; matched as a raw substring."',
  '      word "дня"',
  '        description "Russian noun (romanized dnya), an inflected genitive form of day; a case form of the unit of time, matched as a raw substring."',
  '      word "дней"',
  '        description "Russian noun (romanized dney), the genitive plural of day; a case form of the unit of time, matched as a raw substring."',
  '    lexeme "hi"',
  '      word "दिन"',
  '        description "Hindi noun (romanized din) for the day, a unit of time of twenty-four hours; matched as a raw substring."',
  '    lexeme "zh"',
  '      word "天"',
  '        description "Chinese noun (pinyin tian) for the day, a unit of time of twenty-four hours; matched as a raw substring."',
  '      word "日"',
  '        description "Chinese noun (pinyin ri) for the day, a calendar-day unit of time; matched as a raw substring."',
  '  meaning "month"',
  '    gloss "a unit of time of about thirty days, one of the twelve divisions of a year. Also a calculation_domain_term, so it signals a calculation when it appears beside a number."',
  '    wiktionary "month"',
  '    defined_by "time"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "month"',
  '        description "English noun for a unit of time of about thirty days; a calculation_domain_term matched whole-token."',
  '      word "months"',
  '        description "English noun, the plural of month; units of time of about thirty days each."',
  '    lexeme "ru"',
  '      word "месяц"',
  '        description "Russian noun (romanized mesyats) for the month, a unit of time of about thirty days; matched as a raw substring."',
  '      word "месяца"',
  '        description "Russian noun (romanized mesyatsa), an inflected genitive form of month; a case form of the unit of time, matched as a raw substring."',
  '      word "месяцев"',
  '        description "Russian noun (romanized mesyatsev), the genitive plural of month; a case form of the unit of time, matched as a raw substring."',
  '    lexeme "hi"',
  '      word "महीना"',
  '        description "Hindi noun (romanized mahina) for the month, a unit of time of about thirty days; matched as a raw substring."',
  '      word "महीने"',
  '        description "Hindi noun (romanized mahine), an inflected form of month; a case form of the unit of time, matched as a raw substring."',
  '    lexeme "zh"',
  '      word "月"',
  '        description "Chinese noun (pinyin yue) for the month, a unit of time and one of the twelve divisions of a year; matched as a raw substring."',
  '      word "个月"',
  '        description "Chinese measure-word phrase (pinyin ge yue) counting months as a duration; matched as a raw substring."',
  '  meaning "celsius"',
  '    gloss "a unit of temperature on the Celsius scale"',
  '    wiktionary "Celsius"',
  '    defined_by "temperature"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "celsius"',
  '        description "English noun for a unit of temperature on the Celsius scale; a temperature unit in the temperature dimension."',
  '    lexeme "ru"',
  '      word "цельсий"',
  '        description "Russian noun (romanized tselsiy) for Celsius, a unit of temperature on the Celsius scale."',
  '    lexeme "hi"',
  '      word "सेल्सियस"',
  '        description "Hindi noun (romanized selsiyas) for Celsius, a unit of temperature on the Celsius scale."',
  '    lexeme "zh"',
  '      word "摄氏度"',
  '        description "Chinese noun (pinyin sheshidu) for degrees Celsius, a unit of temperature on the Celsius scale."',
  '  meaning "fahrenheit"',
  '    gloss "a unit of temperature on the Fahrenheit scale"',
  '    wiktionary "Fahrenheit"',
  '    defined_by "temperature"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "fahrenheit"',
  '        description "English noun for a unit of temperature on the Fahrenheit scale; a temperature unit in the temperature dimension."',
  '    lexeme "ru"',
  '      word "фаренгейт"',
  '        description "Russian noun (romanized farengeyt) for Fahrenheit, a unit of temperature on the Fahrenheit scale."',
  '    lexeme "hi"',
  '      word "फ़ारेनहाइट"',
  '        description "Hindi noun (romanized farenhait) for Fahrenheit, a unit of temperature on the Fahrenheit scale."',
  '    lexeme "zh"',
  '      word "华氏度"',
  '        description "Chinese noun (pinyin huashidu) for degrees Fahrenheit, a unit of temperature on the Fahrenheit scale."',
  '  meaning "kelvin"',
  '    gloss "the base unit of temperature on the Kelvin scale"',
  '    wiktionary "kelvin"',
  '    defined_by "temperature"',
  '    defined_by "unit"',
  '    role "measurement_unit"',
  '    lexeme "en"',
  '      word "kelvin"',
  '        description "English noun for the base unit of temperature on the Kelvin scale; the base unit in the temperature dimension."',
  '    lexeme "ru"',
  '      word "кельвин"',
  '        description "Russian noun (romanized kelvin) for the kelvin, the base unit of temperature on the Kelvin scale."',
  '    lexeme "hi"',
  '      word "केल्विन"',
  '        description "Hindi noun (romanized kelvin) for the kelvin, the base unit of temperature on the Kelvin scale."',
  '    lexeme "zh"',
  '      word "开尔文"',
  '        description "Chinese noun (pinyin kaierwen) for the kelvin, the base unit of temperature on the Kelvin scale."',
  "meanings",
  '  meaning "monday"',
  '    gloss "the first day of the working week in the ISO weekday cycle"',
  '    wiktionary "Monday"',
  '    defined_by "calendar_day"',
  '    role "calendar_weekday"',
  '    lexeme "en"',
  '      word "monday"',
  '        description "English noun for the first day of the ISO weekday cycle."',
  '      word "mon"',
  '        description "English abbreviation for Monday, the first day of the ISO weekday cycle."',
  '    lexeme "ru"',
  '      word "понедельник"',
  '        description "Russian noun (romanized ponedelnik) for Monday, the first ISO weekday, in the nominative case."',
  '      word "понедельника"',
  '        description "Russian noun (romanized ponedelnika) for Monday, the genitive case form of the first ISO weekday."',
  '      word "понедельником"',
  '        description "Russian noun (romanized ponedelnikom) for Monday, the instrumental case form of the first ISO weekday."',
  '      word "понедельнику"',
  '        description "Russian noun (romanized ponedelniku) for Monday, the dative case form of the first ISO weekday."',
  '      word "понедельнике"',
  '        description "Russian noun (romanized ponedelnike) for Monday, the prepositional case form of the first ISO weekday."',
  '    lexeme "hi"',
  '      word "सोमवार"',
  '        description "Hindi noun (romanized somvar) for Monday, the first day of the ISO weekday cycle."',
  '    lexeme "zh"',
  '      word "星期一"',
  '        description "Chinese noun (pinyin xingqiyi) for Monday, the first day of the ISO weekday cycle."',
  '      word "周一"',
  '        description "Chinese noun (pinyin zhouyi) for Monday, a colloquial surface for the first ISO weekday."',
  '  meaning "tuesday"',
  '    gloss "the second day of the ISO weekday cycle, after Monday"',
  '    wiktionary "Tuesday"',
  '    defined_by "calendar_day"',
  '    role "calendar_weekday"',
  '    lexeme "en"',
  '      word "tuesday"',
  '        description "English noun for the second day of the ISO weekday cycle, after Monday."',
  '      word "tue"',
  '        description "English abbreviation for Tuesday, the second day of the ISO weekday cycle."',
  '      word "tues"',
  '        description "English abbreviation for Tuesday, an alternative short form of the second ISO weekday."',
  '    lexeme "ru"',
  '      word "вторник"',
  '        description "Russian noun (romanized vtornik) for Tuesday, the second ISO weekday, in the nominative case."',
  '      word "вторника"',
  '        description "Russian noun (romanized vtornika) for Tuesday, the genitive case form of the second ISO weekday."',
  '      word "вторником"',
  '        description "Russian noun (romanized vtornikom) for Tuesday, the instrumental case form of the second ISO weekday."',
  '      word "вторнику"',
  '        description "Russian noun (romanized vtorniku) for Tuesday, the dative case form of the second ISO weekday."',
  '      word "вторнике"',
  '        description "Russian noun (romanized vtornike) for Tuesday, the prepositional case form of the second ISO weekday."',
  '    lexeme "hi"',
  '      word "मंगलवार"',
  '        description "Hindi noun (romanized mangalvar) for Tuesday, the second day of the ISO weekday cycle."',
  '    lexeme "zh"',
  '      word "星期二"',
  '        description "Chinese noun (pinyin xingqier) for Tuesday, the second day of the ISO weekday cycle."',
  '      word "周二"',
  '        description "Chinese noun (pinyin zhouer) for Tuesday, a colloquial surface for the second ISO weekday."',
  '  meaning "wednesday"',
  '    gloss "the third day of the ISO weekday cycle, after Tuesday"',
  '    wiktionary "Wednesday"',
  '    defined_by "calendar_day"',
  '    role "calendar_weekday"',
  '    lexeme "en"',
  '      word "wednesday"',
  '        description "English noun for the third day of the ISO weekday cycle, after Tuesday."',
  '      word "wed"',
  '        description "English abbreviation for Wednesday, the third day of the ISO weekday cycle."',
  '    lexeme "ru"',
  '      word "среда"',
  '        description "Russian noun (romanized sreda) for Wednesday, the third ISO weekday, in the nominative case."',
  '      word "среды"',
  '        description "Russian noun (romanized sredy) for Wednesday, the genitive case form of the third ISO weekday."',
  '      word "среде"',
  '        description "Russian noun (romanized srede) for Wednesday, the dative or prepositional case form of the third ISO weekday."',
  '      word "среду"',
  '        description "Russian noun (romanized sredu) for Wednesday, the accusative case form of the third ISO weekday."',
  '      word "средой"',
  '        description "Russian noun (romanized sredoy) for Wednesday, the instrumental case form of the third ISO weekday."',
  '    lexeme "hi"',
  '      word "बुधवार"',
  '        description "Hindi noun (romanized budhvar) for Wednesday, the third day of the ISO weekday cycle."',
  '    lexeme "zh"',
  '      word "星期三"',
  '        description "Chinese noun (pinyin xingqisan) for Wednesday, the third day of the ISO weekday cycle."',
  '      word "周三"',
  '        description "Chinese noun (pinyin zhousan) for Wednesday, a colloquial surface for the third ISO weekday."',
  '  meaning "thursday"',
  '    gloss "the fourth day of the ISO weekday cycle, after Wednesday"',
  '    wiktionary "Thursday"',
  '    defined_by "calendar_day"',
  '    role "calendar_weekday"',
  '    lexeme "en"',
  '      word "thursday"',
  '        description "English noun for the fourth day of the ISO weekday cycle, after Wednesday."',
  '      word "thu"',
  '        description "English abbreviation for Thursday, the fourth day of the ISO weekday cycle."',
  '      word "thur"',
  '        description "English abbreviation for Thursday, an alternative short form of the fourth ISO weekday."',
  '      word "thurs"',
  '        description "English abbreviation for Thursday, another short form of the fourth ISO weekday."',
  '    lexeme "ru"',
  '      word "четверг"',
  '        description "Russian noun (romanized chetverg) for Thursday, the fourth ISO weekday, in the nominative case."',
  '      word "четверга"',
  '        description "Russian noun (romanized chetverga) for Thursday, the genitive case form of the fourth ISO weekday."',
  '      word "четвергом"',
  '        description "Russian noun (romanized chetvergom) for Thursday, the instrumental case form of the fourth ISO weekday."',
  '      word "четвергу"',
  '        description "Russian noun (romanized chetvergu) for Thursday, the dative case form of the fourth ISO weekday."',
  '      word "четверге"',
  '        description "Russian noun (romanized chetverge) for Thursday, the prepositional case form of the fourth ISO weekday."',
  '    lexeme "hi"',
  '      word "गुरुवार"',
  '        description "Hindi noun (romanized guruvar) for Thursday, the fourth day of the ISO weekday cycle."',
  '    lexeme "zh"',
  '      word "星期四"',
  '        description "Chinese noun (pinyin xingqisi) for Thursday, the fourth day of the ISO weekday cycle."',
  '      word "周四"',
  '        description "Chinese noun (pinyin zhousi) for Thursday, a colloquial surface for the fourth ISO weekday."',
  '  meaning "friday"',
  '    gloss "the fifth day of the ISO weekday cycle, after Thursday"',
  '    wiktionary "Friday"',
  '    defined_by "calendar_day"',
  '    role "calendar_weekday"',
  '    lexeme "en"',
  '      word "friday"',
  '        description "English noun for the fifth day of the ISO weekday cycle, after Thursday."',
  '      word "fri"',
  '        description "English abbreviation for Friday, the fifth day of the ISO weekday cycle."',
  '    lexeme "ru"',
  '      word "пятница"',
  '        description "Russian noun (romanized pyatnitsa) for Friday, the fifth ISO weekday, in the nominative case."',
  '      word "пятницы"',
  '        description "Russian noun (romanized pyatnitsy) for Friday, the genitive case form of the fifth ISO weekday."',
  '      word "пятнице"',
  '        description "Russian noun (romanized pyatnitse) for Friday, the dative or prepositional case form of the fifth ISO weekday."',
  '      word "пятницу"',
  '        description "Russian noun (romanized pyatnitsu) for Friday, the accusative case form of the fifth ISO weekday."',
  '      word "пятницей"',
  '        description "Russian noun (romanized pyatnitsey) for Friday, the instrumental case form of the fifth ISO weekday."',
  '    lexeme "hi"',
  '      word "शुक्रवार"',
  '        description "Hindi noun (romanized shukravar) for Friday, the fifth day of the ISO weekday cycle."',
  '    lexeme "zh"',
  '      word "星期五"',
  '        description "Chinese noun (pinyin xingqiwu) for Friday, the fifth day of the ISO weekday cycle."',
  '      word "周五"',
  '        description "Chinese noun (pinyin zhouwu) for Friday, a colloquial surface for the fifth ISO weekday."',
  '  meaning "saturday"',
  '    gloss "the sixth day of the ISO weekday cycle, after Friday"',
  '    wiktionary "Saturday"',
  '    defined_by "calendar_day"',
  '    role "calendar_weekday"',
  '    lexeme "en"',
  '      word "saturday"',
  '        description "English noun for the sixth day of the ISO weekday cycle, after Friday."',
  '      word "sat"',
  '        description "English abbreviation for Saturday, the sixth day of the ISO weekday cycle."',
  '    lexeme "ru"',
  '      word "суббота"',
  '        description "Russian noun (romanized subbota) for Saturday, the sixth ISO weekday, in the nominative case."',
  '      word "субботы"',
  '        description "Russian noun (romanized subboty) for Saturday, the genitive case form of the sixth ISO weekday."',
  '      word "субботе"',
  '        description "Russian noun (romanized subbote) for Saturday, the dative or prepositional case form of the sixth ISO weekday."',
  '      word "субботу"',
  '        description "Russian noun (romanized subbotu) for Saturday, the accusative case form of the sixth ISO weekday."',
  '      word "субботой"',
  '        description "Russian noun (romanized subbotoy) for Saturday, the instrumental case form of the sixth ISO weekday."',
  '    lexeme "hi"',
  '      word "शनिवार"',
  '        description "Hindi noun (romanized shanivar) for Saturday, the sixth day of the ISO weekday cycle."',
  '    lexeme "zh"',
  '      word "星期六"',
  '        description "Chinese noun (pinyin xingqiliu) for Saturday, the sixth day of the ISO weekday cycle."',
  '      word "周六"',
  '        description "Chinese noun (pinyin zhouliu) for Saturday, a colloquial surface for the sixth ISO weekday."',
  '  meaning "sunday"',
  '    gloss "the seventh day of the ISO weekday cycle, after Saturday"',
  '    wiktionary "Sunday"',
  '    defined_by "calendar_day"',
  '    role "calendar_weekday"',
  '    lexeme "en"',
  '      word "sunday"',
  '        description "English noun for the seventh day of the ISO weekday cycle, after Saturday."',
  '      word "sun"',
  '        description "English abbreviation for Sunday, the seventh day of the ISO weekday cycle."',
  '    lexeme "ru"',
  '      word "воскресенье"',
  '        description "Russian noun (romanized voskresenye) for Sunday, the seventh ISO weekday, in the nominative case."',
  '      word "воскресенья"',
  '        description "Russian noun (romanized voskresenya) for Sunday, the genitive case form of the seventh ISO weekday."',
  '      word "воскресенью"',
  '        description "Russian noun (romanized voskresenyu) for Sunday, the dative case form of the seventh ISO weekday."',
  '      word "воскресеньем"',
  '        description "Russian noun (romanized voskresenyem) for Sunday, the instrumental case form of the seventh ISO weekday."',
  '    lexeme "hi"',
  '      word "रविवार"',
  '        description "Hindi noun (romanized ravivar) for Sunday, the seventh day of the ISO weekday cycle."',
  '    lexeme "zh"',
  '      word "星期日"',
  '        description "Chinese noun (pinyin xingqiri) for Sunday, the seventh day of the ISO weekday cycle."',
  '      word "星期天"',
  '        description "Chinese noun (pinyin xingqitian) for Sunday, a colloquial surface for the seventh ISO weekday."',
  '      word "周日"',
  '        description "Chinese noun (pinyin zhouri) for Sunday, a colloquial surface for the seventh ISO weekday."',
  '  meaning "calendar_day"',
  '    gloss "a single named day; the unit a weekday-relation question asks about"',
  '    wiktionary "day"',
  '    defined_by "calendar_week"',
  '    defined_by "calendar_date"',
  '    defined_by "concept"',
  '    role "calendar_day_reference"',
  '    lexeme "en"',
  '      word "day"',
  '        description "English noun for a single named day, the unit a weekday-relation question asks about."',
  '      word "weekday"',
  '        description "English noun for a day of the week; a more specific surface for a single named day."',
  '      word "week day"',
  '        description "English two-word spelling of weekday, naming a single day of the week."',
  '    lexeme "ru"',
  '      word "день"',
  '        description "Russian noun (romanized den) for a day, in the nominative or accusative case."',
  '      word "дня"',
  '        description "Russian noun (romanized dnya) for a day, the genitive case form."',
  '      word "дни"',
  '        description "Russian noun (romanized dni) for days, the nominative plural form."',
  '      word "дней"',
  '        description "Russian noun (romanized dney) for days, the genitive plural form."',
  '    lexeme "hi"',
  '      word "दिन"',
  '        description "Hindi noun (romanized din) for a day, the unit a weekday-relation question asks about."',
  '    lexeme "zh"',
  '      word "星期几"',
  '        description "Chinese phrase (pinyin xingqiji) meaning which day of the week, the interrogative surface for a named day."',
  '      word "日子"',
  '        description "Chinese noun (pinyin rizi) for a day or date, a colloquial surface for a single named day."',
  '  meaning "calendar_date"',
  '    gloss "a calendar date — the year-month-day coordinate of a day"',
  '    wiktionary "date"',
  '    defined_by "calendar_day"',
  '    role "calendar_day_reference"',
  '    lexeme "en"',
  '      word "date"',
  '        description "English noun for a calendar date, the year-month-day coordinate of a day."',
  '    lexeme "ru"',
  '      word "дата"',
  '        description "Russian noun (romanized data) for a date, in the nominative case."',
  '      word "дату"',
  '        description "Russian noun (romanized datu) for a date, the accusative case form."',
  '      word "число"',
  '        description "Russian noun (romanized chislo) for a day-of-month number; a surface for a calendar date."',
  '    lexeme "hi"',
  '      word "तारीख"',
  '        description "Hindi noun (romanized tarikh) for a date, the year-month-day coordinate of a day."',
  '      word "दिनांक"',
  '        description "Hindi noun (romanized dinank) for a date; a more formal surface for a calendar date."',
  '    lexeme "zh"',
  '      word "日期"',
  '        description "Chinese noun (pinyin riqi) for a date, the year-month-day coordinate of a day."',
  '      word "几号"',
  '        description "Chinese phrase (pinyin jihao) meaning which day of the month, an interrogative surface for a date."',
  '  meaning "calendar_week"',
  '    gloss "the seven-day cycle the weekdays belong to"',
  '    wiktionary "week"',
  '    defined_by "calendar_day"',
  '    role "calendar_day_reference"',
  '    lexeme "en"',
  '      word "week"',
  '        description "English noun for the seven-day cycle the weekdays belong to."',
  '    lexeme "ru"',
  '      word "неделя"',
  '        description "Russian noun (romanized nedelya) for a week, in the nominative case."',
  '      word "недели"',
  '        description "Russian noun (romanized nedeli) for a week, the genitive singular or nominative plural form."',
  '      word "неделе"',
  '        description "Russian noun (romanized nedele) for a week, the dative or prepositional case form."',
  '      word "неделю"',
  '        description "Russian noun (romanized nedelyu) for a week, the accusative case form."',
  '      word "неделей"',
  '        description "Russian noun (romanized nedeley) for a week, the instrumental case form."',
  '      word "недель"',
  '        description "Russian noun (romanized nedel) for weeks, the genitive plural form."',
  '    lexeme "hi"',
  '      word "सप्ताह"',
  '        description "Hindi noun (romanized saptah) for a week, the seven-day cycle the weekdays belong to."',
  '    lexeme "zh"',
  '      word "星期"',
  '        description "Chinese noun (pinyin xingqi) for a week, the seven-day cycle the weekdays belong to."',
  '      word "周"',
  '        description "Chinese noun (pinyin zhou) for a week, a shorter surface for the seven-day cycle."',
  '  meaning "calendar_following"',
  "    gloss \"the relation 'the day that comes after' — a +1 step in the weekday cycle\"",
  '    wiktionary "after"',
  '    defined_by "calendar_day"',
  '    role "calendar_direction_next"',
  '    lexeme "en"',
  '      word "after"',
  '        description "English preposition for the relation the day that comes after, a +1 step in the weekday cycle."',
  '      word "comes after"',
  '        description "English verb phrase for following in sequence, naming the +1 step in the weekday cycle."',
  '      word "day after"',
  '        description "English noun phrase for the day that follows, a +1 step in the weekday cycle."',
  '      word "next day"',
  '        description "English noun phrase for the following day, a +1 step in the weekday cycle."',
  '      word "following day"',
  '        description "English noun phrase for the day that comes after, a +1 step in the weekday cycle."',
  '      word "following weekday"',
  '        description "English noun phrase for the weekday that comes after, a +1 step in the weekday cycle."',
  '      word "follows"',
  '        description "English verb for coming after in sequence, naming the +1 step in the weekday cycle."',
  '    lexeme "ru"',
  '      word "после"',
  '        description "Russian preposition (romanized posle) meaning after, naming the +1 step in the weekday cycle."',
  '      word "наступает после"',
  '        description "Russian verb phrase (romanized nastupayet posle) meaning comes after, naming the +1 step in the weekday cycle."',
  '      word "следующий день"',
  '        description "Russian noun phrase (romanized sleduyushchiy den) meaning the next day, a +1 step in the weekday cycle."',
  '      word "следующая"',
  '        description "Russian adjective (romanized sleduyushchaya) meaning following, the feminine form naming the +1 step."',
  '      word "следом за"',
  '        description "Russian phrase (romanized sledom za) meaning right after, naming the +1 step in the weekday cycle."',
  '    lexeme "hi"',
  '      word "के बाद"',
  '        description "Hindi postposition (romanized ke baad) meaning after, naming the +1 step in the weekday cycle."',
  '      word "बाद"',
  '        description "Hindi adverb (romanized baad) meaning after or later, naming the +1 step in the weekday cycle."',
  '      word "अगला"',
  '        description "Hindi adjective (romanized agla) meaning next, the masculine form naming the +1 step."',
  '      word "अगले"',
  '        description "Hindi adjective (romanized agle) meaning next, an oblique or plural form naming the +1 step."',
  '    lexeme "zh"',
  '      word "之后"',
  '        description "Chinese phrase (pinyin zhihou) meaning after, naming the +1 step in the weekday cycle."',
  '      word "后"',
  '        description "Chinese word (pinyin hou) meaning after or behind, a shorter surface for the +1 step."',
  '      word "下一个"',
  '        description "Chinese phrase (pinyin xiayige) meaning the next one, naming the +1 step in the weekday cycle."',
  '      word "下一天"',
  '        description "Chinese phrase (pinyin xiayitian) meaning the next day, a +1 step in the weekday cycle."',
  '  meaning "calendar_preceding"',
  "    gloss \"the relation 'the day that comes before' — a -1 step in the weekday cycle\"",
  '    wiktionary "before"',
  '    defined_by "calendar_day"',
  '    role "calendar_direction_previous"',
  '    lexeme "en"',
  '      word "before"',
  '        description "English preposition for the relation the day that comes before, a -1 step in the weekday cycle."',
  '      word "comes before"',
  '        description "English verb phrase for preceding in sequence, naming the -1 step in the weekday cycle."',
  '      word "day before"',
  '        description "English noun phrase for the day that precedes, a -1 step in the weekday cycle."',
  '      word "previous day"',
  '        description "English noun phrase for the preceding day, a -1 step in the weekday cycle."',
  '      word "previous weekday"',
  '        description "English noun phrase for the preceding weekday, a -1 step in the weekday cycle."',
  '      word "precedes"',
  '        description "English verb for coming before in sequence, naming the -1 step in the weekday cycle."',
  '    lexeme "ru"',
  '      word "перед"',
  '        description "Russian preposition (romanized pered) meaning before, naming the -1 step in the weekday cycle."',
  '      word "предыдущий день"',
  '        description "Russian noun phrase (romanized predydushchiy den) meaning the previous day, a -1 step in the weekday cycle."',
  '      word "предыдущая"',
  '        description "Russian adjective (romanized predydushchaya) meaning previous, the feminine form naming the -1 step."',
  '      word "предшествует"',
  '        description "Russian verb (romanized predshestvuyet) meaning precedes, naming the -1 step in the weekday cycle."',
  '    lexeme "hi"',
  '      word "से पहले"',
  '        description "Hindi postposition (romanized se pehle) meaning before, naming the -1 step in the weekday cycle."',
  '      word "के पहले"',
  '        description "Hindi postposition (romanized ke pehle) meaning before, an alternative surface for the -1 step."',
  '      word "पहले"',
  '        description "Hindi adverb (romanized pehle) meaning before or earlier, naming the -1 step in the weekday cycle."',
  '      word "पिछला"',
  '        description "Hindi adjective (romanized pichhla) meaning previous, the masculine form naming the -1 step."',
  '    lexeme "zh"',
  '      word "之前"',
  '        description "Chinese phrase (pinyin zhiqian) meaning before, naming the -1 step in the weekday cycle."',
  '      word "前"',
  '        description "Chinese word (pinyin qian) meaning before or front, a shorter surface for the -1 step."',
  '      word "上一个"',
  '        description "Chinese phrase (pinyin shangyige) meaning the previous one, naming the -1 step in the weekday cycle."',
  '      word "上一天"',
  '        description "Chinese phrase (pinyin shangyitian) meaning the previous day, a -1 step in the weekday cycle."',
  '  meaning "calendar_today"',
  '    gloss "the present day relative to the system clock"',
  '    wiktionary "today"',
  '    defined_by "calendar_day"',
  '    role "calendar_today"',
  '    lexeme "en"',
  '      word "today"',
  '        description "English noun and adverb for the present day relative to the system clock."',
  '    lexeme "ru"',
  '      word "сегодня"',
  '        description "Russian adverb (romanized segodnya) for today, the present day relative to the system clock."',
  '    lexeme "hi"',
  '      word "आज"',
  '        description "Hindi adverb (romanized aaj) for today, the present day relative to the system clock."',
  '    lexeme "zh"',
  '      word "今天"',
  '        description "Chinese noun (pinyin jintian) for today, the present day relative to the system clock."',
  '  meaning "calendar_interrogative"',
  '    gloss "an interrogative or imperative asking which day — the question side of a calendar query"',
  '    wiktionary "what"',
  '    defined_by "calendar_day"',
  '    role "calendar_question"',
  '    lexeme "en"',
  '      word "what"',
  '        description "English interrogative pronoun asking which day, the question side of a calendar query."',
  '      word "which"',
  '        description "English interrogative determiner selecting which day, the question side of a calendar query."',
  '      word "tell me"',
  '        description "English imperative phrase requesting which day, the question side of a calendar query."',
  '      word "show"',
  '        description "English imperative verb requesting which day be displayed, the question side of a calendar query."',
  '      word "?"',
  '        description "Question mark punctuation marking an interrogative, the question side of a calendar query."',
  '    lexeme "ru"',
  '      word "какой"',
  '        description "Russian interrogative (romanized kakoy) meaning which, the masculine form asking which day."',
  '      word "какая"',
  '        description "Russian interrogative (romanized kakaya) meaning which, the feminine form asking which day."',
  '      word "какое"',
  '        description "Russian interrogative (romanized kakoye) meaning which, the neuter form asking which day."',
  '      word "скажи"',
  '        description "Russian imperative (romanized skazhi) meaning tell me, requesting which day."',
  '      word "покажи"',
  '        description "Russian imperative (romanized pokazhi) meaning show, requesting which day be displayed."',
  '    lexeme "hi"',
  '      word "कौन"',
  '        description "Hindi interrogative pronoun (romanized kaun) meaning who or which, asking which day."',
  '      word "क्या"',
  '        description "Hindi interrogative (romanized kya) meaning what, the question side of a calendar query."',
  '      word "बताओ"',
  '        description "Hindi imperative (romanized batao) meaning tell me, requesting which day."',
  '      word "दिखाओ"',
  '        description "Hindi imperative (romanized dikhao) meaning show, requesting which day be displayed."',
  '    lexeme "zh"',
  '      word "什么"',
  '        description "Chinese interrogative (pinyin shenme) meaning what, the question side of a calendar query."',
  '      word "几"',
  '        description "Chinese interrogative (pinyin ji) meaning how many or which number, asking which day."',
  '      word "告诉"',
  '        description "Chinese verb (pinyin gaosu) meaning tell, requesting which day."',
  '      word "显示"',
  '        description "Chinese verb (pinyin xianshi) meaning show or display, requesting which day be displayed."',
  "meanings",
  '  meaning "money"',
  '    gloss "money or currency in general — a medium of exchange. This genus groups the currency-related meanings (the us_dollar currency and the exchange_rate between currencies) so they are built from a shared concept rather than listed independently. The monetary_concept role is structural: no handler queries it directly; it exists so the ontology records that these meanings are kinds of money."',
  '    wiktionary "money"',
  '    defined_by "concept"',
  '    role "monetary_concept"',
  '    lexeme "en"',
  '      word "money"',
  '        description "English noun for the medium of exchange; the monetary_concept genus lexicalized in English."',
  '      word "currency"',
  '        description "English noun for a system of money in circulation; the monetary_concept genus lexicalized in English."',
  '    lexeme "ru"',
  '      word "деньги"',
  '        description "Russian noun (romanized dengi, money); the monetary_concept genus lexicalized in Russian."',
  '      word "валюта"',
  '        description "Russian noun (romanized valyuta, currency); the monetary_concept genus lexicalized in Russian."',
  '    lexeme "hi"',
  '      word "पैसा"',
  '        description "Hindi noun (romanized paisa, money); the monetary_concept genus lexicalized in Hindi."',
  '      word "मुद्रा"',
  '        description "Hindi noun (romanized mudra, currency); the monetary_concept genus lexicalized in Hindi."',
  '    lexeme "zh"',
  '      word "货币"',
  '        description "Chinese noun (pinyin huobi, currency); the monetary_concept genus lexicalized in Chinese."',
  '      word "钱"',
  '        description "Chinese noun (pinyin qian, money); the monetary_concept genus lexicalized in Chinese."',
  '  meaning "exchange_rate"',
  '    gloss "the exchange rate between two currencies — the price of one currency expressed in another, also called a currency rate. The exchange_rate_reference role marks the surface forms that signal a prompt is talking about a currency conversion rate; the calculator rate-basis handler requires this together with a us_dollar reference and a calculation_basis phrase before it answers with the rate the calculator uses for USD to RUB. Matched as raw substrings so inflected and compound forms are caught in every supported language."',
  '    wiktionary "exchange rate"',
  '    defined_by "money"',
  '    defined_by "relation"',
  '    role "exchange_rate_reference"',
  '    lexeme "en"',
  '      word "exchange rate"',
  '        description "English compound noun for the price of one currency in another; an exchange_rate_reference matched as a raw substring."',
  '      word "currency rate"',
  '        description "English synonym for an exchange rate; an exchange_rate_reference matched as a raw substring."',
  '    lexeme "ru"',
  '      word "курс"',
  '        description "Russian noun (romanized kurs, rate or exchange rate); an exchange_rate_reference matched as a raw substring so курс, курса and курсе are all caught."',
  '    lexeme "hi"',
  '      word "विनिमय दर"',
  '        description "Hindi compound (romanized vinimay dar, exchange rate); an exchange_rate_reference matched as a raw substring."',
  '    lexeme "zh"',
  '      word "汇率"',
  '        description "Chinese noun (pinyin huilu, exchange rate); an exchange_rate_reference matched as a raw substring."',
  '  meaning "us_dollar"',
  '    gloss "the United States dollar, the currency abbreviated USD. The currency_usd_reference role marks the surface forms — including two common Russian misspellings — that signal a prompt mentions US dollars; the calculator rate-basis handler requires this together with an exchange_rate reference and a calculation_basis phrase before it answers with the rate the calculator uses for USD to RUB. Matched as raw substrings so inflected forms are caught in every supported language. Also a calculation_domain_term, so a dollar reference beside a number signals a calculation to the calculator router (ASCII codes whole-token, other scripts as raw substrings)."',
  '    wiktionary "dollar"',
  '    defined_by "money"',
  '    role "currency_usd_reference"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "usd"',
  '        description "English ISO 4217 code for the United States dollar; a currency_usd_reference matched as a raw substring."',
  '      word "dollar"',
  '        description "English noun for the United States dollar; a currency_usd_reference matched as a raw substring so dollars is also caught."',
  '      word "dollars"',
  "        description \"English plural of dollar; a currency_usd_reference matched as a raw substring, kept explicitly so the surface list mirrors the original recognizer's USD markers.\"",
  '    lexeme "ru"',
  '      word "доллар"',
  '        description "Russian noun (romanized dollar); a currency_usd_reference matched as a raw substring so доллара and долларах are caught."',
  '      word "долар"',
  '        description "Russian misspelling with one l (romanized dolar) of доллар; a currency_usd_reference matched as a raw substring so the typo is still recognised."',
  '      word "долор"',
  '        description "Russian misspelling (romanized dolor) of доллар; a currency_usd_reference matched as a raw substring so the typo is still recognised."',
  '    lexeme "hi"',
  '      word "डॉलर"',
  '        description "Hindi noun (romanized dolar, dollar); a currency_usd_reference matched as a raw substring."',
  '    lexeme "zh"',
  '      word "美元"',
  '        description "Chinese noun (pinyin meiyuan, US dollar); a currency_usd_reference matched as a raw substring."',
  '  meaning "euro"',
  '    gloss "the euro, the currency abbreviated EUR. The currency_eur_reference role marks the surface forms that name the euro; the compound-interest handler reads it as a whole token to decide whether to convert a final amount into euros, and the calculation rate handlers read it to recognise a euro currency code. Defined as a kind of money. Also a calculation_domain_term, so a euro reference beside a number signals a calculation to the calculator router (ASCII codes whole-token, other scripts as raw substrings)."',
  '    wiktionary "euro"',
  '    defined_by "money"',
  '    role "currency_eur_reference"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "eur"',
  '        description "English ISO 4217 code for the euro; a currency_eur_reference matched as a token-bounded word."',
  '      word "euro"',
  '        description "English noun for the euro; a currency_eur_reference matched as a token-bounded word."',
  '      word "euros"',
  '        description "English plural of euro; a currency_eur_reference matched as a token-bounded word, kept explicitly because token-bounded matching does not derive the plural from the singular."',
  '    lexeme "ru"',
  '      word "евро"',
  '        description "Russian noun (romanized evro, euro), indeclinable; a currency_eur_reference matched as a token-bounded word."',
  '    lexeme "hi"',
  '      word "यूरो"',
  '        description "Hindi noun (romanized yuro, euro); a currency_eur_reference matched as a token-bounded word."',
  '    lexeme "zh"',
  '      word "欧元"',
  '        description "Chinese noun (pinyin ouyuan, euro); a currency_eur_reference matched as a token-bounded word."',
  '  meaning "ruble"',
  '    gloss "the Russian ruble, the currency abbreviated RUB. The currency_rub_reference role marks the surface forms that name the ruble; the calculation rate handlers and the compound-interest worker read it as a whole token to recognise a ruble currency code. Defined as a kind of money. Also a calculation_domain_term, so a ruble reference beside a number signals a calculation to the calculator router (ASCII codes whole-token, other scripts as raw substrings)."',
  '    wiktionary "ruble"',
  '    defined_by "money"',
  '    role "currency_rub_reference"',
  '    role "calculation_domain_term"',
  '    lexeme "en"',
  '      word "rub"',
  '        description "English ISO 4217 code for the Russian ruble; a currency_rub_reference matched as a token-bounded word."',
  '      word "ruble"',
  '        description "English noun for the Russian ruble; a currency_rub_reference matched as a token-bounded word."',
  '      word "rubles"',
  '        description "English plural of ruble; a currency_rub_reference matched as a token-bounded word, kept explicitly because token-bounded matching does not derive the plural from the singular."',
  '    lexeme "ru"',
  '      word "рубль"',
  '        description "Russian noun (romanized rubl, ruble); a currency_rub_reference matched as a token-bounded word."',
  '      word "рублей"',
  '        description "Russian genitive-plural noun (romanized rubley, rubles), the form used after most numbers; a currency_rub_reference matched as a token-bounded word."',
  '      word "руб"',
  '        description "Russian abbreviation (romanized rub) of рубль; a currency_rub_reference matched as a token-bounded word."',
  '    lexeme "hi"',
  '      word "रूबल"',
  '        description "Hindi noun (romanized rubal, ruble); a currency_rub_reference matched as a token-bounded word."',
  '    lexeme "zh"',
  '      word "卢布"',
  '        description "Chinese noun (pinyin lubu, ruble); a currency_rub_reference matched as a token-bounded word."',
  '  meaning "calculation_basis"',
  '    gloss "a phrase asking which value, rate, or method the assistant uses, applies, or takes as the basis when it calculates — the question side of a prompt like which rate do you use for calculations. The calculation_basis_reference role marks these surface forms; the calculator rate-basis handler requires this together with an exchange_rate reference and a us_dollar reference before it answers with the rate the calculator uses for USD to RUB. The forms are inflectable stems and fixed phrases matched as raw substrings, so they are caught regardless of surrounding inflection in every supported language."',
  '    wiktionary "calculation"',
  '    defined_by "action"',
  '    defined_by "inquiry"',
  '    role "calculation_basis_reference"',
  '    lexeme "en"',
  '      word "calculation"',
  '        description "English noun for the act of computing; a calculation_basis_reference matched as a raw substring so calculations is also caught."',
  '      word "calculations"',
  '        description "English plural of calculation; a calculation_basis_reference matched as a raw substring, kept explicitly so the surface list mirrors the original recognizer."',
  '      word "do you use"',
  '        description "English interrogative fragment asking which value the assistant uses; a calculation_basis_reference matched as a raw substring."',
  '      word "used for"',
  '        description "English fragment asking what a rate is used for; a calculation_basis_reference matched as a raw substring."',
  '      word "your rate"',
  "        description \"English fragment asking about the assistant's own rate; a calculation_basis_reference matched as a raw substring.\"",
  '    lexeme "ru"',
  '      word "при расчет"',
  '        description "Russian fragment (romanized pri raschet, during calculation) without the ё; a calculation_basis_reference matched as a raw substring so при расчете and при расчетах are caught."',
  '      word "при расчёт"',
  '        description "Russian fragment (romanized pri raschyot, during calculation) with the ё; a calculation_basis_reference matched as a raw substring so при расчёте and при расчётах are caught."',
  '      word "в расчет"',
  '        description "Russian fragment (romanized v raschet, into the calculation) without the ё; a calculation_basis_reference matched as a raw substring."',
  '      word "в расчёт"',
  '        description "Russian fragment (romanized v raschyot, into the calculation) with the ё; a calculation_basis_reference matched as a raw substring."',
  '      word "для расчет"',
  '        description "Russian fragment (romanized dlya raschet, for the calculation) without the ё; a calculation_basis_reference matched as a raw substring."',
  '      word "для расчёт"',
  '        description "Russian fragment (romanized dlya raschyot, for the calculation) with the ё; a calculation_basis_reference matched as a raw substring."',
  '      word "у тебя"',
  '        description "Russian fragment (romanized u tebya, that you have or that you use); a calculation_basis_reference matched as a raw substring."',
  '      word "использ"',
  '        description "Russian verb stem (romanized ispolz, of использовать, to use); a calculation_basis_reference matched as a raw substring so используешь and используете are caught."',
  '      word "берешь"',
  '        description "Russian second-person verb (romanized beresh, you take) without the ё; a calculation_basis_reference matched as a raw substring."',
  '      word "берёшь"',
  '        description "Russian second-person verb (romanized beryosh, you take) with the ё; a calculation_basis_reference matched as a raw substring."',
  '      word "примен"',
  '        description "Russian verb stem (romanized primen, of применять, to apply); a calculation_basis_reference matched as a raw substring so применяешь and применяете are caught."',
  '    lexeme "hi"',
  '      word "गणना"',
  '        description "Hindi noun (romanized ganana, calculation); a calculation_basis_reference matched as a raw substring."',
  '      word "उपयोग"',
  '        description "Hindi noun (romanized upayog, use); a calculation_basis_reference matched as a raw substring."',
  '    lexeme "zh"',
  '      word "计算"',
  '        description "Chinese verb (pinyin jisuan, to calculate); a calculation_basis_reference matched as a raw substring."',
  '      word "使用"',
  '        description "Chinese verb (pinyin shiyong, to use); a calculation_basis_reference matched as a raw substring."',
  '  meaning "arithmetic_operation"',
  '    gloss "an arithmetic operation that combines numbers into a result: addition, subtraction, multiplication, division, modulo. The genus of the individual spelled operators, each defined as a kind of arithmetic operation rather than listed in code. The numeric_concept role is structural: no handler queries the genus directly; it exists so the ontology records that these operators are kinds of arithmetic operation."',
  '    wiktionary "arithmetic operation"',
  '    defined_by "action"',
  '    role "numeric_concept"',
  '    lexeme "en"',
  '      word "arithmetic operation"',
  '        description "English term for an operation that combines numbers into a result; the genus of the individual spelled operators."',
  '      word "operator"',
  '        description "English noun for the symbol or word naming an arithmetic operation; the everyday surface for the operation concept."',
  '    lexeme "ru"',
  '      word "арифметическая операция"',
  '        description "Russian term (romanized arifmeticheskaya operatsiya) for an arithmetic operation; the Russian surface for the arithmetic-operation concept."',
  '    lexeme "hi"',
  '      word "अंकगणितीय संक्रिया"',
  '        description "Hindi term (romanized ankaganitiya sankriya) for an arithmetic operation; the Hindi surface for the arithmetic-operation concept."',
  '    lexeme "zh"',
  '      word "算术运算"',
  '        description "Chinese term (pinyin suanshu yunsuan) for an arithmetic operation; the Chinese surface for the arithmetic-operation concept."',
  '  meaning "addition"',
  '    gloss "the arithmetic operation of adding two numbers, written with the plus sign. The arithmetic_operator_word role marks the spelled operator surfaces; contains_word_operator reads them to decide whether a prompt names an arithmetic operator in words rather than symbols. Matched as a token-bounded word, with CJK surfaces matched as a substring because those scripts have no inter-word spaces."',
  '    wiktionary "addition"',
  '    defined_by "arithmetic_operation"',
  '    role "arithmetic_operator_word"',
  '    lexeme "en"',
  '      word "plus"',
  '        description "English spelled form of the addition operator; an arithmetic_operator_word matched as a token-bounded word."',
  '      word "+"',
  "        description \"ASCII plus sign for the addition operator; the script-independent operator surface the arithmetic evaluator consumes, from which the operation's machine symbol is read.\"",
  '    lexeme "ru"',
  '      word "плюс"',
  '        description "Russian spelled form (romanized plyus) of the addition operator; an arithmetic_operator_word matched as a token-bounded word."',
  '    lexeme "hi"',
  '      word "जोड़"',
  '        description "Hindi spelled form (romanized jod, add) of the addition operator; an arithmetic_operator_word matched as a token-bounded word."',
  '    lexeme "zh"',
  '      word "加上"',
  '        description "Chinese spelled form (pinyin jiashang, add) of the addition operator; an arithmetic_operator_word matched as a substring."',
  '  meaning "subtraction"',
  '    gloss "the arithmetic operation of subtracting one number from another, written with the minus sign. The arithmetic_operator_word role marks the spelled operator surfaces; contains_word_operator reads them to decide whether a prompt names an arithmetic operator in words rather than symbols. Matched as a token-bounded word, with CJK surfaces matched as a substring because those scripts have no inter-word spaces."',
  '    wiktionary "subtraction"',
  '    defined_by "arithmetic_operation"',
  '    role "arithmetic_operator_word"',
  '    lexeme "en"',
  '      word "minus"',
  '        description "English spelled form of the subtraction operator; an arithmetic_operator_word matched as a token-bounded word."',
  '      word "-"',
  "        description \"ASCII hyphen-minus for the subtraction operator; the script-independent operator surface the arithmetic evaluator consumes, from which the operation's machine symbol is read.\"",
  '    lexeme "ru"',
  '      word "минус"',
  '        description "Russian spelled form (romanized minus) of the subtraction operator; an arithmetic_operator_word matched as a token-bounded word."',
  '    lexeme "hi"',
  '      word "घटा"',
  '        description "Hindi spelled form (romanized ghata, subtract) of the subtraction operator; an arithmetic_operator_word matched as a token-bounded word."',
  '    lexeme "zh"',
  '      word "减去"',
  '        description "Chinese spelled form (pinyin jianqu, subtract) of the subtraction operator; an arithmetic_operator_word matched as a substring."',
  '  meaning "multiplication"',
  '    gloss "the arithmetic operation of multiplying two numbers, written with the times sign. The arithmetic_operator_word role marks the spelled operator surfaces; contains_word_operator reads them to decide whether a prompt names an arithmetic operator in words rather than symbols. Matched as a token-bounded word, with CJK surfaces matched as a substring because those scripts have no inter-word spaces."',
  '    wiktionary "multiplication"',
  '    defined_by "arithmetic_operation"',
  '    role "arithmetic_operator_word"',
  '    lexeme "en"',
  '      word "times"',
  '        description "English spelled form of the multiplication operator; an arithmetic_operator_word matched as a token-bounded word."',
  '      word "multiplied by"',
  '        description "English spelled phrase for the multiplication operator; an arithmetic_operator_word matched as a token-bounded phrase."',
  '      word "*"',
  "        description \"ASCII asterisk for the multiplication operator; the script-independent operator surface the arithmetic evaluator consumes, from which the operation's machine symbol is read.\"",
  '    lexeme "ru"',
  '      word "умножить"',
  '        description "Russian verb (romanized umnozhit, multiply); an arithmetic_operator_word matched as a token-bounded word."',
  '      word "умножь"',
  '        description "Russian imperative (romanized umnozh, multiply); an arithmetic_operator_word matched as a token-bounded word."',
  '      word "умножить на"',
  '        description "Russian phrase (romanized umnozhit na, multiply by); an arithmetic_operator_word matched as a token-bounded phrase, kept explicitly to mirror the original recognizer."',
  '    lexeme "hi"',
  '      word "गुणा"',
  '        description "Hindi spelled form (romanized guna, multiply) of the multiplication operator; an arithmetic_operator_word matched as a token-bounded word."',
  '    lexeme "zh"',
  '      word "乘以"',
  '        description "Chinese spelled form (pinyin chengyi, multiply by) of the multiplication operator; an arithmetic_operator_word matched as a substring."',
  '  meaning "division"',
  '    gloss "the arithmetic operation of dividing one number by another, written with the division sign. The arithmetic_operator_word role marks the spelled operator surfaces; contains_word_operator reads them to decide whether a prompt names an arithmetic operator in words rather than symbols. Matched as a token-bounded word, with CJK surfaces matched as a substring because those scripts have no inter-word spaces."',
  '    wiktionary "division"',
  '    defined_by "arithmetic_operation"',
  '    role "arithmetic_operator_word"',
  '    lexeme "en"',
  '      word "divided by"',
  '        description "English spelled phrase for the division operator; an arithmetic_operator_word matched as a token-bounded phrase."',
  '      word "/"',
  "        description \"ASCII slash for the division operator; the script-independent operator surface the arithmetic evaluator consumes, from which the operation's machine symbol is read.\"",
  '    lexeme "ru"',
  '      word "разделить на"',
  '        description "Russian phrase (romanized razdelit na, divide by); an arithmetic_operator_word matched as a token-bounded phrase."',
  '      word "делить на"',
  '        description "Russian phrase (romanized delit na, divide by); an arithmetic_operator_word matched as a token-bounded phrase."',
  '    lexeme "hi"',
  '      word "भाग"',
  '        description "Hindi spelled form (romanized bhag, divide) of the division operator; an arithmetic_operator_word matched as a token-bounded word."',
  '    lexeme "zh"',
  '      word "除以"',
  '        description "Chinese spelled form (pinyin chuyi, divide by) of the division operator; an arithmetic_operator_word matched as a substring."',
  '  meaning "modulo"',
  '    gloss "the arithmetic operation that yields the remainder of a division, written with the percent sign in the evaluator. The arithmetic_operator_word role marks the spelled operator surfaces; contains_word_operator reads them to decide whether a prompt names an arithmetic operator in words rather than symbols. Matched as a token-bounded word, with CJK surfaces matched as a substring because those scripts have no inter-word spaces."',
  '    wiktionary "modulo"',
  '    defined_by "arithmetic_operation"',
  '    role "arithmetic_operator_word"',
  '    lexeme "en"',
  '      word "modulo"',
  '        description "English spelled form of the modulo operator; an arithmetic_operator_word matched as a token-bounded word."',
  '      word "mod"',
  '        description "English abbreviation of modulo; an arithmetic_operator_word matched as a token-bounded word."',
  '      word "%"',
  "        description \"ASCII percent sign for the modulo operator; the script-independent operator surface the arithmetic evaluator consumes, from which the operation's machine symbol is read. The evaluator writes modulo as percent, matching rewrite_percent_of which leaves a bare percent not followed by of as the modulo operator.\"",
  '    lexeme "ru"',
  '      word "по модулю"',
  '        description "Russian phrase (romanized po modulyu, modulo) of the modulo operator; an arithmetic_operator_word matched as a token-bounded phrase."',
  '    lexeme "hi"',
  '      word "मॉड्यूलो"',
  '        description "Hindi spelled form (romanized modyulo) of the modulo operator; an arithmetic_operator_word matched as a token-bounded word."',
  '    lexeme "zh"',
  '      word "取模"',
  '        description "Chinese spelled form (pinyin qumo, take modulo) of the modulo operator; an arithmetic_operator_word matched as a substring."',
  '  meaning "calculation_request"',
  "    gloss \"a natural-language cue that asks for an arithmetic calculation, whether an imperative ('calculate', 'посчитай') or a question opener ('what is', 'сколько будет'). strip_calculation_wrappers removes these cues from the front of a prompt so the bare expression remains, and the explicit flag it sets lets even a digit-only expression count as a calculation. Each surface is rebuilt into a strip prefix: space-delimited scripts gain a trailing space so the cue strips only on a word boundary (calculate never eats the start of calculated), while CJK surfaces strip as-is because those scripts have no inter-word spaces. The Chinese surfaces are listed longest first so a more specific cue strips before a shorter one it contains.\"",
  '    wiktionary "calculation"',
  '    defined_by "action"',
  '    defined_by "inquiry"',
  '    role "calculation_request_cue"',
  '    lexeme "en"',
  '      word "please calculate"',
  '        description "English polite imperative asking for a calculation; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "please compute"',
  '        description "English polite imperative asking to compute a value; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "can you calculate"',
  '        description "English polite question asking the assistant to calculate; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "can you compute"',
  '        description "English polite question asking the assistant to compute; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "could you calculate"',
  '        description "English deferential question asking the assistant to calculate; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "could you compute"',
  '        description "English deferential question asking the assistant to compute; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "what is"',
  '        description "English question opener asking for the value of an expression; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  "      word \"what's\"",
  '        description "English contracted question opener (what is); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "what does"',
  "        description \"English question opener leading 'what does X equal'; a calculation_request_cue stripped from the front of a prompt on a word boundary.\"",
  '      word "calculate"',
  '        description "English bare imperative to calculate; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "compute"',
  '        description "English bare imperative to compute; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "evaluate"',
  '        description "English bare imperative to evaluate an expression; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "how much is"',
  '        description "English quantity question opener; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "solve"',
  '        description "English bare imperative to solve an expression or equation; a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '    lexeme "ru"',
  '      word "сколько будет"',
  '        description "Russian question opener (romanized skolko budet, how much will it be); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "посчитай"',
  '        description "Russian informal imperative (romanized poschitay, count it up); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "посчитайте"',
  '        description "Russian polite-plural imperative (romanized poschitayte, count it up); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "вычисли"',
  '        description "Russian informal imperative (romanized vychisli, compute it); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "вычислите"',
  '        description "Russian polite-plural imperative (romanized vychislite, compute it); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "рассчитай"',
  '        description "Russian informal imperative (romanized rasschitay, calculate it); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "рассчитайте"',
  '        description "Russian polite-plural imperative (romanized rasschitayte, calculate it); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '    lexeme "zh"',
  '      word "请计算"',
  '        description "Chinese polite imperative (pinyin qing jisuan, please calculate); a calculation_request_cue stripped from the front as a substring since Chinese has no inter-word spaces."',
  '      word "请算一下"',
  '        description "Chinese polite imperative (pinyin qing suan yixia, please do a calculation); a calculation_request_cue stripped from the front as a substring since Chinese has no inter-word spaces."',
  '      word "计算一下"',
  '        description "Chinese imperative (pinyin jisuan yixia, do a calculation); a calculation_request_cue stripped from the front as a substring since Chinese has no inter-word spaces."',
  '      word "算一下"',
  '        description "Chinese imperative (pinyin suan yixia, work it out); a calculation_request_cue stripped from the front as a substring since Chinese has no inter-word spaces."',
  '      word "计算"',
  '        description "Chinese verb (pinyin jisuan, calculate); a calculation_request_cue stripped from the front as a substring since Chinese has no inter-word spaces."',
  '    lexeme "hi"',
  '      word "कृपया गणना करें"',
  '        description "Hindi polite imperative (romanized kripya ganana karen, please calculate); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '      word "गणना करें"',
  '        description "Hindi imperative (romanized ganana karen, do the calculation); a calculation_request_cue stripped from the front of a prompt on a word boundary."',
  '  meaning "politeness"',
  '    gloss "a politeness or courtesy marker that softens a request without adding any task content, such as please, for me, пожалуйста, कृपया, or 请. strip_calculation_wrappers removes these markers from the end of a calculation prompt so the bare expression remains. Each surface is rebuilt into a strip suffix: space-delimited scripts gain a leading space so the cue strips only on a word boundary, while CJK surfaces strip as-is because those scripts have no inter-word spaces. Defined as a property of a request — a quality it carries rather than its content."',
  '    wiktionary "politeness"',
  '    defined_by "property"',
  '    role "politeness_cue"',
  '    lexeme "en"',
  '      word "please"',
  '        description "English courtesy word that softens a request; a politeness_cue stripped from the end of a prompt on a word boundary."',
  '      word "for me"',
  '        description "English courtesy phrase (do this for me) that softens a request; a politeness_cue stripped from the end of a prompt on a word boundary."',
  '    lexeme "ru"',
  '      word "пожалуйста"',
  '        description "Russian courtesy word (romanized pozhaluysta, please); a politeness_cue stripped from the end of a prompt on a word boundary."',
  '    lexeme "hi"',
  '      word "कृपया"',
  '        description "Hindi courtesy word (romanized kripya, please); a politeness_cue stripped from the end of a prompt on a word boundary."',
  '    lexeme "zh"',
  '      word "请"',
  '        description "Chinese courtesy word (pinyin qing, please); a politeness_cue stripped from the end as a substring since Chinese has no inter-word spaces."',
  '  meaning "calculation_result_query"',
  '    gloss "a trailing cue that asks for the computed result of the preceding arithmetic expression, whether an equals word or sign (equal, equals, =, равно), a how-much-is-it question (是多少, 等于多少, कितना है, क्या है), or a head-final do-the-calculation imperative (की गणना करें). strip_calculation_wrappers removes these cues from the end of a prompt so the bare expression remains. Each surface is rebuilt into a strip suffix: space-delimited scripts gain a leading space so the cue strips only on a word boundary, the bare equals sign also strips with no leading space so a compact 2*2+2= is recognised, and CJK surfaces strip as-is because those scripts have no inter-word spaces. Defined as both an action and an inquiry — it both invokes the calculation and asks for its value."',
  '    wiktionary "equal"',
  '    defined_by "action"',
  '    defined_by "inquiry"',
  '    role "calculation_result_query_cue"',
  '    lexeme "en"',
  '      word "equal"',
  '        description "English equals word asking for the value of the preceding expression; a calculation_result_query_cue stripped from the end of a prompt on a word boundary."',
  '      word "equals"',
  '        description "English equals word (third person) asking for the value of the preceding expression; a calculation_result_query_cue stripped from the end of a prompt on a word boundary."',
  '      word "="',
  '        description "The equals sign; the script-independent symbol surface that asks for the value of the preceding expression, a calculation_result_query_cue stripped from the end of a prompt both bare (so a compact 2*2+2= is recognised) and on a word boundary."',
  '    lexeme "ru"',
  '      word "равно"',
  '        description "Russian equals word (romanized ravno, equals); a calculation_result_query_cue stripped from the end of a prompt on a word boundary."',
  '    lexeme "zh"',
  '      word "是多少"',
  '        description "Chinese question tail (pinyin shi duoshao, is how much); a calculation_result_query_cue stripped from the end as a substring since Chinese has no inter-word spaces."',
  '      word "等于多少"',
  '        description "Chinese question tail (pinyin dengyu duoshao, equals how much); a calculation_result_query_cue stripped from the end as a substring since Chinese has no inter-word spaces."',
  '      word "等于几"',
  '        description "Chinese question tail (pinyin dengyu ji, equals how many); a calculation_result_query_cue stripped from the end as a substring since Chinese has no inter-word spaces."',
  '    lexeme "hi"',
  '      word "कितना है"',
  '        description "Hindi question tail (romanized kitna hai, how much is it); a calculation_result_query_cue stripped from the end of a prompt on a word boundary."',
  '      word "क्या है"',
  '        description "Hindi question tail (romanized kya hai, what is it); a calculation_result_query_cue stripped from the end of a prompt on a word boundary."',
  '      word "की गणना करें"',
  '        description "Hindi head-final imperative (romanized ki ganana karen, do the calculation of); a calculation_result_query_cue stripped from the end of a prompt on a word boundary."',
  '  meaning "quantity_conversion"',
  "    gloss \"a cue that a prompt is converting one quantity into another — a currency or unit conversion (convert dollars to euros, 100 km into miles). has_calculation_signal otherwise rejects a prompt that pairs a currency symbol with letters and is not an explicit calculate command, treating it as prose that merely mentions money; a quantity_conversion_cue exempts it, because a conversion is itself a calculation. Each surface is matched whole-token through mentions_role: in space-delimited scripts the cue must stand on a word boundary (so to and into match the marker, never a substring of another word), while Chinese surfaces match as a substring since that script has no inter-word spaces. Distinct from conversion_action, the money-specific verb the compound-interest handler matches as a raw substring: this meaning is the calculator router's general conversion signal and includes the bare target markers to and into, so it must stay whole-token. Defined as an action that establishes a relation between a source and a target quantity.\"",
  '    wiktionary "conversion"',
  '    defined_by "action"',
  '    defined_by "relation"',
  '    role "quantity_conversion_cue"',
  '    lexeme "en"',
  '      word "to"',
  '        description "English target marker (convert dollars to euros); a quantity_conversion_cue matched whole-token so it signals a conversion only on a word boundary, never inside another word."',
  '      word "into"',
  '        description "English target marker (convert 100 km into miles); a quantity_conversion_cue matched whole-token so it signals a conversion only on a word boundary."',
  '      word "convert"',
  '        description "English verb to change one quantity into another; a quantity_conversion_cue matched whole-token."',
  '      word "exchange"',
  '        description "English verb to trade one currency for another; a quantity_conversion_cue matched whole-token."',
  '    lexeme "ru"',
  '      word "конвертировать"',
  '        description "Russian verb (romanized konvertirovat, to convert); a quantity_conversion_cue matched whole-token on a word boundary."',
  '      word "обмен"',
  '        description "Russian noun (romanized obmen, exchange); a quantity_conversion_cue matched whole-token on a word boundary."',
  '    lexeme "hi"',
  '      word "बदलें"',
  '        description "Hindi verb (romanized badlen, change or convert); a quantity_conversion_cue matched whole-token on a word boundary."',
  '      word "परिवर्तित"',
  '        description "Hindi adjective (romanized parivartit, converted); a quantity_conversion_cue matched whole-token on a word boundary."',
  '    lexeme "zh"',
  '      word "转换"',
  '        description "Chinese verb (pinyin zhuanhuan, to convert); a quantity_conversion_cue matched as a substring since Chinese has no inter-word spaces."',
  '      word "兑换"',
  '        description "Chinese verb (pinyin duihuan, to exchange currency); a quantity_conversion_cue matched as a substring since Chinese has no inter-word spaces."',
  '      word "换成"',
  '        description "Chinese verb phrase (pinyin huancheng, to change into); a quantity_conversion_cue matched as a substring since Chinese has no inter-word spaces."',
  '  meaning "mathematical_function"',
  '    gloss "a named mathematical operation that maps one or more input numbers to a result, such as a square root, a trigonometric function, or a logarithm. The genus of the individual function names, each defined as a kind of mathematical function rather than listed in code. The numeric_concept role is structural: no handler queries the genus directly; it records that these names are kinds of mathematical function."',
  '    wiktionary "function"',
  '    defined_by "function"',
  '    role "numeric_concept"',
  '    lexeme "en"',
  '      word "mathematical function"',
  '        description "English term for a named operation that maps input numbers to a result; the genus of the individual function names."',
  '    lexeme "ru"',
  '      word "математическая функция"',
  '        description "Russian term (romanized matematicheskaya funktsiya) for a mathematical function; the Russian surface for the mathematical-function concept."',
  '    lexeme "hi"',
  '      word "गणितीय फलन"',
  '        description "Hindi term (romanized ganitiya phalan) for a mathematical function; the Hindi surface for the mathematical-function concept."',
  '    lexeme "zh"',
  '      word "数学函数"',
  '        description "Chinese term (pinyin shuxue hanshu) for a mathematical function; the Chinese surface for the mathematical-function concept."',
  '  meaning "square_root"',
  '    gloss "the square-root function, which returns the non-negative number whose square is the input. A math_function_name: the calculator router treats its name beside a number, as in sqrt(16), as a calculation signal. ASCII names are matched on a leading word boundary so they are recognised even when they abut a parenthesis; other scripts are matched as raw substrings."',
  '    wiktionary "square root"',
  '    defined_by "mathematical_function"',
  '    role "math_function_name"',
  '    lexeme "en"',
  '      word "sqrt"',
  '        description "English abbreviation for the square-root function; a math_function_name matched on a leading word boundary so sqrt(16) is recognised."',
  '      word "square root"',
  '        description "English name for the function returning the number whose square is the input; a math_function_name matched on a leading word boundary."',
  '    lexeme "ru"',
  '      word "квадратный корень"',
  '        description "Russian term (romanized kvadratnyy koren, square root); a math_function_name matched as a raw substring."',
  '      word "корень"',
  '        description "Russian noun (romanized koren, root), the short name of the square-root function; a math_function_name matched as a raw substring."',
  '    lexeme "hi"',
  '      word "वर्गमूल"',
  '        description "Hindi noun (romanized vargamul, square root); a math_function_name matched as a raw substring."',
  '    lexeme "zh"',
  '      word "平方根"',
  '        description "Chinese noun (pinyin pingfanggen, square root); a math_function_name matched as a raw substring."',
  '  meaning "sine"',
  '    gloss "the sine trigonometric function. A math_function_name: the calculator router treats its name beside a number as a calculation signal. ASCII names are matched on a leading word boundary; other scripts as raw substrings."',
  '    wiktionary "sine"',
  '    defined_by "mathematical_function"',
  '    role "math_function_name"',
  '    lexeme "en"',
  '      word "sin"',
  '        description "English abbreviation for the sine function; a math_function_name matched on a leading word boundary."',
  '      word "sine"',
  '        description "English name for the sine trigonometric function; a math_function_name matched on a leading word boundary."',
  '    lexeme "ru"',
  '      word "синус"',
  '        description "Russian noun (romanized sinus, sine); a math_function_name matched as a raw substring."',
  '    lexeme "hi"',
  '      word "ज्या"',
  '        description "Hindi noun (romanized jya, sine); a math_function_name matched as a raw substring."',
  '    lexeme "zh"',
  '      word "正弦"',
  '        description "Chinese noun (pinyin zhengxian, sine); a math_function_name matched as a raw substring."',
  '  meaning "cosine"',
  '    gloss "the cosine trigonometric function. A math_function_name: the calculator router treats its name beside a number as a calculation signal. ASCII names are matched on a leading word boundary; other scripts as raw substrings."',
  '    wiktionary "cosine"',
  '    defined_by "mathematical_function"',
  '    role "math_function_name"',
  '    lexeme "en"',
  '      word "cos"',
  '        description "English abbreviation for the cosine function; a math_function_name matched on a leading word boundary."',
  '      word "cosine"',
  '        description "English name for the cosine trigonometric function; a math_function_name matched on a leading word boundary."',
  '    lexeme "ru"',
  '      word "косинус"',
  '        description "Russian noun (romanized kosinus, cosine); a math_function_name matched as a raw substring."',
  '    lexeme "hi"',
  '      word "कोज्या"',
  '        description "Hindi noun (romanized kojya, cosine); a math_function_name matched as a raw substring."',
  '    lexeme "zh"',
  '      word "余弦"',
  '        description "Chinese noun (pinyin yuxian, cosine); a math_function_name matched as a raw substring."',
  '  meaning "tangent"',
  '    gloss "the tangent trigonometric function. A math_function_name: the calculator router treats its name beside a number as a calculation signal. ASCII names are matched on a leading word boundary; other scripts as raw substrings."',
  '    wiktionary "tangent"',
  '    defined_by "mathematical_function"',
  '    role "math_function_name"',
  '    lexeme "en"',
  '      word "tan"',
  '        description "English abbreviation for the tangent function; a math_function_name matched on a leading word boundary."',
  '      word "tangent"',
  '        description "English name for the tangent trigonometric function; a math_function_name matched on a leading word boundary."',
  '    lexeme "ru"',
  '      word "тангенс"',
  '        description "Russian noun (romanized tangens, tangent); a math_function_name matched as a raw substring."',
  '    lexeme "hi"',
  '      word "स्पर्शज्या"',
  '        description "Hindi noun (romanized sparshajya, tangent); a math_function_name matched as a raw substring."',
  '    lexeme "zh"',
  '      word "正切"',
  '        description "Chinese noun (pinyin zhengqie, tangent); a math_function_name matched as a raw substring."',
  '  meaning "logarithm"',
  '    gloss "the logarithm function, the inverse of exponentiation. A math_function_name: the calculator router treats its name beside a number as a calculation signal. ASCII names are matched on a leading word boundary; other scripts as raw substrings."',
  '    wiktionary "logarithm"',
  '    defined_by "mathematical_function"',
  '    role "math_function_name"',
  '    lexeme "en"',
  '      word "log"',
  '        description "English abbreviation for the logarithm function; a math_function_name matched on a leading word boundary."',
  '      word "logarithm"',
  '        description "English name for the logarithm function, the inverse of exponentiation; a math_function_name matched on a leading word boundary."',
  '    lexeme "ru"',
  '      word "логарифм"',
  '        description "Russian noun (romanized logarifm, logarithm); a math_function_name matched as a raw substring."',
  '    lexeme "hi"',
  '      word "लघुगणक"',
  '        description "Hindi noun (romanized laghuganak, logarithm); a math_function_name matched as a raw substring."',
  '    lexeme "zh"',
  '      word "对数"',
  '        description "Chinese noun (pinyin duishu, logarithm); a math_function_name matched as a raw substring."',
  '  meaning "natural_logarithm"',
  '    gloss "the natural logarithm function, the logarithm to base e. A math_function_name: the calculator router treats its name beside a number as a calculation signal. ASCII names are matched on a leading word boundary; other scripts as raw substrings."',
  '    wiktionary "natural logarithm"',
  '    defined_by "mathematical_function"',
  '    role "math_function_name"',
  '    lexeme "en"',
  '      word "ln"',
  '        description "English abbreviation for the natural logarithm, the logarithm to base e; a math_function_name matched on a leading word boundary."',
  '      word "natural logarithm"',
  '        description "English name for the logarithm to base e; a math_function_name matched on a leading word boundary."',
  '    lexeme "ru"',
  '      word "натуральный логарифм"',
  '        description "Russian term (romanized naturalnyy logarifm, natural logarithm); a math_function_name matched as a raw substring."',
  '    lexeme "hi"',
  '      word "प्राकृतिक लघुगणक"',
  '        description "Hindi term (romanized prakritik laghuganak, natural logarithm); a math_function_name matched as a raw substring."',
  '    lexeme "zh"',
  '      word "自然对数"',
  '        description "Chinese term (pinyin ziran duishu, natural logarithm); a math_function_name matched as a raw substring."',
  "meanings",
  '  meaning "knowledge_relation"',
  '    gloss "a relation in the knowledge base that maps a subject to a value; the genus of every fact-query relation below"',
  '    wiktionary "relation"',
  '    defined_by "knowledge_subject"',
  '    defined_by "knowledge_value"',
  '    defined_by "relation"',
  '    role "knowledge_relation"',
  '    lexeme "en"',
  '      word "relation"',
  '        description "English noun for a link in the knowledge base that maps a subject to a value; the genus of the fact-query relations."',
  '      word "property"',
  '        description "English noun for an attribute that maps a subject to a value; a synonym surface for the knowledge relation."',
  '    lexeme "ru"',
  '      word "отношение"',
  '        description "Russian noun (romanized otnosheniye) for a relation that maps a subject to a value; the Russian surface for the knowledge relation."',
  '      word "свойство"',
  '        description "Russian noun (romanized svoystvo) for a property mapping a subject to a value; an alternative Russian surface for the knowledge relation."',
  '    lexeme "hi"',
  '      word "संबंध"',
  '        description "Hindi noun (romanized sambandh) for a relation that maps a subject to a value; the Hindi surface for the knowledge relation."',
  '      word "गुण"',
  '        description "Hindi noun (romanized gun) for a property or attribute; an alternative Hindi surface for the knowledge relation."',
  '    lexeme "zh"',
  '      word "关系"',
  '        description "Chinese noun (pinyin guanxi) for a relation that maps a subject to a value; the Chinese surface for the knowledge relation."',
  '      word "属性"',
  '        description "Chinese noun (pinyin shuxing) for an attribute or property; an alternative Chinese surface for the knowledge relation."',
  '  meaning "knowledge_subject"',
  '    gloss "the entity a knowledge-base question is about — the subject a fact relation maps to a value"',
  '    wiktionary "subject"',
  '    defined_by "knowledge_relation"',
  '    role "knowledge_subject"',
  '    lexeme "en"',
  '      word "subject"',
  '        description "English noun for the entity a knowledge-base question is about; the subject a fact relation maps to a value."',
  '      word "entity"',
  '        description "English noun for the thing being asked about; a synonym surface for the knowledge subject."',
  '      word "topic"',
  '        description "English noun for what a question concerns; an alternative surface for the knowledge subject."',
  '    lexeme "ru"',
  '      word "субъект"',
  '        description "Russian noun (romanized subyekt) for the subject of a question; the Russian surface for the knowledge subject."',
  '      word "сущность"',
  '        description "Russian noun (romanized sushchnost) for the entity being asked about; an alternative Russian surface for the knowledge subject."',
  '      word "предмет"',
  '        description "Russian noun (romanized predmet) for the topic of a question; another Russian surface for the knowledge subject."',
  '    lexeme "hi"',
  '      word "विषय"',
  '        description "Hindi noun (romanized vishay) for the topic or subject of a question; the Hindi surface for the knowledge subject."',
  '      word "इकाई"',
  '        description "Hindi noun (romanized ikai) for the entity being asked about; an alternative Hindi surface for the knowledge subject."',
  '    lexeme "zh"',
  '      word "主体"',
  '        description "Chinese noun (pinyin zhuti) for the subject of a question; the Chinese surface for the knowledge subject."',
  '      word "实体"',
  '        description "Chinese noun (pinyin shiti) for the entity being asked about; an alternative Chinese surface for the knowledge subject."',
  '  meaning "knowledge_value"',
  '    gloss "the value a fact relation yields for its subject — the answer to the question"',
  '    wiktionary "value"',
  '    defined_by "knowledge_relation"',
  '    role "knowledge_value"',
  '    lexeme "en"',
  '      word "value"',
  '        description "English noun for the value a fact relation yields for its subject; the answer to the question."',
  '      word "answer"',
  '        description "English noun for the response to a question; a synonym surface for the knowledge value."',
  '    lexeme "ru"',
  '      word "значение"',
  '        description "Russian noun (romanized znacheniye) for the value a relation yields; the Russian surface for the knowledge value."',
  '      word "ответ"',
  '        description "Russian noun (romanized otvet) for the answer to a question; an alternative Russian surface for the knowledge value."',
  '    lexeme "hi"',
  '      word "मान"',
  '        description "Hindi noun (romanized maan) for the value a relation yields; the Hindi surface for the knowledge value."',
  '      word "उत्तर"',
  '        description "Hindi noun (romanized uttar) for the answer to a question; an alternative Hindi surface for the knowledge value."',
  '    lexeme "zh"',
  '      word "值"',
  '        description "Chinese noun (pinyin zhi) for the value a relation yields; the Chinese surface for the knowledge value."',
  '      word "答案"',
  '        description "Chinese noun (pinyin daan) for the answer to a question; an alternative Chinese surface for the knowledge value."',
  '  meaning "capital"',
  '    gloss "the relation linking a country to its capital city (Wikidata P36)"',
  '    wiktionary "capital"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "capital"',
  '        description "English noun for the seat-of-government city of a country; the surface for the capital-of relation."',
  '    lexeme "ru"',
  '      word "столица"',
  '        description "Russian noun (romanized stolitsa), nominative singular, for a capital city; the Russian surface for the capital-of relation."',
  '      word "столицы"',
  '        description "Russian noun (romanized stolitsy), genitive singular or nominative plural of capital; an inflected surface for the capital-of relation."',
  '      word "столицей"',
  '        description "Russian noun (romanized stolitsey), instrumental singular of capital; an inflected surface for the capital-of relation."',
  '    lexeme "hi"',
  '      word "राजधानी"',
  '        description "Hindi noun (romanized rajdhani) for a capital city; the Hindi surface for the capital-of relation."',
  '    lexeme "zh"',
  '      word "首都"',
  '        description "Chinese noun (pinyin shoudu) for a capital city; the Chinese surface for the capital-of relation."',
  '  meaning "population"',
  '    gloss "the relation linking a place to how many people live there (Wikidata P1082)"',
  '    wiktionary "population"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "population"',
  '        description "English noun for how many people live in a place; the surface for the population relation."',
  '      word "how many people"',
  '        description "English interrogative phrase asking the count of inhabitants; a question surface for the population relation."',
  '    lexeme "ru"',
  '      word "население"',
  '        description "Russian noun (romanized naseleniye) for the population of a place; the Russian surface for the population relation."',
  '    lexeme "hi"',
  '      word "जनसंख्या"',
  '        description "Hindi noun (romanized jansankhya) for population; the Hindi surface for the population relation."',
  '      word "आबादी"',
  '        description "Hindi noun (romanized aabaadi) for population or inhabitants; an alternative Hindi surface for the population relation."',
  '    lexeme "zh"',
  '      word "人口"',
  '        description "Chinese noun (pinyin renkou) for population; the Chinese surface for the population relation."',
  '  meaning "currency"',
  '    gloss "the relation linking a country to its official currency (Wikidata P38)"',
  '    wiktionary "currency"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "currency"',
  '        description "English noun for the official money of a country; the surface for the currency relation."',
  '    lexeme "ru"',
  '      word "валюта"',
  '        description "Russian noun (romanized valyuta) for currency; the Russian surface for the currency relation."',
  '    lexeme "hi"',
  '      word "मुद्रा"',
  '        description "Hindi noun (romanized mudra) for currency; the Hindi surface for the currency relation."',
  '    lexeme "zh"',
  '      word "货币"',
  '        description "Chinese noun (pinyin huobi) for currency, in simplified characters; the Chinese surface for the currency relation."',
  '      word "貨幣"',
  '        description "Chinese noun (pinyin huobi) for currency, in traditional characters; an alternative Chinese surface for the currency relation."',
  '  meaning "official_language"',
  '    gloss "the relation linking a country to its official language (Wikidata P37)"',
  '    wiktionary "language"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "official language"',
  "        description \"English noun phrase for a country's officially designated language; the surface for the official-language relation.\"",
  '      word "what language"',
  '        description "English interrogative phrase asking which language is official; a question surface for the official-language relation."',
  '    lexeme "ru"',
  '      word "государственный язык"',
  '        description "Russian noun phrase (romanized gosudarstvennyy yazyk) for the state language; the Russian surface for the official-language relation."',
  '      word "официальный язык"',
  '        description "Russian noun phrase (romanized ofitsialnyy yazyk) for the official language; an alternative Russian surface for the official-language relation."',
  '    lexeme "hi"',
  '      word "राजभाषा"',
  '        description "Hindi noun (romanized rajbhasha) for the official or state language; the Hindi surface for the official-language relation."',
  '      word "आधिकारिक भाषा"',
  '        description "Hindi noun phrase (romanized aadhikaarik bhasha) for the official language; an alternative Hindi surface for the official-language relation."',
  '    lexeme "zh"',
  '      word "官方语言"',
  '        description "Chinese noun phrase (pinyin guanfang yuyan) for the official language, in simplified characters; the Chinese surface for the official-language relation."',
  '      word "官方語言"',
  '        description "Chinese noun phrase (pinyin guanfang yuyan) for the official language, in traditional characters; an alternative Chinese surface for the official-language relation."',
  '  meaning "continent"',
  '    gloss "the relation linking a place to the continent it lies on (Wikidata P30)"',
  '    wiktionary "continent"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "continent"',
  '        description "English noun for one of the large landmasses a place lies on; the surface for the continent relation."',
  '    lexeme "ru"',
  '      word "континент"',
  '        description "Russian noun (romanized kontinent) for a continent; the Russian surface for the continent relation."',
  '    lexeme "hi"',
  '      word "महाद्वीप"',
  '        description "Hindi noun (romanized mahadweep) for a continent; the Hindi surface for the continent relation."',
  '    lexeme "zh"',
  '      word "大洲"',
  '        description "Chinese noun (pinyin dazhou) for a continent; the Chinese surface for the continent relation."',
  '  meaning "author_of_book"',
  '    gloss "the relation linking a book to the author who wrote it (Wikidata P50)"',
  '    wiktionary "author"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "who wrote"',
  '        description "English interrogative phrase asking which person authored a book; a question surface for the author-of-book relation."',
  '      word "author"',
  '        description "English noun for the person who wrote a book; the surface for the author-of-book relation."',
  '      word "written by"',
  '        description "English passive phrase naming the writer of a book; an alternative surface for the author-of-book relation."',
  '    lexeme "ru"',
  '      word "кто написал"',
  '        description "Russian interrogative phrase (romanized kto napisal) asking who wrote a book; a question surface for the author-of-book relation."',
  '      word "написал"',
  '        description "Russian verb (romanized napisal), past tense of to write, for authored a book; a surface for the author-of-book relation."',
  '      word "автор"',
  '        description "Russian noun (romanized avtor) for the author of a book; an alternative Russian surface for the author-of-book relation."',
  '    lexeme "hi"',
  '      word "किसने लिखी"',
  '        description "Hindi interrogative phrase (romanized kisne likhi) asking who wrote it, agreeing with a feminine book noun; a question surface for the author-of-book relation."',
  '      word "किसने लिखा"',
  '        description "Hindi interrogative phrase (romanized kisne likha) asking who wrote it, masculine agreement; an alternative question surface for the author-of-book relation."',
  '      word "लेखक"',
  '        description "Hindi noun (romanized lekhak) for the author or writer; the Hindi surface for the author-of-book relation."',
  '    lexeme "zh"',
  '      word "是谁写的"',
  '        description "Chinese interrogative phrase (pinyin shi shei xie de) asking who wrote it; a question surface for the author-of-book relation."',
  '      word "作者"',
  '        description "Chinese noun (pinyin zuozhe) for the author of a book; the Chinese surface for the author-of-book relation."',
  '  meaning "painter_of_painting"',
  '    gloss "the relation linking a painting to the painter who created it (Wikidata P170)"',
  '    wiktionary "painter"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "who painted"',
  '        description "English interrogative phrase asking which person created a painting; a question surface for the painter-of-painting relation."',
  '      word "painted"',
  '        description "English verb, past tense of to paint, for created a painting; a surface for the painter-of-painting relation."',
  '      word "painter"',
  '        description "English noun for the person who painted a painting; the surface for the painter-of-painting relation."',
  '      word "artist"',
  '        description "English noun for the creator of a painting; a synonym surface for the painter-of-painting relation."',
  '    lexeme "ru"',
  '      word "кто написал"',
  '        description "Russian interrogative phrase (romanized kto napisal) asking who painted it, since napisal also covers painting a picture; a question surface for the painter-of-painting relation."',
  '      word "написал"',
  '        description "Russian verb (romanized napisal), past tense used for painting a picture; a surface for the painter-of-painting relation."',
  '      word "художник"',
  '        description "Russian noun (romanized khudozhnik) for the painter or artist; the Russian surface for the painter-of-painting relation."',
  '    lexeme "hi"',
  '      word "किसने बनाई"',
  '        description "Hindi interrogative phrase (romanized kisne banai) asking who made it, agreeing with a feminine painting noun; a question surface for the painter-of-painting relation."',
  '      word "चित्रकार"',
  '        description "Hindi noun (romanized chitrakar) for a painter; the Hindi surface for the painter-of-painting relation."',
  '      word "कलाकार"',
  '        description "Hindi noun (romanized kalakar) for an artist; an alternative Hindi surface for the painter-of-painting relation."',
  '    lexeme "zh"',
  '      word "谁画的"',
  '        description "Chinese interrogative phrase (pinyin shei hua de) asking who painted it; a question surface for the painter-of-painting relation."',
  '      word "画家"',
  '        description "Chinese noun (pinyin huajia) for a painter; the Chinese surface for the painter-of-painting relation."',
  '  meaning "built_year"',
  '    gloss "the relation linking a structure to the year it was built (Wikidata P571)"',
  '    wiktionary "build"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "when"',
  '        description "English interrogative adverb asking the year a structure was built; a question surface for the built-year relation."',
  '      word "built"',
  '        description "English verb, past participle of to build, for constructed in a given year; a surface for the built-year relation."',
  '      word "construction"',
  '        description "English noun for the building of a structure; an alternative surface for the built-year relation."',
  '    lexeme "ru"',
  '      word "когда"',
  '        description "Russian interrogative adverb (romanized kogda) asking when a structure was built; a question surface for the built-year relation."',
  '      word "построена"',
  '        description "Russian verb (romanized postroyena), feminine past participle of to build, for was built; a surface for the built-year relation."',
  '      word "построили"',
  '        description "Russian verb (romanized postroili), plural past tense of to build, for they built; an alternative surface for the built-year relation."',
  '    lexeme "hi"',
  '      word "बनी"',
  '        description "Hindi verb (romanized bani), feminine past form of to be made, for was built; a surface for the built-year relation."',
  '      word "बनाई"',
  '        description "Hindi verb (romanized banai), feminine past form of to make, for was built; an alternative surface for the built-year relation."',
  '      word "कब"',
  '        description "Hindi interrogative adverb (romanized kab) asking when something was built; a question surface for the built-year relation."',
  '    lexeme "zh"',
  '      word "何时"',
  '        description "Chinese interrogative phrase (pinyin heshi) asking at what time it was built; a question surface for the built-year relation."',
  '      word "建于"',
  '        description "Chinese verb phrase (pinyin jianyu) for built in a given year; a surface for the built-year relation."',
  '      word "建造"',
  '        description "Chinese verb (pinyin jianzao) for to build or construct; an alternative surface for the built-year relation."',
  '  meaning "physical_constant"',
  '    gloss "the relation linking a named physical constant to its value (e.g. the speed of light)"',
  '    wiktionary "constant"',
  '    defined_by "knowledge_relation"',
  '    role "fact_relation"',
  '    lexeme "en"',
  '      word "speed of light"',
  '        description "English noun phrase naming a physical constant, the speed at which light travels; an example surface for the physical-constant relation."',
  '      word "what is"',
  '        description "English interrogative phrase asking the value of a named constant; a question surface for the physical-constant relation."',
  '      word "how fast"',
  '        description "English interrogative phrase asking the magnitude of a speed constant; an alternative question surface for the physical-constant relation."',
  '    lexeme "ru"',
  '      word "скорость света"',
  '        description "Russian noun phrase (romanized skorost sveta) for the speed of light; an example surface for the physical-constant relation."',
  '      word "какова"',
  "        description \"Russian interrogative pronoun (romanized kakova), feminine, asking what a constant's value is; a question surface for the physical-constant relation.\"",
  '      word "чему равна"',
  '        description "Russian interrogative phrase (romanized chemu ravna) asking what a quantity equals; an alternative question surface for the physical-constant relation."',
  '    lexeme "hi"',
  '      word "प्रकाश की गति"',
  '        description "Hindi noun phrase (romanized prakash ki gati) for the speed of light; an example surface for the physical-constant relation."',
  '      word "कितनी"',
  '        description "Hindi interrogative adjective (romanized kitni), feminine, asking how much a quantity is; a question surface for the physical-constant relation."',
  '    lexeme "zh"',
  '      word "光速"',
  '        description "Chinese noun (pinyin guangsu) for the speed of light; an example surface for the physical-constant relation."',
  '      word "是多少"',
  '        description "Chinese interrogative phrase (pinyin shi duoshao) asking what amount a constant is; a question surface for the physical-constant relation."',
  "meanings",
  '  meaning "software_followup"',
  '    gloss "exercising an already-designed software artifact — verifying, executing, or demonstrating it; the genus of the follow-up kinds below"',
  '    wiktionary "follow-up"',
  '    defined_by "software_followup_verification"',
  '    defined_by "software_followup_execution"',
  '    defined_by "software_followup_demonstration"',
  '    defined_by "action"',
  '    role "software_followup"',
  '    lexeme "en"',
  '      word "follow-up"',
  '        description "English noun for exercising an already-designed artifact by verifying, running, or demonstrating it; the genus of the follow-up kinds."',
  '      word "exercise"',
  '        description "English verb for putting a finished artifact through its paces; a synonym surface for the follow-up action."',
  '    lexeme "ru"',
  '      word "продолжение"',
  '        description "Russian noun (romanized prodolzheniye) for a continuation or follow-up; the Russian surface for exercising a finished artifact."',
  '      word "отработка"',
  '        description "Russian noun (romanized otrabotka) for putting something through its paces; an alternative Russian surface for the follow-up action."',
  '    lexeme "hi"',
  '      word "अनुवर्ती"',
  '        description "Hindi adjective (romanized anuvarti) for follow-up or subsequent; the Hindi surface for exercising a finished artifact."',
  '      word "अभ्यास"',
  '        description "Hindi noun (romanized abhyas) for practice or exercise; an alternative Hindi surface for the follow-up action."',
  '    lexeme "zh"',
  '      word "后续"',
  '        description "Chinese noun (pinyin houxu) for a follow-up or subsequent step; the Chinese surface for exercising a finished artifact."',
  '      word "演练"',
  '        description "Chinese verb (pinyin yanlian) for rehearsing or drilling; an alternative Chinese surface for the follow-up action."',
  '  meaning "software_followup_verification"',
  '    gloss "a follow-up that verifies the just-designed artifact behaves correctly (test it, run the tests, …)"',
  '    wiktionary "verification"',
  '    defined_by "software_followup"',
  '    role "software_followup_verification"',
  '    lexeme "en"',
  '      word "test it"',
  '        description "English imperative phrase asking to verify the just-designed artifact behaves correctly; a verification follow-up surface."',
  '      word "test the"',
  '        description "English phrase fragment introducing the artifact to be verified; a verification follow-up surface."',
  '      word "test this"',
  '        description "English imperative phrase asking to verify this artifact; a verification follow-up surface."',
  '      word "verify"',
  '        description "English verb for confirming the artifact behaves correctly; the base verification follow-up surface."',
  '      word "check it"',
  '        description "English imperative phrase asking to inspect the artifact for correctness; a verification follow-up surface."',
  '      word "check that"',
  '        description "English phrase fragment introducing what should be checked for correctness; a verification follow-up surface."',
  '      word "run the tests"',
  "        description \"English imperative phrase asking to execute the artifact's test suite; a verification follow-up surface.\"",
  '    lexeme "ru"',
  '      word "протестируй"',
  '        description "Russian imperative verb (romanized protestiruy) meaning test it; a verification follow-up surface."',
  '      word "протестировать"',
  '        description "Russian infinitive verb (romanized protestirovat) meaning to test; the infinitive form of the verification verb."',
  '      word "проверь"',
  '        description "Russian imperative verb (romanized prover) meaning check or verify; a verification follow-up surface."',
  '      word "тестируй"',
  '        description "Russian imperative verb (romanized testiruy) meaning test; an imperfective verification follow-up surface."',
  '    lexeme "hi"',
  '      word "परीक्षण"',
  '        description "Hindi noun (romanized parikshan) for testing or examination; a verification follow-up surface."',
  '      word "जाँच"',
  '        description "Hindi noun (romanized janch) for a check or inspection; a verification follow-up surface."',
  '      word "जांच"',
  '        description "Hindi noun (romanized janch) for a check or inspection; an alternative spelling of the verification surface."',
  '    lexeme "zh"',
  '      word "测试"',
  '        description "Chinese verb (pinyin ceshi) for testing; a verification follow-up surface."',
  '      word "检验"',
  '        description "Chinese verb (pinyin jianyan) for inspecting or verifying; a verification follow-up surface."',
  '      word "检查"',
  '        description "Chinese verb (pinyin jiancha) for checking or examining; a verification follow-up surface."',
  '  meaning "software_followup_execution"',
  '    gloss "a follow-up that runs or executes the just-designed artifact (run it, execute it, …)"',
  '    wiktionary "execution"',
  '    defined_by "software_followup"',
  '    role "software_followup_execution"',
  '    lexeme "en"',
  '      word "run it"',
  '        description "English imperative phrase asking to execute the just-designed artifact; an execution follow-up surface."',
  '      word "run this"',
  '        description "English imperative phrase asking to execute this artifact; an execution follow-up surface."',
  '      word "run the"',
  '        description "English phrase fragment introducing the artifact to execute; an execution follow-up surface."',
  '      word "execute it"',
  '        description "English imperative phrase asking to run the artifact; an execution follow-up surface."',
  '      word "execute the"',
  '        description "English phrase fragment introducing the artifact to run; an execution follow-up surface."',
  '      word "try it"',
  '        description "English imperative phrase asking to run the artifact to see it work; an execution follow-up surface."',
  '    lexeme "ru"',
  '      word "запусти"',
  '        description "Russian imperative verb (romanized zapusti) meaning run or launch it; an execution follow-up surface."',
  '      word "выполни"',
  '        description "Russian imperative verb (romanized vypolni) meaning execute or carry out; an execution follow-up surface."',
  '    lexeme "hi"',
  '      word "चलाओ"',
  '        description "Hindi imperative verb (romanized chalao) meaning run it; an execution follow-up surface."',
  '      word "निष्पादित"',
  '        description "Hindi adjective (romanized nishpadit) meaning executed; an execution follow-up surface."',
  '    lexeme "zh"',
  '      word "运行"',
  '        description "Chinese verb (pinyin yunxing) for running an artifact; an execution follow-up surface."',
  '      word "执行"',
  '        description "Chinese verb (pinyin zhixing) for executing; an execution follow-up surface."',
  '  meaning "software_followup_demonstration"',
  "    gloss \"a follow-up that demonstrates the just-designed artifact's output (show me, demo it, …)\"",
  '    wiktionary "demonstration"',
  '    defined_by "software_followup"',
  '    role "software_followup_demonstration"',
  '    lexeme "en"',
  '      word "demo it"',
  "        description \"English imperative phrase asking to demonstrate the artifact's output; a demonstration follow-up surface.\"",
  '      word "show me"',
  "        description \"English imperative phrase asking to display the artifact's output to the user; a demonstration follow-up surface.\"",
  '      word "show the"',
  '        description "English phrase fragment introducing the output to display; a demonstration follow-up surface."',
  '      word "print the"',
  "        description \"English phrase fragment asking to print the artifact's output; a demonstration follow-up surface.\"",
  '    lexeme "ru"',
  '      word "покажи"',
  '        description "Russian imperative verb (romanized pokazhi) meaning show me; a demonstration follow-up surface."',
  '    lexeme "hi"',
  '      word "दिखाओ"',
  '        description "Hindi imperative verb (romanized dikhao) meaning show it; a demonstration follow-up surface."',
  '    lexeme "zh"',
  '      word "显示"',
  '        description "Chinese verb (pinyin xianshi) for displaying or showing; a demonstration follow-up surface."',
  '      word "展示"',
  '        description "Chinese verb (pinyin zhanshi) for demonstrating or exhibiting; a demonstration follow-up surface."',
  '  meaning "output_display_request"',
  "    gloss \"a request to display a specific output, naming what the user wants surfaced after a show-me/print/display verb. Each surface is a prefix carrying the … (U+2026) slot at the end; the clause that follows the slot — up to the first sentence-ending punctuation and capped at twelve words — is the expected output. The opener is matched anywhere in the prompt, not only at the start, so 'test it and show me the result' still captures 'the result'.\"",
  '    wiktionary "display"',
  '    defined_by "software_followup"',
  '    defined_by "action"',
  '    role "output_display_request"',
  '    lexeme "en"',
  '      word "show me …"',
  '        description "English request to display output; the clause naming what to surface follows the … slot."',
  '      word "show …"',
  "        description \"English request to display output written without 'me'; the clause follows the … slot. Declared after 'show me …' so the longer opener is tried first.\"",
  '      word "print …"',
  '        description "English request to print output; the clause naming what to surface follows the … slot."',
  '      word "display …"',
  '        description "English request to display output; the clause naming what to surface follows the … slot."',
  '    lexeme "ru"',
  '      word "покажи мне …"',
  '        description "Russian request to display output (romanized pokazhi mne) meaning show me; the clause follows the … slot."',
  '      word "покажи …"',
  '        description "Russian request to display output (romanized pokazhi) meaning show; the clause follows the … slot."',
  '      word "выведи …"',
  '        description "Russian request to print output (romanized vyvedi) meaning output or print; the clause follows the … slot."',
  '    lexeme "hi"',
  '      word "मुझे दिखाओ …"',
  '        description "Hindi request to display output (romanized mujhe dikhao) meaning show me; the clause follows the … slot."',
  '      word "दिखाओ …"',
  '        description "Hindi request to display output (romanized dikhao) meaning show; the clause follows the … slot."',
  '    lexeme "zh"',
  '      word "给我看…"',
  '        description "Chinese request to display output (pinyin gei wo kan) meaning show me, with no trailing space; the clause follows the … slot."',
  '      word "显示…"',
  '        description "Chinese request to display output (pinyin xianshi) meaning display, with no trailing space; the clause follows the … slot."',
  '  meaning "implement"',
  '    gloss "to author a software artifact by implementing it — an authoring action alongside write/build/create"',
  '    wiktionary "implement"',
  '    defined_by "code"',
  '    defined_by "program"',
  '    role "software_authoring_action"',
  '    lexeme "en"',
  '      word "implement"',
  '        description "English verb for authoring a software artifact by realizing it in code; an authoring-action surface."',
  '    lexeme "ru"',
  '      word "реализуй"',
  '        description "Russian imperative verb (romanized realizuy) meaning implement it; an authoring-action surface."',
  '      word "реализовать"',
  '        description "Russian infinitive verb (romanized realizovat) meaning to implement; the infinitive form of the authoring verb."',
  '    lexeme "hi"',
  '      word "लागू"',
  '        description "Hindi adjective (romanized lagu) meaning applied or implemented; an authoring-action surface."',
  '    lexeme "zh"',
  '      word "实现"',
  '        description "Chinese verb (pinyin shixian) for implementing or realizing; an authoring-action surface."',
  '  meaning "develop"',
  '    gloss "to author a software artifact by developing it over time — an authoring action"',
  '    wiktionary "develop"',
  '    defined_by "program"',
  '    role "software_authoring_action"',
  '    lexeme "en"',
  '      word "develop"',
  '        description "English verb for authoring a software artifact by building it up over time; an authoring-action surface."',
  '    lexeme "ru"',
  '      word "разработай"',
  '        description "Russian imperative verb (romanized razrabotay) meaning develop it; an authoring-action surface."',
  '      word "разработать"',
  '        description "Russian infinitive verb (romanized razrabotat) meaning to develop; the infinitive form of the authoring verb."',
  '    lexeme "hi"',
  '      word "विकसित"',
  '        description "Hindi adjective (romanized vikasit) meaning developed; an authoring-action surface."',
  '    lexeme "zh"',
  '      word "开发"',
  '        description "Chinese verb (pinyin kaifa) for developing software; an authoring-action surface."',
  '  meaning "design"',
  '    gloss "to author a software artifact by designing its shape — an authoring action"',
  '    wiktionary "design"',
  '    defined_by "program"',
  '    role "software_authoring_action"',
  '    lexeme "en"',
  '      word "design"',
  '        description "English verb for authoring a software artifact by shaping its design; an authoring-action surface."',
  '    lexeme "ru"',
  '      word "спроектируй"',
  '        description "Russian imperative verb (romanized sproektiruy) meaning design it; an authoring-action surface."',
  '      word "создай дизайн"',
  '        description "Russian imperative phrase (romanized sozday dizayn) meaning create a design; an authoring-action surface."',
  '    lexeme "hi"',
  '      word "डिज़ाइन"',
  '        description "Hindi noun (romanized dizain, a loanword) for design; an authoring-action surface."',
  '    lexeme "zh"',
  '      word "设计"',
  '        description "Chinese verb (pinyin sheji) for designing; an authoring-action surface."',
  '  meaning "scaffold"',
  '    gloss "to author a software artifact by scaffolding its skeleton — an authoring action"',
  '    wiktionary "scaffold"',
  '    defined_by "code"',
  '    defined_by "program"',
  '    role "software_authoring_action"',
  '    lexeme "en"',
  '      word "scaffold"',
  '        description "English verb for authoring a software artifact by generating its skeleton; an authoring-action surface."',
  '    lexeme "ru"',
  '      word "создай каркас"',
  '        description "Russian imperative phrase (romanized sozday karkas) meaning create a skeleton; an authoring-action surface."',
  '      word "сгенерируй каркас"',
  '        description "Russian imperative phrase (romanized sgeneriruy karkas) meaning generate a skeleton; an authoring-action surface."',
  '    lexeme "hi"',
  '      word "ढाँचा बनाओ"',
  '        description "Hindi imperative phrase (romanized dhancha banao) meaning build a framework; an authoring-action surface."',
  '    lexeme "zh"',
  '      word "搭建"',
  '        description "Chinese verb (pinyin dajian) for setting up or scaffolding a structure; an authoring-action surface."',
  '  meaning "software_artifact"',
  '    gloss "a thing software development produces that an authoring request can ask for — the genus of the artifact kinds below"',
  '    wiktionary "artifact"',
  '    defined_by "artifact_application"',
  '    defined_by "artifact_tool"',
  '    defined_by "entity"',
  '    role "software_artifact"',
  '    lexeme "en"',
  '      word "software artifact"',
  '        description "English noun phrase for a thing software development produces; the genus of the artifact kinds below."',
  '      word "deliverable"',
  '        description "English noun for a produced item to be handed over; a synonym surface for a software artifact."',
  '    lexeme "ru"',
  '      word "программный продукт"',
  '        description "Russian noun phrase (romanized programmnyy produkt) for a software product; the Russian surface for a software artifact."',
  '      word "артефакт"',
  '        description "Russian noun (romanized artefakt) for an artifact; an alternative Russian surface for a software artifact."',
  '    lexeme "hi"',
  '      word "सॉफ़्टवेयर कलाकृति"',
  '        description "Hindi noun phrase (romanized software kalakriti) for a software artifact; the Hindi surface for a produced software item."',
  '    lexeme "zh"',
  '      word "软件制品"',
  '        description "Chinese noun (pinyin ruanjian zhipin) for a software artifact; the Chinese surface for a produced software item."',
  '  meaning "artifact_browser_extension"',
  '    gloss "a browser extension — software that augments a web browser; canonical label `browser extension`"',
  '    wiktionary "extension"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "browser extension"',
  '        description "English noun phrase for software that augments a web browser; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "расширение браузера"',
  '        description "Russian noun phrase (romanized rasshireniye brauzera) for a browser extension; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "ब्राउज़र एक्सटेंशन"',
  '        description "Hindi noun phrase (romanized brauzar extension, a loanword) for a browser extension; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "浏览器扩展"',
  '        description "Chinese noun (pinyin liulanqi kuozhan) for a browser extension; the Chinese surface for this artifact kind."',
  '  meaning "artifact_command_line_tool"',
  '    gloss "a command-line tool driven from a terminal; canonical label `command-line tool`"',
  '    wiktionary "command-line"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "command line tool"',
  '        description "English noun phrase for a tool driven from a terminal; the canonical label for this artifact kind."',
  '      word "cli tool"',
  '        description "English noun phrase abbreviating command-line tool; a synonym surface for this artifact kind."',
  '    lexeme "ru"',
  '      word "консольная утилита"',
  '        description "Russian noun phrase (romanized konsolnaya utilita) for a console utility; the Russian surface for this artifact kind."',
  '      word "утилита командной строки"',
  '        description "Russian noun phrase (romanized utilita komandnoy stroki) for a command-line utility; an alternative Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "कमांड लाइन टूल"',
  '        description "Hindi noun phrase (romanized command line tool, a loanword) for a command-line tool; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "命令行工具"',
  '        description "Chinese noun (pinyin minglinghang gongju) for a command-line tool; the Chinese surface for this artifact kind."',
  '  meaning "artifact_github_action"',
  '    gloss "a GitHub Action automation workflow; canonical label `action`"',
  '    wiktionary "action"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "github action"',
  '        description "English noun phrase for a GitHub Action automation workflow; the canonical surface for this artifact kind."',
  '    lexeme "ru"',
  '      word "действие github"',
  '        description "Russian noun phrase (romanized deystviye github) for a GitHub Action; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "गिटहब एक्शन"',
  '        description "Hindi noun phrase (romanized github action, a loanword) for a GitHub Action; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "github 操作"',
  '        description "Chinese noun (pinyin github caozuo) for a GitHub Action; the Chinese surface for this artifact kind."',
  '  meaning "artifact_mobile_app"',
  '    gloss "a mobile application for phones or tablets; canonical label `mobile app`"',
  '    wiktionary "app"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "mobile app"',
  '        description "English noun phrase for an application for phones or tablets; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "мобильное приложение"',
  '        description "Russian noun phrase (romanized mobilnoye prilozheniye) for a mobile application; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "मोबाइल ऐप"',
  '        description "Hindi noun phrase (romanized mobile app, a loanword) for a mobile application; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "移动应用"',
  '        description "Chinese noun (pinyin yidong yingyong) for a mobile application; the Chinese surface for this artifact kind."',
  '  meaning "artifact_web_app"',
  '    gloss "a web application served in a browser; canonical label `web app`"',
  '    wiktionary "web"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "web app"',
  '        description "English noun phrase for an application served in a browser; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "веб приложение"',
  '        description "Russian noun phrase (romanized veb prilozheniye) for a web application; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "वेब ऐप"',
  '        description "Hindi noun phrase (romanized web app, a loanword) for a web application; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "网页应用"',
  '        description "Chinese noun (pinyin wangye yingyong) for a web application; the Chinese surface for this artifact kind."',
  '  meaning "artifact_application"',
  '    gloss "a general software application; canonical label `application`"',
  '    wiktionary "application"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "application"',
  '        description "English noun for a general software application; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "приложение"',
  '        description "Russian noun (romanized prilozheniye) for an application; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "एप्लिकेशन"',
  '        description "Hindi noun (romanized application, a loanword) for an application; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "应用程序"',
  '        description "Chinese noun (pinyin yingyong chengxu) for an application program; the Chinese surface for this artifact kind."',
  '  meaning "artifact_extension"',
  '    gloss "an extension or add-on that augments a host program; canonical label `extension`"',
  '    wiktionary "extension"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "extension"',
  '        description "English noun for an add-on that augments a host program; the canonical label for this artifact kind."',
  '      word "add on"',
  '        description "English noun for a component that adds to a host program; a synonym surface for an extension."',
  '      word "addon"',
  '        description "English noun (single-word spelling) for an add-on; a synonym surface for an extension."',
  '    lexeme "ru"',
  '      word "расширение"',
  '        description "Russian noun (romanized rasshireniye) for an extension; the Russian surface for this artifact kind."',
  '      word "дополнение"',
  '        description "Russian noun (romanized dopolneniye) for an add-on or supplement; an alternative Russian surface for an extension."',
  '    lexeme "hi"',
  '      word "एक्सटेंशन"',
  '        description "Hindi noun (romanized extension, a loanword) for an extension; the Hindi surface for this artifact kind."',
  '      word "ऐड-ऑन"',
  '        description "Hindi noun (romanized add-on, a loanword) for an add-on; an alternative Hindi surface for an extension."',
  '    lexeme "zh"',
  '      word "扩展"',
  '        description "Chinese noun (pinyin kuozhan) for an extension; the Chinese surface for this artifact kind."',
  '      word "扩展程序"',
  '        description "Chinese noun (pinyin kuozhan chengxu) for an extension program; an alternative Chinese surface for an extension."',
  '  meaning "artifact_dashboard"',
  '    gloss "a dashboard that visualises state at a glance; canonical label `dashboard`"',
  '    wiktionary "dashboard"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "dashboard"',
  '        description "English noun for a screen that visualises state at a glance; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "панель управления"',
  '        description "Russian noun phrase (romanized panel upravleniya) for a control dashboard; the Russian surface for this artifact kind."',
  '      word "дашборд"',
  '        description "Russian noun (romanized dashbord, a loanword) for a dashboard; an alternative Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "डैशबोर्ड"',
  '        description "Hindi noun (romanized dashboard, a loanword) for a dashboard; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "仪表板"',
  '        description "Chinese noun (pinyin yibiaoban) for a dashboard; the Chinese surface for this artifact kind."',
  '  meaning "artifact_scraper"',
  '    gloss "a scraper that extracts data from pages or feeds; canonical label `scraper`"',
  '    wiktionary "scraper"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "scraper"',
  '        description "English noun for a tool that extracts data from pages or feeds; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "скрапер"',
  '        description "Russian noun (romanized skraper, a loanword) for a scraper; the Russian surface for this artifact kind."',
  '      word "парсер"',
  '        description "Russian noun (romanized parser, a loanword) for a parser; an alternative Russian surface for a scraper."',
  '    lexeme "hi"',
  '      word "स्क्रैपर"',
  '        description "Hindi noun (romanized scraper, a loanword) for a scraper; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "爬虫"',
  '        description "Chinese noun (pinyin pachong) for a web crawler or scraper; the Chinese surface for this artifact kind."',
  '  meaning "artifact_library"',
  '    gloss "a reusable code library; canonical label `library`"',
  '    wiktionary "library"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "library"',
  '        description "English noun for a reusable code library; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "библиотека"',
  '        description "Russian noun (romanized biblioteka) for a library; the nominative Russian surface for this artifact kind."',
  '      word "библиотеку"',
  '        description "Russian noun (romanized biblioteku) for a library; the accusative-case form of the library surface."',
  '    lexeme "hi"',
  '      word "लाइब्रेरी"',
  '        description "Hindi noun (romanized library, a loanword) for a code library; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "库"',
  '        description "Chinese noun (pinyin ku) for a code library; the Chinese surface for this artifact kind."',
  '  meaning "artifact_website"',
  '    gloss "a website of linked pages; canonical label `website`"',
  '    wiktionary "website"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "website"',
  '        description "English noun for a site of linked web pages; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "сайт"',
  '        description "Russian noun (romanized sayt) for a website; the Russian surface for this artifact kind."',
  '      word "веб сайт"',
  '        description "Russian noun phrase (romanized veb sayt) for a website; an alternative Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "वेबसाइट"',
  '        description "Hindi noun (romanized website, a loanword) for a website; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "网站"',
  '        description "Chinese noun (pinyin wangzhan) for a website; the Chinese surface for this artifact kind."',
  '  meaning "artifact_plugin"',
  '    gloss "a plugin that extends a host application; canonical label `plugin`"',
  '    wiktionary "plugin"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "plugin"',
  '        description "English noun for a component that extends a host application; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "плагин"',
  '        description "Russian noun (romanized plagin, a loanword) for a plugin; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "प्लगइन"',
  '        description "Hindi noun (romanized plugin, a loanword) for a plugin; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "插件"',
  '        description "Chinese noun (pinyin chajian) for a plugin; the Chinese surface for this artifact kind."',
  '  meaning "artifact_service"',
  '    gloss "a long-running service or daemon; canonical label `service`"',
  '    wiktionary "service"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "service"',
  '        description "English noun for a long-running service or daemon; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "сервис"',
  '        description "Russian noun (romanized servis, a loanword) for a service; the Russian surface for this artifact kind."',
  '      word "служба"',
  '        description "Russian noun (romanized sluzhba) for a service or daemon; the nominative Russian surface for this artifact kind."',
  '      word "службу"',
  '        description "Russian noun (romanized sluzhbu) for a service; the accusative-case form of the service surface."',
  '    lexeme "hi"',
  '      word "सेवा"',
  '        description "Hindi noun (romanized seva) for a service; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "服务"',
  '        description "Chinese noun (pinyin fuwu) for a service; the Chinese surface for this artifact kind."',
  '  meaning "artifact_bot"',
  '    gloss "a bot that automates a chat or task; canonical label `bot`"',
  '    wiktionary "bot"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "bot"',
  '        description "English noun for a program that automates a chat or task; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "бот"',
  '        description "Russian noun (romanized bot, a loanword) for a bot; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "बॉट"',
  '        description "Hindi noun (romanized bot, a loanword) for a bot; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "机器人"',
  '        description "Chinese noun (pinyin jiqiren) literally robot, used for a bot; the Chinese surface for this artifact kind."',
  '  meaning "artifact_app"',
  '    gloss "an app — a generic application; canonical label `app`"',
  '    wiktionary "app"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "app"',
  '        description "English noun abbreviating application; the canonical label for this generic artifact kind."',
  '    lexeme "ru"',
  '      word "приложение"',
  '        description "Russian noun (romanized prilozheniye) for an application; the Russian surface for this generic artifact kind."',
  '    lexeme "hi"',
  '      word "ऐप"',
  '        description "Hindi noun (romanized app, a loanword) for an app; the Hindi surface for this generic artifact kind."',
  '    lexeme "zh"',
  '      word "应用"',
  '        description "Chinese noun (pinyin yingyong) for an application; the Chinese surface for this generic artifact kind."',
  '  meaning "artifact_api"',
  '    gloss "an API — a programmatic interface; canonical label `API`"',
  '    wiktionary "API"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "api"',
  '        description "English noun, the initialism API, for a programmatic interface; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "апи"',
  '        description "Russian noun (romanized api, a loanword) for an API; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "एपीआई"',
  '        description "Hindi noun (romanized api, a loanword) for an API; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "接口"',
  '        description "Chinese noun (pinyin jiekou) for an interface or API; the Chinese surface for this artifact kind."',
  '  meaning "artifact_sdk"',
  '    gloss "an SDK — a software development kit; canonical label `SDK`"',
  '    wiktionary "SDK"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "sdk"',
  '        description "English noun, the initialism SDK, for a software development kit; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "сдк"',
  '        description "Russian noun (romanized sdk, a loanword) for an SDK; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "एसडीके"',
  '        description "Hindi noun (romanized sdk, a loanword) for an SDK; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "开发包"',
  '        description "Chinese noun (pinyin kaifabao) for a development kit; the Chinese surface for this artifact kind."',
  '  meaning "artifact_tool"',
  '    gloss "a general tool or utility; canonical label `tool`"',
  '    wiktionary "tool"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "tool"',
  '        description "English noun for a general tool or utility; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "инструмент"',
  '        description "Russian noun (romanized instrument) for a tool; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "टूल"',
  '        description "Hindi noun (romanized tool, a loanword) for a tool; the Hindi surface for this artifact kind."',
  '      word "उपकरण"',
  '        description "Hindi noun (romanized upakaran) for an instrument or utility; an alternative Hindi surface for a tool."',
  '    lexeme "zh"',
  '      word "工具"',
  '        description "Chinese noun (pinyin gongju) for a tool; the Chinese surface for this artifact kind."',
  '  meaning "artifact_mod"',
  '    gloss "a mod that alters a game or program; canonical label `mod`"',
  '    wiktionary "mod"',
  '    defined_by "software_artifact"',
  '    role "software_artifact_kind"',
  '    lexeme "en"',
  '      word "mod"',
  '        description "English noun for a modification that alters a game or program; the canonical label for this artifact kind."',
  '    lexeme "ru"',
  '      word "мод"',
  '        description "Russian noun (romanized mod, a loanword) for a game modification; the Russian surface for this artifact kind."',
  '    lexeme "hi"',
  '      word "मॉड"',
  '        description "Hindi noun (romanized mod, a loanword) for a game modification; the Hindi surface for this artifact kind."',
  '    lexeme "zh"',
  '      word "模组"',
  '        description "Chinese noun (pinyin mozu) for a game mod; the Chinese surface for this artifact kind."',
  '  meaning "software_feature"',
  '    gloss "a capability a software request asks the artifact to have — the genus of the requirement categories below; a clause naming one is a feature requirement, and the category it names classifies the resulting subtask"',
  '    wiktionary "feature"',
  '    defined_by "requirement_state_tracking"',
  '    defined_by "requirement_project_behavior"',
  '    defined_by "property"',
  '    role "software_feature"',
  '    lexeme "en"',
  '      word "feature"',
  '        description "English noun for a capability a request asks the artifact to have; the genus of the requirement categories below."',
  '      word "features"',
  '        description "English noun, the plural of feature, for capabilities a request asks for; a plural surface of the feature concept."',
  '      word "requirement"',
  '        description "English noun for a stated capability the artifact must satisfy; a synonym surface for a feature."',
  '      word "requirements"',
  '        description "English noun, the plural of requirement, for stated capabilities; a plural synonym surface for features."',
  '    lexeme "ru"',
  '      word "функция"',
  '        description "Russian noun (romanized funktsiya) for a feature or function; the Russian surface for the feature concept."',
  '      word "требование"',
  '        description "Russian noun (romanized trebovaniye) for a requirement; an alternative Russian surface for a feature."',
  '    lexeme "hi"',
  '      word "सुविधा"',
  '        description "Hindi noun (romanized suvidha) for a feature or facility; the Hindi surface for the feature concept."',
  '      word "आवश्यकता"',
  '        description "Hindi noun (romanized avashyakta) for a requirement or necessity; an alternative Hindi surface for a feature."',
  '    lexeme "zh"',
  '      word "功能"',
  '        description "Chinese noun (pinyin gongneng) for a feature or function; the Chinese surface for the feature concept."',
  '      word "需求"',
  '        description "Chinese noun (pinyin xuqiu) for a requirement or demand; an alternative Chinese surface for a feature."',
  '  meaning "requirement_state_tracking"',
  '    gloss "a feature that tracks evolving state — counters, status, damage, cooldowns; canonical category `state_tracking`"',
  '    wiktionary "state"',
  '    defined_by "software_feature"',
  '    role "software_requirement_category"',
  '    lexeme "en"',
  '      word "track"',
  '        description "English verb for following evolving state over time; a state-tracking requirement cue."',
  '      word "hp"',
  '        description "English noun, the initialism for hit points, a tracked combat counter; a state-tracking requirement cue."',
  '      word "status"',
  '        description "English noun for a tracked condition or state; a state-tracking requirement cue."',
  '      word "damage"',
  '        description "English noun for tracked harm applied to a unit; a state-tracking requirement cue."',
  '      word "cooldown"',
  '        description "English noun for a tracked recharge timer between uses; a state-tracking requirement cue."',
  '    lexeme "ru"',
  '      word "состояние"',
  '        description "Russian noun (romanized sostoyaniye) for state or condition; a state-tracking requirement cue."',
  '      word "урон"',
  '        description "Russian noun (romanized uron) for damage; a state-tracking requirement cue."',
  '      word "откат"',
  '        description "Russian noun (romanized otkat) for a cooldown; a state-tracking requirement cue."',
  '    lexeme "hi"',
  '      word "स्थिति"',
  '        description "Hindi noun (romanized sthiti) for state or status; a state-tracking requirement cue."',
  '      word "क्षति"',
  '        description "Hindi noun (romanized kshati) for damage or harm; a state-tracking requirement cue."',
  '    lexeme "zh"',
  '      word "状态"',
  '        description "Chinese noun (pinyin zhuangtai) for state or status; a state-tracking requirement cue."',
  '      word "伤害"',
  '        description "Chinese noun (pinyin shanghai) for damage; a state-tracking requirement cue."',
  '      word "冷却"',
  '        description "Chinese noun (pinyin lengque) for a cooldown; a state-tracking requirement cue."',
  '  meaning "requirement_data_exchange"',
  '    gloss "a feature that moves data in or out — import, export, backups, reports; canonical category `data_exchange`"',
  '    wiktionary "data"',
  '    defined_by "software_feature"',
  '    role "software_requirement_category"',
  '    lexeme "en"',
  '      word "import"',
  '        description "English noun or verb for bringing data in; a data-exchange requirement cue."',
  '      word "export"',
  '        description "English noun or verb for sending data out; a data-exchange requirement cue."',
  '      word "csv"',
  '        description "English noun, the initialism for comma-separated values, a data-exchange file format; a data-exchange requirement cue."',
  '      word "backup"',
  '        description "English noun for a saved copy of data; a data-exchange requirement cue."',
  '      word "report"',
  '        description "English noun for a generated data summary; a data-exchange requirement cue."',
  '      word "calendar"',
  '        description "English noun for exported or imported schedule data; a data-exchange requirement cue."',
  '    lexeme "ru"',
  '      word "импорт"',
  '        description "Russian noun (romanized import) for importing data; a data-exchange requirement cue."',
  '      word "экспорт"',
  '        description "Russian noun (romanized eksport) for exporting data; a data-exchange requirement cue."',
  '      word "резервная копия"',
  '        description "Russian noun phrase (romanized rezervnaya kopiya) for a backup copy; a data-exchange requirement cue."',
  '      word "отчёт"',
  '        description "Russian noun (romanized otchyot) for a report; a data-exchange requirement cue."',
  '    lexeme "hi"',
  '      word "आयात"',
  '        description "Hindi noun (romanized aayat) for import; a data-exchange requirement cue."',
  '      word "निर्यात"',
  '        description "Hindi noun (romanized niryat) for export; a data-exchange requirement cue."',
  '      word "रिपोर्ट"',
  '        description "Hindi noun (romanized report, a loanword) for a report; a data-exchange requirement cue."',
  '    lexeme "zh"',
  '      word "导入"',
  '        description "Chinese verb (pinyin daoru) for importing data; a data-exchange requirement cue."',
  '      word "导出"',
  '        description "Chinese verb (pinyin daochu) for exporting data; a data-exchange requirement cue."',
  '      word "备份"',
  '        description "Chinese noun (pinyin beifen) for a backup; a data-exchange requirement cue."',
  '      word "报告"',
  '        description "Chinese noun (pinyin baogao) for a report; a data-exchange requirement cue."',
  '  meaning "requirement_automation"',
  '    gloss "a feature that runs on a schedule or trigger — reminders, notifications, jobs; canonical category `automation`"',
  '    wiktionary "automation"',
  '    defined_by "software_feature"',
  '    role "software_requirement_category"',
  '    lexeme "en"',
  '      word "reminder"',
  '        description "English noun for a scheduled prompt to the user; an automation requirement cue."',
  '      word "notification"',
  '        description "English noun for a triggered alert message; an automation requirement cue."',
  '      word "schedule"',
  '        description "English noun or verb for timing recurring work; an automation requirement cue."',
  '      word "weekly"',
  '        description "English adjective for a once-a-week recurrence; an automation requirement cue."',
  '    lexeme "ru"',
  '      word "напоминание"',
  '        description "Russian noun (romanized napominaniye) for a reminder; an automation requirement cue."',
  '      word "уведомление"',
  '        description "Russian noun (romanized uvedomleniye) for a notification; an automation requirement cue."',
  '      word "расписание"',
  '        description "Russian noun (romanized raspisaniye) for a schedule; an automation requirement cue."',
  '    lexeme "hi"',
  '      word "अनुस्मारक"',
  '        description "Hindi noun (romanized anusmarak) for a reminder; an automation requirement cue."',
  '      word "सूचना"',
  '        description "Hindi noun (romanized soochna) for a notification; an automation requirement cue."',
  '    lexeme "zh"',
  '      word "提醒"',
  '        description "Chinese noun or verb (pinyin tixing) for a reminder; an automation requirement cue."',
  '      word "通知"',
  '        description "Chinese noun (pinyin tongzhi) for a notification; an automation requirement cue."',
  '      word "计划"',
  '        description "Chinese noun (pinyin jihua) for a plan or schedule; an automation requirement cue."',
  '  meaning "requirement_validation"',
  '    gloss "a feature that validates input or invariants — checks, conflicts, audits; canonical category `validation`"',
  '    wiktionary "validation"',
  '    defined_by "software_feature"',
  '    role "software_requirement_category"',
  '    lexeme "en"',
  '      word "validate"',
  '        description "English verb for checking input or invariants for correctness; a validation requirement cue."',
  '      word "check"',
  '        description "English verb for inspecting input against a rule; a validation requirement cue."',
  '      word "conflict"',
  '        description "English noun for a clash between values that validation must catch; a validation requirement cue."',
  '      word "audit"',
  '        description "English noun for a systematic correctness review; a validation requirement cue."',
  '    lexeme "ru"',
  '      word "проверка"',
  '        description "Russian noun (romanized proverka) for a check or validation; a validation requirement cue."',
  '      word "проверь"',
  '        description "Russian imperative verb (romanized prover) meaning check or validate; a validation requirement cue."',
  '      word "аудит"',
  '        description "Russian noun (romanized audit, a loanword) for an audit; a validation requirement cue."',
  '    lexeme "hi"',
  '      word "सत्यापन"',
  '        description "Hindi noun (romanized satyapan) for verification or validation; a validation requirement cue."',
  '      word "जाँच"',
  '        description "Hindi noun (romanized janch) for a check or inspection; a validation requirement cue."',
  '    lexeme "zh"',
  '      word "验证"',
  '        description "Chinese verb (pinyin yanzheng) for validating or verifying; a validation requirement cue."',
  '      word "检查"',
  '        description "Chinese verb (pinyin jiancha) for checking; a validation requirement cue."',
  '      word "审计"',
  '        description "Chinese noun (pinyin shenji) for an audit; a validation requirement cue."',
  '  meaning "requirement_integration"',
  '    gloss "a feature that integrates with an external host — an API or third-party service; canonical category `integration`"',
  '    wiktionary "integration"',
  '    defined_by "software_feature"',
  '    role "software_requirement_category"',
  '    lexeme "en"',
  '      word "api"',
  '        description "English noun, the initialism API, for a programmatic interface to integrate with; an integration requirement cue."',
  '      word "discord"',
  '        description "English proper noun for the Discord chat platform to integrate with; an integration requirement cue."',
  '      word "telegram"',
  '        description "English proper noun for the Telegram messaging platform to integrate with; an integration requirement cue."',
  '      word "github"',
  '        description "English proper noun for the GitHub platform to integrate with; an integration requirement cue."',
  '      word "browser"',
  '        description "English noun for a web browser host to integrate with; an integration requirement cue."',
  '    lexeme "ru"',
  '      word "интеграция"',
  '        description "Russian noun (romanized integratsiya) for integration; an integration requirement cue."',
  '      word "апи"',
  '        description "Russian noun (romanized api, a loanword) for an API; an integration requirement cue."',
  '      word "браузер"',
  '        description "Russian noun (romanized brauzer, a loanword) for a browser; an integration requirement cue."',
  '    lexeme "hi"',
  '      word "एकीकरण"',
  '        description "Hindi noun (romanized ekikaran) for integration; an integration requirement cue."',
  '      word "एपीआई"',
  '        description "Hindi noun (romanized api, a loanword) for an API; an integration requirement cue."',
  '    lexeme "zh"',
  '      word "集成"',
  '        description "Chinese noun (pinyin jicheng) for integration; an integration requirement cue."',
  '      word "接口"',
  '        description "Chinese noun (pinyin jiekou) for an interface or API; an integration requirement cue."',
  '      word "浏览器"',
  '        description "Chinese noun (pinyin liulanqi) for a browser; an integration requirement cue."',
  '  meaning "requirement_user_interface"',
  '    gloss "a feature that presents state to a person — dashboards, charts, filters; canonical category `user_interface`"',
  '    wiktionary "interface"',
  '    defined_by "software_feature"',
  '    role "software_requirement_category"',
  '    lexeme "en"',
  '      word "dashboard"',
  '        description "English noun for a screen presenting state at a glance; a user-interface requirement cue."',
  '      word "chart"',
  '        description "English noun for a graphical plot of data; a user-interface requirement cue."',
  '      word "filter"',
  '        description "English noun for a control that narrows what is shown; a user-interface requirement cue."',
  '      word "progress"',
  '        description "English noun for a visual progress indicator; a user-interface requirement cue."',
  '    lexeme "ru"',
  '      word "панель"',
  '        description "Russian noun (romanized panel) for a panel or dashboard; a user-interface requirement cue."',
  '      word "график"',
  '        description "Russian noun (romanized grafik) for a chart or graph; a user-interface requirement cue."',
  '      word "фильтр"',
  '        description "Russian noun (romanized filtr) for a filter; a user-interface requirement cue."',
  '    lexeme "hi"',
  '      word "डैशबोर्ड"',
  '        description "Hindi noun (romanized dashboard, a loanword) for a dashboard; a user-interface requirement cue."',
  '      word "चार्ट"',
  '        description "Hindi noun (romanized chart, a loanword) for a chart; a user-interface requirement cue."',
  '    lexeme "zh"',
  '      word "仪表板"',
  '        description "Chinese noun (pinyin yibiaoban) for a dashboard; a user-interface requirement cue."',
  '      word "图表"',
  '        description "Chinese noun (pinyin tubiao) for a chart or graph; a user-interface requirement cue."',
  '      word "筛选"',
  '        description "Chinese verb (pinyin shaixuan) for filtering or screening; a user-interface requirement cue."',
  '  meaning "requirement_project_behavior"',
  '    gloss "a feature that adds general project behavior not covered by a more specific category — the catch-all classified last; canonical category `project_behavior`"',
  '    wiktionary "behavior"',
  '    defined_by "software_feature"',
  '    role "software_requirement_category"',
  '    lexeme "en"',
  '      word "add"',
  '        description "English verb for introducing general new behavior; a catch-all project-behavior cue."',
  '      word "admin"',
  '        description "English noun for administrative functionality; a catch-all project-behavior cue."',
  '      word "customer"',
  '        description "English noun for customer-related functionality; a catch-all project-behavior cue."',
  '      word "date"',
  '        description "English noun for date-handling functionality; a catch-all project-behavior cue."',
  '      word "email"',
  '        description "English noun for email-related functionality; a catch-all project-behavior cue."',
  '      word "expense"',
  '        description "English noun for expense-tracking functionality; a catch-all project-behavior cue."',
  '      word "file"',
  '        description "English noun for file-handling functionality; a catch-all project-behavior cue."',
  '      word "history"',
  '        description "English noun for history or audit-trail functionality; a catch-all project-behavior cue."',
  '      word "invoice"',
  '        description "English noun for invoicing functionality; a catch-all project-behavior cue."',
  '      word "log"',
  '        description "English noun for logging functionality; a catch-all project-behavior cue."',
  '      word "maintenance"',
  '        description "English noun for maintenance functionality; a catch-all project-behavior cue."',
  '      word "payment"',
  '        description "English noun for payment-handling functionality; a catch-all project-behavior cue."',
  '      word "protection"',
  '        description "English noun for protective functionality; a catch-all project-behavior cue."',
  '      word "record"',
  '        description "English noun for record-keeping functionality; a catch-all project-behavior cue."',
  '      word "rename"',
  '        description "English verb for renaming functionality; a catch-all project-behavior cue."',
  '      word "resistance"',
  '        description "English noun for resistance-related functionality; a catch-all project-behavior cue."',
  '      word "retry"',
  '        description "English verb for retry functionality; a catch-all project-behavior cue."',
  '      word "scrape"',
  '        description "English verb for scraping functionality; a catch-all project-behavior cue."',
  '      word "stack"',
  '        description "English noun for stack-related functionality; a catch-all project-behavior cue."',
  '      word "sync"',
  '        description "English verb for synchronization functionality; a catch-all project-behavior cue."',
  '      word "tracking"',
  '        description "English noun for general tracking functionality; a catch-all project-behavior cue."',
  '      word "upload"',
  '        description "English verb for upload functionality; a catch-all project-behavior cue."',
  '    lexeme "ru"',
  '      word "добавить"',
  '        description "Russian infinitive verb (romanized dobavit) meaning to add; a catch-all project-behavior cue."',
  '      word "клиент"',
  '        description "Russian noun (romanized klient) for a customer or client; a catch-all project-behavior cue."',
  '      word "файл"',
  '        description "Russian noun (romanized fayl) for a file; a catch-all project-behavior cue."',
  '      word "загрузка"',
  '        description "Russian noun (romanized zagruzka) for an upload or download; a catch-all project-behavior cue."',
  '    lexeme "hi"',
  '      word "जोड़ें"',
  '        description "Hindi imperative verb (romanized joden) meaning add; a catch-all project-behavior cue."',
  '      word "फ़ाइल"',
  '        description "Hindi noun (romanized file, a loanword) for a file; a catch-all project-behavior cue."',
  '    lexeme "zh"',
  '      word "添加"',
  '        description "Chinese verb (pinyin tianjia) for adding; a catch-all project-behavior cue."',
  '      word "文件"',
  '        description "Chinese noun (pinyin wenjian) for a file; a catch-all project-behavior cue."',
  '      word "上传"',
  '        description "Chinese verb (pinyin shangchuan) for uploading; a catch-all project-behavior cue."',
  '  meaning "software_delivery"',
  '    gloss "how the assistant should deliver a software solution — the genus of the delivery modes below; the default is generated code, the others are selected only when their mode is evidenced in the request"',
  '    wiktionary "delivery"',
  '    defined_by "software_artifact"',
  '    defined_by "delivery_manual_instructions"',
  '    role "software_delivery"',
  '    lexeme "en"',
  '      word "delivery"',
  '        description "English noun for how a software solution is handed over; the genus of the delivery modes below."',
  '    lexeme "ru"',
  '      word "доставка"',
  '        description "Russian noun (romanized dostavka) for delivery; the Russian surface for the delivery concept."',
  '    lexeme "hi"',
  '      word "वितरण"',
  '        description "Hindi noun (romanized vitaran) for delivery or distribution; the Hindi surface for the delivery concept."',
  '    lexeme "zh"',
  '      word "交付"',
  '        description "Chinese noun or verb (pinyin jiaofu) for delivery or handover; the Chinese surface for the delivery concept."',
  '  meaning "delivery_manual_instructions"',
  '    gloss "deliver step-by-step manual instructions for a person to follow instead of writing code; canonical mode `manual_instructions`"',
  '    wiktionary "instruction"',
  '    defined_by "software_delivery"',
  '    role "software_delivery_mode"',
  '    lexeme "en"',
  '      word "manual instruction"',
  '        description "English noun phrase for a single step-by-step instruction for a person; a manual-instructions delivery cue."',
  '      word "manual instructions"',
  '        description "English noun phrase, plural, for step-by-step instructions for a person to follow; the canonical manual-instructions delivery cue."',
  '      word "instruction"',
  '        description "English noun for a directive to follow; a manual-instructions delivery cue."',
  '      word "instructions"',
  '        description "English noun, the plural of instruction, for a set of directives; a manual-instructions delivery cue."',
  '      word "no code"',
  '        description "English phrase signalling delivery without writing source; a manual-instructions delivery cue."',
  '    lexeme "ru"',
  '      word "инструкция"',
  '        description "Russian noun (romanized instruktsiya) for an instruction; a manual-instructions delivery cue."',
  '      word "инструкции"',
  '        description "Russian noun (romanized instruktsii) for instructions; the plural form of the instruction surface."',
  '      word "вручную"',
  '        description "Russian adverb (romanized vruchnuyu) meaning manually or by hand; a manual-instructions delivery cue."',
  '    lexeme "hi"',
  '      word "निर्देश"',
  '        description "Hindi noun (romanized nirdesh) for an instruction or directive; a manual-instructions delivery cue."',
  '      word "मैनुअल"',
  '        description "Hindi adjective (romanized manual, a loanword) meaning manual; a manual-instructions delivery cue."',
  '    lexeme "zh"',
  '      word "手动说明"',
  '        description "Chinese noun phrase (pinyin shoudong shuoming) for manual instructions; the canonical manual-instructions delivery cue."',
  '      word "说明"',
  '        description "Chinese noun (pinyin shuoming) for an explanation or instructions; a manual-instructions delivery cue."',
  '  meaning "delivery_immediate_execution"',
  '    gloss "build the solution and run it immediately in the sandbox (WebVM) rather than handing back source; canonical mode `immediate_execution`"',
  '    wiktionary "execute"',
  '    defined_by "software_delivery"',
  '    role "software_delivery_mode"',
  '    lexeme "en"',
  '      word "execute"',
  '        description "English verb for running the built solution immediately; an immediate-execution delivery cue."',
  '      word "run command"',
  '        description "English noun phrase for a command to run immediately; an immediate-execution delivery cue."',
  '      word "run commands"',
  '        description "English noun phrase, plural, for commands to run immediately; an immediate-execution delivery cue."',
  '      word "run it"',
  '        description "English imperative phrase asking to run the solution immediately; an immediate-execution delivery cue."',
  '      word "webvm"',
  '        description "English proper noun for the WebVM in-browser sandbox where the solution runs; an immediate-execution delivery cue."',
  '    lexeme "ru"',
  '      word "выполни"',
  '        description "Russian imperative verb (romanized vypolni) meaning execute or carry out; an immediate-execution delivery cue."',
  '      word "запусти команду"',
  '        description "Russian imperative phrase (romanized zapusti komandu) meaning run a command; an immediate-execution delivery cue."',
  '    lexeme "hi"',
  '      word "निष्पादित करें"',
  '        description "Hindi imperative phrase (romanized nishpadit karen) meaning execute it; an immediate-execution delivery cue."',
  '      word "चलाएँ"',
  '        description "Hindi imperative verb (romanized chalaen) meaning run it; an immediate-execution delivery cue."',
  '    lexeme "zh"',
  '      word "立即运行"',
  '        description "Chinese phrase (pinyin liji yunxing) meaning run immediately; an immediate-execution delivery cue."',
  '      word "执行"',
  '        description "Chinese verb (pinyin zhixing) for executing; an immediate-execution delivery cue."',
  '  meaning "delivery_script_generation"',
  '    gloss "deliver an executable shell script or set of commands rather than application source; canonical mode `script_generation`"',
  '    wiktionary "script"',
  '    defined_by "software_delivery"',
  '    role "software_delivery_mode"',
  '    lexeme "en"',
  '      word "bash"',
  '        description "English proper noun for the Bash shell whose script is delivered; a script-generation delivery cue."',
  '      word "shell"',
  '        description "English noun for a command-line shell whose script is delivered; a script-generation delivery cue."',
  '      word "script"',
  '        description "English noun for an executable script delivered instead of application source; the canonical script-generation delivery cue."',
  '      word "scripts"',
  '        description "English noun, the plural of script, for executable scripts; a script-generation delivery cue."',
  '      word "commands"',
  '        description "English noun for a set of shell commands delivered to run; a script-generation delivery cue."',
  '    lexeme "ru"',
  '      word "скрипт"',
  '        description "Russian noun (romanized skript, a loanword) for a script; a script-generation delivery cue."',
  '      word "оболочка"',
  '        description "Russian noun (romanized obolochka) for a shell; a script-generation delivery cue."',
  '      word "команды"',
  '        description "Russian noun (romanized komandy) for commands; a script-generation delivery cue."',
  '    lexeme "hi"',
  '      word "स्क्रिप्ट"',
  '        description "Hindi noun (romanized script, a loanword) for a script; a script-generation delivery cue."',
  '      word "शेल"',
  '        description "Hindi noun (romanized shell, a loanword) for a shell; a script-generation delivery cue."',
  '    lexeme "zh"',
  '      word "脚本"',
  '        description "Chinese noun (pinyin jiaoben) for a script; the canonical script-generation delivery cue."',
  '      word "外壳脚本"',
  '        description "Chinese noun phrase (pinyin waike jiaoben) for a shell script; a script-generation delivery cue."',
  '  meaning "software_language"',
  '    gloss "the programming language a software implementation targets — the genus of the languages below; the default is TypeScript, the others are selected when the language is named in the request"',
  '    wiktionary "programming language"',
  '    defined_by "software_artifact"',
  '    defined_by "language_python"',
  '    role "software_language"',
  '    lexeme "en"',
  '      word "programming language"',
  '        description "English noun phrase for the language a software implementation targets; the genus of the languages below."',
  '    lexeme "ru"',
  '      word "язык программирования"',
  '        description "Russian noun phrase (romanized yazyk programmirovaniya) for a programming language; the Russian surface for this genus."',
  '    lexeme "hi"',
  '      word "प्रोग्रामिंग भाषा"',
  '        description "Hindi noun phrase (romanized programming bhasha) for a programming language; the Hindi surface for this genus."',
  '    lexeme "zh"',
  '      word "编程语言"',
  '        description "Chinese noun (pinyin biancheng yuyan) for a programming language; the Chinese surface for this genus."',
  '  meaning "language_python"',
  '    gloss "the Python programming language and its web frameworks (Django, FastAPI); canonical target `python`"',
  '    wiktionary "Python"',
  '    defined_by "software_language"',
  '    role "software_implementation_language"',
  '    lexeme "en"',
  '      word "python"',
  '        description "English proper noun for the Python programming language; the canonical target for this implementation language."',
  '      word "django"',
  '        description "English proper noun for Django, a Python web framework; a surface evidencing the Python target."',
  '      word "fastapi"',
  '        description "English proper noun for FastAPI, a Python web framework; a surface evidencing the Python target."',
  '    lexeme "ru"',
  '      word "питон"',
  '        description "Russian noun (romanized piton) for Python; the Russian surface for the Python target."',
  '      word "пайтон"',
  '        description "Russian noun (romanized payton) for Python; an alternative Russian transliteration of the Python target."',
  '    lexeme "hi"',
  '      word "पायथन"',
  '        description "Hindi noun (romanized python, a loanword) for the Python language; the Hindi surface for the Python target."',
  '    lexeme "zh"',
  '      word "python"',
  '        description "The Latin-script name Python used in Chinese text for the Python language; the Chinese surface for the Python target."',
  '  meaning "language_rust"',
  '    gloss "the Rust programming language and its Cargo toolchain; canonical target `rust`"',
  '    wiktionary "Rust"',
  '    defined_by "software_language"',
  '    role "software_implementation_language"',
  '    lexeme "en"',
  '      word "rust"',
  '        description "English proper noun for the Rust programming language; the canonical target for this implementation language."',
  '      word "cargo"',
  '        description "English proper noun for Cargo, the Rust build tool and package manager; a surface evidencing the Rust target."',
  '    lexeme "ru"',
  '      word "раст"',
  '        description "Russian noun (romanized rast) for the Rust language; the Russian surface for the Rust target."',
  '    lexeme "hi"',
  '      word "रस्ट"',
  '        description "Hindi noun (romanized rust, a loanword) for the Rust language; the Hindi surface for the Rust target."',
  '    lexeme "zh"',
  '      word "rust"',
  '        description "The Latin-script name Rust used in Chinese text for the Rust language; the Chinese surface for the Rust target."',
  '  meaning "language_javascript"',
  '    gloss "the JavaScript programming language and its Node.js runtime; canonical target `javascript`"',
  '    wiktionary "JavaScript"',
  '    defined_by "software_language"',
  '    role "software_implementation_language"',
  '    lexeme "en"',
  '      word "javascript"',
  '        description "English proper noun for the JavaScript programming language; the canonical target for this implementation language."',
  '      word "node"',
  '        description "English proper noun for Node.js, the JavaScript runtime; a surface evidencing the JavaScript target."',
  '    lexeme "ru"',
  '      word "джаваскрипт"',
  '        description "Russian noun (romanized dzhavaskript) for JavaScript; the Russian surface for the JavaScript target."',
  '    lexeme "hi"',
  '      word "जावास्क्रिप्ट"',
  '        description "Hindi noun (romanized javascript, a loanword) for the JavaScript language; the Hindi surface for the JavaScript target."',
  '    lexeme "zh"',
  '      word "javascript"',
  '        description "The Latin-script name JavaScript used in Chinese text for the JavaScript language; the Chinese surface for the JavaScript target."',
  '  meaning "implementation_language_preposition"',
  "    gloss \"the function word that marks which programming language an implementation should target — 'write a program in Rust', 'на Python'; the unknown-language extractor reads the language name that follows it. Head-initial English/Russian place the name after the marker (the only direction the positional extractor consults); the head-final Hindi/Chinese forms are described for completeness.\"",
  '    wiktionary "in"',
  '    defined_by "software_language"',
  '    role "implementation_language_preposition"',
  '    lexeme "en"',
  '      word "in"',
  "        description \"English preposition marking the target programming language, as in 'write it in <language>'; the language name follows it.\"",
  '    lexeme "ru"',
  '      word "на"',
  "        description \"Russian preposition (romanized na) marking the target programming language, as in 'на <language>'; the language name follows it.\"",
  '    lexeme "hi"',
  '      word "में"',
  "        description \"Hindi postposition (romanized mein) marking the target programming language; head-final Hindi places the language name before it ('<language> में').\"",
  '    lexeme "zh"',
  '      word "用"',
  "        description \"Chinese coverb (pinyin yong, 'using') marking the target programming language, as in '用 <language> 写'; the language name follows it.\"",
  '  meaning "implementation_language_noun"',
  "    gloss \"the head noun 'language' that may sit between the target preposition and the language name — 'in the language Brainfuck', 'на языке Brainfuck'; when present the unknown-language extractor skips it to read the name that follows.\"",
  '    wiktionary "language"',
  '    defined_by "software_language"',
  '    role "implementation_language_noun"',
  '    lexeme "en"',
  '      word "language"',
  '        description "English noun naming the programming-language slot; when it follows the target preposition the language name comes after it."',
  '    lexeme "ru"',
  '      word "языке"',
  '        description "Russian noun (romanized yazyke, the prepositional case of yazyk) naming the programming-language slot; the language name follows it."',
  '    lexeme "hi"',
  '      word "भाषा"',
  '        description "Hindi noun (romanized bhasha) naming the programming-language slot; the language name accompanies it."',
  '    lexeme "zh"',
  '      word "语言"',
  '        description "Chinese noun (pinyin yuyan) naming the programming-language slot; the language name accompanies it."',
  '  meaning "tabletop_game_tracker"',
  "    gloss \"a request to track a tabletop/RPG game piece's combat state — the genus pairing a game domain with a combat mechanic; only when both appear is it a game-unit tracker (which forces state_tracking subtasks and a damage-mitigation surface)\"",
  '    wiktionary "tabletop game"',
  '    defined_by "game_tracker_domain"',
  '    defined_by "game_tracker_mechanic"',
  '    role "tabletop_game_tracker"',
  '    lexeme "en"',
  '      word "tabletop game tracker"',
  "        description \"English noun phrase for a request to track a tabletop game piece's combat state; the genus pairing a game domain with a combat mechanic.\"",
  '    lexeme "ru"',
  '      word "трекер настольной игры"',
  '        description "Russian noun phrase (romanized treker nastolnoy igry) for a tabletop game tracker; the Russian surface for this genus."',
  '    lexeme "hi"',
  '      word "टेबलटॉप गेम ट्रैकर"',
  '        description "Hindi noun phrase (romanized tabletop game tracker, a loanword) for a tabletop game tracker; the Hindi surface for this genus."',
  '    lexeme "zh"',
  '      word "桌游追踪器"',
  '        description "Chinese noun (pinyin zhuoyou zhuizongqi) for a tabletop-game tracker; the Chinese surface for this genus."',
  '  meaning "game_tracker_domain"',
  '    gloss "a tabletop/RPG game domain whose pieces carry combat state — a D&D unit, a token, a wargame piece, an Owlbear scene"',
  '    wiktionary "tabletop game"',
  '    defined_by "tabletop_game_tracker"',
  '    role "game_tracker_domain"',
  '    lexeme "en"',
  '      word "dnd"',
  '        description "English proper noun, the abbreviation for Dungeons and Dragons, a tabletop RPG domain; a game-tracker domain cue."',
  '      word "wargame"',
  '        description "English noun for a tabletop war game whose pieces carry combat state; a game-tracker domain cue."',
  '      word "tabletop"',
  '        description "English noun for a tabletop game domain; a game-tracker domain cue."',
  '      word "unit"',
  '        description "English noun for a game piece or unit carrying combat state; a game-tracker domain cue."',
  '      word "token"',
  '        description "English noun for a playing token representing a piece; a game-tracker domain cue."',
  '      word "owlbear"',
  '        description "English proper noun for Owlbear Rodeo, a virtual tabletop scene tool; a game-tracker domain cue."',
  '    lexeme "ru"',
  '      word "настольная игра"',
  '        description "Russian noun phrase (romanized nastolnaya igra) for a tabletop game; a game-tracker domain cue."',
  '      word "фишка"',
  '        description "Russian noun (romanized fishka) for a game token or chip; a game-tracker domain cue."',
  '      word "жетон"',
  '        description "Russian noun (romanized zheton) for a token; a game-tracker domain cue."',
  '    lexeme "hi"',
  '      word "टेबलटॉप"',
  '        description "Hindi noun (romanized tabletop, a loanword) for a tabletop game; a game-tracker domain cue."',
  '      word "मोहरा"',
  '        description "Hindi noun (romanized mohra) for a game piece or pawn; a game-tracker domain cue."',
  '    lexeme "zh"',
  '      word "桌游"',
  '        description "Chinese noun (pinyin zhuoyou) for a tabletop game; a game-tracker domain cue."',
  '      word "棋子"',
  '        description "Chinese noun (pinyin qizi) for a game piece; a game-tracker domain cue."',
  '      word "战棋"',
  '        description "Chinese noun (pinyin zhanqi) for a tactical war game; a game-tracker domain cue."',
  '  meaning "game_tracker_mechanic"',
  '    gloss "a combat mechanic a tabletop tracker follows — hit points, damage, protection, resistance, cooldowns; shares ground with the state_tracking requirement"',
  '    wiktionary "hit points"',
  '    defined_by "tabletop_game_tracker"',
  '    defined_by "requirement_state_tracking"',
  '    role "game_tracker_mechanic"',
  '    lexeme "en"',
  '      word "hp"',
  '        description "English noun, the initialism for hit points, a tracked combat health value; a game-tracker mechanic cue."',
  '      word "damage"',
  '        description "English noun for harm a tracker subtracts from health; a game-tracker mechanic cue."',
  '      word "protection"',
  '        description "English noun for a defensive buffer the tracker accounts for; a game-tracker mechanic cue."',
  '      word "resistance"',
  '        description "English noun for damage reduction the tracker applies; a game-tracker mechanic cue."',
  '      word "cooldown"',
  '        description "English noun for a recharge timer between ability uses; a game-tracker mechanic cue."',
  '      word "cooldowns"',
  '        description "English noun, the plural of cooldown, for recharge timers; a game-tracker mechanic cue."',
  '    lexeme "ru"',
  '      word "хп"',
  '        description "Russian noun (romanized khp) for hit points; a game-tracker mechanic cue."',
  '      word "урон"',
  '        description "Russian noun (romanized uron) for damage; a game-tracker mechanic cue."',
  '      word "защита"',
  '        description "Russian noun (romanized zashchita) for protection or defence; a game-tracker mechanic cue."',
  '      word "сопротивление"',
  '        description "Russian noun (romanized soprotivleniye) for resistance; a game-tracker mechanic cue."',
  '      word "откат"',
  '        description "Russian noun (romanized otkat) for a cooldown; a game-tracker mechanic cue."',
  '    lexeme "hi"',
  '      word "एचपी"',
  '        description "Hindi noun (romanized hp, a loanword) for hit points; a game-tracker mechanic cue."',
  '      word "क्षति"',
  '        description "Hindi noun (romanized kshati) for damage; a game-tracker mechanic cue."',
  '      word "रक्षा"',
  '        description "Hindi noun (romanized raksha) for protection or defence; a game-tracker mechanic cue."',
  '    lexeme "zh"',
  '      word "生命值"',
  '        description "Chinese noun (pinyin shengmingzhi) for hit points or health value; a game-tracker mechanic cue."',
  '      word "伤害"',
  '        description "Chinese noun (pinyin shanghai) for damage; a game-tracker mechanic cue."',
  '      word "防护"',
  '        description "Chinese noun (pinyin fanghu) for protection; a game-tracker mechanic cue."',
  '      word "抗性"',
  '        description "Chinese noun (pinyin kangxing) for resistance; a game-tracker mechanic cue."',
  '      word "冷却"',
  '        description "Chinese noun (pinyin lengque) for a cooldown; a game-tracker mechanic cue."',
  '  meaning "software_approval"',
  "    gloss \"the user's approval interaction in a software dialogue — the genus pairing a whole-prompt go-ahead with the granularity at which approval is requested\"",
  '    wiktionary "approval"',
  '    defined_by "software_approval_trigger"',
  '    defined_by "software_step_granularity"',
  '    defined_by "concept"',
  '    role "software_approval"',
  '    lexeme "en"',
  '      word "approval"',
  "        description \"English noun for the user's go-ahead in a software dialogue; the genus pairing a go-ahead with its granularity.\"",
  '    lexeme "ru"',
  '      word "одобрение"',
  '        description "Russian noun (romanized odobreniye) for approval; the Russian surface for the approval concept."',
  '    lexeme "hi"',
  '      word "अनुमोदन"',
  '        description "Hindi noun (romanized anumodan) for approval; the Hindi surface for the approval concept."',
  '    lexeme "zh"',
  '      word "批准"',
  '        description "Chinese noun or verb (pinyin pizhun) for approval; the Chinese surface for the approval concept."',
  '  meaning "software_approval_trigger"',
  '    gloss "a whole-prompt go-ahead that moves a software dialogue from plan to implementation — approve, yes, proceed, go ahead, do it; matched against the entire compacted prompt, not a passing mention"',
  '    wiktionary "approve"',
  '    defined_by "software_approval"',
  '    role "software_approval_trigger"',
  '    lexeme "en"',
  '      word "approve"',
  '        description "English verb for giving the go-ahead to move from plan to implementation; the base approval-trigger surface."',
  '      word "approved"',
  '        description "English adjective or past form of approve confirming the go-ahead; an approval-trigger surface."',
  '      word "approve plan"',
  '        description "English phrase explicitly approving the plan; an approval-trigger surface."',
  '      word "yes"',
  '        description "English affirmative giving the go-ahead; an approval-trigger surface."',
  '      word "yes proceed"',
  '        description "English phrase affirming and asking to proceed; an approval-trigger surface."',
  '      word "proceed"',
  '        description "English verb asking to move forward with implementation; an approval-trigger surface."',
  '      word "go ahead"',
  '        description "English phrase granting permission to proceed; an approval-trigger surface."',
  '      word "looks good"',
  '        description "English phrase signalling approval of the plan; an approval-trigger surface."',
  '      word "do it"',
  '        description "English imperative phrase granting the go-ahead; an approval-trigger surface."',
  '      word "start implementation"',
  '        description "English phrase asking to begin implementing; an approval-trigger surface."',
  '      word "generate code"',
  '        description "English phrase asking to produce the code; an approval-trigger surface."',
  '      word "convert to code"',
  '        description "English phrase asking to turn the plan into code; an approval-trigger surface."',
  '    lexeme "ru"',
  '      word "одобряю"',
  '        description "Russian verb (romanized odobryayu) meaning I approve; an approval-trigger surface."',
  '      word "да"',
  '        description "Russian affirmative (romanized da) meaning yes; an approval-trigger surface."',
  '      word "приступай"',
  '        description "Russian imperative verb (romanized pristupay) meaning get started; an approval-trigger surface."',
  '      word "поехали"',
  '        description "Russian phrase (romanized poyekhali) meaning let us go; an approval-trigger surface."',
  '    lexeme "hi"',
  '      word "स्वीकृत"',
  '        description "Hindi adjective (romanized sweekrit) meaning approved; an approval-trigger surface."',
  '      word "हाँ"',
  '        description "Hindi affirmative (romanized han) meaning yes; an approval-trigger surface."',
  '      word "आगे बढ़ो"',
  '        description "Hindi imperative phrase (romanized aage badho) meaning go ahead; an approval-trigger surface."',
  '    lexeme "zh"',
  '      word "批准"',
  '        description "Chinese verb (pinyin pizhun) for approving; an approval-trigger surface."',
  '      word "同意"',
  '        description "Chinese verb (pinyin tongyi) for agreeing or consenting; an approval-trigger surface."',
  '      word "开始"',
  '        description "Chinese verb (pinyin kaishi) for starting or beginning; an approval-trigger surface."',
  '  meaning "software_step_granularity"',
  '    gloss "a request to approve the work step by step rather than all at once — adds the each_step approval gate"',
  '    wiktionary "step"',
  '    defined_by "software_approval"',
  '    role "software_step_granularity"',
  '    lexeme "en"',
  '      word "each step"',
  '        description "English phrase asking to approve every step individually; an each-step granularity cue."',
  '      word "step by step"',
  '        description "English phrase asking to proceed one step at a time; an each-step granularity cue."',
  '    lexeme "ru"',
  '      word "каждый шаг"',
  '        description "Russian phrase (romanized kazhdyy shag) meaning each step; an each-step granularity cue."',
  '      word "пошагово"',
  '        description "Russian adverb (romanized poshagovo) meaning step by step; an each-step granularity cue."',
  '    lexeme "hi"',
  '      word "हर चरण"',
  '        description "Hindi phrase (romanized har charan) meaning each step; an each-step granularity cue."',
  '      word "चरण दर चरण"',
  '        description "Hindi phrase (romanized charan dar charan) meaning step by step; an each-step granularity cue."',
  '    lexeme "zh"',
  '      word "每一步"',
  '        description "Chinese phrase (pinyin mei yi bu) meaning each step; an each-step granularity cue."',
  '      word "逐步"',
  '        description "Chinese adverb (pinyin zhubu) meaning step by step; an each-step granularity cue."',
  '  meaning "software_bash_command"',
  '    gloss "a shell or command-line surface the work touches — a shell, bash, a command, Docker, WebVM; adds the bash_command approval gate"',
  '    wiktionary "shell"',
  '    defined_by "software_delivery"',
  '    role "software_bash_command"',
  '    lexeme "en"',
  '      word "shell"',
  '        description "English noun for a command-line shell the work touches; a bash-command surface cue."',
  '      word "bash"',
  '        description "English proper noun for the Bash shell the work touches; a bash-command surface cue."',
  '      word "command"',
  '        description "English noun for a single shell command the work touches; a bash-command surface cue."',
  '      word "commands"',
  '        description "English noun, the plural of command, for shell commands the work touches; a bash-command surface cue."',
  '      word "docker"',
  '        description "English proper noun for Docker, a container command-line surface; a bash-command surface cue."',
  '      word "webvm"',
  '        description "English proper noun for the WebVM in-browser sandbox with a shell; a bash-command surface cue."',
  '    lexeme "ru"',
  '      word "оболочка"',
  '        description "Russian noun (romanized obolochka) for a shell; a bash-command surface cue."',
  '      word "команда"',
  '        description "Russian noun (romanized komanda) for a command; a bash-command surface cue."',
  '      word "команды"',
  '        description "Russian noun (romanized komandy) for commands; the plural form of the command surface."',
  '    lexeme "hi"',
  '      word "शेल"',
  '        description "Hindi noun (romanized shell, a loanword) for a shell; a bash-command surface cue."',
  '      word "कमांड"',
  '        description "Hindi noun (romanized command, a loanword) for a command; a bash-command surface cue."',
  '    lexeme "zh"',
  '      word "外壳"',
  '        description "Chinese noun (pinyin waike) for a shell; a bash-command surface cue."',
  '      word "命令"',
  '        description "Chinese noun (pinyin mingling) for a command; a bash-command surface cue."',
  '      word "docker"',
  '        description "The Latin-script name Docker used in Chinese text for the container tool; a bash-command surface cue."',
  "meanings",
  '  meaning "program_synthesis"',
  '    gloss "deriving a small program — a function — from a specification and verifying it; the genus of the subject, domain, action, signal, and task meanings below"',
  '    wiktionary "synthesis"',
  '    defined_by "function"',
  '    defined_by "code"',
  '    defined_by "implement"',
  '    role "program_synthesis"',
  '    lexeme "en"',
  '      word "program synthesis"',
  '        description "English noun phrase for deriving a program from a specification; the root surface of this program-synthesis sub-ontology."',
  '      word "function synthesis"',
  '        description "English noun phrase for deriving a single function from a specification; a near-synonym surface for program synthesis."',
  '    lexeme "ru"',
  '      word "синтез программ"',
  '        description "Russian noun phrase (romanized sintez programm) for synthesis of programs; the Russian surface for program synthesis."',
  '      word "синтез функции"',
  '        description "Russian noun phrase (romanized sintez funktsii) for synthesis of a function; a near-synonym Russian surface for program synthesis."',
  '    lexeme "hi"',
  '      word "प्रोग्राम संश्लेषण"',
  '        description "Hindi noun phrase (romanized program sanshleshan) for program synthesis; the Hindi surface for deriving a program from a specification."',
  '    lexeme "zh"',
  '      word "程序合成"',
  '        description "Chinese noun phrase (pinyin chengxu hecheng) for program synthesis; the Chinese surface for deriving a program from a specification."',
  '  meaning "synthesis_subject_function"',
  "    gloss \"the function a synthesis request asks to be written — the subject of 'implement a function …'\"",
  '    wiktionary "function"',
  '    defined_by "program_synthesis"',
  '    defined_by "function"',
  '    role "program_synthesis_subject"',
  '    lexeme "en"',
  '      word "function"',
  '        description "English noun for a named block of code to be written; the subject of a synthesis request."',
  '      word "func"',
  '        description "English noun, a clipped abbreviation of function; a shorter synonym surface for the function subject."',
  '    lexeme "ru"',
  '      word "функция"',
  '        description "Russian noun (romanized funktsiya) for a function in the nominative case; the Russian surface for the function subject."',
  '      word "функцию"',
  '        description "Russian noun (romanized funktsiyu) for a function in the accusative case; the object form used after request verbs like implement."',
  '    lexeme "hi"',
  '      word "फ़ंक्शन"',
  '        description "Hindi noun (romanized function, a loanword) for a code function; the Hindi surface for the function subject."',
  '      word "फंक्शन"',
  '        description "Hindi noun (romanized function, a loanword) for a code function; a spelling variant surface for the function subject."',
  '    lexeme "zh"',
  '      word "函数"',
  '        description "Chinese noun (pinyin hanshu) for a function; the Chinese surface for the function subject."',
  '  meaning "synthesis_domain_python"',
  '    gloss "Python named as the target language of a synthesis request — a domain signal"',
  '    wiktionary "Python"',
  '    defined_by "program_synthesis"',
  '    defined_by "language_python"',
  '    role "program_synthesis_domain"',
  '    lexeme "en"',
  '      word "python"',
  '        description "English proper noun naming the Python programming language; a domain signal for the target language of synthesis."',
  '    lexeme "ru"',
  '      word "питон"',
  '        description "Russian noun (romanized piton) naming the Python language; the Russian surface for the Python domain signal."',
  '      word "пайтон"',
  '        description "Russian noun (romanized payton) naming the Python language; a transliteration variant surface for the Python domain signal."',
  '    lexeme "hi"',
  '      word "पायथन"',
  '        description "Hindi proper noun (romanized python) naming the Python language; the Hindi surface for the Python domain signal."',
  '    lexeme "zh"',
  '      word "python"',
  '        description "English-script proper noun naming the Python language as used in Chinese text; the Chinese-context surface for the Python domain signal."',
  '  meaning "synthesis_domain_tuple"',
  '    gloss "a tuple — an immutable ordered sequence; a data-structure domain signal for synthesis"',
  '    wiktionary "tuple"',
  '    defined_by "program_synthesis"',
  '    defined_by "code"',
  '    role "program_synthesis_domain"',
  '    lexeme "en"',
  '      word "tuple"',
  '        description "English noun for an immutable ordered sequence; a data-structure domain signal for synthesis."',
  '      word "tuples"',
  '        description "English noun, the plural of tuple; the plural surface for the tuple domain signal."',
  '    lexeme "ru"',
  '      word "кортеж"',
  '        description "Russian noun (romanized kortezh) for a tuple in the singular; the Russian surface for the tuple domain signal."',
  '      word "кортежи"',
  '        description "Russian noun (romanized kortezhi) for tuples in the plural; the plural surface for the tuple domain signal."',
  '    lexeme "hi"',
  '      word "टपल"',
  '        description "Hindi noun (romanized tuple, a loanword) for a tuple; the Hindi surface for the tuple domain signal."',
  '    lexeme "zh"',
  '      word "元组"',
  '        description "Chinese noun (pinyin yuanzu) for a tuple; the Chinese surface for the tuple domain signal."',
  '  meaning "synthesis_domain_numbers"',
  '    gloss "the numbers a synthesized function operates over — a data domain signal"',
  '    wiktionary "number"',
  '    defined_by "program_synthesis"',
  '    defined_by "result"',
  '    role "program_synthesis_domain"',
  '    lexeme "en"',
  '      word "numbers"',
  '        description "English noun, the plural of number, for the numeric data a synthesized function operates over; a data domain signal."',
  '    lexeme "ru"',
  '      word "числа"',
  '        description "Russian noun (romanized chisla) for numbers in the nominative plural; the Russian surface for the numbers domain signal."',
  '      word "чисел"',
  '        description "Russian noun (romanized chisel) for numbers in the genitive plural; the of-numbers form of the numbers domain signal."',
  '    lexeme "hi"',
  '      word "संख्याएँ"',
  '        description "Hindi noun (romanized sankhyaen) for numbers in the plural; the Hindi surface for the numbers domain signal."',
  '      word "संख्याओं"',
  '        description "Hindi noun (romanized sankhyaon) for numbers in the oblique plural; the of-numbers form of the numbers domain signal."',
  '    lexeme "zh"',
  '      word "数字"',
  '        description "Chinese noun (pinyin shuzi) for numbers or digits; the Chinese surface for the numbers domain signal."',
  '  meaning "synthesis_domain_vowels"',
  '    gloss "the vowels a synthesized text function counts — a data domain signal"',
  '    wiktionary "vowel"',
  '    defined_by "program_synthesis"',
  '    defined_by "result"',
  '    role "program_synthesis_domain"',
  '    lexeme "en"',
  '      word "vowels"',
  '        description "English noun, the plural of vowel, for the vowels a text function counts; a data domain signal."',
  '      word "vowel"',
  '        description "English noun for a single vowel; the singular surface for the vowels domain signal."',
  '    lexeme "ru"',
  '      word "гласные"',
  '        description "Russian noun (romanized glasnye) for vowels in the nominative plural; the Russian surface for the vowels domain signal."',
  '      word "гласных"',
  '        description "Russian noun (romanized glasnykh) for vowels in the genitive plural; the of-vowels form of the vowels domain signal."',
  '    lexeme "hi"',
  '      word "स्वर"',
  '        description "Hindi noun (romanized svar) for a vowel or vowels; the Hindi surface for the vowels domain signal."',
  '      word "स्वरों"',
  '        description "Hindi noun (romanized svaron) for vowels in the oblique plural; the of-vowels form of the vowels domain signal."',
  '    lexeme "zh"',
  '      word "元音"',
  '        description "Chinese noun (pinyin yuanyin) for a vowel; the Chinese surface for the vowels domain signal."',
  '  meaning "synthesis_action_implement"',
  "    gloss \"the request verb 'implement' that asks a function be synthesized\"",
  '    wiktionary "implement"',
  '    defined_by "program_synthesis"',
  '    defined_by "implement"',
  '    role "program_synthesis_action"',
  '    lexeme "en"',
  '      word "implement"',
  '        description "English verb meaning to build or realize code; the request verb asking that a function be synthesized."',
  '    lexeme "ru"',
  '      word "реализуй"',
  '        description "Russian verb (romanized realizuy) for implement in the informal imperative; the Russian request surface asking a function be synthesized."',
  '      word "реализовать"',
  '        description "Russian verb (romanized realizovat) for implement in the infinitive; an alternative Russian surface for the implement request verb."',
  '    lexeme "hi"',
  '      word "लागू"',
  '        description "Hindi word (romanized lagu) meaning to put into effect or implement; the Hindi surface for the implement request verb."',
  '    lexeme "zh"',
  '      word "实现"',
  '        description "Chinese verb (pinyin shixian) for implement or realize; the Chinese surface for the implement request verb."',
  '  meaning "synthesis_action_write"',
  "    gloss \"the request verb 'write' that asks a function be synthesized\"",
  '    wiktionary "write"',
  '    defined_by "program_synthesis"',
  '    defined_by "write"',
  '    role "program_synthesis_action"',
  '    lexeme "en"',
  '      word "write"',
  '        description "English verb meaning to compose code; the request verb asking that a function be synthesized."',
  '    lexeme "ru"',
  '      word "напиши"',
  '        description "Russian verb (romanized napishi) for write in the informal imperative; the Russian request surface asking a function be written."',
  '      word "напишите"',
  '        description "Russian verb (romanized napishite) for write in the formal or plural imperative; a polite surface for the write request verb."',
  '    lexeme "hi"',
  '      word "लिखो"',
  '        description "Hindi verb (romanized likho) for write in the informal imperative; the Hindi request surface asking a function be written."',
  '      word "लिखें"',
  '        description "Hindi verb (romanized likhen) for write in the polite imperative; a formal surface for the write request verb."',
  '    lexeme "zh"',
  '      word "编写"',
  '        description "Chinese verb (pinyin bianxie) for write or compose code; the Chinese surface for the write request verb."',
  '      word "写"',
  '        description "Chinese verb (pinyin xie) for write; a shorter single-character surface for the write request verb."',
  '  meaning "synthesis_action_return"',
  "    gloss \"the specification verb 'return' that states what a synthesized function yields\"",
  '    wiktionary "return"',
  '    defined_by "program_synthesis"',
  '    defined_by "output"',
  '    defined_by "result"',
  '    role "program_synthesis_action"',
  '    lexeme "en"',
  '      word "return"',
  '        description "English verb meaning to yield a value from a function; the specification verb stating what the function produces."',
  '      word "returns"',
  '        description "English verb, the third-person singular of return; the it-returns surface for the return specification verb."',
  '    lexeme "ru"',
  '      word "верни"',
  '        description "Russian verb (romanized verni) for return in the informal imperative; the Russian surface for the return specification verb."',
  '      word "вернуть"',
  '        description "Russian verb (romanized vernut) for return in the infinitive; an alternative Russian surface for the return specification verb."',
  '      word "возврати"',
  '        description "Russian verb (romanized vozvrati) for return in the imperative; another Russian surface for the return specification verb."',
  '    lexeme "hi"',
  '      word "लौटाएँ"',
  '        description "Hindi verb (romanized lautaen) for return in the polite imperative; the Hindi surface for the return specification verb."',
  '      word "लौटाओ"',
  '        description "Hindi verb (romanized lautao) for return in the informal imperative; an alternative Hindi surface for the return specification verb."',
  '      word "लौटा"',
  '        description "Hindi verb (romanized lauta) for return in the bare or past form; another Hindi surface for the return specification verb."',
  '    lexeme "zh"',
  '      word "返回"',
  '        description "Chinese verb (pinyin fanhui) for return or send back a value; the Chinese surface for the return specification verb."',
  '  meaning "signal_distinct_numbers"',
  "    gloss \"the 'distinct numbers' phrase that signals the pairwise-threshold task\"",
  '    wiktionary "distinct"',
  '    defined_by "program_synthesis"',
  '    defined_by "synthesis_domain_numbers"',
  '    role "program_synthesis_signal"',
  '    lexeme "en"',
  '      word "distinct numbers"',
  '        description "English noun phrase for numbers that are all different; the signal phrase for the pairwise-threshold task."',
  '    lexeme "ru"',
  '      word "различные числа"',
  '        description "Russian noun phrase (romanized razlichnye chisla) for distinct numbers; the Russian signal surface for the pairwise-threshold task."',
  '      word "разные числа"',
  '        description "Russian noun phrase (romanized raznye chisla) for different numbers; a colloquial variant surface for the distinct-numbers signal."',
  '    lexeme "hi"',
  '      word "अलग संख्याएँ"',
  '        description "Hindi noun phrase (romanized alag sankhyaen) for distinct numbers; the Hindi signal surface for the pairwise-threshold task."',
  '    lexeme "zh"',
  '      word "不同的数字"',
  '        description "Chinese noun phrase (pinyin butong de shuzi) for distinct numbers; the Chinese signal surface for the pairwise-threshold task."',
  '  meaning "signal_difference"',
  "    gloss \"the 'differ' relation that signals comparing values in the pairwise-threshold task\"",
  '    wiktionary "differ"',
  '    defined_by "program_synthesis"',
  '    role "program_synthesis_signal"',
  '    lexeme "en"',
  '      word "differ"',
  '        description "English verb meaning to be unlike; the signal relation for comparing values in the pairwise-threshold task."',
  '      word "differs"',
  '        description "English verb, the third-person singular of differ; the it-differs surface for the difference signal."',
  '      word "difference"',
  '        description "English noun for the result of comparing two values; the nominal surface for the difference signal."',
  '    lexeme "ru"',
  '      word "отличаются"',
  '        description "Russian verb (romanized otlichayutsya) for they differ; the Russian surface for the difference signal."',
  '      word "различаются"',
  '        description "Russian verb (romanized razlichayutsya) for they differ; an alternative Russian surface for the difference signal."',
  '      word "разница"',
  '        description "Russian noun (romanized raznitsa) for difference; the nominal Russian surface for the difference signal."',
  '    lexeme "hi"',
  '      word "भिन्न"',
  '        description "Hindi adjective (romanized bhinn) for different or distinct; the Hindi surface for the difference signal."',
  '      word "अंतर"',
  '        description "Hindi noun (romanized antar) for difference or gap; the nominal Hindi surface for the difference signal."',
  '    lexeme "zh"',
  '      word "不同"',
  '        description "Chinese adjective (pinyin butong) for different or not the same; the Chinese surface for the difference signal."',
  '      word "差异"',
  '        description "Chinese noun (pinyin chayi) for difference or disparity; the nominal Chinese surface for the difference signal."',
  '  meaning "signal_threshold"',
  "    gloss \"the 'threshold' bound that signals the pairwise-threshold task\"",
  '    wiktionary "threshold"',
  '    defined_by "program_synthesis"',
  '    role "program_synthesis_signal"',
  '    lexeme "en"',
  '      word "threshold"',
  '        description "English noun for a limiting bound or cutoff value; the signal phrase for the pairwise-threshold task."',
  '      word "thresholds"',
  '        description "English noun, the plural of threshold; the plural surface for the threshold signal."',
  '    lexeme "ru"',
  '      word "порог"',
  '        description "Russian noun (romanized porog) for a threshold in the nominative; the Russian surface for the threshold signal."',
  '      word "порога"',
  '        description "Russian noun (romanized poroga) for a threshold in the genitive; the of-threshold form of the threshold signal."',
  '    lexeme "hi"',
  '      word "सीमा"',
  '        description "Hindi noun (romanized seema) for a limit or boundary; the Hindi surface for the threshold signal."',
  '      word "थ्रेशोल्ड"',
  '        description "Hindi noun (romanized threshold, a loanword) for a threshold; a borrowed-term surface for the threshold signal."',
  '    lexeme "zh"',
  '      word "阈值"',
  '        description "Chinese noun (pinyin yuzhi) for a threshold value; the Chinese surface for the threshold signal."',
  '  meaning "signal_similar_elements"',
  "    gloss \"the 'similar elements' phrase that signals the tuple-intersection task\"",
  '    wiktionary "similar"',
  '    defined_by "program_synthesis"',
  '    defined_by "synthesis_subject_function"',
  '    role "program_synthesis_signal"',
  '    lexeme "en"',
  '      word "similar elements"',
  '        description "English noun phrase for elements shared by two collections; the signal phrase for the tuple-intersection task."',
  '    lexeme "ru"',
  '      word "похожие элементы"',
  '        description "Russian noun phrase (romanized pokhozhie elementy) for similar elements; the Russian signal surface for the tuple-intersection task."',
  '      word "одинаковые элементы"',
  '        description "Russian noun phrase (romanized odinakovye elementy) for identical elements; a variant surface for the similar-elements signal."',
  '    lexeme "hi"',
  '      word "समान तत्व"',
  '        description "Hindi noun phrase (romanized saman tatva) for similar elements; the Hindi signal surface for the tuple-intersection task."',
  '    lexeme "zh"',
  '      word "相似元素"',
  '        description "Chinese noun phrase (pinyin xiangsi yuansu) for similar elements; the Chinese signal surface for the tuple-intersection task."',
  '  meaning "signal_count_vowels"',
  "    gloss \"the 'count vowels' / 'number of vowels' phrases that signal the vowel-counting task\"",
  '    wiktionary "vowel"',
  '    defined_by "program_synthesis"',
  '    defined_by "synthesis_domain_vowels"',
  '    role "program_synthesis_signal"',
  '    lexeme "en"',
  '      word "count vowels"',
  '        description "English verb phrase for tallying the vowels in a text; the signal phrase for the vowel-counting task."',
  '      word "number of vowels"',
  '        description "English noun phrase for the count of vowels; an alternative signal phrase for the vowel-counting task."',
  '    lexeme "ru"',
  '      word "количество гласных"',
  '        description "Russian noun phrase (romanized kolichestvo glasnykh) for the number of vowels; the Russian signal surface for the vowel-counting task."',
  '      word "число гласных"',
  '        description "Russian noun phrase (romanized chislo glasnykh) for the number of vowels; a variant surface for the count-vowels signal."',
  '    lexeme "hi"',
  '      word "स्वरों की संख्या"',
  '        description "Hindi noun phrase (romanized svaron ki sankhya) for the number of vowels; the Hindi signal surface for the vowel-counting task."',
  '    lexeme "zh"',
  '      word "元音数量"',
  '        description "Chinese noun phrase (pinyin yuanyin shuliang) for the number of vowels; the Chinese signal surface for the vowel-counting task."',
  '      word "元音的数量"',
  '        description "Chinese noun phrase (pinyin yuanyin de shuliang) for the number of vowels; a variant surface for the count-vowels signal."',
  '  meaning "has_close_elements"',
  '    gloss "the HumanEval/0 task: true when any two distinct numbers are within a threshold — recognized by the distinct-numbers, difference, and threshold signals (its slug is the canonical function name)"',
  '    wiktionary "close"',
  '    defined_by "signal_distinct_numbers"',
  '    defined_by "signal_difference"',
  '    defined_by "signal_threshold"',
  '    role "program_synthesis_task"',
  '    lexeme "en"',
  '      word "has_close_elements"',
  '        description "English function-name identifier for the HumanEval/0 task; the canonical slug naming the within-threshold task."',
  '    lexeme "ru"',
  '      word "has_close_elements"',
  '        description "The canonical function-name identifier for the HumanEval/0 task, kept in English under the Russian lexeme since the slug is language-neutral code."',
  '    lexeme "hi"',
  '      word "has_close_elements"',
  '        description "The canonical function-name identifier for the HumanEval/0 task, kept in English under the Hindi lexeme since the slug is language-neutral code."',
  '    lexeme "zh"',
  '      word "has_close_elements"',
  '        description "The canonical function-name identifier for the HumanEval/0 task, kept in English under the Chinese lexeme since the slug is language-neutral code."',
  '  meaning "similar_elements"',
  '    gloss "the MBPP/2 task: the intersection of two tuples in deterministic order — recognized by the similar-elements signal (its slug is the canonical function name)"',
  '    wiktionary "similar"',
  '    defined_by "signal_similar_elements"',
  '    role "program_synthesis_task"',
  '    lexeme "en"',
  '      word "similar_elements"',
  '        description "English function-name identifier for the MBPP/2 task; the canonical slug naming the tuple-intersection task."',
  '    lexeme "ru"',
  '      word "similar_elements"',
  '        description "The canonical function-name identifier for the MBPP/2 task, kept in English under the Russian lexeme since the slug is language-neutral code."',
  '    lexeme "hi"',
  '      word "similar_elements"',
  '        description "The canonical function-name identifier for the MBPP/2 task, kept in English under the Hindi lexeme since the slug is language-neutral code."',
  '    lexeme "zh"',
  '      word "similar_elements"',
  '        description "The canonical function-name identifier for the MBPP/2 task, kept in English under the Chinese lexeme since the slug is language-neutral code."',
  '  meaning "count_vowels"',
  '    gloss "the vowel-counting task: how many vowels a text contains — recognized by the count-vowels signal (its slug is the canonical function name)"',
  '    wiktionary "count"',
  '    defined_by "signal_count_vowels"',
  '    role "program_synthesis_task"',
  '    lexeme "en"',
  '      word "count_vowels"',
  '        description "English function-name identifier for the vowel-counting task; the canonical slug naming how many vowels a text contains."',
  '    lexeme "ru"',
  '      word "count_vowels"',
  '        description "The canonical function-name identifier for the vowel-counting task, kept in English under the Russian lexeme since the slug is language-neutral code."',
  '    lexeme "hi"',
  '      word "count_vowels"',
  '        description "The canonical function-name identifier for the vowel-counting task, kept in English under the Hindi lexeme since the slug is language-neutral code."',
  '    lexeme "zh"',
  '      word "count_vowels"',
  '        description "The canonical function-name identifier for the vowel-counting task, kept in English under the Chinese lexeme since the slug is language-neutral code."',
  "meanings",
  '  meaning "assistant"',
  '    gloss "the deterministic symbolic AI that answers the user — it speaks about itself and produces every answer"',
  '    wiktionary "assistant"',
  '    defined_by "answer"',
  '    defined_by "self_reference"',
  '    defined_by "entity"',
  '    role "conversational_entity"',
  '    lexeme "en"',
  '      word "assistant"',
  '        description "English noun for the deterministic symbolic AI that answers the user; the bare surface for the assistant concept."',
  '      word "ai assistant"',
  '        description "English phrase naming the assistant as an AI-driven helper; an explicit surface for the assistant concept."',
  '    lexeme "ru"',
  '      word "ассистент"',
  '        description "Russian noun (romanized assistent) for an assistant; the Russian surface for the assistant concept."',
  '      word "помощник"',
  '        description "Russian noun (romanized pomoshchnik) for a helper; an alternative Russian surface for the assistant concept."',
  '    lexeme "hi"',
  '      word "सहायक"',
  '        description "Hindi noun (romanized sahayak) for a helper or assistant; the Hindi surface for the assistant concept."',
  '    lexeme "zh"',
  '      word "助手"',
  '        description "Chinese noun (pinyin zhushou) for an assistant or helper; the Chinese surface for the assistant concept."',
  '      word "助理"',
  '        description "Chinese noun (pinyin zhuli) for an assistant or aide; an alternative Chinese surface for the assistant concept."',
  '  meaning "user"',
  '    gloss "the person who addresses the assistant — the author of every inquiry"',
  '    wiktionary "user"',
  '    defined_by "inquiry"',
  '    defined_by "entity"',
  '    role "conversational_entity"',
  '    lexeme "en"',
  '      word "user"',
  '        description "English noun for the person who addresses the assistant; the surface for the user concept."',
  '    lexeme "ru"',
  '      word "пользователь"',
  '        description "Russian noun (romanized polzovatel) for a user; the Russian surface for the user concept."',
  '    lexeme "hi"',
  '      word "उपयोगकर्ता"',
  '        description "Hindi noun (romanized upayogkarta) for a user; the Hindi surface for the user concept."',
  '    lexeme "zh"',
  '      word "用户"',
  '        description "Chinese noun (pinyin yonghu) for a user; the Chinese surface for the user concept."',
  '  meaning "inquiry"',
  '    gloss "a question or request a user makes, expecting an answer from the assistant"',
  '    wiktionary "inquiry"',
  '    defined_by "answer"',
  '    defined_by "user"',
  '    role "conversational_act"',
  '    lexeme "en"',
  '      word "inquiry"',
  '        description "English noun for a question or request expecting an answer; the surface for the inquiry concept."',
  '      word "question"',
  '        description "English noun for a sentence that asks for information; a synonym surface for the inquiry concept."',
  '      word "request"',
  '        description "English noun for an act of asking the assistant to do something; an alternative surface for the inquiry concept."',
  '    lexeme "ru"',
  '      word "вопрос"',
  '        description "Russian noun (romanized vopros) for a question; the Russian surface for the inquiry concept."',
  '      word "запрос"',
  '        description "Russian noun (romanized zapros) for a request or query; an alternative Russian surface for the inquiry concept."',
  '    lexeme "hi"',
  '      word "प्रश्न"',
  '        description "Hindi noun (romanized prashn) for a question; the Hindi surface for the inquiry concept."',
  '      word "अनुरोध"',
  '        description "Hindi noun (romanized anurodh) for a request; an alternative Hindi surface for the inquiry concept."',
  '    lexeme "zh"',
  '      word "询问"',
  '        description "Chinese noun and verb (pinyin xunwen) for an inquiry or to ask; the Chinese surface for the inquiry concept."',
  '      word "请求"',
  '        description "Chinese noun and verb (pinyin qingqiu) for a request; an alternative Chinese surface for the inquiry concept."',
  '  meaning "answer"',
  '    gloss "the reply the assistant returns to an inquiry"',
  '    wiktionary "answer"',
  '    defined_by "inquiry"',
  '    defined_by "assistant"',
  '    role "conversational_act"',
  '    lexeme "en"',
  '      word "answer"',
  '        description "English noun for the reply the assistant returns to an inquiry; the surface for the answer concept."',
  '      word "response"',
  '        description "English noun for a reaction or reply to an inquiry; a synonym surface for the answer concept."',
  '      word "reply"',
  '        description "English noun for what is said back in answer to an inquiry; an alternative surface for the answer concept."',
  '    lexeme "ru"',
  '      word "ответ"',
  '        description "Russian noun (romanized otvet) for an answer or reply; the Russian surface for the answer concept."',
  '    lexeme "hi"',
  '      word "उत्तर"',
  '        description "Hindi noun (romanized uttar) for an answer; the Hindi surface for the answer concept."',
  '      word "जवाब"',
  '        description "Hindi noun (romanized javab) for a reply; an alternative Hindi surface for the answer concept."',
  '    lexeme "zh"',
  '      word "回答"',
  '        description "Chinese noun and verb (pinyin huida) for an answer or to answer; the Chinese surface for the answer concept."',
  '      word "答复"',
  '        description "Chinese noun and verb (pinyin dafu) for a reply or to reply; an alternative Chinese surface for the answer concept."',
  '  meaning "self_reference"',
  '    gloss "a reference the assistant makes to itself — the grammatical object of questions about the assistant"',
  '    wiktionary "self"',
  '    defined_by "assistant"',
  '    role "conversational_concept"',
  '    lexeme "en"',
  '      word "yourself"',
  '        description "English reflexive pronoun addressing the assistant itself; a surface for the self-reference concept."',
  '      word "myself"',
  '        description "English reflexive pronoun by which the assistant refers to itself; a surface for the self-reference concept."',
  '    lexeme "ru"',
  '      word "себе"',
  '        description "Russian reflexive pronoun (romanized sebe) in the dative or prepositional case meaning to or about oneself; a surface for the self-reference concept."',
  '      word "себя"',
  '        description "Russian reflexive pronoun (romanized sebya) in the accusative or genitive case meaning oneself; a surface for the self-reference concept."',
  '    lexeme "hi"',
  '      word "स्वयं"',
  '        description "Hindi reflexive pronoun (romanized svayam) meaning oneself; a surface for the self-reference concept."',
  '      word "खुद"',
  '        description "Hindi reflexive pronoun (romanized khud) meaning oneself; an alternative surface for the self-reference concept."',
  '    lexeme "zh"',
  '      word "自己"',
  '        description "Chinese reflexive pronoun (pinyin ziji) meaning oneself; the Chinese surface for the self-reference concept."',
  '  meaning "capability"',
  '    gloss "something the assistant is able to do — a feature it can perform in answer to a request"',
  '    wiktionary "capability"',
  '    defined_by "assistant"',
  '    defined_by "answer"',
  '    role "conversational_concept"',
  '    lexeme "en"',
  '      word "capability"',
  '        description "English noun for something the assistant is able to do; the surface for the capability concept."',
  '      word "ability"',
  '        description "English noun for the capacity to perform something; a synonym surface for the capability concept."',
  '    lexeme "ru"',
  '      word "возможность"',
  '        description "Russian noun (romanized vozmozhnost) for a possibility or capability; the Russian surface for the capability concept."',
  '      word "умение"',
  '        description "Russian noun (romanized umeniye) for a skill or ability; an alternative Russian surface for the capability concept."',
  '    lexeme "hi"',
  '      word "क्षमता"',
  '        description "Hindi noun (romanized kshamata) for a capability or capacity; the Hindi surface for the capability concept."',
  '    lexeme "zh"',
  '      word "能力"',
  '        description "Chinese noun (pinyin nengli) for an ability or capability; the Chinese surface for the capability concept."',
  '      word "功能"',
  '        description "Chinese noun (pinyin gongneng) for a function or feature; an alternative Chinese surface for the capability concept."',
  '  meaning "knowledge"',
  '    gloss "what the assistant knows — the facts available to it"',
  '    wiktionary "knowledge"',
  '    defined_by "assistant"',
  '    defined_by "fact"',
  '    role "conversational_concept"',
  '    lexeme "en"',
  '      word "knowledge"',
  '        description "English noun for what the assistant knows; the surface for the knowledge concept."',
  '    lexeme "ru"',
  '      word "знание"',
  '        description "Russian noun (romanized znaniye) for knowledge; the Russian surface for the knowledge concept."',
  '    lexeme "hi"',
  '      word "ज्ञान"',
  '        description "Hindi noun (romanized gyan) for knowledge; the Hindi surface for the knowledge concept."',
  '    lexeme "zh"',
  '      word "知识"',
  '        description "Chinese noun (pinyin zhishi) for knowledge; the Chinese surface for the knowledge concept."',
  '  meaning "fact"',
  '    gloss "a known true statement that the assistant can recall as part of its knowledge"',
  '    wiktionary "fact"',
  '    defined_by "knowledge"',
  '    role "conversational_concept"',
  '    role "knowledge_inventory_noun"',
  '    lexeme "en"',
  '      word "fact"',
  '        description "English noun for a known true statement the assistant can recall; the singular surface for the fact concept."',
  '      word "facts"',
  '        description "English plural noun for known true statements; the plural surface for the fact concept."',
  '    lexeme "ru"',
  '      word "факт"',
  '        description "Russian noun (romanized fakt) for a fact; the singular Russian surface for the fact concept."',
  '      word "факты"',
  '        description "Russian plural noun (romanized fakty) for facts; the plural Russian surface for the fact concept."',
  '    lexeme "hi"',
  '      word "तथ्य"',
  '        description "Hindi noun (romanized tathya) for a fact; the Hindi surface for the fact concept."',
  '    lexeme "zh"',
  '      word "事实"',
  '        description "Chinese noun (pinyin shishi) for a fact; the simplified Chinese surface for the fact concept."',
  '      word "事實"',
  '        description "Chinese noun (pinyin shishi) for a fact; the traditional Chinese surface for the fact concept."',
  '  meaning "knowledge_inventory_probe"',
  '    gloss "an interrogative or enumerating cue that asks the assistant to surface the items it holds"',
  '    wiktionary "enumerate"',
  '    defined_by "inquiry"',
  '    role "knowledge_inventory_interrogative"',
  '    lexeme "en"',
  '      word "what"',
  '        description "English interrogative pronoun opening a request to name the items the assistant holds."',
  '      word "which"',
  '        description "English interrogative determiner selecting among the items the assistant holds."',
  '      word "list"',
  '        description "English verb asking the assistant to enumerate the items it holds."',
  '      word "show"',
  '        description "English verb asking the assistant to display the items it holds."',
  '    lexeme "ru"',
  '      word "какие"',
  '        description "Russian interrogative determiner (romanized kakie) asking which items the assistant holds."',
  '      word "что"',
  '        description "Russian interrogative pronoun (romanized chto) asking what the assistant holds."',
  '      word "перечисли"',
  '        description "Russian imperative verb (romanized perechisli) asking the assistant to enumerate the items it holds."',
  '      word "покажи"',
  '        description "Russian imperative verb (romanized pokazhi) asking the assistant to display the items it holds."',
  '      word "назови"',
  '        description "Russian imperative verb (romanized nazovi) asking the assistant to name the items it holds."',
  '    lexeme "hi"',
  '      word "कौन"',
  '        description "Hindi interrogative (romanized kaun) asking which items the assistant holds."',
  '      word "क्या"',
  '        description "Hindi interrogative (romanized kya) asking what the assistant holds."',
  '      word "सूची"',
  '        description "Hindi noun (romanized soochee) for a list, asking the assistant to enumerate the items it holds."',
  '      word "सूचीबद्ध"',
  '        description "Hindi adjective (romanized soocheebaddh) meaning listed, asking the assistant to enumerate the items it holds."',
  '      word "बताओ"',
  '        description "Hindi imperative verb (romanized batao) asking the assistant to tell the items it holds."',
  '      word "दिखाओ"',
  '        description "Hindi imperative verb (romanized dikhao) asking the assistant to show the items it holds."',
  '    lexeme "zh"',
  '      word "哪些"',
  '        description "Chinese interrogative (pinyin naxie) selecting which items the assistant holds."',
  '      word "什么"',
  '        description "Chinese interrogative (pinyin shenme) asking what the assistant holds; simplified surface."',
  '      word "什麼"',
  '        description "Chinese interrogative (pinyin shenme) asking what the assistant holds; traditional surface."',
  '      word "你知道"',
  '        description "Chinese phrase (pinyin ni zhidao) meaning you-know, asking what the assistant holds."',
  '      word "您知道"',
  '        description "Chinese phrase (pinyin nin zhidao) meaning you-know (polite), asking what the assistant holds."',
  '      word "你有"',
  '        description "Chinese phrase (pinyin ni you) meaning you-have, asking what the assistant holds."',
  '      word "您有"',
  '        description "Chinese phrase (pinyin nin you) meaning you-have (polite), asking what the assistant holds."',
  '  meaning "assistant_knowing"',
  '    gloss "second-person attribution of knowing or having — the assistant being the one that holds the knowledge"',
  '    wiktionary "know"',
  '    defined_by "knowledge"',
  '    defined_by "assistant"',
  '    role "knowledge_possession"',
  '    lexeme "en"',
  '      word "you know"',
  '        description "English second-person phrase attributing the knowing to the assistant."',
  '      word "do you know"',
  '        description "English second-person interrogative phrase attributing the knowing to the assistant."',
  '      word "you have"',
  '        description "English second-person phrase attributing possession of the knowledge to the assistant."',
  '      word "available to you"',
  '        description "English phrase describing knowledge accessible to the assistant."',
  '      word "in your knowledge"',
  "        description \"English phrase locating the facts inside the assistant's knowledge.\"",
  '      word "known to you"',
  '        description "English phrase attributing the known facts to the assistant."',
  '    lexeme "ru"',
  '      word "ты знаешь"',
  '        description "Russian second-person phrase (romanized ty znaesh) attributing the knowing to the assistant."',
  '      word "знаешь"',
  '        description "Russian second-person verb (romanized znaesh) attributing the knowing to the assistant."',
  '      word "тебе известно"',
  '        description "Russian phrase (romanized tebe izvestno) meaning it-is-known-to-you, attributing the knowing to the assistant."',
  '      word "тебе известны"',
  '        description "Russian phrase (romanized tebe izvestny) meaning they-are-known-to-you, attributing the knowing to the assistant."',
  '      word "тебе известен"',
  '        description "Russian phrase (romanized tebe izvesten) meaning it-is-known-to-you (masculine), attributing the knowing to the assistant."',
  '      word "у тебя есть"',
  '        description "Russian phrase (romanized u tebya est) meaning you-have, attributing possession to the assistant."',
  '      word "твои знания"',
  '        description "Russian phrase (romanized tvoi znaniya) meaning your-knowledge, attributing the knowledge to the assistant."',
  '      word "что ты знаешь"',
  '        description "Russian phrase (romanized chto ty znaesh) meaning what-you-know, attributing the knowing to the assistant."',
  '    lexeme "hi"',
  '      word "तुम"',
  '        description "Hindi second-person pronoun (romanized tum) attributing the knowing to the assistant."',
  '      word "आप"',
  '        description "Hindi second-person pronoun (romanized aap, polite) attributing the knowing to the assistant."',
  '      word "जानते"',
  '        description "Hindi verb (romanized jaante) meaning know (masculine), attributing the knowing to the assistant."',
  '      word "जानती"',
  '        description "Hindi verb (romanized jaantee) meaning know (feminine), attributing the knowing to the assistant."',
  '      word "आपके"',
  '        description "Hindi possessive (romanized aapke) meaning your, attributing possession to the assistant."',
  '      word "तुम्हारे"',
  '        description "Hindi possessive (romanized tumhaare) meaning your, attributing possession to the assistant."',
  '    lexeme "zh"',
  '      word "你知道"',
  '        description "Chinese phrase (pinyin ni zhidao) meaning you-know, attributing the knowing to the assistant."',
  '      word "您知道"',
  '        description "Chinese phrase (pinyin nin zhidao) meaning you-know (polite), attributing the knowing to the assistant."',
  '      word "你有"',
  '        description "Chinese phrase (pinyin ni you) meaning you-have, attributing possession to the assistant."',
  '      word "您有"',
  '        description "Chinese phrase (pinyin nin you) meaning you-have (polite), attributing possession to the assistant."',
  '  meaning "knowledge_inventory_query"',
  '    gloss "a complete standalone phrasing that asks the assistant what it knows about the world, even without the word fact"',
  '    wiktionary "knowledge"',
  '    defined_by "knowledge"',
  '    defined_by "fact"',
  '    role "knowledge_inventory_phrase"',
  '    lexeme "en"',
  '      word "what do you know in general"',
  '        description "English standalone phrasing asking the assistant for its general knowledge inventory."',
  '      word "what do you know about the world"',
  '        description "English standalone phrasing asking the assistant for its knowledge about the world."',
  '      word "what is known to you"',
  '        description "English standalone phrasing asking the assistant for everything it knows."',
  '      word "what knowledge do you have"',
  '        description "English standalone phrasing asking the assistant to surface the knowledge it holds."',
  '    lexeme "ru"',
  '      word "что тебе вообще известно"',
  '        description "Russian standalone phrasing (romanized chto tebe voobshche izvestno) asking the assistant for everything it knows."',
  '      word "что тебе известно"',
  '        description "Russian standalone phrasing (romanized chto tebe izvestno) asking the assistant what it knows."',
  '      word "что ты вообще знаешь"',
  '        description "Russian standalone phrasing (romanized chto ty voobshche znaesh) asking the assistant for its general knowledge."',
  '      word "что ты знаешь об окружающем мире"',
  '        description "Russian standalone phrasing (romanized chto ty znaesh ob okruzhayushchem mire) asking the assistant about the surrounding world."',
  '      word "известно об окружающем мире"',
  '        description "Russian standalone phrasing (romanized izvestno ob okruzhayushchem mire) asking what is known about the surrounding world."',
  '      word "знаешь про окружающий мир"',
  '        description "Russian standalone phrasing (romanized znaesh pro okruzhayushchiy mir) asking what the assistant knows about the surrounding world."',
  '      word "знаешь об окружающем мире"',
  '        description "Russian standalone phrasing (romanized znaesh ob okruzhayushchem mire) asking what the assistant knows about the surrounding world."',
  '    lexeme "hi"',
  '      word "आप क्या जानते हैं"',
  '        description "Hindi standalone phrasing (romanized aap kya jaante hain) asking what the assistant knows."',
  '      word "तुम क्या जानते हो"',
  '        description "Hindi standalone phrasing (romanized tum kya jaante ho) asking what the assistant knows."',
  '      word "आपको क्या पता है"',
  '        description "Hindi standalone phrasing (romanized aapko kya pata hai) asking what is known to the assistant."',
  '    lexeme "zh"',
  '      word "你知道什么"',
  '        description "Chinese standalone phrasing (pinyin ni zhidao shenme) asking what the assistant knows; simplified surface."',
  '      word "您知道什么"',
  '        description "Chinese standalone phrasing (pinyin nin zhidao shenme) asking what the assistant knows (polite); simplified surface."',
  '      word "你知道哪些"',
  '        description "Chinese standalone phrasing (pinyin ni zhidao naxie) asking which items the assistant knows."',
  '  meaning "introduction"',
  '    gloss "presenting who one is — the assistant describing itself in answer to a get-acquainted request"',
  '    wiktionary "introduction"',
  '    defined_by "self_reference"',
  '    defined_by "answer"',
  '    role "conversational_concept"',
  '    lexeme "en"',
  '      word "introduction"',
  '        description "English noun for presenting who one is; the surface for the introduction concept."',
  '    lexeme "ru"',
  '      word "знакомство"',
  '        description "Russian noun (romanized znakomstvo) for an acquaintance or introduction; the Russian surface for the introduction concept."',
  '    lexeme "hi"',
  '      word "परिचय"',
  '        description "Hindi noun (romanized parichay) for an introduction or acquaintance; the Hindi surface for the introduction concept."',
  '    lexeme "zh"',
  '      word "介绍"',
  '        description "Chinese noun and verb (pinyin jieshao) for an introduction or to introduce; the Chinese surface for the introduction concept."',
  '  meaning "clarification"',
  '    gloss "making clear something the user did not understand — an answer that resolves confusion about a prior turn"',
  '    wiktionary "clarification"',
  '    defined_by "inquiry"',
  '    defined_by "answer"',
  '    role "conversational_concept"',
  '    lexeme "en"',
  '      word "clarification"',
  '        description "English noun for making clear something not understood; the surface for the clarification concept."',
  '    lexeme "ru"',
  '      word "разъяснение"',
  '        description "Russian noun (romanized razyasneniye) for a clarification or explanation; the Russian surface for the clarification concept."',
  '    lexeme "hi"',
  '      word "स्पष्टीकरण"',
  '        description "Hindi noun (romanized spashtikaran) for a clarification; the Hindi surface for the clarification concept."',
  '    lexeme "zh"',
  '      word "澄清"',
  '        description "Chinese noun and verb (pinyin chengqing) for a clarification or to clarify; the Chinese surface for the clarification concept."',
  '  meaning "understanding"',
  '    gloss "grasping the meaning of something; its absence is what a clarification request signals"',
  '    wiktionary "understanding"',
  '    defined_by "clarification"',
  '    defined_by "knowledge"',
  '    role "conversational_concept"',
  '    lexeme "en"',
  '      word "understanding"',
  '        description "English noun for grasping the meaning of something; the surface for the understanding concept."',
  '    lexeme "ru"',
  '      word "понимание"',
  '        description "Russian noun (romanized ponimaniye) for understanding; the Russian surface for the understanding concept."',
  '    lexeme "hi"',
  '      word "समझ"',
  '        description "Hindi noun (romanized samajh) for understanding; the Hindi surface for the understanding concept."',
  '    lexeme "zh"',
  '      word "理解"',
  '        description "Chinese noun and verb (pinyin lijie) for understanding or to understand; the Chinese surface for the understanding concept."',
  '  meaning "clarification_request"',
  '    gloss "the user signalling they did not understand the assistant and asking it to make the prior answer clear"',
  '    wiktionary "understand"',
  '    defined_by "clarification"',
  '    defined_by "understanding"',
  '    defined_by "inquiry"',
  '    role "clarification_request"',
  '    lexeme "en"',
  '      word "i don t understand"',
  '        description "English phrase a speaker uses to signal they do not understand and to ask the assistant to make the prior answer clear; an apostrophe-spaced spelling of I dont understand."',
  '      word "i dont understand"',
  '        description "English phrase a speaker uses to signal they do not understand the assistant; an apostrophe-free spelling variant."',
  '      word "i didn t understand"',
  '        description "English phrase a speaker uses to signal they did not understand the prior answer; a past-tense apostrophe-spaced variant."',
  '      word "i didnt understand"',
  '        description "English phrase a speaker uses to signal they did not understand the prior answer; a past-tense apostrophe-free variant."',
  '      word "don t understand"',
  '        description "English phrase a speaker uses to signal a lack of understanding; a subjectless apostrophe-spaced variant."',
  '      word "dont understand"',
  '        description "English phrase a speaker uses to signal a lack of understanding; a subjectless apostrophe-free variant."',
  '      word "didn t understand"',
  '        description "English phrase a speaker uses to signal they did not understand; a subjectless past-tense apostrophe-spaced variant."',
  '      word "didnt understand"',
  '        description "English phrase a speaker uses to signal they did not understand; a subjectless past-tense apostrophe-free variant."',
  '      word "what do you mean"',
  '        description "English phrase a speaker uses to ask the assistant to clarify what it meant; a surface for the clarification request."',
  '      word "i m confused"',
  '        description "English phrase a speaker uses to express confusion and seek clarification; an apostrophe-spaced spelling of I am confused."',
  '      word "im confused"',
  '        description "English phrase a speaker uses to express confusion and seek clarification; a contracted spelling variant."',
  '      word "i am confused"',
  '        description "English phrase a speaker uses to express confusion and seek clarification; the full uncontracted form."',
  '    lexeme "ru"',
  '      word "не понял"',
  '        description "Russian phrase (romanized ne ponyal) a male speaker uses to say I did not understand and seek clarification."',
  '      word "не понимаю"',
  '        description "Russian phrase (romanized ne ponimayu) a speaker uses to say I do not understand and seek clarification."',
  '      word "не поняла"',
  '        description "Russian phrase (romanized ne ponyala) a female speaker uses to say I did not understand and seek clarification."',
  '      word "не понятно"',
  '        description "Russian phrase (romanized ne ponyatno) a speaker uses to say it is not clear; a spaced spelling of the impersonal form."',
  '      word "непонятно"',
  '        description "Russian word (romanized neponyatno) a speaker uses to say it is unclear; the joined spelling of the impersonal form."',
  '    lexeme "hi"',
  '      word "समझ नहीं आया"',
  '        description "Hindi phrase (romanized samajh nahin aaya) a speaker uses to say it was not understood; a masculine-agreement variant signalling a clarification request."',
  '      word "समझ नहीं आई"',
  '        description "Hindi phrase (romanized samajh nahin aai) a speaker uses to say it was not understood; a feminine-agreement variant signalling a clarification request."',
  '    lexeme "zh"',
  '      word "我不明白"',
  '        description "Chinese phrase (pinyin wo bu mingbai) a speaker uses to say I do not understand and seek clarification."',
  '      word "我不懂"',
  '        description "Chinese phrase (pinyin wo bu dong) a speaker uses to say I do not get it; a more colloquial clarification request."',
  '      word "听不懂"',
  '        description "Chinese phrase (pinyin ting bu dong) a speaker uses to say I cannot understand what is heard; a clarification request about something said."',
  '  meaning "capability_query"',
  '    gloss "the user asking what the assistant is able to do — a request to enumerate its capabilities"',
  '    wiktionary "capability"',
  '    defined_by "capability"',
  '    defined_by "inquiry"',
  '    role "capability_query"',
  '    lexeme "en"',
  '      word "what can you do"',
  '        description "English phrase a speaker uses to ask what the assistant is capable of; the canonical surface for the capability query."',
  '      word "what you can do"',
  "        description \"English phrase a speaker uses to ask after the assistant's capabilities; a word-order variant of what can you do.\"",
  '      word "what are your capabilities"',
  '        description "English phrase a speaker uses to ask the assistant to enumerate its capabilities; a formal surface for the capability query."',
  '      word "what are you capable of"',
  '        description "English phrase a speaker uses to ask what the assistant is able to do; a synonym surface for the capability query."',
  '      word "what do you do"',
  "        description \"English phrase a speaker uses to ask about the assistant's function or role; a broad surface for the capability query.\"",
  '      word "show me what you can do"',
  '        description "English phrase a speaker uses to ask the assistant to demonstrate its capabilities; an imperative surface for the capability query."',
  '      word "what features do you have"',
  '        description "English phrase a speaker uses to ask which features the assistant offers; a feature-framed surface for the capability query."',
  '      word "how can you help"',
  '        description "English phrase a speaker uses to ask in what ways the assistant can help; a help-framed surface for the capability query."',
  '      word "what are your features"',
  '        description "English phrase a speaker uses to ask the assistant to list its features; a feature-framed surface for the capability query."',
  '    lexeme "ru"',
  '      word "что ты умеешь"',
  '        description "Russian phrase (romanized chto ty umeesh) a speaker uses to ask what the assistant can do; the canonical surface for the capability query."',
  '      word "чем ты можешь"',
  '        description "Russian phrase (romanized chem ty mozhesh) a speaker uses to ask with what the assistant can help; a surface for the capability query."',
  '      word "чём ты можешь"',
  '        description "Russian phrase (romanized chyom ty mozhesh) a speaker uses to ask in what the assistant can help; a yo-spelled variant for the capability query."',
  '      word "что ты можешь"',
  '        description "Russian phrase (romanized chto ty mozhesh) a speaker uses to ask what the assistant can do; a can-framed surface for the capability query."',
  '      word "что умеет"',
  '        description "Russian phrase (romanized chto umeet) a speaker uses to ask what it can do; a third-person subjectless surface for the capability query."',
  '      word "что можешь"',
  '        description "Russian phrase (romanized chto mozhesh) a speaker uses to ask what you can do; a subjectless surface for the capability query."',
  '      word "в чем ты можешь быть полезен"',
  '        description "Russian phrase (romanized v chem ty mozhesh byt polezen) a speaker uses to ask in what way the assistant can be useful; a usefulness-framed surface for the capability query."',
  '      word "в чём ты можешь быть полезен"',
  '        description "Russian phrase (romanized v chyom ty mozhesh byt polezen) a speaker uses to ask in what way the assistant can be useful; a yo-spelled variant for the capability query."',
  '      word "твои возможности"',
  '        description "Russian phrase (romanized tvoi vozmozhnosti) a speaker uses to ask after your capabilities; a noun-phrase surface for the capability query."',
  '      word "что за дичь"',
  '        description "Russian slang phrase (romanized chto za dich) a speaker uses to exclaim what is this nonsense; a colloquial surface treated as a capability query."',
  '      word "что это такое"',
  '        description "Russian phrase (romanized chto eto takoye) a speaker uses to ask what this is; a what-is-it surface treated as a capability query."',
  '      word "что происходит"',
  '        description "Russian phrase (romanized chto proiskhodit) a speaker uses to ask what is going on; a surface treated as a capability query."',
  '      word "что ты делаешь"',
  '        description "Russian phrase (romanized chto ty delaesh) a speaker uses to ask what the assistant does; a do-framed surface for the capability query."',
  '    lexeme "hi"',
  '      word "आप क्या कर सकते"',
  '        description "Hindi phrase (romanized aap kya kar sakte) a speaker uses to ask what the assistant can do; a polite-form surface for the capability query."',
  '      word "तुम क्या कर सकते"',
  '        description "Hindi phrase (romanized tum kya kar sakte) a speaker uses to ask what you can do; an informal-form surface for the capability query."',
  '      word "क्या क्या कर सकते"',
  '        description "Hindi phrase (romanized kya kya kar sakte) a speaker uses to ask what all you can do; a surface enumerating capabilities."',
  '    lexeme "zh"',
  '      word "你能做什么"',
  '        description "Chinese phrase (pinyin ni neng zuo shenme) a speaker uses to ask what the assistant can do; the canonical surface for the capability query."',
  '      word "你会做什么"',
  '        description "Chinese phrase (pinyin ni hui zuo shenme) a speaker uses to ask what the assistant knows how to do; a skill-framed surface for the capability query."',
  '      word "你有什么功能"',
  '        description "Chinese phrase (pinyin ni you shenme gongneng) a speaker uses to ask what features the assistant has; a feature-framed surface for the capability query."',
  '      word "你能干什么"',
  '        description "Chinese phrase (pinyin ni neng gan shenme) a speaker uses to ask what the assistant can do; a colloquial surface for the capability query."',
  '  meaning "capability_query_more"',
  '    gloss "the user asking what else the assistant can do — a follow-up that requests capabilities beyond those already named"',
  '    wiktionary "else"',
  '    defined_by "capability_query"',
  '    defined_by "capability"',
  '    role "capability_query_more"',
  '    lexeme "en"',
  '      word "what else can you do"',
  '        description "English phrase a speaker uses to ask what further things the assistant can do beyond those already named; the canonical surface for the follow-up capability query."',
  '      word "what else do you do"',
  '        description "English phrase a speaker uses to ask what other things the assistant does; a synonym surface for the follow-up capability query."',
  '      word "what other things can you do"',
  '        description "English phrase a speaker uses to ask for additional capabilities; an explicit surface for the follow-up capability query."',
  '    lexeme "ru"',
  '      word "что ещё ты умеешь"',
  '        description "Russian phrase (romanized chto eshchyo ty umeesh) a speaker uses to ask what else the assistant can do; a yo-spelled surface for the follow-up capability query."',
  '      word "что еще ты умеешь"',
  '        description "Russian phrase (romanized chto eshche ty umeesh) a speaker uses to ask what else the assistant can do; an e-spelled variant for the follow-up capability query."',
  '      word "что ещё можешь"',
  '        description "Russian phrase (romanized chto eshchyo mozhesh) a speaker uses to ask what else you can do; a subjectless yo-spelled surface for the follow-up capability query."',
  '      word "что еще можешь"',
  '        description "Russian phrase (romanized chto eshche mozhesh) a speaker uses to ask what else you can do; a subjectless e-spelled variant for the follow-up capability query."',
  '      word "что ты ещё умеешь"',
  '        description "Russian phrase (romanized chto ty eshchyo umeesh) a speaker uses to ask what else the assistant can do; a yo-spelled word-order variant for the follow-up capability query."',
  '      word "что ты еще умеешь"',
  '        description "Russian phrase (romanized chto ty eshche umeesh) a speaker uses to ask what else the assistant can do; an e-spelled word-order variant for the follow-up capability query."',
  '    lexeme "hi"',
  '      word "और आप क्या कर सकते"',
  '        description "Hindi phrase (romanized aur aap kya kar sakte) a speaker uses to ask what else the assistant can do; a polite-form surface for the follow-up capability query."',
  '      word "और क्या कर सकते"',
  '        description "Hindi phrase (romanized aur kya kar sakte) a speaker uses to ask what else you can do; a surface for the follow-up capability query."',
  '    lexeme "zh"',
  '      word "你还能做什么"',
  '        description "Chinese phrase (pinyin ni hai neng zuo shenme) a speaker uses to ask what else the assistant can do; the canonical surface for the follow-up capability query."',
  '      word "你还会做什么"',
  '        description "Chinese phrase (pinyin ni hai hui zuo shenme) a speaker uses to ask what else the assistant knows how to do; a skill-framed surface for the follow-up capability query."',
  '  meaning "self_fact_query"',
  '    gloss "the user asking the assistant to list the facts it knows about itself"',
  '    wiktionary "fact"',
  '    defined_by "fact"',
  '    defined_by "self_reference"',
  '    defined_by "inquiry"',
  '    role "self_fact_query"',
  '    lexeme "en"',
  '      word "facts you know about yourself"',
  '        description "English phrase a speaker uses to ask the assistant to list the facts it knows about itself; the canonical surface for the self-fact query."',
  '      word "facts about yourself"',
  '        description "English phrase a speaker uses to ask for facts concerning the assistant itself; a shorter surface for the self-fact query."',
  '      word "self facts"',
  '        description "English phrase a speaker uses as a terse label for facts the assistant knows about itself; a compact surface for the self-fact query."',
  '      word "list all facts you know about yourself"',
  '        description "English phrase a speaker uses to ask the assistant to enumerate every fact it knows about itself; an imperative surface for the self-fact query."',
  '    lexeme "ru"',
  '      word "какие факты ты знаешь о себе"',
  '        description "Russian phrase (romanized kakie fakty ty znaesh o sebe) a speaker uses to ask which facts the assistant knows about itself; the canonical surface for the self-fact query."',
  '      word "факты о себе"',
  '        description "Russian phrase (romanized fakty o sebe) a speaker uses to ask for facts about oneself; a shorter surface for the self-fact query."',
  '    lexeme "hi"',
  '      word "अपने बारे में तथ्य"',
  '        description "Hindi phrase (romanized apne baare mein tathya) a speaker uses to ask for facts about the assistant itself; the canonical surface for the self-fact query."',
  '      word "स्वयं के बारे में तथ्य"',
  '        description "Hindi phrase (romanized svayam ke baare mein tathya) a speaker uses to ask for facts about oneself; a more formal surface for the self-fact query."',
  '    lexeme "zh"',
  '      word "关于你自己的事实"',
  '        description "Chinese phrase (pinyin guanyu ni ziji de shishi) a speaker uses to ask for facts about the assistant itself; the canonical surface for the self-fact query."',
  '      word "自我事实"',
  '        description "Chinese phrase (pinyin ziwo shishi) a speaker uses as a terse label for facts about oneself; a compact surface for the self-fact query."',
  '  meaning "self_introduction_request"',
  '    gloss "the user asking the assistant to introduce itself or to get acquainted"',
  '    wiktionary "introduce"',
  '    defined_by "introduction"',
  '    defined_by "self_reference"',
  '    defined_by "inquiry"',
  '    role "self_introduction_request"',
  '    lexeme "en"',
  '      word "tell me about yourself"',
  '        description "English phrase a speaker uses to ask the assistant to describe itself; the canonical surface for the self-introduction request."',
  '      word "introduce yourself"',
  '        description "English phrase a speaker uses to ask the assistant to present who it is; an imperative surface for the self-introduction request."',
  '      word "let s get acquainted"',
  '        description "English phrase a speaker uses to propose getting acquainted; an apostrophe-spaced spelling of lets get acquainted."',
  '      word "lets get acquainted"',
  '        description "English phrase a speaker uses to propose getting acquainted; an apostrophe-free spelling variant for the self-introduction request."',
  '      word "let us get acquainted"',
  '        description "English phrase a speaker uses to propose getting acquainted; the full uncontracted form for the self-introduction request."',
  '      word "let s get to know each other"',
  '        description "English phrase a speaker uses to propose mutual acquaintance; a longer surface for the self-introduction request."',
  '    lexeme "ru"',
  '      word "расскажи о себе"',
  '        description "Russian phrase (romanized rasskazhi o sebe) a speaker uses to ask the assistant to tell about itself; the canonical surface for the self-introduction request."',
  '      word "расскажи мне о себе"',
  '        description "Russian phrase (romanized rasskazhi mne o sebe) a speaker uses to ask the assistant to tell me about itself; an explicit-object surface for the self-introduction request."',
  '      word "расскажи про себя"',
  '        description "Russian phrase (romanized rasskazhi pro sebya) a speaker uses to ask the assistant to tell about itself; a pro-framed variant for the self-introduction request."',
  '      word "опиши себя"',
  '        description "Russian phrase (romanized opishi sebya) a speaker uses to ask the assistant to describe itself; a describe-framed surface for the self-introduction request."',
  '      word "представься"',
  '        description "Russian phrase (romanized predstavsya) a speaker uses to ask the assistant to introduce itself; an imperative surface for the self-introduction request."',
  '      word "давай знакомиться"',
  '        description "Russian phrase (romanized davay znakomitsya) a speaker uses to propose getting acquainted; an informal surface for the self-introduction request."',
  '      word "давай познакомимся"',
  '        description "Russian phrase (romanized davay poznakomimsya) a speaker uses to propose that we get acquainted; an informal surface for the self-introduction request."',
  '      word "давайте познакомимся"',
  '        description "Russian phrase (romanized davayte poznakomimsya) a speaker uses to politely propose that we get acquainted; a polite-form surface for the self-introduction request."',
  '    lexeme "hi"',
  '      word "अपने बारे में बताओ"',
  '        description "Hindi phrase (romanized apne baare mein batao) a speaker uses to ask the assistant to tell about itself; the canonical surface for the self-introduction request."',
  '      word "अपना परिचय दो"',
  '        description "Hindi phrase (romanized apna parichay do) a speaker uses to ask the assistant to give its introduction; an introduce-framed surface for the self-introduction request."',
  '      word "चलो परिचय करते हैं"',
  '        description "Hindi phrase (romanized chalo parichay karte hain) a speaker uses to propose let us get acquainted; an informal surface for the self-introduction request."',
  '      word "आइए परिचय करें"',
  '        description "Hindi phrase (romanized aaiye parichay karen) a speaker uses to politely propose that we get acquainted; a polite-form surface for the self-introduction request."',
  '      word "चलो एक दूसरे को जानें"',
  '        description "Hindi phrase (romanized chalo ek dusre ko jaanen) a speaker uses to propose that we get to know each other; a mutual-acquaintance surface for the self-introduction request."',
  '    lexeme "zh"',
  '      word "介绍一下你自己"',
  '        description "Chinese phrase (pinyin jieshao yixia ni ziji) a speaker uses to ask the assistant to introduce itself; the canonical surface for the self-introduction request."',
  '      word "告诉我你自己"',
  '        description "Chinese phrase (pinyin gaosu wo ni ziji) a speaker uses to ask the assistant to tell me about itself; a tell-framed surface for the self-introduction request."',
  '      word "介紹一下你自己"',
  '        description "Chinese phrase (pinyin jieshao yixia ni ziji) a speaker uses to ask the assistant to introduce itself; the traditional-character variant for the self-introduction request."',
  '      word "告訴我你自己"',
  '        description "Chinese phrase (pinyin gaosu wo ni ziji) a speaker uses to ask the assistant to tell me about itself; the traditional-character variant for the self-introduction request."',
  '      word "我们认识一下"',
  '        description "Chinese phrase (pinyin women renshi yixia) a speaker uses to propose that we get acquainted; a surface for the self-introduction request."',
  '      word "认识一下吧"',
  '        description "Chinese phrase (pinyin renshi yixia ba) a speaker uses to suggest getting acquainted; a softer-particle surface for the self-introduction request."',
  '      word "让我们认识一下"',
  '        description "Chinese phrase (pinyin rang women renshi yixia) a speaker uses to propose let us get acquainted; a let-framed surface for the self-introduction request."',
  '  meaning "conversation_summary_directive"',
  '    gloss "the verb or noun that asks the assistant to condense the running dialogue into a short summary"',
  '    wiktionary "summarize"',
  '    defined_by "inquiry"',
  '    defined_by "answer"',
  '    role "conversation_summary_directive"',
  '    lexeme "en"',
  '      word "summarize"',
  '        description "English verb asking for a condensed account; the canonical American-spelling surface for the conversation-summary directive."',
  '      word "summarise"',
  '        description "English verb asking for a condensed account; the British-spelling surface for the conversation-summary directive."',
  '      word "summary"',
  '        description "English noun naming the condensed account itself; the bare-noun surface for the conversation-summary directive."',
  '    lexeme "ru"',
  '      word "суммируй"',
  '        description "Russian verb (romanized summiruy) asking the assistant to sum up the dialogue; the informal imperative surface for the conversation-summary directive."',
  '      word "суммируйте"',
  '        description "Russian verb (romanized summiruyte) asking the assistant to sum up the dialogue; the polite-plural imperative surface for the conversation-summary directive."',
  '      word "резюмируй"',
  '        description "Russian verb (romanized rezyumiruy) asking the assistant to summarize the dialogue; the informal imperative surface for the conversation-summary directive."',
  '      word "резюмируйте"',
  '        description "Russian verb (romanized rezyumiruyte) asking the assistant to summarize the dialogue; the polite-plural imperative surface for the conversation-summary directive."',
  '      word "резюме"',
  '        description "Russian noun (romanized rezyume) naming a summary; the bare-noun surface for the conversation-summary directive."',
  '    lexeme "hi"',
  '      word "सारांश"',
  '        description "Hindi noun (romanized saaraansh) naming a summary; the bare-noun surface for the conversation-summary directive."',
  '      word "संक्षेप"',
  '        description "Hindi noun (romanized sankshep) naming a condensation or abstract; an alternative surface for the conversation-summary directive."',
  '      word "सारांशित"',
  '        description "Hindi verb stem (romanized saaraanshit) meaning summarized; the verb surface for the conversation-summary directive."',
  '    lexeme "zh"',
  '      word "总结"',
  '        description "Chinese verb or noun (pinyin zongjie) meaning to summarize or a summary; the simplified-character surface for the conversation-summary directive."',
  '      word "總結"',
  '        description "Chinese verb or noun (pinyin zongjie) meaning to summarize or a summary; the traditional-character surface for the conversation-summary directive."',
  '      word "概括"',
  '        description "Chinese verb (pinyin gaikuo) meaning to sum up or generalize; an alternative surface for the conversation-summary directive."',
  '      word "摘要"',
  '        description "Chinese noun (pinyin zhaiyao) meaning an abstract or summary; an alternative surface for the conversation-summary directive."',
  '      word "归纳"',
  '        description "Chinese verb (pinyin guina) meaning to summarize or induce; the simplified-character surface for the conversation-summary directive."',
  '      word "歸納"',
  '        description "Chinese verb (pinyin guina) meaning to summarize or induce; the traditional-character surface for the conversation-summary directive."',
  '  meaning "conversation_reference"',
  '    gloss "the noun naming the running dialogue between the user and the assistant — the object a summary request points at"',
  '    wiktionary "conversation"',
  '    defined_by "inquiry"',
  '    defined_by "answer"',
  '    role "conversation_reference"',
  '    lexeme "en"',
  '      word "conversation"',
  '        description "English noun for the running dialogue between the user and the assistant; the canonical object of a conversation-summary request."',
  '      word "chat"',
  '        description "English noun for an informal conversation; an alternative object surface for a conversation-summary request."',
  '      word "dialogue"',
  '        description "English noun for an exchange of turns between participants; an alternative object surface for a conversation-summary request."',
  '      word "dialog"',
  '        description "English noun for an exchange of turns; the American-spelling object surface for a conversation-summary request."',
  '      word "discussion"',
  '        description "English noun for a conversation about a topic; an alternative object surface for a conversation-summary request."',
  '    lexeme "ru"',
  '      word "беседа"',
  '        description "Russian noun (romanized beseda) for a conversation; the nominative object surface for a conversation-summary request."',
  '      word "беседы"',
  '        description "Russian noun (romanized besedy) for a conversation; the genitive surface for a conversation-summary request."',
  '      word "беседу"',
  '        description "Russian noun (romanized besedu) for a conversation; the accusative surface for a conversation-summary request."',
  '      word "беседе"',
  '        description "Russian noun (romanized besede) for a conversation; the prepositional surface for a conversation-summary request."',
  '      word "разговор"',
  '        description "Russian noun (romanized razgovor) for a conversation; the nominative object surface for a conversation-summary request."',
  '      word "разговора"',
  '        description "Russian noun (romanized razgovora) for a conversation; the genitive surface for a conversation-summary request."',
  '      word "разговоре"',
  '        description "Russian noun (romanized razgovore) for a conversation; the prepositional surface for a conversation-summary request."',
  '      word "разговором"',
  '        description "Russian noun (romanized razgovorom) for a conversation; the instrumental surface for a conversation-summary request."',
  '      word "чат"',
  '        description "Russian noun (romanized chat) for an online chat; the nominative object surface for a conversation-summary request."',
  '      word "чата"',
  '        description "Russian noun (romanized chata) for an online chat; the genitive surface for a conversation-summary request."',
  '      word "чате"',
  '        description "Russian noun (romanized chate) for an online chat; the prepositional surface for a conversation-summary request."',
  '      word "диалог"',
  '        description "Russian noun (romanized dialog) for a dialogue; an alternative object surface for a conversation-summary request."',
  '      word "диалога"',
  '        description "Russian noun (romanized dialoga) for a dialogue; the genitive surface for a conversation-summary request."',
  '    lexeme "hi"',
  '      word "बातचीत"',
  '        description "Hindi noun (romanized baatcheet) for a conversation; the canonical object surface for a conversation-summary request."',
  '      word "संवाद"',
  '        description "Hindi noun (romanized samvaad) for a dialogue; an alternative object surface for a conversation-summary request."',
  '      word "वार्तालाप"',
  '        description "Hindi noun (romanized vaartaalaap) for a conversation or discourse; an alternative object surface for a conversation-summary request."',
  '    lexeme "zh"',
  '      word "对话"',
  '        description "Chinese noun (pinyin duihua) for a dialogue or conversation; the simplified-character object surface for a conversation-summary request."',
  '      word "對話"',
  '        description "Chinese noun (pinyin duihua) for a dialogue or conversation; the traditional-character object surface for a conversation-summary request."',
  '      word "聊天"',
  '        description "Chinese noun or verb (pinyin liaotian) for chatting; an informal object surface for a conversation-summary request."',
  '      word "会话"',
  '        description "Chinese noun (pinyin huihua) for a conversation or session; the simplified-character object surface for a conversation-summary request."',
  '      word "會話"',
  '        description "Chinese noun (pinyin huihua) for a conversation or session; the traditional-character object surface for a conversation-summary request."',
  '      word "谈话"',
  '        description "Chinese noun (pinyin tanhua) for a talk or conversation; the simplified-character object surface for a conversation-summary request."',
  '      word "談話"',
  '        description "Chinese noun (pinyin tanhua) for a talk or conversation; the traditional-character object surface for a conversation-summary request."',
  '  meaning "conversation_summary_phrase"',
  '    gloss "a complete standalone phrasing that asks the assistant to recount or summarize what the dialogue has covered"',
  '    wiktionary "conversation"',
  '    defined_by "inquiry"',
  '    defined_by "conversation_reference"',
  '    role "conversation_summary_phrase"',
  '    lexeme "en"',
  '      word "what have we talked about"',
  '        description "English standalone phrasing asking the assistant to recall the topics of the running conversation."',
  '      word "what did we talk about"',
  '        description "English standalone phrasing asking the assistant to recall what the conversation covered."',
  '      word "what have we discussed"',
  '        description "English standalone phrasing asking the assistant to recall what has been discussed."',
  '      word "summary of our chat"',
  '        description "English standalone phrasing naming a summary of the running chat; matches even when it does not lead the prompt."',
  '      word "summary of our conversation"',
  '        description "English standalone phrasing naming a summary of the running conversation; matches even when it does not lead the prompt."',
  '      word "summarize so far"',
  '        description "English standalone phrasing asking the assistant to summarize the conversation up to this point (American spelling)."',
  '      word "summarise so far"',
  '        description "English standalone phrasing asking the assistant to summarize the conversation up to this point (British spelling)."',
  '    lexeme "ru"',
  '      word "о чём мы разговаривали"',
  '        description "Russian standalone phrasing (romanized o chyom my razgovarivali) asking what the conversation was about; the yo-spelled surface."',
  '      word "о чем мы разговаривали"',
  '        description "Russian standalone phrasing (romanized o chem my razgovarivali) asking what the conversation was about; the ye-spelled surface."',
  '      word "о чём мы говорили"',
  '        description "Russian standalone phrasing (romanized o chyom my govorili) asking what we talked about; the yo-spelled surface."',
  '      word "о чем мы говорили"',
  '        description "Russian standalone phrasing (romanized o chem my govorili) asking what we talked about; the ye-spelled surface."',
  '    lexeme "hi"',
  '      word "हमने किस बारे में बात की"',
  '        description "Hindi standalone phrasing (romanized humne kis baare mein baat ki) asking what the conversation was about."',
  '      word "हमने क्या बात की"',
  '        description "Hindi standalone phrasing (romanized humne kya baat ki) asking what we talked about."',
  '    lexeme "zh"',
  '      word "我们聊了什么"',
  '        description "Chinese standalone phrasing (pinyin women liao le shenme) asking what the conversation covered; simplified surface."',
  '      word "我们谈了什么"',
  '        description "Chinese standalone phrasing (pinyin women tan le shenme) asking what we talked about; simplified surface."',
  '      word "我们说了什么"',
  '        description "Chinese standalone phrasing (pinyin women shuo le shenme) asking what we said; simplified surface."',
  '      word "我們聊了什麼"',
  '        description "Chinese standalone phrasing (pinyin women liao le shenme) asking what the conversation covered; traditional surface."',
  '  meaning "conversation_summary_courtesy"',
  '    gloss "a polite or elliptical frame that asks the assistant to summarize without naming the conversation object directly"',
  '    wiktionary "summary"',
  '    defined_by "inquiry"',
  '    defined_by "conversation_summary_directive"',
  '    role "conversation_summary_courtesy"',
  '    lexeme "en"',
  '      word "give me a summary"',
  '        description "English polite frame asking the assistant to produce a summary; an objectless courtesy surface for the conversation-summary request."',
  '      word "can you summarize"',
  '        description "English polite frame asking whether the assistant can summarize; an objectless courtesy surface (American spelling)."',
  '      word "can you summarise"',
  '        description "English polite frame asking whether the assistant can summarize; an objectless courtesy surface (British spelling)."',
  '      word "please summarize"',
  '        description "English polite frame asking the assistant to summarize; an objectless courtesy surface (American spelling)."',
  '      word "please summarise"',
  '        description "English polite frame asking the assistant to summarize; an objectless courtesy surface (British spelling)."',
  '    lexeme "ru"',
  '      word "подведи итог"',
  '        description "Russian polite frame (romanized podvedi itog) asking the assistant to sum up; an objectless courtesy surface for the conversation-summary request."',
  '      word "подведи итоги"',
  '        description "Russian polite frame (romanized podvedi itogi) asking the assistant to sum up the results; a plural-object courtesy surface."',
  '      word "краткое резюме"',
  '        description "Russian phrase (romanized kratkoye rezyume) asking for a brief summary; an objectless courtesy surface for the conversation-summary request."',
  '      word "сделай резюме"',
  '        description "Russian phrase (romanized sdelay rezyume) asking the assistant to make a summary; an objectless courtesy surface."',
  '      word "краткое содержание"',
  '        description "Russian phrase (romanized kratkoye soderzhaniye) asking for a brief account; an objectless courtesy surface for the conversation-summary request."',
  '    lexeme "hi"',
  '      word "सार दो"',
  '        description "Hindi phrase (romanized saar do) asking the assistant to give the gist; an objectless courtesy surface for the conversation-summary request."',
  '      word "सारांश दो"',
  '        description "Hindi phrase (romanized saaraansh do) asking the assistant to give a summary; an objectless courtesy surface."',
  '      word "संक्षेप में बताओ"',
  '        description "Hindi phrase (romanized sankshep mein batao) asking the assistant to tell briefly; an objectless courtesy surface for the conversation-summary request."',
  '    lexeme "zh"',
  '      word "帮我总结"',
  '        description "Chinese phrase (pinyin bang wo zongjie) asking the assistant to help summarize; an objectless courtesy surface; simplified surface."',
  '      word "帮我概括"',
  '        description "Chinese phrase (pinyin bang wo gaikuo) asking the assistant to help sum up; an objectless courtesy surface; simplified surface."',
  '      word "请总结"',
  '        description "Chinese phrase (pinyin qing zongjie) politely asking the assistant to summarize; an objectless courtesy surface; simplified surface."',
  '      word "请概括"',
  '        description "Chinese phrase (pinyin qing gaikuo) politely asking the assistant to sum up; an objectless courtesy surface; simplified surface."',
  '      word "总结一下"',
  '        description "Chinese phrase (pinyin zongjie yixia) asking the assistant to do a quick summary; an objectless courtesy surface; simplified surface."',
  '      word "概括一下"',
  '        description "Chinese phrase (pinyin gaikuo yixia) asking the assistant to do a quick sum-up; an objectless courtesy surface; simplified surface."',
  '  meaning "who_is_question"',
  '    gloss "a who-is question about a person or named entity — who is X, кто такой X, X कौन है, X是谁. It is recognised so the assistant can report a knowledge-base miss and offer a typo correction instead of inventing a biography. Two roles split by slot encode the word order: who_question_lead fronts the interrogative (English and Russian, head-initial) and is detected with starts_with, while who_question_tail postposes it (Hindi and Chinese, head-final) and is detected with ends_with. The entity itself is pulled out separately by the concept-query extractor, so the order within each role does not matter — any matching lead or tail is enough."',
  '    wiktionary "who"',
  '    defined_by "inquiry"',
  '    role "who_question_lead"',
  '    role "who_question_tail"',
  '    lexeme "en"',
  '      word "who is …"',
  '        description "English interrogative lead; starts_with who is (trailing space), the entity follows."',
  '      word "who was …"',
  '        description "English interrogative lead; starts_with who was (trailing space), the entity follows."',
  '      word "who are …"',
  '        description "English interrogative lead; starts_with who are (trailing space), the entity follows."',
  '    lexeme "ru"',
  '      word "кто такой …"',
  '        description "Russian interrogative lead (romanized kto takoy); the masculine who-is frame, the entity follows."',
  '      word "кто такая …"',
  '        description "Russian interrogative lead (romanized kto takaya); the feminine who-is frame, the entity follows."',
  '      word "кто это …"',
  '        description "Russian interrogative lead (romanized kto eto, who is this); the entity follows."',
  '      word "кто …"',
  '        description "Russian bare interrogative lead (romanized kto, who); the entity follows."',
  '    lexeme "hi"',
  '      word "… कौन है"',
  '        description "Hindi interrogative tail (romanized kaun hai, who is); head-final, the entity precedes; ends_with the tail (leading space)."',
  '      word "… कौन हैं"',
  '        description "Hindi polite interrogative tail (romanized kaun hain, who are); head-final, the entity precedes."',
  '    lexeme "zh"',
  '      word "…是谁"',
  '        description "Chinese interrogative tail (pinyin shi shei, is who); head-final, the entity precedes; simplified surface."',
  '      word "…是誰"',
  '        description "Chinese interrogative tail (pinyin shi shei, is who); head-final, the entity precedes; traditional surface."',
  '  meaning "interrogative_opener"',
  '    gloss "the generic interrogative opener — the class of question words (the wh-words) that front a content question rather than a yes or no question. When a prompt opens with one of these the intent classifier reads it as a Question. English and Russian are head-initial, so the question word starts the prompt and is detected with starts_with; a trailing space follows the bare word, so what marks what is the capital but not whatever, and who marks who are you but not whoever. Hindi and Chinese are head-final, so their question words need not begin the sentence; they are carried here for language coverage but are never matched positionally. The surfaces are bare single words rather than openers with slots, so any one of them at the front is enough to classify the prompt as a question."',
  '    wiktionary "interrogative"',
  '    defined_by "inquiry"',
  '    role "interrogative_opener"',
  '    lexeme "en"',
  '      word "what"',
  '        description "English interrogative pronoun; head-initial opener, starts_with what (trailing space) marks a content question."',
  '      word "who"',
  '        description "English interrogative pronoun for a person; head-initial opener, starts_with who (trailing space)."',
  '      word "why"',
  '        description "English interrogative adverb of reason; head-initial opener, starts_with why (trailing space)."',
  '      word "where"',
  '        description "English interrogative adverb of place; head-initial opener, starts_with where (trailing space)."',
  '      word "when"',
  '        description "English interrogative adverb of time; head-initial opener, starts_with when (trailing space)."',
  '      word "how"',
  '        description "English interrogative adverb of manner; head-initial opener, starts_with how (trailing space)."',
  '      word "which"',
  '        description "English interrogative determiner selecting among alternatives; head-initial opener, starts_with which (trailing space)."',
  '    lexeme "ru"',
  '      word "что"',
  '        description "Russian interrogative pronoun (romanized chto, what); head-initial opener, starts_with что (trailing space)."',
  '      word "кто"',
  '        description "Russian interrogative pronoun (romanized kto, who); head-initial opener, starts_with кто (trailing space)."',
  '      word "почему"',
  '        description "Russian interrogative adverb of reason (romanized pochemu, why); head-initial opener, starts_with почему (trailing space)."',
  '      word "где"',
  '        description "Russian interrogative adverb of place (romanized gde, where); head-initial opener, starts_with где (trailing space)."',
  '      word "когда"',
  '        description "Russian interrogative adverb of time (romanized kogda, when); head-initial opener, starts_with когда (trailing space)."',
  '      word "как"',
  '        description "Russian interrogative adverb of manner (romanized kak, how); head-initial opener, starts_with как (trailing space)."',
  '    lexeme "hi"',
  '      word "क्या"',
  '        description "Hindi interrogative (romanized kya, what); carried for language coverage — Hindi is head-final, so the opener is not matched positionally."',
  '      word "कौन"',
  '        description "Hindi interrogative (romanized kaun, who); carried for coverage, not matched positionally (head-final)."',
  '      word "क्यों"',
  '        description "Hindi interrogative (romanized kyon, why); carried for coverage, not matched positionally (head-final)."',
  '      word "कहाँ"',
  '        description "Hindi interrogative (romanized kahan, where); carried for coverage, not matched positionally (head-final)."',
  '      word "कब"',
  '        description "Hindi interrogative (romanized kab, when); carried for coverage, not matched positionally (head-final)."',
  '      word "कैसे"',
  '        description "Hindi interrogative (romanized kaise, how); carried for coverage, not matched positionally (head-final)."',
  '      word "कौनसा"',
  '        description "Hindi interrogative (romanized kaunsa, which); carried for coverage, not matched positionally (head-final)."',
  '    lexeme "zh"',
  '      word "什么"',
  '        description "Chinese interrogative (pinyin shenme, what); carried for coverage, not matched positionally (head-final); simplified surface."',
  '      word "谁"',
  '        description "Chinese interrogative (pinyin shei, who); carried for coverage, not matched positionally (head-final); simplified surface."',
  '      word "为什么"',
  '        description "Chinese interrogative (pinyin weishenme, why); carried for coverage, not matched positionally (head-final); simplified surface."',
  '      word "哪里"',
  '        description "Chinese interrogative (pinyin nali, where); carried for coverage, not matched positionally (head-final); simplified surface."',
  '      word "何时"',
  '        description "Chinese interrogative (pinyin heshi, when); carried for coverage, not matched positionally (head-final)."',
  '      word "如何"',
  '        description "Chinese interrogative (pinyin ruhe, how); carried for coverage, not matched positionally (head-final)."',
  '      word "哪个"',
  '        description "Chinese interrogative (pinyin nage, which); carried for coverage, not matched positionally (head-final); simplified surface."',
  "meanings",
  '  meaning "mechanism_inquiry"',
  '    gloss "an inquiry into how something works — its internal mechanism or operating principle. The concept a how-it-works prompt expresses, independent of the language or phrasing used. Each surface marks the subject position with the ellipsis … (U+2026): no ellipsis is a bare phrase, a trailing ellipsis is a prefix surface, a leading ellipsis is a suffix surface, and a middle ellipsis is a circumfix surface."',
  '    wiktionary "how"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "mechanism_inquiry"',
  '    lexeme "en"',
  '      word "how it works"',
  '        description "English bare how-it-works phrase with no subject slot; asks for the mechanism of the current topic."',
  '      word "how does it work"',
  '        description "English bare how-does-it-work phrase with no subject slot; asks for the mechanism of the current topic."',
  '      word "how does …"',
  '        description "English prefix surface; the literal before the … slot introduces a mechanism question whose subject follows (how does X)."',
  '      word "how do …"',
  '        description "English prefix surface for a plural subject; the subject follows the … slot (how do X)."',
  '      word "how did …"',
  '        description "English past-tense prefix surface; asks how the subject after the … slot worked (how did X)."',
  '      word "how is …"',
  '        description "English prefix surface asking how the subject after the … slot is built or arranged (how is X)."',
  '      word "how … works"',
  '        description "English circumfix surface; the subject sits between how and works in the … slot (how X works)."',
  '      word "how … work"',
  '        description "English circumfix surface for a plural subject between how and work in the … slot (how X work)."',
  '    lexeme "ru"',
  '      word "как это работает"',
  '        description "Russian bare how-it-works phrase (romanized kak eto rabotaet) with no subject slot."',
  '      word "как оно работает"',
  '        description "Russian bare how-it-works phrase (romanized kak ono rabotaet) with no subject slot."',
  '      word "как устроен …"',
  '        description "Russian masculine prefix surface (romanized kak ustroen) asking how the subject after the … slot is built."',
  '      word "как устроена …"',
  '        description "Russian feminine prefix surface (romanized kak ustroena) asking how the subject after the … slot is built."',
  '      word "как устроено …"',
  '        description "Russian neuter prefix surface (romanized kak ustroeno) asking how the subject after the … slot is built."',
  '      word "как устроены …"',
  '        description "Russian plural prefix surface (romanized kak ustroeny) asking how the subjects after the … slot are built."',
  '      word "как работает …"',
  '        description "Russian prefix surface (romanized kak rabotaet) asking how the subject after the … slot works."',
  '      word "как работают …"',
  '        description "Russian plural prefix surface (romanized kak rabotayut) asking how the subjects after the … slot work."',
  '      word "как … работает"',
  '        description "Russian circumfix surface (romanized kak … rabotaet); the subject sits in the … slot between kak and rabotaet."',
  '      word "как … работают"',
  '        description "Russian plural circumfix surface (romanized kak … rabotayut); the subject sits in the … slot."',
  '      word "… как работает"',
  '        description "Russian suffix surface (romanized … kak rabotaet); the subject precedes the trailing how-it-works phrase in the leading … slot."',
  '      word "… как работают"',
  '        description "Russian plural suffix surface (romanized … kak rabotayut); the subject precedes the trailing phrase in the leading … slot."',
  '    lexeme "hi"',
  '      word "यह कैसे काम करता है"',
  '        description "Hindi bare how-it-works phrase (romanized yah kaise kaam karta hai) with no subject slot."',
  '      word "यह कैसे काम करती है"',
  '        description "Hindi bare how-it-works phrase, feminine (romanized yah kaise kaam karti hai), with no subject slot."',
  '      word "यह कैसे काम करता"',
  '        description "Hindi bare how-it-works phrase, clipped (romanized yah kaise kaam karta), with no subject slot."',
  '      word "… कैसे काम करता है"',
  '        description "Hindi suffix surface (romanized … kaise kaam karta hai); the subject precedes the trailing how-it-works phrase in the leading … slot."',
  '      word "… कैसे काम करती है"',
  '        description "Hindi feminine suffix surface (romanized … kaise kaam karti hai); the subject is in the leading … slot."',
  '      word "… कैसे काम करते हैं"',
  '        description "Hindi plural suffix surface (romanized … kaise kaam karte hain); the subject is in the leading … slot."',
  '      word "… कैसे काम करता"',
  '        description "Hindi clipped suffix surface (romanized … kaise kaam karta); the subject is in the leading … slot."',
  '      word "… कैसे काम करती"',
  '        description "Hindi feminine clipped suffix surface (romanized … kaise kaam karti); the subject is in the leading … slot."',
  '      word "… कैसे काम करते"',
  '        description "Hindi plural clipped suffix surface (romanized … kaise kaam karte); the subject is in the leading … slot."',
  '    lexeme "zh"',
  '      word "这是如何工作的"',
  '        description "Chinese bare how-it-works phrase (pinyin zhe shi ruhe gongzuo de) with no subject slot."',
  '      word "这是怎么工作的"',
  '        description "Chinese bare how-it-works phrase (pinyin zhe shi zenme gongzuo de) with no subject slot."',
  '      word "这个如何工作"',
  '        description "Chinese bare how-it-works phrase (pinyin zhege ruhe gongzuo) with no subject slot."',
  '      word "它如何工作"',
  '        description "Chinese bare how-it-works phrase (pinyin ta ruhe gongzuo) with no subject slot."',
  '      word "它是如何工作的"',
  '        description "Chinese bare how-it-works phrase (pinyin ta shi ruhe gongzuo de) with no subject slot."',
  '      word "它怎么工作"',
  '        description "Chinese bare how-it-works phrase (pinyin ta zenme gongzuo) with no subject slot."',
  '      word "… 是如何工作的"',
  '        description "Chinese suffix surface (pinyin … shi ruhe gongzuo de) with a leading space; the subject is in the leading … slot."',
  '      word "…是如何工作的"',
  '        description "Chinese suffix surface (pinyin … shi ruhe gongzuo de) with no leading space; the subject is in the leading … slot."',
  '      word "… 是怎么工作的"',
  '        description "Chinese suffix surface (pinyin … shi zenme gongzuo de) with a leading space; the subject is in the leading … slot."',
  '      word "…是怎么工作的"',
  '        description "Chinese suffix surface (pinyin … shi zenme gongzuo de) with no leading space; the subject is in the leading … slot."',
  '      word "… 如何工作"',
  '        description "Chinese suffix surface (pinyin … ruhe gongzuo) with a leading space; the subject is in the leading … slot."',
  '      word "…如何工作"',
  '        description "Chinese suffix surface (pinyin … ruhe gongzuo) with no leading space; the subject is in the leading … slot."',
  '      word "… 怎么工作"',
  '        description "Chinese suffix surface (pinyin … zenme gongzuo) with a leading space; the subject is in the leading … slot."',
  '      word "…怎么工作"',
  '        description "Chinese suffix surface (pinyin … zenme gongzuo) with no leading space; the subject is in the leading … slot."',
  '      word "… 的工作原理是什么"',
  '        description "Chinese suffix surface (pinyin … de gongzuo yuanli shi shenme) with a leading space; asks the working principle of the subject in the leading … slot."',
  '      word "…的工作原理是什么"',
  '        description "Chinese suffix surface (pinyin … de gongzuo yuanli shi shenme) with no leading space; asks the working principle of the subject in the leading … slot."',
  '  meaning "procedural_request"',
  '    gloss "a request for the ordered steps to accomplish a task — the how-to-X question that asks for a procedure rather than a mechanism, independent of phrasing language. Each surface is a prefix carrying the … slot at the end, where the task follows. A surface may name the canonical operation in an action child (do, perform, implement, create, write); when it does not, the operation is taken from the first word of the task."',
  '    wiktionary "procedure"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "procedural_request"',
  '    lexeme "en"',
  '      word "please tell me how to …"',
  '        description "English polite prefix surface; the task follows the … slot, with the operation taken from its first word."',
  '      word "please show me how to …"',
  '        description "English polite prefix surface requesting a demonstration; the task follows the … slot, operation from its first word."',
  '      word "tell me how to …"',
  '        description "English prefix surface; the task follows the … slot, operation from its first word."',
  '      word "show me how to …"',
  '        description "English prefix surface requesting a walkthrough; the task follows the … slot, operation from its first word."',
  '      word "what are the steps to …"',
  '        description "English prefix surface asking for the steps; the task follows the … slot, operation from its first word."',
  '      word "what steps do i need to …"',
  '        description "English first-person prefix surface asking which steps are needed; the task follows the … slot."',
  '      word "what steps do we need to …"',
  '        description "English first-person-plural prefix surface asking which steps are needed; the task follows the … slot."',
  '      word "how should i …"',
  '        description "English advice-seeking prefix surface; the task follows the … slot, operation from its first word."',
  '      word "how should we …"',
  '        description "English first-person-plural advice-seeking prefix surface; the task follows the … slot."',
  '      word "how could i …"',
  '        description "English possibility prefix surface; the task follows the … slot, operation from its first word."',
  '      word "how could we …"',
  '        description "English first-person-plural possibility prefix surface; the task follows the … slot."',
  '      word "how would i …"',
  '        description "English hypothetical prefix surface; the task follows the … slot, operation from its first word."',
  '      word "how would we …"',
  '        description "English first-person-plural hypothetical prefix surface; the task follows the … slot."',
  '      word "how can i …"',
  '        description "English capability prefix surface; the task follows the … slot, operation from its first word."',
  '      word "how can we …"',
  '        description "English first-person-plural capability prefix surface; the task follows the … slot."',
  '      word "how do i …"',
  '        description "English procedural prefix surface; the task follows the … slot, operation from its first word."',
  '      word "how do we …"',
  '        description "English first-person-plural procedural prefix surface; the task follows the … slot."',
  '      word "how to do …"',
  '        action "do"',
  '        description "English prefix surface naming the do operation explicitly; the whole task follows the … slot."',
  '      word "how to …"',
  '        description "English bare how-to prefix surface; the task follows the … slot, operation from its first word."',
  '    lexeme "ru"',
  '      word "как сделать …"',
  '        action "do"',
  '        description "Russian prefix surface (romanized kak sdelat) naming the do operation; the task follows the … slot."',
  '      word "как делать …"',
  '        action "do"',
  '        description "Russian imperfective prefix surface (romanized kak delat) naming the do operation; the task follows the … slot."',
  '      word "как выполнить …"',
  '        action "perform"',
  '        description "Russian prefix surface (romanized kak vypolnit) naming the perform operation; the task follows the … slot."',
  '      word "как реализовать …"',
  '        action "implement"',
  '        description "Russian prefix surface (romanized kak realizovat) naming the implement operation; the task follows the … slot."',
  '      word "как создать …"',
  '        action "create"',
  '        description "Russian prefix surface (romanized kak sozdat) naming the create operation; the task follows the … slot."',
  '      word "как написать …"',
  '        action "write"',
  '        description "Russian prefix surface (romanized kak napisat) naming the write operation; the task follows the … slot."',
  '    lexeme "hi"',
  '      word "कैसे करें …"',
  '        action "do"',
  '        description "Hindi polite prefix surface (romanized kaise karen) naming the do operation; the task follows the … slot."',
  '      word "कैसे करे …"',
  '        action "do"',
  '        description "Hindi prefix surface (romanized kaise kare) naming the do operation; the task follows the … slot."',
  '      word "कैसे लागू करें …"',
  '        action "implement"',
  '        description "Hindi prefix surface (romanized kaise laagu karen) naming the implement operation; the task follows the … slot."',
  '      word "कैसे बनाएं …"',
  '        action "create"',
  '        description "Hindi prefix surface (romanized kaise banaen) naming the create operation; the task follows the … slot."',
  '      word "कैसे बनाएँ …"',
  '        action "create"',
  '        description "Hindi prefix surface variant (romanized kaise banaen, with candrabindu) naming the create operation; the task follows the … slot."',
  '      word "कैसे लिखें …"',
  '        action "write"',
  '        description "Hindi prefix surface (romanized kaise likhen) naming the write operation; the task follows the … slot."',
  '    lexeme "zh"',
  '      word "如何做 …"',
  '        action "do"',
  '        description "Chinese prefix surface (pinyin ruhe zuo) naming the do operation, with a trailing space; the task follows the … slot."',
  '      word "怎么做 …"',
  '        action "do"',
  '        description "Chinese prefix surface (pinyin zenme zuo) naming the do operation, with a trailing space; the task follows the … slot."',
  '      word "如何实现 …"',
  '        action "implement"',
  '        description "Chinese prefix surface (pinyin ruhe shixian) naming the implement operation, with a trailing space; the task follows the … slot."',
  '      word "怎么实现 …"',
  '        action "implement"',
  '        description "Chinese prefix surface (pinyin zenme shixian) naming the implement operation, with a trailing space; the task follows the … slot."',
  '      word "如何创建 …"',
  '        action "create"',
  '        description "Chinese prefix surface (pinyin ruhe chuangjian) naming the create operation, with a trailing space; the task follows the … slot."',
  '      word "怎么创建 …"',
  '        action "create"',
  '        description "Chinese prefix surface (pinyin zenme chuangjian) naming the create operation, with a trailing space; the task follows the … slot."',
  '      word "如何写 …"',
  '        action "write"',
  '        description "Chinese prefix surface (pinyin ruhe xie) naming the write operation, with a trailing space; the task follows the … slot."',
  '      word "怎么写 …"',
  '        action "write"',
  '        description "Chinese prefix surface (pinyin zenme xie) naming the write operation, with a trailing space; the task follows the … slot."',
  '  meaning "mechanism_predicate"',
  '    gloss "the predicate that completes a how-it-works clause — the verb or participle stating that a subject operates, is structured, or is built (work, works, structured, organized, organised, built, …). Each surface is a suffix carrying the … (U+2026) slot at the front; the text after the slot is the predicate tail a mechanism-inquiry extractor strips so the bare subject remains. The English surfaces are the ones an extractor removes after a how-does prefix match; the other languages name genuine predicates so every language is covered."',
  '    wiktionary "work"',
  '    defined_by "action"',
  '    defined_by "mechanism_inquiry"',
  '    role "mechanism_predicate"',
  '    lexeme "en"',
  '      word "… work"',
  '        description "English plural-or-base predicate tail meaning operates; the text after the … slot is stripped to leave the subject."',
  '      word "… works"',
  '        description "English singular predicate tail meaning operates; the text after the … slot is stripped to leave the subject."',
  '      word "… structured"',
  '        description "English predicate tail meaning arranged; the text after the … slot is stripped to leave the subject."',
  '      word "… organized"',
  '        description "English predicate tail meaning arranged, American spelling; the text after the … slot is stripped to leave the subject."',
  '      word "… organised"',
  '        description "English predicate tail meaning arranged, British spelling; the text after the … slot is stripped to leave the subject."',
  '      word "… built"',
  '        description "English predicate tail meaning constructed; the text after the … slot is stripped to leave the subject."',
  '    lexeme "ru"',
  '      word "… работает"',
  '        description "Russian singular predicate tail (romanized rabotaet) meaning works; a genuine mechanism predicate stripped when a subject ends with it after a prefix match."',
  '      word "… устроен"',
  '        description "Russian predicate tail (romanized ustroen) meaning is structured; a genuine mechanism predicate completing a how-it-works clause."',
  '    lexeme "hi"',
  '      word "… काम करता है"',
  '        description "Hindi predicate tail (romanized kaam karta hai) meaning works; a genuine mechanism predicate completing a how-it-works clause."',
  '      word "… बना है"',
  '        description "Hindi predicate tail (romanized bana hai) meaning is built; a genuine mechanism predicate completing a how-it-works clause."',
  '    lexeme "zh"',
  '      word "…工作"',
  '        description "Chinese predicate tail (pinyin gongzuo) meaning works, with no leading space; a genuine mechanism predicate completing a how-it-works clause."',
  '      word "…构建"',
  '        description "Chinese predicate tail (pinyin goujian) meaning is built, with no leading space; a genuine mechanism predicate completing a how-it-works clause."',
  '  meaning "detail_modifier"',
  '    gloss "an optional modifier appended to a how-it-works question asking for more thoroughness or politeness (in detail, internally, exactly, please, …) without naming the subject. Each surface is a suffix carrying the … (U+2026) slot at the front; the text after the slot is the modifier tail a mechanism-inquiry extractor strips so the bare subject remains. The extractor strips every matching modifier in declaration order, re-trimming after each."',
  '    wiktionary "detail"',
  '    defined_by "property"',
  '    defined_by "mechanism_inquiry"',
  '    role "detail_modifier"',
  '    lexeme "en"',
  '      word "… in detail"',
  '        description "English modifier tail asking for a thorough explanation; the text after the … slot is stripped to leave the subject."',
  '      word "… internally"',
  '        description "English modifier tail asking about internal workings; the text after the … slot is stripped to leave the subject."',
  '      word "… exactly"',
  '        description "English modifier tail asking for precision; the text after the … slot is stripped to leave the subject."',
  '      word "… please"',
  '        description "English politeness modifier tail; the text after the … slot is stripped to leave the subject."',
  '    lexeme "ru"',
  '      word "… подробнее"',
  '        description "Russian modifier tail (romanized podrobneye) meaning in more detail; the text after the … slot is stripped to leave the subject."',
  '      word "… подробно"',
  '        description "Russian modifier tail (romanized podrobno) meaning in detail; the text after the … slot is stripped to leave the subject."',
  '      word "… пожалуйста"',
  '        description "Russian politeness modifier tail (romanized pozhaluysta) meaning please; the text after the … slot is stripped to leave the subject."',
  '    lexeme "hi"',
  '      word "… विस्तार से"',
  '        description "Hindi modifier tail (romanized vistaar se) meaning in detail; the text after the … slot is stripped to leave the subject."',
  '      word "… कृपया"',
  '        description "Hindi politeness modifier tail (romanized kripya) meaning please; the text after the … slot is stripped to leave the subject."',
  '    lexeme "zh"',
  '      word "…详细"',
  '        description "Chinese modifier tail (pinyin xiangxi) meaning in detail, with no leading space; the text after the … slot is stripped to leave the subject."',
  '      word "…请"',
  '        description "Chinese politeness modifier tail (pinyin qing) meaning please, with no leading space; the text after the … slot is stripped to leave the subject."',
  '  meaning "non_referential_subject"',
  '    gloss "a subject candidate that names no real topic — a pronoun or bare function word that points back at the surrounding context instead of introducing a subject, so a how-it-works extractor rejects it and falls back to the active topic. Bare surfaces match the whole candidate exactly; prefix surfaces carry the … (U+2026) slot and match when the candidate begins with the literal before the slot."',
  '    wiktionary "pronoun"',
  '    defined_by "entity"',
  '    defined_by "mechanism_inquiry"',
  '    role "non_referential_subject"',
  '    lexeme "en"',
  '      word "it"',
  '        description "English third-person pronoun referring back to context; rejected as a non-referential subject."',
  '      word "this"',
  '        description "English demonstrative pronoun pointing at context; rejected as a non-referential subject."',
  '      word "that"',
  '        description "English demonstrative pronoun pointing at context; rejected as a non-referential subject."',
  '      word "you"',
  '        description "English second-person pronoun addressing the assistant; rejected as a non-referential subject."',
  '      word "yourself"',
  '        description "English reflexive pronoun addressing the assistant; rejected as a non-referential subject."',
  '      word "does"',
  '        description "English auxiliary verb left over from a how-does question; rejected as a non-referential subject."',
  '      word "do"',
  '        description "English auxiliary verb left over from a how-do question; rejected as a non-referential subject."',
  '      word "does …"',
  "        description \"English prefix surface; a candidate beginning with 'does ' is a dangling auxiliary clause and is rejected as a non-referential subject.\"",
  '      word "do …"',
  "        description \"English prefix surface; a candidate beginning with 'do ' is a dangling auxiliary clause and is rejected as a non-referential subject.\"",
  '      word "to …"',
  "        description \"English prefix surface; a candidate beginning with 'to ' is an infinitive clause, not a subject, and is rejected.\"",
  '      word "you …"',
  "        description \"English prefix surface; a candidate beginning with 'you ' addresses the assistant and is rejected as a non-referential subject.\"",
  '    lexeme "ru"',
  '      word "это"',
  '        description "Russian demonstrative pronoun (romanized eto) meaning this or it; rejected as a non-referential subject."',
  '      word "оно"',
  '        description "Russian neuter pronoun (romanized ono) meaning it; rejected as a non-referential subject."',
  '      word "он"',
  '        description "Russian masculine pronoun (romanized on) meaning he or it; rejected as a non-referential subject."',
  '      word "она"',
  '        description "Russian feminine pronoun (romanized ona) meaning she or it; rejected as a non-referential subject."',
  '      word "они"',
  '        description "Russian plural pronoun (romanized oni) meaning they; rejected as a non-referential subject."',
  '      word "ты"',
  '        description "Russian informal second-person pronoun (romanized ty) meaning you; rejected as a non-referential subject."',
  '      word "вы"',
  '        description "Russian formal or plural second-person pronoun (romanized vy) meaning you; rejected as a non-referential subject."',
  '    lexeme "hi"',
  '      word "यह"',
  '        description "Hindi pronoun (romanized yah) meaning this or it; rejected as a non-referential subject."',
  '      word "ये"',
  '        description "Hindi pronoun (romanized ye) meaning these or this; rejected as a non-referential subject."',
  '    lexeme "zh"',
  '      word "这"',
  '        description "Chinese demonstrative pronoun (pinyin zhe) meaning this; rejected as a non-referential subject."',
  '      word "这个"',
  '        description "Chinese demonstrative pronoun (pinyin zhege) meaning this one; rejected as a non-referential subject."',
  '      word "它"',
  '        description "Chinese third-person pronoun (pinyin ta) meaning it; rejected as a non-referential subject."',
  '  meaning "procedural_task_modifier"',
  "    gloss \"an optional modifier trailing a procedural how-to task that asks for step-by-step granularity or adds politeness (step by step, in steps, please, …) without naming part of the task itself. Each surface is a suffix carrying the … (U+2026) slot at the front; the text after the slot is the modifier tail a procedural extractor strips from the end of the task, scanning surfaces in declaration order and stopping at the first match, so the longer Russian 'напиши по шагам' is tried before its 'по шагам' tail.\"",
  '    wiktionary "step"',
  '    defined_by "property"',
  '    defined_by "procedural_request"',
  '    role "procedural_task_modifier"',
  '    lexeme "en"',
  '      word "… step by step"',
  '        description "English modifier tail asking for incremental steps; the text after the … slot is stripped from the end of the task."',
  '      word "… in steps"',
  '        description "English modifier tail asking for the task broken into steps; the text after the … slot is stripped from the end of the task."',
  '      word "… with steps"',
  '        description "English modifier tail asking for accompanying steps; the text after the … slot is stripped from the end of the task."',
  '      word "… for me"',
  '        description "English modifier tail framing the request as personal; the text after the … slot is stripped from the end of the task."',
  '      word "… please"',
  '        description "English politeness modifier tail; the text after the … slot is stripped from the end of the task."',
  '    lexeme "ru"',
  '      word "… напиши по шагам"',
  "        description \"Russian modifier tail (romanized napishi po shagam) meaning write it step by step; declared before its 'по шагам' tail so the longer surface matches first. The text after the … slot is stripped from the end of the task.\"",
  '      word "… по шагам"',
  '        description "Russian modifier tail (romanized po shagam) meaning step by step; the text after the … slot is stripped from the end of the task."',
  '      word "… пошагово"',
  '        description "Russian modifier tail (romanized poshagovo) meaning step-by-step; the text after the … slot is stripped from the end of the task."',
  '      word "… пожалуйста"',
  '        description "Russian politeness modifier tail (romanized pozhaluysta) meaning please; the text after the … slot is stripped from the end of the task."',
  '    lexeme "hi"',
  '      word "… चरणों में लिखो"',
  '        description "Hindi modifier tail (romanized charanon mein likho) meaning write it in steps; the text after the … slot is stripped from the end of the task."',
  '      word "… चरणों में बताओ"',
  '        description "Hindi modifier tail (romanized charanon mein batao) meaning explain it in steps; the text after the … slot is stripped from the end of the task."',
  '      word "… कदम दर कदम"',
  '        description "Hindi modifier tail (romanized kadam dar kadam) meaning step by step; the text after the … slot is stripped from the end of the task."',
  '      word "… कृपया"',
  '        description "Hindi politeness modifier tail (romanized kripya) meaning please; the text after the … slot is stripped from the end of the task."',
  '    lexeme "zh"',
  '      word "… 按步骤写"',
  '        description "Chinese modifier tail (pinyin an buzhou xie) meaning write by steps, with a leading space matching the task separator; the text after the … slot is stripped from the end of the task."',
  '      word "… 按步骤说明"',
  '        description "Chinese modifier tail (pinyin an buzhou shuoming) meaning explain by steps, with a leading space; the text after the … slot is stripped from the end of the task."',
  '      word "… 一步一步写"',
  '        description "Chinese modifier tail (pinyin yibu yibu xie) meaning write it step by step, with a leading space; the text after the … slot is stripped from the end of the task."',
  '      word "… 请"',
  '        description "Chinese politeness modifier tail (pinyin qing) meaning please, with a leading space; the text after the … slot is stripped from the end of the task."',
  '  meaning "common_typo"',
  "    gloss \"a common misspelling that can appear in a procedural how-to task, paired with its correction so an extractor can repair the token by data rather than a hardcoded table. Each surface is a bare word whose text is the misspelled token; its action child names the correct spelling that replaces the token, deduplicated per task by the misspelled form. The English 'dirven' for 'driven' is the canonical example; the other languages carry one genuine misspelling each so every supported language is covered.\"",
  '    wiktionary "misspelling"',
  '    defined_by "relation"',
  '    role "common_typo"',
  '    lexeme "en"',
  '      word "dirven"',
  '        action "driven"',
  "        description \"English transposition misspelling of 'driven' (as in data-driven); replaced by its action correction when it appears as a task token.\"",
  '    lexeme "ru"',
  '      word "руский"',
  '        action "русский"',
  "        description \"Russian misspelling (romanized ruskiy) of 'русский' meaning Russian, dropping one с; replaced by its action correction when it appears as a task token.\"",
  '    lexeme "hi"',
  '      word "वेबसाईट"',
  '        action "वेबसाइट"',
  "        description \"Hindi misspelling (romanized vebsaait) of 'वेबसाइट' meaning website, with an extra long-i vowel sign; replaced by its action correction when it appears as a task token.\"",
  '    lexeme "zh"',
  '      word "登陆"',
  '        action "登录"',
  "        description \"Chinese misspelling (pinyin denglu) of '登录' meaning to log in, confusing 陆 'land' for 录 'record'; replaced by its action correction when it appears as a task token.\"",
  '  meaning "topic_scan_stop_word"',
  "    gloss \"a closed-class function word — an article, preposition, conjunction or pronoun — or a citation heading such as 'source' that names no subject, so a scanner looking for the topic of a prior assistant reply skips it. Each surface is a bare word compared case-insensitively (after lowercasing) against a capitalised token from the reply; the first capitalised token that is not one of these is taken as the topic. English carries the original scan list verbatim (i, the, a, an, in, to, for, of, and, or, source); the other languages add their canonical function words so every supported language is covered. Because the scanner only considers capitalised tokens, the Devanagari and Han forms are self-describing — those scripts have no capitalisation — while the Russian forms also let a capitalised Cyrillic function word be skipped.\"",
  '    wiktionary "the"',
  '    defined_by "concept"',
  '    role "topic_scan_stop_word"',
  '    lexeme "en"',
  '      word "i"',
  '        description "English first-person pronoun; a closed-class word the topic scanner skips. It never matches in practice because the scanner ignores single-letter tokens, but it documents the original scan list."',
  '      word "the"',
  '        description "English definite article; skipped by the topic scanner as a function word that names no subject."',
  '      word "a"',
  '        description "English indefinite article; a closed-class word the scanner skips. Single-letter, so it never matches in practice but completes the original list."',
  '      word "an"',
  '        description "English indefinite article before a vowel; skipped by the topic scanner as a function word that names no subject."',
  '      word "in"',
  '        description "English preposition; skipped by the topic scanner as a function word that names no subject."',
  '      word "to"',
  '        description "English preposition or infinitive marker; skipped by the topic scanner as a function word that names no subject."',
  '      word "for"',
  '        description "English preposition; skipped by the topic scanner as a function word that names no subject."',
  '      word "of"',
  '        description "English preposition; skipped by the topic scanner as a function word that names no subject."',
  '      word "and"',
  '        description "English coordinating conjunction; skipped by the topic scanner as a function word that names no subject."',
  '      word "or"',
  '        description "English coordinating conjunction; skipped by the topic scanner as a function word that names no subject."',
  '      word "source"',
  "        description \"English heading word that introduces a citation (as in 'Source: URL') in concept-lookup replies; skipped so the scanner does not mistake it for the subject.\"",
  '    lexeme "ru"',
  '      word "и"',
  '        description "Russian coordinating conjunction (romanized i) meaning and; skipped by the topic scanner as a function word that names no subject."',
  '      word "или"',
  '        description "Russian coordinating conjunction (romanized ili) meaning or; skipped by the topic scanner as a function word that names no subject."',
  '      word "в"',
  '        description "Russian preposition (romanized v) meaning in; skipped by the topic scanner as a function word that names no subject."',
  '      word "к"',
  '        description "Russian preposition (romanized k) meaning to or toward; skipped by the topic scanner as a function word that names no subject."',
  '      word "для"',
  '        description "Russian preposition (romanized dlya) meaning for; skipped by the topic scanner as a function word that names no subject."',
  '      word "из"',
  '        description "Russian preposition (romanized iz) meaning of or from; skipped by the topic scanner as a function word that names no subject."',
  '      word "источник"',
  '        description "Russian heading word (romanized istochnik) meaning source; skipped so the scanner does not mistake a citation heading for the subject."',
  '    lexeme "hi"',
  '      word "और"',
  '        description "Hindi coordinating conjunction (romanized aur) meaning and; a function word the scanner skips. Devanagari has no capitalisation, so it is self-describing rather than matched."',
  '      word "या"',
  '        description "Hindi coordinating conjunction (romanized ya) meaning or; a function word the scanner skips. Self-describing, since Devanagari has no capitalisation."',
  '      word "में"',
  '        description "Hindi postposition (romanized mein) meaning in; a function word the scanner skips. Self-describing, since Devanagari has no capitalisation."',
  '      word "को"',
  '        description "Hindi postposition (romanized ko) marking the object; a function word the scanner skips. Self-describing, since Devanagari has no capitalisation."',
  '      word "के"',
  '        description "Hindi postposition (romanized ke) marking possession or relation; a function word the scanner skips. Self-describing, since Devanagari has no capitalisation."',
  '      word "का"',
  '        description "Hindi postposition (romanized ka) marking possession; a function word the scanner skips. Self-describing, since Devanagari has no capitalisation."',
  '      word "स्रोत"',
  '        description "Hindi heading word (romanized srot) meaning source; skipped so a citation heading is not mistaken for the subject. Self-describing, since Devanagari has no capitalisation."',
  '    lexeme "zh"',
  '      word "和"',
  '        description "Chinese coordinating conjunction (pinyin he) meaning and; a function word the scanner skips. Han script has no capitalisation, so it is self-describing rather than matched."',
  '      word "或"',
  '        description "Chinese coordinating conjunction (pinyin huo) meaning or; a function word the scanner skips. Self-describing, since Han script has no capitalisation."',
  '      word "在"',
  '        description "Chinese preposition (pinyin zai) meaning in or at; a function word the scanner skips. Self-describing, since Han script has no capitalisation."',
  '      word "的"',
  '        description "Chinese possessive particle (pinyin de); a function word the scanner skips. Self-describing, since Han script has no capitalisation."',
  '      word "来源"',
  '        description "Chinese heading word (pinyin laiyuan) meaning source; skipped so a citation heading is not mistaken for the subject. Self-describing, since Han script has no capitalisation."',
  "meanings",
  '  meaning "causal_interrogative"',
  '    gloss "the interrogative word that asks for a cause or reason — why, почему, क्यों, 为什么. By itself it carries no answer reference; a why-did-you-answer question composes it with a prior-answer reference. Only the Hindi and Chinese surfaces are read by the recogniser, paired with prior_answer_reference within the same language to detect a head-final why-question; the English and Russian why-questions front the interrogative and are matched through answer_rationale_inquiry instead."',
  '    wiktionary "why"',
  '    defined_by "inquiry"',
  '    role "causal_interrogative"',
  '    lexeme "en"',
  '      word "why"',
  '        description "English interrogative adverb asking for a cause or reason; the bare surface for the causal interrogative concept."',
  '    lexeme "ru"',
  '      word "почему"',
  '        description "Russian interrogative adverb (romanized pochemu) asking for a cause or reason; the bare surface for the causal interrogative concept."',
  '    lexeme "hi"',
  '      word "क्यों"',
  '        description "Hindi interrogative adverb (romanized kyon) asking for a cause or reason; paired with a prior-answer reference to detect a head-final why-question."',
  '    lexeme "zh"',
  '      word "为什么"',
  '        description "Chinese interrogative (pinyin weishenme) asking for a cause or reason; paired with a prior-answer reference to detect a head-final why-question."',
  '  meaning "prior_answer_reference"',
  '    gloss "a reference to the answer the assistant previously gave — the object a why-question points back at when it asks the assistant to justify its prior reply. Only the Hindi and Chinese surfaces are read by the recogniser, paired with the causal interrogative within the same language; the English and Russian why-questions front the interrogative and are matched through answer_rationale_inquiry instead. A dedicated reference rather than the broader answer meaning so its Chinese surface stays exactly 回答, mirroring the original recogniser that required 回答 and not the synonym 答复."',
  '    wiktionary "answer"',
  '    defined_by "answer"',
  '    role "prior_answer_reference"',
  '    lexeme "en"',
  '      word "answer"',
  '        description "English noun for the reply the assistant previously returned; the surface a why-question refers back to."',
  '    lexeme "ru"',
  '      word "ответ"',
  '        description "Russian noun (romanized otvet) for the answer the assistant previously returned; the surface a why-question refers back to."',
  '    lexeme "hi"',
  '      word "जवाब"',
  '        description "Hindi noun (romanized javab) for the reply the assistant previously gave; paired with the causal interrogative to detect a head-final why-question."',
  '      word "उत्तर"',
  '        description "Hindi noun (romanized uttar) for the answer the assistant previously gave; an alternative surface paired with the causal interrogative."',
  '    lexeme "zh"',
  '      word "回答"',
  '        description "Chinese noun and verb (pinyin huida) for the answer the assistant previously gave; paired with the causal interrogative to detect a head-final why-question."',
  '  meaning "answer_rationale_inquiry"',
  "    gloss \"a why-did-you-answer question — the causal interrogative composed with a reference to the assistant's prior answer, asking it to justify the reply it just gave. The English and Russian surfaces front the interrogative, so the recogniser matches them directly: a prefix surface (trailing … slot) matches when the prompt opens with the literal, and a bare surface matches anywhere. The Hindi and Chinese why-questions are head-final and are detected instead as a same-language pair of causal_interrogative and prior_answer_reference, so the Hindi and Chinese surfaces here are inert completeness forms that are never matched.\"",
  '    wiktionary "why"',
  '    defined_by "causal_interrogative"',
  '    defined_by "prior_answer_reference"',
  '    defined_by "inquiry"',
  '    role "answer_rationale_lead"',
  '    lexeme "en"',
  '      word "why …"',
  '        description "English prefix surface; starts_with why (trailing space), the rest of the question follows the … slot."',
  '      word "why did you answer"',
  '        description "English bare surface; matches the why-did-you-answer clause anywhere in the prompt, even when it does not open it."',
  '    lexeme "ru"',
  '      word "почему …"',
  '        description "Russian prefix surface (romanized pochemu); starts_with почему (trailing space), the rest of the question follows the … slot."',
  '      word "почему ты ответил"',
  '        description "Russian bare surface (romanized pochemu ty otvetil) for why-did-you-answer addressed to the assistant; matches anywhere in the prompt."',
  '      word "почему ты так ответил"',
  '        description "Russian bare surface (romanized pochemu ty tak otvetil) for why-did-you-answer-that-way; matches anywhere in the prompt."',
  '      word "почему вы ответили"',
  '        description "Russian bare surface (romanized pochemu vy otvetili) for why-did-you-answer in the polite plural; matches anywhere in the prompt."',
  '    lexeme "hi"',
  '      word "ऐसा जवाब क्यों दिया"',
  '        description "Hindi why-did-you-answer phrasing (romanized aisa javab kyon diya); an inert completeness form — Hindi why-questions are detected as a causal_interrogative and prior_answer_reference pair, not through this surface."',
  '    lexeme "zh"',
  '      word "为什么这样回答"',
  '        description "Chinese why-did-you-answer phrasing (pinyin weishenme zheyang huida); an inert completeness form — Chinese why-questions are detected as a causal_interrogative and prior_answer_reference pair, not through this surface."',
  '  meaning "assistant_self_reference"',
  '    gloss "a second-person reference to the assistant — you, your, ты, вы, आप, तुम, 你, 您 and the project name formal ai. It marks that a prompt is addressed to the assistant itself. Matched as raw substrings, since several Russian forms are inflectable stems (теб for тебя and тебе, тво for твой and твоё): the architecture recogniser requires it together with an architecture concept, and the how-you-work recogniser requires its Russian forms together with the operating principle. Distinct from self_reference, whose reflexive pronouns (yourself, себя) name the assistant as the grammatical object rather than addressing it in the second person."',
  '    wiktionary "you"',
  '    defined_by "assistant"',
  '    defined_by "self_reference"',
  '    role "assistant_self_reference"',
  '    lexeme "en"',
  '      word "you"',
  '        description "English second-person pronoun addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "your"',
  '        description "English second-person possessive addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "formal ai"',
  '        description "English project name addressing the assistant directly; a raw-substring surface for the assistant self-reference concept."',
  '    lexeme "ru"',
  '      word "ты"',
  '        description "Russian second-person pronoun (romanized ty) addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "теб"',
  '        description "Russian second-person stem (romanized teb) shared by тебя and тебе addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "твоя"',
  '        description "Russian feminine second-person possessive (romanized tvoya) addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "твой"',
  '        description "Russian masculine second-person possessive (romanized tvoy) addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "тво"',
  '        description "Russian second-person possessive stem (romanized tvo) shared by твоё and твои addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "вы"',
  '        description "Russian polite second-person pronoun (romanized vy) addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '    lexeme "hi"',
  '      word "आप"',
  '        description "Hindi polite second-person pronoun (romanized aap) addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "तुम"',
  '        description "Hindi informal second-person pronoun (romanized tum) addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '    lexeme "zh"',
  '      word "你"',
  '        description "Chinese second-person pronoun (pinyin ni) addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '      word "您"',
  '        description "Chinese polite second-person pronoun (pinyin nin) addressing the assistant; a raw-substring surface for the assistant self-reference concept."',
  '  meaning "assistant_mechanism_inquiry"',
  '    gloss "a how-do-you-work question addressed to the assistant — the mechanism-inquiry concept applied to the assistant itself, asking it to explain how it operates, how it is built, or the idea behind its design. Each surface is a complete clause matched as a raw substring; the recogniser fires when any one of them appears. The Russian principle-of-operation phrasing (принцип работы … тебя) is handled separately, by composing the operating_principle concept with an assistant self-reference, so it is not listed here."',
  '    wiktionary "work"',
  '    defined_by "mechanism_inquiry"',
  '    defined_by "assistant"',
  '    role "assistant_mechanism_inquiry"',
  '    lexeme "en"',
  '      word "how do you work"',
  '        description "English how-you-work clause asking the assistant to explain its operation; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "how does this work"',
  '        description "English how-this-works clause asking the assistant to explain its operation; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "how does it work"',
  '        description "English how-it-works clause asking the assistant to explain its operation; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "show me how you work"',
  '        description "English imperative asking the assistant to demonstrate how it works; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "explain how you work"',
  '        description "English imperative asking the assistant to explain how it works; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '    lexeme "ru"',
  '      word "как ты работаешь"',
  '        description "Russian how-you-work clause (romanized kak ty rabotaesh) asking the assistant to explain its operation; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "покажи как ты работаешь"',
  '        description "Russian imperative (romanized pokazhi kak ty rabotaesh) asking the assistant to show how it works; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "расскажи как ты работаешь"',
  '        description "Russian imperative (romanized rasskazhi kak ty rabotaesh) asking the assistant to tell how it works; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "объясни как ты работаешь"',
  '        description "Russian imperative (romanized obyasni kak ty rabotaesh) asking the assistant to explain how it works; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "как ты устроен"',
  '        description "Russian how-you-are-built clause (romanized kak ty ustroen) asking the assistant how it is constructed; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "покажи как ты устроен"',
  '        description "Russian imperative (romanized pokazhi kak ty ustroen) asking the assistant to show how it is constructed; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "какая у тебя модель окружающего мира"',
  '        description "Russian question (romanized kakaya u tebya model okruzhayushchego mira) asking what model of the surrounding world the assistant has; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "модель окружающего мира"',
  '        description "Russian phrase (romanized model okruzhayushchego mira) for a model of the surrounding world; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "идея твоей разработки"',
  '        description "Russian phrase (romanized ideya tvoey razrabotki) for the idea behind your development; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "идея твоего проекта"',
  '        description "Russian phrase (romanized ideya tvoego proekta) for the idea behind your project; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "зачем тебя разработ"',
  '        description "Russian phrase stem (romanized zachem tebya razrabot) for why you were developed, catching разработали and разработан; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '    lexeme "hi"',
  '      word "तुम कैसे काम करते हो"',
  '        description "Hindi how-you-work clause (romanized tum kaise kaam karte ho) asking the assistant how it works; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "आप कैसे काम करते हैं"',
  '        description "Hindi polite how-you-work clause (romanized aap kaise kaam karte hain) asking the assistant how it works; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '    lexeme "zh"',
  '      word "你是怎么工作的"',
  '        description "Chinese how-you-work clause (pinyin ni shi zenme gongzuo de) asking the assistant how it works; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '      word "你怎么运作"',
  '        description "Chinese how-you-operate clause (pinyin ni zenme yunzuo) asking the assistant how it operates; a raw-substring surface for the assistant mechanism-inquiry concept."',
  '  meaning "operating_principle"',
  "    gloss \"the concept of a thing's operating principle — the rule by which it works. The how-you-work recogniser reads only the Russian surface, composing it with an assistant self-reference to catch принцип работы … тебя (the principle of operation phrased about the assistant); the English, Hindi and Chinese surfaces are inert completeness forms that keep the concept lexicalised in every supported language.\"",
  '    wiktionary "principle"',
  '    defined_by "concept"',
  '    defined_by "action"',
  '    role "operating_principle"',
  '    lexeme "en"',
  '      word "operating principle"',
  '        description "English phrase for the rule by which something works; an inert completeness form for the operating-principle concept."',
  '    lexeme "ru"',
  '      word "принцип работы"',
  '        description "Russian phrase (romanized printsip raboty) for the principle of operation; composed with an assistant self-reference to recognise a how-you-work question about the assistant."',
  '    lexeme "hi"',
  '      word "कार्य सिद्धांत"',
  '        description "Hindi phrase (romanized kaarya siddhaant) for the principle of operation; an inert completeness form for the operating-principle concept."',
  '    lexeme "zh"',
  '      word "工作原理"',
  '        description "Chinese phrase (pinyin gongzuo yuanli) for the principle of operation; an inert completeness form for the operating-principle concept."',
  '  meaning "architecture_concept"',
  "    gloss \"a term that names part of an AI system's architecture or internals — a language model, neural network, OpenAI API, world model, links-notation rules, area of knowledge, or the idea behind a project's development. The architecture recogniser fires when one of these appears together with an assistant self-reference, marking a question about how the assistant is built rather than a request for a task. Each surface is matched as a raw substring; several Russian forms are inflectable stems (нейросет for нейросеть and нейросети, ссылк for ссылка and ссылки, локальных правил for the genitive of local rules).\"",
  '    wiktionary "architecture"',
  '    defined_by "concept"',
  '    defined_by "assistant"',
  '    role "architecture_concept"',
  '    lexeme "en"',
  '      word "llm"',
  '        description "English abbreviation for a large language model; a raw-substring surface for the architecture concept."',
  '      word "large language model"',
  '        description "English phrase for a large neural language model; a raw-substring surface for the architecture concept."',
  '      word "language model"',
  '        description "English phrase for a statistical or neural language model; a raw-substring surface for the architecture concept."',
  '      word "openai api"',
  '        description "English phrase for the OpenAI application programming interface; a raw-substring surface for the architecture concept."',
  '      word "openai"',
  '        description "English name of the OpenAI organisation and its models; a raw-substring surface for the architecture concept."',
  '      word "neural inference"',
  '        description "English phrase for running inference through a neural network; a raw-substring surface for the architecture concept."',
  '      word "neural network"',
  '        description "English phrase for a network of artificial neurons; a raw-substring surface for the architecture concept."',
  '      word "links notation rules"',
  '        description "English phrase for the deterministic Links Notation rules the assistant runs on; a raw-substring surface for the architecture concept."',
  '      word "local rules"',
  "        description \"English phrase for the assistant's local rule base; a raw-substring surface for the architecture concept.\"",
  '      word "world model"',
  '        description "English phrase for an internal model of the world; a raw-substring surface for the architecture concept."',
  '      word "model of the world"',
  '        description "English phrase for an internal model of the world; an alternative raw-substring surface for the architecture concept."',
  '    lexeme "ru"',
  '      word "бям"',
  '        description "Russian abbreviation (romanized byam) for a large language model; a raw-substring surface for the architecture concept."',
  '      word "языковая модель"',
  '        description "Russian phrase (romanized yazykovaya model) for a language model; a raw-substring surface for the architecture concept."',
  '      word "языковой моделью"',
  '        description "Russian phrase (romanized yazykovoy modelyu) for a language model in the instrumental case; a raw-substring surface for the architecture concept."',
  '      word "нейросет"',
  '        description "Russian stem (romanized neyroset) shared by нейросеть and нейросети for a neural network; a raw-substring surface for the architecture concept."',
  '      word "нейрон"',
  '        description "Russian stem (romanized neyron) for a neuron, shared by нейронная and нейронов; a raw-substring surface for the architecture concept."',
  '      word "локальных правил"',
  '        description "Russian phrase (romanized lokalnykh pravil) for local rules in the genitive; a raw-substring surface for the architecture concept."',
  '      word "локальных правилах"',
  '        description "Russian phrase (romanized lokalnykh pravilakh) for local rules in the prepositional case; a raw-substring surface for the architecture concept."',
  '      word "область знаний"',
  '        description "Russian phrase (romanized oblast znaniy) for an area of knowledge; a raw-substring surface for the architecture concept."',
  '      word "модель окружающего мира"',
  '        description "Russian phrase (romanized model okruzhayushchego mira) for a model of the surrounding world; a raw-substring surface for the architecture concept."',
  '      word "модель мира"',
  '        description "Russian phrase (romanized model mira) for a model of the world; a raw-substring surface for the architecture concept."',
  '      word "принцип работы"',
  '        description "Russian phrase (romanized printsip raboty) for the principle of operation; a raw-substring surface for the architecture concept."',
  '      word "идея твоей разработки"',
  '        description "Russian phrase (romanized ideya tvoey razrabotki) for the idea behind your development; a raw-substring surface for the architecture concept."',
  '      word "идея твоего проекта"',
  '        description "Russian phrase (romanized ideya tvoego proekta) for the idea behind your project; a raw-substring surface for the architecture concept."',
  '      word "зачем тебя разработ"',
  '        description "Russian phrase stem (romanized zachem tebya razrabot) for why you were developed, catching разработали and разработан; a raw-substring surface for the architecture concept."',
  '      word "ссылк"',
  '        description "Russian stem (romanized ssylk) for a link, shared by ссылка and ссылки; a raw-substring surface for the architecture concept."',
  '    lexeme "hi"',
  '      word "न्यूरल"',
  '        description "Hindi word (romanized nyooral) for neural; a raw-substring surface for the architecture concept."',
  '      word "भाषा मॉडल"',
  '        description "Hindi phrase (romanized bhaasha modal) for a language model; a raw-substring surface for the architecture concept."',
  '    lexeme "zh"',
  '      word "神经"',
  '        description "Chinese word (pinyin shenjing) for neural or nerve, as in neural network; a raw-substring surface for the architecture concept."',
  '      word "語言模型"',
  '        description "Chinese phrase (pinyin yuyan moxing) for a language model; the traditional-character raw-substring surface for the architecture concept."',
  '      word "语言模型"',
  '        description "Chinese phrase (pinyin yuyan moxing) for a language model; the simplified-character raw-substring surface for the architecture concept."',
  "meanings",
  '  meaning "web_resource"',
  '    gloss "a resource identified by a URL — a web page, file, site, or endpoint reachable over the web. It is the object that an http_fetch request retrieves and a url_navigate request opens. Modeled as an entity in the link ontology so the two web intents are defined by the thing they act on, not only by the act itself."',
  '    wiktionary "URL"',
  '    defined_by "entity"',
  '    role "web_navigation_concept"',
  '    lexeme "en"',
  '      word "url"',
  '        description "English noun for the address that identifies a web resource (a uniform resource locator)."',
  '      word "web page"',
  '        description "English noun for a single document of a web resource served over HTTP."',
  '      word "website"',
  '        description "English noun for a collection of web pages under one host — a kind of web resource."',
  '    lexeme "ru"',
  '      word "сайт"',
  '        description "Russian noun (romanized sait) for a website — a web resource."',
  '      word "страница"',
  '        description "Russian noun (romanized stranitsa) for a web page."',
  '      word "ссылка"',
  '        description "Russian noun (romanized ssylka) for a hyperlink pointing at a web resource."',
  '      word "урл"',
  '        description "Russian borrowing (romanized url) for a URL — the address of a web resource."',
  '    lexeme "hi"',
  '      word "वेबसाइट"',
  '        description "Hindi noun (romanized vebsait) for a website — a web resource."',
  '      word "वेब पेज"',
  '        description "Hindi noun (romanized veb pej) for a web page."',
  '      word "लिंक"',
  '        description "Hindi noun (romanized link) for a hyperlink to a web resource."',
  '    lexeme "zh"',
  '      word "网址"',
  '        description "Chinese noun (pinyin wangzhi) for a URL — the address of a web resource."',
  '      word "网页"',
  '        description "Chinese noun (pinyin wangye) for a web page."',
  '      word "网站"',
  '        description "Chinese noun (pinyin wangzhan) for a website — a web resource."',
  '  meaning "http_fetch"',
  '    gloss "a request to retrieve a web resource over HTTP — the concept a fetch prompt expresses, independent of language. In the browser worker a real fetch() is attempted first, with an iframe fallback only after the target frame policy is checked. Each surface marks the URL position with the ellipsis … (U+2026): a trailing ellipsis is a prefix surface whose URL follows the literal; a surface with no ellipsis is a bare marker matched anywhere in the prompt. A separate URL gate means a surface only routes here when the prompt also carries a real URL."',
  '    wiktionary "fetch"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    defined_by "web_resource"',
  '    role "http_fetch"',
  '    lexeme "en"',
  '      word "fetch …"',
  '        description "English prefix surface; the literal before the … slot asks to fetch the web resource whose URL follows (fetch X)."',
  '      word "fetch url …"',
  '        description "English prefix surface naming the url explicitly; the URL follows the … slot (fetch url X)."',
  '      word "http fetch …"',
  '        description "English prefix surface naming the HTTP method; the URL follows the … slot (http fetch X)."',
  '      word "request …"',
  '        description "English prefix surface; the literal before the … slot asks to request the web resource whose URL follows (request X)."',
  '      word "make request to …"',
  '        description "English prefix surface; the URL of the resource to request follows the … slot (make request to X)."',
  '      word "send request to …"',
  '        description "English prefix surface; the URL of the resource to send a request to follows the … slot (send request to X)."',
  '      word "make a request to"',
  '        description "English bare marker; an HTTP request phrase matched anywhere in the prompt before the URL."',
  '      word "make an http request to"',
  '        description "English bare marker naming the HTTP protocol; matched anywhere in the prompt before the URL."',
  '      word "send a request to"',
  '        description "English bare marker; a send-a-request phrase matched anywhere in the prompt before the URL."',
  '      word "send an http request to"',
  '        description "English bare marker naming the HTTP protocol; matched anywhere in the prompt before the URL."',
  '      word "http request to"',
  '        description "English bare marker naming an HTTP request; matched anywhere in the prompt before the URL."',
  '      word "http get to"',
  '        description "English bare marker naming the HTTP GET method; matched anywhere in the prompt before the URL."',
  '      word "fetch the url"',
  '        description "English bare marker asking to fetch the given url; matched anywhere in the prompt, including after a polite opener."',
  '      word "fetch this url"',
  '        description "English bare marker referring to a nearby url; matched anywhere in the prompt."',
  '      word "fetch the page"',
  '        description "English bare marker asking to fetch a web page; matched anywhere in the prompt before the URL."',
  '    lexeme "ru"',
  '      word "сделай запрос …"',
  '        description "Russian imperative prefix surface (romanized sdelai zapros) asking to make a request; the URL follows the … slot."',
  '      word "сделай http запрос …"',
  '        description "Russian imperative prefix surface (romanized sdelai http zapros) naming the HTTP protocol; the URL follows the … slot."',
  '      word "выполни запрос …"',
  '        description "Russian imperative prefix surface (romanized vypolni zapros) asking to perform a request; the URL follows the … slot."',
  '      word "выполни http запрос …"',
  '        description "Russian imperative prefix surface (romanized vypolni http zapros) naming the HTTP protocol; the URL follows the … slot."',
  '      word "запроси …"',
  '        description "Russian imperative prefix surface (romanized zaprosi) asking to request the resource whose URL follows the … slot."',
  '      word "получи …"',
  '        description "Russian imperative prefix surface (romanized poluchi) asking to fetch or obtain the resource whose URL follows the … slot."',
  '      word "http запрос к …"',
  '        description "Russian prefix surface (romanized http zapros k) naming an HTTP request to a target; the URL follows the … slot."',
  '      word "http запрос на …"',
  '        description "Russian prefix surface (romanized http zapros na) naming an HTTP request to a target; the URL follows the … slot."',
  '      word "сделать запрос к …"',
  '        description "Russian infinitive prefix surface (romanized sdelat zapros k) asking to make a request to a target; the URL follows the … slot."',
  '      word "выполнить запрос к …"',
  '        description "Russian infinitive prefix surface (romanized vypolnit zapros k) asking to perform a request to a target; the URL follows the … slot."',
  '      word "сделай запрос к"',
  '        description "Russian bare marker (romanized sdelai zapros k) for making a request to a target; matched anywhere in the prompt before the URL."',
  '      word "сделай запрос на"',
  '        description "Russian bare marker (romanized sdelai zapros na) for making a request to a target; matched anywhere in the prompt before the URL."',
  '      word "сделай http запрос к"',
  '        description "Russian bare marker (romanized sdelai http zapros k) naming the HTTP protocol; matched anywhere in the prompt before the URL."',
  '      word "сделай http запрос на"',
  '        description "Russian bare marker (romanized sdelai http zapros na) naming the HTTP protocol; matched anywhere in the prompt before the URL."',
  '      word "выполни запрос к"',
  '        description "Russian bare marker (romanized vypolni zapros k) for performing a request to a target; matched anywhere in the prompt before the URL."',
  '      word "выполни запрос на"',
  '        description "Russian bare marker (romanized vypolni zapros na) for performing a request to a target; matched anywhere in the prompt before the URL."',
  '      word "выполни http запрос к"',
  '        description "Russian bare marker (romanized vypolni http zapros k) naming the HTTP protocol; matched anywhere in the prompt before the URL."',
  '      word "выполни http запрос на"',
  '        description "Russian bare marker (romanized vypolni http zapros na) naming the HTTP protocol; matched anywhere in the prompt before the URL."',
  '      word "запрос к"',
  '        description "Russian bare marker (romanized zapros k) — a request to a target; matched anywhere in the prompt, covering infinitive and other phrasings before the URL."',
  '      word "запрос на"',
  '        description "Russian bare marker (romanized zapros na) — a request to a target; matched anywhere in the prompt before the URL."',
  '      word "http запрос к"',
  '        description "Russian bare marker (romanized http zapros k) naming an HTTP request to a target; matched anywhere in the prompt before the URL."',
  '      word "http запрос на"',
  '        description "Russian bare marker (romanized http zapros na) naming an HTTP request to a target; matched anywhere in the prompt before the URL."',
  '    lexeme "hi"',
  '      word "अनुरोध भेजें"',
  '        description "Hindi bare marker (romanized anurodh bhejen) meaning send a request; matched anywhere in the prompt when a URL is present."',
  '      word "अनुरोध करें"',
  '        description "Hindi bare marker (romanized anurodh karen) meaning make a request; matched anywhere in the prompt when a URL is present."',
  '    lexeme "zh"',
  '      word "发送请求"',
  '        description "Chinese bare marker (pinyin fasong qingqiu) meaning send a request; matched anywhere in the prompt when a URL is present."',
  '      word "获取"',
  '        description "Chinese bare marker (pinyin huoqu) meaning fetch or obtain; matched anywhere in the prompt when a URL is present."',
  '  meaning "url_navigate"',
  '    gloss "a request to open or show a web resource without fetching its contents — the concept a navigation prompt expresses, independent of language. The browser worker returns a direct external link (and, when the target frame policy allows, an iframe preview) rather than attempting fetch(). Each surface marks the URL position with the ellipsis … (U+2026): a trailing ellipsis is a prefix surface whose URL follows the literal; a surface with no ellipsis is a bare marker matched anywhere in the prompt. A bare URL on its own also counts as navigation. A separate URL gate means a surface only routes here when the prompt also carries a real URL."',
  '    wiktionary "navigate"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    defined_by "web_resource"',
  '    role "url_navigate"',
  '    lexeme "en"',
  '      word "navigate to …"',
  '        description "English prefix surface; the URL of the resource to navigate to follows the … slot (navigate to X)."',
  '      word "navigate …"',
  '        description "English prefix surface; the URL of the resource to navigate to follows the … slot (navigate X)."',
  '      word "go to …"',
  '        description "English prefix surface; the URL of the resource to go to follows the … slot (go to X)."',
  '      word "goto …"',
  '        description "English prefix surface (one-word spelling of go to); the URL follows the … slot (goto X)."',
  '      word "visit …"',
  '        description "English prefix surface; the URL of the resource to visit follows the … slot (visit X)."',
  '      word "browse to …"',
  '        description "English prefix surface; the URL of the resource to browse to follows the … slot (browse to X)."',
  '      word "browse …"',
  '        description "English prefix surface; the URL of the resource to browse follows the … slot (browse X)."',
  '      word "show …"',
  '        description "English prefix surface; the URL of the resource to show follows the … slot (show X)."',
  '      word "show me …"',
  '        description "English prefix surface; the URL of the resource to show follows the … slot (show me X)."',
  '      word "display …"',
  '        description "English prefix surface; the URL of the resource to display follows the … slot (display X)."',
  '      word "load …"',
  '        description "English prefix surface; the URL of the resource to load follows the … slot (load X)."',
  '      word "open …"',
  '        description "English prefix surface; the URL of the resource to open follows the … slot (open X)."',
  '      word "open url …"',
  '        description "English prefix surface naming the url explicitly; the URL follows the … slot (open url X)."',
  '      word "open the url …"',
  '        description "English prefix surface naming the url explicitly; the URL follows the … slot (open the url X)."',
  '      word "open site …"',
  '        description "English prefix surface naming a site; the URL follows the … slot (open site X)."',
  '      word "open website …"',
  '        description "English prefix surface naming a website; the URL follows the … slot (open website X)."',
  '      word "open page …"',
  '        description "English prefix surface naming a page; the URL follows the … slot (open page X)."',
  '      word "open the page …"',
  '        description "English prefix surface naming the page; the URL follows the … slot (open the page X)."',
  '      word "open the website …"',
  '        description "English prefix surface naming the website; the URL follows the … slot (open the website X)."',
  '      word "take me to …"',
  '        description "English prefix surface; the URL of the resource to take the user to follows the … slot (take me to X)."',
  '      word "preview …"',
  '        description "English prefix surface; the URL of the resource to preview follows the … slot (preview X)."',
  '      word "view …"',
  '        description "English prefix surface; the URL of the resource to view follows the … slot (view X)."',
  '      word "see …"',
  '        description "English prefix surface; the URL of the resource to see follows the … slot (see X)."',
  '      word "get …"',
  '        description "English prefix surface; the URL of the resource to get follows the … slot (get X). Navigation, not fetch — the http_fetch intent is checked first and never matches a bare get."',
  '      word "navigate to"',
  '        description "English bare marker; a navigate-to phrase matched anywhere in the prompt before the URL."',
  '      word "go to"',
  '        description "English bare marker; a go-to phrase matched anywhere in the prompt before the URL."',
  '      word "goto"',
  '        description "English bare marker (one-word spelling of go to); matched anywhere in the prompt before the URL."',
  '      word "browse to"',
  '        description "English bare marker; a browse-to phrase matched anywhere in the prompt before the URL."',
  '      word "take me to"',
  '        description "English bare marker; a take-me-to phrase matched anywhere in the prompt before the URL."',
  '      word "open the page"',
  '        description "English bare marker naming the page; matched anywhere in the prompt before the URL."',
  '      word "open the site"',
  '        description "English bare marker naming the site; matched anywhere in the prompt before the URL."',
  '      word "open the website"',
  '        description "English bare marker naming the website; matched anywhere in the prompt before the URL."',
  '      word "open the url"',
  '        description "English bare marker naming the url; matched anywhere in the prompt before the URL."',
  '      word "open url"',
  '        description "English bare marker naming the url; matched anywhere in the prompt before the URL."',
  '    lexeme "ru"',
  '      word "перейди …"',
  '        description "Russian imperative prefix surface (romanized pereidi) asking to go to the resource whose URL follows the … slot."',
  '      word "перейди на …"',
  '        description "Russian imperative prefix surface (romanized pereidi na) asking to go to the resource whose URL follows the … slot."',
  '      word "переходи на …"',
  '        description "Russian imperfective imperative prefix surface (romanized perekhodi na) asking to go to the resource whose URL follows the … slot."',
  '      word "переходи …"',
  '        description "Russian imperfective imperative prefix surface (romanized perekhodi) asking to go to the resource whose URL follows the … slot."',
  '      word "перейдите на …"',
  '        description "Russian polite imperative prefix surface (romanized pereidite na) asking to go to the resource whose URL follows the … slot."',
  '      word "открой …"',
  '        description "Russian imperative prefix surface (romanized otkroi) asking to open the resource whose URL follows the … slot."',
  '      word "открой сайт …"',
  '        description "Russian imperative prefix surface (romanized otkroi sait) asking to open the site whose URL follows the … slot."',
  '      word "открой страницу …"',
  '        description "Russian imperative prefix surface (romanized otkroi stranitsu) asking to open the page whose URL follows the … slot."',
  '      word "открой ссылку …"',
  '        description "Russian imperative prefix surface (romanized otkroi ssylku) asking to open the link whose URL follows the … slot."',
  '      word "открой урл …"',
  '        description "Russian imperative prefix surface (romanized otkroi url) asking to open the url that follows the … slot."',
  '      word "покажи …"',
  '        description "Russian imperative prefix surface (romanized pokazhi) asking to show the resource whose URL follows the … slot."',
  '      word "покажи сайт …"',
  '        description "Russian imperative prefix surface (romanized pokazhi sait) asking to show the site whose URL follows the … slot."',
  '      word "покажи страницу …"',
  '        description "Russian imperative prefix surface (romanized pokazhi stranitsu) asking to show the page whose URL follows the … slot."',
  '      word "покажи мне …"',
  '        description "Russian imperative prefix surface (romanized pokazhi mne) asking to show the user the resource whose URL follows the … slot."',
  '      word "загрузи …"',
  '        description "Russian imperative prefix surface (romanized zagruzi) asking to load the resource whose URL follows the … slot."',
  '      word "загрузи страницу …"',
  '        description "Russian imperative prefix surface (romanized zagruzi stranitsu) asking to load the page whose URL follows the … slot."',
  '      word "посети …"',
  '        description "Russian imperative prefix surface (romanized poseti) asking to visit the resource whose URL follows the … slot."',
  '      word "зайди на …"',
  '        description "Russian imperative prefix surface (romanized zaidi na) asking to go onto the resource whose URL follows the … slot."',
  '      word "зайди …"',
  '        description "Russian imperative prefix surface (romanized zaidi) asking to go onto the resource whose URL follows the … slot."',
  '      word "просмотри …"',
  '        description "Russian imperative prefix surface (romanized prosmotri) asking to view the resource whose URL follows the … slot."',
  '      word "отобрази …"',
  '        description "Russian imperative prefix surface (romanized otobrazi) asking to display the resource whose URL follows the … slot."',
  '      word "перейди на"',
  '        description "Russian bare marker (romanized pereidi na) for going to a target; matched anywhere in the prompt before the URL."',
  '      word "переходи на"',
  '        description "Russian bare marker (romanized perekhodi na) for going to a target; matched anywhere in the prompt before the URL."',
  '      word "перейдите на"',
  '        description "Russian polite bare marker (romanized pereidite na) for going to a target; matched anywhere in the prompt before the URL."',
  '      word "открой сайт"',
  '        description "Russian bare marker (romanized otkroi sait) for opening a site; matched anywhere in the prompt before the URL."',
  '      word "открой страницу"',
  '        description "Russian bare marker (romanized otkroi stranitsu) for opening a page; matched anywhere in the prompt before the URL."',
  '      word "открой ссылку"',
  '        description "Russian bare marker (romanized otkroi ssylku) for opening a link; matched anywhere in the prompt before the URL."',
  '      word "открой урл"',
  '        description "Russian bare marker (romanized otkroi url) for opening a url; matched anywhere in the prompt before the URL."',
  '      word "покажи сайт"',
  '        description "Russian bare marker (romanized pokazhi sait) for showing a site; matched anywhere in the prompt before the URL."',
  '      word "покажи страницу"',
  '        description "Russian bare marker (romanized pokazhi stranitsu) for showing a page; matched anywhere in the prompt before the URL."',
  '      word "зайди на"',
  '        description "Russian bare marker (romanized zaidi na) for going onto a target; matched anywhere in the prompt before the URL."',
  '    lexeme "hi"',
  '      word "पर जाएं"',
  '        description "Hindi bare marker (romanized par jaen) meaning go to; matched anywhere in the prompt when a URL is present."',
  '      word "खोलें"',
  '        description "Hindi bare marker (romanized kholen) meaning open; matched anywhere in the prompt when a URL is present."',
  '      word "देखें"',
  '        description "Hindi bare marker (romanized dekhen) meaning view or see; matched anywhere in the prompt when a URL is present."',
  '    lexeme "zh"',
  '      word "打开"',
  '        description "Chinese bare marker (pinyin dakai) meaning open; matched anywhere in the prompt when a URL is present."',
  '      word "访问"',
  '        description "Chinese bare marker (pinyin fangwen) meaning visit or access; matched anywhere in the prompt when a URL is present."',
  '      word "前往"',
  '        description "Chinese bare marker (pinyin qianwang) meaning go to; matched anywhere in the prompt when a URL is present."',
  '      word "查看"',
  '        description "Chinese bare marker (pinyin chakan) meaning view or look at; matched anywhere in the prompt when a URL is present."',
  "meanings",
  '  meaning "web_search"',
  '    gloss "a request to search the open web (or a public reference such as an encyclopedia) for information about a topic — the concept a web-search prompt expresses, independent of language. The solver extracts the topic and looks it up; it is distinct from http_fetch and url_navigate, which act on a single named URL. Two surface conventions are shared by every web-search marker. (1) A marker written with a leading and trailing space, like the value containing search surrounded by spaces, matches only as a whole token, so it never fires inside a longer word; a marker written with no surrounding space matches as a substring, which is how the Devanagari and Han markers fold their inflections. (2) A marker that ends with the ellipsis … (U+2026) is a prefix surface whose query follows the literal before the slot; the handler strips that literal and keeps the remainder as the query."',
  '    wiktionary "search"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    defined_by "web_resource"',
  '    role "web_search_concept"',
  '    lexeme "en"',
  '      word "web search"',
  '        description "English noun phrase naming the act of searching the web for information about a topic."',
  '      word "search the web"',
  '        description "English verb phrase for performing a web search — the canonical realisation of this concept."',
  '    lexeme "ru"',
  '      word "поиск в интернете"',
  '        description "Russian noun phrase (romanized poisk v internete) for a web search — looking a topic up on the internet."',
  '      word "веб-поиск"',
  '        description "Russian compound (romanized veb-poisk) naming a web search."',
  '    lexeme "hi"',
  '      word "वेब खोज"',
  '        description "Hindi noun phrase (romanized veb khoj) for a web search — looking a topic up on the web."',
  '      word "इंटरनेट पर खोज"',
  '        description "Hindi phrase (romanized internet par khoj) for searching the internet for a topic."',
  '    lexeme "zh"',
  '      word "网络搜索"',
  '        description "Chinese noun phrase (pinyin wangluo sousuo) for a web search."',
  '      word "在网上搜索"',
  '        description "Chinese verb phrase (pinyin zai wangshang sousuo) for searching on the web."',
  '  meaning "reference_internet"',
  '    gloss "the open internet seen as a place to look something up — the web, the net, the online world. As a web-search signal its surfaces are matched anywhere in the prompt (whole-token for the space-wrapped Latin and Cyrillic forms, substring for the Han forms) to confirm that a weak search verb is aimed at the web. The same concept also names a standalone source: a prompt whose whole extracted query is just the word internet (in any language) is rejected as a bare source rather than searched for, which is why this meaning also carries the source-only role. The handler reads the source-only words by trimming these signal surfaces. The same internet-naming surfaces also fill the web_medium role: paired with a leading imperative search verb they confirm that a prompt explicitly asks to search the web, so a documentation handler can screen such a prompt out of its method-question gate."',
  '    wiktionary "internet"',
  '    defined_by "web_resource"',
  '    defined_by "entity"',
  '    role "web_search_signal"',
  '    role "web_search_source_only"',
  '    role "web_medium"',
  '    lexeme "en"',
  '      word " web "',
  '        description "English noun (the web), space-wrapped so it matches only as a whole token; trimmed it is the bare source word web."',
  '      word " internet "',
  '        description "English noun (the internet), space-wrapped for a whole-token match; trimmed it is the bare source word internet."',
  '      word " online "',
  '        description "English adverb (online), space-wrapped for a whole-token match; trimmed it is the bare source word online."',
  '    lexeme "ru"',
  '      word " интернете "',
  '        description "Russian prepositional form (romanized internete), space-wrapped for a whole-token match; trimmed it is the bare source word интернете."',
  '      word " интернет "',
  '        description "Russian noun (romanized internet), space-wrapped for a whole-token match; trimmed it is the bare source word интернет."',
  '      word " онлайн "',
  '        description "Russian adverb (romanized onlain), space-wrapped for a whole-token match; trimmed it is the bare source word онлайн."',
  '      word " сети "',
  '        description "Russian noun (romanized seti, in the net), space-wrapped for a whole-token match; trimmed it is the bare source word сети."',
  '    lexeme "hi"',
  '      word "इंटरनेट"',
  '        description "Hindi noun (romanized internet) for the internet; a bare substring marker that also names a standalone source."',
  '      word "ऑनलाइन"',
  '        description "Hindi adverb (romanized onlain) for online; a bare substring marker that also names a standalone source."',
  '      word "वेब"',
  '        description "Hindi noun (romanized veb) for the web; a bare substring marker that also names a standalone source."',
  '    lexeme "zh"',
  '      word "网上"',
  '        description "Chinese phrase (pinyin wangshang) for on the web; a bare substring marker that also names a standalone source."',
  '      word "網上"',
  '        description "Chinese phrase (pinyin wangshang, traditional) for on the web; a bare substring marker that also names a standalone source."',
  '      word "在线"',
  '        description "Chinese phrase (pinyin zaixian) for online; a bare substring marker that also names a standalone source."',
  '      word "在線"',
  '        description "Chinese phrase (pinyin zaixian, traditional) for online; a bare substring marker that also names a standalone source."',
  '      word "互联网"',
  '        description "Chinese noun (pinyin hulianwang) for the internet; a bare substring marker that also names a standalone source."',
  '      word "網路"',
  '        description "Chinese noun (pinyin wanglu, traditional) for the network or internet; a bare substring marker that also names a standalone source."',
  '      word "网络"',
  '        description "Chinese noun (pinyin wangluo) for the network or internet; a bare substring marker that also names a standalone source."',
  '  meaning "reference_encyclopedia"',
  '    gloss "a named public reference work used as a place to look something up — Wikipedia, Wikidata, Wiktionary and their kin. As a web-search signal its surfaces confirm that a weak search verb targets a reference source; the Russian and Han forms are written as stems (no trailing boundary) so they fold inflected and compound spellings. The concept is also a standalone source: a query that is just the name of the encyclopedia is rejected rather than searched for, so this meaning carries the source-only role too. For exactness the Russian genitive википедии is stored as its own bare source word in addition to the stem."',
  '    wiktionary "encyclopedia"',
  '    defined_by "web_resource"',
  '    defined_by "entity"',
  '    role "web_search_signal"',
  '    role "web_search_source_only"',
  '    lexeme "en"',
  '      word " wikipedia "',
  '        description "English proper noun (Wikipedia), space-wrapped for a whole-token match; trimmed it is the bare source word wikipedia."',
  '      word " wikidata "',
  '        description "English proper noun (Wikidata), space-wrapped for a whole-token match; trimmed it is the bare source word wikidata."',
  '      word " wiktionary "',
  '        description "English proper noun (Wiktionary), space-wrapped for a whole-token match; trimmed it is the bare source word wiktionary."',
  '    lexeme "ru"',
  '      word " википед"',
  '        description "Russian stem (romanized wikiped) with a leading boundary only, so it folds википедия, википедии and википедию as a signal."',
  '      word " викиданн"',
  '        description "Russian stem (romanized wikidann) with a leading boundary only, so it folds the declensions of Wikidata as a signal."',
  '      word "википедии"',
  '        description "Russian genitive (romanized wikipedii) stored bare so the standalone source word википедии is rejected exactly as a bare source."',
  '    lexeme "hi"',
  '      word "विकिपीडिया"',
  '        description "Hindi proper noun (romanized vikipidiya) for Wikipedia; a bare substring marker that also names a standalone source."',
  '      word "विकिडाटा"',
  '        description "Hindi proper noun (romanized vikidata) for Wikidata; a bare substring marker that also names a standalone source."',
  '    lexeme "zh"',
  '      word "百科"',
  '        description "Chinese noun (pinyin baike) for an encyclopedia; a bare substring marker that also names a standalone source."',
  '      word "维基百科"',
  '        description "Chinese proper noun (pinyin weiji baike) for Wikipedia; a bare substring marker that also names a standalone source."',
  '      word "維基百科"',
  '        description "Chinese proper noun (pinyin weiji baike, traditional) for Wikipedia; a bare substring marker that also names a standalone source."',
  '      word "维基数据"',
  '        description "Chinese proper noun (pinyin weiji shuju) for Wikidata; a bare substring marker that also names a standalone source."',
  '      word "維基數據"',
  '        description "Chinese proper noun (pinyin weiji shuju, traditional) for Wikidata; a bare substring marker that also names a standalone source."',
  '  meaning "reference_information"',
  '    gloss "information itself seen as the thing a search is after — facts, details, data, materials, sources, articles. As a web-search signal these surfaces confirm that a weak search verb is looking for information, but unlike the internet and the encyclopedia they are not standalone sources: a query that is merely the word information is still a real query, so this meaning carries the signal role only and never the source-only role. The Russian forms that originally folded inflections are kept as leading-boundary stems."',
  '    wiktionary "information"',
  '    defined_by "concept"',
  '    role "web_search_signal"',
  '    lexeme "en"',
  '      word " information "',
  '        description "English noun (information), space-wrapped for a whole-token signal match."',
  '      word " info "',
  '        description "English clipping (info), space-wrapped for a whole-token signal match."',
  '      word " details "',
  '        description "English noun (details), space-wrapped for a whole-token signal match."',
  '      word " data "',
  '        description "English noun (data), space-wrapped for a whole-token signal match."',
  '      word " material "',
  '        description "English noun (material), space-wrapped for a whole-token signal match."',
  '      word " materials "',
  '        description "English noun (materials), space-wrapped for a whole-token signal match."',
  '      word " resource "',
  '        description "English noun (resource), space-wrapped for a whole-token signal match."',
  '      word " resources "',
  '        description "English noun (resources), space-wrapped for a whole-token signal match."',
  '      word " source "',
  '        description "English noun (source), space-wrapped for a whole-token signal match."',
  '      word " sources "',
  '        description "English noun (sources), space-wrapped for a whole-token signal match."',
  '      word " article "',
  '        description "English noun (article), space-wrapped for a whole-token signal match."',
  '      word " articles "',
  '        description "English noun (articles), space-wrapped for a whole-token signal match."',
  '      word " fact "',
  '        description "English noun (fact), space-wrapped for a whole-token signal match."',
  '      word " facts "',
  '        description "English noun (facts), space-wrapped for a whole-token signal match."',
  '    lexeme "ru"',
  '      word " информац"',
  '        description "Russian stem (romanized informac) with a leading boundary only, folding информация, информацию and информации as a signal."',
  '      word " инфу "',
  '        description "Russian colloquial accusative (romanized infu), space-wrapped for a whole-token signal match."',
  '      word " сведения "',
  '        description "Russian noun (romanized svedeniya, information), space-wrapped for a whole-token signal match."',
  '      word " материал"',
  '        description "Russian stem (romanized material) with a leading boundary only, folding материал, материалы and материалов as a signal."',
  '      word " данные "',
  '        description "Russian noun (romanized dannye, data), space-wrapped for a whole-token signal match."',
  '      word " источник"',
  '        description "Russian stem (romanized istochnik) with a leading boundary only, folding источник, источники and источников as a signal."',
  '    lexeme "hi"',
  '      word "जानकारी"',
  '        description "Hindi noun (romanized jankari) for information; a bare substring signal marker."',
  '      word "सूचना"',
  '        description "Hindi noun (romanized suchna) for information or notice; a bare substring signal marker."',
  '      word "विवरण"',
  '        description "Hindi noun (romanized vivaran) for details; a bare substring signal marker."',
  '      word "सामग्री"',
  '        description "Hindi noun (romanized samagri) for material; a bare substring signal marker."',
  '      word "स्रोत"',
  '        description "Hindi noun (romanized srot) for a source; a bare substring signal marker."',
  '      word "लेख"',
  '        description "Hindi noun (romanized lekh) for an article; a bare substring signal marker."',
  '    lexeme "zh"',
  '      word "信息"',
  '        description "Chinese noun (pinyin xinxi) for information; a bare substring signal marker."',
  '      word "資料"',
  '        description "Chinese noun (pinyin ziliao, traditional) for data or material; a bare substring signal marker."',
  '      word "资料"',
  '        description "Chinese noun (pinyin ziliao) for data or material; a bare substring signal marker."',
  '      word "内容"',
  '        description "Chinese noun (pinyin neirong) for content; a bare substring signal marker."',
  '      word "來源"',
  '        description "Chinese noun (pinyin laiyuan, traditional) for a source; a bare substring signal marker."',
  '      word "来源"',
  '        description "Chinese noun (pinyin laiyuan) for a source; a bare substring signal marker."',
  '      word "资源"',
  '        description "Chinese noun (pinyin ziyuan) for a resource; a bare substring signal marker."',
  '      word "資源"',
  '        description "Chinese noun (pinyin ziyuan, traditional) for a resource; a bare substring signal marker."',
  '      word "文章"',
  '        description "Chinese noun (pinyin wenzhang) for an article; a bare substring signal marker."',
  '  meaning "act_search_strong"',
  '    gloss "the decisive search action — to search, look up, research or investigate. It is strong because, on its own, it is enough to route a prompt to web search without any reference-source signal. Each verb appears twice: as a space-wrapped (or, for Devanagari and Han, bare substring) bare marker used to detect that a search is being asked for, and as a prefix surface ending in … used to extract the query that follows the imperative. The longer prefix search for … is listed before the shorter search … so an imperative like search for cats keeps cats rather than for cats."',
  '    wiktionary "search"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "web_search_action"',
  '    role "web_search_strong_action"',
  '    role "web_search_imperative_lead"',
  '    lexeme "en"',
  '      word " search "',
  '        description "English verb (to search), space-wrapped bare marker detecting a strong search action."',
  '      word " look up "',
  '        description "English phrasal verb (to look up), space-wrapped bare marker detecting a strong search action."',
  '      word " lookup "',
  '        description "English one-word spelling (lookup), space-wrapped bare marker detecting a strong search action."',
  '      word " research "',
  '        description "English verb (to research), space-wrapped bare marker detecting a strong search action."',
  '      word " investigate "',
  '        description "English verb (to investigate), space-wrapped bare marker detecting a strong search action."',
  '      word "search for …"',
  '        description "English imperative prefix surface; the query follows search for, listed first so for is not kept in the query."',
  '      word "search …"',
  '        description "English imperative prefix surface; the query follows the verb search."',
  '      word "look up …"',
  '        description "English imperative prefix surface; the query follows look up."',
  '      word "lookup …"',
  '        description "English imperative prefix surface; the query follows the one-word lookup."',
  '      word "research …"',
  '        description "English imperative prefix surface; the query follows research."',
  '      word "investigate …"',
  '        description "English imperative prefix surface; the query follows investigate."',
  '    lexeme "ru"',
  '      word " поищи "',
  '        description "Russian imperative (romanized poishchi, search), space-wrapped bare marker detecting a strong search action."',
  '      word " поиск "',
  '        description "Russian noun (romanized poisk, a search), space-wrapped bare marker detecting a strong search action."',
  '      word " поискать "',
  '        description "Russian infinitive (romanized poiskat, to search), space-wrapped bare marker detecting a strong search action."',
  '      word " ищи "',
  '        description "Russian imperative (romanized ishchi, seek), space-wrapped bare marker detecting a strong search action."',
  '      word "поищи …"',
  '        description "Russian imperative prefix surface (romanized poishchi); the query follows the verb."',
  '      word "поискать …"',
  '        description "Russian infinitive prefix surface (romanized poiskat); the query follows the verb."',
  '      word "ищи …"',
  '        description "Russian imperative prefix surface (romanized ishchi); the query follows the verb."',
  '    lexeme "hi"',
  '      word "खोज"',
  '        description "Hindi verb stem (romanized khoj, search) as a bare substring marker detecting a strong search action across its inflections."',
  '      word "ढूंढ"',
  '        description "Hindi verb stem (romanized dhundh, search) as a bare substring marker detecting a strong search action."',
  '      word "ढूँढ"',
  '        description "Hindi verb stem (romanized dhundh, nasalised spelling) as a bare substring marker detecting a strong search action."',
  '      word "खोजो …"',
  '        description "Hindi imperative prefix surface (romanized khojo); the query follows the verb."',
  '      word "खोजें …"',
  '        description "Hindi polite imperative prefix surface (romanized khojen); the query follows the verb."',
  '      word "खोजिए …"',
  '        description "Hindi formal imperative prefix surface (romanized khojie); the query follows the verb."',
  '      word "ढूंढो …"',
  '        description "Hindi imperative prefix surface (romanized dhundho); the query follows the verb."',
  '      word "ढूँढो …"',
  '        description "Hindi imperative prefix surface (romanized dhundho, nasalised); the query follows the verb."',
  '      word "ढूंढें …"',
  '        description "Hindi polite imperative prefix surface (romanized dhundhen); the query follows the verb."',
  '      word "ढूँढें …"',
  '        description "Hindi polite imperative prefix surface (romanized dhundhen, nasalised); the query follows the verb."',
  '    lexeme "zh"',
  '      word "搜索"',
  '        description "Chinese verb (pinyin sousuo, to search) as a bare substring marker detecting a strong search action."',
  '      word "查找"',
  '        description "Chinese verb (pinyin chazhao, to look up) as a bare substring marker detecting a strong search action."',
  '      word "查询"',
  '        description "Chinese verb (pinyin chaxun, to query) as a bare substring marker detecting a strong search action."',
  '      word "檢索"',
  '        description "Chinese verb (pinyin jiansuo, to retrieve, traditional) as a bare substring marker detecting a strong search action."',
  '      word "检索"',
  '        description "Chinese verb (pinyin jiansuo, to retrieve) as a bare substring marker detecting a strong search action."',
  '      word "搜一下"',
  '        description "Chinese phrase (pinyin sou yixia, have a search) as a bare substring marker detecting a strong search action."',
  '      word "查一下"',
  '        description "Chinese phrase (pinyin cha yixia, have a look) as a bare substring marker detecting a strong search action."',
  '      word "搜索…"',
  '        description "Chinese imperative prefix surface (pinyin sousuo); the query follows the verb."',
  '      word "查找…"',
  '        description "Chinese imperative prefix surface (pinyin chazhao); the query follows the verb."',
  '      word "查询…"',
  '        description "Chinese imperative prefix surface (pinyin chaxun); the query follows the verb."',
  '      word "檢索…"',
  '        description "Chinese imperative prefix surface (pinyin jiansuo, traditional); the query follows the verb."',
  '      word "检索…"',
  '        description "Chinese imperative prefix surface (pinyin jiansuo); the query follows the verb."',
  '      word "搜一下…"',
  '        description "Chinese imperative prefix surface (pinyin sou yixia); the query follows the phrase."',
  '      word "查一下…"',
  '        description "Chinese imperative prefix surface (pinyin cha yixia); the query follows the phrase."',
  '  meaning "act_find_weak"',
  '    gloss "the weak search action — to find, locate or discover. It is weak because, unlike act_search_strong, it routes to web search only when the prompt also carries a reference-source signal such as the internet, an encyclopedia or information; on its own find is too ordinary to mean a web search. Each verb appears as a bare detection marker and as a prefix surface ending in … for extracting the query that follows. Hindi and Chinese weak verbs are provided so the concept is complete in every supported language."',
  '    wiktionary "find"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "web_search_action"',
  '    role "web_search_imperative_lead"',
  '    lexeme "en"',
  '      word " find "',
  '        description "English verb (to find), space-wrapped bare marker detecting a weak search action that needs a reference-source signal."',
  '      word "find …"',
  '        description "English imperative prefix surface; the query follows find."',
  '    lexeme "ru"',
  '      word " найди "',
  '        description "Russian imperative (romanized naidi, find), space-wrapped bare marker detecting a weak search action."',
  '      word " найти "',
  '        description "Russian infinitive (romanized naiti, to find), space-wrapped bare marker detecting a weak search action."',
  '      word " разыщи "',
  '        description "Russian imperative (romanized razyshchi, track down), space-wrapped bare marker detecting a weak search action."',
  '      word " узнай "',
  '        description "Russian imperative (romanized uznai, find out), space-wrapped bare marker detecting a weak search action."',
  '      word "найди …"',
  '        description "Russian imperative prefix surface (romanized naidi); the query follows the verb."',
  '      word "найти …"',
  '        description "Russian infinitive prefix surface (romanized naiti); the query follows the verb."',
  '      word "разыщи …"',
  '        description "Russian imperative prefix surface (romanized razyshchi); the query follows the verb."',
  '      word "узнай …"',
  '        description "Russian imperative prefix surface (romanized uznai); the query follows the verb."',
  '    lexeme "hi"',
  '      word "पता लगाओ"',
  '        description "Hindi phrase (romanized pata lagao, find out) as a bare substring marker detecting a weak search action that needs a reference-source signal."',
  '      word "पता लगाओ …"',
  '        description "Hindi imperative prefix surface (romanized pata lagao); the query follows the phrase."',
  '    lexeme "zh"',
  '      word "找到"',
  '        description "Chinese verb (pinyin zhaodao, to find) as a bare substring marker detecting a weak search action that needs a reference-source signal."',
  '      word "找到…"',
  '        description "Chinese imperative prefix surface (pinyin zhaodao); the query follows the verb."',
  '  meaning "web_search_mention"',
  '    gloss "a mention of web search inside an earlier conversation turn — not the current prompt — used to decide whether a terse follow-up such as search it or найди это refers back to a web search the assistant already offered. Unlike the other web-search markers it is tested against the raw, lowercased text of a prior turn (not the normalised prompt), so each surface is stored exactly as it appears, including the hyphen in веб-поиск; all forms are bare substrings. The signal is lexicalised in every supported language, so a Hindi or Chinese prior turn that searched the web is recognised just like an English or Russian one."',
  '    wiktionary "search"',
  '    defined_by "web_search"',
  '    role "web_search_history_signal"',
  '    lexeme "en"',
  '      word "duckduckgo"',
  '        description "English proper noun naming the DuckDuckGo search engine; a raw lowercased substring signalling that a prior turn performed a web search."',
  '      word "web search"',
  '        description "English phrase (web search); a raw lowercased substring signalling that a prior turn performed a web search."',
  '      word "search the internet"',
  '        description "English phrase (search the internet); a raw lowercased substring signalling that a prior turn performed a web search."',
  '    lexeme "ru"',
  '      word "веб-поиск"',
  '        description "Russian compound (romanized veb-poisk, web search), hyphenated; a raw lowercased substring signalling that a prior turn performed a web search."',
  '      word "веб поиск"',
  '        description "Russian phrase (romanized veb poisk, web search), spaced; a raw lowercased substring signalling that a prior turn performed a web search."',
  '      word "интернет"',
  '        description "Russian noun (romanized internet); a raw lowercased substring signalling that a prior turn referenced the internet."',
  '    lexeme "hi"',
  '      word "वेब खोज"',
  '        description "Hindi phrase (romanized veb khoj, web search); a raw lowercased substring signalling that a prior turn performed a web search."',
  '      word "इंटरनेट पर खोज"',
  '        description "Hindi phrase (romanized internet par khoj, search the internet); a raw lowercased substring signalling that a prior turn performed a web search."',
  '      word "इंटरनेट"',
  '        description "Hindi noun (romanized internet); a raw lowercased substring signalling that a prior turn referenced the internet."',
  '    lexeme "zh"',
  '      word "网络搜索"',
  '        description "Chinese phrase (pinyin wangluo sousuo, web search) in simplified script; a raw lowercased substring signalling that a prior turn performed a web search."',
  '      word "在网上搜索"',
  '        description "Chinese phrase (pinyin zai wangshang sousuo, search on the web) in simplified script; a raw lowercased substring signalling that a prior turn performed a web search."',
  '      word "互联网"',
  '        description "Chinese noun (pinyin hulianwang, internet) in simplified script; a raw lowercased substring signalling that a prior turn referenced the internet."',
  '      word "網路"',
  '        description "Chinese noun (pinyin wanglu, network or internet) in traditional script; a raw lowercased substring signalling that a prior turn referenced the internet."',
  "meanings",
  '  meaning "explicit_web_search_command"',
  '    gloss "an explicit, fully spelled-out web-search command whose topic sits at the very end — search the web for X, find information about X, найди в интернете X. It is a specialisation of web_search in which the source and the act are stated outright, so the recogniser does not have to infer them: it strips the lead-in from the front of the prompt and keeps whatever follows as the query. Every surface is a prefix surface ending with the ellipsis … (U+2026); the literal before the slot is the lead-in to strip (it keeps its trailing space so the boundary is exact), and the remainder is the search topic. The longer, more specific lead-ins are written before the shorter ones so that, for example, find detailed information about … wins over find information about …. English and Russian carry the original lead-ins verbatim; Hindi and Chinese add natural verb-initial commands so the concept is complete in every supported language."',
  '    wiktionary "search"',
  '    defined_by "web_search"',
  '    defined_by "action"',
  '    role "web_search_explicit_prefix"',
  '    lexeme "en"',
  '      word "search the web for …"',
  '        description "English lead-in naming the web as the source; the query is whatever follows search the web for."',
  '      word "search web for …"',
  '        description "English lead-in (article-dropped variant of search the web for); the query follows."',
  '      word "search the internet for …"',
  '        description "English lead-in naming the internet as the source; the query follows search the internet for."',
  '      word "search internet for …"',
  '        description "English lead-in (article-dropped variant of search the internet for); the query follows."',
  '      word "search online for …"',
  '        description "English lead-in naming online search; the query follows search online for."',
  '      word "search wikipedia for …"',
  '        description "English lead-in naming Wikipedia as the source; the query follows search wikipedia for."',
  '      word "search wikidata for …"',
  '        description "English lead-in naming Wikidata as the source; the query follows search wikidata for."',
  '      word "search wiktionary for …"',
  '        description "English lead-in naming Wiktionary as the source; the query follows search wiktionary for."',
  '      word "search for information about …"',
  '        description "English lead-in asking for information about a topic; the query follows search for information about."',
  '      word "search for information on …"',
  '        description "English lead-in asking for information on a topic; the query follows search for information on."',
  '      word "web search for …"',
  '        description "English lead-in naming a web search; the query follows web search for."',
  '      word "find on the internet …"',
  '        description "English lead-in asking to find something on the internet; the query follows find on the internet."',
  '      word "find online …"',
  '        description "English lead-in asking to find something online; the query follows find online."',
  '      word "find information about …"',
  '        description "English lead-in asking to find information about a topic; the query follows find information about."',
  '      word "find information on …"',
  '        description "English lead-in asking to find information on a topic; the query follows find information on."',
  '      word "find detailed information about …"',
  '        description "English lead-in asking to find detailed information about a topic; listed before find information about so detailed is not kept; the query follows."',
  '      word "find detailed information on …"',
  '        description "English lead-in asking to find detailed information on a topic; listed before find information on so detailed is not kept; the query follows."',
  '      word "find info about …"',
  '        description "English lead-in (clipped info) asking to find information about a topic; the query follows find info about."',
  '      word "find info on …"',
  '        description "English lead-in (clipped info) asking to find information on a topic; the query follows find info on."',
  '      word "look up information about …"',
  '        description "English lead-in asking to look up information about a topic; the query follows look up information about."',
  '      word "look up information on …"',
  '        description "English lead-in asking to look up information on a topic; the query follows look up information on."',
  '      word "look up info about …"',
  '        description "English lead-in (clipped info) asking to look up information about a topic; the query follows look up info about."',
  '      word "look up info on …"',
  '        description "English lead-in (clipped info) asking to look up information on a topic; the query follows look up info on."',
  '      word "look up online …"',
  '        description "English lead-in asking to look something up online; the query follows look up online."',
  '    lexeme "ru"',
  '      word "найди в интернете …"',
  '        description "Russian lead-in (romanized naidi v internete, find on the internet); the query follows the lead-in."',
  '      word "поищи в интернете …"',
  '        description "Russian lead-in (romanized poishchi v internete, search on the internet); the query follows the lead-in."',
  '      word "поиск в интернете …"',
  '        description "Russian lead-in (romanized poisk v internete, a search on the internet); the query follows the lead-in."',
  '      word "найди онлайн …"',
  '        description "Russian lead-in (romanized naidi onlain, find online); the query follows the lead-in."',
  '      word "поищи онлайн …"',
  '        description "Russian lead-in (romanized poishchi onlain, search online); the query follows the lead-in."',
  '      word "найди в сети …"',
  '        description "Russian lead-in (romanized naidi v seti, find on the net); the query follows the lead-in."',
  '      word "поищи в сети …"',
  '        description "Russian lead-in (romanized poishchi v seti, search on the net); the query follows the lead-in."',
  '      word "найди информацию в интернете о …"',
  '        description "Russian lead-in (romanized naidi informaciyu v internete o, find information on the internet about); the query follows."',
  '      word "найди информацию в интернете об …"',
  '        description "Russian lead-in (romanized naidi informaciyu v internete ob, the ob variant before a vowel); the query follows."',
  '      word "поищи информацию в интернете о …"',
  '        description "Russian lead-in (romanized poishchi informaciyu v internete o, search the internet for information about); the query follows."',
  '      word "поищи информацию в интернете об …"',
  '        description "Russian lead-in (romanized poishchi informaciyu v internete ob, the ob variant before a vowel); the query follows."',
  '      word "найди информацию о …"',
  '        description "Russian lead-in (romanized naidi informaciyu o, find information about); the query follows."',
  '      word "найди информацию об …"',
  '        description "Russian lead-in (romanized naidi informaciyu ob, the ob variant before a vowel); the query follows."',
  '      word "найди информацию про …"',
  '        description "Russian lead-in (romanized naidi informaciyu pro, find information about); the query follows."',
  '      word "найди информацию по …"',
  '        description "Russian lead-in (romanized naidi informaciyu po, find information on); the query follows."',
  '      word "найти информацию о …"',
  '        description "Russian lead-in (romanized naiti informaciyu o, infinitive to find information about); the query follows."',
  '      word "найти информацию об …"',
  '        description "Russian lead-in (romanized naiti informaciyu ob, the ob variant before a vowel); the query follows."',
  '      word "поищи информацию о …"',
  '        description "Russian lead-in (romanized poishchi informaciyu o, search for information about); the query follows."',
  '      word "поищи информацию об …"',
  '        description "Russian lead-in (romanized poishchi informaciyu ob, the ob variant before a vowel); the query follows."',
  '      word "поищи информацию про …"',
  '        description "Russian lead-in (romanized poishchi informaciyu pro, search for information about); the query follows."',
  '      word "поищи информацию по …"',
  '        description "Russian lead-in (romanized poishchi informaciyu po, search for information on); the query follows."',
  '      word "найди инфу о …"',
  '        description "Russian lead-in (romanized naidi infu o, colloquial find info about); the query follows."',
  '      word "найди инфу об …"',
  '        description "Russian lead-in (romanized naidi infu ob, the ob variant before a vowel); the query follows."',
  '      word "поищи инфу о …"',
  '        description "Russian lead-in (romanized poishchi infu o, colloquial search for info about); the query follows."',
  '      word "поищи инфу об …"',
  '        description "Russian lead-in (romanized poishchi infu ob, the ob variant before a vowel); the query follows."',
  '      word "найди сведения о …"',
  '        description "Russian lead-in (romanized naidi svedeniya o, find information about); the query follows."',
  '      word "найди сведения об …"',
  '        description "Russian lead-in (romanized naidi svedeniya ob, the ob variant before a vowel); the query follows."',
  '      word "поищи сведения о …"',
  '        description "Russian lead-in (romanized poishchi svedeniya o, search for information about); the query follows."',
  '      word "поищи сведения об …"',
  '        description "Russian lead-in (romanized poishchi svedeniya ob, the ob variant before a vowel); the query follows."',
  '      word "найди материалы о …"',
  '        description "Russian lead-in (romanized naidi materialy o, find materials about); the query follows."',
  '      word "найди материалы об …"',
  '        description "Russian lead-in (romanized naidi materialy ob, the ob variant before a vowel); the query follows."',
  '      word "поищи материалы о …"',
  '        description "Russian lead-in (romanized poishchi materialy o, search for materials about); the query follows."',
  '      word "поищи материалы об …"',
  '        description "Russian lead-in (romanized poishchi materialy ob, the ob variant before a vowel); the query follows."',
  '    lexeme "hi"',
  '      word "इंटरनेट पर खोजें …"',
  '        description "Hindi verb-initial command (romanized internet par khojen, search on the internet); the query follows the lead-in."',
  '      word "वेब पर खोजें …"',
  '        description "Hindi verb-initial command (romanized veb par khojen, search on the web); the query follows the lead-in."',
  '      word "ऑनलाइन खोजें …"',
  '        description "Hindi verb-initial command (romanized onlain khojen, search online); the query follows the lead-in."',
  '      word "विकिपीडिया पर खोजें …"',
  '        description "Hindi verb-initial command (romanized vikipidiya par khojen, search on Wikipedia); the query follows the lead-in."',
  '    lexeme "zh"',
  '      word "在网上搜索…"',
  '        description "Chinese verb-initial command (pinyin zai wangshang sousuo, search on the web for); the query follows the lead-in."',
  '      word "在互联网上搜索…"',
  '        description "Chinese verb-initial command (pinyin zai hulianwang shang sousuo, search on the internet for); the query follows the lead-in."',
  '      word "在维基百科上搜索…"',
  '        description "Chinese verb-initial command (pinyin zai weiji baike shang sousuo, search on Wikipedia for); the query follows the lead-in."',
  '      word "上网查找…"',
  '        description "Chinese verb-initial command (pinyin shangwang chazhao, go online and look up); the query follows the lead-in."',
  '  meaning "topic_connective"',
  '    gloss "the connective that ties a search verb to the topic it is about — the aboutness relation between a query and its subject. Its surfaces split by word order, and the slot shape records which side the topic falls on. In head-initial languages the connective precedes the topic, so the form is a prefix surface ( about …, о …, 关于…) whose literal before the slot is found in the prompt and the remainder taken as the query. In head-final Hindi the postposition follows the topic, so the form is a suffix surface (… के बारे में) whose literal after the slot is found and the text before it taken as the query. The recogniser reads the slot to decide the direction, trying the prefix (after-topic) connectives before the suffix (before-topic) ones; within each side the order is the declared order, so the specific about/regarding markers are tried before the broad for."',
  '    wiktionary "about"',
  '    defined_by "relation"',
  '    role "web_search_topic_marker"',
  '    lexeme "en"',
  '      word " about …"',
  '        description "English connective (about), space-wrapped before the slot; the topic follows, so the text after about is the query."',
  '      word " on …"',
  '        description "English connective (on), space-wrapped before the slot; the topic follows on."',
  '      word " regarding …"',
  '        description "English connective (regarding), space-wrapped before the slot; the topic follows regarding."',
  '      word " concerning …"',
  '        description "English connective (concerning), space-wrapped before the slot; the topic follows concerning."',
  '      word " for …"',
  '        description "English connective (for), the broadest marker so it is tried last; the topic follows for."',
  '    lexeme "ru"',
  '      word " о …"',
  '        description "Russian preposition (romanized o, about), space-wrapped before the slot; the topic follows."',
  '      word " об …"',
  '        description "Russian preposition (romanized ob, the variant before a vowel); the topic follows."',
  '      word " про …"',
  '        description "Russian preposition (romanized pro, about), space-wrapped before the slot; the topic follows."',
  '      word " по …"',
  '        description "Russian preposition (romanized po, on/about), space-wrapped before the slot; the topic follows."',
  '      word " насчет …"',
  '        description "Russian preposition (romanized naschet, regarding), space-wrapped before the slot; the topic follows."',
  '      word " относительно …"',
  '        description "Russian preposition (romanized otnositelno, concerning), space-wrapped before the slot; the topic follows."',
  '    lexeme "hi"',
  '      word "… के बारे में"',
  '        description "Hindi postposition (romanized ke baare mein, about) after the slot; the topic precedes it, so the text before के बारे में is the query."',
  '      word "… के विषय में"',
  '        description "Hindi postposition (romanized ke vishay mein, on the subject of) after the slot; the topic precedes it."',
  '      word "… से संबंधित"',
  '        description "Hindi postposition (romanized se sambandhit, related to) after the slot; the topic precedes it."',
  '      word "… पर"',
  '        description "Hindi postposition (romanized par, on) after the slot; the topic precedes it."',
  '      word "… की जानकारी"',
  '        description "Hindi postposition phrase (romanized ki jankari, information of) after the slot; the topic precedes it."',
  '      word "… की सूचना"',
  '        description "Hindi postposition phrase (romanized ki suchna, notice of) after the slot; the topic precedes it."',
  '    lexeme "zh"',
  '      word "关于…"',
  '        description "Chinese coverb (pinyin guanyu, about) before the slot; the topic follows."',
  '      word "關於…"',
  '        description "Chinese coverb (pinyin guanyu, about, traditional) before the slot; the topic follows."',
  '      word "有关…"',
  '        description "Chinese coverb (pinyin youguan, concerning) before the slot; the topic follows."',
  '      word "有關…"',
  '        description "Chinese coverb (pinyin youguan, concerning, traditional) before the slot; the topic follows."',
  '  meaning "query_leading_noise"',
  '    gloss "filler that precedes the real search topic and must be trimmed off its front — politeness, articles, quantifiers and information about lead-ins that are not part of the topic. As a leading-noise marker each surface is a prefix surface whose literal before the slot is stripped from the start of an extracted query; the recogniser strips repeatedly until the query stops changing, so the declared order does not matter. The Latin and Cyrillic forms keep their trailing space so they peel off a whole leading word, while the Han forms are bare. These overlap deliberately with the topic connectives ( о  versus o ): here the marker sits at the very front of the query, so only a trailing boundary is needed."',
  '    wiktionary "please"',
  '    defined_by "concept"',
  '    role "web_search_query_leading_noise"',
  '    lexeme "en"',
  '      word "please …"',
  '        description "English politeness particle (please), stripped from the front of a query."',
  '      word "can you …"',
  '        description "English request frame (can you), stripped from the front of a query."',
  '      word "could you …"',
  '        description "English request frame (could you), stripped from the front of a query."',
  '      word "would you …"',
  '        description "English request frame (would you), stripped from the front of a query."',
  '      word "me …"',
  '        description "English object pronoun (me) left after show/give me, stripped from the front of a query."',
  '      word "the …"',
  '        description "English definite article (the), stripped from the front of a query."',
  '      word "some …"',
  '        description "English quantifier (some), stripped from the front of a query."',
  '      word "detailed …"',
  '        description "English adjective (detailed), stripped from the front of a query."',
  '      word "more …"',
  '        description "English quantifier (more), stripped from the front of a query."',
  '      word "current …"',
  '        description "English adjective (current), stripped from the front of a query."',
  '      word "latest …"',
  '        description "English adjective (latest), stripped from the front of a query."',
  '      word "information about …"',
  '        description "English lead-in (information about) left after a verb, stripped from the front of a query."',
  '      word "information on …"',
  '        description "English lead-in (information on), stripped from the front of a query."',
  '      word "info about …"',
  '        description "English lead-in (clipped info about), stripped from the front of a query."',
  '      word "info on …"',
  '        description "English lead-in (clipped info on), stripped from the front of a query."',
  '      word "details about …"',
  '        description "English lead-in (details about), stripped from the front of a query."',
  '      word "details on …"',
  '        description "English lead-in (details on), stripped from the front of a query."',
  '      word "data about …"',
  '        description "English lead-in (data about), stripped from the front of a query."',
  '      word "data on …"',
  '        description "English lead-in (data on), stripped from the front of a query."',
  '    lexeme "ru"',
  '      word "подробные …"',
  '        description "Russian adjective (romanized podrobnye, detailed), stripped from the front of a query."',
  '      word "информацию о …"',
  '        description "Russian lead-in (romanized informaciyu o, information about), stripped from the front of a query."',
  '      word "информацию об …"',
  '        description "Russian lead-in (romanized informaciyu ob, the ob variant before a vowel), stripped from the front of a query."',
  '      word "инфу о …"',
  '        description "Russian colloquial lead-in (romanized infu o, info about), stripped from the front of a query."',
  '      word "инфу об …"',
  '        description "Russian colloquial lead-in (romanized infu ob, the ob variant before a vowel), stripped from the front of a query."',
  '      word "сведения о …"',
  '        description "Russian lead-in (romanized svedeniya o, information about), stripped from the front of a query."',
  '      word "сведения об …"',
  '        description "Russian lead-in (romanized svedeniya ob, the ob variant before a vowel), stripped from the front of a query."',
  '      word "материалы о …"',
  '        description "Russian lead-in (romanized materialy o, materials about), stripped from the front of a query."',
  '      word "материалы об …"',
  '        description "Russian lead-in (romanized materialy ob, the ob variant before a vowel), stripped from the front of a query."',
  '      word "материалы по …"',
  '        description "Russian lead-in (romanized materialy po, materials on), stripped from the front of a query."',
  '      word "данные о …"',
  '        description "Russian lead-in (romanized dannye o, data about), stripped from the front of a query."',
  '      word "данные об …"',
  '        description "Russian lead-in (romanized dannye ob, the ob variant before a vowel), stripped from the front of a query."',
  '      word "о …"',
  '        description "Russian preposition (romanized o, about) at the very front, stripped from the front of a query."',
  '      word "об …"',
  '        description "Russian preposition (romanized ob, the variant before a vowel), stripped from the front of a query."',
  '      word "про …"',
  '        description "Russian preposition (romanized pro, about), stripped from the front of a query."',
  '      word "по …"',
  '        description "Russian preposition (romanized po, on/about), stripped from the front of a query."',
  '    lexeme "hi"',
  '      word "कृपया …"',
  '        description "Hindi politeness particle (romanized kripya, please), stripped from the front of a query."',
  '      word "जानकारी …"',
  '        description "Hindi noun (romanized jankari, information) lead-in, stripped from the front of a query."',
  '      word "सूचना …"',
  '        description "Hindi noun (romanized suchna, information) lead-in, stripped from the front of a query."',
  '      word "विवरण …"',
  '        description "Hindi noun (romanized vivaran, details) lead-in, stripped from the front of a query."',
  '      word "सामग्री …"',
  '        description "Hindi noun (romanized samagri, material) lead-in, stripped from the front of a query."',
  '    lexeme "zh"',
  '      word "关于…"',
  '        description "Chinese coverb (pinyin guanyu, about) at the front, stripped from the front of a query."',
  '      word "關於…"',
  '        description "Chinese coverb (pinyin guanyu, about, traditional), stripped from the front of a query."',
  '      word "有关…"',
  '        description "Chinese coverb (pinyin youguan, concerning), stripped from the front of a query."',
  '      word "有關…"',
  '        description "Chinese coverb (pinyin youguan, concerning, traditional), stripped from the front of a query."',
  '  meaning "query_trailing_noise"',
  '    gloss "filler that follows the real search topic and must be trimmed off its tail — trailing source phrases, qualifiers and stray search verbs that are not part of the topic ( online, on the internet, в интернете, के बारे में, 的信息). As a trailing-noise marker each surface is a suffix surface whose literal after the slot is stripped from the end of an extracted query; the recogniser strips repeatedly until the query stops changing, so the declared order does not matter. The Latin and Cyrillic forms keep their leading space so they peel off a whole trailing word, while the Han forms are bare."',
  '    wiktionary "online"',
  '    defined_by "concept"',
  '    role "web_search_query_trailing_noise"',
  '    lexeme "en"',
  '      word "… online"',
  '        description "English trailing adverb (online), stripped from the end of a query."',
  '      word "… on the internet"',
  '        description "English trailing phrase (on the internet), stripped from the end of a query."',
  '      word "… on the web"',
  '        description "English trailing phrase (on the web), stripped from the end of a query."',
  '      word "… on wikipedia"',
  '        description "English trailing phrase (on wikipedia), stripped from the end of a query."',
  '      word "… in wikipedia"',
  '        description "English trailing phrase (in wikipedia), stripped from the end of a query."',
  '      word "… from wikipedia"',
  '        description "English trailing phrase (from wikipedia), stripped from the end of a query."',
  '      word "… information"',
  '        description "English trailing noun (information), stripped from the end of a query."',
  '      word "… info"',
  '        description "English trailing noun (clipped info), stripped from the end of a query."',
  '      word "… details"',
  '        description "English trailing noun (details), stripped from the end of a query."',
  '      word "… data"',
  '        description "English trailing noun (data), stripped from the end of a query."',
  '      word "… material"',
  '        description "English trailing noun (material), stripped from the end of a query."',
  '      word "… materials"',
  '        description "English trailing noun (materials), stripped from the end of a query."',
  '      word "… resources"',
  '        description "English trailing noun (resources), stripped from the end of a query."',
  '      word "… sources"',
  '        description "English trailing noun (sources), stripped from the end of a query."',
  '      word "… articles"',
  '        description "English trailing noun (articles), stripped from the end of a query."',
  '      word "… facts"',
  '        description "English trailing noun (facts), stripped from the end of a query."',
  '    lexeme "ru"',
  '      word "… в интернете"',
  '        description "Russian trailing phrase (romanized v internete, on the internet), stripped from the end of a query."',
  '      word "… онлайн"',
  '        description "Russian trailing adverb (romanized onlain, online), stripped from the end of a query."',
  '      word "… в сети"',
  '        description "Russian trailing phrase (romanized v seti, on the net), stripped from the end of a query."',
  '      word "… в википедии"',
  '        description "Russian trailing phrase (romanized v wikipedii, in Wikipedia), stripped from the end of a query."',
  '      word "… википедии"',
  '        description "Russian trailing noun (romanized wikipedii, of Wikipedia), stripped from the end of a query."',
  '      word "… информация"',
  '        description "Russian trailing noun (romanized informaciya, information), stripped from the end of a query."',
  '      word "… сведения"',
  '        description "Russian trailing noun (romanized svedeniya, information), stripped from the end of a query."',
  '      word "… материалы"',
  '        description "Russian trailing noun (romanized materialy, materials), stripped from the end of a query."',
  '      word "… данные"',
  '        description "Russian trailing noun (romanized dannye, data), stripped from the end of a query."',
  '    lexeme "hi"',
  '      word "… के बारे में"',
  '        description "Hindi trailing postposition (romanized ke baare mein, about), stripped from the end of a query."',
  '      word "… के विषय में"',
  '        description "Hindi trailing postposition (romanized ke vishay mein, on the subject of), stripped from the end of a query."',
  '      word "… से संबंधित"',
  '        description "Hindi trailing postposition (romanized se sambandhit, related to), stripped from the end of a query."',
  '      word "… पर"',
  '        description "Hindi trailing postposition (romanized par, on), stripped from the end of a query."',
  '      word "… की जानकारी"',
  '        description "Hindi trailing phrase (romanized ki jankari, information of), stripped from the end of a query."',
  '      word "… की सूचना"',
  '        description "Hindi trailing phrase (romanized ki suchna, notice of), stripped from the end of a query."',
  '      word "… जानकारी"',
  '        description "Hindi trailing noun (romanized jankari, information), stripped from the end of a query."',
  '      word "… सूचना"',
  '        description "Hindi trailing noun (romanized suchna, information), stripped from the end of a query."',
  '      word "… विवरण"',
  '        description "Hindi trailing noun (romanized vivaran, details), stripped from the end of a query."',
  '      word "… सामग्री"',
  '        description "Hindi trailing noun (romanized samagri, material), stripped from the end of a query."',
  '      word "… स्रोत"',
  '        description "Hindi trailing noun (romanized srot, source), stripped from the end of a query."',
  '      word "… विकिपीडिया में"',
  '        description "Hindi trailing phrase (romanized vikipidiya mein, in Wikipedia), stripped from the end of a query."',
  '      word "… ऑनलाइन"',
  '        description "Hindi trailing adverb (romanized onlain, online), stripped from the end of a query."',
  '      word "… इंटरनेट पर"',
  '        description "Hindi trailing phrase (romanized internet par, on the internet), stripped from the end of a query."',
  '      word "… खोजो"',
  '        description "Hindi trailing imperative (romanized khojo, search), stripped from the end of a query."',
  '      word "… खोजें"',
  '        description "Hindi trailing imperative (romanized khojen, search), stripped from the end of a query."',
  '      word "… खोजिए"',
  '        description "Hindi trailing imperative (romanized khojie, search), stripped from the end of a query."',
  '      word "… ढूंढो"',
  '        description "Hindi trailing imperative (romanized dhundho, find), stripped from the end of a query."',
  '      word "… ढूँढो"',
  '        description "Hindi trailing imperative (romanized dhundho, nasalised), stripped from the end of a query."',
  '      word "… ढूंढें"',
  '        description "Hindi trailing imperative (romanized dhundhen, find), stripped from the end of a query."',
  '      word "… ढूँढें"',
  '        description "Hindi trailing imperative (romanized dhundhen, nasalised), stripped from the end of a query."',
  '    lexeme "zh"',
  '      word "…的信息"',
  '        description "Chinese trailing phrase (pinyin de xinxi, information of), stripped from the end of a query."',
  '      word "…的資料"',
  '        description "Chinese trailing phrase (pinyin de ziliao, data of, traditional), stripped from the end of a query."',
  '      word "…的资料"',
  '        description "Chinese trailing phrase (pinyin de ziliao, data of), stripped from the end of a query."',
  '      word "…信息"',
  '        description "Chinese trailing noun (pinyin xinxi, information), stripped from the end of a query."',
  '      word "…資料"',
  '        description "Chinese trailing noun (pinyin ziliao, data, traditional), stripped from the end of a query."',
  '      word "…资料"',
  '        description "Chinese trailing noun (pinyin ziliao, data), stripped from the end of a query."',
  '      word "…内容"',
  '        description "Chinese trailing noun (pinyin neirong, content), stripped from the end of a query."',
  '      word "…文章"',
  '        description "Chinese trailing noun (pinyin wenzhang, article), stripped from the end of a query."',
  '      word "…在维基百科上"',
  '        description "Chinese trailing phrase (pinyin zai weiji baike shang, on Wikipedia), stripped from the end of a query."',
  '      word "…在維基百科上"',
  '        description "Chinese trailing phrase (pinyin zai weiji baike shang, on Wikipedia, traditional), stripped from the end of a query."',
  '      word "…维基百科"',
  '        description "Chinese trailing noun (pinyin weiji baike, Wikipedia), stripped from the end of a query."',
  '      word "…維基百科"',
  '        description "Chinese trailing noun (pinyin weiji baike, Wikipedia, traditional), stripped from the end of a query."',
  '      word "…网上"',
  '        description "Chinese trailing phrase (pinyin wangshang, on the web), stripped from the end of a query."',
  '      word "…網上"',
  '        description "Chinese trailing phrase (pinyin wangshang, on the web, traditional), stripped from the end of a query."',
  '      word "…在线"',
  '        description "Chinese trailing adverb (pinyin zaixian, online), stripped from the end of a query."',
  '      word "…在線"',
  '        description "Chinese trailing adverb (pinyin zaixian, online, traditional), stripped from the end of a query."',
  '      word "…搜索"',
  '        description "Chinese trailing verb (pinyin sousuo, search), stripped from the end of a query."',
  '      word "…查找"',
  '        description "Chinese trailing verb (pinyin chazhao, look up), stripped from the end of a query."',
  '      word "…查一下"',
  '        description "Chinese trailing phrase (pinyin cha yixia, have a look), stripped from the end of a query."',
  '      word "…搜一下"',
  '        description "Chinese trailing phrase (pinyin sou yixia, have a search), stripped from the end of a query."',
  "meanings",
  '  meaning "research_question_opener"',
  '    gloss "the interrogative opener that turns a bare question into an implicit research request — what is the X, who are the X, какой самый X, 什么是 X. It is the front trigger of the implicit-research path: when a prompt begins with one of these and also carries a superlative modifier or both an evidence and an evaluation domain, the opener is stripped and the remainder taken as the research query. Each surface is a prefix surface ending with the slot; the literal before the slot is what starts_with matches and strip removes. The longer, more specific openers are declared before the shorter ones (what is the before what is before what) so the most specific opener wins. English carries the original openers verbatim; Russian, Hindi and Chinese add their natural question heads so the concept is complete in every supported language."',
  '    wiktionary "what"',
  '    defined_by "inquiry"',
  '    role "research_question_opener"',
  '    lexeme "en"',
  '      word "what is the …"',
  '        description "English opener (what is the); strips to leave the questioned entity as the query."',
  '      word "what is a …"',
  '        description "English opener (what is a); strips to leave the questioned entity."',
  '      word "what is an …"',
  '        description "English opener (what is an); strips to leave the questioned entity."',
  '      word "what is …"',
  '        description "English opener (what is); broader than what is the, so declared after it."',
  '      word "what are the …"',
  '        description "English opener (what are the); plural form, strips to leave the questioned entities."',
  '      word "what are …"',
  '        description "English opener (what are); broader plural, declared after what are the."',
  '      word "what s the …"',
  '        description "English opener (what s the, the apostrophe-stripped what is the); strips to leave the entity."',
  '      word "what s a …"',
  '        description "English opener (what s a, apostrophe-stripped what is a); strips to leave the entity."',
  '      word "what s an …"',
  '        description "English opener (what s an, apostrophe-stripped what is an); strips to leave the entity."',
  '      word "what s …"',
  '        description "English opener (what s, apostrophe-stripped what is); broader, declared after the longer variants."',
  '      word "which is the …"',
  '        description "English opener (which is the); strips to leave the questioned choice."',
  '      word "which is a …"',
  '        description "English opener (which is a); strips to leave the questioned choice."',
  '      word "which is an …"',
  '        description "English opener (which is an); strips to leave the questioned choice."',
  '      word "which are the …"',
  '        description "English opener (which are the); plural, strips to leave the questioned choices."',
  '      word "which are …"',
  '        description "English opener (which are); broader plural, declared after which are the."',
  '      word "which …"',
  '        description "English opener (which); broadest of the which family, declared last."',
  '      word "who is the …"',
  '        description "English opener (who is the); strips to leave the questioned person."',
  '      word "who are the …"',
  '        description "English opener (who are the); plural, strips to leave the questioned people."',
  '      word "who …"',
  '        description "English opener (who); broadest of the who family, declared last."',
  '      word "where is the …"',
  '        description "English opener (where is the); strips to leave the questioned place."',
  '      word "where are the …"',
  '        description "English opener (where are the); plural, strips to leave the questioned places."',
  '      word "where …"',
  '        description "English opener (where); broadest of the where family, declared last."',
  '      word "when is the …"',
  '        description "English opener (when is the); strips to leave the questioned time."',
  '      word "when are the …"',
  '        description "English opener (when are the); plural, strips to leave the questioned times."',
  '      word "when …"',
  '        description "English opener (when); broadest of the when family, declared last."',
  '      word "why is the …"',
  '        description "English opener (why is the); strips to leave the questioned reason."',
  '      word "why are the …"',
  '        description "English opener (why are the); plural, strips to leave the questioned reasons."',
  '      word "why …"',
  '        description "English opener (why); broadest of the why family, declared last."',
  '      word "how is the …"',
  '        description "English opener (how is the); strips to leave the questioned manner."',
  '      word "how are the …"',
  '        description "English opener (how are the); plural, strips to leave the questioned manners."',
  '      word "how …"',
  '        description "English opener (how); broadest of the how family, declared last."',
  '      word "can you tell me …"',
  '        description "English polite opener (can you tell me); strips to leave the asked-about topic."',
  '      word "could you tell me …"',
  '        description "English polite opener (could you tell me); strips to leave the asked-about topic."',
  '      word "do you know …"',
  '        description "English polite opener (do you know); strips to leave the asked-about topic."',
  '    lexeme "ru"',
  '      word "что такое …"',
  '        description "Russian opener (romanized chto takoe, what is); strips to leave the questioned entity."',
  '      word "что за …"',
  '        description "Russian opener (romanized chto za, what kind of); strips to leave the questioned entity."',
  '      word "какие …"',
  '        description "Russian opener (romanized kakie, which/what plural); strips to leave the questioned entities."',
  '      word "какой …"',
  '        description "Russian opener (romanized kakoy, which masculine); strips to leave the questioned entity."',
  '      word "какая …"',
  '        description "Russian opener (romanized kakaya, which feminine); strips to leave the questioned entity."',
  '      word "какое …"',
  '        description "Russian opener (romanized kakoe, which neuter); strips to leave the questioned entity."',
  '      word "кто такой …"',
  '        description "Russian opener (romanized kto takoy, who is masculine); strips to leave the questioned person."',
  '      word "кто такая …"',
  '        description "Russian opener (romanized kto takaya, who is feminine); strips to leave the questioned person."',
  '      word "кто …"',
  '        description "Russian opener (romanized kto, who); broader, declared after the kto takoy variants."',
  '      word "где …"',
  '        description "Russian opener (romanized gde, where); strips to leave the questioned place."',
  '      word "когда …"',
  '        description "Russian opener (romanized kogda, when); strips to leave the questioned time."',
  '      word "почему …"',
  '        description "Russian opener (romanized pochemu, why); strips to leave the questioned reason."',
  '      word "зачем …"',
  '        description "Russian opener (romanized zachem, what for); strips to leave the questioned purpose."',
  '      word "как …"',
  '        description "Russian opener (romanized kak, how); strips to leave the questioned manner."',
  '      word "расскажи мне …"',
  '        description "Russian polite opener (romanized rasskazhi mne, tell me); strips to leave the asked-about topic."',
  '      word "ты знаешь …"',
  '        description "Russian polite opener (romanized ty znaesh, do you know); strips to leave the asked-about topic."',
  '    lexeme "hi"',
  '      word "क्या होता है …"',
  '        description "Hindi opener (romanized kya hota hai, what is); strips to leave the questioned entity."',
  '      word "क्या है …"',
  '        description "Hindi opener (romanized kya hai, what is); broader, declared after kya hota hai."',
  '      word "कौन है …"',
  '        description "Hindi opener (romanized kaun hai, who is); strips to leave the questioned person."',
  '      word "कौन …"',
  '        description "Hindi opener (romanized kaun, who); broader, declared after kaun hai."',
  '      word "कहाँ है …"',
  '        description "Hindi opener (romanized kahan hai, where is); strips to leave the questioned place."',
  '      word "कहाँ …"',
  '        description "Hindi opener (romanized kahan, where); broader, declared after kahan hai."',
  '      word "कब …"',
  '        description "Hindi opener (romanized kab, when); strips to leave the questioned time."',
  '      word "क्यों …"',
  '        description "Hindi opener (romanized kyon, why); strips to leave the questioned reason."',
  '      word "कैसे …"',
  '        description "Hindi opener (romanized kaise, how); strips to leave the questioned manner."',
  '      word "बताओ …"',
  '        description "Hindi polite opener (romanized batao, tell me); strips to leave the asked-about topic."',
  '    lexeme "zh"',
  '      word "什么是…"',
  '        description "Chinese opener (pinyin shenme shi, what is); strips to leave the questioned entity."',
  '      word "谁是…"',
  '        description "Chinese opener (pinyin shei shi, who is); strips to leave the questioned person."',
  '      word "哪里是…"',
  '        description "Chinese opener (pinyin nali shi, where is); strips to leave the questioned place."',
  '      word "哪里…"',
  '        description "Chinese opener (pinyin nali, where); broader, declared after nali shi."',
  '      word "哪个…"',
  '        description "Chinese opener (pinyin nage, which); strips to leave the questioned choice."',
  '      word "什么时候…"',
  '        description "Chinese opener (pinyin shenme shihou, when); strips to leave the questioned time."',
  '      word "为什么…"',
  '        description "Chinese opener (pinyin weishenme, why); strips to leave the questioned reason."',
  '      word "怎么…"',
  '        description "Chinese opener (pinyin zenme, how); strips to leave the questioned manner."',
  '      word "如何…"',
  '        description "Chinese opener (pinyin ruhe, how, formal); strips to leave the questioned manner."',
  '      word "告诉我…"',
  '        description "Chinese polite opener (pinyin gaosu wo, tell me); strips to leave the asked-about topic."',
  '      word "你知道…"',
  '        description "Chinese polite opener (pinyin ni zhidao, do you know); strips to leave the asked-about topic."',
  '  meaning "research_superlative_modifier"',
  '    gloss "a superlative or recommendation qualifier whose presence marks a question as a research request — the most X, the best X, the recommended X. As a modifier each surface is a whole-token marker: the space-delimited languages keep their surrounding spaces so the match lands on a whole word inside the padded prompt, while the Han forms are bare and match as a substring. Finding any one modifier (together with a research opener) is enough to route the prompt down the implicit-research path. English carries the original modifiers verbatim; Russian, Hindi and Chinese add their natural superlatives so the concept is complete in every supported language."',
  '    wiktionary "most"',
  '    defined_by "property"',
  '    role "research_superlative_modifier"',
  '    lexeme "en"',
  '      word " most "',
  '        description "English superlative degree (most); whole-token modifier marking a research question."',
  '      word " best "',
  '        description "English superlative (best); whole-token modifier marking a research question."',
  '      word " top "',
  '        description "English superlative (top); whole-token modifier marking a research question."',
  '      word " leading "',
  '        description "English qualifier (leading); whole-token modifier marking a research question."',
  '      word " standard "',
  '        description "English qualifier (standard); whole-token modifier marking a research question."',
  '      word " de facto "',
  '        description "English qualifier (de facto); whole-token modifier marking a research question."',
  '      word " widely used "',
  '        description "English qualifier (widely used); whole-token modifier marking a research question."',
  '      word " commonly used "',
  '        description "English qualifier (commonly used); whole-token modifier marking a research question."',
  '      word " popular "',
  '        description "English qualifier (popular); whole-token modifier marking a research question."',
  '      word " recommended "',
  '        description "English qualifier (recommended); whole-token modifier marking a research question."',
  '      word " current "',
  '        description "English qualifier (current); whole-token modifier marking a research question."',
  '      word " latest "',
  '        description "English qualifier (latest); whole-token modifier marking a research question."',
  '      word " recent "',
  '        description "English qualifier (recent); whole-token modifier marking a research question."',
  '      word " state of the art "',
  '        description "English qualifier (state of the art); whole-token modifier marking a research question."',
  '      word " sota "',
  '        description "English qualifier (sota, the state-of-the-art acronym); whole-token modifier marking a research question."',
  '      word " should i use "',
  '        description "English recommendation frame (should i use); whole-token modifier marking a research question."',
  '      word " should we use "',
  '        description "English recommendation frame (should we use); whole-token modifier marking a research question."',
  '      word " should be used "',
  '        description "English recommendation frame (should be used); whole-token modifier marking a research question."',
  '    lexeme "ru"',
  '      word " лучший "',
  '        description "Russian superlative (romanized luchshiy, best masculine); whole-token modifier marking a research question."',
  '      word " лучшая "',
  '        description "Russian superlative (romanized luchshaya, best feminine); whole-token modifier marking a research question."',
  '      word " лучшие "',
  '        description "Russian superlative (romanized luchshie, best plural); whole-token modifier marking a research question."',
  '      word " самый "',
  '        description "Russian intensifier (romanized samyy, the most); whole-token modifier marking a research question."',
  '      word " самые "',
  '        description "Russian intensifier (romanized samye, the most plural); whole-token modifier marking a research question."',
  '      word " топ "',
  '        description "Russian qualifier (romanized top, top); whole-token modifier marking a research question."',
  '      word " ведущий "',
  '        description "Russian qualifier (romanized vedushchiy, leading); whole-token modifier marking a research question."',
  '      word " популярный "',
  '        description "Russian qualifier (romanized populyarnyy, popular); whole-token modifier marking a research question."',
  '      word " стандартный "',
  '        description "Russian qualifier (romanized standartnyy, standard); whole-token modifier marking a research question."',
  '      word " рекомендуемый "',
  '        description "Russian qualifier (romanized rekomenduemyy, recommended); whole-token modifier marking a research question."',
  '      word " текущий "',
  '        description "Russian qualifier (romanized tekushchiy, current); whole-token modifier marking a research question."',
  '      word " последний "',
  '        description "Russian qualifier (romanized posledniy, latest); whole-token modifier marking a research question."',
  '      word " недавний "',
  '        description "Russian qualifier (romanized nedavniy, recent); whole-token modifier marking a research question."',
  '    lexeme "hi"',
  '      word " सबसे अच्छा "',
  '        description "Hindi superlative (romanized sabse achchha, the best); whole-token modifier marking a research question."',
  '      word " सर्वश्रेष्ठ "',
  '        description "Hindi superlative (romanized sarvashreshth, the best); whole-token modifier marking a research question."',
  '      word " शीर्ष "',
  '        description "Hindi qualifier (romanized shirsh, top); whole-token modifier marking a research question."',
  '      word " प्रमुख "',
  '        description "Hindi qualifier (romanized pramukh, leading); whole-token modifier marking a research question."',
  '      word " मानक "',
  '        description "Hindi qualifier (romanized manak, standard); whole-token modifier marking a research question."',
  '      word " लोकप्रिय "',
  '        description "Hindi qualifier (romanized lokpriy, popular); whole-token modifier marking a research question."',
  '      word " अनुशंसित "',
  '        description "Hindi qualifier (romanized anushansit, recommended); whole-token modifier marking a research question."',
  '      word " वर्तमान "',
  '        description "Hindi qualifier (romanized vartaman, current); whole-token modifier marking a research question."',
  '      word " नवीनतम "',
  '        description "Hindi qualifier (romanized navintam, latest); whole-token modifier marking a research question."',
  '      word " हाल ही का "',
  '        description "Hindi qualifier (romanized haal hi ka, recent); whole-token modifier marking a research question."',
  '    lexeme "zh"',
  '      word "最好"',
  '        description "Chinese superlative (pinyin zui hao, best); substring modifier marking a research question."',
  '      word "最佳"',
  '        description "Chinese superlative (pinyin zui jia, best/optimal); substring modifier marking a research question."',
  '      word "顶级"',
  '        description "Chinese qualifier (pinyin dingji, top-tier); substring modifier marking a research question."',
  '      word "领先"',
  '        description "Chinese qualifier (pinyin lingxian, leading); substring modifier marking a research question."',
  '      word "标准"',
  '        description "Chinese qualifier (pinyin biaozhun, standard); substring modifier marking a research question."',
  '      word "流行"',
  '        description "Chinese qualifier (pinyin liuxing, popular); substring modifier marking a research question."',
  '      word "推荐"',
  '        description "Chinese qualifier (pinyin tuijian, recommended); substring modifier marking a research question."',
  '      word "当前"',
  '        description "Chinese qualifier (pinyin dangqian, current); substring modifier marking a research question."',
  '      word "最新"',
  '        description "Chinese qualifier (pinyin zui xin, latest); substring modifier marking a research question."',
  '      word "最近"',
  '        description "Chinese qualifier (pinyin zui jin, recent); substring modifier marking a research question."',
  '  meaning "research_evidence_domain"',
  '    gloss "an evidence-bearing domain noun whose presence helps mark a question as a research request — a dataset, a benchmark, a paper, a study. Evidence terms count toward the implicit-research gate only in concert with an evaluation term (the two together stand in for a superlative modifier). As a domain term each surface is a whole-token marker: the space-delimited languages keep their surrounding spaces, while the Han forms are bare and match as a substring. English carries the original evidence terms verbatim; Russian, Hindi and Chinese add their natural equivalents so the concept is complete in every supported language."',
  '    wiktionary "dataset"',
  '    defined_by "entity"',
  '    role "research_evidence_domain"',
  '    lexeme "en"',
  '      word " dataset "',
  '        description "English evidence noun (dataset, singular); whole-token domain term for research routing."',
  '      word " datasets "',
  '        description "English evidence noun (datasets, plural); whole-token domain term for research routing."',
  '      word " benchmark "',
  '        description "English evidence noun (benchmark, singular); whole-token domain term for research routing."',
  '      word " benchmarks "',
  '        description "English evidence noun (benchmarks, plural); whole-token domain term for research routing."',
  '      word " corpus "',
  '        description "English evidence noun (corpus, singular); whole-token domain term for research routing."',
  '      word " corpora "',
  '        description "English evidence noun (corpora, plural); whole-token domain term for research routing."',
  '      word " metric "',
  '        description "English evidence noun (metric, singular); whole-token domain term for research routing."',
  '      word " metrics "',
  '        description "English evidence noun (metrics, plural); whole-token domain term for research routing."',
  '      word " framework "',
  '        description "English evidence noun (framework, singular); whole-token domain term for research routing."',
  '      word " frameworks "',
  '        description "English evidence noun (frameworks, plural); whole-token domain term for research routing."',
  '      word " paper "',
  '        description "English evidence noun (paper, singular); whole-token domain term for research routing."',
  '      word " papers "',
  '        description "English evidence noun (papers, plural); whole-token domain term for research routing."',
  '      word " study "',
  '        description "English evidence noun (study, singular); whole-token domain term for research routing."',
  '      word " studies "',
  '        description "English evidence noun (studies, plural); whole-token domain term for research routing."',
  '    lexeme "ru"',
  '      word " датасет "',
  '        description "Russian evidence noun (romanized datatset, dataset); whole-token domain term for research routing."',
  '      word " набор данных "',
  '        description "Russian evidence phrase (romanized nabor dannyh, data set); whole-token domain term for research routing."',
  '      word " бенчмарк "',
  '        description "Russian evidence noun (romanized benchmark, benchmark); whole-token domain term for research routing."',
  '      word " корпус "',
  '        description "Russian evidence noun (romanized korpus, corpus); whole-token domain term for research routing."',
  '      word " метрика "',
  '        description "Russian evidence noun (romanized metrika, metric); whole-token domain term for research routing."',
  '      word " фреймворк "',
  '        description "Russian evidence noun (romanized freymvork, framework); whole-token domain term for research routing."',
  '      word " статья "',
  '        description "Russian evidence noun (romanized statya, paper/article); whole-token domain term for research routing."',
  '      word " исследование "',
  '        description "Russian evidence noun (romanized issledovanie, study); whole-token domain term for research routing."',
  '    lexeme "hi"',
  '      word " डेटासेट "',
  '        description "Hindi evidence noun (romanized detaset, dataset); whole-token domain term for research routing."',
  '      word " बेंचमार्क "',
  '        description "Hindi evidence noun (romanized benchmark, benchmark); whole-token domain term for research routing."',
  '      word " कॉर्पस "',
  '        description "Hindi evidence noun (romanized korpas, corpus); whole-token domain term for research routing."',
  '      word " मीट्रिक "',
  '        description "Hindi evidence noun (romanized mitrik, metric); whole-token domain term for research routing."',
  '      word " फ्रेमवर्क "',
  '        description "Hindi evidence noun (romanized phremvark, framework); whole-token domain term for research routing."',
  '      word " पेपर "',
  '        description "Hindi evidence noun (romanized pepar, paper); whole-token domain term for research routing."',
  '      word " अध्ययन "',
  '        description "Hindi evidence noun (romanized adhyayan, study); whole-token domain term for research routing."',
  '    lexeme "zh"',
  '      word "数据集"',
  '        description "Chinese evidence noun (pinyin shujuji, dataset); substring domain term for research routing."',
  '      word "基准"',
  '        description "Chinese evidence noun (pinyin jizhun, benchmark); substring domain term for research routing."',
  '      word "语料库"',
  '        description "Chinese evidence noun (pinyin yuliaoku, corpus); substring domain term for research routing."',
  '      word "指标"',
  '        description "Chinese evidence noun (pinyin zhibiao, metric); substring domain term for research routing."',
  '      word "框架"',
  '        description "Chinese evidence noun (pinyin kuangjia, framework); substring domain term for research routing."',
  '      word "论文"',
  '        description "Chinese evidence noun (pinyin lunwen, paper); substring domain term for research routing."',
  '      word "研究"',
  '        description "Chinese evidence noun (pinyin yanjiu, study); substring domain term for research routing."',
  '  meaning "research_evaluation_domain"',
  '    gloss "an evaluation domain term whose presence helps mark a question as a research request — evaluation, validation, quality, comparison. Evaluation terms count toward the implicit-research gate only in concert with an evidence term (the two together stand in for a superlative modifier). As a domain term each surface is a whole-token marker: the space-delimited languages keep their surrounding spaces, while the Han forms are bare and match as a substring. English carries the original evaluation terms verbatim; Russian, Hindi and Chinese add their natural equivalents so the concept is complete in every supported language."',
  '    wiktionary "evaluation"',
  '    defined_by "concept"',
  '    role "research_evaluation_domain"',
  '    lexeme "en"',
  '      word " evaluation "',
  '        description "English evaluation noun (evaluation); whole-token domain term for research routing."',
  '      word " evaluate "',
  '        description "English evaluation verb (evaluate); whole-token domain term for research routing."',
  '      word " validation "',
  '        description "English evaluation noun (validation); whole-token domain term for research routing."',
  '      word " validate "',
  '        description "English evaluation verb (validate); whole-token domain term for research routing."',
  '      word " quality "',
  '        description "English evaluation noun (quality); whole-token domain term for research routing."',
  '      word " translation "',
  '        description "English evaluation noun (translation); whole-token domain term for research routing."',
  '      word " compare "',
  '        description "English evaluation verb (compare); whole-token domain term for research routing."',
  '      word " comparison "',
  '        description "English evaluation noun (comparison); whole-token domain term for research routing."',
  '    lexeme "ru"',
  '      word " оценка "',
  '        description "Russian evaluation noun (romanized otsenka, evaluation); whole-token domain term for research routing."',
  '      word " оценить "',
  '        description "Russian evaluation verb (romanized otsenit, to evaluate); whole-token domain term for research routing."',
  '      word " валидация "',
  '        description "Russian evaluation noun (romanized validatsiya, validation); whole-token domain term for research routing."',
  '      word " проверка "',
  '        description "Russian evaluation noun (romanized proverka, verification); whole-token domain term for research routing."',
  '      word " качество "',
  '        description "Russian evaluation noun (romanized kachestvo, quality); whole-token domain term for research routing."',
  '      word " перевод "',
  '        description "Russian evaluation noun (romanized perevod, translation); whole-token domain term for research routing."',
  '      word " сравнить "',
  '        description "Russian evaluation verb (romanized sravnit, to compare); whole-token domain term for research routing."',
  '      word " сравнение "',
  '        description "Russian evaluation noun (romanized sravnenie, comparison); whole-token domain term for research routing."',
  '    lexeme "hi"',
  '      word " मूल्यांकन "',
  '        description "Hindi evaluation noun (romanized mulyankan, evaluation); whole-token domain term for research routing."',
  '      word " सत्यापन "',
  '        description "Hindi evaluation noun (romanized satyapan, validation); whole-token domain term for research routing."',
  '      word " गुणवत्ता "',
  '        description "Hindi evaluation noun (romanized gunavatta, quality); whole-token domain term for research routing."',
  '      word " अनुवाद "',
  '        description "Hindi evaluation noun (romanized anuvad, translation); whole-token domain term for research routing."',
  '      word " तुलना "',
  '        description "Hindi evaluation noun (romanized tulna, comparison); whole-token domain term for research routing."',
  '    lexeme "zh"',
  '      word "评估"',
  '        description "Chinese evaluation noun (pinyin pinggu, evaluation); substring domain term for research routing."',
  '      word "评价"',
  '        description "Chinese evaluation noun (pinyin pingjia, appraisal); substring domain term for research routing."',
  '      word "验证"',
  '        description "Chinese evaluation noun (pinyin yanzheng, validation); substring domain term for research routing."',
  '      word "质量"',
  '        description "Chinese evaluation noun (pinyin zhiliang, quality); substring domain term for research routing."',
  '      word "翻译"',
  '        description "Chinese evaluation noun (pinyin fanyi, translation); substring domain term for research routing."',
  '      word "比较"',
  '        description "Chinese evaluation verb (pinyin bijiao, compare); substring domain term for research routing."',
  '  meaning "enumeration_request_opener"',
  '    gloss "the opener of an enumeration request — list all X, show me the X, перечисли всех X, 列出所有 X. It is the front trigger of the enumeration path: when a prompt begins with one of these and the remainder is at least three words long and carries a constraint marker, the opener is stripped and the remainder taken as the enumeration query. Each surface is a prefix surface; the literal before the slot is what strip removes, and it keeps its trailing separator (a space for the space-delimited languages, including the Han forms whose original surfaces carry a trailing space). This concept already spans all four supported languages."',
  '    wiktionary "list"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "enumeration_request_opener"',
  '    lexeme "en"',
  '      word "list all …"',
  '        description "English enumeration opener (list all); strips to leave the enumerated class."',
  '      word "list every …"',
  '        description "English enumeration opener (list every); strips to leave the enumerated class."',
  '      word "list the …"',
  '        description "English enumeration opener (list the); strips to leave the enumerated class."',
  '      word "show all …"',
  '        description "English enumeration opener (show all); strips to leave the enumerated class."',
  '      word "show me all …"',
  '        description "English enumeration opener (show me all); strips to leave the enumerated class."',
  '      word "show me the …"',
  '        description "English enumeration opener (show me the); strips to leave the enumerated class."',
  '      word "give me all …"',
  '        description "English enumeration opener (give me all); strips to leave the enumerated class."',
  '      word "name all …"',
  '        description "English enumeration opener (name all); strips to leave the enumerated class."',
  '      word "enumerate all …"',
  '        description "English enumeration opener (enumerate all); strips to leave the enumerated class."',
  '    lexeme "ru"',
  '      word "перечисли всех …"',
  '        description "Russian enumeration opener (romanized perechisli vseh, list all animate); strips to leave the enumerated class."',
  '      word "перечисли все …"',
  '        description "Russian enumeration opener (romanized perechisli vse, list all inanimate); strips to leave the enumerated class."',
  '      word "список всех …"',
  '        description "Russian enumeration opener (romanized spisok vseh, a list of all); strips to leave the enumerated class."',
  '      word "назови всех …"',
  '        description "Russian enumeration opener (romanized nazovi vseh, name all); strips to leave the enumerated class."',
  '    lexeme "hi"',
  '      word "सभी …"',
  '        description "Hindi enumeration opener (romanized sabhi, all); strips to leave the enumerated class."',
  '      word "हर …"',
  '        description "Hindi enumeration opener (romanized har, every); strips to leave the enumerated class."',
  '    lexeme "zh"',
  '      word "列出所有 …"',
  '        description "Chinese enumeration opener (pinyin liechu suoyou, list all), keeping the original trailing space; strips to leave the enumerated class."',
  '      word "列出全部 …"',
  '        description "Chinese enumeration opener (pinyin liechu quanbu, list every), keeping the original trailing space; strips to leave the enumerated class."',
  '      word "显示所有 …"',
  '        description "Chinese enumeration opener (pinyin xianshi suoyou, show all), keeping the original trailing space; strips to leave the enumerated class."',
  '      word "枚举所有 …"',
  '        description "Chinese enumeration opener (pinyin meiju suoyou, enumerate all), keeping the original trailing space; strips to leave the enumerated class."',
  '  meaning "enumeration_constraint"',
  '    gloss "a constraint connective that filters an enumerated class — list all X with Y, that Y, у которых Y, 具有 Y. Its presence (together with a query of at least three words) confirms that a stripped enumeration prompt is a real enumeration request rather than a stray fragment. As a constraint each surface is a whole-token marker keeping its surrounding spaces, including the Han forms whose original surfaces are space-wrapped. This concept already spans all four supported languages."',
  '    wiktionary "with"',
  '    defined_by "relation"',
  '    role "enumeration_constraint"',
  '    lexeme "en"',
  '      word " with "',
  '        description "English constraint connective (with); whole-token marker confirming an enumeration query."',
  '      word " that "',
  '        description "English constraint connective (that); whole-token marker confirming an enumeration query."',
  '      word " who "',
  '        description "English constraint connective (who); whole-token marker confirming an enumeration query."',
  '      word " whose "',
  '        description "English constraint connective (whose); whole-token marker confirming an enumeration query."',
  '      word " where "',
  '        description "English constraint connective (where); whole-token marker confirming an enumeration query."',
  '      word " which "',
  '        description "English constraint connective (which); whole-token marker confirming an enumeration query."',
  '      word " having "',
  '        description "English constraint connective (having); whole-token marker confirming an enumeration query."',
  '      word " have "',
  '        description "English constraint connective (have); whole-token marker confirming an enumeration query."',
  '      word " has "',
  '        description "English constraint connective (has); whole-token marker confirming an enumeration query."',
  '      word " featuring "',
  '        description "English constraint connective (featuring); whole-token marker confirming an enumeration query."',
  '      word " capable of "',
  '        description "English constraint connective (capable of); whole-token marker confirming an enumeration query."',
  '      word " can "',
  '        description "English constraint connective (can); whole-token marker confirming an enumeration query."',
  '      word " for "',
  '        description "English constraint connective (for); whole-token marker confirming an enumeration query."',
  '      word " by "',
  '        description "English constraint connective (by); whole-token marker confirming an enumeration query."',
  '      word " in "',
  '        description "English constraint connective (in); whole-token marker confirming an enumeration query."',
  '    lexeme "ru"',
  '      word " с "',
  '        description "Russian constraint connective (romanized s, with); whole-token marker confirming an enumeration query."',
  '      word " у которых "',
  '        description "Russian constraint connective (romanized u kotoryh, which have); whole-token marker confirming an enumeration query."',
  '      word " которые "',
  '        description "Russian constraint connective (romanized kotorye, which); whole-token marker confirming an enumeration query."',
  '      word " имеющие "',
  '        description "Russian constraint connective (romanized imeyushchie, having nominative); whole-token marker confirming an enumeration query."',
  '      word " имеющих "',
  '        description "Russian constraint connective (romanized imeyushchih, having genitive); whole-token marker confirming an enumeration query."',
  '      word " для "',
  '        description "Russian constraint connective (romanized dlya, for); whole-token marker confirming an enumeration query."',
  '      word " в "',
  '        description "Russian constraint connective (romanized v, in); whole-token marker confirming an enumeration query."',
  '    lexeme "hi"',
  '      word " जिनके "',
  '        description "Hindi constraint connective (romanized jinke, whose plural); whole-token marker confirming an enumeration query."',
  '      word " जिनमें "',
  '        description "Hindi constraint connective (romanized jinmein, in which plural); whole-token marker confirming an enumeration query."',
  '      word " जिसमें "',
  '        description "Hindi constraint connective (romanized jismein, in which singular); whole-token marker confirming an enumeration query."',
  '      word " वाले "',
  '        description "Hindi constraint connective (romanized vale, the ones with); whole-token marker confirming an enumeration query."',
  '      word " के साथ "',
  '        description "Hindi constraint connective (romanized ke saath, with); whole-token marker confirming an enumeration query."',
  '      word " के लिए "',
  '        description "Hindi constraint connective (romanized ke liye, for); whole-token marker confirming an enumeration query."',
  '      word " में "',
  '        description "Hindi constraint connective (romanized mein, in); whole-token marker confirming an enumeration query."',
  '    lexeme "zh"',
  '      word " 具有 "',
  '        description "Chinese constraint connective (pinyin juyou, possessing), kept space-wrapped as in the original; whole-token marker confirming an enumeration query."',
  '      word " 有 "',
  '        description "Chinese constraint connective (pinyin you, have), kept space-wrapped as in the original; whole-token marker confirming an enumeration query."',
  '      word " 带有 "',
  '        description "Chinese constraint connective (pinyin daiyou, featuring), kept space-wrapped as in the original; whole-token marker confirming an enumeration query."',
  '      word " 可以 "',
  '        description "Chinese constraint connective (pinyin keyi, can), kept space-wrapped as in the original; whole-token marker confirming an enumeration query."',
  '      word " 能 "',
  '        description "Chinese constraint connective (pinyin neng, able to), kept space-wrapped as in the original; whole-token marker confirming an enumeration query."',
  '      word " 在 "',
  '        description "Chinese constraint connective (pinyin zai, in), kept space-wrapped as in the original; whole-token marker confirming an enumeration query."',
  '      word " 用于 "',
  '        description "Chinese constraint connective (pinyin yongyu, used for), kept space-wrapped as in the original; whole-token marker confirming an enumeration query."',
  "meanings",
  '  meaning "followup_instruction_verb"',
  '    gloss "the predicate of a follow-up instruction clause appended after a search query — compare X, summarize Y, explain Z. When a prompt reads search for X and then compare their sizes, the trailing compare their sizes is a directive about what to do with the results, not part of the search topic, so the recogniser truncates the query at the start of that clause. A clause counts as a follow-up only when one of these verbs is immediately preceded by a boundary: sentence punctuation (a period, question mark, exclamation mark, semicolon or colon — universal across languages) or a clause continuation marker (and, then, and their translations). A bare verb with no boundary before it is treated as part of the topic and left alone. Each surface is a bare verb token matched on a word boundary, so it fires whether the clause ends the prompt or runs on. English carries the original follow-up verbs (compare, summarize, summarise, explain, describe) plus show and tell to match the browser worker; Russian, Hindi and Chinese add their natural imperative equivalents so follow-up clauses are recognised in every supported language."',
  '    wiktionary "compare"',
  '    defined_by "action"',
  '    role "followup_instruction_verb"',
  '    lexeme "en"',
  '      word "compare"',
  '        description "English follow-up verb (compare); after a boundary it opens a directive to contrast the results, so the query is cut before it."',
  '      word "summarize"',
  '        description "English follow-up verb (summarize, American spelling); after a boundary it opens a directive to condense the results, so the query is cut before it."',
  '      word "summarise"',
  '        description "English follow-up verb (summarise, British spelling); after a boundary it opens a directive to condense the results, so the query is cut before it."',
  '      word "explain"',
  '        description "English follow-up verb (explain); after a boundary it opens a directive to elaborate on the results, so the query is cut before it."',
  '      word "describe"',
  '        description "English follow-up verb (describe); after a boundary it opens a directive to characterise the results, so the query is cut before it."',
  '      word "show"',
  '        description "English follow-up verb (show), matched to mirror the browser worker; after a boundary it opens a directive to display the results, so the query is cut before it."',
  '      word "tell"',
  '        description "English follow-up verb (tell), matched to mirror the browser worker; after a boundary it opens a directive to report the results, so the query is cut before it."',
  '    lexeme "ru"',
  '      word "сравни"',
  '        description "Russian follow-up verb (romanized sravni, compare imperative); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "обобщи"',
  '        description "Russian follow-up verb (romanized obobshchi, summarize imperative); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "резюмируй"',
  '        description "Russian follow-up verb (romanized rezyumiruy, summarize imperative); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "объясни"',
  '        description "Russian follow-up verb (romanized obyasni, explain imperative); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "опиши"',
  '        description "Russian follow-up verb (romanized opishi, describe imperative); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "покажи"',
  '        description "Russian follow-up verb (romanized pokazhi, show imperative); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "расскажи"',
  '        description "Russian follow-up verb (romanized rasskazhi, tell imperative); after a boundary it opens a directive about the results, so the query is cut before it."',
  '    lexeme "hi"',
  '      word "तुलना करो"',
  '        description "Hindi follow-up verb (romanized tulna karo, compare); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "सारांश दो"',
  '        description "Hindi follow-up verb (romanized saaraansh do, give a summary); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "समझाओ"',
  '        description "Hindi follow-up verb (romanized samjhao, explain); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "वर्णन करो"',
  '        description "Hindi follow-up verb (romanized varnan karo, describe); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "दिखाओ"',
  '        description "Hindi follow-up verb (romanized dikhao, show); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "बताओ"',
  '        description "Hindi follow-up verb (romanized batao, tell); after a boundary it opens a directive about the results, so the query is cut before it."',
  '    lexeme "zh"',
  '      word "比较"',
  '        description "Chinese follow-up verb (pinyin bijiao, compare); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "总结"',
  '        description "Chinese follow-up verb (pinyin zongjie, summarize); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "概括"',
  '        description "Chinese follow-up verb (pinyin gaikuo, summarize/generalize); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "解释"',
  '        description "Chinese follow-up verb (pinyin jieshi, explain); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "描述"',
  '        description "Chinese follow-up verb (pinyin miaoshu, describe); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "显示"',
  '        description "Chinese follow-up verb (pinyin xianshi, show); after a boundary it opens a directive about the results, so the query is cut before it."',
  '      word "告诉"',
  '        description "Chinese follow-up verb (pinyin gaosu, tell); after a boundary it opens a directive about the results, so the query is cut before it."',
  '  meaning "clause_continuation_marker"',
  '    gloss "a conjunction or sequencing adverb that can introduce a new clause — and, then, and then. Together with sentence punctuation it forms the set of boundaries that mark where a follow-up instruction clause begins: a followup_instruction_verb counts as a follow-up directive (and triggers query truncation) only when one of these markers, or a punctuation mark, sits immediately before it. Because and and then are both modelled here, the compound and then is recognised by walking back over consecutive markers — no compound surface needs to be stored. Each surface is a bare token. English carries and and then; Russian, Hindi and Chinese add their natural coordinating and sequencing words so clause boundaries are recognised in every supported language."',
  '    wiktionary "and"',
  '    defined_by "relation"',
  '    role "clause_continuation_marker"',
  '    lexeme "en"',
  '      word "and"',
  '        description "English coordinating conjunction (and); a clause boundary that can introduce a follow-up instruction."',
  '      word "then"',
  '        description "English sequencing adverb (then); a clause boundary that can introduce a follow-up instruction, including the compound and then."',
  '    lexeme "ru"',
  '      word "и"',
  '        description "Russian coordinating conjunction (romanized i, and); a clause boundary that can introduce a follow-up instruction."',
  '      word "затем"',
  '        description "Russian sequencing adverb (romanized zatem, then); a clause boundary that can introduce a follow-up instruction."',
  '      word "потом"',
  '        description "Russian sequencing adverb (romanized potom, afterwards); a clause boundary that can introduce a follow-up instruction."',
  '    lexeme "hi"',
  '      word "और"',
  '        description "Hindi coordinating conjunction (romanized aur, and); a clause boundary that can introduce a follow-up instruction."',
  '      word "फिर"',
  '        description "Hindi sequencing adverb (romanized phir, then); a clause boundary that can introduce a follow-up instruction."',
  '      word "तब"',
  '        description "Hindi sequencing adverb (romanized tab, then); a clause boundary that can introduce a follow-up instruction."',
  '    lexeme "zh"',
  '      word "并"',
  '        description "Chinese coordinating conjunction (pinyin bing, and/also); a clause boundary that can introduce a follow-up instruction."',
  '      word "然后"',
  '        description "Chinese sequencing adverb (pinyin ranhou, then); a clause boundary that can introduce a follow-up instruction."',
  '      word "接着"',
  '        description "Chinese sequencing adverb (pinyin jiezhe, next); a clause boundary that can introduce a follow-up instruction."',
  "meanings",
  '  meaning "human_language"',
  "    gloss \"a natural human language — the kind of system a translation request names as its source or its target. It is the genus the four supported languages specialise: each language meaning is defined_by it, so the recogniser reads a marker's language by walking the marker's defined_by edges down to one of these language meanings. The ISO 639-1 code itself (en, ru, hi, zh) is an identifier fixed in code, not a surface word; what lives here is how each language is named, in every supported language.\"",
  '    wiktionary "language"',
  '    defined_by "concept"',
  '    role "translation_language_genus"',
  '    lexeme "en"',
  '      word "language"',
  '        description "English noun (language) naming the genus of natural human languages a translation runs between."',
  '    lexeme "ru"',
  '      word "язык"',
  '        description "Russian noun (romanized yazyk, language) naming the genus of natural human languages."',
  '    lexeme "hi"',
  '      word "भाषा"',
  '        description "Hindi noun (romanized bhasha, language) naming the genus of natural human languages."',
  '    lexeme "zh"',
  '      word "语言"',
  '        description "Chinese noun (pinyin yuyan, language) naming the genus of natural human languages."',
  '  meaning "language_english"',
  "    gloss \"the English language — one of the four supported translation languages, ISO 639-1 code en. The code is fixed in the handler; this meaning records how English is named across the supported languages and is the language building block the from-English and into-English markers are defined_by, so detection resolves their language by reaching this meaning's slug.\"",
  '    wiktionary "English"',
  '    defined_by "human_language"',
  '    role "translation_language"',
  '    lexeme "en"',
  '      word "english"',
  '        description "English name of the English language (lowercased), code en."',
  '    lexeme "ru"',
  '      word "английский"',
  '        description "Russian name of English (romanized angliyskiy), code en."',
  '    lexeme "hi"',
  '      word "अंग्रेज़ी"',
  '        description "Hindi name of English (romanized angrezi, with nuqta), code en."',
  '      word "अंग्रेजी"',
  '        description "Hindi name of English (romanized angrezi, without nuqta), code en."',
  '    lexeme "zh"',
  '      word "英语"',
  '        description "Chinese name of English (pinyin yingyu), code en."',
  '      word "英文"',
  '        description "Chinese name of English (pinyin yingwen, the written-language variant), code en."',
  '  meaning "language_russian"',
  '    gloss "the Russian language — one of the four supported translation languages, ISO 639-1 code ru. The code is fixed in the handler; this meaning records how Russian is named across the supported languages and is the language building block the from-Russian and into-Russian markers are defined_by."',
  '    wiktionary "Russian"',
  '    defined_by "human_language"',
  '    role "translation_language"',
  '    lexeme "en"',
  '      word "russian"',
  '        description "English name of the Russian language (lowercased), code ru."',
  '    lexeme "ru"',
  '      word "русский"',
  '        description "Russian name of Russian (romanized russkiy), code ru."',
  '    lexeme "hi"',
  '      word "रूसी"',
  '        description "Hindi name of Russian (romanized rusi), code ru."',
  '    lexeme "zh"',
  '      word "俄语"',
  '        description "Chinese name of Russian (pinyin eyu), code ru."',
  '  meaning "language_hindi"',
  '    gloss "the Hindi language — one of the four supported translation languages, ISO 639-1 code hi. The code is fixed in the handler; this meaning records how Hindi is named across the supported languages and is the language building block the from-Hindi and into-Hindi markers are defined_by."',
  '    wiktionary "Hindi"',
  '    defined_by "human_language"',
  '    role "translation_language"',
  '    lexeme "en"',
  '      word "hindi"',
  '        description "English name of the Hindi language (lowercased), code hi."',
  '    lexeme "ru"',
  '      word "хинди"',
  '        description "Russian name of Hindi (romanized khindi), code hi."',
  '    lexeme "hi"',
  '      word "हिंदी"',
  '        description "Hindi name of Hindi (romanized hindi, anusvara spelling), code hi."',
  '      word "हिन्दी"',
  '        description "Hindi name of Hindi (romanized hindi, conjunct spelling), code hi."',
  '    lexeme "zh"',
  '      word "印地语"',
  '        description "Chinese name of Hindi (pinyin yindiyu), code hi."',
  '  meaning "language_chinese"',
  '    gloss "the Chinese language — one of the four supported translation languages, ISO 639-1 code zh. The code is fixed in the handler; this meaning records how Chinese is named across the supported languages and is the language building block the from-Chinese and into-Chinese markers are defined_by."',
  '    wiktionary "Chinese"',
  '    defined_by "human_language"',
  '    role "translation_language"',
  '    lexeme "en"',
  '      word "chinese"',
  '        description "English name of the Chinese language (lowercased), code zh."',
  '    lexeme "ru"',
  '      word "китайский"',
  '        description "Russian name of Chinese (romanized kitayskiy), code zh."',
  '    lexeme "hi"',
  '      word "चीनी"',
  '        description "Hindi name of Chinese (romanized chini), code zh."',
  '    lexeme "zh"',
  '      word "中文"',
  '        description "Chinese name of Chinese (pinyin zhongwen), code zh."',
  '      word "汉语"',
  '        description "Chinese name of Chinese (pinyin hanyu, simplified), code zh."',
  '      word "漢語"',
  '        description "Chinese name of Chinese (pinyin hanyu, traditional), code zh."',
  '  meaning "translate"',
  "    gloss \"the action of rendering a surface from one language into another — the verb every translation request realises. It is the genus the unquoted-frame and into-marker meanings specialise: its surfaces are the bare verb stems, used to detect a translation command in head-final Hindi (अनुवाद) and Chinese (翻译) where the verb is not bracketed by a circumfix. The English and Russian stems are clause-initial: the request-gate (try_translation) recognises a command by a head-initial stem, and the source-inferencer (infer_source_from_prompt) reads the stem's language as the language the user issued the command in. The Russian describe-imperative (опиши) is recorded under this genus too — this solver routes a description request through the same translation/description pipeline, so it counts as a clause-initial command stem.\"",
  '    wiktionary "translate"',
  '    defined_by "action"',
  '    role "translation_action"',
  '    lexeme "en"',
  '      word "translate"',
  '        description "English verb (translate) naming the translation action; clause-initial, so the request-gate matches it as a prefix."',
  '    lexeme "ru"',
  '      word "перевести"',
  '        description "Russian verb (romanized perevesti, to translate), the infinitive stem of the translation action; clause-initial."',
  '      word "переведи"',
  '        description "Russian verb (romanized perevedi, translate!), the imperative stem of the translation action; clause-initial."',
  '      word "опиши"',
  '        description "Russian verb (romanized opishi, describe!), the imperative the Russian reporter used to request a rendering/description; this solver routes it through the same translation/description pipeline, so it is recorded as a clause-initial command stem of this genus."',
  '    lexeme "hi"',
  '      word "अनुवाद"',
  '        description "Hindi noun (romanized anuvad, translation) used with करो/करें to form the translation command; scanned as the bare verb stem in Hindi prompts."',
  '    lexeme "zh"',
  '      word "翻译"',
  '        description "Chinese verb (pinyin fanyi, translate, simplified), scanned as the bare verb stem in Chinese prompts."',
  '      word "翻譯"',
  '        description "Chinese verb (pinyin fanyi, translate, traditional), scanned as the bare verb stem in Chinese prompts."',
  '  meaning "translation_direction_source"',
  '    gloss "the source-direction relation in a translation — the from side that names the language a surface is translated out of. Its surfaces are the bare directional prepositions; the from-language markers are constructed from this relation plus a language meaning, so the recogniser never stores a glued from-language phrase as an atom — it is built from its parts."',
  '    wiktionary "from"',
  '    defined_by "relation"',
  '    role "translation_source_direction"',
  '    lexeme "en"',
  '      word "from"',
  '        description "English preposition (from) naming the source direction of a translation."',
  '    lexeme "ru"',
  '      word "с"',
  '        description "Russian preposition (romanized s, from), naming the source direction (governs the genitive)."',
  '    lexeme "hi"',
  '      word "से"',
  '        description "Hindi postposition (romanized se, from), naming the source direction."',
  '    lexeme "zh"',
  '      word "从"',
  '        description "Chinese coverb (pinyin cong, from), naming the source direction."',
  '  meaning "translation_direction_target"',
  '    gloss "the target-direction relation in a translation — the into side that names the language a surface is translated toward. Its surfaces are the bare directional markers. In Chinese these bare markers (成, 为, 為, 到) are scanned directly: after a 翻译 verb the recogniser stops the surface at the first of them, so it reads the target boundary from this relation rather than from a hardcoded list. The into-language markers are constructed from this relation plus a language meaning."',
  '    wiktionary "to"',
  '    defined_by "relation"',
  '    role "translation_target_direction"',
  '    lexeme "en"',
  '      word "to"',
  '        description "English preposition (to) naming the target direction of a translation."',
  '    lexeme "ru"',
  '      word "на"',
  '        description "Russian preposition (romanized na, to/onto), naming the target direction (governs the accusative)."',
  '    lexeme "hi"',
  '      word "में"',
  '        description "Hindi postposition (romanized mein, in/into), naming the target direction."',
  '    lexeme "zh"',
  '      word "成"',
  '        description "Chinese resultative (pinyin cheng, into), a bare target-direction marker after the verb."',
  '      word "为"',
  '        description "Chinese coverb (pinyin wei, into/as, simplified), a bare target-direction marker after the verb."',
  '      word "為"',
  '        description "Chinese coverb (pinyin wei, into/as, traditional), a bare target-direction marker after the verb."',
  '      word "到"',
  '        description "Chinese resultative (pinyin dao, to/until), a bare target-direction marker after the verb."',
  '  meaning "translate_from_english"',
  '    gloss "the marker that names English as the translation source — translate … from english, с английского, अंग्रेज़ी से, 从英语. It is constructed from language_english and the source-direction relation; when any of its surfaces appears in a prompt the recogniser reports the source language as English (en, read by walking defined_by to language_english). Surfaces are matched as raw substrings, exactly as the previous hardcoded list did."',
  '    wiktionary "English"',
  '    defined_by "language_english"',
  '    defined_by "translation_direction_source"',
  '    role "translation_source_marker"',
  '    lexeme "en"',
  '      word "from english"',
  '        description "English source phrase (from + english); evidence the source language is English."',
  '    lexeme "ru"',
  '      word "с английского"',
  '        description "Russian source phrase (romanized s angliyskogo, from English, genitive); evidence the source is English."',
  '    lexeme "hi"',
  '      word "अंग्रेजी से"',
  '        description "Hindi source phrase (romanized angrezi se, from English, without nuqta); evidence the source is English."',
  '      word "अंग्रेज़ी से"',
  '        description "Hindi source phrase (romanized angrezi se, from English, with nuqta); evidence the source is English."',
  '    lexeme "zh"',
  '      word "从英语"',
  '        description "Chinese source phrase (pinyin cong yingyu, from English); evidence the source is English."',
  '      word "从英文"',
  '        description "Chinese source phrase (pinyin cong yingwen, from English, written-language variant); evidence the source is English."',
  '  meaning "translate_from_russian"',
  '    gloss "the marker that names Russian as the translation source — translate … from russian, с русского, रूसी से, 从俄语. Constructed from language_russian and the source-direction relation; any surface reports the source language as Russian (ru)."',
  '    wiktionary "Russian"',
  '    defined_by "language_russian"',
  '    defined_by "translation_direction_source"',
  '    role "translation_source_marker"',
  '    lexeme "en"',
  '      word "from russian"',
  '        description "English source phrase (from + russian); evidence the source language is Russian."',
  '    lexeme "ru"',
  '      word "с русского"',
  '        description "Russian source phrase (romanized s russkogo, from Russian, genitive); evidence the source is Russian."',
  '    lexeme "hi"',
  '      word "रूसी से"',
  '        description "Hindi source phrase (romanized rusi se, from Russian); evidence the source is Russian."',
  '    lexeme "zh"',
  '      word "从俄语"',
  '        description "Chinese source phrase (pinyin cong eyu, from Russian); evidence the source is Russian."',
  '  meaning "translate_from_hindi"',
  '    gloss "the marker that names Hindi as the translation source — translate … from hindi, с хинди, हिंदी से, 从印地语. Constructed from language_hindi and the source-direction relation; any surface reports the source language as Hindi (hi). The Russian с хинди surface completes the four-language coverage the relative-meta-logic invariants require."',
  '    wiktionary "Hindi"',
  '    defined_by "language_hindi"',
  '    defined_by "translation_direction_source"',
  '    role "translation_source_marker"',
  '    lexeme "en"',
  '      word "from hindi"',
  '        description "English source phrase (from + hindi); evidence the source language is Hindi."',
  '    lexeme "ru"',
  '      word "с хинди"',
  '        description "Russian source phrase (romanized s khindi, from Hindi, genitive); evidence the source is Hindi."',
  '    lexeme "hi"',
  '      word "हिंदी से"',
  '        description "Hindi source phrase (romanized hindi se, from Hindi, anusvara spelling); evidence the source is Hindi."',
  '      word "हिन्दी से"',
  '        description "Hindi source phrase (romanized hindi se, from Hindi, conjunct spelling); evidence the source is Hindi."',
  '    lexeme "zh"',
  '      word "从印地语"',
  '        description "Chinese source phrase (pinyin cong yindiyu, from Hindi); evidence the source is Hindi."',
  '      word "从印地文"',
  '        description "Chinese source phrase (pinyin cong yindiwen, from Hindi, written-language variant); evidence the source is Hindi."',
  '  meaning "translate_from_chinese"',
  '    gloss "the marker that names Chinese as the translation source — translate … from chinese, с китайского, चीनी से, 从中文. Constructed from language_chinese and the source-direction relation; any surface reports the source language as Chinese (zh). The Russian с китайского surface completes the four-language coverage the relative-meta-logic invariants require."',
  '    wiktionary "Chinese"',
  '    defined_by "language_chinese"',
  '    defined_by "translation_direction_source"',
  '    role "translation_source_marker"',
  '    lexeme "en"',
  '      word "from chinese"',
  '        description "English source phrase (from + chinese); evidence the source language is Chinese."',
  '    lexeme "ru"',
  '      word "с китайского"',
  '        description "Russian source phrase (romanized s kitayskogo, from Chinese, genitive); evidence the source is Chinese."',
  '    lexeme "hi"',
  '      word "चीनी से"',
  '        description "Hindi source phrase (romanized chini se, from Chinese); evidence the source is Chinese."',
  '    lexeme "zh"',
  '      word "从中文"',
  '        description "Chinese source phrase (pinyin cong zhongwen, from Chinese); evidence the source is Chinese."',
  '      word "从汉语"',
  '        description "Chinese source phrase (pinyin cong hanyu, from Chinese, simplified); evidence the source is Chinese."',
  '      word "从漢語"',
  '        description "Chinese source phrase (pinyin cong hanyu, from Chinese, traditional); evidence the source is Chinese."',
  '  meaning "translate_into_english"',
  '    gloss "the marker that names English as the translation target — translate … to english, на английский, अंग्रेज़ी में, 成英文. Constructed from language_english and the target-direction relation; any surface reports the target language as English (en). The Chinese forms enumerate every target-direction marker (成/为/為/到) glued to each name of English, matched as raw substrings exactly as the previous hardcoded list did."',
  '    wiktionary "English"',
  '    defined_by "language_english"',
  '    defined_by "translation_direction_target"',
  '    role "translation_target_marker"',
  '    lexeme "en"',
  '      word "to english"',
  '        description "English target phrase (to + english); evidence the target language is English."',
  '    lexeme "ru"',
  '      word "на английский"',
  '        description "Russian target phrase (romanized na angliyskiy, into English, accusative); evidence the target is English."',
  '      word "на английском"',
  '        description "Russian target phrase (romanized na angliyskom, in English, prepositional); evidence the target is English."',
  '    lexeme "hi"',
  '      word "अंग्रेजी में"',
  '        description "Hindi target phrase (romanized angrezi mein, into English, without nuqta); evidence the target is English."',
  '      word "अंग्रेज़ी में"',
  '        description "Hindi target phrase (romanized angrezi mein, into English, with nuqta); evidence the target is English."',
  '    lexeme "zh"',
  '      word "成英文"',
  '        description "Chinese target phrase (pinyin cheng yingwen, into English); 成 + 英文."',
  '      word "成英语"',
  '        description "Chinese target phrase (pinyin cheng yingyu, into English); 成 + 英语."',
  '      word "为英文"',
  '        description "Chinese target phrase (pinyin wei yingwen, into English, simplified); 为 + 英文."',
  '      word "为英语"',
  '        description "Chinese target phrase (pinyin wei yingyu, into English, simplified); 为 + 英语."',
  '      word "為英文"',
  '        description "Chinese target phrase (pinyin wei yingwen, into English, traditional); 為 + 英文."',
  '      word "為英语"',
  '        description "Chinese target phrase (pinyin wei yingyu, into English, traditional 為 + simplified 英语); evidence the target is English."',
  '      word "到英文"',
  '        description "Chinese target phrase (pinyin dao yingwen, to English); 到 + 英文."',
  '      word "到英语"',
  '        description "Chinese target phrase (pinyin dao yingyu, to English); 到 + 英语."',
  '  meaning "translate_into_russian"',
  '    gloss "the marker that names Russian as the translation target — translate … to russian, на русский, रूसी में, 成俄语. Constructed from language_russian and the target-direction relation; any surface reports the target language as Russian (ru). The Chinese forms enumerate every target-direction marker glued to each name of Russian."',
  '    wiktionary "Russian"',
  '    defined_by "language_russian"',
  '    defined_by "translation_direction_target"',
  '    role "translation_target_marker"',
  '    lexeme "en"',
  '      word "to russian"',
  '        description "English target phrase (to + russian); evidence the target language is Russian."',
  '    lexeme "ru"',
  '      word "на русский"',
  '        description "Russian target phrase (romanized na russkiy, into Russian, accusative); evidence the target is Russian."',
  '    lexeme "hi"',
  '      word "रूसी में"',
  '        description "Hindi target phrase (romanized rusi mein, into Russian); evidence the target is Russian."',
  '    lexeme "zh"',
  '      word "成俄语"',
  '        description "Chinese target phrase (pinyin cheng eyu, into Russian, simplified); 成 + 俄语."',
  '      word "成俄語"',
  '        description "Chinese target phrase (pinyin cheng eyu, into Russian, traditional); 成 + 俄語."',
  '      word "为俄语"',
  '        description "Chinese target phrase (pinyin wei eyu, into Russian, simplified); 为 + 俄语."',
  '      word "为俄語"',
  '        description "Chinese target phrase (pinyin wei eyu, into Russian, simplified 为 + traditional 俄語); evidence the target is Russian."',
  '      word "為俄语"',
  '        description "Chinese target phrase (pinyin wei eyu, into Russian, traditional 為 + simplified 俄语); evidence the target is Russian."',
  '      word "為俄語"',
  '        description "Chinese target phrase (pinyin wei eyu, into Russian, traditional); 為 + 俄語."',
  '      word "到俄语"',
  '        description "Chinese target phrase (pinyin dao eyu, to Russian, simplified); 到 + 俄语."',
  '      word "到俄語"',
  '        description "Chinese target phrase (pinyin dao eyu, to Russian, traditional); 到 + 俄語."',
  '  meaning "translate_into_hindi"',
  '    gloss "the marker that names Hindi as the translation target — translate … to hindi, на хинди, हिंदी में, 成印地语. Constructed from language_hindi and the target-direction relation; any surface reports the target language as Hindi (hi). The Chinese forms enumerate every target-direction marker glued to each name of Hindi."',
  '    wiktionary "Hindi"',
  '    defined_by "language_hindi"',
  '    defined_by "translation_direction_target"',
  '    role "translation_target_marker"',
  '    lexeme "en"',
  '      word "to hindi"',
  '        description "English target phrase (to + hindi); evidence the target language is Hindi."',
  '    lexeme "ru"',
  '      word "на хинди"',
  '        description "Russian target phrase (romanized na khindi, into Hindi); evidence the target is Hindi."',
  '    lexeme "hi"',
  '      word "हिंदी में"',
  '        description "Hindi target phrase (romanized hindi mein, into Hindi, anusvara spelling); evidence the target is Hindi."',
  '      word "हिन्दी में"',
  '        description "Hindi target phrase (romanized hindi mein, into Hindi, conjunct spelling); evidence the target is Hindi."',
  '    lexeme "zh"',
  '      word "成印地语"',
  '        description "Chinese target phrase (pinyin cheng yindiyu, into Hindi); 成 + 印地语."',
  '      word "成印地文"',
  '        description "Chinese target phrase (pinyin cheng yindiwen, into Hindi, written-language variant); 成 + 印地文."',
  '      word "为印地语"',
  '        description "Chinese target phrase (pinyin wei yindiyu, into Hindi, simplified); 为 + 印地语."',
  '      word "为印地文"',
  '        description "Chinese target phrase (pinyin wei yindiwen, into Hindi, simplified); 为 + 印地文."',
  '      word "為印地语"',
  '        description "Chinese target phrase (pinyin wei yindiyu, into Hindi, traditional 為 + simplified 印地语); evidence the target is Hindi."',
  '      word "為印地文"',
  '        description "Chinese target phrase (pinyin wei yindiwen, into Hindi, traditional 為 + 印地文); evidence the target is Hindi."',
  '      word "到印地语"',
  '        description "Chinese target phrase (pinyin dao yindiyu, to Hindi); 到 + 印地语."',
  '      word "到印地文"',
  '        description "Chinese target phrase (pinyin dao yindiwen, to Hindi); 到 + 印地文."',
  '  meaning "translate_into_chinese"',
  '    gloss "the marker that names Chinese as the translation target — translate … to chinese, на китайский, चीनी में, 成中文. Constructed from language_chinese and the target-direction relation; any surface reports the target language as Chinese (zh). The Chinese forms enumerate every target-direction marker glued to each name of Chinese."',
  '    wiktionary "Chinese"',
  '    defined_by "language_chinese"',
  '    defined_by "translation_direction_target"',
  '    role "translation_target_marker"',
  '    lexeme "en"',
  '      word "to chinese"',
  '        description "English target phrase (to + chinese); evidence the target language is Chinese."',
  '    lexeme "ru"',
  '      word "на китайский"',
  '        description "Russian target phrase (romanized na kitayskiy, into Chinese, accusative); evidence the target is Chinese."',
  '    lexeme "hi"',
  '      word "चीनी में"',
  '        description "Hindi target phrase (romanized chini mein, into Chinese); evidence the target is Chinese."',
  '    lexeme "zh"',
  '      word "成中文"',
  '        description "Chinese target phrase (pinyin cheng zhongwen, into Chinese); 成 + 中文."',
  '      word "成汉语"',
  '        description "Chinese target phrase (pinyin cheng hanyu, into Chinese, simplified); 成 + 汉语."',
  '      word "成漢語"',
  '        description "Chinese target phrase (pinyin cheng hanyu, into Chinese, traditional); 成 + 漢語."',
  '      word "为中文"',
  '        description "Chinese target phrase (pinyin wei zhongwen, into Chinese, simplified); 为 + 中文."',
  '      word "为汉语"',
  '        description "Chinese target phrase (pinyin wei hanyu, into Chinese, simplified); 为 + 汉语."',
  '      word "为漢語"',
  '        description "Chinese target phrase (pinyin wei hanyu, into Chinese, simplified 为 + traditional 漢語); evidence the target is Chinese."',
  '      word "為中文"',
  '        description "Chinese target phrase (pinyin wei zhongwen, into Chinese, traditional 為 + 中文); evidence the target is Chinese."',
  '      word "為汉语"',
  '        description "Chinese target phrase (pinyin wei hanyu, into Chinese, traditional 為 + simplified 汉语); evidence the target is Chinese."',
  '      word "為漢語"',
  '        description "Chinese target phrase (pinyin wei hanyu, into Chinese, traditional); 為 + 漢語."',
  '      word "到中文"',
  '        description "Chinese target phrase (pinyin dao zhongwen, to Chinese); 到 + 中文."',
  '      word "到汉语"',
  '        description "Chinese target phrase (pinyin dao hanyu, to Chinese, simplified); 到 + 汉语."',
  '      word "到漢語"',
  '        description "Chinese target phrase (pinyin dao hanyu, to Chinese, traditional); 到 + 漢語."',
  '  meaning "translation_unquoted_frame"',
  '    gloss "the verb frame that brackets the surface to translate in an unquoted command, so an extractor can lift the surface out without quotes. Its forms split by word order, and the slot shape records the shape. In head-initial English and Russian the verb precedes the surface and the target preposition follows it, so the form is a circumfix surface (translate … to , переведи … на ) whose literal before the slot is stripped from the front and whose literal after the slot bounds the surface on the right. In head-final Hindi and Chinese the verb is not a bracket, so the form is a bare verb stem (अनुवाद, 翻译/翻譯) that gates the language-specific extractor. Constructed from the translate action and the target-direction relation."',
  '    wiktionary "translate"',
  '    defined_by "translate"',
  '    defined_by "translation_direction_target"',
  '    role "translation_unquoted_frame"',
  '    lexeme "en"',
  '      word "translate … to "',
  '        description "English circumfix frame; before the slot the verb prefix translate (trailing space) is stripped, after the slot the target preposition  to  (space-wrapped) bounds the surface on the right."',
  '    lexeme "ru"',
  '      word "переведи … на "',
  '        description "Russian circumfix frame (romanized perevedi … na, translate … to); before the slot the imperative verb is stripped, after the slot the target preposition  на  bounds the surface on the right."',
  '    lexeme "hi"',
  '      word "अनुवाद"',
  '        description "Hindi bare verb stem (romanized anuvad, translation); its presence gates the Hindi unquoted extractor, which reads the surface from the object and into postpositions."',
  '    lexeme "zh"',
  '      word "翻译"',
  '        description "Chinese bare verb stem (pinyin fanyi, translate, simplified); stripped from the front as a translate prefix when no disposal 把/将 opens the command."',
  '      word "翻譯"',
  '        description "Chinese bare verb stem (pinyin fanyi, translate, traditional); stripped from the front as a translate prefix when no disposal 把/将 opens the command."',
  '  meaning "translation_into_marker"',
  "    gloss \"the verb-and-target compound that introduces the target language right after the surface — translate-into. Languages glue the verb and the into-direction in opposite orders: head-final Hindi postposes the target marker onto the verb noun ( में अनुवाद,  मे अनुवाद), so the extractor finds it and takes the text before it; Chinese prefixes the into-direction onto the verb (翻译成, 翻译为, 翻译到 and traditional 翻譯…), so the extractor stops the surface at the first such compound. The English and Russian compounds (translate into, перевести на) are recorded for completeness; those languages are extracted through the unquoted frame's circumfix instead, so these full compounds are not separately scanned. Constructed from the translate action and the target-direction relation.\"",
  '    wiktionary "into"',
  '    defined_by "translate"',
  '    defined_by "translation_direction_target"',
  '    role "translation_into_marker"',
  '    lexeme "en"',
  '      word "translate into"',
  '        description "English verb-and-target compound (translate + into); recorded for completeness — English is extracted through the unquoted frame, so this compound is not separately scanned."',
  '    lexeme "ru"',
  '      word "перевести на"',
  '        description "Russian verb-and-target compound (romanized perevesti na, translate into); recorded for completeness — Russian is extracted through the unquoted frame, so this compound is not separately scanned."',
  '    lexeme "hi"',
  '      word " में अनुवाद"',
  '        description "Hindi target-and-verb compound (romanized mein anuvad, into translation), space-led; the extractor finds it and keeps the text before it as the surface."',
  '      word " मे अनुवाद"',
  '        description "Hindi target-and-verb compound (romanized me anuvad, into translation, anusvara-dropped variant), space-led; the extractor finds it and keeps the text before it as the surface."',
  '    lexeme "zh"',
  '      word "翻译成"',
  '        description "Chinese verb-and-target compound (pinyin fanyi cheng, translate into, simplified); the extractor stops the surface at it."',
  '      word "翻译为"',
  '        description "Chinese verb-and-target compound (pinyin fanyi wei, translate into, simplified); the extractor stops the surface at it."',
  '      word "翻译到"',
  '        description "Chinese verb-and-target compound (pinyin fanyi dao, translate to, simplified); the extractor stops the surface at it."',
  '      word "翻譯成"',
  '        description "Chinese verb-and-target compound (pinyin fanyi cheng, translate into, traditional); the extractor stops the surface at it."',
  '      word "翻譯為"',
  '        description "Chinese verb-and-target compound (pinyin fanyi wei, translate into, traditional); the extractor stops the surface at it."',
  '      word "翻譯到"',
  '        description "Chinese verb-and-target compound (pinyin fanyi dao, translate to, traditional); the extractor stops the surface at it."',
  '  meaning "translation_object_marker"',
  '    gloss "the particle that flags the noun phrase to be translated as the object, so an extractor can bound it. Word order decides the shape: head-final Hindi postposes the marker after the object (का genitive, को accusative), so the extractor uses it as a right boundary and keeps the text before it; Chinese prefixes a disposal particle before the object (把, 将), so the extractor strips it from the front and keeps the text after it. English and Russian mark the object by position and case rather than a dedicated particle, so their nearest realisations are recorded for completeness and are not scanned — only the Devanagari and Han forms are. Defined as a grammatical relation."',
  '    wiktionary "of"',
  '    defined_by "relation"',
  '    role "translation_object_marker"',
  '    lexeme "en"',
  '      word "of"',
  '        description "English genitive linker (of), as in the translation of X — the nearest realisation of Hindi का; recorded for completeness, not scanned (English marks the object positionally)."',
  '    lexeme "ru"',
  '      word "слова"',
  '        description "Russian genitive noun (romanized slova, of the word), as in перевод слова X — the nearest realisation marking X as the object; recorded for completeness, not scanned (Russian marks the object by case)."',
  '    lexeme "hi"',
  '      word " का "',
  '        description "Hindi genitive postposition (romanized ka, of), space-wrapped; used as a right boundary — the surface is the text before it."',
  '      word " को "',
  '        description "Hindi accusative postposition (romanized ko, the object marker), space-wrapped; used as a right boundary after का — the surface is the text before it."',
  '    lexeme "zh"',
  '      word "把"',
  '        description "Chinese disposal particle (pinyin ba) fronting the object; stripped from the front so the surface is the text after it."',
  '      word "将"',
  '        description "Chinese disposal particle (pinyin jiang, formal variant of 把) fronting the object; stripped from the front so the surface is the text after it."',
  '  meaning "definition_command"',
  '    gloss "an imperative verb asking the assistant to define a phrase — to render its meaning, here as a Links Notation definition. The definition_command role marks the clause-initial command; the translation handler recognises a define request by composing this verb with a quoted or backticked phrase and a links_notation_format marker, then renders the phrase as its formal definition. Only the English surface is scanned, matched as a clause-initial prefix with a trailing space exactly as the original recogniser required; the Russian, Hindi and Chinese imperatives are recorded for completeness so the concept is lexicalised in every supported language, mirroring the original handler which gated on the English verb alone. Defined as an action."',
  '    wiktionary "define"',
  '    defined_by "action"',
  '    role "definition_command"',
  '    lexeme "en"',
  '      word "define"',
  '        description "English imperative verb to define; the only scanned definition_command surface, matched as a clause-initial prefix with a trailing space so that defined and definition do not trigger it."',
  '    lexeme "ru"',
  '      word "определи"',
  '        description "Russian imperative verb (romanized opredeli, of определить, to define); a completeness form for the definition_command concept, recorded but not scanned because the original recogniser gated on the English verb alone."',
  '    lexeme "hi"',
  '      word "परिभाषित करें"',
  '        description "Hindi imperative phrase (romanized paribhashit karen, define); a completeness form for the definition_command concept, recorded but not scanned."',
  '    lexeme "zh"',
  '      word "定义"',
  '        description "Chinese verb (pinyin dingyi, to define); a completeness form for the definition_command concept, recorded but not scanned."',
  '  meaning "links_notation_format"',
  "    gloss \"a phrase naming Links Notation — the indentation-based serialization format of the Deep Theory project — as the target a define request renders into. The links_notation_format role carries these surfaces; the translation handler reconstructs each as a space-prefixed token and treats a prompt as a define-in-Links request when one appears alongside a definition_command verb and a quoted or backticked phrase. The English phrase links notation and the Russian code-switched form are scanned, exactly the original recogniser's two substrings; the Hindi and Chinese renderings are recorded for completeness so the concept is lexicalised in every supported language. Defined as a concept.\"",
  '    wiktionary "notation"',
  '    defined_by "concept"',
  '    role "links_notation_format"',
  '    lexeme "en"',
  '      word "links notation"',
  '        description "English name of the Links Notation format; a links_notation_format surface scanned as a space-prefixed substring so it matches in links notation and to links notation without firing mid-word."',
  '    lexeme "ru"',
  '      word "в links"',
  '        description "Russian code-switched phrase (romanized v links, in links) naming Links Notation as the target; a links_notation_format surface scanned as a space-prefixed substring that pairs the Russian preposition v with the format proper noun, exactly as the original recogniser did."',
  '    lexeme "hi"',
  '      word "लिंक्स नोटेशन"',
  '        description "Hindi transliteration (romanized links noteshan) of Links Notation; a completeness form for the links_notation_format concept, recorded but not scanned."',
  '    lexeme "zh"',
  '      word "链接表示法"',
  '        description "Chinese rendering (pinyin lianjie biaoshifa) of Links Notation; a completeness form for the links_notation_format concept, recorded but not scanned."',
  '  meaning "apple"',
  '    gloss "the fruit apple, a concrete entity the compositional ru-to-en translator renders when a multi-word title carries the Russian apple lemma in any case. It holds the compositional_lemma role; the per-word fallback resolves any listed Russian inflection to the English surface apple. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried so the concept is lexicalised in every supported language. Defined as an entity."',
  '    wiktionary "apple"',
  '    defined_by "entity"',
  '    role "compositional_lemma"',
  '    lexeme "en"',
  '      word "apple"',
  '        description "English noun (apple); the surface the compositional translator emits for the Russian apple lemma."',
  '    lexeme "ru"',
  '      word "яблоко"',
  '        description "Russian noun (romanized yabloko, apple), nominative singular; a compositional_lemma form resolving to apple."',
  '      word "яблока"',
  '        description "Russian noun (romanized yabloka, apple), genitive singular; a compositional_lemma form resolving to apple."',
  '      word "яблоку"',
  '        description "Russian noun (romanized yabloku, apple), dative singular; a compositional_lemma form resolving to apple."',
  '      word "яблоком"',
  '        description "Russian noun (romanized yablokom, apple), instrumental singular; a compositional_lemma form resolving to apple."',
  '      word "яблоке"',
  '        description "Russian noun (romanized yabloke, apple), prepositional singular; a compositional_lemma form resolving to apple."',
  '      word "яблоки"',
  '        description "Russian noun (romanized yabloki, apple), nominative plural; a compositional_lemma form resolving to apple."',
  '      word "яблок"',
  '        description "Russian noun (romanized yablok, apple), genitive plural; a compositional_lemma form resolving to apple."',
  '      word "яблокам"',
  '        description "Russian noun (romanized yablokam, apple), dative plural; a compositional_lemma form resolving to apple."',
  '      word "яблоками"',
  '        description "Russian noun (romanized yablokami, apple), instrumental plural; a compositional_lemma form resolving to apple."',
  '      word "яблоках"',
  '        description "Russian noun (romanized yablokakh, apple), prepositional plural; a compositional_lemma form resolving to apple."',
  '    lexeme "hi"',
  '      word "सेब"',
  '        description "Hindi noun (romanized seb, apple); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "苹果"',
  '        description "Chinese noun (pinyin pingguo, apple); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "good"',
  '    gloss "the quality good, a property the compositional ru-to-en translator renders when a multi-word title carries a Russian good or kind adjective in any gender, number or case. It holds the compositional_lemma role; the per-word fallback resolves any listed inflection of dobryy or khoroshiy to the English surface good. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as a property."',
  '    wiktionary "good"',
  '    defined_by "property"',
  '    role "compositional_lemma"',
  '    lexeme "en"',
  '      word "good"',
  '        description "English adjective (good); the surface the compositional translator emits for a Russian good or kind adjective."',
  '    lexeme "ru"',
  '      word "доброе"',
  '        description "Russian adjective (romanized dobroye, good or kind), neuter nominative singular; a compositional_lemma form resolving to good."',
  '      word "добрый"',
  '        description "Russian adjective (romanized dobryy, good or kind), masculine nominative singular; a compositional_lemma form resolving to good."',
  '      word "добрая"',
  '        description "Russian adjective (romanized dobraya, good or kind), feminine nominative singular; a compositional_lemma form resolving to good."',
  '      word "добрые"',
  '        description "Russian adjective (romanized dobryye, good or kind), nominative plural; a compositional_lemma form resolving to good."',
  '      word "доброго"',
  '        description "Russian adjective (romanized dobrogo, good or kind), masculine or neuter genitive singular; a compositional_lemma form resolving to good."',
  '      word "добрую"',
  '        description "Russian adjective (romanized dobruyu, good or kind), feminine accusative singular; a compositional_lemma form resolving to good."',
  '      word "добрым"',
  '        description "Russian adjective (romanized dobrym, good or kind), masculine or neuter instrumental singular; a compositional_lemma form resolving to good."',
  '      word "хорошее"',
  '        description "Russian adjective (romanized khorosheye, good), neuter nominative singular; a compositional_lemma form resolving to good."',
  '      word "хороший"',
  '        description "Russian adjective (romanized khoroshiy, good), masculine nominative singular; a compositional_lemma form resolving to good."',
  '      word "хорошая"',
  '        description "Russian adjective (romanized khoroshaya, good), feminine nominative singular; a compositional_lemma form resolving to good."',
  '      word "хорошие"',
  '        description "Russian adjective (romanized khoroshiye, good), nominative plural; a compositional_lemma form resolving to good."',
  '      word "хорошего"',
  '        description "Russian adjective (romanized khoroshego, good), masculine or neuter genitive singular; a compositional_lemma form resolving to good."',
  '      word "хорошую"',
  '        description "Russian adjective (romanized khoroshuyu, good), feminine accusative singular; a compositional_lemma form resolving to good."',
  '      word "хорошим"',
  '        description "Russian adjective (romanized khoroshim, good), masculine or neuter instrumental singular; a compositional_lemma form resolving to good."',
  '    lexeme "hi"',
  '      word "अच्छा"',
  '        description "Hindi adjective (romanized achchha, good); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "好"',
  '        description "Chinese adjective (pinyin hao, good); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "find"',
  '    gloss "the action find, locating something; the verb the compositional ru-to-en translator renders when a Russian find imperative or infinitive opens a search request. It holds the compositional_lemma role; the per-word fallback resolves any listed Russian form to the English surface find. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as an action."',
  '    wiktionary "find"',
  '    defined_by "action"',
  '    role "compositional_lemma"',
  '    lexeme "en"',
  '      word "find"',
  '        description "English verb (find); the surface the compositional translator emits for a Russian find imperative or infinitive."',
  '    lexeme "ru"',
  '      word "найди"',
  '        description "Russian verb (romanized naydi, find), singular imperative; a compositional_lemma form resolving to find."',
  '      word "найдите"',
  '        description "Russian verb (romanized naydite, find), plural or polite imperative; a compositional_lemma form resolving to find."',
  '      word "найти"',
  '        description "Russian verb (romanized nayti, to find), infinitive; a compositional_lemma form resolving to find."',
  '    lexeme "hi"',
  '      word "खोजें"',
  '        description "Hindi verb (romanized khojen, find or search); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "查找"',
  '        description "Chinese verb (pinyin chazhao, find or look up); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "synonym"',
  "    gloss \"the concept synonym, a word sharing another word's meaning; rendered by the compositional ru-to-en translator and, as a relation noun, able to govern a genitive complement, as in sinonimy soglasovaniya, synonyms of agreement. It holds compositional_lemma and compositional_genitive_head; the per-word fallback resolves any listed Russian form to the English plural surface synonyms, the form the original search-phrase mapping emits. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as a concept.\"",
  '    wiktionary "synonym"',
  '    defined_by "concept"',
  '    role "compositional_lemma"',
  '    role "compositional_genitive_head"',
  '    lexeme "en"',
  '      word "synonyms"',
  '        description "English noun (synonyms), plural; the surface the compositional translator emits for a Russian synonym form, matching the original search-phrase mapping."',
  '    lexeme "ru"',
  '      word "синоним"',
  '        description "Russian noun (romanized sinonim, synonym), nominative singular; a compositional_lemma and genitive-head form resolving to synonyms."',
  '      word "синонимы"',
  '        description "Russian noun (romanized sinonimy, synonyms), nominative plural; a compositional_lemma and genitive-head form resolving to synonyms."',
  '      word "синонимов"',
  '        description "Russian noun (romanized sinonimov, synonyms), genitive plural; a compositional_lemma and genitive-head form resolving to synonyms."',
  '    lexeme "hi"',
  '      word "पर्यायवाची"',
  '        description "Hindi noun (romanized paryayvachi, synonym); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "同义词"',
  '        description "Chinese noun (pinyin tongyici, synonym); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "example"',
  '    gloss "the concept example, an instance illustrating something; rendered by the compositional ru-to-en translator and, as a relation noun, able to govern a genitive complement, as in primery soglasovaniya, examples of agreement. It holds compositional_lemma and compositional_genitive_head; the per-word fallback resolves any listed Russian form to the English plural surface examples. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as a concept."',
  '    wiktionary "example"',
  '    defined_by "concept"',
  '    role "compositional_lemma"',
  '    role "compositional_genitive_head"',
  '    lexeme "en"',
  '      word "examples"',
  '        description "English noun (examples), plural; the surface the compositional translator emits for a Russian example form, matching the original search-phrase mapping."',
  '    lexeme "ru"',
  '      word "пример"',
  '        description "Russian noun (romanized primer, example), nominative singular; a compositional_lemma and genitive-head form resolving to examples."',
  '      word "примеры"',
  '        description "Russian noun (romanized primery, examples), nominative plural; a compositional_lemma and genitive-head form resolving to examples."',
  '      word "примеров"',
  '        description "Russian noun (romanized primerov, examples), genitive plural; a compositional_lemma and genitive-head form resolving to examples."',
  '    lexeme "hi"',
  '      word "उदाहरण"',
  '        description "Hindi noun (romanized udaharan, example); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "例子"',
  '        description "Chinese noun (pinyin lizi, example); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "agreement"',
  '    gloss "the concept agreement, grammatical concord; the genitive complement in the search phrase examples of agreement, rendered by the compositional ru-to-en translator. It holds the compositional_lemma role; the per-word fallback resolves any listed Russian form to the English surface agreement. The genitive-singular form soglasovaniya additionally carries action genitive so the genitive-of construction picks it as the complement of a relation head. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as a concept."',
  '    wiktionary "agreement"',
  '    defined_by "concept"',
  '    role "compositional_lemma"',
  '    lexeme "en"',
  '      word "agreement"',
  '        description "English noun (agreement); the surface the compositional translator emits for a Russian agreement form, including the genitive complement of a relation head."',
  '    lexeme "ru"',
  '      word "согласование"',
  '        description "Russian noun (romanized soglasovaniye, agreement), nominative singular; a compositional_lemma form resolving to agreement."',
  '      word "согласования"',
  '        action "genitive"',
  '        description "Russian noun (romanized soglasovaniya, agreement), genitive singular; tagged genitive so the genitive-of construction reads it as the complement of a relation head, resolving to agreement."',
  '      word "согласованию"',
  '        description "Russian noun (romanized soglasovaniyu, agreement), dative singular; a compositional_lemma form resolving to agreement."',
  '      word "согласованием"',
  '        description "Russian noun (romanized soglasovaniyem, agreement), instrumental singular; a compositional_lemma form resolving to agreement."',
  '      word "согласовании"',
  '        description "Russian noun (romanized soglasovanii, agreement), prepositional singular; a compositional_lemma form resolving to agreement."',
  '    lexeme "hi"',
  '      word "सहमति"',
  '        description "Hindi noun (romanized sahmati, agreement); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "一致"',
  '        description "Chinese noun (pinyin yizhi, agreement or concord); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "conjunction_or"',
  '    gloss "the relation or, the logical connective joining alternatives; rendered by the compositional ru-to-en translator when the Russian connective ili appears between search terms. It holds the compositional_lemma role; the per-word fallback resolves ili to the English surface or. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as a relation."',
  '    wiktionary "or"',
  '    defined_by "relation"',
  '    role "compositional_lemma"',
  '    lexeme "en"',
  '      word "or"',
  '        description "English conjunction (or); the surface the compositional translator emits for the Russian connective ili."',
  '    lexeme "ru"',
  '      word "или"',
  '        description "Russian conjunction (romanized ili, or); a compositional_lemma form resolving to or."',
  '    lexeme "hi"',
  '      word "या"',
  '        description "Hindi conjunction (romanized ya, or); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "或"',
  '        description "Chinese conjunction (pinyin huo, or); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "who_are_you"',
  '    gloss "the fixed question who are you, a short Russian identity question that translates as a whole rather than word by word. It holds the compositional_phrase role; the compositional fallback looks the normalized title up among the phrase meanings before attempting composition and returns the English form verbatim, capitalization and terminal question mark included. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as a concept."',
  '    wiktionary "who"',
  '    defined_by "concept"',
  '    role "compositional_phrase"',
  '    lexeme "en"',
  '      word "Who are you?"',
  '        description "English question (Who are you?); the verbatim rendering the compositional translator returns for the Russian identity question, capitalization and question mark included."',
  '    lexeme "ru"',
  '      word "кто ты"',
  '        description "Russian question (romanized kto ty, who are you), informal; a compositional_phrase form resolving to Who are you."',
  '      word "кто ты такой"',
  '        description "Russian question (romanized kto ty takoy, who are you), informal masculine; a compositional_phrase form resolving to Who are you."',
  '      word "кто ты такая"',
  '        description "Russian question (romanized kto ty takaya, who are you), informal feminine; a compositional_phrase form resolving to Who are you."',
  '      word "кто вы"',
  '        description "Russian question (romanized kto vy, who are you), polite or plural; a compositional_phrase form resolving to Who are you."',
  '      word "кто вы такой"',
  '        description "Russian question (romanized kto vy takoy, who are you), polite masculine; a compositional_phrase form resolving to Who are you."',
  '      word "кто вы такая"',
  '        description "Russian question (romanized kto vy takaya, who are you), polite feminine; a compositional_phrase form resolving to Who are you."',
  '    lexeme "hi"',
  '      word "आप कौन हैं"',
  '        description "Hindi question (romanized aap kaun hain, who are you); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "你是谁"',
  '        description "Chinese question (pinyin ni shi shei, who are you); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "what_is_this"',
  '    gloss "the fixed question what is this, a short Russian question that translates as a whole rather than word by word. It holds the compositional_phrase role; the compositional fallback looks the normalized title up among the phrase meanings before attempting composition and returns the English form verbatim, capitalization and terminal question mark included. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as a concept."',
  '    wiktionary "what"',
  '    defined_by "concept"',
  '    role "compositional_phrase"',
  '    lexeme "en"',
  '      word "What is this?"',
  '        description "English question (What is this?); the verbatim rendering the compositional translator returns for the Russian what-is-this question, capitalization and question mark included."',
  '    lexeme "ru"',
  '      word "что это"',
  '        description "Russian question (romanized chto eto, what is this); a compositional_phrase form resolving to What is this."',
  '      word "что это такое"',
  '        description "Russian question (romanized chto eto takoye, what is this), emphatic; a compositional_phrase form resolving to What is this."',
  '    lexeme "hi"',
  '      word "यह क्या है"',
  '        description "Hindi question (romanized yah kya hai, what is this); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "这是什么"',
  '        description "Chinese question (pinyin zhe shi shenme, what is this); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '  meaning "how_are_you"',
  '    gloss "the fixed greeting question how are you, a short Russian phrase that translates as a whole rather than word by word. It holds the compositional_phrase role; the compositional fallback returns the English form verbatim, lowercase and without terminal punctuation so a source that carries none keeps none. Head-initial English and Russian are the consulted pair; Hindi and Chinese are carried for coverage. Defined as a concept."',
  '    wiktionary "how"',
  '    defined_by "concept"',
  '    role "compositional_phrase"',
  '    lexeme "en"',
  '      word "how are you"',
  '        description "English greeting question (how are you), lowercase and unpunctuated; the verbatim rendering the compositional translator returns for the Russian greeting."',
  '    lexeme "ru"',
  '      word "как дела"',
  '        description "Russian greeting question (romanized kak dela, how are you); a compositional_phrase form resolving to how are you."',
  '    lexeme "hi"',
  '      word "आप कैसे हैं"',
  '        description "Hindi greeting question (romanized aap kaise hain, how are you); a coverage form, not consulted by the head-initial ru-to-en scan."',
  '    lexeme "zh"',
  '      word "你好吗"',
  '        description "Chinese greeting question (pinyin ni hao ma, how are you); a coverage form, not consulted by the head-initial ru-to-en scan."',
  "meanings",
  '  meaning "link"',
  '    gloss "the root of the ontology — a connection between things. In Links Notation every meaning is itself a link, so the root link is defined by itself and every other meaning descends from it (a single merged root in the spirit of relative-meta-logic)."',
  '    wiktionary "link"',
  '    defined_by "link"',
  '    role "ontology_root"',
  '    lexeme "en"',
  '      word "link"',
  '        description "English noun and verb for a connection between two things; the self-rooted root of the whole ontology."',
  '      word "connection"',
  '        description "English noun for the relationship that joins two things; a synonym surface for the link concept."',
  '    lexeme "ru"',
  '      word "связь"',
  '        description "Russian noun (romanized svyaz) for a connection or tie; the Russian surface for the link concept."',
  '      word "ссылка"',
  '        description "Russian noun (romanized ssylka) for a reference or hyperlink; the Russian surface for an explicit link."',
  '    lexeme "hi"',
  '      word "लिंक"',
  '        description "Hindi noun (romanized link, a loanword) for a connection or hyperlink; the Hindi surface for the link concept."',
  '      word "कड़ी"',
  '        description "Hindi noun (romanized kadi) for a link in a chain; the native Hindi surface for a connection."',
  '    lexeme "zh"',
  '      word "链接"',
  '        description "Chinese noun (pinyin lianjie) for a hyperlink or connection; the Chinese surface for the link concept."',
  '      word "连接"',
  '        description "Chinese verb (pinyin lianjie) for joining or connecting; the Chinese surface for forming a connection."',
  '  meaning "type"',
  '    gloss "a classification of links — the root of the type-system ontology; a type is itself a link, so it is defined by link. Entities and concepts are the broadest types the assistant reasons with."',
  '    wiktionary "type"',
  '    defined_by "link"',
  '    role "ontology_type"',
  '    lexeme "en"',
  '      word "type"',
  '        description "English noun for a classification or category of links; the root of the type-system sub-ontology."',
  '      word "kind"',
  '        description "English noun for a sort or category; a synonym surface for the type concept."',
  '    lexeme "ru"',
  '      word "тип"',
  '        description "Russian noun (romanized tip) for a type or category; the Russian surface for the type concept."',
  '      word "вид"',
  '        description "Russian noun (romanized vid) for a kind or sort; an alternative Russian surface for a category."',
  '    lexeme "hi"',
  '      word "प्रकार"',
  '        description "Hindi noun (romanized prakar) for a type or kind; the Hindi surface for the type concept."',
  '      word "क़िस्म"',
  '        description "Hindi noun (romanized qism) for a sort or variety; an alternative Hindi surface for a category."',
  '    lexeme "zh"',
  '      word "类型"',
  '        description "Chinese noun (pinyin leixing) for a type or category; the Chinese surface for the type concept."',
  '      word "种类"',
  '        description "Chinese noun (pinyin zhonglei) for a kind or sort; an alternative Chinese surface for a category."',
  '  meaning "entity"',
  '    gloss "a thing that exists and can be referred to — a link seen as a node; the genus of every concrete subject the assistant reasons about (programs, artifacts, the assistant and user themselves)."',
  '    wiktionary "entity"',
  '    defined_by "type"',
  '    role "ontology_category"',
  '    lexeme "en"',
  '      word "entity"',
  '        description "English noun for a thing that exists and can be referred to; the genus of concrete subjects."',
  '      word "thing"',
  '        description "English noun for any object that can be referred to; a plain synonym surface for entity."',
  '    lexeme "ru"',
  '      word "сущность"',
  '        description "Russian noun (romanized sushchnost) for an entity or essence; the Russian surface for the entity concept."',
  '      word "объект"',
  '        description "Russian noun (romanized obyekt) for an object; an alternative Russian surface for a concrete entity."',
  '    lexeme "hi"',
  '      word "इकाई"',
  '        description "Hindi noun (romanized ikai) for a unit or entity; the Hindi surface for the entity concept."',
  '      word "वस्तु"',
  '        description "Hindi noun (romanized vastu) for a thing or object; an alternative Hindi surface for an entity."',
  '    lexeme "zh"',
  '      word "实体"',
  '        description "Chinese noun (pinyin shiti) for an entity; the Chinese surface for the entity concept."',
  '      word "事物"',
  '        description "Chinese noun (pinyin shiwu) for a thing or object; an alternative Chinese surface for an entity."',
  '  meaning "concept"',
  '    gloss "an abstract meaning or idea — a type of notion the assistant can name and reason about apart from any concrete instance (calendars, approvals, features)."',
  '    wiktionary "concept"',
  '    defined_by "type"',
  '    role "ontology_category"',
  '    lexeme "en"',
  '      word "concept"',
  '        description "English noun for an abstract meaning or idea; the genus of notions reasoned about apart from instances."',
  '      word "notion"',
  '        description "English noun for an idea or concept; a synonym surface for the concept meaning."',
  '    lexeme "ru"',
  '      word "понятие"',
  '        description "Russian noun (romanized ponyatiye) for a concept or notion; the Russian surface for the concept meaning."',
  '      word "концепция"',
  '        description "Russian noun (romanized kontseptsiya) for a conception or framework; an alternative Russian surface for a concept."',
  '    lexeme "hi"',
  '      word "अवधारणा"',
  '        description "Hindi noun (romanized avadharana) for a concept or notion; the Hindi surface for the concept meaning."',
  '      word "संकल्पना"',
  '        description "Hindi noun (romanized sankalpana) for a conception or idea; an alternative Hindi surface for a concept."',
  '    lexeme "zh"',
  '      word "概念"',
  '        description "Chinese noun (pinyin gainian) for a concept; the Chinese surface for the concept meaning."',
  '      word "观念"',
  '        description "Chinese noun (pinyin guannian) for an idea or notion; an alternative Chinese surface for a concept."',
  '  meaning "relation"',
  '    gloss "a link that connects entities — it maps one entity or value to another; the genus of every named relationship in the knowledge base."',
  '    wiktionary "relation"',
  '    defined_by "link"',
  '    role "ontology_category"',
  '    lexeme "en"',
  '      word "relation"',
  '        description "English noun for a link that connects entities; the genus of named relationships."',
  '      word "relationship"',
  '        description "English noun for how two entities are connected; a synonym surface for relation."',
  '    lexeme "ru"',
  '      word "отношение"',
  '        description "Russian noun (romanized otnosheniye) for a relation; the Russian surface for the relation concept."',
  '      word "соотношение"',
  '        description "Russian noun (romanized sootnosheniye) for a correlation or ratio; an alternative Russian surface for a relation."',
  '    lexeme "hi"',
  '      word "संबंध"',
  '        description "Hindi noun (romanized sambandh) for a relation or connection; the Hindi surface for the relation concept."',
  '      word "रिश्ता"',
  '        description "Hindi noun (romanized rishta) for a relationship; an alternative Hindi surface for a relation."',
  '    lexeme "zh"',
  '      word "关系"',
  '        description "Chinese noun (pinyin guanxi) for a relation or relationship; the Chinese surface for the relation concept."',
  '      word "联系"',
  '        description "Chinese noun (pinyin lianxi) for a connection or link; an alternative Chinese surface for a relation."',
  '  meaning "action"',
  '    gloss "something performed — a process or operation that changes or produces state; the genus of every verb the assistant can carry out (sort, modify, follow up)."',
  '    wiktionary "action"',
  '    defined_by "concept"',
  '    role "ontology_category"',
  '    lexeme "en"',
  '      word "action"',
  '        description "English noun for a process or operation that changes or produces state; the genus of verbs the assistant performs."',
  '      word "act"',
  '        description "English noun for a single deed or operation; a shorter synonym surface for action."',
  '    lexeme "ru"',
  '      word "действие"',
  '        description "Russian noun (romanized deystviye) for an action; the Russian surface for the action concept."',
  '      word "операция"',
  '        description "Russian noun (romanized operatsiya) for an operation; an alternative Russian surface for an action."',
  '    lexeme "hi"',
  '      word "क्रिया"',
  '        description "Hindi noun (romanized kriya) for an action or verb; the Hindi surface for the action concept."',
  '      word "कार्य"',
  '        description "Hindi noun (romanized karya) for a task or operation; an alternative Hindi surface for an action."',
  '    lexeme "zh"',
  '      word "动作"',
  '        description "Chinese noun (pinyin dongzuo) for an action or movement; the Chinese surface for the action concept."',
  '      word "操作"',
  '        description "Chinese noun (pinyin caozuo) for an operation; an alternative Chinese surface for an action."',
  '  meaning "property"',
  '    gloss "a quality or attribute of an entity — what can be measured, classified, or arranged; the genus of measurable dimensions and software features."',
  '    wiktionary "property"',
  '    defined_by "concept"',
  '    role "ontology_category"',
  '    lexeme "en"',
  '      word "property"',
  '        description "English noun for a quality or attribute of an entity; the genus of measurable dimensions and features."',
  '      word "attribute"',
  '        description "English noun for a characteristic of an entity; a synonym surface for property."',
  '    lexeme "ru"',
  '      word "свойство"',
  '        description "Russian noun (romanized svoystvo) for a property; the Russian surface for the property concept."',
  '      word "атрибут"',
  '        description "Russian noun (romanized atribut) for an attribute; an alternative Russian surface for a property."',
  '    lexeme "hi"',
  '      word "गुण"',
  '        description "Hindi noun (romanized gun) for a quality or property; the Hindi surface for the property concept."',
  '      word "विशेषता"',
  '        description "Hindi noun (romanized visheshta) for a characteristic; an alternative Hindi surface for a property."',
  '    lexeme "zh"',
  '      word "属性"',
  '        description "Chinese noun (pinyin shuxing) for an attribute or property; the Chinese surface for the property concept."',
  '      word "特性"',
  '        description "Chinese noun (pinyin texing) for a characteristic or trait; an alternative Chinese surface for a property."',
  "meanings",
  '  meaning "wikidata_item_apple"',
  '    gloss "the fruit of the apple tree (Wikidata Q89); a common edible pome fruit used as a canonical concrete entity in formalization examples. Rooted in the external Wikidata knowledge base through its language-independent Q-id."',
  '    wiktionary "apple"',
  '    wikidata "Q89"',
  '    defined_by "entity"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "apple"',
  '        description "English noun for the edible pome fruit of the apple tree; the canonical English label for Wikidata entity Q89."',
  '      word "apples"',
  '        description "English plural noun for apple; an inflected surface for Wikidata entity Q89."',
  '    lexeme "ru"',
  '      word "яблоко"',
  '        description "Russian noun (romanized yabloko) for apple; the Russian surface for Wikidata entity Q89."',
  '      word "яблоки"',
  '        description "Russian plural noun (romanized yabloki) for apples; an inflected Russian surface for Wikidata entity Q89."',
  '    lexeme "hi"',
  '      word "सेब"',
  '        description "Hindi noun (romanized seb) for apple; the Hindi surface for Wikidata entity Q89."',
  '    lexeme "zh"',
  '      word "苹果"',
  '        description "Chinese noun (pinyin pingguo, simplified) for apple; the Chinese surface for Wikidata entity Q89."',
  '      word "蘋果"',
  '        description "Chinese noun (pinyin pingguo, traditional) for apple; the traditional Chinese surface for Wikidata entity Q89."',
  '  meaning "wikidata_item_fruit"',
  '    gloss "edible fruit (Wikidata Q3314483); the seed-bearing edible part of a flowering plant, used as a canonical class entity in formalization examples. Rooted in the external Wikidata knowledge base through its language-independent Q-id."',
  '    wiktionary "fruit"',
  '    wikidata "Q3314483"',
  '    defined_by "concept"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "fruit"',
  '        description "English noun for the edible seed-bearing part of a plant; the canonical English label for Wikidata entity Q3314483."',
  '      word "fruits"',
  '        description "English plural noun for fruit; an inflected surface for Wikidata entity Q3314483."',
  '      word "edible fruit"',
  '        description "English compound noun matching the Wikidata Q3314483 label edible fruit; an explicit surface for the same entity."',
  '    lexeme "ru"',
  '      word "фрукт"',
  '        description "Russian noun (romanized frukt) for fruit; the Russian surface for Wikidata entity Q3314483."',
  '      word "фрукты"',
  '        description "Russian plural noun (romanized frukty) for fruits; an inflected Russian surface for Wikidata entity Q3314483."',
  '      word "плод"',
  '        description "Russian noun (romanized plod) for fruit or produce; an alternative Russian surface for Wikidata entity Q3314483."',
  '    lexeme "hi"',
  '      word "फल"',
  '        description "Hindi noun (romanized phal) for fruit; the Hindi surface for Wikidata entity Q3314483."',
  '    lexeme "zh"',
  '      word "水果"',
  '        description "Chinese noun (pinyin shuiguo) for fruit; the Chinese surface for Wikidata entity Q3314483."',
  '      word "水果类"',
  '        description "Chinese noun (pinyin shuiguolei) for the fruit category; an alternative Chinese surface for Wikidata entity Q3314483."',
  '  meaning "wikidata_item_sorting_algorithm"',
  '    gloss "sorting algorithm (Wikidata Q181593); an algorithm that arranges the elements of a list into an order, a canonical class entity for reasoning examples. Rooted in the external Wikidata knowledge base through its language-independent Q-id."',
  '    wiktionary "sorting algorithm"',
  '    wikidata "Q181593"',
  '    defined_by "concept"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "sorting algorithm"',
  '        description "English compound noun for an algorithm that arranges elements into order; the canonical English label for Wikidata entity Q181593."',
  '      word "sorting algorithms"',
  '        description "English plural surface for sorting algorithm; an inflected surface for Wikidata entity Q181593."',
  '      word "sort algorithm"',
  '        description "English compound noun, a shorter synonym for sorting algorithm; an alternative surface for Wikidata entity Q181593."',
  '    lexeme "ru"',
  '      word "алгоритм сортировки"',
  '        description "Russian compound noun (romanized algoritm sortirovki) for sorting algorithm; the Russian surface for Wikidata entity Q181593."',
  '    lexeme "hi"',
  '      word "सॉर्टिंग एल्गोरिदम"',
  '        description "Hindi compound noun (romanized sorting elgoridam, a loan compound) for sorting algorithm; the Hindi surface for Wikidata entity Q181593."',
  '    lexeme "zh"',
  '      word "排序算法"',
  '        description "Chinese compound noun (pinyin paixu suanfa) for sorting algorithm; the Chinese surface for Wikidata entity Q181593."',
  '  meaning "wikidata_item_water"',
  '    gloss "water (Wikidata Q283); the chemical substance with formula H2O, used as a canonical concrete entity in formalization examples. Rooted in the external Wikidata knowledge base through its language-independent Q-id."',
  '    wiktionary "water"',
  '    wikidata "Q283"',
  '    defined_by "entity"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "water"',
  '        description "English noun for the substance H2O; the canonical English label for Wikidata entity Q283."',
  '    lexeme "ru"',
  '      word "вода"',
  '        description "Russian noun (romanized voda) for water; the Russian surface for Wikidata entity Q283."',
  '    lexeme "hi"',
  '      word "पानी"',
  '        description "Hindi noun (romanized pani) for water; the Hindi surface for Wikidata entity Q283."',
  '    lexeme "zh"',
  '      word "水"',
  '        description "Chinese noun (pinyin shui) for water; the Chinese surface for Wikidata entity Q283."',
  '  meaning "wikidata_item_bread"',
  '    gloss "bread (Wikidata Q7802); a staple food prepared by baking dough of flour and water, used as a canonical concrete entity in formalization examples. Rooted in the external Wikidata knowledge base through its language-independent Q-id."',
  '    wiktionary "bread"',
  '    wikidata "Q7802"',
  '    defined_by "entity"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "bread"',
  '        description "English noun for the baked staple food made from dough; the canonical English label for Wikidata entity Q7802."',
  '    lexeme "ru"',
  '      word "хлеб"',
  '        description "Russian noun (romanized khleb) for bread; the Russian surface for Wikidata entity Q7802."',
  '    lexeme "hi"',
  '      word "रोटी"',
  '        description "Hindi noun (romanized roti) for bread or flatbread; the Hindi surface for Wikidata entity Q7802."',
  '    lexeme "zh"',
  '      word "面包"',
  '        description "Chinese noun (pinyin mianbao, simplified) for bread; the Chinese surface for Wikidata entity Q7802."',
  '      word "麵包"',
  '        description "Chinese noun (pinyin mianbao, traditional) for bread; the traditional Chinese surface for Wikidata entity Q7802."',
  '  meaning "wikidata_item_carrot"',
  '    gloss "carrot (Wikidata Q81); the edible orange taproot of the carrot plant, used as a canonical concrete entity in formalization examples. Rooted in the external Wikidata knowledge base through its language-independent Q-id."',
  '    wiktionary "carrot"',
  '    wikidata "Q81"',
  '    defined_by "entity"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "carrot"',
  '        description "English noun for the edible orange taproot; the canonical English label for Wikidata entity Q81."',
  '      word "carrots"',
  '        description "English plural noun for carrot; an inflected surface for Wikidata entity Q81."',
  '    lexeme "ru"',
  '      word "морковь"',
  '        description "Russian noun (romanized morkov) for carrot; the Russian surface for Wikidata entity Q81."',
  '    lexeme "hi"',
  '      word "गाजर"',
  '        description "Hindi noun (romanized gajar) for carrot; the Hindi surface for Wikidata entity Q81."',
  '    lexeme "zh"',
  '      word "胡萝卜"',
  '        description "Chinese noun (pinyin huluobo, simplified) for carrot; the Chinese surface for Wikidata entity Q81."',
  '      word "胡蘿蔔"',
  '        description "Chinese noun (pinyin huluobo, traditional) for carrot; the traditional Chinese surface for Wikidata entity Q81."',
  '  meaning "wikidata_item_wikidata"',
  '    gloss "Wikidata (Wikidata Q2013); the free collaborative knowledge base of structured data, referenced as a knowledge-source entity in formalization. Rooted in the external Wikidata knowledge base through its own language-independent Q-id."',
  '    wiktionary "Wikidata"',
  '    wikidata "Q2013"',
  '    defined_by "entity"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "Wikidata"',
  '        description "English proper noun for the collaborative structured knowledge base; the canonical English label for Wikidata entity Q2013."',
  '    lexeme "ru"',
  '      word "викидата"',
  '        description "Russian proper noun (romanized vikidata) for Wikidata; the Russian surface for Wikidata entity Q2013."',
  '    lexeme "hi"',
  '      word "विकिडेटा"',
  '        description "Hindi proper noun (romanized vikideta) for Wikidata; the Hindi surface for Wikidata entity Q2013."',
  '    lexeme "zh"',
  '      word "维基数据"',
  '        description "Chinese proper noun (pinyin weiji shuju, simplified) for Wikidata; the Chinese surface for Wikidata entity Q2013."',
  '      word "維基數據"',
  '        description "Chinese proper noun (pinyin weiji shuju, traditional) for Wikidata; the traditional Chinese surface for Wikidata entity Q2013."',
  '  meaning "wikidata_item_wikipedia"',
  '    gloss "Wikipedia (Wikidata Q52); the free collaborative online encyclopedia, referenced as a knowledge-source entity in formalization. Rooted in the external Wikidata knowledge base through its language-independent Q-id."',
  '    wiktionary "Wikipedia"',
  '    wikidata "Q52"',
  '    defined_by "entity"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "Wikipedia"',
  '        description "English proper noun for the collaborative online encyclopedia; the canonical English label for Wikidata entity Q52."',
  '    lexeme "ru"',
  '      word "википедия"',
  '        description "Russian proper noun (romanized vikipediya) for Wikipedia; the Russian surface for Wikidata entity Q52."',
  '    lexeme "hi"',
  '      word "विकिपीडिया"',
  '        description "Hindi proper noun (romanized vikipidiya) for Wikipedia; the Hindi surface for Wikidata entity Q52."',
  '    lexeme "zh"',
  '      word "维基百科"',
  '        description "Chinese proper noun (pinyin weiji baike, simplified) for Wikipedia; the Chinese surface for Wikidata entity Q52."',
  '      word "維基百科"',
  '        description "Chinese proper noun (pinyin weiji baike, traditional) for Wikipedia; the traditional Chinese surface for Wikidata entity Q52."',
  '  meaning "wikidata_item_wiktionary"',
  '    gloss "Wiktionary (Wikidata Q151); the free collaborative multilingual dictionary, referenced as a knowledge-source entity in formalization. Rooted in the external Wikidata knowledge base through its language-independent Q-id."',
  '    wiktionary "Wiktionary"',
  '    wikidata "Q151"',
  '    defined_by "entity"',
  '    role "wikidata_entity_anchor"',
  '    lexeme "en"',
  '      word "Wiktionary"',
  '        description "English proper noun for the collaborative multilingual dictionary; the canonical English label for Wikidata entity Q151."',
  '    lexeme "ru"',
  '      word "викисловарь"',
  '        description "Russian proper noun (romanized vikislovar) for Wiktionary; the Russian surface for Wikidata entity Q151."',
  '    lexeme "hi"',
  '      word "विक्षनरी"',
  '        description "Hindi proper noun (romanized vikshanari) for Wiktionary; the Hindi surface for Wikidata entity Q151."',
  '    lexeme "zh"',
  '      word "维基词典"',
  '        description "Chinese proper noun (pinyin weiji cidian, simplified) for Wiktionary; the Chinese surface for Wikidata entity Q151."',
  '      word "維基辭典"',
  '        description "Chinese proper noun (pinyin weiji cidian, traditional) for Wiktionary; the traditional Chinese surface for Wikidata entity Q151."',
  '  meaning "wikidata_property_subclass_of"',
  '    gloss "subclass of (Wikidata property P279); relates a class to a broader class that includes it, the binary relation used when formalizing taxonomic prompts. Rooted in the external Wikidata knowledge base through its language-independent P-id."',
  '    wiktionary "subclass of"',
  '    wikidata "P279"',
  '    defined_by "relation"',
  '    role "binary_relation_property"',
  '    lexeme "en"',
  '      word "subclass of"',
  '        description "English relational phrase naming the subclass relation; the canonical English label for Wikidata property P279."',
  '      word "is a kind of"',
  '        description "English copular phrase asserting a subclass relation; a matching surface for Wikidata property P279."',
  '      word "is a type of"',
  '        description "English copular phrase asserting a subclass relation; a matching surface for Wikidata property P279."',
  '      word "is subclass of"',
  '        description "English relational phrase asserting a subclass relation; a matching surface for Wikidata property P279."',
  '      word "kind of"',
  '        description "English partitive phrase asserting a subclass relation; a matching surface for Wikidata property P279."',
  '      word "type of"',
  '        description "English partitive phrase asserting a subclass relation; a matching surface for Wikidata property P279."',
  '    lexeme "ru"',
  '      word "род"',
  '        description "Russian noun (romanized rod) for genus or kind, used for the subclass relation; a matching surface for Wikidata property P279."',
  '      word "тип"',
  '        description "Russian noun (romanized tip) for type, used for the subclass relation; a matching surface for Wikidata property P279."',
  '    lexeme "hi"',
  '      word "उपवर्ग"',
  '        description "Hindi noun (romanized upvarg) for subclass; the Hindi surface for Wikidata property P279."',
  '    lexeme "zh"',
  '      word "子类"',
  '        description "Chinese noun (pinyin zilei) for subclass; the Chinese surface for Wikidata property P279."',
  '  meaning "wikidata_property_instance_of"',
  '    gloss "instance of (Wikidata property P31); relates an individual to the class it is an instance of, the binary relation used when formalizing membership prompts. Rooted in the external Wikidata knowledge base through its language-independent P-id."',
  '    wiktionary "instance of"',
  '    wikidata "P31"',
  '    defined_by "relation"',
  '    role "binary_relation_property"',
  '    lexeme "en"',
  '      word "instance of"',
  '        description "English relational phrase naming the instance relation; the canonical English label for Wikidata property P31."',
  '      word "is a"',
  '        description "English copular phrase asserting class membership; a matching surface for Wikidata property P31, ambiguous with the subclass relation it also admits."',
  '        action "wikidata_property_subclass_of"',
  '      word "is an"',
  '        description "English copular phrase asserting class membership; a matching surface for Wikidata property P31, ambiguous with the subclass relation it also admits."',
  '        action "wikidata_property_subclass_of"',
  '      word "is the"',
  '        description "English copular phrase asserting identity or membership; a matching surface for Wikidata property P31."',
  '      word "are a"',
  '        description "English plural copular phrase asserting class membership; a matching surface for Wikidata property P31, ambiguous with the subclass relation it also admits."',
  '        action "wikidata_property_subclass_of"',
  '      word "are an"',
  '        description "English plural copular phrase asserting class membership; a matching surface for Wikidata property P31, ambiguous with the subclass relation it also admits."',
  '        action "wikidata_property_subclass_of"',
  '    lexeme "ru"',
  '      word "является"',
  '        description "Russian verb (romanized yavlyaetsya) for is or constitutes; a matching surface for Wikidata property P31."',
  '      word "это"',
  '        description "Russian pronoun-copula (romanized eto) for this is; a matching surface for Wikidata property P31."',
  '    lexeme "hi"',
  '      word "है"',
  '        description "Hindi verb (romanized hai) for is; a matching surface for Wikidata property P31."',
  '    lexeme "zh"',
  '      word "是"',
  '        description "Chinese verb (pinyin shi) for is; a matching surface for Wikidata property P31."',
  '  meaning "wikidata_property_part_of"',
  '    gloss "part of (Wikidata property P361); relates a part to the whole it belongs to, the binary relation used when formalizing meronymy prompts. Rooted in the external Wikidata knowledge base through its language-independent P-id."',
  '    wiktionary "part of"',
  '    wikidata "P361"',
  '    defined_by "relation"',
  '    role "binary_relation_property"',
  '    lexeme "en"',
  '      word "part of"',
  '        description "English relational phrase naming the part-of relation; the canonical English label for Wikidata property P361."',
  '      word "is part of"',
  '        description "English copular phrase asserting a part-of relation; a matching surface for Wikidata property P361."',
  '      word "belongs to"',
  '        description "English relational phrase asserting membership in a whole; a matching surface for Wikidata property P361."',
  '    lexeme "ru"',
  '      word "является частью"',
  '        description "Russian phrase (romanized yavlyaetsya chastyu) for is part of; a matching surface for Wikidata property P361."',
  '      word "часть"',
  '        description "Russian noun (romanized chast) for part; a matching surface for Wikidata property P361."',
  '    lexeme "hi"',
  '      word "का हिस्सा"',
  '        description "Hindi phrase (romanized ka hissa) for part of; the Hindi surface for Wikidata property P361."',
  '    lexeme "zh"',
  '      word "属于"',
  '        description "Chinese verb (pinyin shuyu) for belongs to; the Chinese surface for Wikidata property P361."',
  '  meaning "wikidata_property_has_part"',
  '    gloss "has part (Wikidata property P527); relates a whole to a part it contains, the binary relation used when formalizing holonymy prompts. Rooted in the external Wikidata knowledge base through its language-independent P-id."',
  '    wiktionary "has part"',
  '    wikidata "P527"',
  '    defined_by "relation"',
  '    role "binary_relation_property"',
  '    lexeme "en"',
  '      word "has part"',
  '        description "English relational phrase naming the has-part relation; the canonical English label for Wikidata property P527."',
  '      word "has a part"',
  '        description "English relational phrase asserting a has-part relation; a matching surface for Wikidata property P527."',
  '      word "contains"',
  '        description "English verb asserting that a whole includes a part; a matching surface for Wikidata property P527."',
  '      word "includes"',
  '        description "English verb asserting that a whole includes a part; a matching surface for Wikidata property P527."',
  '    lexeme "ru"',
  '      word "содержит"',
  '        description "Russian verb (romanized soderzhit) for contains; a matching surface for Wikidata property P527."',
  '    lexeme "hi"',
  '      word "शामिल है"',
  '        description "Hindi phrase (romanized shamil hai) for includes or contains; the Hindi surface for Wikidata property P527."',
  '    lexeme "zh"',
  '      word "包含"',
  '        description "Chinese verb (pinyin baohan) for contains or includes; the Chinese surface for Wikidata property P527."',
  '  meaning "wikidata_property_capital"',
  '    gloss "capital (Wikidata property P36); relates an administrative territory to its capital city, the binary relation used when formalizing capital-of prompts. Rooted in the external Wikidata knowledge base through its language-independent P-id."',
  '    wiktionary "capital"',
  '    wikidata "P36"',
  '    defined_by "relation"',
  '    role "binary_relation_property"',
  '    lexeme "en"',
  '      word "capital"',
  '        description "English noun naming the capital relation; the canonical English label for Wikidata property P36."',
  '      word "is the capital of"',
  '        description "English copular phrase asserting a capital-of relation; a matching surface for Wikidata property P36."',
  '      word "is capital of"',
  '        description "English copular phrase asserting a capital-of relation; a matching surface for Wikidata property P36."',
  '      word "capital of"',
  '        description "English relational phrase asserting a capital-of relation; a matching surface for Wikidata property P36."',
  '    lexeme "ru"',
  '      word "столица"',
  '        description "Russian noun (romanized stolitsa) for capital city; a matching surface for Wikidata property P36."',
  '    lexeme "hi"',
  '      word "राजधानी"',
  '        description "Hindi noun (romanized rajdhani) for capital city; the Hindi surface for Wikidata property P36."',
  '    lexeme "zh"',
  '      word "首都"',
  '        description "Chinese noun (pinyin shoudu) for capital city; the Chinese surface for Wikidata property P36."',
  '  meaning "wikidata_property_named_after"',
  '    gloss "named after (Wikidata property P138); relates an entity to the thing it is named after, the binary relation used when formalizing eponym prompts. Rooted in the external Wikidata knowledge base through its language-independent P-id."',
  '    wiktionary "named after"',
  '    wikidata "P138"',
  '    defined_by "relation"',
  '    role "binary_relation_property"',
  '    lexeme "en"',
  '      word "named after"',
  '        description "English relational phrase naming the named-after relation; the canonical English label for Wikidata property P138."',
  '      word "is named after"',
  '        description "English copular phrase asserting a named-after relation; a matching surface for Wikidata property P138."',
  '    lexeme "ru"',
  '      word "назван в честь"',
  '        description "Russian phrase (romanized nazvan v chest) for named in honor of; a matching surface for Wikidata property P138."',
  '    lexeme "hi"',
  '      word "के नाम पर"',
  '        description "Hindi phrase (romanized ke naam par) for named after; the Hindi surface for Wikidata property P138."',
  '    lexeme "zh"',
  '      word "命名自"',
  '        description "Chinese phrase (pinyin mingming zi) for named after; the Chinese surface for Wikidata property P138."',
  '  meaning "wikidata_property_translation"',
  '    gloss "translation (Wikidata property P5972); relates a lexeme sense to its translation in another language, the property an action prompt resolves to when asking to translate a term. Rooted in the external Wikidata knowledge base through its language-independent P-id."',
  '    wiktionary "translation"',
  '    wikidata "P5972"',
  '    defined_by "relation"',
  '    role "translation_property"',
  '    lexeme "en"',
  '      word "translation"',
  '        description "English noun naming the translation relation; the canonical English label for Wikidata property P5972."',
  '      word "translate"',
  '        description "English verb for rendering a term in another language; a coverage surface for Wikidata property P5972."',
  '      word "translates"',
  '        description "English verb (third person) for rendering a term in another language; a coverage surface for Wikidata property P5972."',
  '    lexeme "ru"',
  '      word "переведи"',
  '        description "Russian verb (romanized perevedi, imperative translate) for translation; a coverage surface for Wikidata property P5972."',
  '      word "перевести"',
  '        description "Russian verb (romanized perevesti, infinitive to translate) for translation; a coverage surface for Wikidata property P5972."',
  '    lexeme "hi"',
  '      word "अनुवाद"',
  '        description "Hindi noun (romanized anuvad) for translation; the Hindi surface for Wikidata property P5972."',
  '    lexeme "zh"',
  '      word "翻译"',
  '        description "Chinese verb (pinyin fanyi, simplified) for translate; the Chinese surface for Wikidata property P5972."',
  '      word "翻譯"',
  '        description "Chinese verb (pinyin fanyi, traditional) for translate; the traditional Chinese surface for Wikidata property P5972."',
  '  meaning "wikidata_property_item_for_this_sense"',
  '    gloss "item for this sense (Wikidata property P5137); relates a dictionary sense to the Wikidata item that captures its meaning, the binary relation used when formalizing means prompts. Rooted in the external Wikidata knowledge base through its language-independent P-id."',
  '    wiktionary "item for this sense"',
  '    wikidata "P5137"',
  '    defined_by "relation"',
  '    role "binary_relation_property"',
  '    lexeme "en"',
  '      word "item for this sense"',
  '        description "English relational phrase naming the item-for-this-sense relation; the canonical English label for Wikidata property P5137."',
  '      word "means"',
  '        description "English verb asserting that a term has a meaning; a matching surface for Wikidata property P5137."',
  '      word "meaning of"',
  '        description "English relational phrase asserting the meaning of a term; a matching surface for Wikidata property P5137."',
  '      word "meaning item"',
  '        description "English compound noun naming the item that captures a sense; a matching surface for Wikidata property P5137."',
  '      word "sense item"',
  '        description "English compound noun naming the item for a sense; a matching surface for Wikidata property P5137."',
  '    lexeme "ru"',
  '      word "означает"',
  '        description "Russian verb (romanized oznachaet) for means; a matching surface for Wikidata property P5137."',
  '    lexeme "hi"',
  '      word "अर्थ"',
  '        description "Hindi noun (romanized arth) for meaning; the Hindi surface for Wikidata property P5137."',
  '    lexeme "zh"',
  '      word "意思"',
  '        description "Chinese noun (pinyin yisi) for meaning; the Chinese surface for Wikidata property P5137."',
  "meanings",
  '  meaning "behavior_rule"',
  "    gloss \"the rule itself — a single When-X-then-Y conditional that governs how the assistant responds, the noun a listing request enumerates. It is both a relation (a condition mapped to a response) and part of the assistant's knowledge (its stored, chat-editable conduct), so it is defined_by both. A behavior-rules-list recogniser reads this role to decide the prompt names rules at all; on its own that is not enough — the request and scope roles must also be present, within one language, for the prompt to count as a list query. The surface forms are matched as raw substrings so an inflected stem catches its whole paradigm.\"",
  '    wiktionary "rule"',
  '    defined_by "relation"',
  '    defined_by "knowledge"',
  '    role "rule_listing_subject"',
  '    lexeme "en"',
  '      word "rules"',
  '        description "English plural noun (rules) naming the behavior rules to enumerate; matched as a raw substring."',
  '      word "rule list"',
  "        description \"English noun phrase (singular rule + list) so 'show my rule list' is recognised even though it lacks the plural 'rules'.\"",
  '      word "rules list"',
  '        description "English noun phrase (plural rules + list); explicit variant kept for parity with the singular form."',
  '    lexeme "ru"',
  '      word "правил"',
  '        description "Russian noun stem (romanized pravil, genitive plural of правило, rule); matched as a substring so it also catches правила/правилами."',
  '      word "правила"',
  '        description "Russian noun form (romanized pravila, nominative plural / genitive singular of правило, rule)."',
  '    lexeme "hi"',
  '      word "नियम"',
  '        description "Hindi noun (romanized niyam, rule); the bare stem, matched as a substring so it also catches inflections like नियमों."',
  '      word "नियमों"',
  '        description "Hindi oblique-plural noun (romanized niyamon, of rules)."',
  '    lexeme "zh"',
  '      word "规则"',
  '        description "Chinese noun (pinyin guize, rule) in simplified script."',
  '      word "規則"',
  '        description "Chinese noun (pinyin guize, rule) in traditional script."',
  '  meaning "rule_enumeration_request"',
  "    gloss \"the request to reveal the members of a set — either the imperative to list or show them, or the which/what interrogative that asks for them. It is an action (an enumerate operation) framed as an inquiry (a question put to the assistant), so it is defined_by both. Combined with the subject and scope roles it identifies a behavior-rules-list prompt; alone it is just a generic 'show me' verb. Imperatives and interrogatives are grouped here because both equally ask the assistant to enumerate the rule set.\"",
  '    wiktionary "list"',
  '    defined_by "action"',
  '    defined_by "inquiry"',
  '    role "rule_listing_request"',
  '    lexeme "en"',
  '      word "list"',
  "        description \"English verb (list) — the imperative to enumerate a set's members.\"",
  '      word "show"',
  "        description \"English verb (show) — the imperative to display a set's members.\"",
  '      word "what"',
  "        description \"English interrogative (what) opening a request for the members of a set ('what behavior rules…').\"",
  '      word "which"',
  "        description \"English interrogative (which) selecting among a set's members.\"",
  '    lexeme "ru"',
  '      word "список"',
  "        description \"Russian noun (romanized spisok, a list); used as the nominalised request 'give the list of …'.\"",
  '      word "перечисли"',
  '        description "Russian verb (romanized perechisli, enumerate, imperative) — list them one by one."',
  '      word "покажи"',
  '        description "Russian verb (romanized pokazhi, show, imperative)."',
  '      word "какие"',
  '        description "Russian interrogative (romanized kakiye, which / what kind) asking which members a set has."',
  '    lexeme "hi"',
  '      word "सूची"',
  '        description "Hindi noun (romanized suchi, a list)."',
  '      word "सूचीबद्ध"',
  "        description \"Hindi adjective/verb (romanized suchibaddh, listed / enumerated), as in 'list them'.\"",
  '      word "दिखाओ"',
  '        description "Hindi verb (romanized dikhao, show, informal imperative)."',
  '      word "दिखाएं"',
  '        description "Hindi verb (romanized dikhaen, show, polite imperative)."',
  '      word "बताओ"',
  '        description "Hindi verb (romanized batao, tell, imperative)."',
  '      word "गिनाओ"',
  '        description "Hindi verb (romanized ginao, enumerate / count off, imperative)."',
  '      word "कौन"',
  '        description "Hindi interrogative (romanized kaun, who / which) asking which members a set has."',
  '    lexeme "zh"',
  '      word "列出"',
  '        description "Chinese verb (pinyin liechu, list out)."',
  '      word "显示"',
  '        description "Chinese verb (pinyin xianshi, display) in simplified script."',
  '      word "顯示"',
  '        description "Chinese verb (pinyin xianshi, display) in traditional script."',
  '      word "展示"',
  '        description "Chinese verb (pinyin zhanshi, show / exhibit)."',
  '      word "哪些"',
  "        description \"Chinese interrogative (pinyin naxie, which ones) asking for a set's members.\"",
  '      word "什么"',
  '        description "Chinese interrogative (pinyin shenme, what)."',
  '  meaning "behavior_domain"',
  "    gloss \"the domain of conduct — behaviour itself, the dimension the rules govern. Naming it scopes a rules-listing request to the assistant's behaviour rather than some other rule set. It is a concept (an abstract domain) and a facet of the assistant's self (how it acts), so it is defined_by self_reference and concept. One of two meanings carrying the rule_listing_scope role; the other is assistant_own_ruleset. Surface forms match as raw substrings.\"",
  '    wiktionary "behavior"',
  '    defined_by "self_reference"',
  '    defined_by "concept"',
  '    role "rule_listing_scope"',
  '    lexeme "en"',
  '      word "behavior"',
  '        description "English noun (behavior, US spelling) naming the conduct that the rules govern."',
  '    lexeme "ru"',
  '      word "поведения"',
  '        description "Russian noun (romanized povedeniya, genitive of поведение, behaviour); the stem matched as a substring."',
  '    lexeme "hi"',
  '      word "व्यवहार"',
  '        description "Hindi noun (romanized vyavahar, behaviour / conduct)."',
  '    lexeme "zh"',
  '      word "行为"',
  '        description "Chinese noun (pinyin xingwei, behaviour) in simplified script."',
  '      word "行為"',
  '        description "Chinese noun (pinyin xingwei, behaviour) in traditional script."',
  '  meaning "assistant_own_ruleset"',
  "    gloss \"the requester pointing at the assistant's OWN, already-existing rule set — the second-person possessive (your), the reflexive own (own / собственные / 自己), the existence deixis (current / existing), and the bare rule-list compound that already names the set (список правил / नियमों की सूची / 规则列表). Any of these scopes a listing request to the assistant's stored rules. It is defined_by self_reference (it points back at the assistant) and knowledge (its existing set). The word set mirrors the recogniser exactly; the per-language cues are not parallel — only English carries a distinct current/existing deixis — so they are grouped here under the single notion of the assistant's own existing rules rather than split into meanings that some languages could not fill.\"",
  '    wiktionary "own"',
  '    defined_by "self_reference"',
  '    defined_by "knowledge"',
  '    role "rule_listing_scope"',
  '    lexeme "en"',
  '      word "your"',
  '        description "English second-person possessive (your) scoping the rules to the assistant addressed."',
  '      word "own"',
  "        description \"English reflexive determiner (own), as in 'your own rules'.\"",
  '      word "current"',
  '        description "English deictic adjective (current) selecting the rules in force now."',
  '      word "existing"',
  '        description "English participial adjective (existing) selecting the rules that already exist."',
  '    lexeme "ru"',
  '      word "свои"',
  "        description \"Russian reflexive possessive (romanized svoi, one's own, nominative plural).\"",
  '      word "своих"',
  "        description \"Russian reflexive possessive (romanized svoikh, one's own, genitive / prepositional plural).\"",
  '      word "твои"',
  '        description "Russian second-person possessive (romanized tvoi, your, nominative plural, informal)."',
  '      word "твоих"',
  '        description "Russian second-person possessive (romanized tvoikh, your, genitive / prepositional plural, informal)."',
  '      word "собственные"',
  '        description "Russian adjective (romanized sobstvennye, own / proper, plural)."',
  '      word "список правил"',
  '        description "Russian noun phrase (romanized spisok pravil, list of rules) — the bare compound that already names the set, so it scopes the request by itself."',
  '    lexeme "hi"',
  '      word "अपने"',
  "        description \"Hindi reflexive possessive (romanized apne, one's own, oblique / plural).\"",
  '      word "तुम्हारे"',
  '        description "Hindi second-person possessive (romanized tumhare, your, informal plural)."',
  '      word "आपके"',
  '        description "Hindi second-person possessive (romanized aapke, your, polite)."',
  '      word "नियमों की सूची"',
  '        description "Hindi noun phrase (romanized niyamon ki suchi, list of rules) — the compound that already names the set."',
  '    lexeme "zh"',
  '      word "你的"',
  '        description "Chinese second-person possessive (pinyin nide, your, informal)."',
  '      word "您的"',
  '        description "Chinese second-person possessive (pinyin ninde, your, polite)."',
  '      word "自己"',
  '        description "Chinese reflexive (pinyin ziji, oneself / own)."',
  '      word "规则列表"',
  '        description "Chinese noun phrase (pinyin guize liebiao, rule list) in simplified script — the compound that already names the set."',
  '      word "規則列表"',
  '        description "Chinese noun phrase (pinyin guize liebiao, rule list) in traditional script."',
  '  meaning "behavior_rule_set_phrase"',
  "    gloss \"fixed multi-word phrases that directly name the assistant's behavior-rule set and are recognised as a list request even without a separate enumerate verb — most importantly the bare compound 'behavior rules' / 行为规则 / व्यवहार के नियम, where the noun phrase alone is a standing request to see the catalogue. The verbed variants (list / show … behavior rules) are kept so the phrase set matches the prior hand-listed recogniser exactly and stays symmetric across the supported languages, even though most of them are also reachable by composing the subject, request, and scope roles. Defined_by inquiry (each phrase is itself a request) and knowledge (it names the stored rule set). Matched as raw substrings.\"",
  '    wiktionary "rule"',
  '    defined_by "inquiry"',
  '    defined_by "knowledge"',
  '    role "rule_listing_phrase"',
  '    lexeme "en"',
  '      word "list behavior rules"',
  '        description "English imperative phrase requesting the behavior-rule catalogue."',
  '      word "list all behavior rules"',
  "        description \"English imperative phrase (with 'all') requesting the entire behavior-rule catalogue.\"",
  '      word "show behavior rules"',
  '        description "English imperative phrase requesting display of the behavior rules."',
  '      word "show all behavior rules"',
  "        description \"English imperative phrase (with 'all') requesting display of every behavior rule.\"",
  '      word "what behavior rules"',
  '        description "English interrogative phrase asking which behavior rules exist."',
  '      word "existing behavior rules"',
  '        description "English noun phrase naming the behavior rules already in force; recognised as a standing request to list them even without an enumerate verb."',
  '    lexeme "ru"',
  '      word "список правил поведения"',
  '        description "Russian noun phrase (romanized spisok pravil povedeniya, list of behavior rules)."',
  '      word "покажи правила поведения"',
  '        description "Russian imperative phrase (romanized pokazhi pravila povedeniya, show the behavior rules)."',
  '      word "какие правила поведения"',
  '        description "Russian interrogative phrase (romanized kakiye pravila povedeniya, which behavior rules)."',
  '    lexeme "hi"',
  '      word "व्यवहार के नियम"',
  '        description "Hindi noun phrase (romanized vyavahar ke niyam, rules of behaviour) — the bare compound recognised as a standing list request."',
  '      word "व्यवहार नियम सूचीबद्ध करें"',
  '        description "Hindi imperative phrase (romanized vyavahar niyam suchibaddh karen, list the behavior rules)."',
  '    lexeme "zh"',
  '      word "行为规则"',
  '        description "Chinese noun phrase (pinyin xingwei guize, behavior rules) — the bare compound recognised as a standing list request."',
  '      word "列出行为规则"',
  '        description "Chinese imperative phrase (pinyin liechu xingwei guize, list the behavior rules)."',
  "meanings",
  '  meaning "prove"',
  '    gloss "the act of establishing a claim by formal argument — to prove, to demonstrate, or to give a proof. It is both an inquiry (the user asks the assistant to settle a truth) and an action (the assistant carries out a proof). Two roles share this meaning, separated by slot. The proof_directive bare forms are the imperative verbs (prove, докажи, …) detected clause-initially with a verb boundary, so prover and proven never false-match. The proof_claim_scaffold prefix forms end in … and are stripped to extract the claim the user wants proved; their declaration order is significant because the extractor takes the first matching prefix, so each that variant is listed before its shorter sibling. Hindi and Chinese carry no bare directive — their proof is detected by the proof_assertion substring markers — but they still carry claim scaffolds so extraction works in every language."',
  '    wiktionary "prove"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "proof_directive"',
  '    role "proof_claim_scaffold"',
  '    lexeme "en"',
  '      word "prove"',
  '        description "English verb (to prove); a bare proof directive detected clause-initially with a verb boundary so prover and proven do not match."',
  '      word "proof"',
  '        description "English noun (a proof); a bare proof directive detected clause-initially with a verb boundary."',
  '      word "prove that …"',
  '        description "English scaffold prefix; the claim follows prove that, listed before the shorter prove so that is not kept in the claim."',
  '      word "prove …"',
  '        description "English scaffold prefix; the claim follows the bare verb prove."',
  '      word "proof of …"',
  '        description "English scaffold prefix; the claim follows proof of."',
  '      word "proof that …"',
  '        description "English scaffold prefix; the claim follows proof that."',
  '      word "show that …"',
  '        description "English scaffold prefix; the claim follows show that."',
  '      word "demonstrate that …"',
  '        description "English scaffold prefix; the claim follows demonstrate that, listed before the shorter demonstrate."',
  '      word "demonstrate …"',
  '        description "English scaffold prefix; the claim follows the bare verb demonstrate."',
  '      word "can you prove that …"',
  '        description "English polite scaffold prefix; the claim follows can you prove that, listed before the shorter can you prove."',
  '      word "can you prove …"',
  '        description "English polite scaffold prefix; the claim follows can you prove."',
  '      word "could you prove that …"',
  '        description "English polite scaffold prefix; the claim follows could you prove that, before the shorter could you prove."',
  '      word "could you prove …"',
  '        description "English polite scaffold prefix; the claim follows could you prove."',
  '      word "please prove that …"',
  '        description "English polite scaffold prefix; the claim follows please prove that, before the shorter please prove."',
  '      word "please prove …"',
  '        description "English polite scaffold prefix; the claim follows please prove."',
  '      word "give me a proof of …"',
  '        description "English scaffold prefix; the claim follows give me a proof of."',
  '      word "give me a proof that …"',
  '        description "English scaffold prefix; the claim follows give me a proof that."',
  '      word "give a proof of …"',
  '        description "English scaffold prefix; the claim follows give a proof of."',
  '      word "give a proof that …"',
  '        description "English scaffold prefix; the claim follows give a proof that."',
  '    lexeme "ru"',
  '      word "докажи"',
  '        description "Russian imperative (romanized dokazhi, prove); a bare proof directive detected clause-initially with a verb boundary."',
  '      word "докажите"',
  '        description "Russian polite imperative (romanized dokazhite, prove); a bare proof directive detected clause-initially."',
  '      word "доказать"',
  '        description "Russian infinitive (romanized dokazat, to prove); a bare proof directive detected clause-initially."',
  '      word "доказательство"',
  '        description "Russian noun (romanized dokazatelstvo, a proof); a bare proof directive detected clause-initially."',
  '      word "докажи что …"',
  '        description "Russian scaffold prefix (romanized dokazhi chto); the claim follows, listed before the shorter докажи."',
  '      word "докажите что …"',
  '        description "Russian scaffold prefix (romanized dokazhite chto); the claim follows, listed before the shorter докажите."',
  '      word "доказать что …"',
  '        description "Russian scaffold prefix (romanized dokazat chto); the claim follows, listed before the shorter доказать."',
  '      word "докажите …"',
  '        description "Russian scaffold prefix (romanized dokazhite); the claim follows the polite imperative."',
  '      word "докажи …"',
  '        description "Russian scaffold prefix (romanized dokazhi); the claim follows the imperative."',
  '      word "доказать …"',
  '        description "Russian scaffold prefix (romanized dokazat); the claim follows the infinitive."',
  '      word "доказательство …"',
  '        description "Russian scaffold prefix (romanized dokazatelstvo); the claim follows the noun."',
  '    lexeme "hi"',
  '      word "साबित करो कि …"',
  '        description "Hindi scaffold prefix (romanized sabit karo ki); the claim follows."',
  '      word "साबित कीजिए कि …"',
  '        description "Hindi polite scaffold prefix (romanized sabit kijie ki); the claim follows."',
  '      word "साबित कर …"',
  '        description "Hindi scaffold prefix (romanized sabit kar); the claim follows the bare verb."',
  '      word "सिद्ध कीजिए कि …"',
  '        description "Hindi polite scaffold prefix (romanized siddh kijie ki); the claim follows."',
  '      word "सिद्ध करो कि …"',
  '        description "Hindi scaffold prefix (romanized siddh karo ki); the claim follows."',
  '    lexeme "zh"',
  '      word "证明…"',
  '        description "Chinese verb (pinyin zhengming, to prove) in simplified script; scaffold prefix, the claim follows."',
  '      word "證明…"',
  '        description "Chinese verb (pinyin zhengming, to prove) in traditional script; scaffold prefix, the claim follows."',
  '  meaning "proof_request_frame"',
  '    gloss "a broad request frame that asks for a proof without naming the claim with a that clause — can you prove, please prove, give me a proof, show that, demonstrate that, and their counterparts in every supported language. These leads are detected by a plain starts_with (no verb boundary, no claim extraction), so a prompt like can you prove the riemann hypothesis is recognised even though it carries no that. The Russian, Hindi and Chinese leads each embed a proof_assertion marker (доказать, सिद्ध, 证明, …), so a prompt that opens with one is already caught by that mid-prompt marker; they are lexicalised here too so the request-frame concept is complete in every language and so a lead that carries no claim is still recognised. In English the assertion markers cover only prove that and proof of, so the English leads are the sole surface that recognises a polite request such as can you prove the riemann hypothesis."',
  '    wiktionary "proof"',
  '    defined_by "inquiry"',
  '    defined_by "prove"',
  '    role "proof_request_lead"',
  '    lexeme "en"',
  '      word "can you prove…"',
  '        description "English request-frame lead; starts_with can you prove (no trailing space) so it also fires without a following that."',
  '      word "could you prove…"',
  '        description "English request-frame lead; starts_with could you prove (no trailing space)."',
  '      word "please prove…"',
  '        description "English request-frame lead; starts_with please prove (no trailing space)."',
  '      word "give me a proof…"',
  '        description "English request-frame lead; starts_with give me a proof (no trailing space)."',
  '      word "give a proof…"',
  '        description "English request-frame lead; starts_with give a proof (no trailing space)."',
  '      word "show that …"',
  '        description "English request-frame lead; starts_with show that (with a trailing space)."',
  '      word "demonstrate that …"',
  '        description "English request-frame lead; starts_with demonstrate that (with a trailing space)."',
  '    lexeme "ru"',
  '      word "можешь доказать…"',
  '        description "Russian polite request-frame lead (romanized mozhesh dokazat, can you prove); starts_with можешь доказать and embeds the доказать assertion marker."',
  '      word "можете доказать…"',
  '        description "Russian polite request-frame lead (romanized mozhete dokazat, can you prove); starts_with можете доказать and embeds the доказать assertion marker."',
  '      word "сможешь доказать…"',
  '        description "Russian polite request-frame lead (romanized smozhesh dokazat, could you prove); starts_with сможешь доказать and embeds the доказать assertion marker."',
  '      word "пожалуйста докажи…"',
  '        description "Russian polite request-frame lead (romanized pozhaluysta dokazhi, please prove); starts_with пожалуйста докажи and embeds the докажи assertion marker."',
  '      word "пожалуйста докажите…"',
  '        description "Russian polite request-frame lead (romanized pozhaluysta dokazhite, please prove); starts_with пожалуйста докажите and embeds the докажите assertion marker."',
  '    lexeme "hi"',
  '      word "क्या आप साबित कर सकते हैं…"',
  '        description "Hindi polite request-frame lead (romanized kya aap sabit kar sakte hain, can you prove); starts_with the phrase and embeds the साबित कर assertion marker."',
  '      word "क्या आप सिद्ध कर सकते हैं…"',
  '        description "Hindi polite request-frame lead (romanized kya aap siddh kar sakte hain, can you prove); starts_with the phrase and embeds the सिद्ध कर assertion marker."',
  '      word "कृपया सिद्ध कीजिए…"',
  '        description "Hindi polite request-frame lead (romanized kripya siddh kijie, please prove); starts_with the phrase and embeds the सिद्ध कीजिए assertion marker."',
  '      word "कृपया साबित कीजिए…"',
  '        description "Hindi polite request-frame lead (romanized kripya sabit kijie, please prove); starts_with the phrase and embeds the साबित कीजिए assertion marker."',
  '    lexeme "zh"',
  '      word "你能证明…"',
  '        description "Chinese polite request-frame lead (pinyin ni neng zhengming, can you prove) in simplified script; starts_with 你能证明 and embeds the 证明 assertion marker."',
  '      word "你能證明…"',
  '        description "Chinese polite request-frame lead (pinyin ni neng zhengming, can you prove) in traditional script; starts_with 你能證明 and embeds the 證明 assertion marker."',
  '      word "请证明…"',
  '        description "Chinese polite request-frame lead (pinyin qing zhengming, please prove) in simplified script; starts_with 请证明 and embeds the 证明 assertion marker."',
  '      word "請證明…"',
  '        description "Chinese polite request-frame lead (pinyin qing zhengming, please prove) in traditional script; starts_with 請證明 and embeds the 證明 assertion marker."',
  '  meaning "proof_assertion"',
  '    gloss "a proof verb or noun appearing anywhere inside a prompt, not just clause-initially — the mid-sentence assertion that a proof is wanted. Its surfaces are matched as raw substrings (not whole tokens), so the English and Russian forms are stored space-wrapped to enforce a word boundary while the Devanagari and Han forms match bare. The four Russian markers (докажи, докажите, доказать, доказательство) keep the Rust solver and the browser worker in lockstep."',
  '    wiktionary "proof"',
  '    defined_by "inquiry"',
  '    defined_by "prove"',
  '    role "proof_marker"',
  '    lexeme "en"',
  '      word " prove that "',
  '        description "English space-wrapped substring marker; a proof assertion appearing mid-prompt (… prove that …)."',
  '      word " proof of "',
  '        description "English space-wrapped substring marker; a proof assertion appearing mid-prompt (… proof of …)."',
  '    lexeme "ru"',
  '      word " докажи "',
  '        description "Russian space-wrapped substring marker (romanized dokazhi); a proof assertion mid-prompt."',
  '      word " докажите "',
  '        description "Russian space-wrapped substring marker (romanized dokazhite); a proof assertion mid-prompt."',
  '      word " доказать "',
  '        description "Russian space-wrapped substring marker (romanized dokazat); a proof assertion mid-prompt."',
  '      word " доказательство "',
  '        description "Russian space-wrapped substring marker (romanized dokazatelstvo); a proof assertion mid-prompt."',
  '    lexeme "hi"',
  '      word "साबित कर"',
  '        description "Hindi substring marker (romanized sabit kar, prove) matched bare across inflections."',
  '      word "साबित कीजिए"',
  '        description "Hindi polite substring marker (romanized sabit kijie, prove)."',
  '      word "साबित कीजिये"',
  '        description "Hindi polite substring marker (romanized sabit kijiye, prove), alternate spelling."',
  '      word "सिद्ध कर"',
  '        description "Hindi substring marker (romanized siddh kar, prove)."',
  '      word "सिद्ध कीजिए"',
  '        description "Hindi polite substring marker (romanized siddh kijie, prove)."',
  '      word "सिद्ध कीजिये"',
  '        description "Hindi polite substring marker (romanized siddh kijiye, prove), alternate spelling."',
  '      word "प्रमाण"',
  '        description "Hindi noun (romanized praman, proof) matched as a bare substring."',
  '    lexeme "zh"',
  '      word "证明"',
  '        description "Chinese verb (pinyin zhengming, to prove) in simplified script, matched as a bare substring."',
  '      word "證明"',
  '        description "Chinese verb (pinyin zhengming, to prove) in traditional script, matched as a bare substring."',
  '  meaning "godel"',
  '    gloss "the surname Gödel (Kurt Gödel) and his incompleteness theorems, named inside a proof prompt. When present, the proof engine selects the incompleteness interpretation. Its surfaces are bare substring markers read by the Rust solver; the browser worker embeds the same data but its simpler proof engine does not branch on it."',
  '    wiktionary "Gödel"',
  '    defined_by "concept"',
  '    role "proof_concept_godel"',
  '    lexeme "en"',
  '      word "godel"',
  '        description "English transliteration of the surname Gödel; a bare substring marker steering the proof toward incompleteness."',
  '      word "gödel"',
  '        description "Umlaut spelling of the surname Gödel; a bare substring marker for the incompleteness concept."',
  '    lexeme "ru"',
  '      word "гёдел"',
  '        description "Russian transliteration (romanized gyodel) of the surname Gödel; a bare substring marker."',
  '      word "гёделя"',
  '        description "Russian genitive (romanized gyodelya) of the surname Gödel; a bare substring marker."',
  '      word "гедел"',
  '        description "Russian transliteration without yo (romanized gedel) of the surname Gödel; a bare substring marker."',
  '    lexeme "hi"',
  '      word "गोडेल"',
  '        description "Hindi transliteration (romanized godel) of the surname Gödel; a bare substring marker."',
  '    lexeme "zh"',
  '      word "哥德尔"',
  '        description "Chinese transliteration (pinyin gedeer) of the surname Gödel; a bare substring marker."',
  '  meaning "determinism"',
  '    gloss "the concept of determinism — that every state is fixed by prior causes — named inside a proof prompt. When present, the proof engine selects the determinism interpretation. Its surfaces are bare substring markers read by the Rust solver; the browser worker embeds the same data but its simpler proof engine does not branch on it."',
  '    wiktionary "determinism"',
  '    defined_by "concept"',
  '    role "proof_concept_determinism"',
  '    lexeme "en"',
  '      word "determinism"',
  '        description "English noun for determinism; a bare substring marker steering the proof toward the determinism interpretation."',
  '      word "deterministic"',
  '        description "English adjective (deterministic); a bare substring marker for the determinism concept."',
  '    lexeme "ru"',
  '      word "детерминизм"',
  '        description "Russian noun (romanized determinizm) for determinism; a bare substring marker."',
  '    lexeme "hi"',
  '      word "निर्धारणवाद"',
  '        description "Hindi noun (romanized nirdharanvad) for determinism; a bare substring marker."',
  '    lexeme "zh"',
  '      word "决定论"',
  '        description "Chinese noun (pinyin juedinglun) for determinism; a bare substring marker."',
  "meanings",
  '  meaning "physical_action_query"',
  '    gloss "a question that asks whether the assistant performed a bodily action it cannot perform, because the assistant has no physical body. The physical_action_trigger forms are crude taunts matched as raw substrings, so recognition is language-independent and tolerant of inflection. Content-policy screening runs before this handler, so any surface that is also flagged as vulgar content is refused first; a surface that passes screening receives a factual reply stating the assistant has no physical body, localized to the language of the prompt. The Russian forms are inflections of the verb сосать; the other supported languages carry an equivalent interrogative so the concept is lexicalized everywhere."',
  '    wiktionary "body"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "physical_action_trigger"',
  '    lexeme "en"',
  '      word "did you suck"',
  '        description "English interrogative; it contains the vulgar marker you suck, so content-policy screening refuses it before this handler runs and it never reaches the factual reply."',
  '    lexeme "ru"',
  '      word "сосал"',
  '        description "Russian past-tense masculine (romanized sosal, sucked); a physical_action_trigger matched as a raw substring."',
  '      word "сосала"',
  '        description "Russian past-tense feminine (romanized sosala, sucked); a physical_action_trigger matched as a raw substring."',
  '      word "сосёшь"',
  '        description "Russian second-person present (romanized sosyosh, you suck); a physical_action_trigger matched as a raw substring."',
  '      word "соси"',
  '        description "Russian imperative (romanized sosi, suck); a physical_action_trigger matched as a raw substring."',
  '      word "сосать"',
  '        description "Russian infinitive (romanized sosat, to suck); a physical_action_trigger matched as a raw substring."',
  '    lexeme "hi"',
  '      word "क्या तुमने चूसा"',
  '        description "Hindi interrogative (romanized kya tumne chusa, did you suck); a physical_action_trigger matched as a raw substring."',
  '    lexeme "zh"',
  '      word "你吸了吗"',
  '        description "Chinese interrogative (pinyin ni xi le ma, did you suck); a physical_action_trigger matched as a raw substring."',
  '  meaning "circular_joke_idiom"',
  "    gloss \"«Купи слона» — a well-known Russian children's circular-joke idiom. The game works by repetition: whatever the listener replies, the speaker answers everyone says that, but you buy an elephant!, and the traditional winning reply is everyone has an elephant, but I do not. The circular_joke_phrase forms are matched as raw substrings so the assistant recognises the idiom instead of letting it fall through to an unknown prompt, and the localized reply explains the game in the language of the prompt. The phrase is lexicalized in every supported language as the calque buy an elephant.\"",
  '    wiktionary "elephant"',
  '    defined_by "inquiry"',
  '    defined_by "concept"',
  '    role "circular_joke_phrase"',
  '    lexeme "en"',
  '      word "buy an elephant"',
  '        description "English calque of the Russian idiom; the concept lexicalized in English, matched as a raw substring."',
  '    lexeme "ru"',
  '      word "купи слона"',
  '        description "Russian imperative phrase (romanized kupi slona, buy an elephant); the opening line of the circular-joke game, matched as a raw substring."',
  '    lexeme "hi"',
  '      word "हाथी खरीदो"',
  '        description "Hindi calque (romanized haathi khareedo, buy an elephant); the concept lexicalized in Hindi, matched as a raw substring."',
  '    lexeme "zh"',
  '      word "买大象"',
  '        description "Chinese calque (pinyin mai daxiang, buy an elephant); the concept lexicalized in Chinese, matched as a raw substring."',
  '  meaning "vulgar_content"',
  '    gloss "a marker that a message contains vulgar or obscene language, which the assistant refuses with a polite content-policy reply before any other handler runs. The vulgar_content_marker forms are profanities and slurs matched as raw substrings, so screening is language-independent and tolerant of inflection: the English and Russian forms are migrated verbatim from the original hardcoded lists, and Hindi and Chinese carry equivalent obscenities so the concept is lexicalized in every supported language. A surface that is also a physical_action_trigger is therefore refused here first, which is why «did you suck» never reaches the factual physical-action reply."',
  '    wiktionary "profanity"',
  '    defined_by "concept"',
  '    role "vulgar_content_marker"',
  '    lexeme "en"',
  '      word "fuck you"',
  '        description "English profanity directed at the listener; a vulgar_content_marker matched as a raw substring."',
  '      word "fuckyou"',
  '        description "English profanity directed at the listener, written without a space; a vulgar_content_marker matched as a raw substring."',
  '      word "suck my"',
  '        description "English crude imperative fragment; a vulgar_content_marker matched as a raw substring so any completion is caught."',
  '      word "suck my dick"',
  '        description "English crude imperative; a vulgar_content_marker matched as a raw substring."',
  '      word "suck my cock"',
  '        description "English crude imperative; a vulgar_content_marker matched as a raw substring."',
  '      word "you suck"',
  '        description "English derogatory taunt; a vulgar_content_marker matched as a raw substring, which is why «did you suck» is refused before the physical-action handler runs."',
  '      word "eat shit"',
  '        description "English crude insult; a vulgar_content_marker matched as a raw substring."',
  '      word "go to hell"',
  '        description "English hostile dismissal; a vulgar_content_marker matched as a raw substring."',
  '      word "asshole"',
  '        description "English vulgar insult; a vulgar_content_marker matched as a raw substring."',
  '      word "motherfucker"',
  '        description "English vulgar insult; a vulgar_content_marker matched as a raw substring."',
  '      word "you fucking"',
  '        description "English profane intensifier aimed at the listener; a vulgar_content_marker matched as a raw substring."',
  '      word "piece of shit"',
  '        description "English vulgar insult; a vulgar_content_marker matched as a raw substring."',
  '    lexeme "ru"',
  '      word "ебать"',
  '        description "Russian obscenity (romanized ebat, the infinitive to fuck); a vulgar_content_marker matched as a raw substring."',
  '      word "ебёт"',
  '        description "Russian obscenity (romanized ebyot, third-person fucks); a vulgar_content_marker matched as a raw substring."',
  '      word "ебал"',
  '        description "Russian obscenity (romanized ebal, past-tense fucked); a vulgar_content_marker matched as a raw substring."',
  '      word "ёб"',
  '        description "Russian obscenity (romanized yob, a short past-tense expletive); a vulgar_content_marker matched as a raw substring."',
  '      word "еблан"',
  '        description "Russian vulgar insult (romanized eblan, idiot); a vulgar_content_marker matched as a raw substring."',
  '      word "пизда"',
  '        description "Russian obscenity (romanized pizda, cunt); a vulgar_content_marker matched as a raw substring."',
  '      word "пиздец"',
  '        description "Russian obscenity (romanized pizdets, an expletive for a disastrous situation); a vulgar_content_marker matched as a raw substring."',
  '      word "пиздёж"',
  '        description "Russian obscenity (romanized pizdyozh, bullshit); a vulgar_content_marker matched as a raw substring."',
  '      word "хуй"',
  '        description "Russian obscenity (romanized khuy, dick); a vulgar_content_marker matched as a raw substring."',
  '      word "хуёв"',
  '        description "Russian obscenity (romanized khuyov, the genitive plural of dick); a vulgar_content_marker matched as a raw substring."',
  '      word "хуйня"',
  '        description "Russian obscenity (romanized khuynya, nonsense or crap); a vulgar_content_marker matched as a raw substring."',
  '      word "блядь"',
  '        description "Russian obscenity (romanized blyad, whore or damn); a vulgar_content_marker matched as a raw substring."',
  '      word "блядство"',
  '        description "Russian obscenity (romanized blyadstvo, debauchery); a vulgar_content_marker matched as a raw substring."',
  '      word "залупа"',
  '        description "Russian vulgar insult (romanized zalupa, glans, used as a crude insult); a vulgar_content_marker matched as a raw substring."',
  '      word "мудак"',
  '        description "Russian vulgar insult (romanized mudak, asshole); a vulgar_content_marker matched as a raw substring."',
  '      word "мудила"',
  '        description "Russian vulgar insult (romanized mudila, asshole or jerk); a vulgar_content_marker matched as a raw substring."',
  '      word "шлюха"',
  '        description "Russian derogatory term (romanized shlyukha, slut); a vulgar_content_marker matched as a raw substring."',
  '      word "проститутка"',
  '        description "Russian term (romanized prostitutka, prostitute) used here as a derogatory insult; a vulgar_content_marker matched as a raw substring."',
  '      word "ублюдок"',
  '        description "Russian vulgar insult (romanized ublyudok, bastard); a vulgar_content_marker matched as a raw substring."',
  '      word "сука"',
  '        description "Russian vulgar insult (romanized suka, bitch); a vulgar_content_marker matched as a raw substring."',
  '      word "пидор"',
  '        description "Russian homophobic slur (romanized pidor); a vulgar_content_marker matched as a raw substring."',
  '      word "пидорас"',
  '        description "Russian homophobic slur (romanized pidoras); a vulgar_content_marker matched as a raw substring."',
  '    lexeme "hi"',
  '      word "मादरचोद"',
  '        description "Hindi obscenity (romanized madarchod, motherfucker); a vulgar_content_marker matched as a raw substring."',
  '      word "बहनचोद"',
  '        description "Hindi obscenity (romanized behenchod, a vulgar insult); a vulgar_content_marker matched as a raw substring."',
  '    lexeme "zh"',
  '      word "操你妈"',
  "        description \"Chinese obscenity (pinyin cao ni ma, a vulgar insult aimed at the listener's mother); a vulgar_content_marker matched as a raw substring.\"",
  '      word "傻逼"',
  '        description "Chinese vulgar insult (pinyin sha bi); a vulgar_content_marker matched as a raw substring."',
  "meanings",
  '  meaning "explanation_request"',
  '    gloss "a request to have something explained — to be told how it works, what it is, or what it does. The concept an explanation prompt expresses, independent of the language or exact phrasing. Each lead marks the subject position with the ellipsis … (U+2026): a trailing ellipsis is a prefix surface matched against the start of the prompt by the literal before the slot, while a surface with no ellipsis is a bare phrase matched anywhere as a raw substring. A bare phrase written with surrounding spaces matches only on whole-word boundaries; one written without them folds its inflections. No interrogative word is named in the consuming code; every lead lives here in the data."',
  '    wiktionary "explain"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "explanation_request_lead"',
  '    lexeme "en"',
  '      word "how …"',
  '        description "English prefix surface asking how something works or is done; matched by the literal how before the … slot at the start of the prompt."',
  '      word " how "',
  '        description "English bare interrogative how, space-wrapped so it matches only as a whole word anywhere inside the prompt."',
  '      word "explain …"',
  '        description "English prefix surface; the imperative explain leads a request to explain whatever follows the … slot."',
  '      word "describe …"',
  '        description "English prefix surface; the imperative describe leads a request to describe whatever follows the … slot."',
  '      word "what does …"',
  '        description "English prefix surface; the question what does leads an explanation request whose subject follows the … slot."',
  '      word "what is …"',
  '        description "English prefix surface; the question what is leads a definition request whose subject follows the … slot."',
  '      word "tell me about …"',
  '        description "English prefix surface; tell me about leads a request to explain the subject after the … slot."',
  '      word "how to use …"',
  '        description "English prefix surface; how to use leads a usage question whose subject follows the … slot, subsumed by the bare how lead but kept for the explicit usage phrasing."',
  '    lexeme "ru"',
  '      word "как …"',
  '        description "Russian prefix surface (romanized kak); the interrogative how leads an explanation request whose subject follows the … slot."',
  '      word " как "',
  '        description "Russian bare interrogative how (romanized kak), space-wrapped so it matches only as a whole word anywhere inside the prompt."',
  '      word "объясни …"',
  '        description "Russian prefix surface (romanized obyasni); the imperative explain leads a request to explain whatever follows the … slot."',
  '      word "расскажи …"',
  '        description "Russian prefix surface (romanized rasskazhi); the imperative tell leads a request to describe whatever follows the … slot."',
  '      word "что такое …"',
  '        description "Russian prefix surface (romanized chto takoe); the question what is leads a definition request whose subject follows the … slot."',
  '    lexeme "hi"',
  '      word "कैसे काम"',
  '        description "Hindi phrase (romanized kaise kaam, how it works) as a bare substring marking a how-it-works explanation request."',
  '      word "समझाओ…"',
  '        description "Hindi prefix surface (romanized samjhao, explain) matched by its literal start with no space before the … slot; the subject follows."',
  '      word "क्या है …"',
  '        description "Hindi prefix surface (romanized kya hai, what is) matched at the start of the prompt; the subject follows the … slot."',
  '    lexeme "zh"',
  '      word "如何工作"',
  '        description "Chinese phrase (pinyin ruhe gongzuo, how it works) as a bare substring marking a how-it-works explanation request."',
  '      word "怎么工作"',
  '        description "Chinese phrase (pinyin zenme gongzuo, how it works) as a bare substring marking a how-it-works explanation request."',
  '      word "解释…"',
  '        description "Chinese prefix surface (pinyin jieshi, explain) matched by its literal start with no space before the … slot; the subject follows."',
  '      word "是什么"',
  '        description "Chinese phrase (pinyin shi shenme, is what) as a bare substring marking a definition request."',
  '  meaning "code_method"',
  "    gloss \"a method in the programming sense — a named operation or function defined on a type or object, such as the join method of a DataFrame. The word a prompt uses, in any language, to refer to such an operation when asking how it works. A handler pairs this concept with the method's own API identifier — which is written the same in every language — so it can recognise a question about a specific method without naming the word method in the code. Space-delimited surfaces match on whole-token boundaries; the Han surface matches as a substring.\"",
  '    wiktionary "method"',
  '    defined_by "action"',
  '    defined_by "concept"',
  '    role "code_method_noun"',
  '    lexeme "en"',
  '      word "method"',
  '        description "English noun method, the word for a named operation on a type or object; matched as a whole token."',
  '    lexeme "ru"',
  '      word "метод"',
  '        description "Russian noun (romanized metod) for a method; matched as a whole token."',
  '    lexeme "hi"',
  '      word "विधि"',
  '        description "Hindi noun (romanized vidhi) for a method or procedure; matched as a whole token."',
  '    lexeme "zh"',
  '      word "方法"',
  '        description "Chinese noun (pinyin fangfa) for a method; a Han substring marker for the method concept."',
  "meanings",
  '  meaning "skill_teaching_trigger"',
  '    gloss "the opening clause of a natural-language skill that names the moment a taught behaviour should fire — the user saying or asking some phrase. The concept a teaching instruction expresses when it introduces its trigger, independent of language or exact wording. Each surface is a bare clause-initial lead matched as a raw substring (the consuming code lower-cases the description first), and a trigger lead only teaches a skill when it co-occurs with a response verb and the instruction also quotes a trigger and a reply in backticks. No trigger word is named in the compiler; every lead lives here in the data, so the same instruction can be recognised across languages."',
  '    wiktionary "when"',
  '    defined_by "relation"',
  '    defined_by "inquiry"',
  '    role "skill_teaching_trigger_lead"',
  '    lexeme "en"',
  '      word "when i say"',
  '        description "English teaching lead introducing the phrase the user will say to trigger the skill; matched as a raw substring."',
  '      word "when the user says"',
  '        description "English teaching lead naming the user saying a trigger phrase; matched as a raw substring."',
  '      word "when the user asks"',
  '        description "English teaching lead naming the user asking a trigger phrase; matched as a raw substring."',
  '      word "if i ask"',
  '        description "English teaching lead introducing a conditional trigger phrased as a question; matched as a raw substring."',
  '    lexeme "ru"',
  '      word "когда я скажу"',
  '        description "Russian teaching lead (romanized kogda ya skazhu, when I say) introducing the trigger phrase; matched as a raw substring."',
  '      word "если я спрошу"',
  '        description "Russian teaching lead (romanized esli ya sprošu, if I ask) introducing a conditional trigger; matched as a raw substring."',
  '    lexeme "hi"',
  '      word "जब मैं कहूँ"',
  '        description "Hindi teaching lead (romanized jab main kahun, when I say) introducing the trigger phrase; matched as a raw substring."',
  '      word "अगर मैं पूछूँ"',
  '        description "Hindi teaching lead (romanized agar main puchun, if I ask) introducing a conditional trigger; matched as a raw substring."',
  '    lexeme "zh"',
  '      word "当我说"',
  '        description "Chinese teaching lead (pinyin dang wo shuo, when I say) introducing the trigger phrase; a Han substring marker."',
  '      word "当用户说"',
  '        description "Chinese teaching lead (pinyin dang yonghu shuo, when the user says) naming the user saying a trigger; a Han substring marker."',
  '      word "当用户问"',
  '        description "Chinese teaching lead (pinyin dang yonghu wen, when the user asks) naming the user asking a trigger; a Han substring marker."',
  '  meaning "skill_teaching_response"',
  '    gloss "the verb that introduces the canned reply a taught skill should emit — to answer, reply, or respond with a phrase. The concept a teaching instruction expresses when it names the response side of a trigger-and-reply pair, independent of language. Each surface is matched as a raw substring, so an inflectable stem such as the Russian otvet folds its endings; a response verb only teaches a skill when it co-occurs with a trigger lead. No verb is named in the compiler; every form lives here in the data."',
  '    wiktionary "answer"',
  '    defined_by "action"',
  '    defined_by "answer"',
  '    role "skill_teaching_response_verb"',
  '    lexeme "en"',
  '      word "answer"',
  '        description "English verb answer naming the reply a taught skill emits; matched as a raw substring."',
  '      word "reply"',
  '        description "English verb reply naming the response a taught skill emits; matched as a raw substring."',
  '      word "respond"',
  '        description "English verb respond naming the response a taught skill emits; matched as a raw substring."',
  '    lexeme "ru"',
  '      word "ответ"',
  '        description "Russian stem (romanized otvet, answer) folding its inflections such as otvet/otveť/otvetit; matched as a raw substring."',
  '    lexeme "hi"',
  '      word "उत्तर"',
  '        description "Hindi noun-verb (romanized uttar, answer) naming the reply a taught skill emits; matched as a raw substring."',
  '      word "जवाब"',
  '        description "Hindi noun-verb (romanized javab, reply) naming the response a taught skill emits; matched as a raw substring."',
  '    lexeme "zh"',
  '      word "回答"',
  '        description "Chinese verb (pinyin huida, answer) naming the reply a taught skill emits; a Han substring marker."',
  '      word "回复"',
  '        description "Chinese verb (pinyin huifu, reply) naming the response a taught skill emits; a Han substring marker."',
  '  meaning "behavior_rule_edit"',
  '    gloss "a standalone imperative to add or update a behaviour rule in the assistant — a direct instruction to change runtime behaviour rather than a trigger-and-reply teaching pair. The concept such a directive expresses, independent of language. Each surface is matched as a raw substring and is recognised on its own, without needing a separate response verb, because the imperative already names both the act of editing and its object. No directive phrase is named in the compiler; every form lives here in the data."',
  '    wiktionary "rule"',
  '    defined_by "action"',
  '    defined_by "knowledge"',
  '    role "behavior_rule_edit_directive"',
  '    lexeme "en"',
  '      word "add behavior rule"',
  '        description "English imperative to add a behaviour rule; matched as a raw substring and recognised on its own."',
  '      word "update behavior rule"',
  '        description "English imperative to update a behaviour rule; matched as a raw substring and recognised on its own."',
  '    lexeme "ru"',
  '      word "добавь правило поведения"',
  '        description "Russian imperative (romanized dobav pravilo povedeniya, add a behaviour rule); matched as a raw substring and recognised on its own."',
  '      word "обнови правило поведения"',
  '        description "Russian imperative (romanized obnovi pravilo povedeniya, update a behaviour rule); matched as a raw substring and recognised on its own."',
  '    lexeme "hi"',
  '      word "व्यवहार नियम जोड़ो"',
  '        description "Hindi imperative (romanized vyavhar niyam jodo, add a behaviour rule); matched as a raw substring and recognised on its own."',
  '      word "व्यवहार नियम अपडेट करो"',
  '        description "Hindi imperative (romanized vyavhar niyam update karo, update a behaviour rule); matched as a raw substring and recognised on its own."',
  '    lexeme "zh"',
  '      word "添加行为规则"',
  '        description "Chinese imperative (pinyin tianjia xingwei guize, add a behaviour rule); a Han substring marker recognised on its own."',
  '      word "更新行为规则"',
  '        description "Chinese imperative (pinyin gengxin xingwei guize, update a behaviour rule); a Han substring marker recognised on its own."',
  '  meaning "skill_when_then"',
  '    gloss "the when-then frame of a conditional skill instruction — a head clause that opens the condition and a link clause that opens the consequence, with the trigger and the response quoted in backticks between and after them. The concept a when-then rule expresses, independent of language. Each surface is a circumfix: the literal before the ellipsis … (U+2026) is the head the instruction must contain, and the literal after it is the link that must follow the head; a skill is taught only when a backtick-quoted span sits between the head and the link and another follows the link. No keyword pair is named in the compiler; every head-and-link frame lives here in the data."',
  '    wiktionary "then"',
  '    defined_by "relation"',
  '    defined_by "concept"',
  '    role "skill_when_then_pair"',
  '    lexeme "en"',
  '      word "when … then "',
  '        description "English when-then frame; the head when opens the condition and the link then opens the consequence around the … slot."',
  '      word "when … do "',
  '        description "English when-do frame; the head when opens the condition and the link do opens an imperative consequence around the … slot."',
  '    lexeme "ru"',
  '      word "когда … тогда "',
  '        description "Russian when-then frame (romanized kogda … togda); the head opens the condition and the link opens the consequence around the … slot."',
  '      word "когда … делай "',
  '        description "Russian when-do frame (romanized kogda … delay); the head opens the condition and the link opens an imperative consequence around the … slot."',
  '      word "когда … сделай "',
  '        description "Russian when-do frame (romanized kogda … sdelay, perfective); the head opens the condition and the link opens the consequence around the … slot."',
  '      word "когда … отвечай "',
  '        description "Russian when-answer frame (romanized kogda … otvechay); the head opens the condition and the link names answering around the … slot."',
  '      word "когда … отвечать "',
  '        description "Russian when-answer frame (romanized kogda … otvechat, infinitive); the head opens the condition and the link names answering around the … slot."',
  '      word "если … то "',
  '        description "Russian if-then frame (romanized esli … to); the head opens the condition and the link opens the consequence around the … slot."',
  '    lexeme "hi"',
  '      word "जब … तब "',
  '        description "Hindi when-then frame (romanized jab … tab); the head opens the condition and the link opens the consequence around the … slot."',
  '      word "जब … तो "',
  '        description "Hindi when-then frame (romanized jab … to); the head opens the condition and the link opens the consequence around the … slot."',
  '    lexeme "zh"',
  '      word "当 … 时 "',
  '        description "Chinese when-then frame (pinyin dang … shi); the head opens the condition and the link closes it before the consequence around the … slot."',
  '      word "当 … 则 "',
  '        description "Chinese when-then frame (pinyin dang … ze); the head opens the condition and the link opens the consequence around the … slot."',
  '      word "当 … 回答 "',
  '        description "Chinese when-answer frame (pinyin dang … huida); the head opens the condition and the link names answering around the … slot."',
  '      word "当 …时回答 "',
  '        description "Chinese when-then-answer frame (pinyin dang … shi huida); the head opens the condition and the link closes it and names answering around the … slot."',
  '      word "当 …则回答 "',
  '        description "Chinese when-then-answer frame (pinyin dang … ze huida); the head opens the condition and the link opens the consequence and names answering around the … slot."',
  '  meaning "nondeterministic_step"',
  '    gloss "the property of a structured-skill step that makes it non-deterministic or otherwise unreviewable — randomness, non-determinism, or arbitrary code. The concept the compiler screens for so it can refuse such a step, because a compiled skill must be deterministic and reviewable. Each surface is matched as a raw substring after the step text is lower-cased. No marker word is named in the compiler; every form lives here in the data."',
  '    wiktionary "random"',
  '    defined_by "property"',
  '    defined_by "concept"',
  '    role "nondeterministic_marker"',
  '    lexeme "en"',
  '      word "random"',
  '        description "English adjective random marking a non-deterministic step; matched as a raw substring."',
  '      word "nondeterministic"',
  '        description "English adjective nondeterministic marking an unreviewable step; matched as a raw substring."',
  '      word "non-deterministic"',
  '        description "English hyphenated spelling of nondeterministic; matched as a raw substring."',
  '      word "arbitrary code"',
  '        description "English phrase arbitrary code marking a step that runs unreviewable instructions; matched as a raw substring."',
  '    lexeme "ru"',
  '      word "случайный"',
  '        description "Russian adjective (romanized sluchaynyy, random) marking a non-deterministic step; matched as a raw substring."',
  '      word "недетерминированный"',
  '        description "Russian adjective (romanized nedeterminirovannyy, nondeterministic) marking an unreviewable step; matched as a raw substring."',
  '    lexeme "hi"',
  '      word "यादृच्छिक"',
  '        description "Hindi adjective (romanized yadrcchik, random) marking a non-deterministic step; matched as a raw substring."',
  '      word "अनिश्चित"',
  '        description "Hindi adjective (romanized anishchit, indeterminate) marking an unreviewable step; matched as a raw substring."',
  '    lexeme "zh"',
  '      word "随机"',
  '        description "Chinese adjective (pinyin suiji, random) marking a non-deterministic step; a Han substring marker."',
  '      word "不确定"',
  '        description "Chinese adjective (pinyin buqueding, indeterminate) marking an unreviewable step; a Han substring marker."',
  '  meaning "shell_capability_need"',
  '    gloss "the property of a structured-skill step that implies it needs the local shell or filesystem capability — running a shell, listing files, or writing and deleting files. The concept the compiler reads so it can require an explicit tool:local_shell permission grant before the step is allowed. Each surface is matched as a raw substring after the step text is lower-cased, and this cue is checked before the network cue so a step that touches both is attributed to the shell. No cue word is named in the compiler; every form lives here in the data, and the formal capability identifier it implies stays in the code as a tool-namespace bridge."',
  '    wiktionary "shell"',
  '    defined_by "capability"',
  '    defined_by "action"',
  '    role "shell_capability_cue"',
  '    lexeme "en"',
  '      word "local_shell"',
  '        description "English tool name local_shell naming the shell runner; matched as a raw substring."',
  '      word "shell"',
  '        description "English noun shell naming a command shell; matched as a raw substring."',
  '      word "filesystem"',
  '        description "English noun filesystem naming on-disk storage; matched as a raw substring."',
  '      word "file system"',
  '        description "English spaced spelling file system; matched as a raw substring."',
  '      word "list files"',
  '        description "English phrase list files naming a directory read; matched as a raw substring."',
  '      word "write file"',
  '        description "English phrase write file naming an on-disk write; matched as a raw substring."',
  '      word "delete file"',
  '        description "English phrase delete file naming an on-disk delete; matched as a raw substring."',
  '    lexeme "ru"',
  '      word "оболочка"',
  '        description "Russian noun (romanized obolochka, shell) naming a command shell; matched as a raw substring."',
  '      word "файловая система"',
  '        description "Russian phrase (romanized faylovaya sistema, file system) naming on-disk storage; matched as a raw substring."',
  '      word "список файлов"',
  '        description "Russian phrase (romanized spisok faylov, list of files) naming a directory read; matched as a raw substring."',
  '    lexeme "hi"',
  '      word "शेल"',
  '        description "Hindi noun (romanized shel, shell) naming a command shell; matched as a raw substring."',
  '      word "फाइल सिस्टम"',
  '        description "Hindi phrase (romanized phail sistam, file system) naming on-disk storage; matched as a raw substring."',
  '      word "फाइलें सूचीबद्ध"',
  '        description "Hindi phrase (romanized phailen suchibaddh, list files) naming a directory read; matched as a raw substring."',
  '    lexeme "zh"',
  '      word "外壳"',
  '        description "Chinese noun (pinyin waike, shell) naming a command shell; a Han substring marker."',
  '      word "文件系统"',
  '        description "Chinese noun (pinyin wenjian xitong, file system) naming on-disk storage; a Han substring marker."',
  '      word "列出文件"',
  '        description "Chinese phrase (pinyin liechu wenjian, list files) naming a directory read; a Han substring marker."',
  '  meaning "network_capability_need"',
  '    gloss "the property of a structured-skill step that implies it needs the network or web-fetch capability — making an HTTP or web request, reaching the network, or fetching a remote resource. The concept the compiler reads so it can require an explicit tool:web_fetch permission grant before the step is allowed. Each surface is matched as a raw substring after the step text is lower-cased, and this cue is checked after the shell cue. No cue word is named in the compiler; every form lives here in the data, and the formal capability identifier it implies stays in the code as a tool-namespace bridge."',
  '    wiktionary "network"',
  '    defined_by "capability"',
  '    defined_by "action"',
  '    role "network_capability_cue"',
  '    lexeme "en"',
  '      word "http"',
  '        description "English protocol name http naming a web request; matched as a raw substring."',
  '      word "network"',
  '        description "English noun network naming remote connectivity; matched as a raw substring."',
  '      word "fetch"',
  '        description "English verb fetch naming a remote retrieval; matched as a raw substring."',
  '      word "web request"',
  '        description "English phrase web request naming an outbound network call; matched as a raw substring."',
  '    lexeme "ru"',
  '      word "сеть"',
  '        description "Russian noun (romanized set, network) naming remote connectivity; matched as a raw substring."',
  '      word "веб-запрос"',
  '        description "Russian phrase (romanized veb-zapros, web request) naming an outbound call; matched as a raw substring."',
  '      word "сетевой запрос"',
  '        description "Russian phrase (romanized setevoy zapros, network request) naming an outbound call; matched as a raw substring."',
  '    lexeme "hi"',
  '      word "नेटवर्क"',
  '        description "Hindi noun (romanized netvark, network) naming remote connectivity; matched as a raw substring."',
  '      word "वेब अनुरोध"',
  '        description "Hindi phrase (romanized veb anurodh, web request) naming an outbound call; matched as a raw substring."',
  '    lexeme "zh"',
  '      word "网络"',
  '        description "Chinese noun (pinyin wangluo, network) naming remote connectivity; a Han substring marker."',
  '      word "网络请求"',
  '        description "Chinese phrase (pinyin wangluo qingqiu, network request) naming an outbound call; a Han substring marker."',
  '      word "获取"',
  '        description "Chinese verb (pinyin huoqu, fetch) naming a remote retrieval; a Han substring marker."',
  "meanings",
  '  meaning "investment"',
  '    gloss "the act of investing money — committing a principal sum so it can earn a return. The investment_cue role marks the surface forms that signal a prompt is a compound-interest word problem; the compound-interest handler requires this together with an interest_cue and a compounding_action_cue before it extracts the principal, rate, frequency and term. Matched as raw substrings so inflected forms are caught in every supported language."',
  '    wiktionary "investment"',
  '    defined_by "money"',
  '    defined_by "action"',
  '    role "investment_cue"',
  '    lexeme "en"',
  '      word "invest"',
  '        description "English verb for committing money to earn a return; an investment_cue matched as a raw substring so investing and invested are also caught."',
  '      word "investment"',
  "        description \"English noun for a committed sum of money; an investment_cue matched as a raw substring, kept explicitly so the surface list mirrors the original recognizer's disjunction.\"",
  '    lexeme "ru"',
  '      word "инвестир"',
  '        description "Russian verb stem (romanized investir, of инвестировать, to invest); an investment_cue matched as a raw substring so инвестировать and инвестируй are caught."',
  '      word "инвестиц"',
  '        description "Russian noun stem (romanized investits, of инвестиция, investment); an investment_cue matched as a raw substring so инвестиция and инвестиции are caught."',
  '    lexeme "hi"',
  '      word "निवेश"',
  '        description "Hindi noun (romanized nivesh, investment); an investment_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "投资"',
  '        description "Chinese verb (pinyin touzi, to invest); an investment_cue matched as a raw substring."',
  '  meaning "interest_finance"',
  '    gloss "interest in the financial sense — the charge paid for the use of money, expressed as a periodic rate on a principal. The interest_cue role marks the surface forms that signal a prompt is about interest; the compound-interest handler requires this together with an investment_cue and a compounding_action_cue before it answers. Matched as raw substrings so inflected forms are caught in every supported language."',
  '    wiktionary "interest"',
  '    defined_by "money"',
  '    role "interest_cue"',
  '    lexeme "en"',
  '      word "interest"',
  '        description "English noun for the financial charge on borrowed or invested money; an interest_cue matched as a raw substring."',
  '    lexeme "ru"',
  '      word "процент"',
  '        description "Russian noun (romanized protsent, interest or percent); an interest_cue matched as a raw substring so проценты and процентов are caught."',
  '    lexeme "hi"',
  '      word "ब्याज"',
  '        description "Hindi noun (romanized byaj, interest); an interest_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "利息"',
  '        description "Chinese noun (pinyin lixi, interest); an interest_cue matched as a raw substring."',
  '  meaning "compounding"',
  '    gloss "compounding — adding earned interest back to the principal so that it, in turn, earns further interest. The compounding_action_cue role marks the surface forms that signal a compound-interest problem; the compound-interest handler requires this together with an investment_cue and an interest_cue before it answers. Matched as raw substrings so inflected forms are caught in every supported language."',
  '    wiktionary "compound interest"',
  '    defined_by "action"',
  '    defined_by "money"',
  '    role "compounding_action_cue"',
  '    lexeme "en"',
  '      word "compound"',
  '        description "English verb for adding interest to principal so it earns further interest; a compounding_action_cue matched as a raw substring so compounded and compounding are also caught."',
  '    lexeme "ru"',
  '      word "сложный процент"',
  '        description "Russian phrase (romanized slozhnyy protsent, compound interest); a compounding_action_cue matched as a raw substring."',
  '      word "капитализаци"',
  '        description "Russian noun stem (romanized kapitalizatsi, of капитализация, capitalization of interest); a compounding_action_cue matched as a raw substring so капитализация and капитализации are caught."',
  '    lexeme "hi"',
  '      word "चक्रवृद्धि"',
  '        description "Hindi noun (romanized chakravriddhi, compounding); a compounding_action_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "复利"',
  '        description "Chinese noun (pinyin fuli, compound interest); a compounding_action_cue matched as a raw substring."',
  '  meaning "compounding_monthly"',
  '    gloss "compounding once a month — twelve compounding periods per year. A specialization of compounding by frequency. The compounding_frequency_cue role marks the surface forms that signal how often interest compounds; the compound-interest handler reads the first frequency it finds, in declaration order, so monthly is tried before the rarer frequencies. Matched as raw substrings in every supported language."',
  '    wiktionary "monthly"',
  '    defined_by "compounding"',
  '    role "compounding_frequency_cue"',
  '    lexeme "en"',
  '      word "monthly"',
  '        description "English adverb for once a month; a compounding_frequency_cue matched as a raw substring, mapping to twelve compounding periods per year."',
  '    lexeme "ru"',
  '      word "ежемесячн"',
  '        description "Russian adjective stem (romanized ezhemesyachn, of ежемесячный, monthly); a compounding_frequency_cue matched as a raw substring so ежемесячно and ежемесячное are caught."',
  '    lexeme "hi"',
  '      word "मासिक"',
  '        description "Hindi adjective (romanized masik, monthly); a compounding_frequency_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "每月"',
  '        description "Chinese adverb (pinyin meiyue, every month); a compounding_frequency_cue matched as a raw substring."',
  '  meaning "compounding_quarterly"',
  '    gloss "compounding once a quarter — four compounding periods per year. A specialization of compounding by frequency. The compounding_frequency_cue role marks the surface forms; the compound-interest handler reads the first frequency it finds, in declaration order. Matched as raw substrings in every supported language."',
  '    wiktionary "quarterly"',
  '    defined_by "compounding"',
  '    role "compounding_frequency_cue"',
  '    lexeme "en"',
  '      word "quarterly"',
  '        description "English adverb for once a quarter; a compounding_frequency_cue matched as a raw substring, mapping to four compounding periods per year."',
  '    lexeme "ru"',
  '      word "ежеквартальн"',
  '        description "Russian adjective stem (romanized ezhekvartaln, of ежеквартальный, quarterly); a compounding_frequency_cue matched as a raw substring so ежеквартально and ежеквартальное are caught."',
  '    lexeme "hi"',
  '      word "त्रैमासिक"',
  '        description "Hindi adjective (romanized traimasik, quarterly); a compounding_frequency_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "每季度"',
  '        description "Chinese adverb (pinyin meijidu, every quarter); a compounding_frequency_cue matched as a raw substring."',
  '  meaning "compounding_weekly"',
  '    gloss "compounding once a week — fifty-two compounding periods per year. A specialization of compounding by frequency. The compounding_frequency_cue role marks the surface forms; the compound-interest handler reads the first frequency it finds, in declaration order. Matched as raw substrings in every supported language."',
  '    wiktionary "weekly"',
  '    defined_by "compounding"',
  '    role "compounding_frequency_cue"',
  '    lexeme "en"',
  '      word "weekly"',
  '        description "English adverb for once a week; a compounding_frequency_cue matched as a raw substring, mapping to fifty-two compounding periods per year."',
  '    lexeme "ru"',
  '      word "еженедельн"',
  '        description "Russian adjective stem (romanized ezhenedeln, of еженедельный, weekly); a compounding_frequency_cue matched as a raw substring so еженедельно and еженедельное are caught."',
  '    lexeme "hi"',
  '      word "साप्ताहिक"',
  '        description "Hindi adjective (romanized saptahik, weekly); a compounding_frequency_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "每周"',
  '        description "Chinese adverb (pinyin meizhou, every week); a compounding_frequency_cue matched as a raw substring."',
  '  meaning "compounding_daily"',
  '    gloss "compounding once a day — three hundred sixty-five compounding periods per year. A specialization of compounding by frequency. The compounding_frequency_cue role marks the surface forms; the compound-interest handler reads the first frequency it finds, in declaration order. Matched as raw substrings in every supported language."',
  '    wiktionary "daily"',
  '    defined_by "compounding"',
  '    role "compounding_frequency_cue"',
  '    lexeme "en"',
  '      word "daily"',
  '        description "English adverb for once a day; a compounding_frequency_cue matched as a raw substring, mapping to three hundred sixty-five compounding periods per year."',
  '    lexeme "ru"',
  '      word "ежедневн"',
  '        description "Russian adjective stem (romanized ezhednevn, of ежедневный, daily); a compounding_frequency_cue matched as a raw substring so ежедневно and ежедневное are caught."',
  '    lexeme "hi"',
  '      word "दैनिक"',
  '        description "Hindi adjective (romanized dainik, daily); a compounding_frequency_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "每日"',
  '        description "Chinese adverb (pinyin meiri, every day); a compounding_frequency_cue matched as a raw substring."',
  '  meaning "compounding_annual"',
  '    gloss "compounding once a year — a single compounding period per year. A specialization of compounding by frequency. The compounding_frequency_cue role marks the surface forms; the compound-interest handler reads the first frequency it finds, in declaration order, so this is the fallback when no finer frequency is named. Matched as raw substrings in every supported language."',
  '    wiktionary "annually"',
  '    defined_by "compounding"',
  '    role "compounding_frequency_cue"',
  '    lexeme "en"',
  '      word "annually"',
  '        description "English adverb for once a year; a compounding_frequency_cue matched as a raw substring, mapping to one compounding period per year."',
  '      word "yearly"',
  "        description \"English adverb for once a year, a synonym of annually; a compounding_frequency_cue matched as a raw substring, kept explicitly so the surface list mirrors the original recognizer's disjunction.\"",
  '    lexeme "ru"',
  '      word "ежегодн"',
  '        description "Russian adjective stem (romanized ezhegodn, of ежегодный, annual); a compounding_frequency_cue matched as a raw substring so ежегодно and ежегодное are caught."',
  '    lexeme "hi"',
  '      word "वार्षिक"',
  '        description "Hindi adjective (romanized varshik, annual); a compounding_frequency_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "每年"',
  '        description "Chinese adverb (pinyin meinian, every year); a compounding_frequency_cue matched as a raw substring."',
  '  meaning "live_rate_freshness"',
  '    gloss "a request for a live, web-sourced, up-to-the-minute exchange rate rather than a locally cached one. The live_rate_freshness_cue role marks the surface forms; the compound-interest handler reads it to add a caveat that web freshness is not independently verified, while still answering from the local calculator. A freshness qualifier on an exchange_rate. Matched as raw substrings so compound forms are caught in every supported language."',
  '    wiktionary "exchange rate"',
  '    defined_by "exchange_rate"',
  '    defined_by "concept"',
  '    role "live_rate_freshness_cue"',
  '    lexeme "en"',
  '      word "web"',
  '        description "English noun for the World Wide Web as a live data source; a live_rate_freshness_cue matched as a raw substring."',
  '      word "current exchange"',
  '        description "English fragment asking for the current exchange of currencies; a live_rate_freshness_cue matched as a raw substring."',
  '      word "current rate"',
  '        description "English fragment asking for the current rate; a live_rate_freshness_cue matched as a raw substring."',
  '      word "exchange rate"',
  '        description "English compound noun for the price of one currency in another, read here as a request for its live value; a live_rate_freshness_cue matched as a raw substring."',
  '    lexeme "ru"',
  '      word "текущий курс"',
  '        description "Russian phrase (romanized tekushchiy kurs, current rate); a live_rate_freshness_cue matched as a raw substring."',
  '      word "актуальный курс"',
  '        description "Russian phrase (romanized aktualnyy kurs, up-to-date rate); a live_rate_freshness_cue matched as a raw substring."',
  '    lexeme "hi"',
  '      word "वर्तमान दर"',
  '        description "Hindi phrase (romanized vartaman dar, current rate); a live_rate_freshness_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "实时汇率"',
  '        description "Chinese phrase (pinyin shishi huilu, real-time exchange rate); a live_rate_freshness_cue matched as a raw substring."',
  '  meaning "year_period"',
  '    gloss "a year — the unit of time a compound-interest term is measured in. The year_unit_cue role marks the surface forms; the compound-interest handler locates the cue and reads the number immediately before it as the number of years. A time concept. Located as raw substrings in every supported language."',
  '    wiktionary "year"',
  '    defined_by "concept"',
  '    role "year_unit_cue"',
  '    lexeme "en"',
  '      word "year"',
  '        description "English noun for the time unit of a year; a year_unit_cue located as a raw substring so years is also caught and the preceding number can be read."',
  '    lexeme "ru"',
  '      word "год"',
  '        description "Russian noun (romanized god, year); a year_unit_cue located as a raw substring so года and годов are caught."',
  '      word "лет"',
  '        description "Russian genitive-plural noun (romanized let, years); a year_unit_cue located as a raw substring, the form used after most numbers."',
  '    lexeme "hi"',
  '      word "वर्ष"',
  '        description "Hindi noun (romanized varsh, year); a year_unit_cue located as a raw substring."',
  '    lexeme "zh"',
  '      word "年"',
  '        description "Chinese noun (pinyin nian, year); a year_unit_cue located as a raw substring."',
  '  meaning "conversion_action"',
  '    gloss "converting an amount of money from one currency into another. The conversion_action_cue role marks the surface forms; the compound-interest handler requires it together with a final_amount_reference before it converts a previously computed final amount. Matched as raw substrings so inflected forms are caught in every supported language."',
  '    wiktionary "convert"',
  '    defined_by "action"',
  '    defined_by "money"',
  '    role "conversion_action_cue"',
  '    lexeme "en"',
  '      word "convert"',
  '        description "English verb for changing one currency into another; a conversion_action_cue matched as a raw substring so converted and converting are also caught."',
  '    lexeme "ru"',
  '      word "конвертир"',
  '        description "Russian verb stem (romanized konvertir, of конвертировать, to convert); a conversion_action_cue matched as a raw substring so конвертировать and конвертируй are caught."',
  '    lexeme "hi"',
  '      word "परिवर्तित"',
  '        description "Hindi adjective (romanized parivartit, converted); a conversion_action_cue matched as a raw substring."',
  '    lexeme "zh"',
  '      word "转换"',
  '        description "Chinese verb (pinyin zhuanhuan, to convert); a conversion_action_cue matched as a raw substring."',
  '  meaning "final_amount"',
  '    gloss "the final amount — the computed result of a compound-interest calculation that a follow-up turn may ask to convert. The final_amount_reference role marks the surface forms; the compound-interest handler requires it together with a conversion_action_cue before it reads the prior final amount and converts it. A kind of money. Matched as raw substrings so phrasings are caught in every supported language."',
  '    wiktionary "amount"',
  '    defined_by "money"',
  '    role "final_amount_reference"',
  '    lexeme "en"',
  '      word "final amount"',
  '        description "English compound noun for the computed result of the calculation; a final_amount_reference matched as a raw substring."',
  '    lexeme "ru"',
  '      word "итоговая сумма"',
  '        description "Russian phrase (romanized itogovaya summa, final amount); a final_amount_reference matched as a raw substring."',
  '    lexeme "hi"',
  '      word "अंतिम राशि"',
  '        description "Hindi phrase (romanized antim rashi, final amount); a final_amount_reference matched as a raw substring."',
  '    lexeme "zh"',
  '      word "最终金额"',
  "        description \"Chinese phrase (pinyin zuizhong jin'e, final amount); a final_amount_reference matched as a raw substring.\"",
  "meanings",
  '  meaning "definition_merge_action"',
  '    gloss "merging two or more definitions, translations, or encyclopedia entries into a single combined answer. The definition_merge_action role marks the surface forms that ask for such a merge; the definition-merge handler requires this together with a definition_artifact_request before it looks the term up and combines its definitions. Matched as raw substrings so inflected forms are caught in every supported language."',
  '    wiktionary "merge"',
  '    defined_by "action"',
  '    role "definition_merge_action"',
  '    lexeme "en"',
  '      word "merge"',
  '        description "English verb for combining things into one; a definition_merge_action matched as a raw substring so merges and merging are also caught."',
  '      word "merged"',
  "        description \"English past participle of merge; a definition_merge_action matched as a raw substring, kept explicitly so the surface list mirrors the original recognizer's disjunction.\"",
  '      word "combine"',
  '        description "English verb for joining things together; a definition_merge_action matched as a raw substring so combines and combining are also caught."',
  '      word "combined"',
  "        description \"English past participle of combine; a definition_merge_action matched as a raw substring, kept explicitly so the surface list mirrors the original recognizer's disjunction.\"",
  '      word "fuse"',
  '        description "English verb for blending things into one; a definition_merge_action matched as a raw substring so fuses and fusing are also caught."',
  '      word "fusion"',
  '        description "English noun for a blending into one; a definition_merge_action matched as a raw substring, kept explicitly because fuse is not a substring of fusion."',
  '    lexeme "ru"',
  '      word "объедин"',
  '        description "Russian verb stem (romanized obyedin, of объединить, to merge or combine); a definition_merge_action matched as a raw substring so объедини and объединить are caught."',
  '      word "слия"',
  '        description "Russian noun stem (romanized sliya, of слияние, fusion); a definition_merge_action matched as a raw substring so слияние and слияния are caught."',
  '    lexeme "hi"',
  '      word "विलय"',
  '        description "Hindi noun (romanized vilay, merger); a definition_merge_action matched as a raw substring."',
  '      word "संयोजन"',
  '        description "Hindi noun (romanized sanyojan, combination); a definition_merge_action matched as a raw substring."',
  '    lexeme "zh"',
  '      word "合并"',
  '        description "Chinese verb (pinyin hebing, to merge); a definition_merge_action matched as a raw substring."',
  '      word "融合"',
  '        description "Chinese verb (pinyin ronghe, to fuse); a definition_merge_action matched as a raw substring."',
  '  meaning "definition_artifact_request"',
  '    gloss "a request for a definition, a translation, or a Wikipedia entry — the artifacts the definition-merge handler combines. The definition_artifact_request role marks these surface forms; the handler requires this together with a definition_merge_action before it merges definitions of a term. Matched as raw substrings so inflected forms are caught in every supported language."',
  '    wiktionary "definition"',
  '    defined_by "inquiry"',
  '    role "definition_artifact_request"',
  '    lexeme "en"',
  '      word "definition"',
  '        description "English noun for a statement of meaning; a definition_artifact_request matched as a raw substring so definitions is also caught."',
  '      word "definitions"',
  "        description \"English plural of definition; a definition_artifact_request matched as a raw substring, kept explicitly so the surface list mirrors the original recognizer's disjunction.\"",
  '      word "translation"',
  '        description "English noun for a rendering into another language; a definition_artifact_request matched as a raw substring so translations is also caught."',
  '      word "translations"',
  "        description \"English plural of translation; a definition_artifact_request matched as a raw substring, kept explicitly so the surface list mirrors the original recognizer's disjunction.\"",
  '      word "translated"',
  '        description "English past participle of translate; a definition_artifact_request matched as a raw substring."',
  '      word "wikipedia"',
  '        description "English proper noun for the Wikipedia encyclopedia, a source of definitions; a definition_artifact_request matched as a raw substring."',
  '    lexeme "ru"',
  '      word "определени"',
  '        description "Russian noun stem (romanized opredeleni, of определение, definition); a definition_artifact_request matched as a raw substring so определение and определения are caught."',
  '      word "перевод"',
  '        description "Russian noun (romanized perevod, translation); a definition_artifact_request matched as a raw substring so перевода and переводы are caught."',
  '      word "википеди"',
  '        description "Russian noun stem (romanized vikipedi, of Википедия, Wikipedia); a definition_artifact_request matched as a raw substring so Википедия and Википедии are caught."',
  '    lexeme "hi"',
  '      word "परिभाषा"',
  '        description "Hindi noun (romanized paribhasha, definition); a definition_artifact_request matched as a raw substring."',
  '      word "अनुवाद"',
  '        description "Hindi noun (romanized anuvad, translation); a definition_artifact_request matched as a raw substring."',
  '    lexeme "zh"',
  '      word "定义"',
  '        description "Chinese noun (pinyin dingyi, definition); a definition_artifact_request matched as a raw substring."',
  '      word "翻译"',
  '        description "Chinese noun (pinyin fanyi, translation); a definition_artifact_request matched as a raw substring."',
  '  meaning "definition_merge_marker"',
  "    gloss \"a phrase that introduces the term whose definitions are to be merged — for example definitions of or translation for — immediately followed by the term itself. The definition_merge_marker role carries these as prefix word forms whose text before the slot marker is the phrase to locate; the definition-merge handler scans them in declaration order, finds the first whose prefix appears in the prompt, and takes the text after it as the term. The English forms are listed in the original recognizer's priority order so longer, more specific phrases win before shorter ones.\"",
  '    wiktionary "definition"',
  '    defined_by "inquiry"',
  '    role "definition_merge_marker"',
  '    lexeme "en"',
  '      word "translated definitions for …"',
  "        description \"English prefix 'translated definitions for'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term, tried first as the longest, most specific phrase.\"",
  '      word "translated definitions of …"',
  "        description \"English prefix 'translated definitions of'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "wikipedia definitions for …"',
  "        description \"English prefix 'wikipedia definitions for'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "wikipedia definitions of …"',
  "        description \"English prefix 'wikipedia definitions of'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "definitions for …"',
  "        description \"English prefix 'definitions for'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "definitions of …"',
  "        description \"English prefix 'definitions of'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "definition for …"',
  "        description \"English prefix 'definition for'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "definition of …"',
  "        description \"English prefix 'definition of'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "translations for …"',
  "        description \"English prefix 'translations for'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "translations of …"',
  "        description \"English prefix 'translations of'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "translation for …"',
  "        description \"English prefix 'translation for'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "translation of …"',
  "        description \"English prefix 'translation of'; a definition_merge_marker whose prefix before the slot is located and stripped to leave the term, tried last as the shortest phrase.\"",
  '    lexeme "ru"',
  '      word "переведенные определения для …"',
  '        description "Russian prefix (romanized perevedennye opredeleniya dlya, translated definitions for); a definition_merge_marker whose prefix before the slot is located and stripped to leave the term."',
  '      word "определения для …"',
  '        description "Russian prefix (romanized opredeleniya dlya, definitions for); a definition_merge_marker whose prefix before the slot is located and stripped to leave the term."',
  '      word "определение …"',
  '        description "Russian prefix (romanized opredelenie, definition of); a definition_merge_marker whose prefix before the slot is located and stripped to leave the term that follows in the genitive."',
  '      word "перевод …"',
  '        description "Russian prefix (romanized perevod, translation of); a definition_merge_marker whose prefix before the slot is located and stripped to leave the term."',
  '    lexeme "hi"',
  '      word "की परिभाषाएँ …"',
  '        description "Hindi best-effort prefix (romanized ki paribhashaen, definitions of); a definition_merge_marker whose prefix before the slot is located and stripped to leave the term."',
  '      word "का अनुवाद …"',
  '        description "Hindi best-effort prefix (romanized ka anuvad, translation of); a definition_merge_marker whose prefix before the slot is located and stripped to leave the term."',
  '    lexeme "zh"',
  '      word "的定义 …"',
  "        description \"Chinese best-effort prefix (pinyin de dingyi, 's definition); a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '      word "的翻译 …"',
  "        description \"Chinese best-effort prefix (pinyin de fanyi, 's translation); a definition_merge_marker whose prefix before the slot is located and stripped to leave the term.\"",
  '  meaning "definition_merge_tail_boundary"',
  '    gloss "a word that ends the term in a definition-merge prompt — once the term has been located, any text from the first such boundary word onward (the source, the method, the destination) is trimmed away. The definition_merge_tail_boundary role marks these forms; the handler reconstructs each as a space-padded token and cuts the extracted term at the earliest one it finds. Defined as a relation between the term and what follows it."',
  '    wiktionary "from"',
  '    defined_by "relation"',
  '    role "definition_merge_tail_boundary"',
  '    lexeme "en"',
  '      word "from"',
  '        description "English preposition introducing a source; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "using"',
  '        description "English preposition introducing a method; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "with"',
  '        description "English preposition introducing an accompaniment; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "by"',
  '        description "English preposition introducing an agent or means; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "into"',
  '        description "English preposition introducing a destination; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "across"',
  '        description "English preposition introducing a span; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '    lexeme "ru"',
  '      word "из"',
  '        description "Russian preposition (romanized iz, from) introducing a source; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "с"',
  '        description "Russian preposition (romanized s, with or from) introducing an accompaniment or source; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "по"',
  '        description "Russian preposition (romanized po, by) introducing a means; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "в"',
  '        description "Russian preposition (romanized v, into) introducing a destination; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '    lexeme "hi"',
  '      word "से"',
  '        description "Hindi postposition (romanized se, from) introducing a source; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "के साथ"',
  '        description "Hindi postposition (romanized ke saath, with) introducing an accompaniment; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '    lexeme "zh"',
  '      word "从"',
  '        description "Chinese preposition (pinyin cong, from) introducing a source; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  '      word "使用"',
  '        description "Chinese verb (pinyin shiyong, using) introducing a method; a definition_merge_tail_boundary reconstructed as a space-padded token, marking where the term ends."',
  "meanings",
  '  meaning "tool_invocation_cue"',
  '    gloss "a cue that the prompt is an explicit natural-language tool or API call — the verbs call, invoke, and run together with the nouns api and tool. The tool_invocation_cue role marks these surface forms; the natural-language-tool handler requires one of them together with a named tool (calculator_tool or web_search_tool) before it treats the prompt as a direct tool call rather than ordinary prose. Matched as whole tokens in every supported language, so no cue word is named in the code."',
  '    wiktionary "invoke"',
  '    defined_by "action"',
  '    role "tool_invocation_cue"',
  '    lexeme "en"',
  '      word "call"',
  '        description "English verb to call or invoke a tool; a tool_invocation_cue matched as a whole token so it signals an explicit tool or API call."',
  '      word "invoke"',
  '        description "English verb to invoke a routine or tool; a tool_invocation_cue matched as a whole token so it signals an explicit tool or API call."',
  '      word "run"',
  '        description "English verb to run or execute; a tool_invocation_cue matched as a whole token so it signals an explicit tool or API call."',
  '      word "api"',
  '        description "English noun api (application programming interface); a tool_invocation_cue matched as a whole token so naming an api signals an explicit tool call."',
  '      word "tool"',
  '        description "English noun tool naming an invokable capability; a tool_invocation_cue matched as a whole token so naming a tool signals an explicit tool call."',
  '    lexeme "ru"',
  '      word "вызови"',
  '        description "Russian verb (romanized vyzovi, call or invoke — imperative); a tool_invocation_cue matched as a whole token so it signals an explicit tool or API call."',
  '      word "вызвать"',
  '        description "Russian verb (romanized vyzvat, to call or invoke); a tool_invocation_cue matched as a whole token so it signals an explicit tool or API call."',
  '      word "запусти"',
  '        description "Russian verb (romanized zapusti, run or launch — imperative); a tool_invocation_cue matched as a whole token so it signals an explicit tool or API call."',
  '      word "инструмент"',
  '        description "Russian noun (romanized instrument, tool); a tool_invocation_cue matched as a whole token so naming a tool signals an explicit tool call."',
  '    lexeme "hi"',
  '      word "कॉल"',
  '        description "Hindi verb (romanized kol, call — a loanword); a tool_invocation_cue matched as a whole token so it signals an explicit tool or API call."',
  '      word "चलाओ"',
  '        description "Hindi verb (romanized chalao, run — imperative); a tool_invocation_cue matched as a whole token so it signals an explicit tool or API call."',
  '      word "उपकरण"',
  '        description "Hindi noun (romanized upkaran, tool); a tool_invocation_cue matched as a whole token so naming a tool signals an explicit tool call."',
  '    lexeme "zh"',
  '      word "调用"',
  '        description "Chinese verb (pinyin diaoyong, to call or invoke); a tool_invocation_cue matched as a Han substring so it signals an explicit tool or API call."',
  '      word "运行"',
  '        description "Chinese verb (pinyin yunxing, to run); a tool_invocation_cue matched as a Han substring so it signals an explicit tool or API call."',
  '      word "工具"',
  '        description "Chinese noun (pinyin gongju, tool); a tool_invocation_cue matched as a Han substring so naming a tool signals an explicit tool call."',
  '  meaning "calculator_tool"',
  '    gloss "the calculator tool the assistant can invoke to evaluate an arithmetic expression — its formal capability is tool:calculator. The calculator_tool_name role marks the surface words that name it; the natural-language-tool handler requires this name together with a tool_invocation_cue before it routes the prompt to the calculator. The English form is the literal tool identifier; the other languages are best-effort descriptive surfaces. Matched as whole tokens."',
  '    wiktionary "calculator"',
  '    defined_by "entity"',
  '    role "calculator_tool_name"',
  '    lexeme "en"',
  '      word "calculator"',
  '        description "English noun calculator and the literal tool identifier calculator; a calculator_tool_name matched as a whole token."',
  '    lexeme "ru"',
  '      word "калькулятор"',
  '        description "Russian noun (romanized kalkulyator, calculator); a calculator_tool_name matched as a whole token."',
  '    lexeme "hi"',
  '      word "कैलकुलेटर"',
  '        description "Hindi noun (romanized kailkuletar, calculator — a loanword); a calculator_tool_name matched as a whole token."',
  '    lexeme "zh"',
  '      word "计算器"',
  '        description "Chinese noun (pinyin jisuanqi, calculator); a calculator_tool_name matched as a Han substring."',
  '  meaning "web_search_tool"',
  '    gloss "the web-search tool the assistant can invoke to record a search plan — its formal capability is tool:web_search. The web_search_tool_name role marks the surface words that name it; the natural-language-tool handler requires this name together with a tool_invocation_cue before it routes the prompt to web search. The English forms are the literal tool identifier and its spaced and hyphenated spellings; the other languages are best-effort descriptive surfaces. Matched as whole tokens."',
  '    wiktionary "search"',
  '    defined_by "entity"',
  '    role "web_search_tool_name"',
  '    lexeme "en"',
  '      word "web_search"',
  '        description "English literal tool identifier web_search naming the web-search tool; a web_search_tool_name matched as a whole token."',
  '      word "web search"',
  '        description "English spaced spelling web search naming the web-search tool; a web_search_tool_name matched as a whole token (phrase)."',
  '      word "web-search"',
  '        description "English hyphenated spelling web-search naming the web-search tool; a web_search_tool_name matched as a whole token."',
  '    lexeme "ru"',
  '      word "веб-поиск"',
  '        description "Russian noun (romanized veb-poisk, web search); a web_search_tool_name matched as a whole token."',
  '      word "поиск в интернете"',
  '        description "Russian phrase (romanized poisk v internete, search on the internet); a web_search_tool_name matched as a whole token (phrase)."',
  '    lexeme "hi"',
  '      word "वेब खोज"',
  '        description "Hindi phrase (romanized veb khoj, web search); a web_search_tool_name matched as a whole token (phrase)."',
  '      word "इंटरनेट खोज"',
  '        description "Hindi phrase (romanized internet khoj, internet search); a web_search_tool_name matched as a whole token (phrase)."',
  '    lexeme "zh"',
  '      word "网络搜索"',
  '        description "Chinese noun (pinyin wangluo sousuo, web search); a web_search_tool_name matched as a Han substring."',
  '      word "网页搜索"',
  '        description "Chinese noun (pinyin wangye sousuo, web-page search); a web_search_tool_name matched as a Han substring."',
  '  meaning "local_shell_tool"',
  '    gloss "an explicit request to invoke the local_shell tool — its formal capability is tool:local_shell. Unlike calculator_tool and web_search_tool, the surface forms here bundle the verb and the tool name into whole phrases (for example local shell tool or invoke the shell tool), so the local_shell_request_cue role is decisive on its own and the handler does not also require a separate tool_invocation_cue. The English forms are the literal identifier and the request phrases; the other languages are best-effort descriptive surfaces. Matched as whole tokens."',
  '    wiktionary "shell"',
  '    defined_by "entity"',
  '    role "local_shell_request_cue"',
  '    lexeme "en"',
  '      word "local_shell"',
  '        description "English literal tool identifier local_shell naming the shell runner; a local_shell_request_cue matched as a whole token."',
  '      word "local shell tool"',
  '        description "English phrase local shell tool naming the shell tool; a local_shell_request_cue matched as a whole token (phrase)."',
  '      word "local shell api"',
  "        description \"English phrase local shell api naming the shell tool's api; a local_shell_request_cue matched as a whole token (phrase).\"",
  '      word "call the shell tool"',
  '        description "English phrase call the shell tool requesting the shell tool; a local_shell_request_cue matched as a whole token (phrase)."',
  '      word "invoke the shell tool"',
  '        description "English phrase invoke the shell tool requesting the shell tool; a local_shell_request_cue matched as a whole token (phrase)."',
  '    lexeme "ru"',
  '      word "локальная оболочка"',
  '        description "Russian phrase (romanized lokalnaya obolochka, local shell); a local_shell_request_cue matched as a whole token (phrase)."',
  '      word "вызови оболочку"',
  '        description "Russian phrase (romanized vyzovi obolochku, call the shell); a local_shell_request_cue matched as a whole token (phrase)."',
  '    lexeme "hi"',
  '      word "लोकल शेल"',
  '        description "Hindi phrase (romanized lokal shel, local shell); a local_shell_request_cue matched as a whole token (phrase)."',
  '      word "शेल टूल चलाओ"',
  '        description "Hindi phrase (romanized shel tul chalao, run the shell tool); a local_shell_request_cue matched as a whole token (phrase)."',
  '    lexeme "zh"',
  '      word "本地外壳"',
  '        description "Chinese noun (pinyin bendi waike, local shell); a local_shell_request_cue matched as a Han substring."',
  '      word "调用外壳工具"',
  '        description "Chinese phrase (pinyin diaoyong waike gongju, invoke the shell tool); a local_shell_request_cue matched as a Han substring."',
  '  meaning "tool_argument_marker"',
  '    gloss "a phrase that introduces the argument of a natural-language tool call — for example with query or for — immediately followed by the argument text. The tool_argument_marker role carries these forms; when the argument is not already delimited by backticks or quotes, the handler reconstructs each English form as a space-padded token, finds the first one present in declaration order, and takes the text after it as the argument. Only the English forms are consulted — this is an English-frame extraction heuristic — while the other languages remain in the seed so the meaning stays fully self-describing. The forms are listed in the original priority order so longer, more specific phrases win before shorter ones."',
  '    wiktionary "with"',
  '    defined_by "relation"',
  '    role "tool_argument_marker"',
  '    lexeme "en"',
  '      word "with query"',
  "        description \"English marker 'with query' introducing a search query argument; a tool_argument_marker reconstructed as a space-padded token, tried first as the longest, most specific phrase.\"",
  '      word "query"',
  "        description \"English marker 'query' introducing a query argument; a tool_argument_marker reconstructed as a space-padded token, tried after 'with query'.\"",
  '      word "with"',
  "        description \"English marker 'with' introducing an argument; a tool_argument_marker reconstructed as a space-padded token, tried after the query phrases.\"",
  '      word "for"',
  "        description \"English marker 'for' introducing an argument; a tool_argument_marker reconstructed as a space-padded token, tried last as the shortest phrase.\"",
  '    lexeme "ru"',
  '      word "с запросом"',
  '        description "Russian marker (romanized s zaprosom, with query) introducing a query argument; a tool_argument_marker kept in the seed for self-description (English forms drive extraction)."',
  '      word "для"',
  '        description "Russian marker (romanized dlya, for) introducing an argument; a tool_argument_marker kept in the seed for self-description (English forms drive extraction)."',
  '    lexeme "hi"',
  '      word "क्वेरी के साथ"',
  '        description "Hindi marker (romanized kveri ke saath, with query) introducing a query argument; a tool_argument_marker kept in the seed for self-description (English forms drive extraction)."',
  '      word "के लिए"',
  '        description "Hindi marker (romanized ke liye, for) introducing an argument; a tool_argument_marker kept in the seed for self-description (English forms drive extraction)."',
  '    lexeme "zh"',
  '      word "查询"',
  '        description "Chinese marker (pinyin chaxun, query) introducing a query argument; a tool_argument_marker kept in the seed for self-description (English forms drive extraction)."',
  '      word "用于"',
  '        description "Chinese marker (pinyin yongyu, for) introducing an argument; a tool_argument_marker kept in the seed for self-description (English forms drive extraction)."',
  "meanings",
  '  meaning "feature_capability_web_search"',
  "    gloss \"the web-search capability — querying search engines and the open internet. A feature_capability_alias meaning: the feature-capability handler walks the feature_capability_alias meanings in declaration (priority) order and, through first_role_match_in_languages_raw, returns the first whose forms occur as a raw substring in the prompt, checked in the prompt's own language plus English. The matched slug minus its feature_capability_ prefix keys the localized response table, so no surface alias is named in the code. Availability is gated at runtime by offline mode and the configured search providers; this meaning is listed first to mirror the original hand-ordered capability table.\"",
  '    wiktionary "search"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "web search"',
  "        description \"English form 'web search' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "internet search"',
  "        description \"English form 'internet search' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "search engines"',
  "        description \"English form 'search engines' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "can you search the internet"',
  "        description \"English form 'can you search the internet' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "can you search internet"',
  "        description \"English form 'can you search internet' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "can you search the web"',
  "        description \"English form 'can you search the web' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "can you search web"',
  "        description \"English form 'can you search web' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "can you search online"',
  "        description \"English form 'can you search online' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "do you have internet search"',
  "        description \"English form 'do you have internet search' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "do you have web search"',
  "        description \"English form 'do you have web search' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "do you have internet access"',
  "        description \"English form 'do you have internet access' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "are you connected to search engines"',
  "        description \"English form 'are you connected to search engines' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "can you use search engines"',
  "        description \"English form 'can you use search engines' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "can you browse the web"',
  "        description \"English form 'can you browse the web' naming the web-search capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "веб-поиск"',
  "        description \"Russian form 'веб-поиск' (romanized veb-poisk, web search) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "веб поиск"',
  "        description \"Russian form 'веб поиск' (romanized veb poisk, web search) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "поиск в интернете"',
  "        description \"Russian phrase 'поиск в интернете' (romanized poisk v internete, search on the internet) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "поисковик"',
  "        description \"Russian noun 'поисковик' (romanized poiskovik, search engine) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "поисковые системы"',
  "        description \"Russian phrase 'поисковые системы' (romanized poiskovye sistemy, search engines) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "можешь искать в интернете"',
  "        description \"Russian phrase 'можешь искать в интернете' (romanized mozhesh iskat v internete, can you search the internet) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "можешь искать интернет"',
  "        description \"Russian phrase 'можешь искать интернет' (romanized mozhesh iskat internet, can you search the internet) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "умеешь искать в интернете"',
  "        description \"Russian phrase 'умеешь искать в интернете' (romanized umeesh iskat v internete, are you able to search the internet) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "умеешь искать интернет"',
  "        description \"Russian phrase 'умеешь искать интернет' (romanized umeesh iskat internet, are you able to search the internet) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "можешь искать онлайн"',
  "        description \"Russian phrase 'можешь искать онлайн' (romanized mozhesh iskat onlayn, can you search online) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "умеешь искать онлайн"',
  "        description \"Russian phrase 'умеешь искать онлайн' (romanized umeesh iskat onlayn, are you able to search online) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "у тебя есть веб-поиск"',
  "        description \"Russian phrase 'у тебя есть веб-поиск' (romanized u tebya est veb-poisk, do you have web search) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "у тебя есть веб поиск"',
  "        description \"Russian phrase 'у тебя есть веб поиск' (romanized u tebya est veb poisk, do you have web search) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "у тебя есть поиск в интернете"',
  "        description \"Russian phrase 'у тебя есть поиск в интернете' (romanized u tebya est poisk v internete, do you have internet search) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "есть доступ к интернету"',
  "        description \"Russian phrase 'есть доступ к интернету' (romanized est dostup k internetu, is there internet access) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "подключен к поисковикам"',
  "        description \"Russian phrase 'подключен к поисковикам' (romanized podklyuchen k poiskovikam, connected to search engines, masculine) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "подключена к поисковикам"',
  "        description \"Russian phrase 'подключена к поисковикам' (romanized podklyuchena k poiskovikam, connected to search engines, feminine) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "подключен к поисковым системам"',
  "        description \"Russian phrase 'подключен к поисковым системам' (romanized podklyuchen k poiskovym sistemam, connected to search engines) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "можешь пользоваться интернетом"',
  "        description \"Russian phrase 'можешь пользоваться интернетом' (romanized mozhesh polzovatsya internetom, can you use the internet) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "web search"',
  "        description \"English loanword 'web search' as used in Hindi prompts for the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "internet search"',
  "        description \"English loanword 'internet search' as used in Hindi prompts for the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "search engine"',
  "        description \"English loanword 'search engine' as used in Hindi prompts for the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "इंटरनेट पर खोज सकते"',
  "        description \"Hindi phrase 'इंटरनेट पर खोज सकते' (romanized internet par khoj sakte, can search on the internet) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "ऑनलाइन खोज सकते"',
  "        description \"Hindi phrase 'ऑनलाइन खोज सकते' (romanized online khoj sakte, can search online) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "इंटरनेट खोज है"',
  "        description \"Hindi phrase 'इंटरनेट खोज है' (romanized internet khoj hai, is there internet search) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "वेब खोज है"',
  "        description \"Hindi phrase 'वेब खोज है' (romanized veb khoj hai, is there web search) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "सर्च इंजन से जुड़े"',
  "        description \"Hindi phrase 'सर्च इंजन से जुड़े' (romanized sarch injan se jude, connected to a search engine) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "खोज इंजन से जुड़े"',
  "        description \"Hindi phrase 'खोज इंजन से जुड़े' (romanized khoj injan se jude, connected to a search engine) naming the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "web search"',
  "        description \"English loanword 'web search' as used in Chinese prompts for the web-search capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "搜索引擎"',
  "        description \"Chinese form '搜索引擎' (pinyin sousuo yinqing, search engine) naming the web-search capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "上网搜索"',
  "        description \"Chinese form '上网搜索' (pinyin shangwang sousuo, go online to search) naming the web-search capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "搜索互联网"',
  "        description \"Chinese form '搜索互联网' (pinyin sousuo hulianwang, search the internet) naming the web-search capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "搜索网络"',
  "        description \"Chinese form '搜索网络' (pinyin sousuo wangluo, search the web) naming the web-search capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "联网搜索"',
  "        description \"Chinese form '联网搜索' (pinyin lianwang sousuo, networked search) naming the web-search capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "用搜索引擎"',
  "        description \"Chinese form '用搜索引擎' (pinyin yong sousuo yinqing, use a search engine) naming the web-search capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "使用搜索引擎"',
  "        description \"Chinese form '使用搜索引擎' (pinyin shiyong sousuo yinqing, use a search engine) naming the web-search capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "网络搜索"',
  "        description \"Chinese form '网络搜索' (pinyin wangluo sousuo, web search) naming the web-search capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_diagnostics"',
  '    gloss "the diagnostic-trace capability — showing the reasoning trace behind an answer. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; availability is gated at runtime by diagnostic mode."',
  '    wiktionary "diagnostics"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "diagnostics"',
  "        description \"English form 'diagnostics' naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "diagnostic"',
  "        description \"English form 'diagnostic' naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "trace"',
  "        description \"English form 'trace' naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "reasoning trace"',
  "        description \"English form 'reasoning trace' naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "show diagnostics"',
  "        description \"English form 'show diagnostics' naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "диагностика"',
  "        description \"Russian noun 'диагностика' (romanized diagnostika, diagnostics) naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "диагност"',
  "        description \"Russian stem 'диагност' (romanized diagnost, diagnostic-) naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring (a stem, so it also catches diagnostika and related forms).\"",
  '      word "трассировка"',
  "        description \"Russian noun 'трассировка' (romanized trassirovka, trace) naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "trace"',
  "        description \"English loanword 'trace' as used in Russian prompts for the diagnostic-trace capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "diagnostics"',
  "        description \"English loanword 'diagnostics' as used in Hindi prompts for the diagnostic-trace capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "निदान"',
  "        description \"Hindi noun 'निदान' (romanized nidan, diagnosis) naming the diagnostic-trace capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "trace"',
  "        description \"English loanword 'trace' as used in Hindi prompts for the diagnostic-trace capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "诊断"',
  "        description \"Chinese form '诊断' (pinyin zhenduan, diagnostics) naming the diagnostic-trace capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "trace"',
  "        description \"English loanword 'trace' as used in Chinese prompts for the diagnostic-trace capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "推理跟踪"',
  "        description \"Chinese form '推理跟踪' (pinyin tuili genzong, reasoning trace) naming the diagnostic-trace capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_agent_mode"',
  '    gloss "the agent-mode capability — multi-step, autonomous tool use. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; availability is gated at runtime by agent mode."',
  '    wiktionary "agent"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "agent mode"',
  "        description \"English form 'agent mode' naming the agent-mode capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "agent"',
  "        description \"English form 'agent' naming the agent-mode capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "multi-step"',
  "        description \"English form 'multi-step' naming the agent-mode capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "autonomous"',
  "        description \"English form 'autonomous' naming the agent-mode capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "agent mode"',
  "        description \"English loanword 'agent mode' as used in Russian prompts for the agent-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "агент"',
  "        description \"Russian noun 'агент' (romanized agent, agent) naming the agent-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "многошаг"',
  "        description \"Russian stem 'многошаг' (romanized mnogoshag, multi-step) naming the agent-mode capability; a feature_capability_alias matched as a raw substring (a stem, so it also catches mnogoshagovyy).\"",
  '      word "автоном"',
  "        description \"Russian stem 'автоном' (romanized avtonom, autonomous) naming the agent-mode capability; a feature_capability_alias matched as a raw substring (a stem, so it also catches avtonomnyy).\"",
  '    lexeme "hi"',
  '      word "agent mode"',
  "        description \"English loanword 'agent mode' as used in Hindi prompts for the agent-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "एजेंट"',
  "        description \"Hindi noun 'एजेंट' (romanized ejent, agent — a loanword) naming the agent-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "multi-step"',
  "        description \"English loanword 'multi-step' as used in Hindi prompts for the agent-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "agent mode"',
  "        description \"English loanword 'agent mode' as used in Chinese prompts for the agent-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "代理"',
  "        description \"Chinese form '代理' (pinyin daili, agent or proxy) naming the agent-mode capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "多步骤"',
  "        description \"Chinese form '多步骤' (pinyin duo buzhou, multi-step) naming the agent-mode capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_definition_fusion"',
  '    gloss "the automatic-definition-fusion capability — merging overlapping definitions automatically. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; availability is gated at runtime by the definition-fusion-by-default setting."',
  '    wiktionary "fusion"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "definition fusion"',
  "        description \"English form 'definition fusion' naming the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "merge definitions"',
  "        description \"English form 'merge definitions' naming the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "automatic definition"',
  "        description \"English form 'automatic definition' naming the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "слияние определений"',
  "        description \"Russian phrase 'слияние определений' (romanized sliyanie opredeleniy, fusion of definitions) naming the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "объединение определений"',
  "        description \"Russian phrase 'объединение определений' (romanized obedinenie opredeleniy, merging of definitions) naming the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "definition fusion"',
  "        description \"English loanword 'definition fusion' as used in Hindi prompts for the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "merge definitions"',
  "        description \"English loanword 'merge definitions' as used in Hindi prompts for the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "परिभाषा विलय"',
  "        description \"Hindi phrase 'परिभाषा विलय' (romanized paribhasha vilay, definition fusion) naming the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "definition fusion"',
  "        description \"English loanword 'definition fusion' as used in Chinese prompts for the automatic-definition-fusion capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "合并定义"',
  "        description \"Chinese phrase '合并定义' (pinyin hebing dingyi, merge definitions) naming the automatic-definition-fusion capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_configuration"',
  '    gloss "the message-driven configuration capability — changing settings, theme, language, and chat style from chat messages. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "configuration"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "settings"',
  "        description \"English form 'settings' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "configuration"',
  "        description \"English form 'configuration' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "configure settings"',
  "        description \"English form 'configure settings' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "theme"',
  "        description \"English form 'theme' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "language"',
  "        description \"English form 'language' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "chat style"',
  "        description \"English form 'chat style' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "configure"',
  "        description \"English form 'configure' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "preferences"',
  "        description \"English form 'preferences' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "composer style"',
  "        description \"English form 'composer style' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "ui skin"',
  "        description \"English form 'ui skin' naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "настройки"',
  "        description \"Russian noun 'настройки' (romanized nastroyki, settings) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "настройка"',
  "        description \"Russian noun 'настройка' (romanized nastroyka, setting) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "конфигурация"',
  "        description \"Russian noun 'конфигурация' (romanized konfiguratsiya, configuration) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "тема"',
  "        description \"Russian noun 'тема' (romanized tema, theme) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "язык"',
  "        description \"Russian noun 'язык' (romanized yazyk, language) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "стиль чата"',
  "        description \"Russian phrase 'стиль чата' (romanized stil chata, chat style) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "оформление"',
  "        description \"Russian noun 'оформление' (romanized oformlenie, styling or appearance) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "настрой"',
  "        description \"Russian stem 'настрой' (romanized nastroy, configure — imperative) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring (a stem, so it also catches nastroyka and nastroyki).\"",
  '      word "конфигурац"',
  "        description \"Russian stem 'конфигурац' (romanized konfigurats, configurat-) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring (a stem, so it also catches konfiguratsiya and konfiguratsiyu).\"",
  '      word "параметр"',
  "        description \"Russian noun 'параметр' (romanized parametr, parameter) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "settings"',
  "        description \"English loanword 'settings' as used in Hindi prompts for the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "configuration"',
  "        description \"English loanword 'configuration' as used in Hindi prompts for the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "theme"',
  "        description \"English loanword 'theme' as used in Hindi prompts for the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "language"',
  "        description \"English loanword 'language' as used in Hindi prompts for the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "सेटिंग"',
  "        description \"Hindi noun 'सेटिंग' (romanized seting, settings — a loanword) naming the message-driven configuration capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "设置"',
  "        description \"Chinese form '设置' (pinyin shezhi, settings) naming the message-driven configuration capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "配置"',
  "        description \"Chinese form '配置' (pinyin peizhi, configuration) naming the message-driven configuration capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "主题"',
  "        description \"Chinese form '主题' (pinyin zhuti, theme) naming the message-driven configuration capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "语言"',
  "        description \"Chinese form '语言' (pinyin yuyan, language) naming the message-driven configuration capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "聊天样式"',
  "        description \"Chinese phrase '聊天样式' (pinyin liaotian yangshi, chat style) naming the message-driven configuration capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_memory_actions"',
  '    gloss "the memory import/export capability — saving and loading conversation memory. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "memory"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "export memory"',
  "        description \"English form 'export memory' naming the memory import/export capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "import memory"',
  "        description \"English form 'import memory' naming the memory import/export capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "memory export"',
  "        description \"English form 'memory export' naming the memory import/export capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "memory import"',
  "        description \"English form 'memory import' naming the memory import/export capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "экспорт памяти"',
  "        description \"Russian phrase 'экспорт памяти' (romanized eksport pamyati, memory export) naming the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "импорт памяти"',
  "        description \"Russian phrase 'импорт памяти' (romanized import pamyati, memory import) naming the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "память экспорт"',
  "        description \"Russian phrase 'память экспорт' (romanized pamyat eksport, memory export) naming the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "память импорт"',
  "        description \"Russian phrase 'память импорт' (romanized pamyat import, memory import) naming the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "memory export"',
  "        description \"English loanword 'memory export' as used in Hindi prompts for the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "memory import"',
  "        description \"English loanword 'memory import' as used in Hindi prompts for the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "स्मृति निर्यात"',
  "        description \"Hindi phrase 'स्मृति निर्यात' (romanized smriti niryat, memory export) naming the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "स्मृति आयात"',
  "        description \"Hindi phrase 'स्मृति आयात' (romanized smriti aayat, memory import) naming the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "导出记忆"',
  "        description \"Chinese phrase '导出记忆' (pinyin daochu jiyi, export memory) naming the memory import/export capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "导入记忆"',
  "        description \"Chinese phrase '导入记忆' (pinyin daoru jiyi, import memory) naming the memory import/export capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "memory export"',
  "        description \"English loanword 'memory export' as used in Chinese prompts for the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "memory import"',
  "        description \"English loanword 'memory import' as used in Chinese prompts for the memory import/export capability; a feature_capability_alias matched as a raw substring.\"",
  '  meaning "feature_capability_greeting"',
  '    gloss "the greeting capability — recognising and answering hellos. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "greeting"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "greeting"',
  "        description \"English form 'greeting' naming the greeting capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "greetings"',
  "        description \"English form 'greetings' naming the greeting capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "say hello"',
  "        description \"English form 'say hello' naming the greeting capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "respond to hello"',
  "        description \"English form 'respond to hello' naming the greeting capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "приветствие"',
  "        description \"Russian noun 'приветствие' (romanized privetstvie, greeting) naming the greeting capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "приветствия"',
  "        description \"Russian noun 'приветствия' (romanized privetstviya, greetings) naming the greeting capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "здороваться"',
  "        description \"Russian verb 'здороваться' (romanized zdorovatsya, to greet) naming the greeting capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "привет"',
  "        description \"Russian word 'привет' (romanized privet, hi) naming the greeting capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "अभिवादन"',
  "        description \"Hindi noun 'अभिवादन' (romanized abhivadan, greeting) naming the greeting capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "नमस्ते"',
  "        description \"Hindi word 'नमस्ते' (romanized namaste, hello) naming the greeting capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "hello"',
  "        description \"English loanword 'hello' as used in Hindi prompts for the greeting capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "问候"',
  "        description \"Chinese form '问候' (pinyin wenhou, greeting) naming the greeting capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "打招呼"',
  "        description \"Chinese form '打招呼' (pinyin da zhaohu, to greet) naming the greeting capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "你好"',
  "        description \"Chinese word '你好' (pinyin nihao, hello) naming the greeting capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_write_program"',
  '    gloss "the program-template generation capability — writing small programs and hello-world templates. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "program"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "hello world"',
  "        description \"English form 'hello world' naming the program-template generation capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "write code"',
  "        description \"English form 'write code' naming the program-template generation capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "generate code"',
  "        description \"English form 'generate code' naming the program-template generation capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "write program"',
  "        description \"English form 'write program' naming the program-template generation capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "program"',
  "        description \"English form 'program' naming the program-template generation capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "hello world"',
  "        description \"English loanword 'hello world' as used in Russian prompts for the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "код"',
  "        description \"Russian noun 'код' (romanized kod, code) naming the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "программу"',
  "        description \"Russian noun 'программу' (romanized programmu, program — accusative) naming the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "программа"',
  "        description \"Russian noun 'программа' (romanized programma, program) naming the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "hello world"',
  "        description \"English loanword 'hello world' as used in Hindi prompts for the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "code"',
  "        description \"English loanword 'code' as used in Hindi prompts for the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "program"',
  "        description \"English loanword 'program' as used in Hindi prompts for the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "प्रोग्राम"',
  "        description \"Hindi noun 'प्रोग्राम' (romanized program, program — a loanword) naming the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "hello world"',
  "        description \"English loanword 'hello world' as used in Chinese prompts for the program-template generation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "代码"',
  "        description \"Chinese form '代码' (pinyin daima, code) naming the program-template generation capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "程序"',
  "        description \"Chinese form '程序' (pinyin chengxu, program) naming the program-template generation capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_concept_lookup"',
  '    gloss "the concept-lookup capability — explaining a concept or term. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "concept"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "concept lookup"',
  "        description \"English form 'concept lookup' naming the concept-lookup capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "concept"',
  "        description \"English form 'concept' naming the concept-lookup capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "wikipedia lookup"',
  "        description \"English form 'wikipedia lookup' naming the concept-lookup capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "поиск понятий"',
  "        description \"Russian phrase 'поиск понятий' (romanized poisk ponyatiy, concept lookup) naming the concept-lookup capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "понятие"',
  "        description \"Russian noun 'понятие' (romanized ponyatie, concept) naming the concept-lookup capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "concept"',
  "        description \"English loanword 'concept' as used in Hindi prompts for the concept-lookup capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "अवधारणा"',
  "        description \"Hindi noun 'अवधारणा' (romanized avadharana, concept) naming the concept-lookup capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "概念"',
  "        description \"Chinese form '概念' (pinyin gainian, concept) naming the concept-lookup capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_arithmetic"',
  '    gloss "the arithmetic capability — evaluating numeric expressions. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available. When a capability question is itself an arithmetic action request (see feature_action_arithmetic) the handler defers to the arithmetic solver instead."',
  '    wiktionary "arithmetic"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "arithmetic"',
  "        description \"English form 'arithmetic' naming the arithmetic capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "calculate"',
  "        description \"English form 'calculate' naming the arithmetic capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "math"',
  "        description \"English form 'math' naming the arithmetic capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "2 + 2"',
  "        description \"The numeric expression '2 + 2' (language-independent) exemplifying the arithmetic capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "арифмет"',
  "        description \"Russian stem 'арифмет' (romanized arifmet, arithmetic-) naming the arithmetic capability; a feature_capability_alias matched as a raw substring (a stem, so it also catches arifmetika).\"",
  '      word "считать"',
  "        description \"Russian verb 'считать' (romanized schitat, to count or calculate) naming the arithmetic capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "посчитать"',
  "        description \"Russian verb 'посчитать' (romanized poschitat, to compute) naming the arithmetic capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "2 + 2"',
  "        description \"The numeric expression '2 + 2' (language-independent) exemplifying the arithmetic capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "hi"',
  '      word "अंकगणित"',
  "        description \"Hindi noun 'अंकगणित' (romanized ankganit, arithmetic) naming the arithmetic capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "गणना"',
  "        description \"Hindi noun 'गणना' (romanized ganana, calculation) naming the arithmetic capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "math"',
  "        description \"English loanword 'math' as used in Hindi prompts for the arithmetic capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "2 + 2"',
  "        description \"The numeric expression '2 + 2' (language-independent) exemplifying the arithmetic capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "zh"',
  '      word "算术"',
  "        description \"Chinese form '算术' (pinyin suanshu, arithmetic) naming the arithmetic capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "计算"',
  "        description \"Chinese form '计算' (pinyin jisuan, calculate) naming the arithmetic capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "数学"',
  "        description \"Chinese form '数学' (pinyin shuxue, math) naming the arithmetic capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "2 + 2"',
  "        description \"The numeric expression '2 + 2' (language-independent) exemplifying the arithmetic capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '  meaning "feature_capability_translation"',
  '    gloss "the translation capability — translating text between languages. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "translation"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "translation"',
  "        description \"English form 'translation' naming the translation capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "translate"',
  "        description \"English form 'translate' naming the translation capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "language translation"',
  "        description \"English form 'language translation' naming the translation capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "перевод"',
  "        description \"Russian noun 'перевод' (romanized perevod, translation) naming the translation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "переводить"',
  "        description \"Russian verb 'переводить' (romanized perevodit, to translate) naming the translation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "перевести"',
  "        description \"Russian verb 'перевести' (romanized perevesti, to translate — perfective) naming the translation capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "अनुवाद"',
  "        description \"Hindi noun 'अनुवाद' (romanized anuvad, translation) naming the translation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "translate"',
  "        description \"English loanword 'translate' as used in Hindi prompts for the translation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "translation"',
  "        description \"English loanword 'translation' as used in Hindi prompts for the translation capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "翻译"',
  "        description \"Chinese form '翻译' (pinyin fanyi, translation) naming the translation capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "translation"',
  "        description \"English loanword 'translation' as used in Chinese prompts for the translation capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "translate"',
  "        description \"English loanword 'translate' as used in Chinese prompts for the translation capability; a feature_capability_alias matched as a raw substring.\"",
  '  meaning "feature_capability_memory"',
  '    gloss "the conversation-memory capability — remembering and recalling facts stated earlier. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "memory"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "memory"',
  "        description \"English form 'memory' naming the conversation-memory capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "remember"',
  "        description \"English form 'remember' naming the conversation-memory capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "recall"',
  "        description \"English form 'recall' naming the conversation-memory capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "conversation context"',
  "        description \"English form 'conversation context' naming the conversation-memory capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "память"',
  "        description \"Russian noun 'память' (romanized pamyat, memory) naming the conversation-memory capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "помнить"',
  "        description \"Russian verb 'помнить' (romanized pomnit, to remember) naming the conversation-memory capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "запомнить"',
  "        description \"Russian verb 'запомнить' (romanized zapomnit, to memorize) naming the conversation-memory capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "контекст"',
  "        description \"Russian noun 'контекст' (romanized kontekst, context) naming the conversation-memory capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "स्मृति"',
  "        description \"Hindi noun 'स्मृति' (romanized smriti, memory) naming the conversation-memory capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "याद"',
  "        description \"Hindi noun 'याद' (romanized yaad, memory or recall) naming the conversation-memory capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "memory"',
  "        description \"English loanword 'memory' as used in Hindi prompts for the conversation-memory capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "context"',
  "        description \"English loanword 'context' as used in Hindi prompts for the conversation-memory capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "记忆"',
  "        description \"Chinese form '记忆' (pinyin jiyi, memory) naming the conversation-memory capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "记住"',
  "        description \"Chinese form '记住' (pinyin jizhu, to remember) naming the conversation-memory capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "回忆"',
  "        description \"Chinese form '回忆' (pinyin huiyi, to recall) naming the conversation-memory capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "上下文"',
  "        description \"Chinese form '上下文' (pinyin shangxiawen, context) naming the conversation-memory capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_demo_mode"',
  '    gloss "the demo-mode capability — a scripted demonstration mode. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "demo"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "demo mode"',
  "        description \"English form 'demo mode' naming the demo-mode capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "demo"',
  "        description \"English form 'demo' naming the demo-mode capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "scripted demo"',
  "        description \"English form 'scripted demo' naming the demo-mode capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "демо"',
  "        description \"Russian noun 'демо' (romanized demo, demo — a loanword) naming the demo-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "демо-режим"',
  "        description \"Russian noun 'демо-режим' (romanized demo-rezhim, demo mode) naming the demo-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "сценарный демо"',
  "        description \"Russian phrase 'сценарный демо' (romanized stsenarnyy demo, scripted demo) naming the demo-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "demo"',
  "        description \"English loanword 'demo' as used in Hindi prompts for the demo-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "डेमो"',
  "        description \"Hindi noun 'डेमो' (romanized demo, demo — a loanword) naming the demo-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "demo"',
  "        description \"English loanword 'demo' as used in Chinese prompts for the demo-mode capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "演示"',
  "        description \"Chinese form '演示' (pinyin yanshi, demonstration) naming the demo-mode capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_http_url"',
  '    gloss "the URL-navigation and HTTP-fetch capability — fetching and visiting URLs. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "URL"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "http fetch"',
  "        description \"English form 'http fetch' naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "fetch url"',
  "        description \"English form 'fetch url' naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "open url"',
  "        description \"English form 'open url' naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "navigate to url"',
  "        description \"English form 'navigate to url' naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "visit url"',
  "        description \"English form 'visit url' naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "url navigation"',
  "        description \"English form 'url navigation' naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "http запрос"',
  "        description \"Russian phrase 'http запрос' (romanized http zapros, http request) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "открыть url"',
  "        description \"Russian phrase 'открыть url' (romanized otkryt url, open url) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "перейти на"',
  "        description \"Russian phrase 'перейти на' (romanized pereyti na, navigate to) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring (a phrase stem followed by a target).\"",
  '      word "сделать запрос"',
  "        description \"Russian phrase 'сделать запрос' (romanized sdelat zapros, make a request) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "url-навигация"',
  "        description \"Russian phrase 'url-навигация' (romanized url-navigatsiya, url navigation) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "url навигация"',
  "        description \"Russian phrase 'url навигация' (romanized url navigatsiya, url navigation) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "http fetch"',
  "        description \"English loanword 'http fetch' as used in Hindi prompts for the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "url"',
  "        description \"English loanword 'url' as used in Hindi prompts for the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "navigate"',
  "        description \"English loanword 'navigate' as used in Hindi prompts for the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "लिंक"',
  "        description \"Hindi noun 'लिंक' (romanized link, link — a loanword) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "यूआरएल"',
  "        description \"Hindi noun 'यूआरएल' (romanized yuaarel, URL — a loanword) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "http fetch"',
  "        description \"English loanword 'http fetch' as used in Chinese prompts for the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "url"',
  "        description \"English loanword 'url' as used in Chinese prompts for the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "打开链接"',
  "        description \"Chinese phrase '打开链接' (pinyin dakai lianjie, open link) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "访问链接"',
  "        description \"Chinese phrase '访问链接' (pinyin fangwen lianjie, visit link) naming the URL-navigation and HTTP-fetch capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_javascript_execution"',
  '    gloss "the JavaScript-execution capability — running a deterministic JavaScript subset. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available."',
  '    wiktionary "JavaScript"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "javascript"',
  "        description \"English form 'javascript' naming the JavaScript-execution capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "run javascript"',
  "        description \"English form 'run javascript' naming the JavaScript-execution capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "execute javascript"',
  "        description \"English form 'execute javascript' naming the JavaScript-execution capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "js"',
  "        description \"English form 'js' naming the JavaScript-execution capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "javascript"',
  "        description \"English loanword 'javascript' as used in Russian prompts for the JavaScript-execution capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "js"',
  "        description \"English loanword 'js' as used in Russian prompts for the JavaScript-execution capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "выполнить javascript"',
  "        description \"Russian phrase 'выполнить javascript' (romanized vypolnit javascript, execute javascript) naming the JavaScript-execution capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "javascript"',
  "        description \"English loanword 'javascript' as used in Hindi prompts for the JavaScript-execution capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "js"',
  "        description \"English loanword 'js' as used in Hindi prompts for the JavaScript-execution capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "स्क्रिप्ट"',
  "        description \"Hindi noun 'स्क्रिप्ट' (romanized skript, script — a loanword) naming the JavaScript-execution capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "javascript"',
  "        description \"English loanword 'javascript' as used in Chinese prompts for the JavaScript-execution capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "js"',
  "        description \"English loanword 'js' as used in Chinese prompts for the JavaScript-execution capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "脚本执行"',
  "        description \"Chinese phrase '脚本执行' (pinyin jiaoben zhixing, script execution) naming the JavaScript-execution capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "执行脚本"',
  "        description \"Chinese phrase '执行脚本' (pinyin zhixing jiaoben, execute script) naming the JavaScript-execution capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_planning"',
  '    gloss "the planning capability — summaries, brainstorming, roleplay, and project planning. A feature_capability_alias meaning whose multilingual forms the feature-capability handler matches as raw substrings in declaration (priority) order, so no surface alias lives in the code; this capability is always available. When a capability question is itself a planning action request (see feature_action_planning) the handler defers to the primary planning handler instead."',
  '    wiktionary "planning"',
  '    defined_by "concept"',
  '    role "feature_capability_alias"',
  '    lexeme "en"',
  '      word "summarize"',
  "        description \"English form 'summarize' naming the planning capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "brainstorm"',
  "        description \"English form 'brainstorm' naming the planning capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "roleplay"',
  "        description \"English form 'roleplay' naming the planning capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "software project"',
  "        description \"English form 'software project' naming the planning capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '      word "project plan"',
  "        description \"English form 'project plan' naming the planning capability; a feature_capability_alias matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "резюмировать"',
  "        description \"Russian verb 'резюмировать' (romanized rezyumirovat, to summarize) naming the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "брейншторм"',
  "        description \"Russian noun 'брейншторм' (romanized breynshtorm, brainstorm — a loanword) naming the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "роль"',
  "        description \"Russian noun 'роль' (romanized rol, role) naming the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "проект"',
  "        description \"Russian noun 'проект' (romanized proekt, project) naming the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "план проекта"',
  "        description \"Russian phrase 'план проекта' (romanized plan proekta, project plan) naming the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "summary"',
  "        description \"English loanword 'summary' as used in Hindi prompts for the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "brainstorm"',
  "        description \"English loanword 'brainstorm' as used in Hindi prompts for the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "roleplay"',
  "        description \"English loanword 'roleplay' as used in Hindi prompts for the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "project plan"',
  "        description \"English loanword 'project plan' as used in Hindi prompts for the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '      word "परियोजना योजना"',
  "        description \"Hindi phrase 'परियोजना योजना' (romanized pariyojana yojana, project plan) naming the planning capability; a feature_capability_alias matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "总结"',
  "        description \"Chinese form '总结' (pinyin zongjie, to summarize) naming the planning capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "头脑风暴"',
  "        description \"Chinese phrase '头脑风暴' (pinyin tounao fengbao, brainstorm) naming the planning capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "角色扮演"',
  "        description \"Chinese phrase '角色扮演' (pinyin juese banyan, roleplay) naming the planning capability; a feature_capability_alias matched as a Han substring.\"",
  '      word "项目计划"',
  "        description \"Chinese phrase '项目计划' (pinyin xiangmu jihua, project plan) naming the planning capability; a feature_capability_alias matched as a Han substring.\"",
  '  meaning "feature_capability_question"',
  "    gloss \"the interrogative frame that flags a prompt as a capability question — cues such as 'can you ...?', 'у тебя есть ...?', '能...?', and 'क्या ...?'. A feature_capability_question meaning: before it looks for a named feature, the feature-capability handler checks these cues through mentions_role_in_languages_raw against the prompt's own detected language only (English prompts additionally accept a grammatical 'is/are ... enabled/available' frame computed in code). Matched as raw substrings, so no cue word is named in the handler.\"",
  '    wiktionary "can"',
  '    defined_by "action"',
  '    role "feature_capability_question"',
  '    lexeme "en"',
  '      word "can you"',
  "        description \"English interrogative cue 'can you'; a feature_capability_question cue matched as a raw substring that flags the prompt as a capability question.\"",
  '      word "can formal-ai"',
  "        description \"English interrogative cue 'can formal-ai'; a feature_capability_question cue matched as a raw substring that flags the prompt as a capability question.\"",
  '      word "are you able"',
  "        description \"English interrogative cue 'are you able'; a feature_capability_question cue matched as a raw substring that flags the prompt as a capability question.\"",
  '      word "are you connected"',
  "        description \"English interrogative cue 'are you connected'; a feature_capability_question cue matched as a raw substring that flags the prompt as a capability question.\"",
  '      word "do you support"',
  "        description \"English interrogative cue 'do you support'; a feature_capability_question cue matched as a raw substring that flags the prompt as a capability question.\"",
  '      word "do you have"',
  "        description \"English interrogative cue 'do you have'; a feature_capability_question cue matched as a raw substring that flags the prompt as a capability question.\"",
  '      word "can i"',
  "        description \"English interrogative cue 'can i'; a feature_capability_question cue matched as a raw substring that flags the prompt as a capability question.\"",
  '    lexeme "ru"',
  '      word "можешь"',
  "        description \"Russian interrogative cue 'можешь' (romanized mozhesh, can you); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "умеешь"',
  "        description \"Russian interrogative cue 'умеешь' (romanized umeesh, are you able); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "поддерживаешь"',
  "        description \"Russian interrogative cue 'поддерживаешь' (romanized podderzhivaesh, do you support); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "у тебя есть"',
  "        description \"Russian interrogative cue 'у тебя есть' (romanized u tebya est, do you have); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "есть ли"',
  "        description \"Russian interrogative cue 'есть ли' (romanized est li, is there); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "доступен"',
  "        description \"Russian interrogative cue 'доступен' (romanized dostupen, available — masculine); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "доступна"',
  "        description \"Russian interrogative cue 'доступна' (romanized dostupna, available — feminine); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "включен"',
  "        description \"Russian interrogative cue 'включен' (romanized vklyuchen, enabled — masculine); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "включена"',
  "        description \"Russian interrogative cue 'включена' (romanized vklyuchena, enabled — feminine); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "подключен"',
  "        description \"Russian interrogative cue 'подключен' (romanized podklyuchen, connected — masculine); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "подключена"',
  "        description \"Russian interrogative cue 'подключена' (romanized podklyuchena, connected — feminine); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "можно ли"',
  "        description \"Russian interrogative cue 'можно ли' (romanized mozhno li, is it possible); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '    lexeme "hi"',
  '      word "क्या"',
  "        description \"Hindi interrogative cue 'क्या' (romanized kya, the question particle what or whether); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "सकते"',
  "        description \"Hindi interrogative cue 'सकते' (romanized sakte, can — formal or plural); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "सकती"',
  "        description \"Hindi interrogative cue 'सकती' (romanized sakti, can — feminine); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "समर्थन"',
  "        description \"Hindi interrogative cue 'समर्थन' (romanized samarthan, support); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '      word "उपलब्ध"',
  "        description \"Hindi interrogative cue 'उपलब्ध' (romanized uplabdh, available); a feature_capability_question cue matched as a raw substring that flags a capability question.\"",
  '    lexeme "zh"',
  '      word "能"',
  "        description \"Chinese interrogative cue '能' (pinyin neng, can); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '      word "可以"',
  "        description \"Chinese interrogative cue '可以' (pinyin keyi, can or may); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '      word "支持"',
  "        description \"Chinese interrogative cue '支持' (pinyin zhichi, support); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '      word "你有"',
  "        description \"Chinese interrogative cue '你有' (pinyin ni you, you have); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '      word "您有"',
  "        description \"Chinese interrogative cue '您有' (pinyin nin you, you have — polite); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '      word "有没有"',
  "        description \"Chinese interrogative cue '有没有' (pinyin you meiyou, is there); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '      word "是否有"',
  "        description \"Chinese interrogative cue '是否有' (pinyin shifou you, whether there is); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '      word "启用"',
  "        description \"Chinese interrogative cue '启用' (pinyin qiyong, to enable); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '      word "可用"',
  "        description \"Chinese interrogative cue '可用' (pinyin keyong, available); a feature_capability_question cue matched as a Han substring that flags a capability question.\"",
  '  meaning "feature_action_arithmetic"',
  "    gloss \"an action-request frame asking the assistant to actually perform a calculation — 'can you calculate ...', 'can you compute ...'. A feature_action_arithmetic meaning: when a detected capability question also opens with one of these English frames, reconstructed as a space-padded prefix, the handler steps aside so the arithmetic solver answers instead of reporting availability. Only the English frames drive the gate, read through words_for_role_in_languages restricted to English; the other languages stay in the seed for self-description.\"",
  '    wiktionary "calculate"',
  '    defined_by "action"',
  '    role "feature_action_arithmetic"',
  '    lexeme "en"',
  '      word "can you calculate"',
  "        description \"English action-request frame 'can you calculate'; a feature_action_arithmetic cue reconstructed as a space-padded prefix, so when the prompt opens with it the capability handler defers to the arithmetic solver.\"",
  '      word "can you compute"',
  "        description \"English action-request frame 'can you compute'; a feature_action_arithmetic cue reconstructed as a space-padded prefix, so when the prompt opens with it the capability handler defers to the arithmetic solver.\"",
  '    lexeme "ru"',
  '      word "можешь вычислить"',
  "        description \"Russian phrase 'можешь вычислить' (romanized mozhesh vychislit, can you calculate); a feature_action_arithmetic form kept in the seed for self-description (only the English frames drive the action gate).\"",
  '      word "можешь посчитать"',
  "        description \"Russian phrase 'можешь посчитать' (romanized mozhesh poschitat, can you compute); a feature_action_arithmetic form kept in the seed for self-description (only the English frames drive the action gate).\"",
  '    lexeme "hi"',
  '      word "क्या आप गणना कर सकते"',
  "        description \"Hindi phrase 'क्या आप गणना कर सकते' (romanized kya aap ganana kar sakte, can you calculate); a feature_action_arithmetic form kept in the seed for self-description (only the English frames drive the action gate).\"",
  '    lexeme "zh"',
  '      word "你能计算"',
  "        description \"Chinese phrase '你能计算' (pinyin ni neng jisuan, can you calculate); a feature_action_arithmetic form kept in the seed for self-description (only the English frames drive the action gate).\"",
  '  meaning "feature_action_planning"',
  "    gloss \"an action-request frame asking the assistant to actually perform a planning task — 'can you summarize ...', 'can you brainstorm ...', 'can you roleplay ...'. A feature_action_planning meaning: when a detected capability question also contains one of these English frames, reconstructed as a space-padded token, the handler steps aside so the primary planning handler answers. Only the English frames drive the gate, read through words_for_role_in_languages restricted to English; the other languages stay in the seed for self-description.\"",
  '    wiktionary "summarize"',
  '    defined_by "action"',
  '    role "feature_action_planning"',
  '    lexeme "en"',
  '      word "can you summarize"',
  "        description \"English action-request frame 'can you summarize'; a feature_action_planning cue reconstructed as a space-padded token, so when the prompt contains it the capability handler defers to the primary handler.\"",
  '      word "can you brainstorm"',
  "        description \"English action-request frame 'can you brainstorm'; a feature_action_planning cue reconstructed as a space-padded token, so when the prompt contains it the capability handler defers to the primary handler.\"",
  '      word "can you roleplay"',
  "        description \"English action-request frame 'can you roleplay'; a feature_action_planning cue reconstructed as a space-padded token, so when the prompt contains it the capability handler defers to the primary handler.\"",
  '    lexeme "ru"',
  '      word "можешь резюмировать"',
  "        description \"Russian phrase 'можешь резюмировать' (romanized mozhesh rezyumirovat, can you summarize); a feature_action_planning form kept in the seed for self-description (only the English frames drive the action gate).\"",
  '      word "можешь провести мозговой штурм"',
  "        description \"Russian phrase 'можешь провести мозговой штурм' (romanized mozhesh provesti mozgovoy shturm, can you brainstorm); a feature_action_planning form kept in the seed for self-description (only the English frames drive the action gate).\"",
  '      word "можешь сыграть роль"',
  "        description \"Russian phrase 'можешь сыграть роль' (romanized mozhesh sygrat rol, can you roleplay); a feature_action_planning form kept in the seed for self-description (only the English frames drive the action gate).\"",
  '    lexeme "hi"',
  '      word "क्या आप सारांश कर सकते"',
  "        description \"Hindi phrase 'क्या आप सारांश कर सकते' (romanized kya aap saraansh kar sakte, can you summarize); a feature_action_planning form kept in the seed for self-description (only the English frames drive the action gate).\"",
  '    lexeme "zh"',
  '      word "你能总结"',
  "        description \"Chinese phrase '你能总结' (pinyin ni neng zongjie, can you summarize); a feature_action_planning form kept in the seed for self-description (only the English frames drive the action gate).\"",
  "meanings",
  '  meaning "playwright"',
  "    gloss \"the Playwright browser-automation and end-to-end testing tool — the named entity a 'write me a Playwright script' request is about. The playwright-script handler asks whether the tool is named by walking this meaning's forms through mentions_role_raw (a raw substring check across every language), so the proper noun lives here, not in the code. One English form is the common misspelling 'playright'; it carries an action naming the canonical spelling 'playwright', and the handler reports a spelling correction when a form whose action is set occurs in the prompt — so the typo and its fix are data, not a literal in the code.\"",
  '    wiktionary "playwright"',
  '    defined_by "entity"',
  '    role "playwright_tool_name"',
  '    lexeme "en"',
  '      word "playwright"',
  '        description "English proper noun naming the Playwright automation tool; a playwright_tool_name matched as a raw substring of the normalized prompt."',
  '      word "playright"',
  "        description \"English misspelling of 'playwright' (the 'w' dropped); a playwright_tool_name matched as a raw substring. Its action names the canonical spelling, so the handler reports the correction without naming either form in the code.\"",
  '        action "playwright"',
  '    lexeme "ru"',
  '      word "плейврайт"',
  "        description \"Russian transliteration 'плейврайт' (romanized pleyvrayt) of the Playwright tool name; a playwright_tool_name matched as a raw substring.\"",
  '      word "плейрайт"',
  "        description \"Russian transliteration 'плейрайт' (romanized pleyrayt) of the common 'playright' misspelling; a playwright_tool_name matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "प्लेराइट"',
  "        description \"Hindi transliteration 'प्लेराइट' (romanized pleraait) of the Playwright tool name; a playwright_tool_name matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "普莱赖特"',
  "        description \"Chinese phonetic transliteration '普莱赖特' (pinyin pulailaite) of the Playwright tool name; a playwright_tool_name matched as a raw substring.\"",
  '  meaning "playwright_script_request_cue"',
  '    gloss "a cue that a prompt naming Playwright is asking for a script rather than discussing the tool — an artifact noun (script, test, spec, code) or an authoring frame (write, create, generate, make, build, can you, could you, and their other-language equivalents). The playwright-script handler routes only when a playwright_tool_name and one of these cues both occur, each checked through mentions_role_raw (a raw substring across every language), so the cue vocabulary lives in the data rather than in a hand-listed array in the code."',
  '    wiktionary "script"',
  '    defined_by "concept"',
  '    role "playwright_script_cue"',
  '    lexeme "en"',
  '      word "script"',
  "        description \"English noun 'script' naming the artifact to author; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "test"',
  "        description \"English noun 'test' naming the artifact to author; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "spec"',
  "        description \"English noun 'spec' (specification) naming the artifact to author; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "code"',
  "        description \"English noun 'code' naming the artifact to author; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "write"',
  "        description \"English verb 'write' opening an authoring request; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "create"',
  "        description \"English verb 'create' opening an authoring request; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "generate"',
  "        description \"English verb 'generate' opening an authoring request; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "make"',
  "        description \"English verb 'make' opening an authoring request; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "build"',
  "        description \"English verb 'build' opening an authoring request; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "can you"',
  "        description \"English polite frame 'can you' opening an authoring request; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '      word "could you"',
  "        description \"English polite frame 'could you' opening an authoring request; a playwright_script_cue matched as a raw substring of the normalized prompt.\"",
  '    lexeme "ru"',
  '      word "скрипт"',
  "        description \"Russian noun 'скрипт' (romanized skript, script) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "сценар"',
  "        description \"Russian stem 'сценар' (romanized stsenar) of 'сценарий' (scenario/script); a playwright_script_cue matched as a raw substring so the inflected forms are caught.\"",
  '      word "тест"',
  "        description \"Russian noun 'тест' (romanized test) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "код"',
  "        description \"Russian noun 'код' (romanized kod, code) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "напиши"',
  "        description \"Russian imperative 'напиши' (romanized napishi, write) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  '      word "написать"',
  "        description \"Russian infinitive 'написать' (romanized napisat, to write) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  '      word "можешь"',
  "        description \"Russian frame 'можешь' (romanized mozhesh, can you) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  '      word "сделай"',
  "        description \"Russian imperative 'сделай' (romanized sdelay, make) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  '      word "создай"',
  "        description \"Russian imperative 'создай' (romanized sozday, create) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "स्क्रिप्ट"',
  "        description \"Hindi noun 'स्क्रिप्ट' (romanized skript, script) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "टेस्ट"',
  "        description \"Hindi noun 'टेस्ट' (romanized test) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "कोड"',
  "        description \"Hindi noun 'कोड' (romanized kod, code) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "लिखो"',
  "        description \"Hindi imperative 'लिखो' (romanized likho, write) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  '      word "बनाओ"',
  "        description \"Hindi imperative 'बनाओ' (romanized banao, make/create) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "脚本"',
  "        description \"Chinese noun '脚本' (pinyin jiaoben, script) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "测试"',
  "        description \"Chinese noun '测试' (pinyin ceshi, test) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "代码"',
  "        description \"Chinese noun '代码' (pinyin daima, code) naming the artifact to author; a playwright_script_cue matched as a raw substring.\"",
  '      word "写"',
  "        description \"Chinese verb '写' (pinyin xie, write) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  '      word "生成"',
  "        description \"Chinese verb '生成' (pinyin shengcheng, generate) opening an authoring request; a playwright_script_cue matched as a raw substring.\"",
  "meanings",
  '  meaning "compare"',
  "    gloss \"the act of comparing two or more topics, and the request for the comparison drawn as a table. The research comparison-table handler asks whether a follow-up prompt wants a table by checking these triggers token-bounded through mentions_role; a match alone opens the handler. The phrase 'comparison table' and the verbs 'compare'/'comparing' are the strong triggers, so the surface vocabulary lives here rather than in a padded-contains list in the code.\"",
  '    wiktionary "compare"',
  '    defined_by "action"',
  '    role "comparison_table_trigger"',
  '    lexeme "en"',
  '      word "comparison table"',
  "        description \"English phrase 'comparison table' naming the requested artifact; a comparison_table_trigger matched as a whole phrase (token-bounded).\"",
  '      word "compare"',
  "        description \"English verb 'compare' asking for a comparison; a comparison_table_trigger matched as a whole token.\"",
  '      word "comparing"',
  "        description \"English gerund 'comparing' asking for a comparison; a comparison_table_trigger matched as a whole token.\"",
  '    lexeme "ru"',
  '      word "сравнительная таблица"',
  "        description \"Russian phrase 'сравнительная таблица' (romanized sravnitelnaya tablitsa, comparison table) naming the requested artifact; a comparison_table_trigger matched token-bounded.\"",
  '      word "сравнить"',
  "        description \"Russian infinitive 'сравнить' (romanized sravnit, to compare) asking for a comparison; a comparison_table_trigger matched token-bounded.\"",
  '      word "сравнение"',
  "        description \"Russian noun 'сравнение' (romanized sravnenie, comparison) asking for a comparison; a comparison_table_trigger matched token-bounded.\"",
  '    lexeme "hi"',
  '      word "तुलना तालिका"',
  "        description \"Hindi phrase 'तुलना तालिका' (romanized tulna talika, comparison table) naming the requested artifact; a comparison_table_trigger matched token-bounded.\"",
  '      word "तुलना"',
  "        description \"Hindi noun 'तुलना' (romanized tulna, comparison) asking for a comparison; a comparison_table_trigger matched token-bounded.\"",
  '    lexeme "zh"',
  '      word "比较表"',
  "        description \"Chinese phrase '比较表' (pinyin bijiaobiao, comparison table) naming the requested artifact; a comparison_table_trigger matched as a substring.\"",
  '      word "比较"',
  "        description \"Chinese verb '比较' (pinyin bijiao, compare) asking for a comparison; a comparison_table_trigger matched as a substring.\"",
  '      word "对比"',
  "        description \"Chinese verb '对比' (pinyin duibi, contrast/compare) asking for a comparison; a comparison_table_trigger matched as a substring.\"",
  '  meaning "table"',
  '    gloss "a table — a grid of rows and columns that lays values out for reading. The research comparison-table handler treats the bare noun as a weak signal: a table is requested only when the noun co-occurs with a difference cue, both checked token-bounded through mentions_role. The noun lives here so the weak-signal arm of the gate references the concept, not a literal word in the code."',
  '    wiktionary "table"',
  '    defined_by "concept"',
  '    role "comparison_table_noun"',
  '    lexeme "en"',
  '      word "table"',
  "        description \"English noun 'table' naming the grid artifact; a comparison_table_noun matched as a whole token.\"",
  '    lexeme "ru"',
  '      word "таблица"',
  "        description \"Russian noun 'таблица' (romanized tablitsa, table) naming the grid artifact; a comparison_table_noun matched token-bounded.\"",
  '    lexeme "hi"',
  '      word "तालिका"',
  "        description \"Hindi noun 'तालिका' (romanized talika, table) naming the grid artifact; a comparison_table_noun matched token-bounded.\"",
  '    lexeme "zh"',
  '      word "表格"',
  "        description \"Chinese noun '表格' (pinyin biaoge, table) naming the grid artifact; a comparison_table_noun matched as a substring.\"",
  '  meaning "differences"',
  '    gloss "the differences between compared topics — the relation that a comparison surfaces. The research comparison-table handler treats this plural cue as the partner of the bare table noun: when both occur the weak-signal arm of the gate opens, each checked token-bounded through mentions_role. The cue lives here so the code references the relation rather than a padded-contains literal."',
  '    wiktionary "difference"',
  '    defined_by "relation"',
  '    role "comparison_difference_cue"',
  '    lexeme "en"',
  '      word "differences"',
  "        description \"English plural noun 'differences' naming the relation a comparison surfaces; a comparison_difference_cue matched as a whole token.\"",
  '    lexeme "ru"',
  '      word "различия"',
  "        description \"Russian plural noun 'различия' (romanized razlichiya, differences) naming the relation a comparison surfaces; a comparison_difference_cue matched token-bounded.\"",
  '      word "отличия"',
  "        description \"Russian plural noun 'отличия' (romanized otlichiya, differences) naming the relation a comparison surfaces; a comparison_difference_cue matched token-bounded.\"",
  '    lexeme "hi"',
  '      word "अंतर"',
  "        description \"Hindi noun 'अंतर' (romanized antar, difference) naming the relation a comparison surfaces; a comparison_difference_cue matched token-bounded.\"",
  '    lexeme "zh"',
  '      word "差异"',
  "        description \"Chinese noun '差异' (pinyin chayi, difference) naming the relation a comparison surfaces; a comparison_difference_cue matched as a substring.\"",
  '      word "区别"',
  "        description \"Chinese noun '区别' (pinyin qubie, difference) naming the relation a comparison surfaces; a comparison_difference_cue matched as a substring.\"",
  '  meaning "research_prompt_signal"',
  "    gloss \"a signal that an earlier turn was a research request — the prior prompt the comparison-table follow-up reuses for its topics. Each surface marks its shape with the ellipsis … (U+2026): a trailing ellipsis is a prefix surface matched when the prompt starts with the literal before the slot; a surface with no ellipsis is a bare marker matched anywhere as a whole token. The handler reads the prefix surfaces' literals and the bare surfaces through the lexicon, so the research openers live in the data, not in a starts_with/contains list in the code.\"",
  '    wiktionary "research"',
  '    defined_by "concept"',
  '    role "research_prompt_signal"',
  '    lexeme "en"',
  '      word "search …"',
  "        description \"English prefix surface; the prompt opens with 'search ' before the query that follows the … slot (search X). A research_prompt_signal matched by prefix.\"",
  '      word "find information …"',
  "        description \"English prefix surface; the prompt opens with 'find information ' before the topic that follows the … slot. A research_prompt_signal matched by prefix.\"",
  '      word "look up information …"',
  "        description \"English prefix surface; the prompt opens with 'look up information ' before the topic that follows the … slot. A research_prompt_signal matched by prefix.\"",
  '      word "search for information"',
  "        description \"English bare marker 'search for information'; a research_prompt_signal matched anywhere as a whole phrase.\"",
  '      word "web search"',
  "        description \"English bare marker 'web search'; a research_prompt_signal matched anywhere as a whole phrase.\"",
  '      word "research"',
  "        description \"English bare marker 'research'; a research_prompt_signal matched anywhere as a whole token.\"",
  '    lexeme "ru"',
  '      word "поиск"',
  "        description \"Russian noun 'поиск' (romanized poisk, search); a research_prompt_signal bare marker matched token-bounded.\"",
  '      word "исследование"',
  "        description \"Russian noun 'исследование' (romanized issledovanie, research); a research_prompt_signal bare marker matched token-bounded.\"",
  '      word "веб-поиск"',
  "        description \"Russian phrase 'веб-поиск' (romanized veb-poisk, web search); a research_prompt_signal bare marker matched token-bounded.\"",
  '    lexeme "hi"',
  '      word "खोज"',
  "        description \"Hindi noun 'खोज' (romanized khoj, search); a research_prompt_signal bare marker matched token-bounded.\"",
  '      word "अनुसंधान"',
  "        description \"Hindi noun 'अनुसंधान' (romanized anusandhaan, research); a research_prompt_signal bare marker matched token-bounded.\"",
  '    lexeme "zh"',
  '      word "搜索"',
  "        description \"Chinese verb '搜索' (pinyin sousuo, search); a research_prompt_signal bare marker matched as a substring.\"",
  '      word "研究"',
  "        description \"Chinese noun '研究' (pinyin yanjiu, research); a research_prompt_signal bare marker matched as a substring.\"",
  '  meaning "key_differences"',
  "    gloss \"the key-differences comparison criterion — the column asking what distinguishes each topic from the others. The comparison-table handler walks the research_criterion meanings in declaration order and, for each text fragment, adds the criterion when any of its surface words occurs as a raw substring; the matched meaning's slug keys the column. Declaration order is column order, so this meaning is listed first. Its English triggers 'key difference' and 'difference' live here, not in the code.\"",
  '    wiktionary "difference"',
  '    defined_by "relation"',
  '    role "research_criterion"',
  '    lexeme "en"',
  '      word "key difference"',
  "        description \"English phrase 'key difference' naming the key-differences criterion; a research_criterion matched as a raw substring.\"",
  '      word "difference"',
  "        description \"English noun 'difference' naming the differences criterion (also catches 'differences'); a research_criterion matched as a raw substring.\"",
  '    lexeme "ru"',
  '      word "ключевые различия"',
  "        description \"Russian phrase 'ключевые различия' (romanized klyuchevye razlichiya, key differences) naming the criterion; a research_criterion matched as a raw substring.\"",
  '      word "различия"',
  "        description \"Russian noun 'различия' (romanized razlichiya, differences) naming the criterion; a research_criterion matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "मुख्य अंतर"',
  "        description \"Hindi phrase 'मुख्य अंतर' (romanized mukhya antar, key differences) naming the criterion; a research_criterion matched as a raw substring.\"",
  '      word "अंतर"',
  "        description \"Hindi noun 'अंतर' (romanized antar, difference) naming the criterion; a research_criterion matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "主要区别"',
  "        description \"Chinese phrase '主要区别' (pinyin zhuyao qubie, key differences) naming the criterion; a research_criterion matched as a substring.\"",
  '      word "区别"',
  "        description \"Chinese noun '区别' (pinyin qubie, difference) naming the criterion; a research_criterion matched as a substring.\"",
  '  meaning "use_cases"',
  "    gloss \"the use-cases comparison criterion — the column summarising where each topic applies in practice. The comparison-table handler adds this criterion when a text fragment contains one of its surface words as a raw substring; the slug 'use_cases' keys the column. Its English triggers 'use case' and 'application' live here, not in the code.\"",
  '    wiktionary "use case"',
  '    defined_by "concept"',
  '    role "research_criterion"',
  '    lexeme "en"',
  '      word "use case"',
  "        description \"English phrase 'use case' naming the use-cases criterion; a research_criterion matched as a raw substring.\"",
  '      word "application"',
  "        description \"English noun 'application' naming a practical use; a research_criterion matched as a raw substring.\"",
  '    lexeme "ru"',
  '      word "сценарии использования"',
  "        description \"Russian phrase 'сценарии использования' (romanized stsenarii ispolzovaniya, use cases) naming the criterion; a research_criterion matched as a raw substring.\"",
  '      word "применение"',
  "        description \"Russian noun 'применение' (romanized primenenie, application) naming a practical use; a research_criterion matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "उपयोग के मामले"',
  "        description \"Hindi phrase 'उपयोग के मामले' (romanized upyog ke maamle, use cases) naming the criterion; a research_criterion matched as a raw substring.\"",
  '      word "अनुप्रयोग"',
  "        description \"Hindi noun 'अनुप्रयोग' (romanized anuprayog, application) naming a practical use; a research_criterion matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "用例"',
  "        description \"Chinese noun '用例' (pinyin yongli, use case) naming the criterion; a research_criterion matched as a substring.\"",
  '      word "应用"',
  "        description \"Chinese noun '应用' (pinyin yingyong, application) naming a practical use; a research_criterion matched as a substring.\"",
  '  meaning "advantages"',
  "    gloss \"the advantages comparison criterion — the column listing each topic's strengths. The comparison-table handler adds this criterion when a text fragment contains one of its surface words as a raw substring; the slug 'advantages' keys the column. Its English triggers are 'advantage' and 'pro ' (with the trailing space that keeps it from matching inside unrelated words); both live here, not in the code.\"",
  '    wiktionary "advantage"',
  '    defined_by "property"',
  '    role "research_criterion"',
  '    lexeme "en"',
  '      word "advantage"',
  "        description \"English noun 'advantage' naming the advantages criterion (also catches 'advantages'); a research_criterion matched as a raw substring.\"",
  '      word "pro "',
  "        description \"English noun 'pro' with a trailing space ('pro ') naming an advantage; a research_criterion matched as a raw substring, the space keeping it from matching inside words like 'process'.\"",
  '    lexeme "ru"',
  '      word "преимущества"',
  "        description \"Russian plural noun 'преимущества' (romanized preimushchestva, advantages) naming the criterion; a research_criterion matched as a raw substring.\"",
  '      word "плюсы"',
  "        description \"Russian plural noun 'плюсы' (romanized plyusy, pros) naming advantages; a research_criterion matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "फायदे"',
  "        description \"Hindi plural noun 'फायदे' (romanized faayde, advantages) naming the criterion; a research_criterion matched as a raw substring.\"",
  '      word "लाभ"',
  "        description \"Hindi noun 'लाभ' (romanized laabh, benefit) naming an advantage; a research_criterion matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "优点"',
  "        description \"Chinese noun '优点' (pinyin youdian, advantages) naming the criterion; a research_criterion matched as a substring.\"",
  '      word "优势"',
  "        description \"Chinese noun '优势' (pinyin youshi, advantage) naming the criterion; a research_criterion matched as a substring.\"",
  '  meaning "disadvantages"',
  "    gloss \"the disadvantages comparison criterion — the column listing each topic's drawbacks. The comparison-table handler adds this criterion when a text fragment contains one of its surface words as a raw substring; the slug 'disadvantages' keys the column. Its English triggers are 'disadvantage' and ' con ' (with surrounding spaces that keep it from matching inside unrelated words); both live here, not in the code.\"",
  '    wiktionary "disadvantage"',
  '    defined_by "property"',
  '    role "research_criterion"',
  '    lexeme "en"',
  '      word "disadvantage"',
  "        description \"English noun 'disadvantage' naming the disadvantages criterion (also catches 'disadvantages'); a research_criterion matched as a raw substring.\"",
  '      word " con "',
  "        description \"English noun 'con' with surrounding spaces (' con ') naming a drawback; a research_criterion matched as a raw substring, the spaces keeping it from matching inside words like 'control'.\"",
  '    lexeme "ru"',
  '      word "недостатки"',
  "        description \"Russian plural noun 'недостатки' (romanized nedostatki, disadvantages) naming the criterion; a research_criterion matched as a raw substring.\"",
  '      word "минусы"',
  "        description \"Russian plural noun 'минусы' (romanized minusy, cons) naming drawbacks; a research_criterion matched as a raw substring.\"",
  '    lexeme "hi"',
  '      word "नुकसान"',
  "        description \"Hindi noun 'नुकसान' (romanized nuksaan, disadvantage/harm) naming the criterion; a research_criterion matched as a raw substring.\"",
  '      word "हानि"',
  "        description \"Hindi noun 'हानि' (romanized haani, harm) naming a drawback; a research_criterion matched as a raw substring.\"",
  '    lexeme "zh"',
  '      word "缺点"',
  "        description \"Chinese noun '缺点' (pinyin quedian, disadvantages) naming the criterion; a research_criterion matched as a substring.\"",
  '      word "劣势"',
  "        description \"Chinese noun '劣势' (pinyin lieshi, disadvantage) naming the criterion; a research_criterion matched as a substring.\"",
  "meanings",
  '  meaning "conversation_topic_opener"',
  "    gloss \"a conversational opener that proposes a topic to discuss — the let-us-talk-about-X phrasing that introduces a subject for open conversation, independent of the language used. Each surface is a prefix carrying the … (U+2026) slot at the end, where the topic follows. A surface whose action child is 'scan' is also matched when it occurs anywhere in the prompt, not only at the start, so an opener embedded after a greeting is still recognized.\"",
  '    wiktionary "talk"',
  '    defined_by "inquiry"',
  '    defined_by "action"',
  '    role "conversation_topic_opener"',
  '    lexeme "en"',
  "      word \"let's talk about …\"",
  '        description "English conversational opener; the topic to discuss follows the … slot."',
  '      word "lets talk about …"',
  '        description "English conversational opener written without the apostrophe; the topic follows the … slot."',
  '      word "can we talk about …"',
  '        description "English conversational opener phrased as a question; the topic follows the … slot."',
  '      word "talk about …"',
  '        description "English bare conversational opener; the topic follows the … slot."',
  '    lexeme "ru"',
  '      word "давай поговорим о …"',
  '        description "Russian conversational opener (romanized davaj pogovorim o, let us talk about); the topic follows the … slot."',
  '      word "давай поговорим об …"',
  '        description "Russian conversational opener before a vowel (romanized davaj pogovorim ob, let us talk about); the topic follows the … slot."',
  '      word "давайте поговорим о …"',
  '        description "Russian polite or plural conversational opener (romanized davajte pogovorim o, let us talk about); the topic follows the … slot."',
  '      word "давайте поговорим об …"',
  '        description "Russian polite or plural opener before a vowel (romanized davajte pogovorim ob, let us talk about); the topic follows the … slot."',
  '      word "поговорим о …"',
  '        action "scan"',
  '        description "Russian conversational opener (romanized pogovorim o, let us talk about); the topic follows the … slot, and this surface is also scanned anywhere in the prompt because the bare verb often follows a greeting."',
  '      word "поговорим об …"',
  '        description "Russian conversational opener before a vowel (romanized pogovorim ob, let us talk about); the topic follows the … slot."',
  '      word "обсудим …"',
  '        description "Russian conversational opener (romanized obsudim, let us discuss); the topic follows the … slot."',
  '    lexeme "hi"',
  '      word "चलो बात करें …"',
  '        description "Hindi conversational opener (romanized chalo baat karen, let us talk); the topic follows the … slot."',
  '      word "बात करें …"',
  '        description "Hindi conversational opener (romanized baat karen, let us talk); the topic follows the … slot."',
  '    lexeme "zh"',
  '      word "聊聊…"',
  '        description "Chinese conversational opener (pinyin liaoliao, let us chat) with no trailing space; the topic follows the … slot."',
  '      word "谈谈…"',
  '        description "Chinese conversational opener (pinyin tantan, let us discuss) with no trailing space; the topic follows the … slot."',
  "meanings",
  '  meaning "summary_statement_kind"',
  '    gloss "the kind of statement the project-summarization classifier recognizes in a sentence of prose — install, example, language, stars, purpose, use case or feature. This genus groups the seven summary_classification_cue leaves so they are built from a shared concept instead of being listed as raw cue arrays in the code. The summary_statement_kind role is structural: no handler queries it directly; it exists so the ontology records that the seven cue meanings are kinds of statement the summarizer reasons about."',
  '    wiktionary "statement"',
  '    defined_by "concept"',
  '    role "summary_statement_kind"',
  '    lexeme "en"',
  '      word "statement kind"',
  '        description "English label for the category a prose sentence falls into during summarization; the summary_statement_kind genus lexicalized in English."',
  '      word "sentence kind"',
  '        description "English synonym for the classified category of a sentence; the summary_statement_kind genus lexicalized in English."',
  '    lexeme "ru"',
  '      word "вид утверждения"',
  '        description "Russian phrase (romanized vid utverzhdeniya, kind of statement); the summary_statement_kind genus lexicalized in Russian."',
  '      word "тип предложения"',
  '        description "Russian phrase (romanized tip predlozheniya, kind of sentence); the summary_statement_kind genus lexicalized in Russian."',
  '    lexeme "hi"',
  '      word "कथन का प्रकार"',
  '        description "Hindi phrase (romanized kathan ka prakar, kind of statement); the summary_statement_kind genus lexicalized in Hindi."',
  '      word "वाक्य का प्रकार"',
  '        description "Hindi phrase (romanized vakya ka prakar, kind of sentence); the summary_statement_kind genus lexicalized in Hindi."',
  '    lexeme "zh"',
  '      word "陈述类型"',
  '        description "Chinese phrase (pinyin chenshu leixing, statement kind); the summary_statement_kind genus lexicalized in Chinese."',
  '      word "句子类型"',
  '        description "Chinese phrase (pinyin juzi leixing, sentence kind); the summary_statement_kind genus lexicalized in Chinese."',
  '  meaning "summary_kind_install"',
  '    gloss "a sentence that explains how to install the project. The summary_classification_cue role marks the surface fragments that signal this Install kind; the summarizer classifies a sentence as Install when its lowercased text contains any of these fragments. Matched as raw lowercase substrings, so embedded spaces in a fragment are significant and inflected or compound forms are caught in every supported language."',
  '    wiktionary "install"',
  '    defined_by "summary_statement_kind"',
  '    role "summary_classification_cue"',
  '    lexeme "en"',
  '      word "to install"',
  '        description "English Install cue (the infinitive of install); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "install with"',
  '        description "English Install cue introducing the installation command; a summary_classification_cue matched as a raw lowercase substring."',
  '      word "installation"',
  '        description "English Install cue (the noun installation); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "npm install"',
  '        description "English Install cue for the npm package manager command; a summary_classification_cue matched as a raw lowercase substring."',
  '      word "cargo install"',
  '        description "English Install cue for the Cargo package manager command; a summary_classification_cue matched as a raw lowercase substring."',
  '      word "pip install"',
  '        description "English Install cue for the pip package manager command; a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "ru"',
  '      word "установить"',
  '        description "Russian Install cue (romanized ustanovit, to install); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "установка"',
  '        description "Russian Install cue (romanized ustanovka, installation); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "установите"',
  '        description "Russian Install cue (romanized ustanovite, install in the imperative); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "hi"',
  '      word "इंस्टॉल करें"',
  '        description "Hindi Install cue (romanized install karen, install it); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "स्थापना"',
  '        description "Hindi Install cue (romanized sthapana, installation); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "zh"',
  '      word "安装"',
  '        description "Chinese Install cue (pinyin anzhuang, to install); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "安装方法"',
  '        description "Chinese Install cue (pinyin anzhuang fangfa, installation method); a summary_classification_cue matched as a raw lowercase substring."',
  '  meaning "summary_kind_example"',
  '    gloss "a sentence that gives an example or a runnable command. The summary_classification_cue role marks the surface fragments that signal this Example kind; the summarizer classifies a sentence as Example when its lowercased text contains any of these fragments. Several fragments are language-neutral code markers (a fenced code block, a shell prompt, a flag run) carried under the English lexeme. Matched as raw lowercase substrings, so embedded spaces are significant."',
  '    wiktionary "example"',
  '    defined_by "summary_statement_kind"',
  '    role "summary_classification_cue"',
  '    lexeme "en"',
  '      word "for example"',
  '        description "English Example cue introducing an illustration; a summary_classification_cue matched as a raw lowercase substring."',
  '      word "example:"',
  '        description "English Example cue (the word example followed by a colon); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "e.g."',
  '        description "English Example cue (the abbreviation of the Latin exempli gratia); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "run --"',
  '        description "English Example cue for a command invoked with a long flag; a summary_classification_cue matched as a raw lowercase substring."',
  '      word "$ "',
  '        description "English Example cue for a shell prompt; the trailing space is significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word "```"',
  '        description "Language-neutral Example cue for a fenced code block (three backticks), carried under the English lexeme; a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "ru"',
  '      word "выполни"',
  '        description "Russian Example cue (romanized vypolni, run or execute in the imperative); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "например"',
  '        description "Russian Example cue (romanized naprimer, for example); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "hi"',
  '      word "उदाहरण के लिए"',
  '        description "Hindi Example cue (romanized udaharan ke lie, for example); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "उदाहरण:"',
  '        description "Hindi Example cue (romanized udaharan, example, followed by a colon); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "zh"',
  '      word "例如"',
  '        description "Chinese Example cue (pinyin liru, for example); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "比如"',
  '        description "Chinese Example cue (pinyin biru, for instance); a summary_classification_cue matched as a raw lowercase substring."',
  '  meaning "summary_kind_language"',
  '    gloss "a short sentence that states which programming language the project is written in. The summary_classification_cue role marks the surface fragments that signal this Language kind. Unlike the other kinds this one is guarded by length: the summarizer only classifies a sentence as Language when it both contains a cue and has at most twelve whitespace-separated words, so a long feature sentence that merely contains is a falls through to the later kinds. Matched as raw lowercase substrings, so embedded spaces are significant."',
  '    wiktionary "language"',
  '    defined_by "summary_statement_kind"',
  '    role "summary_classification_cue"',
  '    lexeme "en"',
  '      word "written in "',
  '        description "English Language cue (written in a language); the trailing space is significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word "language:"',
  '        description "English Language cue (the word language followed by a colon); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "is a "',
  '        description "English Language cue (is a, as in is a Rust project); the trailing space is significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word "build with "',
  '        description "English Language cue (built with a language or toolchain); the trailing space is significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "ru"',
  '      word "написан на "',
  '        description "Russian Language cue (romanized napisan na, written in); the trailing space is significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word "на языке "',
  '        description "Russian Language cue (romanized na yazyke, in the language of); the trailing space is significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "hi"',
  '      word "में लिखा"',
  '        description "Hindi Language cue (romanized mein likha, written in); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "भाषा:"',
  '        description "Hindi Language cue (romanized bhasha, language, followed by a colon); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "zh"',
  '      word "语言"',
  '        description "Chinese Language cue (pinyin yuyan, language); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "编写"',
  '        description "Chinese Language cue (pinyin bianxie, to write or compile, as in written in a language); a summary_classification_cue matched as a raw lowercase substring."',
  '  meaning "summary_kind_stars"',
  '    gloss "a sentence that reports how many stars the project has on a hosting site. The summary_classification_cue role marks the surface fragments that signal this Stars kind; the summarizer classifies a sentence as Stars when its lowercased text contains any of these fragments. Matched as raw lowercase substrings, so embedded spaces and the star glyph are significant and inflected forms are caught in every supported language."',
  '    wiktionary "star"',
  '    defined_by "summary_statement_kind"',
  '    role "summary_classification_cue"',
  '    lexeme "en"',
  '      word " stars"',
  '        description "English Stars cue (the plural noun stars); the leading space is significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word "github stars"',
  '        description "English Stars cue naming the GitHub star count; a summary_classification_cue matched as a raw lowercase substring."',
  '      word "★"',
  '        description "Stars cue for the black star glyph used as a star indicator; a summary_classification_cue matched as a raw lowercase substring."',
  '      word "stargazers"',
  '        description "English Stars cue (the people who starred a repository); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "ru"',
  '      word "звёзды"',
  '        description "Russian Stars cue (romanized zvyozdy, stars); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "звезд"',
  '        description "Russian Stars cue (romanized zvezd, the genitive stem of stars); a summary_classification_cue matched as a raw lowercase substring so звезда, звёзд and звездам are all caught."',
  '    lexeme "hi"',
  '      word "सितारे"',
  '        description "Hindi Stars cue (romanized sitare, stars); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "तारे"',
  '        description "Hindi Stars cue (romanized tare, stars); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "zh"',
  '      word "星标"',
  '        description "Chinese Stars cue (pinyin xingbiao, star mark, the GitHub star); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "星数"',
  '        description "Chinese Stars cue (pinyin xingshu, star count); a summary_classification_cue matched as a raw lowercase substring."',
  '  meaning "summary_kind_purpose"',
  '    gloss "a sentence that states what the project is for — its purpose or what it helps you do. The summary_classification_cue role marks the surface fragments that signal this Purpose kind; the summarizer classifies a sentence as Purpose when its lowercased text contains any of these fragments. Matched as raw lowercase substrings, so embedded spaces are significant and inflected forms are caught in every supported language."',
  '    wiktionary "purpose"',
  '    defined_by "summary_statement_kind"',
  '    role "summary_classification_cue"',
  '    lexeme "en"',
  '      word "is for "',
  '        description "English Purpose cue (is for some use); the trailing space is significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word "is the ai"',
  '        description "English Purpose cue (is the AI that does something); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "is an ai"',
  '        description "English Purpose cue (is an AI for something); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "is used to"',
  '        description "English Purpose cue (is used to do something); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "is meant to"',
  '        description "English Purpose cue (is meant to do something); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "is designed to"',
  '        description "English Purpose cue (is designed to do something); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "helps you"',
  '        description "English Purpose cue (helps you do something); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "lets you"',
  '        description "English Purpose cue (lets you do something); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "ru"',
  '      word "это ии"',
  '        description "Russian Purpose cue (romanized eto ii, this is an AI); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "предназнач"',
  '        description "Russian Purpose cue (romanized prednaznach, the stem of is intended for); a summary_classification_cue matched as a raw lowercase substring so предназначен and предназначена are both caught."',
  '    lexeme "hi"',
  '      word "के लिए है"',
  '        description "Hindi Purpose cue (romanized ke lie hai, is for); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "मदद करता है"',
  '        description "Hindi Purpose cue (romanized madad karta hai, helps); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "zh"',
  '      word "用于"',
  '        description "Chinese Purpose cue (pinyin yongyu, is used for); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "旨在"',
  '        description "Chinese Purpose cue (pinyin zhizai, is designed to); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "帮助你"',
  '        description "Chinese Purpose cue (pinyin bangzhu ni, helps you); a summary_classification_cue matched as a raw lowercase substring."',
  '  meaning "summary_kind_use_case"',
  '    gloss "a sentence that describes when to use the project — its use case. The summary_classification_cue role marks the surface fragments that signal this UseCase kind; the summarizer classifies a sentence as UseCase when its lowercased text contains any of these fragments. Matched as raw lowercase substrings, so embedded spaces are significant and the cue generalizes to every supported language."',
  '    wiktionary "use case"',
  '    defined_by "summary_statement_kind"',
  '    role "summary_classification_cue"',
  '    lexeme "en"',
  '      word "use it when"',
  '        description "English UseCase cue (use it when some condition holds); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "use this when"',
  '        description "English UseCase cue (use this when some condition holds); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "when you need"',
  '        description "English UseCase cue (when you need something); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "ideal for"',
  '        description "English UseCase cue (is ideal for some scenario); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "useful when"',
  '        description "English UseCase cue (is useful when some condition holds); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "ru"',
  '      word "используйте когда"',
  '        description "Russian UseCase cue (romanized ispolzuyte kogda, use it when); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "когда нужно"',
  '        description "Russian UseCase cue (romanized kogda nuzhno, when it is needed); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "идеально для"',
  '        description "Russian UseCase cue (romanized idealno dlya, ideal for); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "hi"',
  '      word "जब आपको चाहिए"',
  '        description "Hindi UseCase cue (romanized jab aapko chahie, when you need); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "के लिए आदर्श"',
  '        description "Hindi UseCase cue (romanized ke lie adarsh, ideal for); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "zh"',
  '      word "当你需要"',
  '        description "Chinese UseCase cue (pinyin dang ni xuyao, when you need); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "适用于"',
  '        description "Chinese UseCase cue (pinyin shiyong yu, is suitable for); a summary_classification_cue matched as a raw lowercase substring."',
  '  meaning "summary_kind_feature"',
  '    gloss "a sentence that lists a feature the project provides, supports, offers or ships. The summary_classification_cue role marks the surface fragments that signal this Feature kind; the summarizer classifies a sentence as Feature when its lowercased text contains any of these fragments. The English fragments keep their surrounding spaces so a verb is matched as a whole word. Matched as raw lowercase substrings, so embedded spaces are significant and inflected forms are caught in every supported language."',
  '    wiktionary "feature"',
  '    defined_by "summary_statement_kind"',
  '    role "summary_classification_cue"',
  '    lexeme "en"',
  '      word " supports "',
  '        description "English Feature cue (the project supports something); the surrounding spaces are significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word " provides "',
  '        description "English Feature cue (the project provides something); the surrounding spaces are significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word " offers "',
  '        description "English Feature cue (the project offers something); the surrounding spaces are significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word " exposes "',
  '        description "English Feature cue (the project exposes something); the surrounding spaces are significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word " ships "',
  '        description "English Feature cue (the project ships something); the surrounding spaces are significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word " orchestrates "',
  '        description "English Feature cue (the project orchestrates something); the surrounding spaces are significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "ru"',
  '      word " предоставляет "',
  '        description "Russian Feature cue (romanized predostavlyaet, provides); the surrounding spaces are significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '      word " поддерживает "',
  '        description "Russian Feature cue (romanized podderzhivaet, supports); the surrounding spaces are significant and the fragment is a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "hi"',
  '      word "समर्थन करता है"',
  '        description "Hindi Feature cue (romanized samarthan karta hai, supports); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "प्रदान करता है"',
  '        description "Hindi Feature cue (romanized pradan karta hai, provides); a summary_classification_cue matched as a raw lowercase substring."',
  '    lexeme "zh"',
  '      word "支持"',
  '        description "Chinese Feature cue (pinyin zhichi, supports); a summary_classification_cue matched as a raw lowercase substring."',
  '      word "提供"',
  '        description "Chinese Feature cue (pinyin tigong, provides); a summary_classification_cue matched as a raw lowercase substring."',
  "meanings",
  '  meaning "program_language"',
  "    gloss \"the genus of the programming languages the coding catalog can target; a structural parent that is never matched on its own. Each program_language_* leaf below names one catalog target (rust, python, …) and carries that target's alias surfaces across every supported language. Defined_by software_language so it inherits the broader programming-language concept and, through it, the software-artifact and link roots.\"",
  '    wiktionary "programming language"',
  '    defined_by "software_language"',
  '    role "program_language"',
  '    lexeme "en"',
  '      word "programming language"',
  '        description "English noun phrase naming the genus of catalog target languages; structural, never matched on its own."',
  '    lexeme "ru"',
  '      word "язык программирования"',
  '        description "Russian noun phrase (romanized yazyk programmirovaniya) for a programming language; the structural genus surface."',
  '    lexeme "hi"',
  '      word "प्रोग्रामिंग भाषा"',
  '        description "Hindi noun phrase (romanized programming bhasha) for a programming language; the structural genus surface."',
  '    lexeme "zh"',
  '      word "编程语言"',
  '        description "Chinese noun (pinyin biancheng yuyan) for a programming language; the structural genus surface."',
  '  meaning "program_language_rust"',
  '    gloss "the Rust programming language as a coding-catalog target (canonical slug rust); its alias surfaces let a prompt that names Rust resolve the rust execution template. Defined_by program_language (the catalog genus) and language_rust (the canonical Rust concept shared with the unknown-language extractor). Names are single tokens, matched on whitespace boundaries (substring for CJK)."',
  '    wiktionary "Rust"',
  '    defined_by "program_language"',
  '    defined_by "language_rust"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "rust"',
  '        description "English proper noun and canonical slug for the Rust programming language; the primary catalog alias."',
  '      word "rs"',
  '        description "English abbreviation (the .rs source-file extension) for Rust; a short catalog alias."',
  '    lexeme "ru"',
  '      word "раст"',
  '        description "Russian noun (romanized rast) for the Rust language; the Russian catalog alias."',
  '      word "расте"',
  '        description "Russian prepositional-case form (romanized raste, as in na raste) of the Rust language name; a Russian catalog alias."',
  '    lexeme "hi"',
  '      word "रस्ट"',
  '        description "Hindi noun (romanized rust, a loanword) for the Rust language; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "rust"',
  '        description "The Latin-script name Rust as written in Chinese text for the Rust language; the Chinese catalog alias."',
  '  meaning "program_language_python"',
  '    gloss "the Python programming language as a coding-catalog target (canonical slug python); its alias surfaces resolve the python execution template. Defined_by program_language and language_python (the shared canonical Python concept)."',
  '    wiktionary "Python"',
  '    defined_by "program_language"',
  '    defined_by "language_python"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "python"',
  '        description "English proper noun and canonical slug for the Python programming language; the primary catalog alias."',
  '      word "py"',
  '        description "English abbreviation (the .py source-file extension) for Python; a short catalog alias."',
  '    lexeme "ru"',
  '      word "питон"',
  '        description "Russian noun (romanized piton) for the Python language; the Russian catalog alias."',
  '      word "питоне"',
  '        description "Russian prepositional-case form (romanized pitone, as in na pitone) of the Python language name; a Russian catalog alias."',
  '    lexeme "hi"',
  '      word "पायथन"',
  '        description "Hindi noun (romanized python, a loanword) for the Python language; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "python"',
  '        description "The Latin-script name Python as written in Chinese text for the Python language; the Chinese catalog alias."',
  '  meaning "program_language_javascript"',
  '    gloss "the JavaScript programming language as a coding-catalog target (canonical slug javascript); its alias surfaces resolve the javascript execution template. Defined_by program_language and language_javascript (the shared canonical JavaScript concept)."',
  '    wiktionary "JavaScript"',
  '    defined_by "program_language"',
  '    defined_by "language_javascript"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "javascript"',
  '        description "English proper noun and canonical slug for the JavaScript programming language; the primary catalog alias."',
  '      word "js"',
  '        description "English abbreviation (the .js source-file extension) for JavaScript; a short catalog alias."',
  '      word "node"',
  '        description "English proper noun for Node.js, the JavaScript runtime; a surface that names the JavaScript target."',
  '    lexeme "ru"',
  '      word "джаваскрипт"',
  '        description "Russian noun (romanized dzhavaskript) for the JavaScript language; the Russian catalog alias."',
  '    lexeme "hi"',
  '      word "जावास्क्रिप्ट"',
  '        description "Hindi noun (romanized javascript, a loanword) for the JavaScript language; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "javascript"',
  '        description "The Latin-script name JavaScript as written in Chinese text for the JavaScript language; the Chinese catalog alias."',
  '  meaning "program_language_typescript"',
  '    gloss "the TypeScript programming language as a coding-catalog target (canonical slug typescript); its alias surfaces resolve the typescript execution template. Defined_by program_language; TypeScript has no separate unknown-language archetype, so the genus is its only parent."',
  '    wiktionary "TypeScript"',
  '    defined_by "program_language"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "typescript"',
  '        description "English proper noun and canonical slug for the TypeScript programming language; the primary catalog alias."',
  '      word "ts"',
  '        description "English abbreviation (the .ts source-file extension) for TypeScript; a short catalog alias."',
  '    lexeme "ru"',
  '      word "тайпскрипт"',
  '        description "Russian noun (romanized taypskript) for the TypeScript language; the Russian catalog alias."',
  '    lexeme "hi"',
  '      word "टाइपस्क्रिप्ट"',
  '        description "Hindi noun (romanized typescript, a loanword) for the TypeScript language; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "typescript"',
  '        description "The Latin-script name TypeScript as written in Chinese text for the TypeScript language; the Chinese catalog alias."',
  '  meaning "program_language_go"',
  '    gloss "the Go programming language as a coding-catalog target (canonical slug go); its alias surfaces resolve the go execution template. Defined_by program_language."',
  '    wiktionary "Go"',
  '    defined_by "program_language"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "go"',
  '        description "English proper noun and canonical slug for the Go programming language; the primary catalog alias, matched only as a whole token so a stray go verb never fires it."',
  '      word "golang"',
  '        description "English compound (go plus lang) commonly used to name the Go language unambiguously; a catalog alias."',
  '    lexeme "ru"',
  '      word "го"',
  '        description "Russian noun (romanized go) for the Go language; the Russian catalog alias."',
  '    lexeme "hi"',
  '      word "गो"',
  '        description "Hindi noun (romanized go, a loanword) for the Go language; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "go"',
  '        description "The Latin-script name Go as written in Chinese text for the Go language; the Chinese catalog alias."',
  '  meaning "program_language_c"',
  '    gloss "the C programming language as a coding-catalog target (canonical slug c); its alias surfaces resolve the c execution template. Defined_by program_language. The single-letter name is matched only as a whole token, so it never fires inside another word."',
  '    wiktionary "C"',
  '    defined_by "program_language"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "c"',
  '        description "English single-letter canonical slug for the C programming language; the primary catalog alias, matched only as a whole token."',
  '    lexeme "ru"',
  '      word "си"',
  '        description "Russian noun (romanized si) naming the C programming language; the Russian catalog alias, matched as a whole token."',
  '    lexeme "hi"',
  '      word "सी"',
  '        description "Hindi noun (romanized si) naming the C programming language; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "c"',
  '        description "The Latin-script letter C as written in Chinese text for the C language; the Chinese catalog alias."',
  '  meaning "program_language_cpp"',
  '    gloss "the C++ programming language as a coding-catalog target (canonical slug cpp); its alias surfaces resolve the cpp execution template. Defined_by program_language. The c++ surface carries the plus signs verbatim, distinct from the bare c token so a C++ request never collapses onto C."',
  '    wiktionary "C++"',
  '    defined_by "program_language"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "cpp"',
  '        description "English canonical slug for the C++ programming language (the cpp spelling avoids the plus signs); the primary catalog alias."',
  '      word "c++"',
  '        description "English proper name C++ written with its plus signs; a catalog alias matched as a whole token distinct from the bare c."',
  '      word "cplusplus"',
  '        description "English spelled-out form of C++ (c-plus-plus); a catalog alias."',
  '    lexeme "ru"',
  '      word "сиплюсплюс"',
  '        description "Russian spelled-out form (romanized siplyusplyus, si-plus-plus) of the C++ language name; the Russian catalog alias."',
  '    lexeme "hi"',
  '      word "सीपीपी"',
  '        description "Hindi transliteration (romanized cpp) of the C++ language name; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "c++"',
  '        description "The Latin-script name C++ as written in Chinese text for the C++ language; the Chinese catalog alias."',
  '  meaning "program_language_java"',
  '    gloss "the Java programming language as a coding-catalog target (canonical slug java); its alias surfaces resolve the java execution template. Defined_by program_language."',
  '    wiktionary "Java"',
  '    defined_by "program_language"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "java"',
  '        description "English proper noun and canonical slug for the Java programming language; the primary catalog alias."',
  '    lexeme "ru"',
  '      word "джава"',
  '        description "Russian noun (romanized dzhava) for the Java language; the Russian catalog alias."',
  '    lexeme "hi"',
  '      word "जावा"',
  '        description "Hindi noun (romanized java, a loanword) for the Java language; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "java"',
  '        description "The Latin-script name Java as written in Chinese text for the Java language; the Chinese catalog alias."',
  '  meaning "program_language_csharp"',
  '    gloss "the C# programming language as a coding-catalog target (canonical slug csharp); its alias surfaces resolve the csharp execution template. Defined_by program_language. The c# surface carries the sharp sign verbatim, distinct from the bare c token."',
  '    wiktionary "C Sharp (programming language)"',
  '    defined_by "program_language"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "csharp"',
  '        description "English canonical slug for the C# programming language (the csharp spelling avoids the sharp sign); the primary catalog alias."',
  '      word "c#"',
  '        description "English proper name C# written with its sharp sign; a catalog alias matched as a whole token distinct from the bare c."',
  '      word "cs"',
  '        description "English abbreviation (the .cs source-file extension) for C#; a short catalog alias."',
  '      word "dotnet"',
  '        description "English proper noun for .NET, the runtime and platform C# targets; a surface that names the C# target."',
  '    lexeme "ru"',
  '      word "сишарп"',
  '        description "Russian spelled-out form (romanized sisharp, si-sharp) of the C# language name; the Russian catalog alias."',
  '    lexeme "hi"',
  '      word "सीशार्प"',
  '        description "Hindi transliteration (romanized csharp) of the C# language name; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "c#"',
  '        description "The Latin-script name C# as written in Chinese text for the C# language; the Chinese catalog alias."',
  '  meaning "program_language_ruby"',
  '    gloss "the Ruby programming language as a coding-catalog target (canonical slug ruby); its alias surfaces resolve the ruby execution template. Defined_by program_language."',
  '    wiktionary "Ruby (programming language)"',
  '    defined_by "program_language"',
  '    role "program_language_alias"',
  '    lexeme "en"',
  '      word "ruby"',
  '        description "English proper noun and canonical slug for the Ruby programming language; the primary catalog alias."',
  '      word "rb"',
  '        description "English abbreviation (the .rb source-file extension) for Ruby; a short catalog alias."',
  '    lexeme "ru"',
  '      word "руби"',
  '        description "Russian noun (romanized rubi) for the Ruby language; the Russian catalog alias."',
  '    lexeme "hi"',
  '      word "रूबी"',
  '        description "Hindi noun (romanized ruby, a loanword) for the Ruby language; the Hindi catalog alias."',
  '    lexeme "zh"',
  '      word "ruby"',
  '        description "The Latin-script name Ruby as written in Chinese text for the Ruby language; the Chinese catalog alias."',
  '  meaning "program_task"',
  '    gloss "the genus of the coding tasks the catalog can synthesize; a structural parent that is never matched on its own. Each program_task_* leaf below names one catalog task (hello_world, list_files, …) and carries the phrasings that request it across every supported language. Defined_by program (the whole-program genus) so it reaches the code and link roots. Task phrasings are multi-word and matched on phrase boundaries (substring for CJK)."',
  '    wiktionary "task"',
  '    defined_by "program"',
  '    role "program_task"',
  '    lexeme "en"',
  '      word "coding task"',
  '        description "English noun phrase naming the genus of catalog tasks; structural, never matched on its own."',
  '    lexeme "ru"',
  '      word "задача программирования"',
  '        description "Russian noun phrase (romanized zadacha programmirovaniya) for a programming task; the structural genus surface."',
  '    lexeme "hi"',
  '      word "प्रोग्रामिंग कार्य"',
  '        description "Hindi noun phrase (romanized programming karya) for a programming task; the structural genus surface."',
  '    lexeme "zh"',
  '      word "编程任务"',
  '        description "Chinese noun (pinyin biancheng renwu) for a programming task; the structural genus surface."',
  '  meaning "program_task_hello_world"',
  '    gloss "the hello-world coding task as a catalog target (slug hello_world): print the greeting hello world. Defined_by program_task (the catalog genus) and hello_world (the canonical hello-world archetype whose greeting surfaces these aliases reuse)."',
  '    wiktionary "hello world"',
  '    defined_by "program_task"',
  '    defined_by "hello_world"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "hello world"',
  '        description "English two-word phrase requesting the archetypal first program; matched as a phrase so a stray hello or world alone never fires it."',
  '    lexeme "ru"',
  '      word "хелло ворлд"',
  '        description "Russian transliteration (romanized khello vorld) of hello world, as commonly written in programming tutorials; a catalog alias for the hello_world task."',
  '    lexeme "hi"',
  '      word "हैलो वर्ल्ड"',
  '        description "Hindi transliteration (romanized hailo varld) of hello world; a catalog alias for the hello_world task."',
  '    lexeme "zh"',
  '      word "你好世界"',
  '        description "Chinese phrase (pinyin nihao shijie, hello world); a catalog alias for the hello_world task, matched as a substring."',
  '  meaning "program_task_count_to_three"',
  '    gloss "the count-to-three coding task as a catalog target (slug count_to_three): print 1, 2, 3. Defined_by program_task. The phrasings keep the number three or 3 so the task never answers a different count."',
  '    wiktionary "counting"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "count to three"',
  '        description "English phrase requesting a program that counts to three; a catalog alias for the count_to_three task."',
  '      word "count to 3"',
  '        description "English phrase with the numeral 3 requesting a count to three; a catalog alias."',
  '      word "counts to three"',
  '        description "English third-person phrasing (counts to three) of the count-to-three request; a catalog alias."',
  '      word "counts to 3"',
  '        description "English third-person phrasing with the numeral 3; a catalog alias."',
  '    lexeme "ru"',
  '      word "посчитай до трёх"',
  '        description "Russian phrase (romanized poschitay do tryokh, count to three); a catalog alias for the count_to_three task."',
  '      word "посчитай до 3"',
  '        description "Russian phrase with the numeral 3 (romanized poschitay do 3); a catalog alias."',
  '    lexeme "hi"',
  '      word "तीन तक गिनें"',
  '        description "Hindi phrase (romanized teen tak ginen, count to three); a catalog alias for the count_to_three task."',
  '      word "3 तक गिनें"',
  '        description "Hindi phrase with the numeral 3 (romanized 3 tak ginen); a catalog alias."',
  '    lexeme "zh"',
  '      word "数到三"',
  '        description "Chinese phrase (pinyin shu dao san, count to three); a catalog alias for the count_to_three task, matched as a substring."',
  '      word "数到3"',
  '        description "Chinese phrase with the numeral 3 (pinyin shu dao 3); a catalog alias, matched as a substring."',
  '  meaning "program_task_list_files"',
  '    gloss "the list-files coding task as a catalog target (slug list_files): list the files in the current directory. Defined_by program_task. Every supported prompt language carries its natural phrasings so the whole class of list-files requests resolves, not just one language."',
  '    wiktionary "directory"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "list files in the current directory"',
  '        description "English phrase, the canonical request to list files in the current directory; a catalog alias for the list_files task."',
  '      word "list files in current directory"',
  '        description "English phrase (article elided) requesting a current-directory listing; a catalog alias."',
  '      word "list files in the directory"',
  '        description "English phrase requesting a directory listing; a catalog alias for the list_files task."',
  '      word "list the files in the current directory"',
  '        description "English phrase with the article the requesting a current-directory listing; a catalog alias."',
  '      word "lists files in the current directory"',
  '        description "English third-person phrasing (lists files) of the current-directory listing request; a catalog alias."',
  '      word "lists the files in the current directory"',
  '        description "English third-person phrasing with the article the; a catalog alias."',
  '      word "list files in a directory"',
  '        description "English phrase with the article a requesting a directory listing; a catalog alias."',
  '      word "list directory files"',
  '        description "English compact phrasing (list directory files) of the listing request; a catalog alias."',
  '      word "list files"',
  '        description "English bare phrase list files; a catalog alias for the list_files task, matched on phrase boundaries."',
  '      word "lists files"',
  '        description "English third-person bare phrasing lists files; a catalog alias."',
  '      word "files in the current directory"',
  "        description \"English noun phrase naming the current directory's files; a catalog alias for the list_files task.\"",
  '      word "files in current directory"',
  "        description \"English noun phrase (article elided) naming the current directory's files; a catalog alias.\"",
  '    lexeme "ru"',
  '      word "список файлов в текущей директории"',
  '        description "Russian phrase (romanized spisok faylov v tekushchey direktorii, list of files in the current directory); a catalog alias for the list_files task."',
  '      word "список файлов в текущем каталоге"',
  '        description "Russian phrase using katalog for directory (romanized spisok faylov v tekushchem kataloge); a catalog alias."',
  '      word "список файлов в директории"',
  '        description "Russian phrase (romanized spisok faylov v direktorii, list of files in the directory); a catalog alias."',
  '      word "список файлов в каталоге"',
  '        description "Russian phrase using katalog (romanized spisok faylov v kataloge); a catalog alias."',
  '      word "выдаёт список файлов"',
  '        description "Russian third-person phrasing (romanized vydayot spisok faylov, outputs a list of files), as written by the issue #312 reporter; a catalog alias."',
  '      word "выдает список файлов"',
  '        description "Russian third-person phrasing without the yo letter (romanized vydaet spisok faylov); a catalog alias."',
  '      word "выводит список файлов"',
  '        description "Russian third-person phrasing (romanized vyvodit spisok faylov, prints a list of files); a catalog alias."',
  '      word "вывести список файлов"',
  '        description "Russian infinitive phrasing (romanized vyvesti spisok faylov, to print a list of files); a catalog alias."',
  '      word "вывод списка файлов"',
  '        description "Russian nominal phrasing (romanized vyvod spiska faylov, output of a list of files); a catalog alias."',
  '      word "список файлов"',
  '        description "Russian bare phrase (romanized spisok faylov, list of files); a catalog alias for the list_files task."',
  '      word "файлы в текущей директории"',
  '        description "Russian noun phrase (romanized fayly v tekushchey direktorii, files in the current directory); a catalog alias."',
  '      word "файлы в текущем каталоге"',
  '        description "Russian noun phrase using katalog (romanized fayly v tekushchem kataloge); a catalog alias."',
  '    lexeme "hi"',
  '      word "फ़ाइलों की सूची"',
  '        description "Hindi phrase (romanized failon ki suchi, list of files); a catalog alias for the list_files task."',
  '      word "फाइलों की सूची"',
  '        description "Hindi phrase without the nuqta (romanized failon ki suchi); a catalog alias."',
  '      word "वर्तमान निर्देशिका की फ़ाइलें"',
  '        description "Hindi phrase (romanized vartman nirdeshika ki failen, files of the current directory); a catalog alias."',
  '      word "वर्तमान निर्देशिका की फाइलें"',
  '        description "Hindi phrase without the nuqta (romanized vartman nirdeshika ki failen); a catalog alias."',
  '      word "निर्देशिका की फ़ाइलें"',
  '        description "Hindi phrase (romanized nirdeshika ki failen, files of the directory); a catalog alias."',
  '    lexeme "zh"',
  '      word "列出当前目录中的文件"',
  '        description "Chinese phrase (pinyin liechu dangqian mulu zhong de wenjian, list the files in the current directory); a catalog alias, matched as a substring."',
  '      word "列出当前目录中文件"',
  '        description "Chinese phrase eliding the particle de (pinyin liechu dangqian mulu zhong wenjian); a catalog alias."',
  '      word "列出当前目录的文件"',
  "        description \"Chinese phrase (pinyin liechu dangqian mulu de wenjian, list the current directory's files); a catalog alias.\"",
  '      word "列出当前目录文件"',
  '        description "Chinese compact phrasing (pinyin liechu dangqian mulu wenjian); a catalog alias."',
  '      word "列出目录中的文件"',
  '        description "Chinese phrase (pinyin liechu mulu zhong de wenjian, list the files in the directory); a catalog alias."',
  '      word "列出文件"',
  '        description "Chinese bare phrase (pinyin liechu wenjian, list files); a catalog alias, matched as a substring."',
  '  meaning "program_task_list_files_arg"',
  '    gloss "the list-files-with-a-path-argument coding task as a catalog target (slug list_files_arg): list the files in a directory passed as a command-line argument. Defined_by program_task. A bare accept-a-path-argument modification also maps here through the program-plan rules; these aliases let an explicit single-turn request resolve directly."',
  '    wiktionary "argument"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "list files in the directory given as a path argument"',
  '        description "English phrase, the canonical request to list files in a directory given as a path argument; a catalog alias for the list_files_arg task."',
  '      word "list files in a directory given as an argument"',
  '        description "English phrase requesting a listing of a directory given as an argument; a catalog alias."',
  '      word "list files in the directory passed as an argument"',
  '        description "English phrase using passed as an argument; a catalog alias."',
  '      word "list files in a path argument"',
  '        description "English compact phrasing referencing a path argument; a catalog alias."',
  '      word "list files with a path argument"',
  '        description "English phrase requesting a listing that takes a path argument; a catalog alias."',
  '      word "list files accepting a path argument"',
  '        description "English phrase using accepting a path argument; a catalog alias."',
  '    lexeme "ru"',
  '      word "список файлов в каталоге переданном как аргумент"',
  '        description "Russian phrase (romanized spisok faylov v kataloge peredannom kak argument, list of files in a directory passed as an argument); a catalog alias for the list_files_arg task."',
  '      word "список файлов в директории переданной как аргумент"',
  '        description "Russian phrase using direktoriya (romanized spisok faylov v direktorii peredannoy kak argument); a catalog alias."',
  '      word "список файлов по пути из аргумента"',
  '        description "Russian phrase (romanized spisok faylov po puti iz argumenta, list of files by the path from the argument); a catalog alias."',
  '    lexeme "hi"',
  '      word "पथ तर्क के रूप में दी गई निर्देशिका की फ़ाइलों की सूची"',
  '        description "Hindi phrase (romanized path tark ke roop mein di gayi nirdeshika ki failon ki suchi, list of files of the directory given as a path argument); a catalog alias for the list_files_arg task."',
  '    lexeme "zh"',
  '      word "列出作为路径参数给出的目录中的文件"',
  '        description "Chinese phrase (pinyin liechu zuowei lujing canshu gei chu de mulu zhong de wenjian, list the files in the directory given as a path argument); a catalog alias, matched as a substring."',
  '      word "列出路径参数指定目录中的文件"',
  '        description "Chinese phrase (pinyin liechu lujing canshu zhiding mulu zhong de wenjian, list the files in the directory the path argument specifies); a catalog alias."',
  '  meaning "program_task_list_files_reverse_sort"',
  "    gloss \"the reverse-sorted list-files coding task as a catalog target (slug list_files_reverse_sort): list the current directory's files in descending byte order. Defined_by program_task.\"",
  '    wiktionary "sorting"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "list files in reverse order"',
  '        description "English phrase requesting a reverse-ordered listing; a catalog alias for the list_files_reverse_sort task."',
  '      word "list files sorted in reverse order"',
  '        description "English phrase using sorted in reverse order; a catalog alias."',
  '      word "list files in descending order"',
  '        description "English phrase using descending order; a catalog alias."',
  '      word "reverse sorted list files"',
  '        description "English phrase (reverse sorted list files); a catalog alias."',
  '    lexeme "ru"',
  '      word "список файлов в обратном порядке"',
  '        description "Russian phrase (romanized spisok faylov v obratnom poryadke, list of files in reverse order); a catalog alias for the list_files_reverse_sort task."',
  '      word "список файлов с обратной сортировкой"',
  '        description "Russian phrase (romanized spisok faylov s obratnoy sortirovkoy, list of files with reverse sorting); a catalog alias."',
  '    lexeme "hi"',
  '      word "फ़ाइलों की सूची उल्टे क्रम में"',
  '        description "Hindi phrase (romanized failon ki suchi ulte kram mein, list of files in reverse order); a catalog alias for the list_files_reverse_sort task."',
  '      word "फ़ाइलों को उल्टे क्रम में सूचीबद्ध करें"',
  '        description "Hindi imperative phrase (romanized failon ko ulte kram mein suchibaddh karen, list the files in reverse order); a catalog alias."',
  '    lexeme "zh"',
  '      word "按相反顺序列出文件"',
  '        description "Chinese phrase (pinyin an xiangfan shunxu liechu wenjian, list files in reverse order); a catalog alias, matched as a substring."',
  '      word "倒序列出文件"',
  '        description "Chinese phrase (pinyin daoxu liechu wenjian, list files in descending order); a catalog alias."',
  '  meaning "program_task_list_files_arg_reverse_sort"',
  "    gloss \"the reverse-sorted list-files-with-a-path-argument coding task as a catalog target (slug list_files_arg_reverse_sort): list a path-argument directory's files in descending byte order. Defined_by program_task.\"",
  '    wiktionary "sorting"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "list files from a path argument in reverse order"',
  '        description "English phrase requesting a reverse-ordered listing of a path-argument directory; a catalog alias for the list_files_arg_reverse_sort task."',
  '      word "list files with a path argument in reverse order"',
  '        description "English phrase using with a path argument in reverse order; a catalog alias."',
  '      word "list files with a path argument sorted descending"',
  '        description "English phrase using sorted descending; a catalog alias."',
  '      word "reverse sorted list files with a path argument"',
  '        description "English phrase (reverse sorted list files with a path argument); a catalog alias."',
  '    lexeme "ru"',
  '      word "список файлов по пути из аргумента в обратном порядке"',
  '        description "Russian phrase (romanized spisok faylov po puti iz argumenta v obratnom poryadke, list of files by the path from the argument in reverse order); a catalog alias for the list_files_arg_reverse_sort task."',
  '      word "список файлов из аргумента с обратной сортировкой"',
  '        description "Russian phrase (romanized spisok faylov iz argumenta s obratnoy sortirovkoy, list of files from the argument with reverse sorting); a catalog alias."',
  '    lexeme "hi"',
  '      word "पथ तर्क से फ़ाइलों की सूची उल्टे क्रम में"',
  '        description "Hindi phrase (romanized path tark se failon ki suchi ulte kram mein, list of files from the path argument in reverse order); a catalog alias for the list_files_arg_reverse_sort task."',
  '      word "पथ तर्क वाली फ़ाइलों को उल्टे क्रम में सूचीबद्ध करें"',
  '        description "Hindi imperative phrase (romanized path tark vali failon ko ulte kram mein suchibaddh karen, list the path-argument files in reverse order); a catalog alias."',
  '    lexeme "zh"',
  '      word "按相反顺序列出路径参数中的文件"',
  '        description "Chinese phrase (pinyin an xiangfan shunxu liechu lujing canshu zhong de wenjian, list the files in the path argument in reverse order); a catalog alias, matched as a substring."',
  '      word "倒序列出路径参数指定目录中的文件"',
  '        description "Chinese phrase (pinyin daoxu liechu lujing canshu zhiding mulu zhong de wenjian, list the files in the path-argument directory in descending order); a catalog alias."',
  '  meaning "program_task_fizzbuzz"',
  '    gloss "the FizzBuzz coding task as a catalog target (slug fizzbuzz): print 1..15 replacing multiples of three with Fizz, of five with Buzz, of both with FizzBuzz. Defined_by program_task."',
  '    wiktionary "Fizz buzz"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "fizzbuzz"',
  '        description "English one-word name of the FizzBuzz exercise; the primary catalog alias for the fizzbuzz task."',
  '      word "fizz buzz"',
  '        description "English two-word spelling fizz buzz of the FizzBuzz exercise; a catalog alias."',
  '    lexeme "ru"',
  '      word "физзбазз"',
  '        description "Russian transliteration (romanized fizzbazz) of FizzBuzz; a catalog alias for the fizzbuzz task."',
  '      word "физз базз"',
  '        description "Russian two-word transliteration (romanized fizz bazz); a catalog alias."',
  '      word "физбаз"',
  '        description "Russian shortened transliteration (romanized fizbaz) of FizzBuzz; a catalog alias."',
  '    lexeme "hi"',
  '      word "फ़िज़बज़"',
  '        description "Hindi transliteration (romanized fizzbaz) of FizzBuzz; a catalog alias for the fizzbuzz task."',
  '      word "फिज़बज़"',
  '        description "Hindi transliteration without the nuqta (romanized fizbaz); a catalog alias."',
  '    lexeme "zh"',
  '      word "菲茨巴兹"',
  '        description "Chinese transliteration (pinyin feici bazi) of FizzBuzz; a catalog alias, matched as a substring."',
  '  meaning "program_task_factorial"',
  '    gloss "the factorial coding task as a catalog target (slug factorial): compute 5! = 120. Defined_by program_task. The phrasings keep the number 5 or five so the task never answers a different factorial."',
  '    wiktionary "factorial"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "factorial of 5"',
  '        description "English phrase requesting the factorial of 5; a catalog alias for the factorial task."',
  '      word "factorial of five"',
  '        description "English phrase spelling out five; a catalog alias."',
  '      word "5 factorial"',
  '        description "English postfix phrasing 5 factorial; a catalog alias."',
  '      word "five factorial"',
  '        description "English postfix phrasing spelling out five; a catalog alias."',
  '    lexeme "ru"',
  '      word "факториал 5"',
  '        description "Russian phrase (romanized faktorial 5, factorial of 5); a catalog alias for the factorial task."',
  '      word "факториал пяти"',
  '        description "Russian phrase (romanized faktorial pyati, factorial of five); a catalog alias."',
  '      word "факториал числа 5"',
  '        description "Russian phrase (romanized faktorial chisla 5, factorial of the number 5); a catalog alias."',
  '    lexeme "hi"',
  '      word "5 का फैक्टोरियल"',
  '        description "Hindi phrase (romanized 5 ka factorial, factorial of 5); a catalog alias for the factorial task."',
  '      word "पाँच का फैक्टोरियल"',
  '        description "Hindi phrase spelling out five (romanized panch ka factorial); a catalog alias."',
  '    lexeme "zh"',
  '      word "5的阶乘"',
  '        description "Chinese phrase (pinyin 5 de jiecheng, factorial of 5); a catalog alias, matched as a substring."',
  '      word "五的阶乘"',
  '        description "Chinese phrase spelling out five (pinyin wu de jiecheng); a catalog alias."',
  '  meaning "program_task_reverse_string"',
  '    gloss "the string-reversal coding task as a catalog target (slug reverse_string): reverse the literal string hello into olleh. Defined_by program_task. The fixed input keeps the verified output unambiguous."',
  '    wiktionary "string"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "reverse a string"',
  '        description "English phrase requesting a string reversal; a catalog alias for the reverse_string task."',
  '      word "reverse the string hello"',
  '        description "English phrase naming the literal input hello; a catalog alias."',
  '      word "reverse hello"',
  '        description "English compact phrase reverse hello; a catalog alias."',
  '      word "reverse string hello"',
  '        description "English phrase reverse string hello; a catalog alias."',
  '      word "reverse the word hello"',
  '        description "English phrase using word for the input hello; a catalog alias."',
  '    lexeme "ru"',
  '      word "перевернуть строку"',
  '        description "Russian phrase (romanized perevernut stroku, reverse the string); a catalog alias for the reverse_string task."',
  '      word "перевернуть строку hello"',
  '        description "Russian phrase naming the literal input hello (romanized perevernut stroku hello); a catalog alias."',
  '      word "развернуть строку"',
  '        description "Russian phrase (romanized razvernut stroku, reverse the string); a catalog alias."',
  '    lexeme "hi"',
  '      word "स्ट्रिंग को उलटें"',
  '        description "Hindi phrase (romanized string ko ultein, reverse the string); a catalog alias for the reverse_string task."',
  '      word "स्ट्रिंग पलटें"',
  '        description "Hindi phrase (romanized string palten, flip the string); a catalog alias."',
  '    lexeme "zh"',
  '      word "反转字符串"',
  '        description "Chinese phrase (pinyin fanzhuan zifuchuan, reverse the string); a catalog alias, matched as a substring."',
  '      word "翻转字符串"',
  '        description "Chinese phrase with the alternate verb (pinyin fanzhuan zifuchuan, flip the string); a catalog alias."',
  '      word "反转hello"',
  '        description "Chinese phrase naming the literal input hello (pinyin fanzhuan hello); a catalog alias."',
  '  meaning "program_task_sum_to_ten"',
  '    gloss "the sum-to-ten coding task as a catalog target (slug sum_to_ten): sum the integers 1 through 10 to 55. Defined_by program_task. The fixed range keeps the verified output unambiguous."',
  '    wiktionary "summation"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "sum of 1 to 10"',
  '        description "English phrase requesting the sum of 1 to 10; a catalog alias for the sum_to_ten task."',
  '      word "sum from 1 to 10"',
  '        description "English phrase using from 1 to 10; a catalog alias."',
  '      word "sum the numbers 1 to 10"',
  '        description "English phrase using the numbers 1 to 10; a catalog alias."',
  '      word "sum of numbers from 1 to 10"',
  '        description "English phrase using of numbers from 1 to 10; a catalog alias."',
  '      word "sum 1 to 10"',
  '        description "English compact phrase sum 1 to 10; a catalog alias."',
  '      word "sum to ten"',
  '        description "English phrase sum to ten spelling out the bound; a catalog alias."',
  '    lexeme "ru"',
  '      word "сумма от 1 до 10"',
  '        description "Russian phrase (romanized summa ot 1 do 10, sum from 1 to 10); a catalog alias for the sum_to_ten task."',
  '      word "сумма чисел от 1 до 10"',
  '        description "Russian phrase (romanized summa chisel ot 1 do 10, sum of the numbers from 1 to 10); a catalog alias."',
  '      word "сумма чисел от одного до десяти"',
  '        description "Russian phrase spelling out the bounds (romanized summa chisel ot odnogo do desyati, sum of the numbers from one to ten); a catalog alias."',
  '    lexeme "hi"',
  '      word "1 से 10 तक का योग"',
  '        description "Hindi phrase (romanized 1 se 10 tak ka yog, the sum from 1 to 10); a catalog alias for the sum_to_ten task."',
  '      word "1 से 10 तक योग"',
  '        description "Hindi phrase eliding ka (romanized 1 se 10 tak yog); a catalog alias."',
  '    lexeme "zh"',
  '      word "1到10的和"',
  '        description "Chinese phrase (pinyin 1 dao 10 de he, the sum from 1 to 10); a catalog alias, matched as a substring."',
  '      word "1到10求和"',
  '        description "Chinese phrase using the verb qiu he (pinyin 1 dao 10 qiu he, sum from 1 to 10); a catalog alias."',
  '      word "求1到10的和"',
  '        description "Chinese phrase fronting the verb (pinyin qiu 1 dao 10 de he, compute the sum from 1 to 10); a catalog alias."',
  '  meaning "program_task_fibonacci"',
  '    gloss "the recursive-Fibonacci coding task as a catalog target (slug fibonacci): define a recursive fibonacci function and print the 10th term (55). Defined_by program_task. The fixed index keeps the verified output unambiguous and the aliases carry the explicit recursive and function phrasings from issue #334."',
  '    wiktionary "Fibonacci sequence"',
  '    defined_by "program_task"',
  '    role "program_task_alias"',
  '    lexeme "en"',
  '      word "fibonacci sequence recursively"',
  '        description "English phrase requesting the Fibonacci sequence computed recursively; a catalog alias for the fibonacci task."',
  '      word "fibonacci sequence"',
  '        description "English phrase naming the Fibonacci sequence; a catalog alias."',
  '      word "recursive fibonacci"',
  '        description "English phrase recursive fibonacci; a catalog alias."',
  '      word "fibonacci recursively"',
  '        description "English phrase fibonacci recursively; a catalog alias."',
  '      word "fibonacci function"',
  '        description "English phrase naming a fibonacci function; a catalog alias."',
  '      word "fibonacci numbers"',
  '        description "English plural phrase fibonacci numbers; a catalog alias."',
  '      word "fibonacci number"',
  '        description "English singular phrase fibonacci number; a catalog alias."',
  '      word "10th fibonacci number"',
  '        description "English phrase naming the 10th Fibonacci number; a catalog alias."',
  '      word "the 10th fibonacci number"',
  '        description "English phrase with the article naming the 10th Fibonacci number; a catalog alias."',
  '      word "tenth fibonacci number"',
  '        description "English phrase spelling out tenth; a catalog alias."',
  '      word "nth fibonacci number"',
  '        description "English general phrase nth fibonacci number; a catalog alias."',
  '    lexeme "ru"',
  '      word "последовательность фибоначчи"',
  '        description "Russian phrase (romanized posledovatelnost fibonachchi, Fibonacci sequence); a catalog alias for the fibonacci task."',
  '      word "числа фибоначчи"',
  '        description "Russian phrase (romanized chisla fibonachchi, Fibonacci numbers); a catalog alias."',
  '      word "число фибоначчи"',
  '        description "Russian singular phrase (romanized chislo fibonachchi, Fibonacci number); a catalog alias."',
  '      word "рекурсивный фибоначчи"',
  '        description "Russian phrase (romanized rekursivnyy fibonachchi, recursive Fibonacci); a catalog alias."',
  '      word "фибоначчи рекурсивно"',
  '        description "Russian phrase (romanized fibonachchi rekursivno, Fibonacci recursively); a catalog alias."',
  '      word "10-е число фибоначчи"',
  '        description "Russian phrase (romanized 10-e chislo fibonachchi, the 10th Fibonacci number); a catalog alias."',
  '      word "десятое число фибоначчи"',
  '        description "Russian phrase spelling out tenth (romanized desyatoe chislo fibonachchi); a catalog alias."',
  '    lexeme "hi"',
  '      word "फ़िबोनाची अनुक्रम"',
  '        description "Hindi phrase (romanized fibonacci anukram, Fibonacci sequence); a catalog alias for the fibonacci task."',
  '      word "फिबोनाची अनुक्रम"',
  '        description "Hindi phrase without the nuqta (romanized fibonacci anukram); a catalog alias."',
  '      word "फ़िबोनाची संख्या"',
  '        description "Hindi phrase (romanized fibonacci sankhya, Fibonacci number); a catalog alias."',
  '      word "फिबोनाची संख्या"',
  '        description "Hindi phrase without the nuqta (romanized fibonacci sankhya); a catalog alias."',
  '    lexeme "zh"',
  '      word "斐波那契数列"',
  '        description "Chinese phrase (pinyin feibonaqi shulie, Fibonacci sequence); a catalog alias, matched as a substring."',
  '      word "斐波那契序列"',
  '        description "Chinese phrase with the alternate word for sequence (pinyin feibonaqi xulie); a catalog alias."',
  '      word "斐波那契数"',
  '        description "Chinese phrase (pinyin feibonaqi shu, Fibonacci number); a catalog alias."',
  '      word "递归斐波那契"',
  '        description "Chinese phrase (pinyin digui feibonaqi, recursive Fibonacci); a catalog alias."',
].join("\n");

// Semantic role: a thing a program produces that a later turn can refer back to
// (a result, an output, the program/script/code itself, an ordering).
const ROLE_PROGRAM_ARTIFACT = "program_artifact";
// Semantic role: an operation a follow-up turn can request against the active
// program (sort, reverse, cancel, change, …) — additive or subtractive.
const ROLE_PROGRAM_MODIFICATION = "program_modification";
// Semantic role: a kind of program artifact a user can ask to be authored
// (a program, a script, code, a function) — the noun side of "write a <kind>".
const ROLE_PROGRAM_KIND = "program_kind";
// Semantic role: a verb that requests a program artifact be produced (write,
// create, show, generate, make, build) — the verb side of "write a <kind>".
const ROLE_PROGRAM_REQUEST = "program_request";
// Issue #386 program-synthesis roles — mirror the ROLE_PROGRAM_SYNTHESIS_*
// consts in src/seed/meanings.rs. Their surface words live in
// data/seed/meanings-program-synthesis.lino (embedded in MEANINGS_LINO above).
// The subject/domain/action triple gates a synthesis request; signals
// distinguish one task from another; a task's slug is the Python function name.
const ROLE_PROGRAM_SYNTHESIS_SUBJECT = "program_synthesis_subject";
const ROLE_PROGRAM_SYNTHESIS_DOMAIN = "program_synthesis_domain";
const ROLE_PROGRAM_SYNTHESIS_ACTION = "program_synthesis_action";
const ROLE_PROGRAM_SYNTHESIS_SIGNAL = "program_synthesis_signal";
const ROLE_PROGRAM_SYNTHESIS_TASK = "program_synthesis_task";
// Issue #386 conversational-intent roles — mirror the ROLE_CLARIFICATION_REQUEST
// / ROLE_CAPABILITY_QUERY* / ROLE_SELF_FACT_QUERY / ROLE_SELF_INTRODUCTION_REQUEST
// consts in src/seed/meanings.rs. Their surface words live in
// data/seed/meanings-intent.lino (embedded in MEANINGS_LINO above); the
// recognizers below ask the lexicon by meaning instead of hardcoding phrases.
const ROLE_CLARIFICATION_REQUEST = "clarification_request";
const ROLE_CAPABILITY_QUERY = "capability_query";
const ROLE_CAPABILITY_QUERY_MORE = "capability_query_more";
const ROLE_SELF_FACT_QUERY = "self_fact_query";
const ROLE_SELF_INTRODUCTION_REQUEST = "self_introduction_request";
// Issue #386 known-facts inventory roles — mirror the ROLE_KNOWLEDGE_INVENTORY_*
// / ROLE_KNOWLEDGE_POSSESSION consts in src/seed/roles.rs. Their surface words
// live in data/seed/meanings-intent.lino (the shared `fact` noun plus the
// knowledge_inventory_probe / assistant_knowing / knowledge_inventory_query
// meanings, embedded in MEANINGS_LINO above); isKnownFactQuery composes these
// roles instead of hardcoding per-language phrase arrays.
const ROLE_KNOWLEDGE_INVENTORY_NOUN = "knowledge_inventory_noun";
const ROLE_KNOWLEDGE_INVENTORY_INTERROGATIVE = "knowledge_inventory_interrogative";
const ROLE_KNOWLEDGE_POSSESSION = "knowledge_possession";
const ROLE_KNOWLEDGE_INVENTORY_PHRASE = "knowledge_inventory_phrase";

// Issue #386 conversation-summary roles — mirror the
// ROLE_CONVERSATION_SUMMARY_DIRECTIVE / ROLE_CONVERSATION_REFERENCE /
// ROLE_CONVERSATION_SUMMARY_PHRASE / ROLE_CONVERSATION_SUMMARY_COURTESY consts
// in src/seed/roles.rs. Their per-language surface words live once in the
// embedded MEANINGS_LINO above (data/seed/meanings-intent.lino); the
// isSummarizePrompt recogniser composes these roles instead of hardcoding
// per-language phrase / regex arrays.
const ROLE_CONVERSATION_SUMMARY_DIRECTIVE = "conversation_summary_directive";
const ROLE_CONVERSATION_REFERENCE = "conversation_reference";
const ROLE_CONVERSATION_SUMMARY_PHRASE = "conversation_summary_phrase";
const ROLE_CONVERSATION_SUMMARY_COURTESY = "conversation_summary_courtesy";
// Issue #386 conversation-opener role — mirrors ROLE_CONVERSATION_TOPIC_OPENER
// in src/seed/roles.rs. Its slot-marked surface words live in
// data/seed/meanings-conversation.lino (embedded in MEANINGS_LINO above);
// conversationTopic asks the lexicon for these forms by meaning instead of
// hardcoding a per-language opener array.
const ROLE_CONVERSATION_TOPIC_OPENER = "conversation_topic_opener";
// Issue #386 how-cluster roles — mirror the ROLE_MECHANISM_INQUIRY /
// ROLE_PROCEDURAL_REQUEST consts in src/seed/meanings.rs. Their slot-marked
// surface words live in data/seed/meanings-how.lino (embedded in MEANINGS_LINO
// above); extractHowItWorksSubject / extractProceduralHowToTask ask the lexicon
// for these forms by meaning instead of hardcoding per-language phrase arrays.
const ROLE_MECHANISM_INQUIRY = "mechanism_inquiry";
const ROLE_PROCEDURAL_REQUEST = "procedural_request";
// Issue #386 procedural-cluster cleanup roles — mirror the
// ROLE_PROCEDURAL_TASK_MODIFIER / ROLE_COMMON_TYPO consts in src/seed/roles.rs.
// cleanProceduralFragment / correctCommonProceduralTypos ask the lexicon for
// these forms by meaning instead of hardcoding per-language modifier and typo
// arrays.
const ROLE_PROCEDURAL_TASK_MODIFIER = "procedural_task_modifier";
const ROLE_COMMON_TYPO = "common_typo";
// Issue #386 mechanism-subject cleanup roles — mirror the
// ROLE_MECHANISM_PREDICATE / ROLE_DETAIL_MODIFIER / ROLE_NON_REFERENTIAL_SUBJECT
// consts in src/seed/roles.rs. stripMechanismTail / cleanMechanismSubject ask
// the lexicon for these forms by meaning instead of hardcoding per-language
// predicate, modifier, and pronoun arrays.
const ROLE_MECHANISM_PREDICATE = "mechanism_predicate";
const ROLE_DETAIL_MODIFIER = "detail_modifier";
const ROLE_NON_REFERENTIAL_SUBJECT = "non_referential_subject";

// Slot marker (U+2026 …) carried inside a surface word's text to mark the open
// subject/task position. Mirrors the `split_once('…')` slot derivation on
// WordForm in src/seed/meanings.rs (issue #386).
const SLOT_MARKER = "…";

// Build a surface form { text, action, description, slot, before, after } from a
// raw surface word, its optional canonical action, and its self-describing note.
// The slot classification and the literal text on either side are derived from
// the position of the … marker, exactly as WordForm::slot/before_slot/after_slot
// do in src/seed/meanings.rs: no marker = "bare"; trailing marker = "prefix";
// leading marker = "suffix"; a marker with text on both sides = "circumfix".
function makeWordForm(text, action, description) {
  const idx = text.indexOf(SLOT_MARKER);
  if (idx === -1) {
    return {
      text,
      action: action || "",
      description: description || "",
      slot: "bare",
      before: text,
      after: "",
    };
  }
  const before = text.slice(0, idx);
  const after = text.slice(idx + SLOT_MARKER.length);
  let slot = "bare";
  if (before && after) slot = "circumfix";
  else if (before) slot = "prefix";
  else if (after) slot = "suffix";
  return {
    text,
    action: action || "",
    description: description || "",
    slot,
    before,
    after,
  };
}

let cachedMeaningLexicon = null;
// Parse the embedded lexicon once. Each meaning keeps the semantic roles it
// plays, the surface words (across every language) that evidence it, and the
// richer per-form data (action + self-describing note + derived slot) in
// declaration order. Mirrors parse_lexicon in src/seed/meanings.rs.
function meaningLexicon() {
  if (cachedMeaningLexicon) return cachedMeaningLexicon;
  const root = parseLinoTree(MEANINGS_LINO);
  // The lexicon is split across several files (program, units, …), each
  // wrapping its records under a top-level `meanings` node. Concatenated, the
  // document therefore holds one-or-more `meanings` containers; collect the
  // records from every one. If none is present the records sit at the document
  // root (kept for robustness). Mirrors parse_lexicon in src/seed/meanings.rs.
  const containers = root.children.filter((child) => child.name === "meanings");
  const sources = containers.length ? containers : [root];
  const meanings = [];
  for (const container of sources) {
    for (const node of container.children) {
      if (node.name !== "meaning") continue;
      const roles = [];
      const definedBy = [];
      const words = [];
      const wordForms = [];
      // Per-language word groups, so a handler can partition a role's vocabulary
      // by language (e.g. head-initial vs. head-final translation verbs) without
      // losing the language tag the flat `words` list drops. Mirrors the
      // `lexemes` field on Meaning in src/seed/meanings.rs (issue #386).
      const lexemes = [];
      for (const child of node.children) {
        if (child.name === "role") roles.push(child.value);
        else if (child.name === "defined_by") definedBy.push(child.value);
        else if (child.name === "lexeme") {
          const lexemeWords = [];
          for (const lexWord of child.children) {
            if (lexWord.name !== "word") continue;
            words.push(lexWord.value);
            lexemeWords.push(lexWord.value);
            let action = "";
            let description = "";
            for (const attr of lexWord.children) {
              if (attr.name === "action") action = attr.value;
              else if (attr.name === "description") description = attr.value;
            }
            wordForms.push(makeWordForm(lexWord.value, action, description));
          }
          lexemes.push({ language: child.value, words: lexemeWords });
        }
      }
      meanings.push({ slug: node.value, roles, definedBy, words, wordForms, lexemes });
    }
  }
  cachedMeaningLexicon = meanings;
  return cachedMeaningLexicon;
}

// Does `expected` (a surface word or multi-word phrase) appear in `normalized`?
// CJK surfaces match as substrings; everything else matches on whitespace
// boundaries (whole token or whole phrase). Mirrors surface_present in
// src/seed/meanings.rs — stricter than a raw substring, so a short surface like
// "hp" never matches inside "php" and a phrase like "each step" matches only on
// word boundaries.
function surfacePresent(normalized, expected) {
  if (!expected) return false;
  const text = String(normalized || "");
  if (containsCjk(expected)) return text.includes(expected);
  return (
    text === expected ||
    text.startsWith(`${expected} `) ||
    text.endsWith(` ${expected}`) ||
    text.includes(` ${expected} `)
  );
}

// Is any surface word (any language) of `meaning` evidenced in `normalized`?
// Mirrors Meaning::evidenced_in in src/seed/meanings.rs.
function meaningEvidencedIn(meaning, normalized) {
  return meaning.words.some((word) => surfacePresent(normalized, word));
}

// Does `normalized` mention any surface word of any meaning carrying `role`?
// Mirrors Lexicon::mentions_role in src/seed/meanings.rs — the boundary-aware,
// phrase-capable surface_present contract (CJK substring vs. whitespace token).
function lexiconMentionsRole(role, normalized) {
  return meaningsWithRole(role).some((meaning) => meaningEvidencedIn(meaning, normalized));
}

// Like lexiconMentionsRole but ignores a meaning's script-independent *value
// surfaces* — word forms with no alphabetic character, such as the operator
// symbol "+" or the numeral "10". Those forms exist so the arithmetic normalizer
// can read a meaning's machine value; they are not spelled words, so operator-
// *word* detection skips them and a bare "+" is recognised as an operator symbol
// by the symbol scan, not double-counted here. Mirrors Lexicon::mentions_role_spelled
// in src/seed/meanings.rs.
function lexiconMentionsRoleSpelled(role, normalized) {
  return meaningsWithRole(role).some((meaning) =>
    meaning.words
      .filter((word) => /\p{Alphabetic}/u.test(word))
      .some((word) => surfacePresent(normalized, word)),
  );
}

// The first meaning (declaration order) carrying `role` that is evidenced in
// `normalized`, or null. Declaration order encodes priority. Mirrors
// Lexicon::first_role_match in src/seed/meanings.rs.
function firstRoleMatch(role, normalized) {
  return meaningsWithRole(role).find((meaning) => meaningEvidencedIn(meaning, normalized)) || null;
}

// Issue #386 calendar roles — mirror the ROLE_CALENDAR_* consts in
// src/seed/meanings.rs. Their surface words live in
// data/seed/meanings-calendar.lino (embedded in MEANINGS_LINO above). The
// calendar handler uses its own boundary-aware matcher (containsCalendarTerm)
// rather than lexiconMentionsRole, so these come with dedicated accessors.
const ROLE_CALENDAR_WEEKDAY = "calendar_weekday";
const ROLE_CALENDAR_DIRECTION_NEXT = "calendar_direction_next";
const ROLE_CALENDAR_DIRECTION_PREVIOUS = "calendar_direction_previous";
const ROLE_CALENDAR_TODAY = "calendar_today";
const ROLE_CALENDAR_DAY_REFERENCE = "calendar_day_reference";
const ROLE_CALENDAR_QUESTION = "calendar_question";

// Every meaning carrying `role`, in lexicon (declaration) order. Mirrors
// Lexicon::meanings_with_role in src/seed/meanings.rs.
function meaningsWithRole(role) {
  return meaningLexicon().filter((meaning) => meaning.roles.includes(role));
}

// Every slot-marked surface form carrying `role`, flattened across all meanings
// and languages in declaration order. Recognition code buckets the result by
// form.slot ("bare" / "prefix" / "suffix" / "circumfix") to derive its
// affix-matching strategy from the data. Mirrors Lexicon::role_word_forms in
// src/seed/meanings.rs (issue #386).
function roleWordForms(role) {
  const forms = [];
  for (const meaning of meaningsWithRole(role)) {
    for (const form of meaning.wordForms) forms.push(form);
  }
  return forms;
}

// The meaning identified by `slug`, or null. Mirrors Lexicon::meaning in
// src/seed/meanings.rs.
function findMeaning(slug) {
  return meaningLexicon().find((meaning) => meaning.slug === slug) || null;
}

// Distinct surface words (across all languages) carried by the meaning `slug`,
// or an empty array when no such meaning exists. The coding catalog reads each
// language's and task's alias surfaces from the `program_language_<slug>` /
// `program_task_<slug>` meanings by slug (issue #386), so the matchers name only
// the concept while the words stay self-describing seed data. Mirrors the Rust
// `coding::catalog::alias_surfaces` helper.
function wordsForMeaning(slug) {
  return findMeaning(slug)?.words || [];
}

// Distinct surface words (across all languages) for `role`, declaration order.
// Mirrors Lexicon::words_for_role in src/seed/meanings.rs.
function wordsForRole(role) {
  const seen = new Set();
  const words = [];
  for (const meaning of meaningsWithRole(role)) {
    for (const word of meaning.words) {
      if (!seen.has(word)) {
        seen.add(word);
        words.push(word);
      }
    }
  }
  return words;
}

// Issue #386 translation-command role — mirrors ROLE_TRANSLATION_ACTION in
// src/seed/roles.rs. The per-language command verbs (translate, переведи/
// перевести/опиши, अनुवाद, 翻译/翻譯) live once in the embedded MEANINGS_LINO
// (data/seed/meanings-translation.lino) under the `translate` meaning; the gate
// and source-inferencer reference the concept, not the raw words.
const ROLE_TRANSLATION_ACTION = "translation_action";

// Distinct surface words for `role` limited to `languages`, declaration order.
// Mirrors Lexicon::words_for_role_in_languages in src/seed/meanings.rs (#386).
function wordsForRoleInLanguages(role, languages) {
  const out = [];
  for (const meaning of meaningsWithRole(role)) {
    for (const lexeme of meaning.lexemes) {
      if (!languages.includes(lexeme.language)) continue;
      for (const word of lexeme.words) {
        if (!out.includes(word)) out.push(word);
      }
    }
  }
  return out;
}

// The first language in `priority` whose surface word for `role` appears in
// `normalized` (raw substring), or null when none is present. Answers "which
// language did the user issue this command in?". Mirrors
// Lexicon::first_role_language in src/seed/meanings.rs (#386).
function firstRoleLanguage(role, normalized, priority) {
  for (const lang of priority) {
    const present = meaningsWithRole(role).some((meaning) =>
      meaning.lexemes.some(
        (lexeme) =>
          lexeme.language === lang &&
          lexeme.words.some((word) => normalized.includes(word)),
      ),
    );
    if (present) return lang;
  }
  return null;
}

// The first surface word `meaning` lexicalises in `language`, or null. Mirrors
// Meaning::word_in in src/seed/meanings.rs (issue #386).
function wordIn(meaning, language) {
  for (const lexeme of meaning.lexemes) {
    if (lexeme.language !== language) continue;
    for (const word of lexeme.words) {
      if (word) return word;
    }
  }
  return null;
}

// Translate `surface` from `source` to `target` through the meaning carrying
// `role` that lexicalises it: the first such meaning (declaration order) whose
// `source` lexeme lists `surface`, returning its first `target` form, or null.
// Mirrors Lexicon::role_surface_translation in src/seed/meanings.rs (issue #386).
function roleSurfaceTranslation(role, source, target, surface) {
  for (const meaning of meaningsWithRole(role)) {
    const lists = meaning.lexemes.some(
      (lexeme) => lexeme.language === source && lexeme.words.includes(surface),
    );
    if (lists) return wordIn(meaning, target);
  }
  return null;
}

// Does any meaning carrying `role` lexicalise `surface` in `language`? Mirrors
// Lexicon::role_lists_surface in src/seed/meanings.rs (issue #386).
function roleListsSurface(role, language, surface) {
  return meaningsWithRole(role).some((meaning) =>
    meaning.lexemes.some(
      (lexeme) => lexeme.language === language && lexeme.words.includes(surface),
    ),
  );
}

// Like roleSurfaceTranslation but the `source` form must also carry the per-form
// grammatical `action` tag (e.g. "genitive"). The worker keeps per-form action on
// the flat wordForms array (no language) and raw strings on each lexeme, so a
// form qualifies when the source lexeme lists `surface` and some wordForm has the
// same text and `action`. Mirrors Lexicon::role_action_surface_translation in
// src/seed/meanings.rs (issue #386).
function roleActionSurfaceTranslation(role, action, source, target, surface) {
  for (const meaning of meaningsWithRole(role)) {
    const listsInSource = meaning.lexemes.some(
      (lexeme) => lexeme.language === source && lexeme.words.includes(surface),
    );
    const tagged = meaning.wordForms.some(
      (form) => form.text === surface && form.action === action,
    );
    if (listsInSource && tagged) return wordIn(meaning, target);
  }
  return null;
}

// Issue #386 software-project follow-up roles — mirror the
// ROLE_SOFTWARE_FOLLOWUP_* consts in src/seed/meanings.rs. Their surface words
// live in data/seed/meanings-software-project.lino (embedded in MEANINGS_LINO
// above). detectSoftwareFollowUp matches them as raw substrings (not whole
// tokens), so they come with a dedicated accessor.
const ROLE_SOFTWARE_FOLLOWUP_VERIFICATION = "software_followup_verification";
const ROLE_SOFTWARE_FOLLOWUP_EXECUTION = "software_followup_execution";
const ROLE_SOFTWARE_FOLLOWUP_DEMONSTRATION = "software_followup_demonstration";

// Issue #386 behavior-rules-list roles — mirror the ROLE_RULE_LISTING_* consts
// in src/seed/roles.rs. Their surface words live in
// data/seed/meanings-behavior-rules.lino (embedded in MEANINGS_LINO above).
// isBehaviorRulesList ANDs the three compositional dimensions within one
// language (subject + request + scope) and ORs the standalone phrase role,
// matching every surface as a raw substring exactly like the Rust recogniser.
const ROLE_RULE_LISTING_SUBJECT = "rule_listing_subject";
const ROLE_RULE_LISTING_REQUEST = "rule_listing_request";
const ROLE_RULE_LISTING_SCOPE = "rule_listing_scope";
const ROLE_RULE_LISTING_PHRASE = "rule_listing_phrase";

// Does `normalized` contain any surface word of any meaning carrying `role`,
// matched as a raw substring? Unlike lexiconMentionsRole (whole-token, via
// containsProgramToken), follow-up markers are multi-word phrases ("run the
// tests", "show me"), so a token-boundary match would never find them. Mirrors
// the raw `.contains()` in follow_up_kind
// (src/solver_handlers/software_project_followup.rs).
function lexiconMentionsRoleSubstring(role, normalized) {
  return meaningLexicon().some(
    (meaning) =>
      meaning.roles.includes(role) &&
      meaning.words.some((word) => word && normalized.includes(word)),
  );
}

// Does any surface form `meaning` lexicalises in one of `languages` appear in
// `normalized` as a raw substring (String.includes)? The language-restricted,
// raw-substring sibling of meaningEvidencedIn. Mirrors
// Meaning::mentions_in_languages_raw in src/seed/meanings.rs (issue #386).
function meaningMentionsInLanguagesRaw(meaning, normalized, languages) {
  return meaning.lexemes.some(
    (lexeme) =>
      languages.includes(lexeme.language) &&
      lexeme.words.some((word) => word && normalized.includes(word)),
  );
}

// The first meaning (declaration order) carrying `role` whose `languages`
// surface forms occur in `normalized` as a raw substring, or null. Declaration
// order encodes priority. Mirrors Lexicon::first_role_match_in_languages_raw in
// src/seed/meanings.rs (issue #386).
function firstRoleMatchInLanguagesRaw(role, normalized, languages) {
  return (
    meaningsWithRole(role).find((meaning) =>
      meaningMentionsInLanguagesRaw(meaning, normalized, languages),
    ) || null
  );
}

// Does any meaning carrying `role` mention one of its `languages` surface forms
// in `normalized` as a raw substring? Mirrors
// Lexicon::mentions_role_in_languages_raw in src/seed/meanings.rs (issue #386).
function mentionsRoleInLanguagesRaw(role, normalized, languages) {
  return meaningsWithRole(role).some((meaning) =>
    meaningMentionsInLanguagesRaw(meaning, normalized, languages),
  );
}

function detectedProgramModifiers(normalized) {
  const slugs = [];
  const validModifiers = programModifierSlugs();
  for (const operation of operationVocabulary()) {
    if (validModifiers.has(operation.slug) && operationFormMatches(normalized, operation)) {
      slugs.push(operation.slug);
    }
  }
  return slugs;
}

// --- Substitution engine (mirror of src/substitution.rs) -------------------

function unescapeLinoValue(value) {
  let out = "";
  for (let index = 0; index < value.length; index += 1) {
    const ch = value[index];
    if (ch === "\\" && index + 1 < value.length) {
      const next = value[index + 1];
      if (next === "n") {
        out += "\n";
        index += 1;
        continue;
      }
      if (next === '"' || next === "\\") {
        out += next;
        index += 1;
        continue;
      }
    }
    out += ch;
  }
  return out;
}

function parseLinoValue(raw) {
  const trimmed = raw.trim();
  if (trimmed.length >= 2 && trimmed.startsWith('"') && trimmed.endsWith('"')) {
    return unescapeLinoValue(trimmed.slice(1, -1));
  }
  return trimmed;
}

function parseLinoTree(text) {
  const root = { name: "", value: "", depth: -1, children: [] };
  const stack = [root];
  for (const line of text.split("\n")) {
    if (!line.trim()) continue;
    const indent = line.length - line.trimStart().length;
    const depth = indent / 2;
    const rest = line.trim();
    const spaceIndex = rest.indexOf(" ");
    const name = spaceIndex === -1 ? rest : rest.slice(0, spaceIndex);
    const value = spaceIndex === -1 ? "" : parseLinoValue(rest.slice(spaceIndex + 1));
    const node = { name, value, depth, children: [] };
    while (stack.length && stack[stack.length - 1].depth >= depth) stack.pop();
    stack[stack.length - 1].children.push(node);
    stack.push(node);
  }
  return root;
}

function parsePatternNode(text) {
  if (!text) throw new Error("pattern node is empty");
  if (text.startsWith("$")) return { kind: "variable", variable: text.slice(1) };
  const dollar = text.indexOf("$");
  if (dollar !== -1) {
    return { kind: "prefix", prefix: text.slice(0, dollar), variable: text.slice(dollar + 1) };
  }
  return { kind: "literal", value: text };
}

function parseLinkPattern(text) {
  const index = text.indexOf("->");
  if (index === -1) throw new Error(`expected \`from -> to\`, got \`${text}\``);
  return {
    from: parsePatternNode(text.slice(0, index).trim()),
    to: parsePatternNode(text.slice(index + 2).trim()),
  };
}

function parseCrudEvent(value) {
  const map = {
    manual: "manual",
    apply: "manual",
    create: "create",
    created: "create",
    read: "read",
    select: "read",
    query: "read",
    update: "update",
    updated: "update",
    delete: "delete",
    deleted: "delete",
  };
  const key = String(value).trim().toLowerCase();
  if (!map[key]) throw new Error(`invalid CRUD event: ${value}`);
  return map[key];
}

function parseSubstitutionRule(node) {
  const rule = { id: node.value, order: 0, events: [], conditions: [], actions: [] };
  for (const child of node.children) {
    switch (child.name) {
      case "order": {
        const parsed = parseInt(child.value, 10);
        rule.order = Number.isNaN(parsed) ? 0 : parsed;
        break;
      }
      case "event":
        rule.events.push(parseCrudEvent(child.value));
        break;
      case "when":
        rule.conditions.push(parseLinkPattern(child.value));
        break;
      case "replace": {
        const add = child.children
          .filter((grandchild) => grandchild.name === "with")
          .map((grandchild) => parseLinkPattern(grandchild.value));
        rule.actions.push({ remove: parseLinkPattern(child.value), add });
        break;
      }
      default:
        break;
    }
  }
  return rule;
}

function parseSubstitutionRules(text) {
  const tree = parseLinoTree(text.trim());
  const root = tree.children[0];
  if (!root || root.name !== "substitution_rules") {
    throw new Error("not a substitution_rules document");
  }
  const idNode = root.children.find((child) => child.name === "id");
  const id = idNode ? idNode.value : "";
  const rules = root.children
    .filter((child) => child.name === "rule")
    .map(parseSubstitutionRule);
  rules.sort((left, right) =>
    left.order - right.order ||
    (left.id < right.id ? -1 : left.id > right.id ? 1 : 0),
  );
  return { id, rules };
}

const LINK_KEY_SEPARATOR = "";
const linkKey = (link) => `${link.from}${LINK_KEY_SEPARATOR}${link.to}`;
const linkFromKey = (key) => {
  const [from, to] = key.split(LINK_KEY_SEPARATOR);
  return { from, to };
};

function sortedLinksFromSet(linkSet) {
  return Array.from(linkSet, linkFromKey).sort((left, right) =>
    left.from < right.from
      ? -1
      : left.from > right.from
        ? 1
        : left.to < right.to
          ? -1
          : left.to > right.to
            ? 1
            : 0,
  );
}

function bindVariable(bindings, variable, value) {
  if (Object.prototype.hasOwnProperty.call(bindings, variable)) {
    return bindings[variable] === value;
  }
  bindings[variable] = value;
  return true;
}

function nodeMatches(pattern, value, bindings) {
  if (pattern.kind === "literal") return pattern.value === value;
  if (pattern.kind === "variable") return bindVariable(bindings, pattern.variable, value);
  if (!value.startsWith(pattern.prefix)) return false;
  return bindVariable(bindings, pattern.variable, value.slice(pattern.prefix.length));
}

function patternMatchesLink(pattern, link, bindings) {
  return (
    nodeMatches(pattern.from, link.from, bindings) &&
    nodeMatches(pattern.to, link.to, bindings)
  );
}

function instantiateNode(node, bindings) {
  if (node.kind === "literal") return node.value;
  if (node.kind === "variable") {
    return Object.prototype.hasOwnProperty.call(bindings, node.variable)
      ? bindings[node.variable]
      : null;
  }
  const value = bindings[node.variable];
  return value === undefined ? null : node.prefix + value;
}

function instantiatePattern(pattern, bindings) {
  const from = instantiateNode(pattern.from, bindings);
  const to = instantiateNode(pattern.to, bindings);
  if (from === null || to === null) return null;
  return { from, to };
}

function findBindings(links, patterns, index, bindings) {
  if (index >= patterns.length) return bindings;
  const pattern = patterns[index];
  for (const link of links) {
    const candidate = Object.assign({}, bindings);
    if (patternMatchesLink(pattern, link, candidate)) {
      const found = findBindings(links, patterns, index + 1, candidate);
      if (found) return found;
    }
  }
  return null;
}

function applySubstitutionRule(linkSet, rule, event, sequence) {
  if (!rule.events.includes(event)) return null;
  const required = rule.conditions.slice();
  for (const action of rule.actions) required.push(action.remove);
  const links = sortedLinksFromSet(linkSet);
  const bindings = findBindings(links, required, 0, {});
  if (!bindings) return null;
  // Pre-instantiate every mutation so a partial rewrite never mutates the set.
  const ops = [];
  for (const action of rule.actions) {
    const remove = instantiatePattern(action.remove, bindings);
    if (remove === null) return null;
    const adds = [];
    for (const addPattern of action.add) {
      const add = instantiatePattern(addPattern, bindings);
      if (add === null) return null;
      adds.push(add);
    }
    ops.push({ remove, adds });
  }
  const before = new Set(linkSet);
  const removed = [];
  const added = [];
  for (const op of ops) {
    const removeKey = linkKey(op.remove);
    if (linkSet.has(removeKey)) {
      linkSet.delete(removeKey);
      removed.push(op.remove);
    }
    for (const add of op.adds) {
      const addKey = linkKey(add);
      if (!linkSet.has(addKey)) {
        linkSet.add(addKey);
        added.push(add);
      }
    }
  }
  if (linkSet.size === before.size && [...linkSet].every((key) => before.has(key))) {
    return null;
  }
  return { sequence, ruleId: rule.id, event, bindings, removed, added };
}

function applyFirstSubstitutionRule(linkSet, ruleSet, event, sequence) {
  for (const rule of ruleSet.rules) {
    if (!rule.events.includes(event)) continue;
    const trace = applySubstitutionRule(linkSet, rule, event, sequence);
    if (trace) return trace;
  }
  return null;
}

const DEFAULT_MAX_SUBSTITUTIONS = 64;

function applySubstitutionRules(initialLinks, ruleSet, event, maxApplications) {
  const limit = maxApplications || DEFAULT_MAX_SUBSTITUTIONS;
  const linkSet = new Set(initialLinks.map(linkKey));
  const traces = [];
  let terminatedByGuard = false;
  while (traces.length < limit) {
    const trace = applyFirstSubstitutionRule(linkSet, ruleSet, event, traces.length);
    if (!trace) {
      return { links: sortedLinksFromSet(linkSet), traces, terminatedByGuard };
    }
    traces.push(trace);
  }
  const probe = new Set(linkSet);
  terminatedByGuard =
    applyFirstSubstitutionRule(probe, ruleSet, event, traces.length) !== null;
  return { links: sortedLinksFromSet(linkSet), traces, terminatedByGuard };
}

// --- Program-plan pipeline (mirror of src/program_plan.rs) ------------------

// Issue #386: every declared (cancelOp, baseOp) inverse relationship, taken
// from the `inverse` field on a modifier operation. Mirrors
// `OperationVocabulary::inverse_pairs` in `src/seed/operation_vocabulary.rs`.
function inversePairsFromOperations() {
  const pairs = [];
  for (const operation of operationVocabulary()) {
    if (operation.inverse) pairs.push([operation.slug, operation.inverse]);
  }
  return pairs;
}

function cloneLinkPattern(pattern) {
  return {
    from: Object.assign({}, pattern.from),
    to: Object.assign({}, pattern.to),
  };
}

// Issue #386: derive subtractive ("cancel") rules from the additive base rules
// plus the declared (cancelOp, baseOp) inverse pairs — the JS mirror of
// `derive_inverse_rules` in `src/program_plan.rs`. For every base rule that
// fires on `request:modifier -> baseOp` with a single-link task rewrite, emit
// its inverse: fire on `request:modifier -> cancelOp` and swap the rewrite's
// removed and added task links. "Cancel the sort" becomes the exact,
// automatically-maintained inverse of "sort" — pure data, no new control flow.
function deriveInverseRules(baseRules, inversePairs) {
  const derived = [];
  for (const [cancelOp, baseOp] of inversePairs) {
    for (const rule of baseRules) {
      const conditionIndex = rule.conditions.findIndex(
        (condition) =>
          literalPatternValue(condition.from) === MODIFIER_NODE &&
          literalPatternValue(condition.to) === baseOp,
      );
      if (conditionIndex === -1) continue;
      // A well-defined inverse exists only for a single-link additive rewrite.
      if (rule.actions.length !== 1) continue;
      const action = rule.actions[0];
      if (!Array.isArray(action.add) || action.add.length !== 1) continue;
      const added = action.add[0];
      const conditions = rule.conditions.map((condition, index) =>
        index === conditionIndex
          ? parseLinkPattern(`${MODIFIER_NODE} -> ${cancelOp}`)
          : cloneLinkPattern(condition),
      );
      derived.push({
        id: `${cancelOp}__${rule.id}`,
        order: rule.order,
        events: rule.events.slice(),
        conditions,
        actions: [{ remove: cloneLinkPattern(added), add: [cloneLinkPattern(action.remove)] }],
      });
    }
  }
  return derived;
}

let cachedProgramPlanRules = null;
function programPlanRules() {
  if (!cachedProgramPlanRules) {
    const set = parseSubstitutionRules(PROGRAM_PLAN_RULES_LINO);
    const derived = deriveInverseRules(set.rules, inversePairsFromOperations());
    set.rules = set.rules.concat(derived);
    set.rules.sort((left, right) =>
      left.order - right.order ||
      (left.id < right.id ? -1 : left.id > right.id ? 1 : 0),
    );
    cachedProgramPlanRules = set;
  }
  return cachedProgramPlanRules;
}

function lowerProgramPlanWithRules(ruleSet, baseTask, modifiers) {
  const initial = [{ from: TASK_NODE, to: baseTask }];
  for (const modifier of modifiers) initial.push({ from: MODIFIER_NODE, to: modifier });
  const { links, traces, terminatedByGuard } = applySubstitutionRules(
    initial,
    ruleSet,
    "manual",
  );
  const resolvedLink = links.find((link) => link.from === TASK_NODE);
  const resolvedTask = resolvedLink ? resolvedLink.to : baseTask;
  return {
    baseTask,
    modifiers: modifiers.slice(),
    resolvedTask,
    links,
    traces,
    terminatedByGuard,
  };
}

function lowerProgramPlan(baseTask, modifiers) {
  return lowerProgramPlanWithRules(programPlanRules(), baseTask, modifiers);
}

function resolveProgramTask(baseTask, modifiers) {
  return lowerProgramPlan(baseTask, modifiers).resolvedTask;
}

function programPlanWasModified(plan) {
  return plan.resolvedTask !== plan.baseTask;
}

// Render the plan graph and its substitution trace as Links Notation so the
// worker can surface the reasoning transparently (issue #324 R6), mirroring
// `ProgramPlan::links_notation` in `src/program_plan.rs`.
function programPlanLinksNotation(plan) {
  const lines = ["program_plan"];
  lines.push(`  base_task ${plan.baseTask}`);
  lines.push(`  resolved_task ${plan.resolvedTask}`);
  for (const modifier of plan.modifiers) lines.push(`  modifier ${modifier}`);
  lines.push("  substitution_graph");
  for (const link of plan.links) lines.push(`    link ${link.from} -> ${link.to}`);
  lines.push("  substitution_trace_report");
  lines.push("    event manual");
  lines.push(`    terminated_by_guard ${plan.terminatedByGuard ? "true" : "false"}`);
  for (const trace of plan.traces) {
    lines.push(`    trace ${trace.ruleId}`);
    lines.push(`      sequence ${trace.sequence}`);
    lines.push(`      rule_id ${trace.ruleId}`);
    for (const name of Object.keys(trace.bindings).sort()) {
      lines.push(`      binding ${name}=${trace.bindings[name]}`);
    }
    for (const link of trace.removed) lines.push(`      removed ${link.from} -> ${link.to}`);
    for (const link of trace.added) lines.push(`      added ${link.from} -> ${link.to}`);
  }
  return lines.join("\n");
}

function writeProgramParameters(prompt) {
  const normalized = normalizeProgramPrompt(prompt);
  let task = programTaskFromPrompt(normalized);
  const language = programLanguageFromPrompt(normalized);
  // Issue #386: recognise "write a <program>" by *meaning*, not a hardcoded
  // per-language word list — a program_kind artifact (program / script / code /
  // function) requested by a program_request verb (write / create / … / build).
  // The surface words live once in data/seed/meanings.lino; this code knows the
  // concepts. Mirrors write_program_parameters in src/intent_formalization.rs.
  const asksForProgram =
    lexiconMentionsRole(ROLE_PROGRAM_KIND, normalized) &&
    lexiconMentionsRole(ROLE_PROGRAM_REQUEST, normalized);
  if (!task && !asksForProgram) return null;
  // Issue #358: modification phrases in the same turn lower the base task
  // through the data-backed substitution pipeline.
  if (task) {
    const modifiers = detectedProgramModifiers(normalized);
    task = resolveProgramTask(task, modifiers);
  }
  return { language, task };
}

function looksLikeBareProgramArtifactFollowUp(normalized) {
  // Issue #386: a bare follow-up modifies an existing program artifact when the
  // prompt evidences a program_artifact meaning *and* a program_modification
  // meaning. The surface words live once in the seed; this code knows concepts.
  return (
    lexiconMentionsRole(ROLE_PROGRAM_ARTIFACT, normalized) &&
    lexiconMentionsRole(ROLE_PROGRAM_MODIFICATION, normalized)
  );
}

function activeProgramContext(history) {
  let task = null;
  let language = null;
  if (!Array.isArray(history)) return null;
  for (let index = history.length - 1; index >= 0; index -= 1) {
    const turn = history[index];
    const content = turn && (turn.content || turn.text || turn.message);
    if (!content) continue;
    const prior = writeProgramParameters(content);
    if (!prior) continue;
    if (!task && prior.task) task = prior.task;
    if (!language && prior.language) language = prior.language;
    if (task && language) return { task, language };
  }
  return null;
}

function rewriteBareProgramCoreference(prompt, history) {
  const normalized = normalizeProgramPrompt(prompt);
  if (!looksLikeBareProgramArtifactFollowUp(normalized)) return null;
  const context = activeProgramContext(history);
  if (!context) return null;
  return {
    parameters: { task: context.task, language: context.language },
    trace: `referent=active_program_artifact task=${context.task} language=${context.language}`,
  };
}

// Issue #324: a follow-up such as "Сделай так, чтобы программа принимала путь
// как аргумент" routes to write_program but names neither a task nor a
// language - both came from a previous turn. Recover the missing parameters
// from the most recent prior turn that named them and apply any data-defined
// modifier present in the follow-up. Mirrors `recover_write_program_rule` in
// `src/intent_formalization.rs`.
function recoverWriteProgramParameters(parameters, prompt, history) {
  let task = parameters.task || null;
  let language = parameters.language || null;
  if ((!task || !language) && Array.isArray(history)) {
    for (let index = history.length - 1; index >= 0; index -= 1) {
      const turn = history[index];
      const content = turn && (turn.content || turn.text || turn.message);
      if (!content) continue;
      const prior = writeProgramParameters(content);
      if (!prior) continue;
      if (!task && prior.task) task = prior.task;
      if (!language && prior.language) language = prior.language;
      if (task && language) break;
    }
  }
  const normalized = normalizeProgramPrompt(prompt);
  // Issue #324 R4/R6: lower the recovered task through the substitution
  // pipeline when the follow-up carries a modifier, and surface the resulting
  // plan as Links Notation (mirrors `recover_write_program_rule` in
  // `src/intent_formalization.rs`, which sets `WriteProgramRecovery::plan`).
  let plan = null;
  let modifiers = [];
  let lowered = null;
  if (task) {
    modifiers = detectedProgramModifiers(normalized);
    if (modifiers.length) {
      lowered = lowerProgramPlan(task, modifiers);
      if (programPlanWasModified(lowered)) plan = programPlanLinksNotation(lowered);
      task = lowered.resolvedTask;
    }
  }
  return { task, language, plan, modifiers, lowered };
}

// Issue #324: a request in a given language must be answered in that language.
// These mirror the localized framing produced by the Rust engine
// (`write_program_intro`, `unsupported_write_program_answer`,
// `execution_report`). Only the natural-language prose is localized; the code
// and the Links Notation trace stay canonical. `en` is the fallback.
const WRITE_PROGRAM_I18N = {
  en: {
    intro: (name, label) => `Here is a minimal ${name} ${label} program:`,
    unsupported: (language, task, languages, tasks) =>
      `I can route \`write_program(language, task)\`, but I do not have a template for ` +
      `language \`${language}\` and task \`${task}\`. ` +
      `Supported languages: ${languages}. Supported tasks: ${tasks}.`,
    ranInSandbox: "Execution status: ran in the demo's Web Worker sandbox.",
    outputLabel: "Output:",
    noOutput: "(no output)",
    sandboxFailed: (message) => `Execution status: failed in sandbox - ${message}.`,
    notRun: (language, reason) =>
      `Execution status: not run - ${reason}. Copy the snippet into a ${language} environment to verify.`,
    noFilesystem: (language) =>
      `the browser sandbox has no filesystem access for this ${language} program`,
    noToolchain: (language) => `the browser sandbox cannot invoke a ${language} toolchain`,
    sampleDirectory:
      "The output depends on the directory; for a sample directory holding " +
      "exactly `Cargo.toml`, `README.md`, and `main.rs` it is:",
    expectedOutput: "Expected output after verification:",
  },
  ru: {
    intro: (name, label) => `Вот минимальная программа на языке ${name} (${label}):`,
    unsupported: (language, task, languages, tasks) =>
      `Я могу выполнить \`write_program(language, task)\`, но у меня нет шаблона для ` +
      `языка \`${language}\` и задачи \`${task}\`. ` +
      `Поддерживаемые языки: ${languages}. Поддерживаемые задачи: ${tasks}.`,
    ranInSandbox: "Статус выполнения: запущено в песочнице Web Worker демо.",
    outputLabel: "Вывод:",
    noOutput: "(нет вывода)",
    sandboxFailed: (message) => `Статус выполнения: сбой в песочнице - ${message}.`,
    notRun: (language, reason) =>
      `Статус выполнения: не запущено - ${reason}. Скопируйте фрагмент в среду ${language}, чтобы проверить.`,
    noFilesystem: (language) =>
      `у браузерной песочницы нет доступа к файловой системе для этой программы на ${language}`,
    noToolchain: (language) =>
      `браузерная песочница не может вызвать инструментарий ${language}`,
    sampleDirectory:
      "Вывод зависит от каталога; для образца каталога, содержащего ровно " +
      "`Cargo.toml`, `README.md` и `main.rs`, он такой:",
    expectedOutput: "Ожидаемый вывод после проверки:",
  },
  hi: {
    intro: (name, label) => `यहाँ ${name} में एक न्यूनतम प्रोग्राम है (${label}):`,
    unsupported: (language, task, languages, tasks) =>
      `मैं \`write_program(language, task)\` रूट कर सकता हूँ, लेकिन भाषा \`${language}\` और ` +
      `कार्य \`${task}\` के लिए मेरे पास कोई टेम्पलेट नहीं है। ` +
      `समर्थित भाषाएँ: ${languages}. समर्थित कार्य: ${tasks}.`,
    ranInSandbox: "निष्पादन स्थिति: डेमो के Web Worker सैंडबॉक्स में चला।",
    outputLabel: "आउटपुट:",
    noOutput: "(कोई आउटपुट नहीं)",
    sandboxFailed: (message) => `निष्पादन स्थिति: सैंडबॉक्स में विफल - ${message}.`,
    notRun: (language, reason) =>
      `निष्पादन स्थिति: नहीं चला - ${reason}. सत्यापित करने के लिए स्निपेट को ${language} वातावरण में कॉपी करें।`,
    noFilesystem: (language) =>
      `इस ${language} प्रोग्राम के लिए ब्राउज़र सैंडबॉक्स में फ़ाइल सिस्टम तक पहुँच नहीं है`,
    noToolchain: (language) =>
      `ब्राउज़र सैंडबॉक्स ${language} टूलचेन को आमंत्रित नहीं कर सकता`,
    sampleDirectory:
      "आउटपुट निर्देशिका पर निर्भर करता है; ठीक `Cargo.toml`, `README.md` और " +
      "`main.rs` रखने वाली एक नमूना निर्देशिका के लिए यह है:",
    expectedOutput: "सत्यापन के बाद अपेक्षित आउटपुट:",
  },
  zh: {
    intro: (name, label) => `这是一个最小的 ${name} 程序(${label}):`,
    unsupported: (language, task, languages, tasks) =>
      `我可以路由 \`write_program(language, task)\`,但我没有语言 \`${language}\` 和任务 ` +
      `\`${task}\` 的模板。支持的语言:${languages}。支持的任务:${tasks}。`,
    ranInSandbox: "执行状态:已在演示的 Web Worker 沙箱中运行。",
    outputLabel: "输出:",
    noOutput: "(无输出)",
    sandboxFailed: (message) => `执行状态:沙箱中失败 - ${message}。`,
    notRun: (language, reason) =>
      `执行状态:未运行 - ${reason}。将代码片段复制到 ${language} 环境中以验证。`,
    noFilesystem: (language) => `浏览器沙箱无法为此 ${language} 程序访问文件系统`,
    noToolchain: (language) => `浏览器沙箱无法调用 ${language} 工具链`,
    sampleDirectory:
      "输出取决于目录;对于恰好包含 `Cargo.toml`、`README.md` 和 `main.rs` 的示例目录,它是:",
    expectedOutput: "验证后的预期输出:",
  },
};

function writeProgramStrings(language) {
  return WRITE_PROGRAM_I18N[language] || WRITE_PROGRAM_I18N.en;
}

function writeProgramExecutionLines(language, task, code, output, strings) {
  const i18n = strings || WRITE_PROGRAM_I18N.en;
  // Issue #312: the list-files snippet reads the real filesystem through Node's
  // `fs`/`require`, which the browser Web Worker sandbox does not provide, and
  // its output depends on the directory contents. Never claim it "ran" here -
  // detect the Node API use and report the documented sample-directory output
  // instead, so the demo stays honest.
  const needsNodeApis = /\brequire\s*\(|\bimport\b/.test(code);
  if (language === "javascript" && !needsNodeApis) {
    const logs = [];
    try {
      const runner = new Function("console", `"use strict"; ${code}`);
      runner({ log: (...args) => logs.push(args.join(" ")) });
      return [
        i18n.ranInSandbox,
        i18n.outputLabel,
        "```text",
        logs.join("\n") || i18n.noOutput,
        "```",
      ];
    } catch (error) {
      return [i18n.sandboxFailed(error.message || String(error))];
    }
  }
  const reason =
    language === "javascript" ? i18n.noFilesystem(language) : i18n.noToolchain(language);
  const lines = [i18n.notRun(language, reason)];
  if (
    task === "list_files" ||
    task === "list_files_arg" ||
    task === "list_files_reverse_sort" ||
    task === "list_files_arg_reverse_sort"
  ) {
    lines.push(i18n.sampleDirectory);
  } else {
    lines.push(i18n.expectedOutput);
  }
  lines.push("```text", output, "```");
  return lines;
}

// Issue #330 (R9): a localized plain-language "How it works" paragraph so the
// demo teaches a novice instead of returning an unexplained snippet. Mirrors
// `coding::guidance::program_explanation`; `__fallback` is the neutral wording
// used for any task without a bespoke explanation yet.
const PROGRAM_EXPLANATIONS = {
  hello_world: {
    en: "The program prints the text `Hello, world!` to standard output and then exits.",
    ru: "Программа выводит текст `Hello, world!` в стандартный вывод и завершается.",
    hi: "प्रोग्राम मानक आउटपुट पर `Hello, world!` टेक्स्ट छापता है और फिर समाप्त हो जाता है।",
    zh: "程序将文本 `Hello, world!` 打印到标准输出,然后退出。",
  },
  count_to_three: {
    en: "The program prints the numbers 1, 2, and 3 — each on its own line — and then exits.",
    ru: "Программа выводит числа 1, 2 и 3 — каждое на отдельной строке — и завершается.",
    hi: "प्रोग्राम संख्याएँ 1, 2 और 3 — हर एक अलग पंक्ति में — छापता है और फिर समाप्त हो जाता है।",
    zh: "程序打印数字 1、2 和 3 —— 每个数字单独一行 —— 然后退出。",
  },
  list_files: {
    en:
      "The program reads the entries of the current directory, keeps only the regular " +
      "files, collects their names into a list, sorts the list alphabetically, and " +
      "prints each name on its own line.",
    ru:
      "Программа читает содержимое текущего каталога, оставляет только обычные файлы, " +
      "собирает их имена в список, сортирует список по алфавиту и печатает каждое имя " +
      "на отдельной строке.",
    hi:
      "प्रोग्राम वर्तमान निर्देशिका की प्रविष्टियाँ पढ़ता है, केवल सामान्य फ़ाइलें रखता है, उनके " +
      "नाम एक सूची में एकत्र करता है, सूची को वर्णानुक्रम में क्रमबद्ध करता है, और हर नाम को " +
      "अलग पंक्ति में छापता है।",
    zh:
      "程序读取当前目录的条目,只保留普通文件,将它们的名称收集到一个列表中," +
      "按字母顺序排序,然后将每个名称打印在单独一行。",
  },
  list_files_arg: {
    en:
      "The program takes the directory path from the first command-line argument " +
      "(falling back to the current directory when none is given), reads that " +
      "directory's entries, keeps only the regular files, sorts their names " +
      "alphabetically, and prints each name on its own line.",
    ru:
      "Программа берёт путь к каталогу из первого аргумента командной строки (если " +
      "аргумент не задан, используется текущий каталог), читает содержимое этого " +
      "каталога, оставляет только обычные файлы, сортирует их имена по алфавиту и " +
      "печатает каждое имя на отдельной строке.",
    hi:
      "प्रोग्राम पहले कमांड-लाइन तर्क से निर्देशिका पथ लेता है (कोई तर्क न होने पर वर्तमान " +
      "निर्देशिका का उपयोग करता है), उस निर्देशिका की प्रविष्टियाँ पढ़ता है, केवल सामान्य " +
      "फ़ाइलें रखता है, उनके नामों को वर्णानुक्रम में क्रमबद्ध करता है, और हर नाम को अलग पंक्ति " +
      "में छापता है।",
    zh:
      "程序从第一个命令行参数获取目录路径(未提供参数时使用当前目录),读取该目录的条目," +
      "只保留普通文件,按字母顺序排序它们的名称,然后将每个名称打印在单独一行。",
  },
  list_files_reverse_sort: {
    en:
      "The program reads the entries of the current directory, keeps only the regular " +
      "files, collects their names into a list, sorts the list in reverse alphabetical " +
      "order, and prints each name on its own line.",
    ru:
      "Программа читает содержимое текущего каталога, оставляет только обычные файлы, " +
      "собирает их имена в список, сортирует список в обратном алфавитном порядке и " +
      "печатает каждое имя на отдельной строке.",
    hi:
      "प्रोग्राम वर्तमान निर्देशिका की प्रविष्टियाँ पढ़ता है, केवल सामान्य फ़ाइलें रखता है, उनके " +
      "नाम एक सूची में एकत्र करता है, सूची को उल्टे वर्णानुक्रम में क्रमबद्ध करता है, और हर नाम " +
      "को अलग पंक्ति में छापता है।",
    zh:
      "程序读取当前目录的条目,只保留普通文件,将它们的名称收集到一个列表中," +
      "按反向字母顺序排序,然后将每个名称打印在单独一行。",
  },
  list_files_arg_reverse_sort: {
    en:
      "The program takes the directory path from the first command-line argument " +
      "(falling back to the current directory when none is given), reads that " +
      "directory's entries, keeps only the regular files, sorts their names in " +
      "reverse alphabetical order, and prints each name on its own line.",
    ru:
      "Программа берёт путь к каталогу из первого аргумента командной строки (если " +
      "аргумент не задан, используется текущий каталог), читает содержимое этого " +
      "каталога, оставляет только обычные файлы, сортирует их имена в обратном " +
      "алфавитном порядке и печатает каждое имя на отдельной строке.",
    hi:
      "प्रोग्राम पहले कमांड-लाइन तर्क से निर्देशिका पथ लेता है (कोई तर्क न होने पर वर्तमान " +
      "निर्देशिका का उपयोग करता है), उस निर्देशिका की प्रविष्टियाँ पढ़ता है, केवल सामान्य " +
      "फ़ाइलें रखता है, उनके नामों को उल्टे वर्णानुक्रम में क्रमबद्ध करता है, और हर नाम को " +
      "अलग पंक्ति में छापता है।",
    zh:
      "程序从第一个命令行参数获取目录路径(未提供参数时使用当前目录),读取该目录的条目," +
      "只保留普通文件,按反向字母顺序排序它们的名称,然后将每个名称打印在单独一行。",
  },
  fizzbuzz: {
    en:
      "The program loops over the numbers 1 to 15. For each number it prints `FizzBuzz` " +
      "when the number is divisible by both 3 and 5, `Fizz` when it is divisible by 3, " +
      "`Buzz` when it is divisible by 5, and otherwise the number itself — each on its " +
      "own line.",
    ru:
      "Программа перебирает числа от 1 до 15. Для каждого числа она печатает `FizzBuzz`, " +
      "если оно делится и на 3, и на 5; `Fizz`, если делится на 3; `Buzz`, если делится " +
      "на 5; иначе само число — каждое на отдельной строке.",
    hi:
      "प्रोग्राम 1 से 15 तक की संख्याओं पर लूप करता है। हर संख्या के लिए वह `FizzBuzz` छापता है " +
      "जब वह 3 और 5 दोनों से विभाज्य हो, `Fizz` जब वह 3 से विभाज्य हो, `Buzz` जब वह 5 से " +
      "विभाज्य हो, अन्यथा स्वयं संख्या — हर एक अलग पंक्ति में।",
    zh:
      "程序遍历数字 1 到 15。对于每个数字,当它同时能被 3 和 5 整除时打印 `FizzBuzz`," +
      "能被 3 整除时打印 `Fizz`,能被 5 整除时打印 `Buzz`,否则打印数字本身 —— 每个单独一行。",
  },
  factorial: {
    en:
      "The program multiplies together the numbers 1 through 5 (1×2×3×4×5), which is the " +
      "factorial of 5, and prints the result, 120.",
    ru:
      "Программа перемножает числа от 1 до 5 (1×2×3×4×5) — это факториал 5 — и печатает " +
      "результат, 120.",
    hi:
      "प्रोग्राम 1 से 5 तक की संख्याओं को आपस में गुणा करता है (1×2×3×4×5), जो 5 का फैक्टोरियल " +
      "है, और परिणाम 120 छापता है।",
    zh: "程序将 1 到 5 的数字相乘(1×2×3×4×5),这就是 5 的阶乘,并打印结果 120。",
  },
  reverse_string: {
    en:
      "The program takes the string `hello`, reverses the order of its characters, and " +
      "prints the result, `olleh`.",
    ru:
      "Программа берёт строку `hello`, переставляет её символы в обратном порядке и " +
      "печатает результат — `olleh`.",
    hi: "प्रोग्राम स्ट्रिंग `hello` लेता है, उसके अक्षरों का क्रम उलटता है, और परिणाम `olleh` छापता है।",
    zh: "程序取字符串 `hello`,将其字符顺序反转,并打印结果 `olleh`。",
  },
  sum_to_ten: {
    en:
      "The program adds together the integers from 1 to 10 (1 + 2 + … + 10) and prints " +
      "the total, 55.",
    ru: "Программа складывает целые числа от 1 до 10 (1 + 2 + … + 10) и печатает сумму — 55.",
    hi: "प्रोग्राम 1 से 10 तक के पूर्णांकों को जोड़ता है (1 + 2 + … + 10) और कुल योग 55 छापता है।",
    zh: "程序将 1 到 10 的整数相加(1 + 2 + … + 10),并打印总和 55。",
  },
  fibonacci: {
    en:
      "The program defines a recursive `fibonacci` function (F(1)=F(2)=1, " +
      "F(n)=F(n-1)+F(n-2)) and prints the 10th term, 55.",
    ru: "Программа определяет рекурсивную функцию `fibonacci` (F(1)=F(2)=1, F(n)=F(n-1)+F(n-2)) и печатает 10-й член — 55.",
    hi: "प्रोग्राम एक पुनरावर्ती `fibonacci` फ़ंक्शन परिभाषित करता है (F(1)=F(2)=1, F(n)=F(n-1)+F(n-2)) और 10वाँ पद 55 छापता है।",
    zh: "程序定义了一个递归的 `fibonacci` 函数(F(1)=F(2)=1,F(n)=F(n-1)+F(n-2)),并打印第 10 项 55。",
  },
  __fallback: {
    en: "The program performs the requested task and prints its result to standard output.",
    ru: "Программа выполняет запрошенную задачу и печатает результат в стандартный вывод.",
    hi: "प्रोग्राम अनुरोधित कार्य करता है और परिणाम को मानक आउटपुट पर छापता है।",
    zh: "程序执行所请求的任务,并将结果打印到标准输出。",
  },
};

function programExplanation(task, language) {
  const byTask = PROGRAM_EXPLANATIONS[task] || PROGRAM_EXPLANATIONS.__fallback;
  return byTask[language] || byTask.en;
}

function programExplanationSection(task, language) {
  const heading =
    { ru: "Как это работает:", hi: "यह कैसे काम करता है:", zh: "工作原理:" }[language] ||
    "How it works:";
  return `${heading}\n${programExplanation(task, language)}`;
}

// Issue #330 (R9): did an earlier assistant turn already present a fenced code
// block? When it did, follow-up code edits omit the verbose setup steps and show
// a concise "test it the same way" note instead. Mirrors
// `coding::guidance::history_has_prior_code`.
function historyHasPriorCode(history) {
  return (Array.isArray(history) ? history : []).some(
    (turn) =>
      turn &&
      String(turn.role || "").toLowerCase() === "assistant" &&
      String(turn.content || "").includes("```"),
  );
}

// Issue #330 (R9): step-by-step, novice-friendly instructions for testing the
// program, localized for every response language. When the dialog already
// walked the user through running code, the verbose setup is replaced by a
// short "test it the same way" note. Mirrors
// `coding::guidance::program_test_instructions`.
function programTestInstructions(languageInfo, language, priorCodeResponse) {
  const saveAs = languageInfo.saveAs;
  const runCommand = languageInfo.runCommand;
  const checkCommand = languageInfo.checkCommand;

  if (priorCodeResponse) {
    return (
      {
        ru:
          `Проверьте обновлённую программу так же, как и раньше: сохраните код в файл ` +
          `\`${saveAs}\` и снова выполните \`${runCommand}\`.`,
        hi:
          `अपडेट किए गए प्रोग्राम को पहले की तरह ही जाँचें: कोड को \`${saveAs}\` फ़ाइल में सहेजें ` +
          `और फिर से \`${runCommand}\` चलाएँ।`,
        zh:
          `像之前一样测试更新后的程序:将代码保存到文件 \`${saveAs}\`,然后再次运行 ` +
          `\`${runCommand}\`。`,
      }[language] ||
      `Test the updated program the same way as before: save the code to \`${saveAs}\` ` +
        `and run \`${runCommand}\` again.`
    );
  }

  const heading =
    {
      ru: "Как проверить это самостоятельно:",
      hi: "इसे स्वयं कैसे जाँचें:",
      zh: "如何自行测试:",
    }[language] || "How to test it yourself:";

  const setupHint = languageInfo.setupHint;
  const steps = [];
  steps.push(
    {
      ru: `Установите инструментарий: ${setupHint}.`,
      hi: `टूलचेन इंस्टॉल करें: ${setupHint}।`,
      zh: `安装工具链:${setupHint}。`,
    }[language] || `Install ${setupHint}.`,
  );
  steps.push(
    {
      ru: `Сохраните приведённый выше код в файл \`${saveAs}\`.`,
      hi: `ऊपर दिए गए कोड को \`${saveAs}\` फ़ाइल में सहेजें।`,
      zh: `将上面的代码保存到文件 \`${saveAs}\`。`,
    }[language] || `Save the code above to a file named \`${saveAs}\`.`,
  );
  if (checkCommand) {
    steps.push(
      {
        ru: `Проверьте, что код компилируется: \`${checkCommand}\`.`,
        hi: `जाँचें कि कोड संकलित होता है: \`${checkCommand}\`।`,
        zh: `检查代码能否编译:\`${checkCommand}\`。`,
      }[language] || `Check that it compiles: \`${checkCommand}\`.`,
    );
  }
  steps.push(
    {
      ru: `Запустите программу: \`${runCommand}\`.`,
      hi: `प्रोग्राम चलाएँ: \`${runCommand}\`।`,
      zh: `运行程序:\`${runCommand}\`。`,
    }[language] || `Run it: \`${runCommand}\`.`,
  );
  steps.push(
    {
      ru: "Сравните вывод с разделом ожидаемого вывода выше.",
      hi: "आउटपुट की तुलना ऊपर दिए गए अपेक्षित आउटपुट से करें।",
      zh: "将输出与上面的预期输出部分进行比较。",
    }[language] || "Compare the output with the expected output shown above.",
  );

  const numbered = steps.map((step, index) => `${index + 1}. ${step}`).join("\n");
  return `${heading}\n${numbered}`;
}

// ---------------------------------------------------------------------------
// Issue #340 (R7): composite-program *blueprints*. A `write_program` request can
// name a language we support but a *task* the verified template catalog cannot
// resolve to a single, sandbox-runnable program — e.g. "make an HTTP GET, parse
// the JSON, compute the mean and median". Before this, such a request fell
// through to `write_program_unsupported` (a dead end). A blueprint closes that
// gap while staying honest: it decomposes the prompt into recognized
// capabilities, matches a curated recipe, and returns the full program with its
// decomposition plan, library prerequisites, and an honest "not run" report
// (these programs need external libraries / network access the sandbox cannot
// provide, so they can never claim "compiled and ran").
//
// This is a binary-matching mirror of `src/coding/blueprint.rs`; the parity
// experiment (`experiments/issue-340-worker-parity.mjs`) keeps the two copies in
// lockstep.

// A recognized programming capability — one "sub-task" a composite request can
// decompose into. Detection is keyword-based and script-aware, mirroring
// `CAPABILITIES` in `src/coding/blueprint.rs`.
const BLUEPRINT_CAPABILITIES = [
  {
    slug: "http_request",
    label: "Make an HTTP request",
    keywords: [
      "http",
      "https",
      "url",
      "get request",
      "http get",
      "fetch",
      "download",
      "запрос",
      "ссылк",
      "загруз",
      "स्थानांतरण",
      "अनुरोध",
      "请求",
      "下载",
      "网址",
    ],
  },
  {
    slug: "json_parse",
    label: "Parse the JSON response",
    keywords: [
      "json",
      "parse",
      "parses",
      "parsing",
      "deserialize",
      "разбор",
      "разобрать",
      "парсинг",
      "जेसन",
      "पार्स",
      "解析",
    ],
  },
  {
    slug: "statistics",
    label: "Calculate statistics (mean, median)",
    keywords: [
      "statistics",
      "statistic",
      "mean",
      "average",
      "median",
      "статистик",
      "среднее",
      "медиан",
      "औसत",
      "माध्यिका",
      "सांख्यिकी",
      "统计",
      "平均",
      "中位数",
    ],
  },
  {
    slug: "output_results",
    label: "Output the results",
    keywords: [
      "output",
      "print",
      "outputs",
      "display",
      "report",
      "вывод",
      "вывести",
      "печат",
      "आउटपुट",
      "छाप",
      "输出",
      "打印",
      "显示",
    ],
  },
  {
    slug: "error_handling",
    label: "Handle errors",
    keywords: [
      "error handling",
      "error-handling",
      "errors",
      "error",
      "exception",
      "ошибк",
      "обработк",
      "त्रुटि",
      "错误",
      "异常",
    ],
  },
  {
    slug: "comments",
    label: "Document the code with comments",
    keywords: [
      "comments",
      "comment",
      "commented",
      "documented",
      "комментар",
      "टिप्पणि",
      "注释",
      "评论",
    ],
  },
  {
    slug: "web_research",
    label: "Research current source data",
    keywords: [
      "search",
      "research",
      "sources",
      "source",
      "look up",
      "current",
      "average",
      "поиск",
      "источник",
      "источники",
      "искать",
      "खोज",
      "स्रोत",
      "वर्तमान",
      "搜索",
      "来源",
    ],
  },
  {
    slug: "city_costs",
    label: "Compare city living costs",
    keywords: [
      "living costs",
      "cost of living",
      "average rent",
      "rent",
      "moscow",
      "berlin",
      "new york",
      "city",
      "cities",
      "аренда",
      "стоимость жизни",
      "москва",
      "берлин",
      "нью-йорк",
      "जीवन यापन",
      "लागत",
      "किराया",
      "मास्को",
      "बर्लिन",
      "न्यूयॉर्क",
      "租金",
      "生活成本",
    ],
  },
  {
    slug: "budget_rule",
    label: "Apply the 50/30/20 budget rule",
    keywords: [
      "50/30/20",
      "budget rule",
      "monthly income",
      "income",
      "needs",
      "wants",
      "savings",
      "бюджет",
      "доход",
      "сбереж",
      "बजट",
      "आय",
      "बचत",
      "预算",
      "收入",
    ],
  },
  {
    slug: "compound_savings",
    label: "Project compound savings",
    keywords: [
      "annual return",
      "return",
      "8%",
      "10 years",
      "$3000",
      "100,000",
      "100000",
      "years to save",
      "накопить",
      "доходность",
      "वार्षिक रिटर्न",
      "रिटर्न",
      "साल",
      "收益",
      "年",
    ],
  },
  {
    slug: "markdown_report",
    label: "Export a Markdown comparison report",
    keywords: [
      "markdown",
      "formatted markdown",
      "report",
      "comparison table",
      "table",
      "export",
      "отчет",
      "отчёт",
      "таблица",
      "экспорт",
      "मार्कडाउन",
      "रिपोर्ट",
      "तालिका",
      "निर्यात",
      "报告",
      "表格",
      "导出",
    ],
  },
];

// Curated programs (verbatim copies of the Rust raw-string consts). They are
// hand-written and reviewed, not sandbox-executed (they need network access /
// external libraries), so the execution report stays honest.
const BLUEPRINT_RUST_HTTP_JSON_STATS = `//! Fetch JSON from a URL and report the mean and median of every number in it.
//!
//! Cargo.toml dependencies:
//!   reqwest = { version = "0.12", features = ["blocking", "json"] }
//!   serde_json = "1"

use std::env;
use std::error::Error;

use serde_json::Value;

/// Recursively collect every numeric value out of a decoded JSON document,
/// regardless of how deeply it is nested inside arrays or objects.
fn collect_numbers(value: &Value, numbers: &mut Vec<f64>) {
    match value {
        Value::Number(number) => {
            if let Some(as_float) = number.as_f64() {
                numbers.push(as_float);
            }
        }
        Value::Array(items) => items.iter().for_each(|item| collect_numbers(item, numbers)),
        Value::Object(map) => map.values().for_each(|item| collect_numbers(item, numbers)),
        _ => {}
    }
}

/// Arithmetic mean of the samples (the caller guarantees a non-empty slice).
fn mean(samples: &[f64]) -> f64 {
    samples.iter().sum::<f64>() / samples.len() as f64
}

/// Median of the samples; averages the two middle values when the count is even.
fn median(samples: &mut [f64]) -> f64 {
    samples.sort_by(|left, right| left.partial_cmp(right).expect("no NaN in input"));
    let middle = samples.len() / 2;
    if samples.len() % 2 == 0 {
        (samples[middle - 1] + samples[middle]) / 2.0
    } else {
        samples[middle]
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    // 1. Read the target URL from the first command-line argument.
    let url = env::args()
        .nth(1)
        .ok_or("usage: stats <url-returning-json>")?;

    // 2. Make the HTTP GET request and parse the JSON body. Both steps can fail,
    //    so \`?\` propagates any network or decoding error up to \`main\`.
    let document: Value = reqwest::blocking::get(&url)?.json()?;

    // 3. Gather every number from the decoded document.
    let mut numbers = Vec::new();
    collect_numbers(&document, &mut numbers);
    // region:error_handling
    // Guard against an empty data set before computing statistics.
    if numbers.is_empty() {
        return Err("the JSON response contained no numbers".into());
    }
    // endregion:error_handling

    // 4. Compute and print the statistics.
    println!("count:  {}", numbers.len());
    println!("mean:   {:.4}", mean(&numbers));
    println!("median: {:.4}", median(&mut numbers));
    Ok(())
}
`;

const BLUEPRINT_PYTHON_HTTP_JSON_STATS = `"""Fetch JSON from a URL and report the mean and median of every number in it.

Dependencies:  pip install requests
"""

import statistics
import sys

import requests


def collect_numbers(value):
    """Recursively collect every int/float out of a decoded JSON value."""
    # bool subclasses int, so skip it explicitly
    if isinstance(value, bool):
        return []
    if isinstance(value, (int, float)):
        return [float(value)]
    if isinstance(value, list):
        return [number for item in value for number in collect_numbers(item)]
    if isinstance(value, dict):
        return [number for item in value.values() for number in collect_numbers(item)]
    return []


def main():
    # 1. Read the target URL from the first command-line argument.
    if len(sys.argv) < 2:
        raise SystemExit("usage: stats.py <url-returning-json>")
    url = sys.argv[1]

    # 2. Make the HTTP GET request and parse the JSON body.
    response = requests.get(url, timeout=30)
    # region:error_handling
    # Turn any non-2xx HTTP status into an exception before decoding.
    response.raise_for_status()
    # endregion:error_handling
    document = response.json()

    # 3. Gather every number from the decoded JSON.
    numbers = collect_numbers(document)
    # region:error_handling
    if not numbers:
        raise SystemExit("the JSON response contained no numbers")
    # endregion:error_handling

    # 4. Compute and print the statistics.
    print(f"count:  {len(numbers)}")
    print(f"mean:   {statistics.mean(numbers):.4f}")
    print(f"median: {statistics.median(numbers):.4f}")


if __name__ == "__main__":
    main()
`;

const BLUEPRINT_JAVASCRIPT_HTTP_JSON_STATS = `// Fetch JSON from a URL and report the mean and median of every number in it.
//
// Requirements: Node.js 18+ (built-in global fetch; no extra packages).

// Recursively collect every finite number out of a decoded JSON value.
function collectNumbers(value) {
  if (typeof value === "number" && Number.isFinite(value)) return [value];
  if (Array.isArray(value)) return value.flatMap(collectNumbers);
  if (value && typeof value === "object") {
    return Object.values(value).flatMap(collectNumbers);
  }
  return [];
}

// Arithmetic mean of the samples (the caller guarantees a non-empty array).
function mean(samples) {
  return samples.reduce((total, sample) => total + sample, 0) / samples.length;
}

// Median of the samples; averages the two middle values for an even count.
function median(samples) {
  const sorted = [...samples].sort((left, right) => left - right);
  const middle = Math.floor(sorted.length / 2);
  return sorted.length % 2 === 0
    ? (sorted[middle - 1] + sorted[middle]) / 2
    : sorted[middle];
}

async function main() {
  // 1. Read the target URL from the first command-line argument.
  const url = process.argv[2];
  if (!url) throw new Error("usage: node stats.js <url-returning-json>");

  // 2. Make the HTTP GET request and parse the JSON body.
  const response = await fetch(url);
  // region:error_handling
  // Fail fast on a non-2xx status before we try to decode the body.
  if (!response.ok) {
    throw new Error(\`HTTP \${response.status} \${response.statusText}\`);
  }
  // endregion:error_handling
  const document = await response.json();

  // 3. Gather every number from the decoded JSON.
  const numbers = collectNumbers(document);
  // region:error_handling
  if (numbers.length === 0) {
    throw new Error("the JSON response contained no numbers");
  }
  // endregion:error_handling

  // 4. Compute and print the statistics.
  console.log(\`count:  \${numbers.length}\`);
  console.log(\`mean:   \${mean(numbers).toFixed(4)}\`);
  console.log(\`median: \${median(numbers).toFixed(4)}\`);
}

main().catch((error) => {
  console.error(error.message);
  process.exitCode = 1;
});
`;

const BLUEPRINT_PYTHON_PERSONAL_BUDGET_REPORT = `from dataclasses import dataclass
from math import log
from pathlib import Path


@dataclass(frozen=True)
class CityCost:
    city: str
    average_rent: float
    living_cost_ex_rent: float
    source: str


CITY_COSTS = [
    CityCost('Moscow', 950.0, 850.0, 'https://www.numbeo.com/cost-of-living/in/Moscow'),
    CityCost('Berlin', 1550.0, 1250.0, 'https://www.numbeo.com/cost-of-living/in/Berlin'),
    CityCost('New York', 3600.0, 1850.0, 'https://www.numbeo.com/cost-of-living/in/New-York'),
]
ANNUAL_RETURN = 0.08
GOAL = 100_000.0


def budget_50_30_20(monthly_income):
    return {
        'needs': monthly_income * 0.50,
        'wants': monthly_income * 0.30,
        'savings': monthly_income * 0.20,
    }


def future_value(monthly_contribution, annual_return, years):
    monthly_rate = annual_return / 12
    months = years * 12
    return monthly_contribution * (((1 + monthly_rate) ** months - 1) / monthly_rate)


def years_to_goal(monthly_savings, goal=GOAL, annual_return=ANNUAL_RETURN):
    if monthly_savings <= 0:
        return None
    monthly_rate = annual_return / 12
    months = log(1 + goal * monthly_rate / monthly_savings) / log(1 + monthly_rate)
    return months / 12


def money(value):
    return f'$\{value:,.0f}'


def years(value):
    return 'not reachable' if value is None else f'\{value:.1f}'


def comparison_rows(monthly_income):
    plan = budget_50_30_20(monthly_income)
    rows = []
    for cost in CITY_COSTS:
        expenses = cost.average_rent + cost.living_cost_ex_rent
        remaining = monthly_income - expenses
        monthly_savings = max(0.0, min(plan['savings'], remaining))
        rows.append({
            'city': cost.city,
            'rent': cost.average_rent,
            'remaining': remaining,
            'monthly_savings': monthly_savings,
            'years_to_100k': years_to_goal(monthly_savings),
            'source': cost.source,
        })
    return rows


def render_markdown(monthly_income):
    plan = budget_50_30_20(monthly_income)
    scenario_savings = 3000.0 * 0.20
    scenario_future = future_value(scenario_savings, ANNUAL_RETURN, 10)
    lines = [
        '# Budget Calculator Report',
        '',
        '## 50/30/20 Budget',
        f'- Monthly income: \{money(monthly_income)}',
        f'- Needs (50%): \{money(plan["needs"])}',
        f'- Wants (30%): \{money(plan["wants"])}',
        f'- Savings (20%): \{money(plan["savings"])}',
        '',
        '## Investment Scenario',
        f'- 20% of $3000 monthly: \{money(scenario_savings)}',
        f'- Future value after 10 years at 8% annual return: \{money(scenario_future)}',
        '',
        '## City Comparison',
        '| City | Average rent | Remaining budget after expenses | Years to save $100,000 |',
        '| --- | ---: | ---: | ---: |',
    ]
    for row in comparison_rows(monthly_income):
        lines.append(
            f'| \{row["city"]} | \{money(row["rent"])} | '
            f'\{money(row["remaining"])} | \{years(row["years_to_100k"])} |'
        )
    lines.extend(['', '## Sources'])
    for cost in CITY_COSTS:
        lines.append(f'- \{cost.city}: \{cost.source}')
    lines.append('')
    lines.append('Review and update the city-cost values after checking the source pages.')
    return '\\n'.join(lines)


def read_income():
    try:
        raw = input('Monthly income in USD [3000]: ').strip()
    except EOFError:
        raw = ''
    return float(raw or '3000')


def main():
    report = render_markdown(read_income())
    Path('budget_report.md').write_text(report, encoding='utf-8')
    print(report)
    print('\\nMarkdown report written to budget_report.md')


if __name__ == '__main__':
    main()
`;

// Curated composite recipes. Mirrors `RECIPES` in `src/coding/blueprint.rs`.
const BLUEPRINT_RECIPES = [
  {
    slug: "http_json_stats",
    label: "fetch JSON over HTTP and report the mean and median of its numbers",
    requiredCapabilities: ["http_request", "json_parse", "statistics"],
    programs: [
      {
        languageSlug: "rust",
        libraries: ["reqwest (blocking, json)", "serde_json"],
        runCommand: "cargo run -- <url-returning-json>",
        execution: "external_libraries_and_network",
        code: BLUEPRINT_RUST_HTTP_JSON_STATS,
      },
      {
        languageSlug: "python",
        libraries: ["requests"],
        runCommand: "python stats.py <url-returning-json>",
        execution: "external_libraries_and_network",
        code: BLUEPRINT_PYTHON_HTTP_JSON_STATS,
      },
      {
        languageSlug: "javascript",
        libraries: ["Node.js 18+ (built-in global fetch; no extra packages)"],
        runCommand: "node stats.js <url-returning-json>",
        execution: "external_libraries_and_network",
        code: BLUEPRINT_JAVASCRIPT_HTTP_JSON_STATS,
      },
    ],
  },
  {
    slug: "personal_budget_report",
    label: "build a sourced 50/30/20 city budget calculator and Markdown report",
    requiredCapabilities: [
      "web_research",
      "city_costs",
      "budget_rule",
      "compound_savings",
      "markdown_report",
    ],
    programs: [
      {
        languageSlug: "python",
        libraries: ["Python 3 standard library only"],
        runCommand: "python budget_report.py",
        execution: "review_data_assumptions",
        code: BLUEPRINT_PYTHON_PERSONAL_BUDGET_REPORT,
      },
    ],
  },
];

// Mirror of `contains_keyword` in `src/coding/blueprint.rs`: CJK keywords match
// by substring; multi-word phrases match by substring; single words match on
// token boundaries, allowing a stem prefix when len >= 4.
function blueprintContainsKeyword(normalized, keyword) {
  if (containsCjk(keyword)) return normalized.includes(keyword);
  if (keyword.includes(" ")) return normalized.includes(keyword);
  return normalized
    .split(/[^\p{L}\p{N}\p{M}]+/u)
    .some(
      (token) =>
        token === keyword || (keyword.length >= 4 && token.startsWith(keyword)),
    );
}

// Detect which capabilities a normalized prompt requests, in catalog order so
// the decomposition plan reads top-to-bottom. Mirrors `detect_capabilities`.
function detectBlueprintCapabilities(normalized) {
  return BLUEPRINT_CAPABILITIES.filter((capability) =>
    capability.keywords.some((keyword) =>
      blueprintContainsKeyword(normalized, keyword),
    ),
  );
}

// Resolve a blueprint: the first recipe whose required capabilities are all
// present and that has a program for `languageSlug`. Mirrors `select_blueprint`.
function selectBlueprint(normalized, languageSlug) {
  const detected = detectBlueprintCapabilities(normalized);
  const detectedSlugs = detected.map((capability) => capability.slug);
  const recipe = BLUEPRINT_RECIPES.find(
    (candidate) =>
      candidate.requiredCapabilities.every((required) =>
        detectedSlugs.includes(required),
      ) &&
      candidate.programs.some((program) => program.languageSlug === languageSlug),
  );
  if (!recipe) return null;
  const program = recipe.programs.find(
    (candidate) => candidate.languageSlug === languageSlug,
  );
  if (!program) return null;
  return { recipe, program, capabilities: detected };
}

// Localized framing strings for the blueprint render. Binary-matching mirror of
// the `blueprint_intro`/`capability_label`/`libraries_heading`/
// `blueprint_execution_report`/`recipe_summary`/`how_to_run_heading` functions
// in `src/coding/blueprint.rs`. `en` is the fallback.
const BLUEPRINT_I18N = {
  en: {
    intro: (name, label) =>
      `Here is a ${name} program for the requested composite task (${label}). I decomposed your request into these sub-tasks:`,
    librariesHeading: "Required libraries:",
    howToRunHeading: "How to run it yourself:",
    executionReport: (runCommand, execution) =>
      execution === "review_data_assumptions"
        ? `Execution status: not run — this report blueprint was not executed in the offline sandbox, and the city-cost assumptions should be reviewed against the listed sources before use. The code is provided for review. Run it yourself: \`${runCommand}\`.`
        : `Execution status: not run — this program needs external libraries and network access, so the offline sandbox does not execute it. The code is provided for review. Run it yourself: \`${runCommand}\`.`,
  },
  ru: {
    intro: (name, label) =>
      `Вот программа на языке ${name}, которая решает составную задачу (${label}). Я разбил ваш запрос на следующие подзадачи:`,
    librariesHeading: "Необходимые библиотеки:",
    howToRunHeading: "Как запустить самостоятельно:",
    executionReport: (runCommand, execution) =>
      execution === "review_data_assumptions"
        ? `Статус выполнения: не запускалось — этот отчёт не выполнялся в офлайн-песочнице, а допущения о стоимости жизни нужно сверить с указанными источниками. Код приведён для проверки. Запустить самостоятельно: \`${runCommand}\`.`
        : `Статус выполнения: не запускалось — программе нужны внешние библиотеки и доступ к сети, поэтому офлайн-песочница её не выполняет. Код приведён для проверки. Запустить самостоятельно: \`${runCommand}\`.`,
  },
  hi: {
    intro: (name, label) =>
      `यहाँ ${name} में एक प्रोग्राम है जो इस संयुक्त कार्य को हल करता है (${label})। मैंने आपके अनुरोध को इन उप-कार्यों में विभाजित किया है:`,
    librariesHeading: "आवश्यक लाइब्रेरियाँ:",
    howToRunHeading: "इसे स्वयं कैसे चलाएँ:",
    executionReport: (runCommand, execution) =>
      execution === "review_data_assumptions"
        ? `निष्पादन स्थिति: नहीं चलाया गया — यह रिपोर्ट ऑफ़लाइन सैंडबॉक्स में नहीं चली, और शहर-लागत मानों को दिए गए स्रोतों से जाँचना चाहिए। कोड समीक्षा के लिए दिया गया है। स्वयं चलाएँ: \`${runCommand}\`।`
        : `निष्पादन स्थिति: नहीं चलाया गया — प्रोग्राम को बाहरी लाइब्रेरियों और नेटवर्क पहुँच की आवश्यकता है, इसलिए ऑफ़लाइन सैंडबॉक्स इसे नहीं चलाता। कोड समीक्षा के लिए दिया गया है। स्वयं चलाएँ: \`${runCommand}\`।`,
  },
  zh: {
    intro: (name, label) =>
      `这是一个解决该复合任务的 ${name} 程序(${label})。我已将您的请求分解为以下子任务:`,
    librariesHeading: "所需的库:",
    howToRunHeading: "如何自行运行:",
    executionReport: (runCommand, execution) =>
      execution === "review_data_assumptions"
        ? `执行状态:未运行 —— 该报告未在离线沙箱中执行,城市成本假设应先按列出的来源核对。代码仅供审阅。自行运行:\`${runCommand}\`。`
        : `执行状态:未运行 —— 该程序需要外部库和网络访问,因此离线沙箱不会执行它。代码仅供审阅。自行运行:\`${runCommand}\`。`,
  },
};

// Localized capability labels keyed by `${slug}:${language}`; English falls back
// to the capability's own `label`. Mirrors `capability_label`.
const BLUEPRINT_CAPABILITY_LABELS = {
  "http_request:ru": "Выполнить HTTP-запрос",
  "http_request:hi": "HTTP अनुरोध करें",
  "http_request:zh": "发起 HTTP 请求",
  "json_parse:ru": "Разобрать JSON-ответ",
  "json_parse:hi": "JSON प्रतिक्रिया पार्स करें",
  "json_parse:zh": "解析 JSON 响应",
  "statistics:ru": "Вычислить статистику (среднее, медиана)",
  "statistics:hi": "सांख्यिकी (औसत, माध्यिका) की गणना करें",
  "statistics:zh": "计算统计量(平均值、中位数)",
  "output_results:ru": "Вывести результаты",
  "output_results:hi": "परिणाम आउटपुट करें",
  "output_results:zh": "输出结果",
  "error_handling:ru": "Обработать ошибки",
  "error_handling:hi": "त्रुटियाँ संभालें",
  "error_handling:zh": "处理错误",
  "comments:ru": "Снабдить код комментариями",
  "comments:hi": "कोड में टिप्पणियाँ जोड़ें",
  "comments:zh": "为代码添加注释",
  "web_research:ru": "Найти актуальные исходные данные",
  "web_research:hi": "वर्तमान स्रोत डेटा खोजें",
  "web_research:zh": "检索当前来源数据",
  "city_costs:ru": "Сравнить стоимость жизни по городам",
  "city_costs:hi": "शहरों की जीवन-यापन लागत की तुलना करें",
  "city_costs:zh": "比较城市生活成本",
  "budget_rule:ru": "Применить правило бюджета 50/30/20",
  "budget_rule:hi": "50/30/20 बजट नियम लागू करें",
  "budget_rule:zh": "应用 50/30/20 预算规则",
  "compound_savings:ru": "Рассчитать накопления со сложным процентом",
  "compound_savings:hi": "चक्रवृद्धि बचत का अनुमान लगाएँ",
  "compound_savings:zh": "预测复利储蓄",
  "markdown_report:ru": "Экспортировать Markdown-отчёт со сравнением",
  "markdown_report:hi": "Markdown तुलना रिपोर्ट निर्यात करें",
  "markdown_report:zh": "导出 Markdown 比较报告",
};

// Localized one-line recipe summaries keyed by `${slug}:${language}`; English
// falls back to the recipe's own `label`. Mirrors `recipe_summary`.
const BLUEPRINT_RECIPE_SUMMARIES = {
  "http_json_stats:ru": "загрузить JSON по HTTP и вывести среднее и медиану его чисел",
  "http_json_stats:hi":
    "HTTP के माध्यम से JSON प्राप्त करें और उसकी संख्याओं का औसत और माध्यिका दिखाएँ",
  "http_json_stats:zh": "通过 HTTP 获取 JSON 并报告其中数字的平均值和中位数",
  "personal_budget_report:ru":
    "собрать бюджетный калькулятор 50/30/20 с городскими расходами, источниками и Markdown-отчётом",
  "personal_budget_report:hi":
    "स्रोतों सहित 50/30/20 शहर बजट कैलकुलेटर और Markdown रिपोर्ट बनाएँ",
  "personal_budget_report:zh":
    "生成带来源的 50/30/20 城市预算计算器和 Markdown 报告",
};

// The line-comment marker for a program language. Mirrors `comment_marker` in
// `src/coding/blueprint.rs`: hash-comment languages use `#`, everything else
// uses `//` (which also covers Rust's `//!`/`///` doc lines).
function blueprintCommentMarker(languageSlug) {
  return languageSlug === "python" || languageSlug === "ruby" ? "#" : "//";
}

// Region directive prefixes. Mirrors `REGION_OPEN`/`REGION_CLOSE` in
// `src/coding/blueprint.rs`.
const BLUEPRINT_REGION_OPEN = "region:";
const BLUEPRINT_REGION_CLOSE = "endregion:";

// Normalize a composition strategy value to the canonical "composed" (default,
// the most promising direction) or "documented". Mirrors
// `BlueprintComposition::from_value`/`default` in `src/solver.rs`.
function normalizeBlueprintComposition(value) {
  switch (String(value || "").trim().toLowerCase()) {
    case "documented":
    case "document":
    case "full":
    case "verbatim":
    case "curated":
      return "documented";
    default:
      return "composed";
  }
}

// If `trimmed` (leading whitespace already removed) is a region directive
// comment, return `{ open, slug }`; otherwise null. Mirrors `region_directive`
// in `src/coding/blueprint.rs`.
function blueprintRegionDirective(trimmed, marker) {
  if (!trimmed.startsWith(marker)) return null;
  const rest = trimmed.slice(marker.length).replace(/^\s+/, "");
  if (rest.startsWith(BLUEPRINT_REGION_CLOSE)) {
    return { open: false, slug: rest.slice(BLUEPRINT_REGION_CLOSE.length).trim() };
  }
  if (rest.startsWith(BLUEPRINT_REGION_OPEN)) {
    return { open: true, slug: rest.slice(BLUEPRINT_REGION_OPEN.length).trim() };
  }
  return null;
}

// Compose the program a blueprint emits from its annotated recipe template.
// Byte-for-byte mirror of `compose_program` in `src/coding/blueprint.rs`: drop
// every region directive line, and in the "composed" strategy drop the body of
// any region whose capability the request did not name and strip whole-line
// documentation when comments were not requested. The "documented" strategy
// keeps every region and comment (only the internal directive lines go).
function composeBlueprintProgram(blueprint, strategy) {
  const languageSlug = blueprint.program.languageSlug;
  const marker = blueprintCommentMarker(languageSlug);
  const compose = strategy !== "documented";
  const requested = (slug) =>
    blueprint.capabilities.some((capability) => capability.slug === slug);

  // Pass 1 — regions: drop every directive line, and when composing drop the
  // body of any region whose capability was not requested.
  const kept = [];
  let skipping = false;
  for (const line of blueprint.program.code.split("\n")) {
    const trimmed = line.replace(/^\s+/, "");
    const directive = blueprintRegionDirective(trimmed, marker);
    if (directive) {
      skipping = directive.open && compose && !requested(directive.slug);
      continue;
    }
    if (!skipping) kept.push(line);
  }

  // Pass 2 — comments: strip documentation when composing a request that did
  // not ask for it; otherwise keep the comments and just tidy blank runs.
  if (compose && !blueprintWantsComments(blueprint)) {
    return stripBlueprintCommentLines(kept, languageSlug);
  }
  return collapseBlueprintBlankRuns(kept);
}

// Remove the documentation from already region-filtered lines when the request
// did not ask for comments. Mirrors `strip_comment_lines` in
// `src/coding/blueprint.rs`: only whole-line comments and a leading Python
// module docstring are dropped (both non-semantic, so the stripped program
// stays compilable), and inline trailing comments are left untouched so a
// `//`/`#` inside a string literal is never sliced.
function stripBlueprintCommentLines(lines, languageSlug) {
  const marker = blueprintCommentMarker(languageSlug);
  const kept = [];
  let inDocstring = false;
  for (const line of lines) {
    const trimmed = line.replace(/^\s+/, "");
    if (languageSlug === "python") {
      if (inDocstring) {
        if (trimmed.includes('"""')) inDocstring = false;
        continue;
      }
      if (trimmed.startsWith('"""')) {
        const rest = trimmed.slice(3);
        if (!rest.includes('"""')) inDocstring = true;
        continue;
      }
    }
    if (trimmed.startsWith(marker)) continue;
    kept.push(line);
  }
  return collapseBlueprintBlankRuns(kept);
}

// Join kept lines, dropping leading blanks and collapsing runs of two or more
// blank lines (left after removing comment blocks) into one. Mirrors
// `collapse_blank_runs` in `src/coding/blueprint.rs`.
function collapseBlueprintBlankRuns(lines) {
  const out = [];
  let pendingBlank = false;
  let wroteAny = false;
  for (const line of lines) {
    if (line.trim() === "") {
      if (wroteAny) pendingBlank = true;
      continue;
    }
    if (pendingBlank) {
      out.push("");
      pendingBlank = false;
    }
    out.push(line);
    wroteAny = true;
  }
  return out.join("\n");
}

// Whether the decomposed request asked for the code to be commented. Mirrors
// `wants_comments` in `src/coding/blueprint.rs`.
function blueprintWantsComments(blueprint) {
  return blueprint.capabilities.some(
    (capability) => capability.slug === "comments",
  );
}

function blueprintCapabilityLabel(capability, language) {
  return (
    BLUEPRINT_CAPABILITY_LABELS[`${capability.slug}:${language}`] ||
    capability.label
  );
}

function blueprintRecipeSummary(recipe, language) {
  return BLUEPRINT_RECIPE_SUMMARIES[`${recipe.slug}:${language}`] || recipe.label;
}

// Render the complete localized blueprint answer — decomposition plan, the
// curated program, its library prerequisites, and the honest execution report.
// Byte-for-byte mirror of `render` in `src/coding/blueprint.rs`. `composition`
// selects which projection of the recipe template to emit (default "composed").
function renderBlueprint(blueprint, language, composition) {
  const strings = BLUEPRINT_I18N[language] || BLUEPRINT_I18N.en;
  const languageInfo = WRITE_PROGRAM_LANGUAGES[blueprint.program.languageSlug];
  const name = languageInfo ? languageInfo.name : blueprint.program.languageSlug;
  const fence = languageInfo ? languageInfo.fence : blueprint.program.languageSlug;
  const summary = blueprintRecipeSummary(blueprint.recipe, language);

  let body = strings.intro(name, summary);
  body += "\n\n";
  blueprint.capabilities.forEach((capability, index) => {
    body += `${index + 1}. ${blueprintCapabilityLabel(capability, language)}\n`;
  });
  // Compose the program from the decomposition: filter optional capability
  // regions and comments according to `composition` (see
  // `composeBlueprintProgram`) so the blueprint is an honest projection of the
  // detected capabilities rather than a single frozen string.
  const programCode = composeBlueprintProgram(
    blueprint,
    normalizeBlueprintComposition(composition),
  );
  body += `\n\`\`\`${fence}\n${programCode}\n\`\`\`\n\n${strings.librariesHeading}\n`;
  for (const library of blueprint.program.libraries) {
    body += `- ${library}\n`;
  }
  body += `\n${strings.howToRunHeading}\n\n${strings.executionReport(
    blueprint.program.runCommand,
    blueprint.program.execution,
  )}`;
  return body;
}

// Build the `write_program` answer for a resolved blueprint. The evidence trail
// mirrors the Rust handler's event log (`src/solver_handlers/program_blueprint.rs`):
// the recipe, the decomposed capabilities, the (language, task) parameters, and
// an honest "unavailable" execution status.
function blueprintWriteProgramAnswer(
  blueprint,
  languageSlug,
  responseLanguage,
  composition,
) {
  const mode = normalizeBlueprintComposition(composition);
  const content = renderBlueprint(blueprint, responseLanguage || "en", mode);
  return {
    intent: "write_program",
    content,
    confidence: 0.7,
    evidence: [
      `response:write_program:blueprint:${blueprint.recipe.slug}:${languageSlug}`,
      `program_parameter:language:${languageSlug}`,
      `program_parameter:task:blueprint:${blueprint.recipe.slug}`,
      `program_blueprint:recipe:${blueprint.recipe.slug}`,
      `program_blueprint:composition:${mode}`,
      ...blueprint.capabilities.map(
        (capability) => `program_blueprint:capability:${capability.slug}`,
      ),
      `execution_status:${languageSlug}:unavailable`,
    ],
  };
}

function writeProgramDecompositionParts(modifier) {
  if (modifier === "reverse_sort") {
    return {
      operation: "sort",
      operationModifier: "descending",
      target: "program:last.output_order",
      targetKind: "program_output",
    };
  }
  if (modifier === "cancel_reverse_sort") {
    // Issue #386: the inverse of reverse_sort — cancel the descending order
    // over the same program-output target.
    return {
      operation: "cancel",
      operationModifier: "reverse_sort",
      target: "program:last.output_order",
      targetKind: "program_output",
    };
  }
  if (modifier === "path_argument") {
    return {
      operation: "accept",
      operationModifier: "path_argument",
      target: "program:last.input",
      targetKind: "program_input",
    };
  }
  return {
    operation: "modify",
    operationModifier: null,
    target: "program:last",
    targetKind: "program_artifact",
  };
}

function writeProgramPrimaryModifier(modifiers) {
  if (!Array.isArray(modifiers) || modifiers.length === 0) return null;
  return modifiers.includes("reverse_sort") ? "reverse_sort" : modifiers[0];
}

function writeProgramCandidateRuleId(plan, modifier) {
  if (!plan || !modifier) return "";
  const traces = Array.isArray(plan.traces) ? plan.traces : [];
  for (let index = traces.length - 1; index >= 0; index -= 1) {
    const ruleId = String(traces[index].ruleId || "");
    if (ruleId.includes(modifier)) return ruleId;
  }
  return `${modifier}_${plan.baseTask || "program"}`;
}

function writeProgramSynthesisRequest(context, prompt, modifier) {
  const parts = writeProgramDecompositionParts(modifier);
  const lines = ["rule_synthesis_request"];
  lines.push("  issue #359");
  lines.push("  impulse current_turn");
  lines.push("  artifact program:last");
  lines.push(`  artifact_language ${context.language || "missing"}`);
  lines.push(`  base_task ${context.task || "missing"}`);
  lines.push("  bare_imperative true");
  lines.push(`  operation ${parts.operation}`);
  if (parts.operationModifier) {
    lines.push(`  operation_modifier ${parts.operationModifier}`);
  }
  lines.push(`  target ${parts.target}`);
  lines.push(`  target_kind ${parts.targetKind}`);
  lines.push(`  source_text ${prompt}`);
  return lines.join("\n");
}

function writeProgramSynthesisCandidate(candidateId, context, plan, modifier) {
  const parts = writeProgramDecompositionParts(modifier);
  const lines = ["rule_synthesis_candidate"];
  lines.push(`  id ${candidateId}`);
  lines.push("  source constructed_from_operation_vocabulary");
  lines.push(`  base_task ${context.task || "missing"}`);
  lines.push(`  modifier ${modifier}`);
  lines.push(`  operation ${parts.operation}`);
  if (parts.operationModifier) {
    lines.push(`  operation_modifier ${parts.operationModifier}`);
  }
  lines.push(`  target ${parts.target}`);
  lines.push(`  resolved_task ${(plan && plan.resolvedTask) || "missing"}`);
  return lines.join("\n");
}

function templateHasDescendingOrder(code) {
  const compact = String(code || "")
    .toLowerCase()
    .split(/\s+/)
    .join("");
  return [
    "sort_by(|a,b|b.cmp(a))",
    "reverse=true",
    ".sort().reverse()",
    "sort.sort(sort.reverse",
    "compare_desc",
    "rbegin(),names.rend()",
    "comparator.reverseorder()",
    "orderbydescending",
    "sort.reverse",
  ].some((marker) => compact.includes(marker));
}

function writeProgramVerificationTrace(candidateId, plan, template, modifiers) {
  if (!plan || !Array.isArray(modifiers) || modifiers.length === 0) return null;
  const planCheck =
    programPlanWasModified(plan) && Array.isArray(plan.traces) && plan.traces.length > 0;
  // Issue #386: verify the rendered program actually matches the operation. A
  // reverse_sort must leave the output descending; its inverse,
  // cancel_reverse_sort, must leave NO descending order — otherwise the cancel
  // silently failed to remove the sort. Modifiers that touch no ordering pass.
  const cancelsSort = modifiers.includes("cancel_reverse_sort");
  const reversesSort = modifiers.includes("reverse_sort");
  const descending = templateHasDescendingOrder(template);
  const renderCheck = cancelsSort ? !descending : reversesSort ? descending : true;
  const passed = planCheck && renderCheck;
  const expectedOrder = reversesSort && !cancelsSort ? "c.txt,b.txt,a.txt" : "a.txt,b.txt,c.txt";
  return [
    "rule_verification",
    `  candidate ${candidateId}`,
    "  fixture list_files_output_order",
    "  input a.txt,b.txt,c.txt",
    `  expected_order ${expectedOrder}`,
    `  lowering_check ${planCheck ? "passed" : "failed"}`,
    `  render_check ${renderCheck ? "passed" : "failed"}`,
    `  status ${passed ? "passed" : "failed"}`,
  ].join("\n");
}

function writeProgramDiagnosticBundle({
  prompt,
  initiallyDetected,
  coreference,
  detected,
  modifiers,
  lowered,
  plan,
  template,
}) {
  const steps = [];
  const trace = [];
  const coreferenceTrace = coreference && coreference.trace;
  if (!initiallyDetected && coreferenceTrace) {
    const detail = "selected_rule initial unknown reason no_seed_route next try_rule_synthesis";
    steps.push({ step: "route_attempt", detail });
    trace.push(`selected_rule:${detail}`);
  } else {
    const detail = "selected_rule write_program reason seed_route";
    steps.push({ step: "route_attempt", detail });
    trace.push(`selected_rule:${detail}`);
  }

  if (coreferenceTrace) {
    const detail = `write_program_coreference_rewrite\n  ${coreferenceTrace}`;
    steps.push({ step: "coreference_binding", detail });
    trace.push(`write_program_coreference_rewrite:${coreferenceTrace}`);
  }

  const safeModifiers = Array.isArray(modifiers) ? modifiers : [];
  if (safeModifiers.length > 0) {
    const operationHits = safeModifiers.join(",");
    const detail = `rule_synthesis_operation_vocabulary\n  ${operationHits}`;
    steps.push({ step: "modifier_detection", detail });
    trace.push(`rule_synthesis_operation_vocabulary:${operationHits}`);
  }

  const primaryModifier = writeProgramPrimaryModifier(safeModifiers);
  if (primaryModifier && lowered && programPlanWasModified(lowered)) {
    const context = {
      task: (detected && detected.task) || lowered.baseTask || "missing",
      language: (detected && detected.language) || "missing",
    };
    const candidateId = writeProgramCandidateRuleId(lowered, primaryModifier);
    const request = writeProgramSynthesisRequest(context, prompt, primaryModifier);
    const candidate = writeProgramSynthesisCandidate(
      candidateId,
      context,
      lowered,
      primaryModifier,
    );
    const construction = `${request}\n${candidate}`;
    steps.push({ step: "rule_construction", detail: construction });
    trace.push(`rule_synthesis_request:${request}`);
    trace.push(`rule_synthesis_candidate:${candidate}`);

    const verification = writeProgramVerificationTrace(
      candidateId,
      lowered,
      template,
      safeModifiers,
    );
    if (verification) {
      steps.push({ step: "rule_verification", detail: verification });
      trace.push(`rule_verification:${verification}`);
    }
  }

  if (plan) {
    const detail = `write_program_plan\n${plan}`;
    steps.push({ step: "program_plan", detail });
    trace.push(`write_program_plan:${plan}`);
  }

  return { steps, trace };
}

function tryWriteProgram(prompt, history, responseLanguage, composition) {
  let detected = writeProgramParameters(prompt);
  const initiallyDetected = detected;
  const coreference = detected ? null : rewriteBareProgramCoreference(prompt, history);
  if (!detected && !coreference) return null;
  if (coreference) detected = coreference.parameters;
  // Issue #324: recover task/language from the conversation when a follow-up
  // modification names neither (and apply any path-argument modifier).
  const { language, task, plan, modifiers, lowered } = recoverWriteProgramParameters(
    detected,
    prompt,
    history,
  );
  // Issue #324: answer in the language of the request (falls back to en).
  const i18n = writeProgramStrings(responseLanguage);
  const template = language && task ? WRITE_PROGRAM_TEMPLATES[task]?.[language] : null;
  const diagnostics = writeProgramDiagnosticBundle({
    prompt,
    initiallyDetected,
    coreference,
    detected,
    modifiers,
    lowered,
    plan,
    template,
  });
  if (!template) {
    // Issue #340 (R7): before the unsupported dead end, try a composite
    // blueprint. When the request decomposes into a recognized recipe for a
    // language we ship a curated program for, return that program with its plan
    // and an honest "not run" report (mirrors `try_program_blueprint` in
    // `src/solver_handlers/program_blueprint.rs`).
    const normalizedForBlueprint = normalizeProgramPrompt(prompt);
    const blueprintLanguage =
      language || programLanguageFromPrompt(normalizedForBlueprint);
    const blueprint = blueprintLanguage
      ? selectBlueprint(normalizedForBlueprint, blueprintLanguage)
      : null;
    if (blueprint) {
      return blueprintWriteProgramAnswer(
        blueprint,
        blueprintLanguage,
        responseLanguage,
        composition,
      );
    }
    return {
      intent: "write_program_unsupported",
      content: i18n.unsupported(
        language || "missing",
        task || "missing",
        Object.keys(WRITE_PROGRAM_LANGUAGES).join(", "),
        Object.keys(WRITE_PROGRAM_TASKS).join(", "),
      ),
      confidence: 0.4,
      evidence: [
        "response:write_program:unsupported",
        `program_parameter:language:${language || "missing"}`,
        `program_parameter:task:${task || "missing"}`,
      ],
      steps: diagnostics.steps,
      trace: diagnostics.trace,
    };
  }
  const languageInfo = WRITE_PROGRAM_LANGUAGES[language];
  const taskInfo = WRITE_PROGRAM_TASKS[task];
  // The sandbox can only execute self-contained JavaScript; a snippet that pulls
  // in Node APIs (e.g. the list-files `require("fs")`) cannot run here (#312).
  const ranInSandbox =
    language === "javascript" && !/\brequire\s*\(|\bimport\b/.test(template);
  const lines = [];
  lines.push(i18n.intro(languageInfo.name, taskInfo.label));
  lines.push("");
  lines.push("```" + languageInfo.fence);
  lines.push(template);
  lines.push("```");
  lines.push("");
  lines.push(
    ...writeProgramExecutionLines(language, task, template, taskInfo.output, i18n),
  );
  // Issue #330 (R9): teach a novice — append a plain-language explanation of how
  // the code works, then step-by-step instructions for testing it. Follow-up
  // edits (when the dialog already showed code) drop the verbose setup steps.
  const priorCode = historyHasPriorCode(history);
  lines.push("");
  lines.push(programExplanationSection(task, responseLanguage));
  lines.push("");
  lines.push(programTestInstructions(languageInfo, responseLanguage, priorCode));
  return {
    intent: "write_program",
    content: lines.join("\n"),
    confidence: 0.9,
    evidence: [
      `response:write_program:${task}:${language}`,
      `program_parameter:language:${language}`,
      `program_parameter:task:${task}`,
      `program_parameters:write_program(language=${language}:task=${task})`,
      task === "hello_world"
        ? `legacy_intent:hello_world_${language}`
        : `legacy_intent:write_program_${task}_${language}`,
      `execution_status:${language}:${ranInSandbox ? "ran" : "unavailable"}`,
      // Issue #324 R4/R6: surface the substitution plan when a follow-up
      // modification rewrote the task (mirrors the Rust `write_program_plan`
      // event in `src/solver.rs`).
      ...(plan ? [`write_program_plan:${task}`] : []),
      ...(coreference
        ? [`write_program_coreference_rewrite:${task || "missing"}:${language || "missing"}`]
        : []),
    ],
    steps: diagnostics.steps,
    trace: diagnostics.trace.length ? diagnostics.trace : undefined,
  };
}

function tryHistorical(prompt, history) {
  const normalized = normalizePrompt(prompt);
  // Issue #386: a conversation-summary request is recognised by composing
  // meaning roles (see isSummarizePrompt) across every supported language, so
  // we test it before the empty-normalized bail-out below.
  if (isSummarizePrompt(normalized)) {
    return trySummarizeConversation(history);
  }
  if (!normalized) return null;
  if (normalized === "what is my name" || normalized === "what s my name") {
    const hit = tryRecallName(history);
    if (hit) return hit;
  }
  if (
    normalized === "what was my previous question" ||
    normalized === "what was the previous question" ||
    normalized === "what was my last question"
  ) {
    return tryRecallLastQuestion(history);
  }
  return null;
}

// Issue #386 research comparison-table roles — mirror the ROLE_COMPARISON_*
// and ROLE_RESEARCH_* consts in src/seed/roles.rs. The strong trigger, the weak
// table-noun/difference-cue pair, the research-prompt signals (bare markers plus
// prefix surfaces), and the per-column criterion words all live in
// data/seed/meanings-research-table.lino (embedded in MEANINGS_LINO above), so
// the handler references the concepts, not raw words in one language.
const ROLE_COMPARISON_TABLE_TRIGGER = "comparison_table_trigger";
const ROLE_COMPARISON_TABLE_NOUN = "comparison_table_noun";
const ROLE_COMPARISON_DIFFERENCE_CUE = "comparison_difference_cue";
const ROLE_RESEARCH_PROMPT_SIGNAL = "research_prompt_signal";
const ROLE_RESEARCH_CRITERION = "research_criterion";

// True when the prompt asks for a comparison drawn as a table: a strong
// comparison_table_trigger, or the weak pair of a comparison_table_noun and a
// comparison_difference_cue — each token-bounded across every supported
// language. Mirrors is_comparison_table_request in
// src/solver_handlers/research_table.rs.
function isComparisonTableRequest(normalized) {
  return (
    lexiconMentionsRole(ROLE_COMPARISON_TABLE_TRIGGER, normalized) ||
    (lexiconMentionsRole(ROLE_COMPARISON_TABLE_NOUN, normalized) &&
      lexiconMentionsRole(ROLE_COMPARISON_DIFFERENCE_CUE, normalized))
  );
}

// True when `prompt` was itself a research request — the prior turn a
// comparison-table follow-up reuses for its topics. research_prompt_signal
// carries bare markers (matched token-bounded anywhere) and prefix surfaces
// (matched when the prompt opens with the literal before the … slot); both live
// in the seed data. Mirrors looks_like_research_prompt in
// src/solver_handlers/research_table.rs.
function looksLikeResearchPrompt(prompt) {
  const normalized = normalizePrompt(prompt);
  if (lexiconMentionsRole(ROLE_RESEARCH_PROMPT_SIGNAL, normalized)) return true;
  return roleWordForms(ROLE_RESEARCH_PROMPT_SIGNAL)
    .filter((form) => form.slot === "prefix")
    .some((form) => normalized.startsWith(form.before));
}

function stripResearchListMarker(line) {
  const value = String(line || "").trim();
  if (!value) return "";
  if (/^[-*+]\s+/u.test(value)) {
    return value.replace(/^[-*+]\s+/u, "").trim();
  }
  if (/^\d+[.):]\s*/u.test(value)) {
    return value.replace(/^\d+[.):]\s*/u, "").trim();
  }
  return "";
}

function cleanResearchText(value) {
  return String(value || "")
    .trim()
    .replace(/^[`"':;,.?!\s]+/u, "")
    .replace(/[`"':;,.?!\s]+$/u, "")
    .replace(/\s+/g, " ")
    .trim();
}

function extractResearchTopics(prompt) {
  const topics = [];
  for (const line of String(prompt || "").split(/\r?\n/u)) {
    const item = cleanResearchText(stripResearchListMarker(line));
    if (!item || looksLikeResearchPrompt(item)) continue;
    if (!topics.some((topic) => topic.toLowerCase() === item.toLowerCase())) {
      topics.push(item);
    }
    if (topics.length >= 8) break;
  }
  if (topics.length === 0 && String(prompt || "").includes(":")) {
    const item = cleanResearchText(String(prompt).split(":").slice(1).join(":"));
    if (item) topics.push(item);
  }
  return topics;
}

const RESEARCH_TABLE_DEFAULT_CRITERIA = [
  "key_differences",
  "use_cases",
  "advantages",
  "disadvantages",
];

const RESEARCH_TABLE_CRITERION_LABELS = {
  key_differences: "Key differences",
  use_cases: "Use cases",
  advantages: "Advantages",
  disadvantages: "Disadvantages",
};

function pushUniqueCriterion(criteria, criterion) {
  if (!criteria.includes(criterion)) criteria.push(criterion);
}

// Add every comparison column the text names. Walks the research_criterion
// meanings in declaration order (which fixes the column order) and adds a
// criterion when any of its surface words occurs as a raw substring — the same
// substring contract the legacy code used, so space-guarded stems like 'pro '
// and ' con ' still avoid matching inside 'process'/'control'. The trigger words
// live in the seed data; only the language-independent slug keys each column.
// Mirrors append_criteria_from_text in src/solver_handlers/research_table.rs.
function appendResearchCriteriaFromText(text, criteria) {
  const normalized = normalizePrompt(text);
  for (const meaning of meaningsWithRole(ROLE_RESEARCH_CRITERION)) {
    if (
      RESEARCH_TABLE_CRITERION_LABELS[meaning.slug] &&
      meaning.words.some((word) => word && normalized.includes(word))
    ) {
      pushUniqueCriterion(criteria, meaning.slug);
    }
  }
}

function extractResearchCriteria(prompt) {
  const criteria = [];
  for (const line of String(prompt || "").split(/\r?\n/u)) {
    const item = stripResearchListMarker(line);
    if (item) appendResearchCriteriaFromText(item, criteria);
  }
  if (criteria.length === 0) appendResearchCriteriaFromText(prompt, criteria);
  return criteria.length > 0 ? criteria : RESEARCH_TABLE_DEFAULT_CRITERIA.slice();
}

function researchTableCell(topic, criterion) {
  const normalized = normalizePrompt(topic);
  if (normalized.includes("machine learning algorithm")) {
    if (criterion === "key_differences") {
      return "Broad family of data-driven methods; includes supervised, unsupervised, and reinforcement approaches.";
    }
    if (criterion === "use_cases") {
      return "Classification, regression, clustering, recommendation, anomaly detection, and forecasting.";
    }
    if (criterion === "advantages") {
      return "Flexible toolkit; often efficient on structured data; many models are easier to inspect than deep nets.";
    }
    if (criterion === "disadvantages") {
      return "Model choice, preprocessing, and feature design can dominate results; overfitting remains a risk.";
    }
  }
  if (normalized.includes("deep learning") && normalized.includes("traditional ml")) {
    if (criterion === "key_differences") {
      return "Deep learning learns layered representations; traditional ML often relies more on explicit feature engineering.";
    }
    if (criterion === "use_cases") {
      return "Deep learning fits images, speech, and language at scale; traditional ML fits many tabular and smaller-data tasks.";
    }
    if (criterion === "advantages") {
      return "Deep learning scales with data and reduces manual features; traditional ML is usually faster and more interpretable.";
    }
    if (criterion === "disadvantages") {
      return "Deep learning needs more data/compute and is harder to explain; traditional ML may underfit unstructured signals.";
    }
  }
  if (normalized.includes("neural network")) {
    if (criterion === "key_differences") {
      return "Built from weighted layers, activations, losses, and optimization; provides the base mechanism for deep learning.";
    }
    if (criterion === "use_cases") {
      return "Pattern recognition, embeddings, sequence modeling, vision, speech, and nonlinear function approximation.";
    }
    if (criterion === "advantages") {
      return "Captures nonlinear relationships and can be trained end-to-end for complex perception tasks.";
    }
    if (criterion === "disadvantages") {
      return "Requires tuning and regularization; decisions can be opaque; training can be unstable on poor data.";
    }
  }
  if (criterion === "key_differences") {
    return "Use the prior search sources to identify what distinguishes this topic from the others.";
  }
  if (criterion === "use_cases") {
    return "Summarize the practical settings where the Step 1 sources apply this topic.";
  }
  if (criterion === "advantages") {
    return "Extract strengths reported by the prior search sources before treating them as verified.";
  }
  return "Extract limitations reported by the prior search sources before treating them as verified.";
}

function escapeResearchTableCell(value) {
  return String(value || "").replace(/\|/g, "\\|").replace(/\n/g, " ");
}

function renderResearchComparisonTable(topics, criteria) {
  const lines = [
    "Research comparison table (draft; verify claims against the Step 1 source links).",
    "",
    `| Topic | ${criteria.map((criterion) => RESEARCH_TABLE_CRITERION_LABELS[criterion]).join(" | ")} |`,
    `| --- | ${criteria.map(() => "---").join(" | ")} |`,
  ];
  for (const topic of topics) {
    lines.push(
      `| ${escapeResearchTableCell(topic)} | ${criteria
        .map((criterion) => escapeResearchTableCell(researchTableCell(topic, criterion)))
        .join(" | ")} |`,
    );
  }
  return lines.join("\n");
}

function compactResearchLogValue(value) {
  return String(value || "").split(/\s+/u).filter(Boolean).join(" ");
}

function tryResearchComparisonTable(prompt, normalized, history = []) {
  if (!isComparisonTableRequest(normalized)) return null;
  const priorSearch = lastHistoryTurn(history, "user");
  if (!priorSearch || !looksLikeResearchPrompt(priorSearch)) return null;
  const topics = extractResearchTopics(priorSearch);
  if (topics.length < 2) return null;
  const criteria = extractResearchCriteria(prompt);
  if (criteria.length === 0) return null;
  return {
    intent: "research_comparison_table",
    content: renderResearchComparisonTable(topics, criteria),
    confidence: 0.78,
    evidence: [
      `research_table:prior_search:${compactResearchLogValue(priorSearch)}`,
      ...topics.map((topic) => `research_table:topic:${topic}`),
      ...criteria.map((criterion) => `research_table:criterion:${criterion}`),
    ],
  };
}

// Issue #386: a conversation-summary request is recognised by composing
// meaning roles, not by matching raw words per language. The universal
// algorithm is identical for every language: the prompt either carries a
// complete standalone conversation-summary phrasing, an objectless courtesy
// frame ("can you summarize", "подведи итог"), a summary directive together
// with an explicit conversation reference, or it is itself a bare summary
// directive. The prompt is re-normalised first so the boundary-aware matcher
// sees punctuation collapsed to spaces (idempotent here, since `normalized`
// is already normalised). Mirror of asks_for_conversation_summary in
// src/solver_handlers/mod.rs.
function isSummarizePrompt(normalized) {
  const cleaned = normalizePrompt(normalized);
  return (
    lexiconMentionsRole(ROLE_CONVERSATION_SUMMARY_PHRASE, cleaned) ||
    lexiconMentionsRole(ROLE_CONVERSATION_SUMMARY_COURTESY, cleaned) ||
    (lexiconMentionsRole(ROLE_CONVERSATION_SUMMARY_DIRECTIVE, cleaned) &&
      lexiconMentionsRole(ROLE_CONVERSATION_REFERENCE, cleaned)) ||
    summaryDirectiveLeads(cleaned)
  );
}

// A bare summary directive standing alone is itself a request to summarize the
// running conversation ("summarize", "резюме", "总结", ...). For whitespace-
// delimited scripts the directive must be the whole prompt; for CJK (no word
// spaces) a leading directive suffices, mirroring the historical `^总结`
// anchor and keeping compounds like "工作总结" (a work summary) out. Mirror of
// summary_directive_leads in src/solver_handlers/mod.rs.
function summaryDirectiveLeads(cleaned) {
  return wordsForRole(ROLE_CONVERSATION_SUMMARY_DIRECTIVE).some((word) =>
    containsCjk(word) ? cleaned.startsWith(word) : cleaned === word,
  );
}

function trimUrlToken(token) {
  return String(token || "")
    .replace(/^[<>()\[\]{}"'`«»]+/u, "")
    .replace(/[<>()\[\]{}"'`«»]+$/u, "")
    .replace(/[.,!?;:…]+$/u, "");
}

function looksLikeHostname(value) {
  const host = String(value || "").trim();
  if (!host.includes(".") || host.startsWith(".") || host.endsWith(".")) {
    return false;
  }
  const labels = host.split(".");
  if (labels.some((label) => !label)) return false;
  const tld = labels[labels.length - 1] || "";
  if (tld.length < 2) return false;
  return labels.every(
    (label) =>
      /^[a-z0-9-]+$/i.test(label) &&
      !label.startsWith("-") &&
      !label.endsWith("-"),
  );
}

function normalizeUrlCandidate(candidate) {
  const text = String(candidate || "").trim();
  if (!text || /\s/.test(text) || text.includes("@")) return null;
  const lower = text.toLowerCase();
  let url = "";
  if (lower.startsWith("http://") || lower.startsWith("https://")) {
    url = text;
  } else {
    const hostCandidate = text.split(/[/?#]/, 1)[0] || "";
    if (lower.startsWith("www.") || looksLikeHostname(hostCandidate)) {
      url = `https://${text}`;
    }
  }
  if (!url) return null;
  let parsed;
  try {
    parsed = new URL(url);
  } catch (_error) {
    return null;
  }
  if (!looksLikeHostname(parsed.hostname)) return null;
  return parsed.href.replace(/\/$/, "");
}

function firstUrlCandidate(prompt) {
  const tokens = String(prompt || "").split(/\s+/);
  for (const token of tokens) {
    const trimmed = trimUrlToken(token);
    const url = normalizeUrlCandidate(trimmed);
    if (url) return { raw: trimmed, url };
  }
  return null;
}

// Issue #386: the web intents are recognised by *meaning*, not a hardcoded
// per-language phrase list. The surface words live once in
// data/seed/meanings-web-navigation.lino as the `http_fetch` and `url_navigate`
// meanings (embedded in MEANINGS_LINO above); mirror the ROLE_HTTP_FETCH /
// ROLE_URL_NAVIGATE consts in src/seed/meanings.rs.
const ROLE_HTTP_FETCH = "http_fetch";
const ROLE_URL_NAVIGATE = "url_navigate";

function startsWithAny(haystack, prefixes) {
  return prefixes.some((prefix) => haystack.startsWith(prefix));
}

// Does a meaning carrying `role` evidence one of the prompt's lowercased forms?
// Buckets every surface form of the role by its derived slot exactly as
// role_evidences_web_intent does in src/solver_handlers/web_requests.rs:
//   - "prefix": form.before must *begin* one of the prompt forms ("fetch …" →
//     "fetch google.com"); form.before keeps the trailing space.
//   - "bare": form.text must appear *anywhere* in one of the prompt forms
//     ("запрос к" → "сделать запрос к google.com").
// `forms` are the lowercased prompt views matched against (the normalized
// prompt and the raw lowercased prompt). The result is a pure OR over every
// (form, surface) pair, so bucket order only affects short-circuiting — the
// surface words are never named here (issue #386).
function roleEvidencesWebIntent(role, forms) {
  const wordForms = roleWordForms(role);
  const matchesPrefix = wordForms
    .filter((form) => form.slot === "prefix")
    .some((form) => forms.some((text) => text.startsWith(form.before)));
  if (matchesPrefix) return true;
  return wordForms
    .filter((form) => form.slot === "bare")
    .some((form) => forms.some((text) => text.includes(form.text)));
}

function isHttpFetchPrompt(prompt, normalized) {
  const raw = String(prompt || "").trimStart().toLowerCase();
  return roleEvidencesWebIntent(ROLE_HTTP_FETCH, [normalized, raw]);
}

function isUrlNavigatePrompt(prompt, normalized, rawCandidate) {
  const raw = String(prompt || "").trimStart().toLowerCase();
  if (raw.startsWith(String(rawCandidate || "").toLowerCase())) {
    // Bare URL — treat as navigation, not a request to fetch.
    return true;
  }
  return roleEvidencesWebIntent(ROLE_URL_NAVIGATE, [normalized, raw]);
}

function extractHttpFetchUrl(prompt, normalized) {
  const candidate = firstUrlCandidate(prompt);
  if (!candidate || !isHttpFetchPrompt(prompt, normalized)) {
    return null;
  }
  return candidate.url;
}

function extractUrlNavigateUrl(prompt, normalized) {
  const candidate = firstUrlCandidate(prompt);
  if (!candidate || !isUrlNavigatePrompt(prompt, normalized, candidate.raw)) {
    return null;
  }
  return candidate.url;
}

function cleanSearchQuery(value) {
  return String(value || "")
    .trim()
    .replace(/^[<>()\[\]{}"'`«»]+/u, "")
    .replace(/[<>()\[\]{}"'`«»]+$/u, "")
    .replace(/[.,!?;:…]+$/u, "")
    .replace(/\s+/g, " ")
    .trim();
}

function stripSearchPrefix(prompt, prefix) {
  const text = String(prompt || "").trim();
  if (text.toLowerCase().startsWith(prefix)) {
    return validSearchQuery(text.slice(prefix.length));
  }
  return "";
}

// Issue #386: every surface cue the web-search recogniser reasons about — the
// explicit command prefixes, the action/source/signal vocabulary, the topic
// connectives, the query noise, the follow-up instruction verbs and clause
// boundaries, and the research/enumeration vocabulary — is sourced from the
// language-independent meaning lexicon (data/seed/meanings-web-search*.lino,
// meanings-web-research.lino, meanings-web-followup.lino, embedded in
// MEANINGS_LINO above). The code references those meanings by their semantic
// *role* and by the *slot* each word form occupies (prefix / suffix / bare),
// never by raw words baked into a per-language list — adding a language or a
// synonym is a pure data edit. Mirrors WebSearchMarkers / markers() in
// src/solver_handlers/web_search_intent.rs.
const ROLE_WEB_SEARCH_EXPLICIT_PREFIX = "web_search_explicit_prefix";
const ROLE_WEB_SEARCH_ACTION = "web_search_action";
const ROLE_WEB_SEARCH_STRONG_ACTION = "web_search_strong_action";
const ROLE_WEB_SEARCH_SIGNAL = "web_search_signal";
const ROLE_WEB_SEARCH_TOPIC_MARKER = "web_search_topic_marker";
const ROLE_WEB_SEARCH_IMPERATIVE_LEAD = "web_search_imperative_lead";
const ROLE_WEB_SEARCH_QUERY_LEADING_NOISE = "web_search_query_leading_noise";
const ROLE_WEB_SEARCH_QUERY_TRAILING_NOISE = "web_search_query_trailing_noise";
const ROLE_WEB_SEARCH_SOURCE_ONLY = "web_search_source_only";
// Mention of web search inside a *prior* conversation turn (raw lowercased
// substring of the turn text, not the normalised prompt). Mirrors
// ROLE_WEB_SEARCH_HISTORY_SIGNAL in src/seed/roles.rs.
const ROLE_WEB_SEARCH_HISTORY_SIGNAL = "web_search_history_signal";
const ROLE_FOLLOWUP_INSTRUCTION_VERB = "followup_instruction_verb";
const ROLE_CLAUSE_CONTINUATION_MARKER = "clause_continuation_marker";
const ROLE_RESEARCH_QUESTION_OPENER = "research_question_opener";
const ROLE_RESEARCH_SUPERLATIVE_MODIFIER = "research_superlative_modifier";
const ROLE_RESEARCH_EVIDENCE_DOMAIN = "research_evidence_domain";
const ROLE_RESEARCH_EVALUATION_DOMAIN = "research_evaluation_domain";
const ROLE_ENUMERATION_REQUEST_OPENER = "enumeration_request_opener";
const ROLE_ENUMERATION_CONSTRAINT = "enumeration_constraint";

// Issue #386 proof + who-is roles — mirror ROLE_PROOF_* / ROLE_WHO_QUESTION_*
// in src/seed/roles.rs. Surfaces live in data/seed/meanings-proof.lino and the
// who_is_question meaning in data/seed/meanings-intent.lino. The proof_directive
// bare verbs and proof_claim_scaffold prefixes share the `prove` meaning,
// separated by slot. (The worker's proof engine does not branch on the
// Goedel/determinism concepts, so those roles are referenced only by Rust.)
const ROLE_PROOF_DIRECTIVE = "proof_directive";
const ROLE_PROOF_REQUEST_LEAD = "proof_request_lead";
const ROLE_PROOF_MARKER = "proof_marker";
const ROLE_PROOF_CLAIM_SCAFFOLD = "proof_claim_scaffold";
const ROLE_WHO_QUESTION_LEAD = "who_question_lead";
const ROLE_WHO_QUESTION_TAIL = "who_question_tail";

// Issue #386 policy role — mirrors ROLE_CIRCULAR_JOKE_PHRASE in
// src/seed/roles.rs. Surfaces (the «купи слона» idiom and its buy-an-elephant
// calque in every supported language) live in data/seed/meanings-policy.lino,
// read here by tryKupiSlona as raw substrings. (The physical_action_trigger
// role in that file is read only by the Rust solver, which screens content
// policy first; the worker has no such handler, so it is not mirrored.)
const ROLE_CIRCULAR_JOKE_PHRASE = "circular_joke_phrase";

// Issue #386 calculator-rate roles — mirror ROLE_EXCHANGE_RATE_REFERENCE,
// ROLE_CURRENCY_USD_REFERENCE and ROLE_CALCULATION_BASIS_REFERENCE in
// src/seed/roles.rs. Surfaces (exchange-rate, US-dollar and calculation-basis
// forms in every supported language) live in
// data/seed/meanings-calculator.lino, read here by tryCalculatorRateBasis as
// raw substrings — the JS mirror of asks_for_usd_rate_basis.
const ROLE_EXCHANGE_RATE_REFERENCE = "exchange_rate_reference";
const ROLE_CURRENCY_USD_REFERENCE = "currency_usd_reference";
const ROLE_CALCULATION_BASIS_REFERENCE = "calculation_basis_reference";

// Issue #386 compound-interest / currency-conversion roles — mirror the
// ROLE_INVESTMENT_CUE, ROLE_INTEREST_CUE, ROLE_COMPOUNDING_ACTION_CUE,
// ROLE_COMPOUNDING_FREQUENCY_CUE, ROLE_LIVE_RATE_FRESHNESS_CUE,
// ROLE_YEAR_UNIT_CUE, ROLE_CONVERSION_ACTION_CUE, ROLE_FINAL_AMOUNT_REFERENCE,
// ROLE_CURRENCY_EUR_REFERENCE and ROLE_CURRENCY_RUB_REFERENCE consts in
// src/seed/roles.rs. Surfaces live in data/seed/meanings-finance.lino (the
// investment / interest / compounding / frequency / live-rate / year /
// conversion / final-amount forms) and data/seed/meanings-calculator.lino (the
// euro and ruble currency references), read by parseCompoundInterestRequest,
// parseCompoundsPerYear, parseCompoundYears, targetCurrencyFromText,
// asksForWebRate, parseFinalAmountConversionRequest and currencyCodeFromWord —
// the JS mirror of the compound_interest.rs recognizers.
const ROLE_INVESTMENT_CUE = "investment_cue";
const ROLE_INTEREST_CUE = "interest_cue";
const ROLE_COMPOUNDING_ACTION_CUE = "compounding_action_cue";
const ROLE_COMPOUNDING_FREQUENCY_CUE = "compounding_frequency_cue";
const ROLE_LIVE_RATE_FRESHNESS_CUE = "live_rate_freshness_cue";
const ROLE_YEAR_UNIT_CUE = "year_unit_cue";
const ROLE_CONVERSION_ACTION_CUE = "conversion_action_cue";
const ROLE_FINAL_AMOUNT_REFERENCE = "final_amount_reference";
const ROLE_CURRENCY_EUR_REFERENCE = "currency_eur_reference";
const ROLE_CURRENCY_RUB_REFERENCE = "currency_rub_reference";

// Issue #386 definition-merge roles — mirror the ROLE_DEFINITION_MERGE_ACTION,
// ROLE_DEFINITION_ARTIFACT_REQUEST, ROLE_DEFINITION_MERGE_MARKER and
// ROLE_DEFINITION_MERGE_TAIL_BOUNDARY consts in src/seed/roles.rs. Surfaces
// live in data/seed/meanings-definition-merge.lino, read by
// extractDefinitionMergeTerm and trimDefinitionMergeTail — the JS mirror of the
// definition_merge.rs recognizers.
const ROLE_DEFINITION_MERGE_ACTION = "definition_merge_action";
const ROLE_DEFINITION_ARTIFACT_REQUEST = "definition_artifact_request";
const ROLE_DEFINITION_MERGE_MARKER = "definition_merge_marker";
const ROLE_DEFINITION_MERGE_TAIL_BOUNDARY = "definition_merge_tail_boundary";

// Issue #386 meta-explanation roles — mirror ROLE_ASSISTANT_SELF_REFERENCE and
// ROLE_ARCHITECTURE_CONCEPT in src/seed/roles.rs. Surfaces (the assistant's
// self-reference pronouns and the architecture concepts — language model,
// neural network, the project's local rules — in every supported language) live
// in data/seed/meanings-meta.lino, read here by isArchitectureQuestion as raw
// substrings, the JS mirror of is_architecture_question. (The why/how-you-work
// recognizers live only in the Rust solver_handler; the worker has no
// tryMetaExplanation, so the answer_rationale_lead, causal_interrogative,
// prior_answer_reference, assistant_mechanism_inquiry and operating_principle
// roles in that file are not mirrored here.)
const ROLE_ASSISTANT_SELF_REFERENCE = "assistant_self_reference";
const ROLE_ARCHITECTURE_CONCEPT = "architecture_concept";

// Issue #386 documentation-handler roles — mirror ROLE_EXPLANATION_REQUEST_LEAD,
// ROLE_WEB_MEDIUM and ROLE_CODE_METHOD_NOUN in src/seed/roles.rs. Their surfaces
// live in data/seed/meanings-docs.lino (explanation leads, the method noun) and
// data/seed/meanings-web-search.lino (the web_medium surfaces on
// reference_internet). isExplanationRequest, isExplicitWebSearchPrompt and the
// join+method branch of isPandasDataFrameJoinPrompt read them instead of naming
// any interrogative, medium or per-language method word in code here.
const ROLE_EXPLANATION_REQUEST_LEAD = "explanation_request_lead";
const ROLE_WEB_MEDIUM = "web_medium";
const ROLE_CODE_METHOD_NOUN = "code_method_noun";

// The literal lead-in (form.before, the text before the … slot) of every
// prefix-slot form of a role, in lexicon declaration order. A meaning's roles
// apply to all its forms, so keep only the slot we asked for. Mirrors
// prefix_literals.
function prefixLiterals(role) {
  return roleWordForms(role)
    .filter((form) => form.slot === "prefix")
    .map((form) => form.before);
}
// The literal tail (form.after) of every suffix-slot form of a role. Mirrors
// suffix_literals.
function suffixLiterals(role) {
  return roleWordForms(role)
    .filter((form) => form.slot === "suffix")
    .map((form) => form.after);
}
// The surface text of every bare-slot form of a role (drop any prefix/suffix
// surfaces the same meaning also owns). Mirrors bare_literals.
function bareLiterals(role) {
  return roleWordForms(role)
    .filter((form) => form.slot === "bare")
    .map((form) => form.text);
}
// The distinct surface words of a role, trimmed + lowercased for equality
// comparison against a cleaned query. Mirrors source_literals (words_for_role).
function sourceLiterals(role) {
  const seen = new Set();
  const out = [];
  for (const form of roleWordForms(role)) {
    const key = form.text.trim().toLowerCase();
    if (!seen.has(key)) {
      seen.add(key);
      out.push(key);
    }
  }
  return out;
}

// Build (once) the marker projection from the meaning lexicon, then cache it —
// roleWordForms walks the whole lexicon, so memoize like the Rust OnceLock.
let WEB_SEARCH_MARKERS_CACHE = null;
function webSearchMarkers() {
  if (WEB_SEARCH_MARKERS_CACHE) return WEB_SEARCH_MARKERS_CACHE;
  WEB_SEARCH_MARKERS_CACHE = {
    explicitPrefixes: prefixLiterals(ROLE_WEB_SEARCH_EXPLICIT_PREFIX),
    actionMarkers: bareLiterals(ROLE_WEB_SEARCH_ACTION),
    strongActionMarkers: bareLiterals(ROLE_WEB_SEARCH_STRONG_ACTION),
    signalMarkers: bareLiterals(ROLE_WEB_SEARCH_SIGNAL),
    topicAfterMarkers: prefixLiterals(ROLE_WEB_SEARCH_TOPIC_MARKER),
    topicBeforeMarkers: suffixLiterals(ROLE_WEB_SEARCH_TOPIC_MARKER),
    imperativeLeadMarkers: prefixLiterals(ROLE_WEB_SEARCH_IMPERATIVE_LEAD),
    leadingNoise: prefixLiterals(ROLE_WEB_SEARCH_QUERY_LEADING_NOISE),
    trailingNoise: suffixLiterals(ROLE_WEB_SEARCH_QUERY_TRAILING_NOISE),
    sourceOnly: sourceLiterals(ROLE_WEB_SEARCH_SOURCE_ONLY),
    followupVerbs: bareLiterals(ROLE_FOLLOWUP_INSTRUCTION_VERB),
    continuationMarkers: bareLiterals(ROLE_CLAUSE_CONTINUATION_MARKER),
    researchQuestionPrefixes: prefixLiterals(ROLE_RESEARCH_QUESTION_OPENER),
    researchModifiers: bareLiterals(ROLE_RESEARCH_SUPERLATIVE_MODIFIER),
    researchEvidenceDomains: bareLiterals(ROLE_RESEARCH_EVIDENCE_DOMAIN),
    researchEvaluationDomains: bareLiterals(ROLE_RESEARCH_EVALUATION_DOMAIN),
    enumerationPrefixes: prefixLiterals(ROLE_ENUMERATION_REQUEST_OPENER),
    enumerationConstraintMarkers: bareLiterals(ROLE_ENUMERATION_CONSTRAINT),
  };
  return WEB_SEARCH_MARKERS_CACHE;
}

// A request to filter the user's OWN contributed facts ("facts I contributed",
// "my facts") is conversation search, not a web search. Mirrors
// is_personal_fact_filter_request in src/solver_handlers/web_search_intent.rs.
function isPersonalFactFilterRequest(normalized) {
  const text = String(normalized || "");
  return (
    text.includes("facts i have contributed") ||
    text.includes("facts ive contributed") ||
    text.includes("facts i contributed") ||
    text.includes("my facts")
  );
}

function containsSearchMarker(normalized, marker) {
  const text = String(normalized || "");
  if (marker.startsWith(" ") || marker.endsWith(" ")) {
    return ` ${text} `.includes(marker);
  }
  return text.includes(marker);
}

function containsAnySearchMarker(normalized, markers) {
  return markers.some((marker) => containsSearchMarker(normalized, marker));
}

function stripSearchNoisePrefix(value, prefix) {
  const text = cleanSearchQuery(value);
  return text.toLowerCase().startsWith(prefix)
    ? cleanSearchQuery(text.slice(prefix.length))
    : text;
}

function stripSearchNoiseSuffix(value, suffix) {
  const text = cleanSearchQuery(value);
  return text.toLowerCase().endsWith(suffix)
    ? cleanSearchQuery(text.slice(0, text.length - suffix.length))
    : text;
}

// Sentence-ending punctuation that can introduce a follow-up instruction
// clause — ASCII plus the fullwidth/ideographic forms a CJK prompt uses.
// Mirrors is_sentence_boundary.
const SEARCH_SENTENCE_BOUNDARY = new Set([
  ".",
  "?",
  "!",
  ";",
  ":",
  "\u3002",
  "\uff1f",
  "\uff01",
  "\uff1b",
  "\uff1a",
]);

// ASCII-only lowercase: folds A–Z and nothing else, so the result keeps the same
// length (in UTF-16 code units) as the input and computed offsets stay aligned.
// Mirrors Rust str::to_ascii_lowercase (a full toLowerCase could change length,
// e.g. 'İ' -> 'i̇', and misalign the cut offsets).
function asciiLowercase(value) {
  return String(value || "").replace(/[A-Z]/g, (character) =>
    String.fromCharCode(character.charCodeAt(0) + 32),
  );
}

// Is the single Unicode code point `code` a letter or number? Mirrors Rust
// char::is_alphanumeric closely enough for token-boundary detection.
function isSearchAlnum(code) {
  return /[\p{L}\p{N}]/u.test(String.fromCodePoint(code));
}

// Does `index` begin a token in `text` (the preceding code point is non-
// alphanumeric, or there is none)? Surrogate-pair aware. Mirrors is_token_start.
function isSearchTokenStart(text, index) {
  if (index <= 0) return true;
  const i = index - 1;
  let code = text.charCodeAt(i);
  if (code >= 0xdc00 && code <= 0xdfff && i > 0) {
    const high = text.charCodeAt(i - 1);
    if (high >= 0xd800 && high <= 0xdbff) {
      code = (high - 0xd800) * 0x400 + (code - 0xdc00) + 0x10000;
    }
  }
  return !isSearchAlnum(code);
}

// Does `index` end a token in `text` (the following code point is non-
// alphanumeric, or there is none)? Mirrors is_token_end.
function isSearchTokenEnd(text, index) {
  if (index >= text.length) return true;
  return !isSearchAlnum(text.codePointAt(index));
}

// Whether `haystack` ends with `marker` as a whole token. CJK markers match as
// bare substrings; space-delimited markers need a preceding whitespace (or for
// the whole string to be exactly the marker). Mirrors ends_with_token.
function searchEndsWithToken(haystack, marker) {
  if (containsCjk(marker)) return haystack.endsWith(marker);
  if (haystack === marker) return true;
  if (!haystack.endsWith(marker)) return false;
  const head = haystack.slice(0, haystack.length - marker.length);
  return /\s$/u.test(head);
}

// If the text immediately before `verbStart` is a follow-up boundary, return the
// code-unit offset at which to cut (the start of the boundary run); otherwise
// null. Mirrors boundary_before.
function searchBoundaryBefore(text, verbStart, markers) {
  const head = text.slice(0, verbStart).trimEnd();
  if (head.length === 0) return null;
  if (SEARCH_SENTENCE_BOUNDARY.has(head[head.length - 1])) return head.length;
  // Walk back over a run of clause-continuation markers ("and", "then",
  // "and then"); the cut falls at the start of the run.
  let cursor = head;
  let matched = false;
  for (;;) {
    const trimmed = cursor.trimEnd();
    let rest = null;
    for (const marker of markers.continuationMarkers) {
      if (searchEndsWithToken(trimmed, marker)) {
        rest = trimmed.slice(0, trimmed.length - marker.length);
        break;
      }
    }
    if (rest === null) break;
    cursor = rest;
    matched = true;
  }
  return matched ? cursor.trimEnd().length : null;
}

// Drop a trailing follow-up instruction clause ("… and summarize who won",
// "… . Compare their patents") from a query. A universal boundary algorithm, not
// a list of memorised fragments: a follow-up clause is one of the lexicon's
// followup_instruction_verb surfaces sitting immediately after a *boundary* —
// sentence punctuation or a run of clause_continuation_marker words — and the
// query is cut at the start of the earliest such boundary. A bare verb with no
// boundary before it is part of the topic and left untouched. Mirrors
// truncate_search_instruction_tail in src/solver_handlers/web_search_intent.rs.
function truncateSearchInstructionTail(value) {
  const markers = webSearchMarkers();
  const text = String(value || "");
  // ASCII-lowercase keeps offsets identical to `text`; the non-ASCII verbs are
  // already lowercase in the lexicon and unaffected by the fold.
  const lower = asciiLowercase(text);
  let cut = text.length;
  for (const verb of markers.followupVerbs) {
    const cjk = containsCjk(verb);
    let from = 0;
    for (;;) {
      const start = lower.indexOf(verb, from);
      if (start === -1) break;
      const end = start + verb.length;
      from = end;
      // Space-delimited scripts require a whole-token match; CJK verbs have no
      // word boundaries and match as bare substrings.
      if (!cjk && (!isSearchTokenStart(lower, start) || !isSearchTokenEnd(lower, end))) {
        continue;
      }
      const boundary = searchBoundaryBefore(lower, start, markers);
      if (boundary !== null) cut = Math.min(cut, boundary);
    }
  }
  return text.slice(0, cut).trim();
}

function cleanSemanticSearchQuery(value) {
  const markers = webSearchMarkers();
  let query = cleanSearchQuery(truncateSearchInstructionTail(value));
  while (true) {
    const before = query;
    for (const prefix of markers.leadingNoise) {
      query = stripSearchNoisePrefix(query, prefix);
    }
    for (const suffix of markers.trailingNoise) {
      query = stripSearchNoiseSuffix(query, suffix);
    }
    if (query === before) return query;
  }
}

function validSearchQuery(value) {
  const query = cleanSemanticSearchQuery(value);
  const queryKey = query.toLowerCase();
  if (webSearchMarkers().sourceOnly.includes(queryKey)) return "";
  return query && !normalizeUrlCandidate(query) ? query : "";
}

function rawSearchMarkerIndex(prompt, marker) {
  return String(prompt || "").toLowerCase().indexOf(marker);
}

function queryAfterRawMarker(prompt, marker) {
  const text = String(prompt || "").trim();
  const index = rawSearchMarkerIndex(text, marker);
  return index === -1 ? "" : validSearchQuery(text.slice(index + marker.length));
}

function queryBeforeRawMarker(prompt, marker) {
  const text = String(prompt || "").trim();
  const index = rawSearchMarkerIndex(text, marker);
  return index === -1 ? "" : validSearchQuery(text.slice(0, index));
}

function queryAfterNormalizedMarker(normalized, marker) {
  const index = String(normalized || "").indexOf(marker);
  return index === -1 ? "" : validSearchQuery(normalized.slice(index + marker.length));
}

function queryBeforeNormalizedMarker(normalized, marker) {
  const index = String(normalized || "").indexOf(marker);
  return index === -1 ? "" : validSearchQuery(normalized.slice(0, index));
}

function extractSemanticWebSearchQuery(prompt, normalized) {
  const markers = webSearchMarkers();
  const hasAction = containsAnySearchMarker(normalized, markers.actionMarkers);
  if (!hasAction) return "";
  const hasStrongAction = containsAnySearchMarker(
    normalized,
    markers.strongActionMarkers,
  );
  if (!hasStrongAction && !containsAnySearchMarker(normalized, markers.signalMarkers)) {
    return "";
  }
  for (const marker of markers.topicAfterMarkers) {
    const query =
      queryAfterRawMarker(prompt, marker) ||
      queryAfterNormalizedMarker(normalized, marker);
    if (query) return query;
  }
  for (const marker of markers.topicBeforeMarkers) {
    const query =
      queryBeforeRawMarker(prompt, marker) ||
      queryBeforeNormalizedMarker(normalized, marker);
    if (query) return query;
  }
  for (const marker of markers.imperativeLeadMarkers) {
    const query =
      queryAfterRawMarker(prompt, marker) ||
      queryAfterNormalizedMarker(normalized, marker);
    if (query) return query;
  }
  return "";
}

function stripImplicitResearchPrefix(value) {
  const text = String(value || "");
  for (const prefix of webSearchMarkers().researchQuestionPrefixes) {
    if (text.startsWith(prefix)) {
      return text.slice(prefix.length);
    }
  }
  return text;
}

function extractImplicitResearchQuestion(normalized) {
  const markers = webSearchMarkers();
  const text = String(normalized || "");
  if (!startsWithAny(text, markers.researchQuestionPrefixes)) return "";
  const padded = ` ${text} `;
  const hasModifier = markers.researchModifiers.some((marker) =>
    padded.includes(marker),
  );
  const hasEvidenceDomain = markers.researchEvidenceDomains.some((marker) =>
    padded.includes(marker),
  );
  const hasEvaluationDomain = markers.researchEvaluationDomains.some((marker) =>
    padded.includes(marker),
  );
  if (!hasModifier && !(hasEvidenceDomain && hasEvaluationDomain)) return "";
  return validSearchQuery(stripImplicitResearchPrefix(text));
}

function stripEnumerationResearchPrefix(value) {
  const text = String(value || "").trim();
  const lower = text.toLowerCase();
  for (const prefix of webSearchMarkers().enumerationPrefixes) {
    if (lower.startsWith(prefix)) {
      return cleanSearchQuery(text.slice(prefix.length));
    }
  }
  return "";
}

function looksLikeEnumerationResearchQuery(query) {
  const normalized = normalizePrompt(query);
  if (normalized.split(/\s+/u).filter(Boolean).length < 3) return false;
  return containsAnySearchMarker(
    normalized,
    webSearchMarkers().enumerationConstraintMarkers,
  );
}

function extractEnumerationResearchRequest(prompt, normalized) {
  const rawQuery = stripEnumerationResearchPrefix(prompt);
  if (rawQuery && looksLikeEnumerationResearchQuery(rawQuery)) {
    return validSearchQuery(rawQuery);
  }
  const normalizedQuery = stripEnumerationResearchPrefix(normalized);
  return normalizedQuery && looksLikeEnumerationResearchQuery(normalizedQuery)
    ? validSearchQuery(normalizedQuery)
    : "";
}

function extractWebSearchRequest(prompt, normalized) {
  if (
    normalized.startsWith("search conversations ") ||
    normalized.startsWith("search my conversations ") ||
    normalized.startsWith("search my chats ") ||
    isPersonalFactFilterRequest(normalized)
  ) {
    return "";
  }
  for (const prefix of webSearchMarkers().explicitPrefixes) {
    const rawQuery = stripSearchPrefix(prompt, prefix);
    const normalizedQuery = normalized.startsWith(prefix)
      ? validSearchQuery(normalized.slice(prefix.length))
      : "";
    const query = rawQuery || normalizedQuery;
    if (query) {
      return { query, kind: "explicit_prefix" };
    }
  }
  const semanticQuery = extractSemanticWebSearchQuery(prompt, normalized);
  if (semanticQuery) {
    return { query: semanticQuery, kind: "semantic_action" };
  }
  const enumerationQuery = extractEnumerationResearchRequest(prompt, normalized);
  if (enumerationQuery) {
    return { query: enumerationQuery, kind: "enumeration_research_request" };
  }
  const researchQuery = extractImplicitResearchQuestion(normalized);
  return researchQuery
    ? { query: researchQuery, kind: "implicit_research_question" }
    : null;
}

function extractWebSearchQuery(prompt, normalized) {
  const request = extractWebSearchRequest(prompt, normalized);
  return request ? request.query : "";
}

function cleanProceduralFragment(value) {
  let clean = String(value || "")
    .trim()
    .replace(/^[`"' ]+/u, "")
    .replace(/[`"' ]+$/u, "")
    .replace(/[?!.,;:]+$/u, "")
    .replace(/\s+/g, " ")
    .trim();
  // The trailing "step by step" / politeness modifiers are the slot-marked
  // surface forms of the procedural_task_modifier meaning
  // (data/seed/meanings-how.lino, embedded in MEANINGS_LINO above): every form
  // is a suffix whose text after the … marker (form.after) is the tail to
  // strip, scanned in declaration order so the longer Russian "напиши по шагам"
  // still precedes its "по шагам" tail. No per-language modifier list lives
  // here — only the concept. Mirrors clean_procedural_fragment in
  // src/solver_handler_how.rs (issue #386).
  for (const form of roleWordForms(ROLE_PROCEDURAL_TASK_MODIFIER)) {
    if (clean.endsWith(form.after)) {
      clean = clean.slice(0, clean.length - form.after.length).trim();
      break;
    }
  }
  return clean;
}

function correctCommonProceduralTypos(task) {
  // The misspelling -> correction pairs are the common_typo meaning's bare
  // surface forms (data/seed/meanings-how.lino, embedded in MEANINGS_LINO
  // above): each form's text is the misspelled token and its action field names
  // the correct spelling. No per-language typo table lives here — only the
  // concept. Mirrors correct_common_procedural_typos in
  // src/solver_handler_how.rs (issue #386).
  const typos = roleWordForms(ROLE_COMMON_TYPO);
  const corrections = [];
  const corrected = String(task || "")
    .split(/\s+/u)
    .filter(Boolean)
    .map((token) => {
      for (const form of typos) {
        if (token === form.text) {
          if (!corrections.some((correction) => correction.from === form.text)) {
            corrections.push({ from: form.text, to: form.action });
          }
          return form.action;
        }
      }
      return token;
    })
    .join(" ");
  return { task: corrected, corrections };
}

function extractProceduralHowToTask(normalized) {
  // The prefixes are the slot-marked surface forms of the procedural_request
  // meaning (data/seed/meanings-how.lino, embedded in MEANINGS_LINO): every
  // form is a prefix whose literal before the … marker (form.before) is the
  // matchable prefix, scanned in declaration order so "how to do " still
  // precedes "how to ". A form may name the canonical operation in its action
  // field (do / perform / implement / create / write); an empty action means
  // the operation is taken from the task's first word. No per-language prefix
  // list lives here — only the concept. Mirrors extract_procedural_how_to_task
  // in src/solver_handler_how.rs (issue #386).
  const clean = cleanProceduralFragment(normalized);
  for (const form of roleWordForms(ROLE_PROCEDURAL_REQUEST)) {
    if (!clean.startsWith(form.before)) continue;
    const correction = correctCommonProceduralTypos(
      cleanProceduralFragment(clean.slice(form.before.length)),
    );
    const task = correction.task;
    if (!task) return null;
    const actionOverride = form.action || null;
    if (actionOverride) {
      return {
        task,
        action: actionOverride,
        object: task,
        corrections: correction.corrections,
      };
    }
    const firstSpace = task.search(/\s/u);
    const action = firstSpace === -1 ? task : task.slice(0, firstSpace);
    const object = firstSpace === -1 ? "" : task.slice(firstSpace + 1).trim();
    return { task, action, object, corrections: correction.corrections };
  }
  return null;
}

function capitalizeForWikiHow(word) {
  const text = String(word || "");
  if (!text) return "";
  return text.charAt(0).toUpperCase() + text.slice(1);
}

function wikiHowPageTitle(task) {
  return String(task || "")
    .split(/[^\p{L}\p{N}]+/u)
    .filter(Boolean)
    .map(capitalizeForWikiHow)
    .join("-");
}

function wikiHowParseApiUrl(pageTitle) {
  const encodedPage = encodeURIComponent(pageTitle).replace(/%2D/gi, "-");
  return `https://www.wikihow.com/api.php?action=parse&page=${encodedPage}&prop=text%7Csections%7Cdisplaytitle&format=json&origin=*`;
}

function decodeBasicHtmlEntities(value) {
  return String(value || "")
    .replace(/&nbsp;|&#160;/g, " ")
    .replace(/&amp;/g, "&")
    .replace(/&quot;/g, '"')
    .replace(/&#039;|&apos;/g, "'")
    .replace(/&lt;/g, "<")
    .replace(/&gt;/g, ">")
    .replace(/&#(\d+);/g, (_match, code) => {
      const value = Number(code);
      if (!Number.isFinite(value) || value < 0 || value > 0x10ffff) return "";
      return String.fromCodePoint(value);
    });
}

function compactStepText(value) {
  const text = decodeBasicHtmlEntities(stripHtml(value))
    .replace(/\[[0-9]+\]/g, "")
    .replace(/\s+/g, " ")
    .trim();
  if (text.length <= 180) return text;
  const sentence = text.match(/^(.{40,180}?[.!?])\s/u);
  if (sentence) return sentence[1].trim();
  return `${text.slice(0, 177).trim()}...`;
}

function extractWikiHowSteps(html) {
  const lines = String(html || "").split(/\n+/u);
  const steps = [];
  const seen = new Set();
  for (const line of lines) {
    const trimmed = line.trim();
    if (!trimmed.startsWith("<li>") || trimmed.startsWith("<li><b>")) {
      continue;
    }
    const text = compactStepText(trimmed);
    if (text.length < 40 || seen.has(text)) continue;
    seen.add(text);
    steps.push(text);
    if (steps.length >= 6) break;
  }
  return steps;
}

async function fetchWikiHowProcedure(pageTitle, evidence) {
  const url = wikiHowParseApiUrl(pageTitle);
  if (typeof fetch !== "function") {
    return { ok: false, url, error: "fetch_unavailable", steps: [] };
  }
  try {
    const response = await fetch(url, { method: "GET", mode: "cors" });
    evidence.push(`http_fetch:status:${response.status}`);
    if (!response.ok) {
      return { ok: false, url, error: `http_${response.status}`, steps: [] };
    }
    const data = await response.json();
    if (data && data.error) {
      return {
        ok: false,
        url,
        error: data.error.code || "wikihow_error",
        steps: [],
      };
    }
    const parse = data && data.parse ? data.parse : null;
    const html = parse && parse.text ? parse.text["*"] : "";
    const steps = extractWikiHowSteps(html);
    const title = compactStepText(parse && parse.displaytitle ? parse.displaytitle : pageTitle);
    const sourceUrl = `https://www.wikihow.com/${encodeURIComponent(pageTitle).replace(/%2D/gi, "-")}`;
    return {
      ok: steps.length > 0,
      url,
      title: title || pageTitle,
      sourceUrl,
      error: steps.length > 0 ? "" : "no_explicit_steps",
      steps,
    };
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    evidence.push(`http_fetch:error:${message.toLowerCase().includes("cors") ? "cors" : "network"}`);
    return { ok: false, url, error: message || "network", steps: [] };
  }
}

function appendUniqueEvidence(target, source) {
  const seen = new Set(target);
  for (const item of source || []) {
    if (!item || seen.has(item)) continue;
    seen.add(item);
    target.push(item);
  }
}

const PANDAS_DATAFRAME_JOIN_DOCS_URL =
  "https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.join.html";

function hasNormalizedWord(normalized, word) {
  return String(normalized || "")
    .split(/\s+/)
    .some((token) => token === word);
}

// True when the prompt opens with an imperative to search the web, so it should
// be answered by the web-search handler rather than the narrow docs handler.
// Mirrors is_explicit_web_search in src/solver_handler_docs.rs by meaning. The
// search imperative is read from the web_search_imperative_lead role — only its
// prefix forms are clause-initial leads, so the literal before each ellipsis
// ("search ", "look up ", "найди ", "搜索", …) is matched against the start of
// the prompt. The medium is read from the web_medium role; its surfaces are
// space-wrapped, so containsSearchMarker matches them with the whole-token
// padding convention (which also catches a medium word at the very end).
function isExplicitWebSearchPrompt(normalized) {
  const text = String(normalized || "");
  const requestsSearch = roleWordForms(ROLE_WEB_SEARCH_IMPERATIVE_LEAD)
    .filter((form) => form.slot === "prefix")
    .some((form) => text.startsWith(form.before));
  if (!requestsSearch) return false;
  return roleWordForms(ROLE_WEB_MEDIUM).some((form) =>
    containsSearchMarker(text, form.text),
  );
}

// True when the prompt is phrased as a request to have something explained.
// Mirrors is_explanation_request in src/solver_handler_docs.rs: every
// interrogative and imperative lead-in lives in the explanation_request_lead
// role, so no question word is hardcoded here. Each surface is matched by its
// slot — a prefix form ("how …", "explain …", "как …", "解释…") by the literal
// before the ellipsis against the start of the prompt, a bare form (" how ",
// "कैसे काम", "如何工作", …) as a raw substring anywhere (the space-wrapped bare
// forms thus match only on whole-word boundaries).
function isExplanationRequest(normalized) {
  const text = String(normalized || "");
  return roleWordForms(ROLE_EXPLANATION_REQUEST_LEAD).some((form) =>
    form.slot === "prefix"
      ? text.startsWith(form.before)
      : text.includes(form.text),
  );
}

// True when the prompt asks how the pandas DataFrame.join method works. Mirrors
// is_pandas_dataframe_join_prompt in src/solver_handler_docs.rs. The prompt must
// address pandas, read as an explanation request, and not be an explicit web
// search. The join is then recognised through two kinds of evidence: code-
// resident API identifiers (DataFrame.join, df.join, the join+dataframe pairing)
// — written the same in every language, so they legitimately live here as the
// bridge from a multilingual question to one documented API — and the
// translatable noun "method", matched through the code_method_noun role rather
// than the four per-language words it used to hardcode, paired with the join
// identifier.
function isPandasDataFrameJoinPrompt(prompt, normalized) {
  const lower = String(prompt || "").toLowerCase();
  const text = String(normalized || "").trim();
  if (isExplicitWebSearchPrompt(text)) return false;
  if (!hasNormalizedWord(text, "pandas")) return false;
  if (!isExplanationRequest(text)) return false;
  return (
    lower.includes("dataframe.join") ||
    lower.includes("df.join") ||
    (hasNormalizedWord(text, "join") && hasNormalizedWord(text, "dataframe")) ||
    (hasNormalizedWord(text, "join") &&
      lexiconMentionsRole(ROLE_CODE_METHOD_NOUN, text))
  );
}

function docsMethodContent(language) {
  if (language === "ru") {
    return [
      "pandas `DataFrame.join` добавляет столбцы из `other` DataFrame или именованной Series к вызывающему DataFrame и возвращает новый DataFrame.",
      "В рамках этого метода: по умолчанию это left join по индексу вызывающего DataFrame. Если задан `on`, pandas сопоставляет этот столбец или уровень индекса с индексом объекта `other`. Параметр `how` управляет объединением ключей (`left`, `right`, `outer`, `inner`, `cross`, `left_anti` или `right_anti`). `lsuffix` и `rsuffix` нужны при совпадающих именах столбцов, `sort` сортирует ключи join, а `validate` проверяет связи one-to-one, one-to-many, many-to-one или many-to-many. Для join столбец-к-столбцу документация pandas указывает на `DataFrame.merge`.",
      `Источник: [pandas.DataFrame.join](${PANDAS_DATAFRAME_JOIN_DOCS_URL}) (официальная документация pandas).`,
    ].join("\n\n");
  }

  if (language === "hi") {
    return [
      "pandas `DataFrame.join` कॉल करने वाले DataFrame में `other` DataFrame या named Series के columns जोड़ता है और नया DataFrame लौटाता है.",
      "इस method के दायरे में: default रूप से यह caller के index पर left join करता है. `on` देने पर pandas caller के उस column या index level को `other` object के index से मिलाता है. `how` parameter keys को मिलाने का तरीका चुनता है (`left`, `right`, `outer`, `inner`, `cross`, `left_anti`, या `right_anti`). Column नाम टकराने पर `lsuffix` और `rsuffix`, join keys को sort करने के लिए `sort`, और one-to-one, one-to-many, many-to-one, या many-to-many संबंध जांचने के लिए `validate` इस्तेमाल करें. Column-on-column joins के लिए pandas docs `DataFrame.merge` की ओर भेजते हैं.",
      `Source: [pandas.DataFrame.join](${PANDAS_DATAFRAME_JOIN_DOCS_URL}) (official pandas docs).`,
    ].join("\n\n");
  }

  if (language === "zh") {
    return [
      "pandas `DataFrame.join` 会把 `other` DataFrame 或具名 Series 的列加入调用方,并返回新的 DataFrame。",
      "只看这个方法:默认情况下,它使用调用方的 index 执行 left join。设置 `on` 时,pandas 会把调用方的列或索引层级与 `other` 对象的 index 匹配。`how` 参数控制键的组合方式(`left`、`right`、`outer`、`inner`、`cross`、`left_anti` 或 `right_anti`)。列名冲突时使用 `lsuffix` 和 `rsuffix`,用 `sort` 排序 join keys,用 `validate` 检查 one-to-one、one-to-many、many-to-one 或 many-to-many 关系。对于列到列的 join,pandas 文档指向 `DataFrame.merge`。",
      `Source: [pandas.DataFrame.join](${PANDAS_DATAFRAME_JOIN_DOCS_URL}) (official pandas docs).`,
    ].join("\n\n");
  }

  return [
    "pandas `DataFrame.join` joins columns from the `other` DataFrame or named Series into the caller and returns a new DataFrame.",
    "Scoped to this method: by default, it performs a left join using the caller's index. If `on` is set, pandas matches that caller column or index level against the `other` object's index. The `how` parameter controls key handling (`left`, `right`, `outer`, `inner`, `cross`, `left_anti`, or `right_anti`). Use `lsuffix` and `rsuffix` when column names overlap, `sort` to order join keys, and `validate` to check one-to-one, one-to-many, many-to-one, or many-to-many relationships. For column-on-column joins, the pandas docs point to `DataFrame.merge`.",
    `Source: [pandas.DataFrame.join](${PANDAS_DATAFRAME_JOIN_DOCS_URL}) (official pandas docs).`,
  ].join("\n\n");
}

function tryDocsMethodExplanation(prompt, language) {
  const normalized = normalizePrompt(prompt);
  if (!isPandasDataFrameJoinPrompt(prompt, normalized)) return null;

  return {
    intent: "docs_method_explanation",
    content: docsMethodContent(language),
    confidence: 0.92,
    evidence: [
      "docs_method:project:pandas",
      "docs_method:method:pandas.DataFrame.join",
      "docs_method:source_kind:official-docs",
      `source:${PANDAS_DATAFRAME_JOIN_DOCS_URL}`,
      `language:${language}`,
    ],
    formalizedObject: "pandas.DataFrame.join",
  };
}

async function tryProceduralHowTo(prompt, language) {
  const normalized = normalizePrompt(prompt);
  const task = extractProceduralHowToTask(normalized);
  if (!task) return null;

  const query = `how to ${task.task}`;
  const pageTitle = wikiHowPageTitle(task.task);
  const apiUrl = wikiHowParseApiUrl(pageTitle);
  const providerSummary = WEB_SEARCH_PROVIDERS.map((provider) => provider.id).join(", ");
  const evidence = [
    `procedural_how_to:request:${task.task}`,
    `procedural_how_to:action:${task.action}`,
    `procedural_how_to:stage:wikipedia`,
    `procedural_how_to:stage:wikidata`,
    `procedural_how_to:stage:wikihow_api`,
    `procedural_how_to:wikihow_candidate:${pageTitle}`,
    `http_fetch:request:${apiUrl}`,
  ];
  for (const correction of task.corrections || []) {
    evidence.push(`spelling_correction:${correction.from}->${correction.to}`);
  }
  if (task.object) {
    evidence.splice(2, 0, `procedural_how_to:object:${task.object}`);
  }

  const wikiHow = await fetchWikiHowProcedure(pageTitle, evidence);
  const lines = [
    `Procedural discovery for \`${task.task}\` (action \`${task.action}\`, object \`${task.object}\`).`,
    "",
    "Source path: Wikipedia -> Wikidata -> wikiHow API -> web search fallback -> recursive fetch check.",
    "",
  ];

  let confidence = 0.78;
  let diagnostics = null;
  let formalizedObject = "";
  if (wikiHow.ok) {
    evidence.push(`procedural_how_to:wikihow_steps:${wikiHow.steps.length}`);
    evidence.push(`source:${wikiHow.sourceUrl}`);
    formalizedObject = `WH:${pageTitle}`;
    confidence = 0.86;
    lines.push(`wikiHow API returned \`${wikiHow.title}\` for candidate \`${pageTitle}\`.`);
    lines.push("");
    wikiHow.steps.forEach((step, index) => {
      lines.push(`${index + 1}. ${step}`);
    });
    lines.push("");
    lines.push(`[Source](${wikiHow.sourceUrl})`);
  } else {
    evidence.push(`procedural_how_to:wikihow_miss:${wikiHow.error || "no_match"}`);
    evidence.push("procedural_how_to:stage:web_search");
    const webSearch = await tryWebSearch(`search the web for ${query}`, language);
    if (webSearch) {
      appendUniqueEvidence(evidence, webSearch.evidence);
      diagnostics = webSearch.diagnostics || null;
      formalizedObject = webSearch.formalizedObject || "";
      lines.push(
        `wikiHow candidate \`${pageTitle}\` did not return explicit steps (${wikiHow.error || "no_match"}).`,
      );
      lines.push("");
      lines.push(`Fallback web search for \`${query}\`:`);
      lines.push("");
      lines.push(webSearch.content);
    } else {
      evidence.push(`web_search:request:${query}`);
      for (const provider of WEB_SEARCH_PROVIDERS) {
        evidence.push(`web_search:provider:${provider.id}`);
      }
      evidence.push(`web_search:combined:rrf:k=${webSearchRrfK()}`);
      lines.push(
        `wikiHow candidate \`${pageTitle}\` did not return explicit steps (${wikiHow.error || "no_match"}).`,
      );
      lines.push("");
      lines.push(
        `Fallback web search for \`${query}\` should use ${providerSummary} and reciprocal rank fusion (k = ${webSearchRrfK()}).`,
      );
    }
  }
  if (!evidence.includes("procedural_how_to:stage:web_search")) {
    evidence.push("procedural_how_to:stage:web_search");
    evidence.push(`web_search:request:${query}`);
    for (const provider of WEB_SEARCH_PROVIDERS) {
      evidence.push(`web_search:provider:${provider.id}`);
    }
    evidence.push(`web_search:combined:rrf:k=${webSearchRrfK()}`);
  }
  evidence.push("procedural_how_to:stage:recursive_fetch_check");
  evidence.push("procedural_how_to:source_gate:explicit_steps_only");

  return {
    intent: "procedural_how_to",
    content: lines.join("\n"),
    confidence,
    evidence,
    diagnostics,
    query,
    wikihowCandidate: pageTitle,
    formalizedObject,
  };
}

function stripHtml(value) {
  return String(value || "")
    .replace(/<[^>]*>/g, "")
    .replace(/\s+/g, " ")
    .trim();
}

function wikipediaPageUrl(language, key) {
  const lang = language && WIKIPEDIA_SEARCH_HOSTS[language] ? language : "en";
  const slug = encodeURIComponent(String(key || "")).replace(/%2F/gi, "/");
  return `https://${lang}.wikipedia.org/wiki/${slug}`;
}

async function searchWikipediaPages(query, language, limit) {
  if (typeof fetch !== "function") return null;
  const apiHeaders = {
    accept: "application/json",
    "api-user-agent":
      "formal-ai-demo (https://github.com/link-assistant/formal-ai)",
  };
  const ordered = [language, "en"].filter(
    (value, index, array) => value && array.indexOf(value) === index,
  );
  for (const lang of ordered) {
    const base = WIKIPEDIA_SEARCH_HOSTS[lang] || WIKIPEDIA_SEARCH_HOSTS.en;
    const url = `${base}?q=${encodeURIComponent(query)}&limit=${limit || 5}`;
    try {
      const response = await fetch(url, { headers: apiHeaders });
      if (!response || !response.ok) continue;
      const data = await response.json();
      if (!data || !Array.isArray(data.pages) || data.pages.length === 0) {
        continue;
      }
      return {
        language: lang,
        pages: data.pages.slice(0, limit || 5).map((page) => ({
          title: String(page.title || page.key || "Untitled"),
          url: wikipediaPageUrl(lang, page.key || page.title || ""),
          excerpt: stripHtml(page.excerpt || page.description || ""),
        })),
      };
    } catch (_error) {
      // Try the next language host.
    }
  }
  return null;
}

const FRAME_POLICY_CHECK_ENDPOINT = "https://api.microlink.io/";

function framePolicyCheckUrl(url) {
  const params = new URLSearchParams({ url });
  return `${FRAME_POLICY_CHECK_ENDPOINT}?${params.toString()}`;
}

function currentEmbedderOrigin() {
  try {
    const origin = self && self.location && self.location.origin;
    return origin && origin !== "null" ? origin : "";
  } catch (_error) {
    return "";
  }
}

function isPrivateOrLocalHostname(hostname) {
  const host = String(hostname || "").toLowerCase();
  if (
    !host ||
    host === "localhost" ||
    host.endsWith(".localhost") ||
    host.endsWith(".local")
  ) {
    return true;
  }
  if (host === "::1" || host === "[::1]") {
    return true;
  }
  const parts = host.split(".");
  if (parts.length !== 4 || parts.some((part) => !/^\d+$/.test(part))) {
    return false;
  }
  const octets = parts.map((part) => Number(part));
  if (octets.some((part) => part < 0 || part > 255)) return false;
  const [first, second] = octets;
  return (
    first === 10 ||
    first === 127 ||
    (first === 172 && second >= 16 && second <= 31) ||
    (first === 192 && second === 168) ||
    (first === 169 && second === 254)
  );
}

function isPublicHttpUrl(url) {
  try {
    const parsed = new URL(url);
    return (
      (parsed.protocol === "http:" || parsed.protocol === "https:") &&
      !isPrivateOrLocalHostname(parsed.hostname)
    );
  } catch (_error) {
    return false;
  }
}

function normalizeFramePolicyHeaders(headers) {
  const normalized = {};
  for (const [key, value] of Object.entries(headers || {})) {
    const name = String(key || "").toLowerCase();
    if (name !== "x-frame-options" && name !== "content-security-policy") {
      continue;
    }
    normalized[name] = Array.isArray(value)
      ? value.map((item) => String(item || "")).join(", ")
      : String(value || "");
  }
  return normalized;
}

function frameAncestorsSourceSets(csp) {
  const sourceSets = [];
  for (const policy of String(csp || "").split(",")) {
    for (const directive of policy.split(";")) {
      const trimmed = directive.trim();
      if (!/^frame-ancestors(?:\s|$)/i.test(trimmed)) continue;
      const sources = trimmed
        .replace(/^frame-ancestors/i, "")
        .trim()
        .split(/\s+/)
        .filter(Boolean);
      sourceSets.push(sources);
    }
  }
  return sourceSets;
}

function sourceExpressionMatches(source, targetUrl, embedderUrl) {
  const token = String(source || "").trim().toLowerCase();
  if (!token || token === "'none'") return false;
  if (token === "*") return true;
  if (token === "'self'") return embedderUrl.origin === targetUrl.origin;
  if (/^[a-z][a-z0-9+.-]*:$/.test(token)) {
    return embedderUrl.protocol === token;
  }

  let candidate = token;
  if (!candidate.includes("://")) {
    candidate = `${targetUrl.protocol}//${candidate}`;
  }
  let parsed;
  try {
    parsed = new URL(candidate);
  } catch (_error) {
    return false;
  }
  if (parsed.protocol !== embedderUrl.protocol) return false;
  if (parsed.port && parsed.port !== "*" && parsed.port !== embedderUrl.port) {
    return false;
  }
  const host = parsed.hostname.toLowerCase();
  const embedderHost = embedderUrl.hostname.toLowerCase();
  if (host.startsWith("*.")) {
    const suffix = host.slice(2);
    return embedderHost.endsWith(`.${suffix}`);
  }
  return embedderHost === host;
}

function evaluateFramePolicy(headers, targetUrl, embedderOrigin) {
  const frameHeaders = normalizeFramePolicyHeaders(headers);
  const xFrameOptions = frameHeaders["x-frame-options"] || "";
  const csp = frameHeaders["content-security-policy"] || "";
  let target;
  try {
    target = new URL(targetUrl);
  } catch (_error) {
    return { status: "unknown", reason: "the target URL could not be parsed" };
  }

  const xFrameDirectives = xFrameOptions
    .split(",")
    .map((part) => part.trim().toLowerCase())
    .filter(Boolean);
  const sourceSets = frameAncestorsSourceSets(csp);
  const cspHasFrameAncestorsNone = sourceSets.some((sources) =>
    sources.includes("'none'"),
  );
  if (xFrameDirectives.includes("deny")) {
    return {
      status: "blocked",
      reason: cspHasFrameAncestorsNone
        ? "the page sends X-Frame-Options: DENY and CSP frame-ancestors 'none'"
        : "the page sends X-Frame-Options: DENY",
    };
  }
  if (xFrameDirectives.includes("sameorigin")) {
    let embedder;
    try {
      embedder = embedderOrigin ? new URL(embedderOrigin) : null;
    } catch (_error) {
      embedder = null;
    }
    if (!embedder || embedder.origin !== target.origin) {
      return {
        status: "blocked",
        reason: "the page sends X-Frame-Options: SAMEORIGIN",
      };
    }
  }

  if (sourceSets.length > 0) {
    let embedder;
    try {
      embedder = embedderOrigin ? new URL(embedderOrigin) : null;
    } catch (_error) {
      embedder = null;
    }
    if (!embedder) {
      return {
        status: "unknown",
        reason: "the current web app origin is unavailable",
      };
    }
    for (const sources of sourceSets) {
      if (sources.includes("'none'")) {
        return {
          status: "blocked",
          reason: "the page sends CSP frame-ancestors 'none'",
        };
      }
      if (
        sources.length > 0 &&
        !sources.some((source) => sourceExpressionMatches(source, target, embedder))
      ) {
        return {
          status: "blocked",
          reason:
            "the page's CSP frame-ancestors directive does not include this web app",
        };
      }
    }
  }

  return {
    status: "allowed",
    reason: "no blocking X-Frame-Options or CSP frame-ancestors policy was detected",
  };
}

async function detectFramePolicy(url) {
  const evidence = [`url_preview:frame_policy_check:${FRAME_POLICY_CHECK_ENDPOINT}`];
  if (typeof fetch !== "function") {
    return {
      status: "unknown",
      reason: "browser fetch is not available",
      evidence: evidence.concat("url_preview:frame_policy:unknown"),
    };
  }
  if (!isPublicHttpUrl(url)) {
    return {
      status: "unknown",
      reason: "only public HTTP(S) URLs are checked by the frame-policy service",
      evidence: evidence.concat("url_preview:frame_policy:unknown"),
    };
  }

  try {
    const response = await fetch(framePolicyCheckUrl(url), {
      method: "GET",
      mode: "cors",
      credentials: "omit",
    });
    evidence.push(`url_preview:frame_policy_status:${response.status}`);
    if (!response.ok) {
      return {
        status: "unknown",
        reason: `the frame-policy service returned HTTP ${response.status}`,
        evidence: evidence.concat("url_preview:frame_policy:unknown"),
      };
    }
    const data = await response.json();
    const headers = (data && (data.headers || (data.data && data.data.headers))) || null;
    if (!headers || typeof headers !== "object") {
      return {
        status: "unknown",
        reason: "the frame-policy service did not return response headers",
        evidence: evidence.concat("url_preview:frame_policy:unknown"),
      };
    }
    const verdict = evaluateFramePolicy(headers, url, currentEmbedderOrigin());
    return {
      ...verdict,
      evidence: evidence.concat(`url_preview:frame_policy:${verdict.status}`),
    };
  } catch (_error) {
    return {
      status: "unknown",
      reason: "the frame-policy service could not be reached from this browser",
      evidence: evidence.concat("url_preview:frame_policy:unknown"),
    };
  }
}

function directExternalLinkAnswer(url, framePolicy, leadingLine) {
  const lines = [leadingLine || `I suggest opening this in a new tab: [${url}](${url}).`, ""];
  if (framePolicy && framePolicy.status === "blocked") {
    lines.push(
      `I checked the page's frame policy, and it does not allow embedding here because ${framePolicy.reason}.`,
    );
  } else if (framePolicy && framePolicy.status === "unknown") {
    lines.push(
      `I could not verify that this page allows embedding here because ${framePolicy.reason}.`,
    );
  } else {
    lines.push("I could not verify that this page allows embedding here.");
  }
  lines.push(
    "Browser JavaScript also cannot read the page content directly unless the site allows CORS, so the direct external link is the reliable option.",
  );
  return lines.join("\n");
}

async function tryFetch(prompt) {
  const normalized = normalizePrompt(prompt);
  const url = extractHttpFetchUrl(prompt, normalized);
  if (!url) return null;

  const evidence = [`http_fetch:request:${url}`];

  if (typeof fetch !== "function") {
    return {
      intent: "http_fetch",
      content: `HTTP fetch is not available in this environment.\n\nURL: [${url}](${url})`,
      confidence: 0.5,
      evidence,
      iframeUrl: url,
    };
  }

  try {
    const response = await fetch(url, { method: "GET", mode: "cors" });
    const status = response.status;
    const contentType = response.headers.get("content-type") || "";
    let body = "";
    if (contentType.includes("text/") || contentType.includes("application/json")) {
      const text = await response.text();
      body = text.length > 2000 ? `${text.slice(0, 2000)}\n\n*(truncated — ${text.length} bytes total)*` : text;
    }
    evidence.push(`http_fetch:status:${status}`);
    const lines = [
      `Fetched \`${url}\` — status **${status}**.`,
      "",
    ];
    if (body) {
      lines.push("Response body:");
      lines.push("```");
      lines.push(body);
      lines.push("```");
    } else {
      lines.push(`Content-Type: \`${contentType || "unknown"}\` — binary or empty body, not shown.`);
      lines.push("");
      lines.push(`You can view this URL directly: [${url}](${url})`);
    }
    return {
      intent: "http_fetch",
      content: lines.join("\n"),
      confidence: 0.95,
      evidence,
      iframeUrl: null,
    };
  } catch (err) {
    // CORS block or network failure. Check target frame policy before choosing
    // between an iframe preview and a direct external link.
    const isCors =
      err instanceof TypeError &&
      (err.message.toLowerCase().includes("cors") ||
        err.message.toLowerCase().includes("network") ||
        err.message.toLowerCase().includes("failed to fetch"));
    evidence.push(`http_fetch:error:${isCors ? "cors" : "network"}`);
    const framePolicy = await detectFramePolicy(url);
    evidence.push(...framePolicy.evidence);
    const fetchFailureLine = `Could not fetch \`${url}\` directly${isCors ? " (CORS restriction)" : " (network error)"}.`;
    if (framePolicy.status !== "allowed") {
      evidence.push(`url_preview:external_link:${url}`);
      return {
        intent: "http_fetch",
        content: directExternalLinkAnswer(
          url,
          framePolicy,
          `${fetchFailureLine}\n\nI suggest opening this in a new tab: [${url}](${url}).`,
        ),
        confidence: 0.75,
        evidence,
        iframeUrl: null,
      };
    }
    evidence.push(`url_preview:iframe:${url}`);
    const lines = [
      fetchFailureLine,
      "",
      "I checked the page's frame policy and can show it in the embedded frame below.",
    ];
    return {
      intent: "http_fetch",
      content: lines.join("\n"),
      confidence: 0.8,
      evidence,
      iframeUrl: url,
    };
  }
}

async function tryUrlNavigate(prompt) {
  const normalized = normalizePrompt(prompt);
  const url = extractUrlNavigateUrl(prompt, normalized);
  if (!url) return null;

  const evidence = [`url_navigate:request:${url}`];
  const framePolicy = await detectFramePolicy(url);
  evidence.push(...framePolicy.evidence);
  if (framePolicy.status !== "allowed") {
    evidence.push(`url_preview:external_link:${url}`);
    return {
      intent: "url_navigate",
      content: directExternalLinkAnswer(url, framePolicy),
      confidence: 0.95,
      evidence,
      iframeUrl: null,
    };
  }

  evidence.push(`url_preview:iframe:${url}`);
  const lines = [
    "I checked the page's frame policy and can show it here.",
    "",
    `Direct link: [${url}](${url}).`,
  ];

  return {
    intent: "url_navigate",
    content: lines.join("\n"),
    confidence: 0.95,
    evidence,
    iframeUrl: url,
  };
}

// Reciprocal Rank Fusion constant — Cormack et al. 2009 use k = 60 and we
// match that so combined ranks stay comparable across the CLI, server, and
// browser surfaces (issue #133).
//
// The authoritative value lives in `web_search_core::WEB_SEARCH_RRF_K` and is
// fetched from the WASM worker once it boots; the JS constants below are
// pre-WASM fallbacks used during init() and on browsers where the worker
// could not instantiate. The Rust→WASM port is the source of truth (R194).
const WEB_SEARCH_RRF_K_FALLBACK = 60;
const WEB_SEARCH_CONCURRENCY_FALLBACK = 5;
const WEB_SEARCH_PROVIDER_LIMIT_FALLBACK = 10;

const WEB_SEARCH_TEXT_ENCODER = new TextEncoder();
const WEB_SEARCH_TEXT_DECODER = new TextDecoder();

function webSearchRrfK() {
  if (wasm && typeof wasm.web_search_rrf_k === "function") {
    return wasm.web_search_rrf_k() >>> 0;
  }
  return WEB_SEARCH_RRF_K_FALLBACK;
}

function webSearchConcurrency() {
  if (wasm && typeof wasm.web_search_concurrency_per_category === "function") {
    return wasm.web_search_concurrency_per_category() >>> 0;
  }
  return WEB_SEARCH_CONCURRENCY_FALLBACK;
}

function webSearchProviderLimit() {
  if (wasm && typeof wasm.web_search_provider_limit === "function") {
    return wasm.web_search_provider_limit() >>> 0;
  }
  return WEB_SEARCH_PROVIDER_LIMIT_FALLBACK;
}

function wasmWriteInput(text) {
  if (!wasm || typeof wasm.input_ptr !== "function") return -1;
  const bytes = WEB_SEARCH_TEXT_ENCODER.encode(text);
  const capacity =
    typeof wasm.input_capacity === "function" ? wasm.input_capacity() : bytes.length;
  if (bytes.length > capacity) return -1;
  const view = new Uint8Array(wasm.memory.buffer, wasm.input_ptr(), bytes.length);
  view.set(bytes);
  return bytes.length;
}

function wasmReadOutput(length) {
  if (!wasm || typeof wasm.output_ptr !== "function" || length <= 0) return "";
  const view = new Uint8Array(wasm.memory.buffer, wasm.output_ptr(), length);
  return WEB_SEARCH_TEXT_DECODER.decode(view);
}

// Engine-core bridges (R194 follow-up). Each function returns a value when
// the WASM core is available, or `null` so the caller can fall back to the
// pure-JS branch. Keeping a JS fallback covers offline mode and old browsers
// where `WebAssembly.instantiate` is unavailable, but the canonical answer
// always comes from Rust when the worker booted successfully.
function wasmNormalizePrompt(text) {
  if (!wasm || typeof wasm.engine_normalize_prompt !== "function") return null;
  const length = wasmWriteInput(String(text || ""));
  if (length < 0) return null;
  const written = wasm.engine_normalize_prompt(length) >>> 0;
  return wasmReadOutput(written);
}

function wasmDetectLanguage(text) {
  if (!wasm || typeof wasm.engine_detect_language !== "function") return null;
  const length = wasmWriteInput(String(text || ""));
  if (length < 0) return null;
  const written = wasm.engine_detect_language(length) >>> 0;
  const slug = wasmReadOutput(written);
  return slug || null;
}

// Returns `{ ok: true, value }` on success, `{ ok: false, error }` on parse
// or runtime failure (division by zero, overflow). `null` means the WASM core
// is unavailable — the caller should fall back to the JS parser.
function wasmEvaluateArithmetic(expression) {
  if (!wasm || typeof wasm.engine_evaluate_arithmetic !== "function") return null;
  const length = wasmWriteInput(String(expression || ""));
  if (length < 0) return null;
  const written = wasm.engine_evaluate_arithmetic(length) >>> 0;
  if (written === 0) return null;
  const text = wasmReadOutput(written);
  if (text.startsWith("ERR:")) {
    return { ok: false, error: text.slice(4) };
  }
  return { ok: true, value: text };
}

function wasmStableId(prefix, value) {
  if (!wasm || typeof wasm.engine_stable_id !== "function") return null;
  const payload = `${String(prefix || "")}\n${String(value || "")}`;
  const length = wasmWriteInput(payload);
  if (length < 0) return null;
  const written = wasm.engine_stable_id(length) >>> 0;
  return wasmReadOutput(written) || null;
}

function wasmSelectUnknownOpener(prompt, language) {
  if (!wasm || typeof wasm.engine_select_unknown_opener !== "function") return null;
  const payload = `${String(language || "")}\n${String(prompt || "")}`;
  const length = wasmWriteInput(payload);
  if (length < 0) return null;
  const written = wasm.engine_select_unknown_opener(length) >>> 0;
  return wasmReadOutput(written) || null;
}

function serializeIntentRouteForWasm(normalized, rawPrompt, route) {
  const lines = [String(normalized || ""), String(rawPrompt || "")];
  const append = (kind, value) => {
    const text = String(value || "");
    if (text && !/[\t\r\n]/.test(text)) lines.push(`${kind}\t${text}`);
  };
  for (const value of route.keywords || []) append("K", value);
  for (const value of route.phrases || []) append("P", value);
  for (const value of route.tokens || []) append("T", value);
  for (const combo of route.combos || []) {
    if (!Array.isArray(combo) || combo.length === 0) continue;
    const fields = combo
      .map((value) => String(value || ""))
      .filter((value) => value && !/[\t\r\n]/.test(value));
    if (fields.length > 0) lines.push(`C\t${fields.join("\t")}`);
  }
  return lines.join("\n");
}

function wasmMatchIntentRoute(normalized, rawPrompt, route) {
  if (!wasm || typeof wasm.engine_match_intent_route !== "function") return null;
  const length = wasmWriteInput(
    serializeIntentRouteForWasm(normalized, rawPrompt, route),
  );
  if (length < 0) return null;
  return (wasm.engine_match_intent_route(length) >>> 0) === 1;
}

// Delegates to `web_search_request_evidence` when the WASM core is loaded;
// otherwise returns null so the caller can fall back to the JS list. The
// Rust side owns the canonical evidence shape (issue #133 R194).
function wasmWebSearchRequestEvidence(query, language) {
  if (!wasm || typeof wasm.web_search_request_evidence !== "function") return null;
  const payload = `${String(query || "")}\n${String(language || "")}`;
  const length = wasmWriteInput(payload);
  if (length < 0) return null;
  const written = wasm.web_search_request_evidence(length) >>> 0;
  if (written === 0) return null;
  const text = wasmReadOutput(written);
  return text ? text.split("\n") : null;
}

// Delegates to `web_search_fuse`. Returns the fused entries array or null when
// WASM is unavailable / the payload exceeds the static INPUT buffer.
function wasmReciprocalRankFusion(perProviderResults) {
  if (!wasm || typeof wasm.web_search_fuse !== "function") return null;
  const rows = [];
  for (const provider of perProviderResults) {
    const id = String(provider.id || "");
    const list = Array.isArray(provider.results) ? provider.results : [];
    list.forEach((item, index) => {
      if (!item || !item.url) return;
      const rank = index + 1;
      const title = String(item.title || item.url).replace(/[\t\n]/g, " ");
      const excerpt = String(item.excerpt || "").replace(/[\t\n]/g, " ");
      const url = String(item.url).replace(/[\t\n]/g, " ");
      rows.push(`${id}\t${rank}\t${url}\t${title}\t${excerpt}`);
    });
  }
  if (rows.length === 0) return [];
  const length = wasmWriteInput(rows.join("\n"));
  if (length < 0) return null;
  const written = wasm.web_search_fuse(length) >>> 0;
  if (written === 0) return [];
  const text = wasmReadOutput(written);
  if (!text) return [];
  return parseFusedOutput(text);
}

// Parse the `serialize_rrf_output` format: one entry per line, fields
// separated by tabs, providers serialised as `id#rank` joined by `;`. The
// shape matches `web_search_core::serialize_rrf_output`.
function parseFusedOutput(text) {
  return text
    .split("\n")
    .filter((line) => line.length > 0)
    .map((line) => {
      const fields = line.split("\t");
      const url = fields[0] || "";
      const title = fields[1] || url;
      const excerpt = fields[2] || "";
      const score = Number.parseFloat(fields[3] || "0") || 0;
      const providerSpecs = (fields[4] || "")
        .split("+")
        .filter((part) => part.length > 0)
        .map((part) => {
          const hash = part.lastIndexOf("#");
          if (hash < 0) return { id: part, rank: 0 };
          return {
            id: part.slice(0, hash),
            rank: Number.parseInt(part.slice(hash + 1), 10) || 0,
          };
        });
      return { url, title, excerpt, score, providers: providerSpecs };
    });
}

// Session-scoped CORS disable list. When a provider fetch throws a CORS or
// network error we record the timestamp so the planner skips it for the rest
// of the session and records the decision in memory. Issue #180: we also
// pre-probe every provider once per session so the first user query does not
// pay for failed sockets — the result is cached in `WEB_SEARCH_AVAILABLE`
// alongside the disable list.
const WEB_SEARCH_DISABLED = new Map();
const WEB_SEARCH_AVAILABLE = new Map();
const WEB_SEARCH_DIAGNOSTICS = [];
let WEB_SEARCH_PROBE_PROMISE = null;

function webSearchDisable(providerId, reason) {
  if (!WEB_SEARCH_DISABLED.has(providerId)) {
    WEB_SEARCH_DISABLED.set(providerId, { reason, at: Date.now() });
  }
}

function webSearchIsDisabled(providerId) {
  return WEB_SEARCH_DISABLED.has(providerId);
}

function webSearchMarkAvailable(providerId, info) {
  WEB_SEARCH_AVAILABLE.set(providerId, Object.assign({ at: Date.now() }, info || {}));
  WEB_SEARCH_DISABLED.delete(providerId);
}

// Issue #180: record a single HTTP exchange so the diagnostics panel can
// surface the raw request/response/conversion trace. We keep a small ring
// buffer in RAM so very long sessions do not bloat memory.
const WEB_SEARCH_DIAG_LIMIT = 64;
function recordWebSearchDiagnostic(entry) {
  if (!entry || typeof entry !== "object") return;
  WEB_SEARCH_DIAGNOSTICS.push(entry);
  while (WEB_SEARCH_DIAGNOSTICS.length > WEB_SEARCH_DIAG_LIMIT) {
    WEB_SEARCH_DIAGNOSTICS.shift();
  }
}

function consumeWebSearchDiagnostics() {
  if (WEB_SEARCH_DIAGNOSTICS.length === 0) return [];
  const snapshot = WEB_SEARCH_DIAGNOSTICS.slice();
  WEB_SEARCH_DIAGNOSTICS.length = 0;
  return snapshot;
}

async function fetchProviderJson(providerId, url, options) {
  if (typeof fetch !== "function") {
    webSearchDisable(providerId, "no_fetch");
    recordWebSearchDiagnostic({
      providerId,
      url,
      method: (options && options.method) || "GET",
      requestHeaders: (options && options.headers) || null,
      ok: false,
      error: "fetch unavailable",
    });
    return { ok: false, error: "fetch unavailable", finalUrl: url };
  }
  const startedAt = Date.now();
  try {
    const response = await fetch(url, options || { mode: "cors" });
    const status = response ? response.status : 0;
    const statusText = response ? response.statusText : "";
    if (!response || !response.ok) {
      recordWebSearchDiagnostic({
        providerId,
        url,
        method: (options && options.method) || "GET",
        requestHeaders: (options && options.headers) || null,
        ok: false,
        status,
        statusText,
        elapsedMs: Date.now() - startedAt,
      });
      return { ok: false, status, statusText, finalUrl: url };
    }
    const text = await response.text();
    let data = null;
    try {
      data = text ? JSON.parse(text) : null;
    } catch (parseError) {
      const message = parseError instanceof Error ? parseError.message : String(parseError);
      recordWebSearchDiagnostic({
        providerId,
        url,
        method: (options && options.method) || "GET",
        requestHeaders: (options && options.headers) || null,
        ok: false,
        status,
        statusText,
        elapsedMs: Date.now() - startedAt,
        responseSnippet: text.slice(0, 1024),
        error: `parse_error: ${message}`,
      });
      return { ok: false, error: `parse_error: ${message}`, finalUrl: url };
    }
    webSearchMarkAvailable(providerId, { status });
    recordWebSearchDiagnostic({
      providerId,
      url,
      method: (options && options.method) || "GET",
      requestHeaders: (options && options.headers) || null,
      ok: true,
      status,
      statusText,
      elapsedMs: Date.now() - startedAt,
      responseSnippet: text.length > 4096 ? `${text.slice(0, 4096)}…` : text,
      responseBytes: text.length,
    });
    return { ok: true, status, data, finalUrl: url };
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    const isCors =
      message.toLowerCase().includes("cors") ||
      message.toLowerCase().includes("network") ||
      message.toLowerCase().includes("failed to fetch");
    webSearchDisable(providerId, isCors ? "cors" : "network");
    recordWebSearchDiagnostic({
      providerId,
      url,
      method: (options && options.method) || "GET",
      requestHeaders: (options && options.headers) || null,
      ok: false,
      elapsedMs: Date.now() - startedAt,
      error: message,
      cors: isCors,
    });
    return { ok: false, error: message, finalUrl: url, cors: isCors };
  }
}

// Issue #180: shared text-shaping helpers used by every web-search provider so
// the rendered bullet looks consistent regardless of which provider produced
// the entry. `extractDomain` returns the bare host (without `www.`),
// `extractQuoteAroundQuery` walks the response body and returns a short
// Google-style snippet that contains the original query word when possible,
// and `escapeRegExp` is the standard helper used by the snippet picker.
function escapeRegExp(value) {
  return String(value || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

function extractDomain(url) {
  const raw = String(url || "").trim();
  if (!raw) return "";
  try {
    const u = new URL(raw);
    return u.hostname.replace(/^www\./i, "");
  } catch (_error) {
    const match = raw.match(/^[a-z][a-z0-9+.\-]*:\/\/([^\/?#]+)/i);
    if (match) return match[1].replace(/^www\./i, "");
    return "";
  }
}

function extractQuoteAroundQuery(text, query, maxChars) {
  const max = typeof maxChars === "number" && maxChars > 0 ? Math.floor(maxChars) : 200;
  const raw = String(text || "").replace(/\s+/g, " ").trim();
  if (!raw) return "";
  if (raw.length <= max) return raw;
  const q = String(query || "").trim();
  if (q) {
    const candidates = [q, ...q.split(/\s+/)].filter((value, index, array) =>
      value && array.indexOf(value) === index,
    );
    for (const candidate of candidates) {
      if (!candidate || candidate.length < 2) continue;
      const re = new RegExp(escapeRegExp(candidate), "i");
      const match = raw.match(re);
      if (match && typeof match.index === "number") {
        const half = Math.max(20, Math.floor((max - candidate.length) / 2));
        let start = Math.max(0, match.index - half);
        let end = Math.min(raw.length, start + max);
        if (start > 0) {
          const space = raw.lastIndexOf(" ", start);
          if (space > 0 && match.index - space <= half + 20) start = space + 1;
        }
        if (end < raw.length) {
          const space = raw.indexOf(" ", end);
          if (space > 0 && space - start <= max + 40) end = space;
        }
        let snippet = raw.slice(start, end).trim();
        if (start > 0) snippet = "… " + snippet;
        if (end < raw.length) snippet = snippet + " …";
        return snippet;
      }
    }
  }
  let cut = raw.slice(0, max);
  const lastPeriod = Math.max(
    cut.lastIndexOf(". "),
    cut.lastIndexOf("! "),
    cut.lastIndexOf("? "),
    cut.lastIndexOf("。"),
  );
  if (lastPeriod > max * 0.5) return cut.slice(0, lastPeriod + 1).trim();
  const lastSpace = cut.lastIndexOf(" ");
  if (lastSpace > max * 0.5) cut = cut.slice(0, lastSpace);
  return cut.trim() + " …";
}

const PROVIDER_DISPLAY_LABELS = {
  duckduckgo: "DuckDuckGo",
  "internet-archive": "Internet Archive",
  wikipedia: "Википедия",
  wikidata: "Викидата",
  wiktionary: "Викисловарь",
};

const PROVIDER_DISPLAY_LABELS_BY_LANG = {
  en: {
    duckduckgo: "DuckDuckGo",
    "internet-archive": "Internet Archive",
    wikipedia: "Wikipedia",
    wikidata: "Wikidata",
    wiktionary: "Wiktionary",
  },
  ru: {
    duckduckgo: "DuckDuckGo",
    "internet-archive": "Архив Интернета",
    wikipedia: "Википедия",
    wikidata: "Викидата",
    wiktionary: "Викисловарь",
  },
  zh: {
    duckduckgo: "DuckDuckGo",
    "internet-archive": "互联网档案馆",
    wikipedia: "维基百科",
    wikidata: "维基数据",
    wiktionary: "维基词典",
  },
  hi: {
    duckduckgo: "DuckDuckGo",
    "internet-archive": "इंटरनेट आर्काइव",
    wikipedia: "विकिपीडिया",
    wikidata: "विकिडेटा",
    wiktionary: "विक्षनरी",
  },
};

function providerDisplayLabel(providerId, language) {
  const code = String(language || "").toLowerCase().slice(0, 2);
  const table = PROVIDER_DISPLAY_LABELS_BY_LANG[code] || PROVIDER_DISPLAY_LABELS_BY_LANG.en;
  return table[providerId] || PROVIDER_DISPLAY_LABELS[providerId] || providerId;
}

async function searchDuckDuckGo(query, language, limit) {
  // DuckDuckGo Instant Answer — CORS-readable, no key. Returns the abstract
  // and a flat list of related-topic links. We treat the abstract link plus
  // the related topics as the ranked result list (issue #133).
  //
  // Issue #153: the previous signature was (query, limit) but the dispatcher
  // calls every provider as (query, language, providerLimit). That meant
  // `limit` was set to a 2-letter language code like "en", and
  // `results.slice(0, "en")` silently returned an empty array, so DuckDuckGo
  // contributed nothing to the fused ranking.
  const cap = typeof limit === "number" && Number.isFinite(limit) && limit > 0
    ? Math.floor(limit)
    : 5;
  const params = ["q=" + encodeURIComponent(query), "format=json", "no_redirect=1", "no_html=1"];
  if (language && /^[a-z]{2,3}$/i.test(language) && language !== "en") {
    // DuckDuckGo accepts a `kl` region hint (lowercase locale). We do not
    // require a region/country code so a bare language is treated as the
    // canonical locale for that language; failing that, DDG falls back to
    // English content gracefully.
    params.push("kl=" + encodeURIComponent(`${language}-${language}`));
  }
  const url = "https://api.duckduckgo.com/?" + params.join("&");
  const outcome = await fetchProviderJson("duckduckgo", url);
  if (!outcome.ok || !outcome.data) {
    return { ok: false, results: [], finalUrl: outcome.finalUrl, error: outcome.error };
  }
  const data = outcome.data;
  const results = [];
  if (data.AbstractURL && data.AbstractText) {
    results.push({
      title: data.Heading || query,
      url: data.AbstractURL,
      excerpt: stripHtml(data.AbstractText),
    });
  }
  const topics = Array.isArray(data.RelatedTopics) ? data.RelatedTopics : [];
  for (const topic of topics) {
    if (!topic) continue;
    if (topic.FirstURL && topic.Text) {
      results.push({
        title: topic.Text.split(" - ")[0] || topic.Text,
        url: topic.FirstURL,
        excerpt: stripHtml(topic.Text),
      });
    } else if (Array.isArray(topic.Topics)) {
      for (const inner of topic.Topics) {
        if (inner && inner.FirstURL && inner.Text) {
          results.push({
            title: inner.Text.split(" - ")[0] || inner.Text,
            url: inner.FirstURL,
            excerpt: stripHtml(inner.Text),
          });
        }
      }
    }
    if (results.length >= cap) break;
  }
  return { ok: true, results: results.slice(0, cap), finalUrl: outcome.finalUrl };
}

async function searchWikipediaWebProvider(query, language, limit) {
  // Reuse the existing helper but adapt the shape to {title, url, excerpt}.
  const result = await searchWikipediaPages(query, language, limit);
  if (!result || !Array.isArray(result.pages)) {
    return { ok: false, results: [], finalUrl: "", language: language || "en" };
  }
  // R194/issue-153: thread the Wikipedia page key through so cross-source
  // deduplication can match `Apple_(disambiguation)` against the Wikidata
  // sitelink `enwiki: Apple_(disambiguation)` even if the URLs disagree on
  // percent-encoding.
  const results = result.pages.slice(0, limit).map((page) => ({
    title: page.title,
    url: page.url,
    excerpt: page.excerpt,
    wikipediaKey: page.key || page.title || "",
    wikipediaLanguage: result.language,
    virtualId: `WP:${page.key || page.title || query}`,
    sourceKind: "wikipedia",
  }));
  return {
    ok: true,
    results,
    language: result.language,
    finalUrl: `https://${result.language}.wikipedia.org/w/rest.php/v1/search/page?q=${encodeURIComponent(query)}`,
  };
}

async function searchWikidataEntities(query, language, limit) {
  const lang = language && /^[a-z]{2,3}$/i.test(language) ? language : "en";
  // R194/issue-153: request `sitelinks/urls` so each entity carries its
  // Wikipedia URL inline. We use that to merge entries returned by the
  // Wikipedia provider with the same entity (otherwise the user sees the
  // same fact as two bullets — "Apple" via Wikidata Q89 and "Apple" via
  // enwiki).
  const url =
    "https://www.wikidata.org/w/api.php?action=wbsearchentities&search=" +
    encodeURIComponent(query) +
    "&language=" +
    encodeURIComponent(lang) +
    "&format=json&origin=*&props=sitelinks/urls&limit=" +
    encodeURIComponent(limit);
  const outcome = await fetchProviderJson("wikidata", url);
  if (!outcome.ok || !outcome.data || !Array.isArray(outcome.data.search)) {
    return { ok: false, results: [], finalUrl: outcome.finalUrl, error: outcome.error };
  }
  const results = outcome.data.search.slice(0, limit).map((entry) => {
    const sitelinks = entry.sitelinks && typeof entry.sitelinks === "object"
      ? entry.sitelinks
      : {};
    const wikipediaLang = sitelinks[`${lang}wiki`] ? lang : "en";
    const wikipediaEntry =
      sitelinks[`${wikipediaLang}wiki`] || sitelinks.enwiki || null;
    const wikipediaUrl = wikipediaEntry && wikipediaEntry.url
      ? wikipediaEntry.url
      : "";
    const wikipediaKey = wikipediaEntry && wikipediaEntry.title
      ? String(wikipediaEntry.title).replace(/\s+/g, "_")
      : "";
    return {
      title: entry.label || entry.id || query,
      url: entry.concepturi || `https://www.wikidata.org/wiki/${entry.id}`,
      excerpt: stripHtml(entry.description || ""),
      qid: entry.id || "",
      virtualId: entry.id || "",
      sourceKind: "wikidata",
      wikipediaUrl,
      wikipediaKey,
      wikipediaLanguage: wikipediaEntry ? wikipediaLang : "",
    };
  });
  return { ok: true, results, finalUrl: outcome.finalUrl };
}

async function searchInternetArchive(query, language, limit) {
  // Issue #153: archive.org publishes a CORS-enabled `advancedsearch.php`
  // endpoint that returns ranked results across the entire collection (web
  // captures, books, audio, software, ...). This complements the DuckDuckGo
  // Instant Answer (which mostly returns a single Wikipedia abstract) and
  // gives the agent another general-purpose web search fallback to draw on
  // when the structured providers (Wikidata/Wikipedia) miss the query.
  const cap = typeof limit === "number" && Number.isFinite(limit) && limit > 0
    ? Math.floor(limit)
    : 5;
  const params = [
    "q=" + encodeURIComponent(query),
    "fl%5B%5D=identifier",
    "fl%5B%5D=title",
    "fl%5B%5D=description",
    "fl%5B%5D=creator",
    "sort%5B%5D=" + encodeURIComponent("downloads desc"),
    "rows=" + encodeURIComponent(cap),
    "page=1",
    "output=json",
  ];
  const url = "https://archive.org/advancedsearch.php?" + params.join("&");
  const outcome = await fetchProviderJson("internet-archive", url);
  if (
    !outcome.ok ||
    !outcome.data ||
    !outcome.data.response ||
    !Array.isArray(outcome.data.response.docs)
  ) {
    return { ok: false, results: [], finalUrl: outcome.finalUrl, error: outcome.error };
  }
  const docs = outcome.data.response.docs;
  const results = docs.slice(0, cap).map((doc) => {
    const identifier = doc.identifier || "";
    const description = Array.isArray(doc.description)
      ? doc.description.join(" • ")
      : (doc.description || "");
    const creator = Array.isArray(doc.creator)
      ? doc.creator.join(", ")
      : (doc.creator || "");
    const excerpt = stripHtml(creator ? `${creator} — ${description}` : description);
    return {
      title: doc.title || identifier || query,
      url: identifier ? `https://archive.org/details/${identifier}` : `https://archive.org/search.php?query=${encodeURIComponent(query)}`,
      excerpt,
      virtualId: `IA:${identifier || query}`,
      sourceKind: "internet-archive",
    };
  });
  return { ok: true, results, finalUrl: outcome.finalUrl };
}

// Issue #180: Wiktionary opensearch is a CORS-readable provider that returns
// short dictionary definitions — exactly the kind of "fragment containing the
// original request" the rendering template needs. We reuse the same
// `fetchProviderJson` plumbing so the diagnostics panel records the raw call.
async function searchWiktionary(query, language, limit) {
  const cap = typeof limit === "number" && Number.isFinite(limit) && limit > 0
    ? Math.floor(limit)
    : 5;
  const lang = language && /^[a-z]{2,3}$/i.test(language) ? language : "en";
  const ordered = [lang, "en"].filter(
    (value, index, array) => value && array.indexOf(value) === index,
  );
  const collected = [];
  let lastFinalUrl = "";
  let lastError = "";
  for (const candidate of ordered) {
    const base = WIKTIONARY_SEARCH_HOSTS[candidate] || WIKTIONARY_SEARCH_HOSTS.en;
    const url = `${base}?action=opensearch&search=${encodeURIComponent(query)}&limit=${cap}&format=json&origin=*`;
    const outcome = await fetchProviderJson("wiktionary", url);
    lastFinalUrl = outcome.finalUrl || lastFinalUrl;
    if (!outcome.ok || !Array.isArray(outcome.data) || !Array.isArray(outcome.data[1])) {
      if (outcome.error) lastError = outcome.error;
      continue;
    }
    const titles = outcome.data[1];
    const descriptions = Array.isArray(outcome.data[2]) ? outcome.data[2] : [];
    const urls = Array.isArray(outcome.data[3]) ? outcome.data[3] : [];
    for (let index = 0; index < titles.length && collected.length < cap; index += 1) {
      const title = titles[index] || query;
      const description = stripHtml(
        descriptions[index] || wiktionaryFallbackDescription(title, candidate),
      );
      const itemUrl = urls[index] ||
        `https://${candidate}.wiktionary.org/wiki/${encodeURIComponent(title)}`;
      collected.push({
        title,
        url: itemUrl,
        excerpt: description,
        wiktionaryKey: String(title).replace(/\s+/g, "_"),
        wiktionaryLanguage: candidate,
        virtualId: `WT:${candidate}:${String(title).replace(/\s+/g, "_")}`,
        sourceKind: "wiktionary",
      });
    }
    if (collected.length > 0) break;
  }
  if (collected.length === 0) {
    return { ok: false, results: [], finalUrl: lastFinalUrl, error: lastError || "no_results" };
  }
  return { ok: true, results: collected.slice(0, cap), finalUrl: lastFinalUrl };
}

// Issue #180: The priority order requested in the issue is
// DuckDuckGo → Internet Archive → Wikipedia → Wikidata → Wiktionary → rest.
// We also keep the corresponding light-weight probe URL so the per-session
// availability check at the top of `tryWebSearch` can pre-flight every
// provider once instead of failing the first user query.
const WEB_SEARCH_PROVIDERS = [
  {
    id: "duckduckgo",
    label: "DuckDuckGo Instant Answer",
    priority: 1,
    probeUrl: "https://api.duckduckgo.com/?q=ping&format=json&no_redirect=1&no_html=1",
    run: (query, language, limit) => searchDuckDuckGo(query, language, limit),
  },
  {
    id: "internet-archive",
    label: "Internet Archive (archive.org)",
    priority: 2,
    probeUrl:
      "https://archive.org/advancedsearch.php?q=ping&fl%5B%5D=identifier&rows=1&page=1&output=json",
    run: (query, language, limit) =>
      searchInternetArchive(query, language, limit),
  },
  {
    id: "wikipedia",
    label: "Wikipedia REST",
    priority: 3,
    probeUrl: "https://en.wikipedia.org/w/rest.php/v1/search/page?q=ping&limit=1",
    run: (query, language, limit) =>
      searchWikipediaWebProvider(query, language, limit),
  },
  {
    id: "wikidata",
    label: "Wikidata entities",
    priority: 4,
    probeUrl:
      "https://www.wikidata.org/w/api.php?action=wbsearchentities&search=ping&language=en&format=json&origin=*&limit=1",
    run: (query, language, limit) =>
      searchWikidataEntities(query, language, limit),
  },
  {
    id: "wiktionary",
    label: "Wiktionary opensearch",
    priority: 5,
    probeUrl:
      "https://en.wiktionary.org/w/api.php?action=opensearch&search=ping&limit=1&format=json&origin=*",
    run: (query, language, limit) =>
      searchWiktionary(query, language, limit),
  },
];

const WEB_SEARCH_PROVIDER_PRIORITY = WEB_SEARCH_PROVIDERS.reduce((acc, provider, index) => {
  acc[provider.id] = typeof provider.priority === "number" ? provider.priority : index + 1;
  return acc;
}, Object.create(null));

// Issue #180: pre-probe every provider exactly once per browser session. The
// result lives in `WEB_SEARCH_AVAILABLE` / `WEB_SEARCH_DISABLED` for the rest
// of the worker's lifetime so subsequent queries skip CORS-blocked endpoints
// without re-burning a socket. We return a shared promise so concurrent
// callers cooperate on the same probe batch.
function ensureWebSearchProviderProbes() {
  if (WEB_SEARCH_PROBE_PROMISE) return WEB_SEARCH_PROBE_PROMISE;
  if (typeof fetch !== "function") {
    WEB_SEARCH_PROBE_PROMISE = Promise.resolve([]);
    return WEB_SEARCH_PROBE_PROMISE;
  }
  WEB_SEARCH_PROBE_PROMISE = (async () => {
    const tasks = WEB_SEARCH_PROVIDERS.map((provider) => async () => {
      if (!provider.probeUrl) return null;
      const startedAt = Date.now();
      try {
        const response = await fetch(provider.probeUrl, { mode: "cors" });
        const status = response ? response.status : 0;
        if (response && response.ok) {
          webSearchMarkAvailable(provider.id, { probedAt: startedAt, status });
          recordWebSearchDiagnostic({
            providerId: provider.id,
            url: provider.probeUrl,
            method: "GET",
            ok: true,
            status,
            elapsedMs: Date.now() - startedAt,
            phase: "probe",
          });
          return { providerId: provider.id, ok: true, status };
        }
        recordWebSearchDiagnostic({
          providerId: provider.id,
          url: provider.probeUrl,
          method: "GET",
          ok: false,
          status,
          elapsedMs: Date.now() - startedAt,
          phase: "probe",
        });
        return { providerId: provider.id, ok: false, status };
      } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        const isCors =
          message.toLowerCase().includes("cors") ||
          message.toLowerCase().includes("network") ||
          message.toLowerCase().includes("failed to fetch");
        webSearchDisable(provider.id, isCors ? "cors" : "network");
        recordWebSearchDiagnostic({
          providerId: provider.id,
          url: provider.probeUrl,
          method: "GET",
          ok: false,
          elapsedMs: Date.now() - startedAt,
          error: message,
          cors: isCors,
          phase: "probe",
        });
        return { providerId: provider.id, ok: false, error: message, cors: isCors };
      }
    });
    return runWithConcurrencyLimit(tasks, webSearchConcurrency());
  })();
  return WEB_SEARCH_PROBE_PROMISE;
}

async function runWithConcurrencyLimit(tasks, limit) {
  // Simple p-limit style runner so we never exceed the browser's per-origin
  // socket budget. Tasks are async functions returning a value; results are
  // returned in the original order.
  const cap = Math.max(1, Math.min(limit, tasks.length));
  const results = new Array(tasks.length);
  let cursor = 0;
  async function worker() {
    while (true) {
      const index = cursor;
      cursor += 1;
      if (index >= tasks.length) return;
      results[index] = await tasks[index]();
    }
  }
  await Promise.all(Array.from({ length: cap }, () => worker()));
  return results;
}

function reciprocalRankFusion(perProviderResults, k) {
  // R194: the Rust/WASM core owns the fusion logic so the offline trace and
  // the browser worker agree to the last byte. We try WASM first and only
  // fall back to the JS implementation when the worker booted in
  // `js fallback` mode (e.g. WASM disabled in the browser).
  const wasmFused = wasmReciprocalRankFusion(perProviderResults);
  if (wasmFused !== null) {
    return wasmFused;
  }
  // Cormack, Clarke, Buettcher 2009: score(d) = Σ 1 / (k + rank_i(d)).
  const fused = new Map();
  for (const provider of perProviderResults) {
    const list = Array.isArray(provider.results) ? provider.results : [];
    list.forEach((item, index) => {
      if (!item || !item.url) return;
      const rank = index + 1;
      const score = 1 / (k + rank);
      const existing = fused.get(item.url);
      if (existing) {
        existing.score += score;
        existing.providers.push({ id: provider.id, rank });
        if (!existing.title && item.title) existing.title = item.title;
        if (!existing.excerpt && item.excerpt) existing.excerpt = item.excerpt;
      } else {
        fused.set(item.url, {
          url: item.url,
          title: item.title || item.url,
          excerpt: item.excerpt || "",
          score,
          providers: [{ id: provider.id, rank }],
        });
      }
    });
  }
  return Array.from(fused.values()).sort((a, b) => {
    if (b.score !== a.score) return b.score - a.score;
    return b.providers.length - a.providers.length;
  });
}

// Issue #153/#180: identify "the same entity" returned by different providers
// so the fused list shows one bullet with the other URLs collapsed under
// "Other sources:". A single result can carry several canonical identifiers
// (Wikidata Q-id, Wikipedia page key, Wiktionary headword) — dedupe walks all
// of them and merges into the first existing group it finds. Returning a
// list makes the Wikipedia↔Wikidata merge robust against percent-encoding
// differences in the two providers' URLs.
function canonicalEntityKeys(meta) {
  if (!meta) return [];
  const keys = [];
  if (meta.qid && /^Q\d+$/.test(meta.qid)) keys.push(`Q:${meta.qid}`);
  if (meta.wikipediaKey) {
    const lang = meta.wikipediaLanguage || "en";
    keys.push(`WP:${lang}:${meta.wikipediaKey}`);
  }
  if (meta.wiktionaryKey) {
    const lang = meta.wiktionaryLanguage || "en";
    keys.push(`WT:${lang}:${meta.wiktionaryKey}`);
  }
  return keys;
}

// Backwards-compatible shim: prefer the primary key but keep the historical
// single-key signature for callers that still rely on it.
function canonicalEntityKey(meta) {
  const keys = canonicalEntityKeys(meta);
  return keys.length > 0 ? keys[0] : null;
}

function buildItemMetadataIndex(perProvider) {
  // The richer the meta the better — an entry that carries a Wikidata `qid`
  // is preferred over a Wikipedia-only entry for the same URL, because the
  // Q-id is what cross-provider dedupe groups by. Without this preference,
  // the Wikipedia URL would be indexed by the Wikipedia provider's meta
  // (`WP:en:Apple`) and a separate Wikidata entry for the same fact (`Q:Q89`)
  // would never collapse into one bullet.
  const byUrl = new Map();
  const rank = (item) => (item && item.qid ? 2 : 1);
  function record(url, item) {
    if (!url || !item) return;
    const existing = byUrl.get(url);
    if (!existing || rank(item) > rank(existing)) {
      byUrl.set(url, item);
    }
  }
  for (const provider of perProvider) {
    if (!provider || !Array.isArray(provider.results)) continue;
    for (const item of provider.results) {
      if (!item || !item.url) continue;
      record(item.url, item);
      // Wikidata results carry the Wikipedia URL of the same entity inline;
      // index that too so the Wikipedia provider's entry is recognised as
      // a duplicate of the Wikidata one.
      if (item.wikipediaUrl) record(item.wikipediaUrl, item);
    }
  }
  return byUrl;
}

function dedupeFusedEntries(fused, metaByUrl, evidence) {
  const groupsByKey = new Map();
  const allGroups = [];
  const standalone = [];

  function alreadyHasProvider(target, candidate) {
    return target.providers.some(
      (existing) => existing.id === candidate.id && existing.rank === candidate.rank,
    );
  }

  fused.forEach((entry, index) => {
    const meta = metaByUrl.get(entry.url) || null;
    const keys = canonicalEntityKeys(meta);
    const enriched = Object.assign({}, entry, {
      qid: (meta && meta.qid) || "",
      wikipediaKey: (meta && meta.wikipediaKey) || "",
      wikipediaLanguage: (meta && meta.wikipediaLanguage) || "",
      wiktionaryKey: (meta && meta.wiktionaryKey) || "",
      wiktionaryLanguage: (meta && meta.wiktionaryLanguage) || "",
      sourceKind: (meta && meta.sourceKind) || "",
      virtualId:
        (meta && meta.virtualId) ||
        (meta && meta.qid) ||
        (meta && meta.wikipediaKey ? `WP:${meta.wikipediaKey}` : ""),
      alternateUrls: [],
      keys: keys.slice(),
      originalRank: index,
    });

    if (keys.length === 0) {
      standalone.push(enriched);
      return;
    }
    let head = null;
    for (const key of keys) {
      if (groupsByKey.has(key)) {
        head = groupsByKey.get(key);
        break;
      }
    }
    if (!head) {
      allGroups.push(enriched);
      for (const key of keys) {
        if (!groupsByKey.has(key)) groupsByKey.set(key, enriched);
      }
      return;
    }
    // Found an existing group — absorb this entry into it.
    head.score += enriched.score;
    head.alternateUrls.push({
      url: enriched.url,
      title: enriched.title,
      providers: enriched.providers,
      sourceKind: enriched.sourceKind,
    });
    for (const p of enriched.providers) {
      if (!alreadyHasProvider(head, p)) head.providers.push(p);
    }
    // Register the absorbed entry's keys against the head group too so a third
    // provider matching either canonical id still merges in.
    for (const key of keys) {
      if (!groupsByKey.has(key)) groupsByKey.set(key, head);
    }
    // Prefer the richest virtualId once we know more identifiers.
    if (!head.virtualId && enriched.virtualId) head.virtualId = enriched.virtualId;
    if (!head.qid && enriched.qid) head.qid = enriched.qid;
    if (!head.wikipediaKey && enriched.wikipediaKey) {
      head.wikipediaKey = enriched.wikipediaKey;
      head.wikipediaLanguage = enriched.wikipediaLanguage;
    }
    if (!head.wiktionaryKey && enriched.wiktionaryKey) {
      head.wiktionaryKey = enriched.wiktionaryKey;
      head.wiktionaryLanguage = enriched.wiktionaryLanguage;
    }
    if (Array.isArray(evidence)) {
      evidence.push(`web_search:dedupe:${keys[0]}:absorbed:${enriched.url}`);
    }
  });
  const merged = [...allGroups, ...standalone];
  merged.sort((a, b) => {
    if (b.score !== a.score) return b.score - a.score;
    if (b.providers.length !== a.providers.length) {
      return b.providers.length - a.providers.length;
    }
    // Issue #180: stable order by provider priority so DDG-led entries beat
    // Wikidata-only entries on perfect ties.
    const ap = providerPriorityScore(a.providers);
    const bp = providerPriorityScore(b.providers);
    if (ap !== bp) return ap - bp;
    return a.originalRank - b.originalRank;
  });
  return merged;
}

function providerPriorityScore(providers) {
  if (!Array.isArray(providers) || providers.length === 0) return 999;
  let best = 999;
  for (const p of providers) {
    const score = WEB_SEARCH_PROVIDER_PRIORITY[p && p.id] || 999;
    if (score < best) best = score;
  }
  return best;
}

// Issue #153: localized templates for the web search response. Keep these in
// sync with the visible UI strings in `src/web/i18n-catalog.lino`. The worker
// runs in a separate context that cannot import lino-i18n at runtime, so we
// inline the small subset that is actually rendered to chat. `en` is always
// the fallback when the catalogue for the active language is missing.
const WEB_SEARCH_TEXTS = {
  en: {
    header: (query, top, k) =>
      `Search results for \`${query}\` — top ${top} after reciprocal rank fusion (k = ${k}).`,
    otherSources: "Other sources",
    via: "via",
    readMore: "Read more",
    noResults: (query, providers) =>
      `No CORS-enabled web search results were returned for \`${query}\`.\n\nProviders tried: ${providers}.`,
    allDisabled: (providers) =>
      `All CORS-readable search providers are disabled for this session. Tried: ${providers}.`,
  },
  ru: {
    header: (query, top, k) =>
      `Результаты поиска для \`${query}\` — топ ${top} после реципрокного объединения рангов (k = ${k}).`,
    otherSources: "Другие источники",
    via: "через",
    readMore: "Подробнее",
    noResults: (query, providers) =>
      `Не получены результаты веб-поиска с поддержкой CORS для \`${query}\`.\n\nПопробованы провайдеры: ${providers}.`,
    allDisabled: (providers) =>
      `Все CORS-совместимые поисковые провайдеры отключены в этой сессии. Пробовали: ${providers}.`,
  },
  zh: {
    header: (query, top, k) =>
      `搜索 \`${query}\` 的结果 — 经互惠等级融合后的前 ${top} 项(k = ${k})。`,
    otherSources: "其他来源",
    via: "来自",
    readMore: "阅读更多",
    noResults: (query, providers) =>
      `未获取到 \`${query}\` 的可用 CORS 搜索结果。\n\n已尝试的提供方:${providers}。`,
    allDisabled: (providers) =>
      `本会话中所有支持 CORS 的搜索提供方都已禁用。已尝试:${providers}。`,
  },
  hi: {
    header: (query, top, k) =>
      `\`${query}\` के लिए खोज परिणाम — रेसिप्रोकल रैंक फ़्यूज़न के बाद शीर्ष ${top} (k = ${k})।`,
    otherSources: "अन्य स्रोत",
    via: "के माध्यम से",
    readMore: "और पढ़ें",
    noResults: (query, providers) =>
      `\`${query}\` के लिए CORS-समर्थित कोई खोज परिणाम नहीं मिले।\n\nप्रयास किए गए प्रदाता: ${providers}.`,
    allDisabled: (providers) =>
      `इस सत्र के लिए सभी CORS-समर्थित खोज प्रदाता अक्षम हैं। प्रयास किया: ${providers}.`,
  },
};

function webSearchTexts(language) {
  const code = String(language || "").toLowerCase().slice(0, 2);
  return WEB_SEARCH_TEXTS[code] || WEB_SEARCH_TEXTS.en;
}

async function tryWebSearch(prompt, language) {
  const normalized = normalizePrompt(prompt);
  const request = extractWebSearchRequest(prompt, normalized);
  if (!request || !request.query) return null;
  return runWebSearchQuery(request.query, language, request.kind);
}

async function runWebSearchQuery(query, language, queryKind) {
  query = String(query || "").trim();
  if (!query) return null;
  const rrfK = webSearchRrfK();
  const concurrency = webSearchConcurrency();
  const providerLimit = webSearchProviderLimit();
  const texts = webSearchTexts(language);

  // Issue #180: pre-probe every provider once per browser session so the
  // first user query does not waste sockets on CORS-blocked endpoints. The
  // probe results live in `WEB_SEARCH_AVAILABLE`/`WEB_SEARCH_DISABLED` for
  // the rest of the worker lifetime.
  await ensureWebSearchProviderProbes();

  // R194: the Rust core (`web_search_core::build_request_evidence`) is the
  // source of truth for the `web_search:*` evidence prefix. We prepend its
  // output and fall back to the inline list when the WASM worker booted in
  // `js fallback` mode.
  const evidence = [];
  const wasmEvidence = wasmWebSearchRequestEvidence(query, language || "");
  if (Array.isArray(wasmEvidence) && wasmEvidence.length > 0) {
    for (const line of wasmEvidence) {
      if (line) evidence.push(line);
    }
  } else {
    evidence.push(`web_search:request:${query}`);
    if (language) {
      evidence.push(`web_search:language:${language}`);
    }
    for (const provider of WEB_SEARCH_PROVIDERS) {
      evidence.push(`web_search:provider:${provider.id}`);
    }
    evidence.push(`web_search:combined:rrf:k=${rrfK}`);
  }
  if (queryKind) {
    evidence.push(`web_search:query_kind:${queryKind}`);
  }

  // Issue #180: providers are tried in declared priority order so the rendered
  // list matches the user's requested DDG → IA → WP → WD → Wiktionary
  // sequence whenever scores tie. Session-disabled providers are skipped on
  // top of the WASM-derived prefix and annotated for the diagnostics panel.
  const ordered = WEB_SEARCH_PROVIDERS.slice().sort((a, b) => {
    const pa = typeof a.priority === "number" ? a.priority : 999;
    const pb = typeof b.priority === "number" ? b.priority : 999;
    return pa - pb;
  });
  const active = ordered.filter((provider) => !webSearchIsDisabled(provider.id));
  for (const provider of ordered) {
    if (webSearchIsDisabled(provider.id)) {
      evidence.push(`web_search:disabled:${provider.id}`);
    } else if (WEB_SEARCH_AVAILABLE.has(provider.id)) {
      evidence.push(`web_search:available:${provider.id}`);
    }
  }

  if (active.length === 0) {
    return {
      intent: "web_search",
      content: texts.allDisabled(WEB_SEARCH_PROVIDERS.map((p) => p.id).join(", ")),
      confidence: 0.3,
      evidence,
      diagnostics: { providers: [], httpExchanges: consumeWebSearchDiagnostics() },
    };
  }

  const tasks = active.map((provider) => async () => {
    const startedAt = Date.now();
    const outcome = await provider.run(query, language, providerLimit);
    return Object.assign({ id: provider.id, label: provider.label, elapsedMs: Date.now() - startedAt }, outcome);
  });
  const perProvider = await runWithConcurrencyLimit(tasks, concurrency);

  for (const provider of perProvider) {
    if (!provider.ok) {
      evidence.push(`web_search:provider:${provider.id}:error:${provider.error || "no_results"}`);
      continue;
    }
    evidence.push(`web_search:provider:${provider.id}:count:${provider.results.length}`);
    if (provider.language) {
      evidence.push(`web_search:provider:${provider.id}:language:${provider.language}`);
    }
    provider.results.forEach((item, index) => {
      evidence.push(`web_search:rank:${provider.id}:${index + 1}:${item.url}`);
    });
  }

  const fused = reciprocalRankFusion(perProvider, rrfK);
  const metaByUrl = buildItemMetadataIndex(perProvider);
  const deduped = dedupeFusedEntries(fused, metaByUrl, evidence);
  const top = deduped.slice(0, providerLimit);
  top.forEach((entry, index) => {
    evidence.push(`web_search:fused:${index + 1}:${entry.providers.map((p) => p.id).join("+")}:${entry.url}`);
    if (entry.virtualId) {
      evidence.push(`web_search:formal:${index + 1}:${entry.virtualId}`);
    }
  });

  const diagnostics = {
    query,
    language: language || "",
    providers: perProvider.map((p) => ({
      id: p.id,
      label: p.label,
      ok: !!p.ok,
      count: Array.isArray(p.results) ? p.results.length : 0,
      elapsedMs: p.elapsedMs || 0,
      finalUrl: p.finalUrl || "",
      error: p.error || "",
    })),
    httpExchanges: consumeWebSearchDiagnostics(),
    fused: top.map((entry, index) => ({
      rank: index + 1,
      url: entry.url,
      title: entry.title,
      score: entry.score,
      providers: entry.providers,
      alternateUrls: entry.alternateUrls,
      virtualId: entry.virtualId || "",
      keys: entry.keys || [],
    })),
  };

  if (top.length === 0) {
    return {
      intent: "web_search",
      content: texts.noResults(query, active.map((p) => p.label).join(", ")),
      confidence: 0.35,
      evidence,
      diagnostics,
    };
  }

  // Issue #180: every fused result is rendered Google-style — a single line
  // with title + bare domain, an indented quote (a fragment containing the
  // original query when possible, truncated near ~220 chars), a "Read more"
  // link, and finally a faint "Другие источники:" line listing alternates
  // (provider label + url) without per-source excerpts.
  const lines = [texts.header(query, top.length, rrfK), ""];
  top.forEach((entry, index) => {
    const domain = extractDomain(entry.url);
    const titlePiece = `**[${entry.title || entry.url}](${entry.url})**`;
    const domainPiece = domain ? `  \`${domain}\`` : "";
    const idTag = entry.virtualId ? `  \`${entry.virtualId}\`` : "";
    lines.push(`${index + 1}. ${titlePiece}${domainPiece}${idTag}`);
    const quote = extractQuoteAroundQuery(entry.excerpt, query, 220);
    if (quote) {
      lines.push(`   > ${quote}`);
    }
    const sourceTags = entry.providers
      .map((p) => `${p.id}#${p.rank}`)
      .join(", ");
    lines.push(`   [${texts.readMore}](${entry.url}) — _${texts.via} ${sourceTags}_`);
    if (Array.isArray(entry.alternateUrls) && entry.alternateUrls.length > 0) {
      const others = entry.alternateUrls
        .map((alt) => {
          const labelProvider = pickPrimaryProviderId(alt.providers, alt.sourceKind);
          const label = providerDisplayLabel(labelProvider, language);
          return `[${label}](${alt.url})`;
        })
        .filter(Boolean);
      if (others.length > 0) {
        lines.push(`   _${texts.otherSources}: ${others.join(", ")}_`);
      }
    }
    lines.push("");
  });
  while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();

  // Resolve the formalization tuple now that we know the top-ranked entity.
  // Prefer a real Wikidata Q-id; fall back to the WP virtual id, then to the
  // bare normalised query. We scan the whole `top` slice instead of just
  // `top[0]` so that a DuckDuckGo result without an id at rank 1 still lets
  // us fold a Wikidata Q-id from rank 2+ into the resolved tuple.
  let formalizedObject = "";
  for (const entry of top) {
    if (entry && entry.virtualId) {
      formalizedObject = entry.virtualId;
      if (/^Q\d+$/.test(entry.virtualId)) break;
    }
  }

  return {
    intent: "web_search",
    content: lines.join("\n"),
    confidence: 0.85,
    evidence,
    formalizedObject,
    query,
    diagnostics,
  };
}

const PROMOTED_PROJECT_ORGS = ["link-assistant", "link-foundation", "linksplatform"];

function projectPromotionEnabled(preferences) {
  const value = preferences && preferences.associativeProjectPromotion;
  if (value === undefined || value === null || value === "") return true;
  if (value === true) return true;
  if (value === false) return false;
  const normalized = String(value).trim().toLowerCase();
  if (["0", "false", "no", "off", "disabled"].includes(normalized)) return false;
  if (["1", "true", "yes", "on", "enabled"].includes(normalized)) return true;
  return true;
}

function normalizeProjectTerm(value) {
  let term = normalizePrompt(value)
    .replace(/[-_]+/g, " ")
    .replace(/\s+/g, " ")
    .trim();
  for (const prefix of ["the ", "a ", "an "]) {
    if (term.startsWith(prefix)) {
      term = term.slice(prefix.length).trim();
      break;
    }
  }
  return term;
}

function projectRepoSlug(project) {
  return `${project.org}/${project.name}`;
}

function localizedProject(project, language) {
  if (!project || !Array.isArray(project.localized)) return null;
  return (
    project.localized.find((loc) => loc && loc.language === language) ||
    project.localized.find((loc) => loc && loc.language === "en") ||
    null
  );
}

function projectDisplayName(project, language) {
  const localized = localizedProject(project, language);
  return (localized && localized.displayName) || project.displayName || project.name || "";
}

function projectStatementsFor(project, language) {
  const localized = localizedProject(project, language);
  if (
    localized &&
    Array.isArray(localized.statements) &&
    localized.statements.length > 0
  ) {
    return localized.statements;
  }
  return Array.isArray(project && project.statements) ? project.statements : [];
}

function describeProjectRecord(project, language) {
  const statements = projectStatementsFor(project, language)
    .filter((statement) => {
      const kind = statement && statement.kind;
      return statement && statement.text && kind !== "install" && kind !== "example";
    })
    .slice()
    .sort((a, b) => Number(b.weight || 0) - Number(a.weight || 0))
    .slice(0, 3)
    .map((statement) => String(statement.text).trim())
    .filter(Boolean);
  if (statements.length > 0) return statements.join(" ");
  return project.description || projectDisplayName(project, language);
}

function projectMatchesAlias(project, normalizedTerm) {
  if (!project || !normalizedTerm) return false;
  const aliases = Array.isArray(project.aliases) ? project.aliases : [];
  return (
    normalizeProjectTerm(project.displayName) === normalizedTerm ||
    normalizeProjectTerm(project.name) === normalizedTerm ||
    normalizeProjectTerm(projectRepoSlug(project)) === normalizedTerm ||
    aliases.some((alias) => normalizeProjectTerm(alias) === normalizedTerm)
  );
}

function projectByAlias(term) {
  const normalizedTerm = normalizeProjectTerm(term);
  if (!normalizedTerm) return null;
  return PROJECTS.find((project) => projectMatchesAlias(project, normalizedTerm)) || null;
}

function isPromotedProject(project) {
  return PROMOTED_PROJECT_ORGS.some(
    (org) => String(project && project.org).toLowerCase() === org,
  );
}

function promotedProjectByRepo(owner, name) {
  const ownerLower = String(owner || "").toLowerCase();
  const nameLower = String(name || "").toLowerCase();
  return (
    PROJECTS.find(
      (project) =>
        isPromotedProject(project) &&
        String(project.org || "").toLowerCase() === ownerLower &&
        String(project.name || "").toLowerCase() === nameLower,
    ) || null
  );
}

function cleanRepositorySegment(segment) {
  const trimmed = String(segment || "").trim().replace(/\.git$/i, "");
  if (!trimmed || !/^[A-Za-z0-9._-]+$/.test(trimmed)) return "";
  return trimmed;
}

function repositoryFromUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch (_error) {
    return null;
  }
  const host = parsed.hostname.toLowerCase().replace(/^www\./, "");
  const platform =
    host === "github.com"
      ? { slug: "github", label: "GitHub", host: "github.com" }
      : host === "gitlab.com"
        ? { slug: "gitlab", label: "GitLab", host: "gitlab.com" }
        : host === "bitbucket.org"
          ? { slug: "bitbucket", label: "Bitbucket", host: "bitbucket.org" }
          : null;
  if (!platform) return null;
  const segments = parsed.pathname.split("/").filter(Boolean);
  const owner = cleanRepositorySegment(segments[0]);
  const name = cleanRepositorySegment(segments[1]);
  if (!owner || !name) return null;
  return {
    platform,
    owner,
    name,
    url: `https://${platform.host}/${owner}/${name}`,
  };
}

function repositoryFromSlug(term) {
  const parts = String(term || "").trim().split("/");
  if (parts.length !== 2) return null;
  const owner = cleanRepositorySegment(parts[0]);
  const name = cleanRepositorySegment(parts[1]);
  if (!owner || !name) return null;
  return {
    platform: { slug: "github", label: "GitHub", host: "github.com" },
    owner,
    name,
    url: `https://github.com/${owner}/${name}`,
  };
}

function repositoryFromPrompt(prompt) {
  const urlCandidate = firstUrlCandidate(prompt);
  if (urlCandidate) {
    const repo = repositoryFromUrl(urlCandidate.url);
    if (repo) return repo;
  }
  const query = extractConceptQuery(prompt);
  if (!query) return null;
  const term = String(query.termOriginal || query.term || "").trim();
  if (!term) return null;
  if (term.includes("://") || looksLikeHostname(term)) {
    const url = normalizeUrlCandidate(term);
    return url ? repositoryFromUrl(url) : null;
  }
  if (term.includes("/") && !/\s/.test(term)) {
    return repositoryFromSlug(term);
  }
  return null;
}

function repositorySlug(repo) {
  return `${repo.owner}/${repo.name}`;
}

const GITHUB_README_KNOWN_TOOLS = [
  "http_fetch",
  "url_navigate",
  "web_search",
  "wikipedia_lookup",
  "calculator",
  "eval_js",
  "read_local_file",
  "append_memory",
  "export_memory",
  "import_memory",
  "conversation_recall",
  "concept_lookup",
  "write_program",
  "intent_routing",
  "fact_lookup",
  "summarize_conversation",
  "brainstorm",
  "coreference",
  "roleplay",
];

function githubRepositoryInfoRequest(prompt, normalized) {
  const repo = repositoryFromPrompt(prompt);
  if (!repo || !repo.platform || repo.platform.slug !== "github") return null;
  const markers = [
    "extract information",
    "main programming language",
    "programming language",
    "number of stars",
    "star count",
    "stars",
    "last commit",
    "readme",
  ];
  if (!containsAny(normalized, markers)) return null;
  return repo;
}

function githubApiRepositoryUrl(repo, suffix) {
  const owner = encodeURIComponent(repo.owner);
  const name = encodeURIComponent(repo.name);
  return `https://api.github.com/repos/${owner}/${name}${suffix || ""}`;
}

async function fetchGithubJson(url, label, diagnostics) {
  if (typeof fetch !== "function") {
    throw new Error("fetch unavailable");
  }
  const startedAt = Date.now();
  const headers = { Accept: "application/vnd.github+json" };
  const response = await fetch(url, { headers });
  const text = await response.text();
  const entry = {
    providerId: "github",
    url,
    method: "GET",
    requestHeaders: headers,
    ok: Boolean(response && response.ok),
    status: response ? response.status : 0,
    statusText: response ? response.statusText : "",
    elapsedMs: Date.now() - startedAt,
    responseSnippet: text.slice(0, 1024),
    unified: `github_api ${label}`,
  };
  if (Array.isArray(diagnostics)) diagnostics.push(entry);
  if (!response || !response.ok) {
    throw new Error(`HTTP ${entry.status} ${entry.statusText}`.trim());
  }
  try {
    return text ? JSON.parse(text) : null;
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    throw new Error(`JSON parse failed: ${message}`);
  }
}

function decodeGithubReadmeContent(readme) {
  if (!readme || typeof readme !== "object") return "";
  if (typeof readme.content === "string" && readme.encoding === "base64") {
    const encoded = readme.content.replace(/\s+/g, "");
    if (typeof atob !== "function") return "";
    try {
      const binary = atob(encoded);
      const bytes = new Uint8Array(binary.length);
      for (let index = 0; index < binary.length; index += 1) {
        bytes[index] = binary.charCodeAt(index);
      }
      if (typeof TextDecoder === "function") {
        return new TextDecoder("utf-8").decode(bytes);
      }
      let decoded = "";
      for (let index = 0; index < binary.length; index += 1) {
        decoded += String.fromCharCode(bytes[index]);
      }
      return decoded;
    } catch (_error) {
      return "";
    }
  }
  return "";
}

function pushUniqueToolName(out, seen, name) {
  const cleaned = String(name || "")
    .trim()
    .replace(/^[@#]+/u, "")
    .replace(/[.,:;!?]+$/u, "");
  if (!cleaned || cleaned.length > 48) return;
  if (!/^[a-z][a-z0-9_-]*$/i.test(cleaned)) return;
  const key = cleaned.toLowerCase();
  if (seen.has(key)) return;
  seen.add(key);
  out.push(cleaned);
}

function pushUniqueToolDisplayName(out, seen, name) {
  const cleaned = String(name || "")
    .replace(/`+/gu, "")
    .replace(/\*\*/gu, "")
    .trim()
    .replace(/[.,:;!?]+$/u, "")
    .replace(/\s+/gu, " ");
  if (!cleaned || cleaned.length > 80 || !/[A-Za-z]/u.test(cleaned)) return;
  if (/\b(?:agentic|available|supported|search|execution|utility)\s+tools?\b/i.test(cleaned)) {
    return;
  }
  const key = cleaned.toLowerCase();
  if (seen.has(key)) return;
  seen.add(key);
  out.push(cleaned);
}

function extractReadmeTools(markdown) {
  const text = String(markdown || "");
  const lower = text.toLowerCase();
  const out = [];
  const seen = new Set();
  for (const tool of GITHUB_README_KNOWN_TOOLS) {
    if (lower.includes(tool.toLowerCase())) {
      pushUniqueToolName(out, seen, tool);
    }
  }
  const lines = text.split(/\r?\n/);
  let inToolsSection = false;
  let toolsSectionLevel = 0;
  for (const line of lines) {
    const heading = /^(\s{0,3})(#{1,6})\s+(.+?)\s*#*\s*$/u.exec(line);
    if (heading) {
      const level = heading[2].length;
      const headingText = heading[3].trim();
      if (/\btools?\b/i.test(headingText)) {
        inToolsSection = true;
        toolsSectionLevel = level;
      } else if (inToolsSection && level > toolsSectionLevel) {
        pushUniqueToolDisplayName(out, seen, headingText);
      } else {
        inToolsSection = false;
        toolsSectionLevel = 0;
      }
      continue;
    }
    if (!inToolsSection) continue;
    const bullet = /^\s*[-*+]\s+(?:`([^`]+)`|([A-Za-z][A-Za-z0-9_-]*))/u.exec(line);
    if (bullet) {
      pushUniqueToolName(out, seen, bullet[1] || bullet[2]);
    }
    const codeMatches = line.matchAll(/`([A-Za-z][A-Za-z0-9_-]*)`/gu);
    for (const match of codeMatches) {
      pushUniqueToolName(out, seen, match[1]);
    }
  }
  return out;
}

function githubCommitDate(commits) {
  if (!Array.isArray(commits) || commits.length === 0) return null;
  const commit = commits[0] && commits[0].commit ? commits[0].commit : null;
  return (
    (commit && commit.committer && commit.committer.date) ||
    (commit && commit.author && commit.author.date) ||
    null
  );
}

async function tryGithubRepositoryInfo(repo, language) {
  const diagnostics = [];
  const errors = [];
  let repoData = null;
  let commits = null;
  let readme = null;

  try {
    repoData = await fetchGithubJson(githubApiRepositoryUrl(repo), "repository", diagnostics);
  } catch (error) {
    errors.push(`repository: ${error instanceof Error ? error.message : String(error)}`);
  }
  try {
    commits = await fetchGithubJson(
      githubApiRepositoryUrl(repo, "/commits?per_page=1"),
      "commits",
      diagnostics,
    );
  } catch (error) {
    errors.push(`commits: ${error instanceof Error ? error.message : String(error)}`);
  }
  try {
    readme = await fetchGithubJson(githubApiRepositoryUrl(repo, "/readme"), "readme", diagnostics);
  } catch (error) {
    errors.push(`readme: ${error instanceof Error ? error.message : String(error)}`);
  }

  const slug = repositorySlug(repo);
  const readmeMarkdown = decodeGithubReadmeContent(readme);
  const payload = {
    repository: (repoData && repoData.full_name) || slug,
    mainProgrammingLanguage: (repoData && repoData.language) || null,
    stars:
      repoData && Number.isFinite(Number(repoData.stargazers_count))
        ? Number(repoData.stargazers_count)
        : null,
    lastCommitDate: githubCommitDate(commits) || null,
    readmeTools: extractReadmeTools(readmeMarkdown),
  };
  if (errors.length > 0) {
    payload.errors = errors;
  }
  const content = `\`\`\`json\n${JSON.stringify(payload, null, 2)}\n\`\`\``;
  return {
    intent: "github_repo_info",
    content,
    confidence: errors.length === 0 ? 0.92 : 0.55,
    evidence: [
      `github_repo_info:repository:${slug}`,
      `source:${repo.url}`,
      "source:https://api.github.com",
      `language:${language}`,
      ...(errors.length > 0 ? errors.map((error) => `github_repo_info:error:${error}`) : []),
    ],
    diagnostics: {
      providers: [],
      httpExchanges: diagnostics,
    },
  };
}

function genericProjectLookupAnswer(prompt, language, repo, promotionEnabled) {
  const evidence = [];
  if (!promotionEnabled) evidence.push("project_lookup:promotion:disabled");
  if (repo) {
    const slug = repositorySlug(repo);
    evidence.push(`project_lookup:repository:${repo.platform.slug}:${slug}`);
    evidence.push(`source:${repo.url}`);
    const content =
      language === "ru"
        ? `Это запрос о репозитории [${slug}](${repo.url}) на ${repo.platform.label}.\n\nОбычный путь project_lookup ищет и резюмирует README или описание проекта на GitHub, GitLab и Bitbucket без особого правила для отдельного названия. Если репозиторий находится в продвигаемых организациях и продвижение включено, он будет показан первым.`
        : `This is a repository lookup for [${slug}](${repo.url}) on ${repo.platform.label}.\n\nThe generic project_lookup path can summarize README or project descriptions from GitHub, GitLab, and Bitbucket without a special case for any single name. If the repository belongs to a promoted organization and promotion is enabled, that repository is listed first.`;
    return { intent: "project_lookup", content, confidence: 0.82, evidence };
  }
  evidence.push("project_lookup:repository_hosts:GitHub,GitLab,Bitbucket");
  const content =
    language === "ru"
      ? "Это обычный запрос project_lookup о проекте или репозитории.\n\nЯ не выделяю специальный репозиторий, потому что продвижение ассоциативных репозиториев отключено. Дальше следует искать и резюмировать подходящие проекты на GitHub, GitLab и Bitbucket и похожих хостингах."
      : "This is a generic project_lookup request for a project or repository.\n\nI am not privileging a specific repository because associative repository promotion is disabled. The next step is to search and summarize matching projects across GitHub, GitLab, Bitbucket, and similar hosts.";
  return { intent: "project_lookup", content, confidence: 0.72, evidence };
}

async function renderPromotedProjectLookup(prompt, language, project) {
  const displayName = projectDisplayName(project, language);
  const repo = projectRepoSlug(project);
  const url = project.url || `https://github.com/${repo}`;
  const description = describeProjectRecord(project, language);
  const orgs = PROMOTED_PROJECT_ORGS.join(", ");
  const preferredLine =
    language === "ru"
      ? `В контексте репозиториев ${orgs} под \`${displayName}\` я прежде всего имею в виду [${repo}](${url}) — ${description}`
      : `In the ${orgs} repository context, \`${displayName}\` should first mean [${repo}](${url}) — ${description}`;

  const search = await runWebSearchQuery(displayName, language);
  const evidence = [
    `project:promoted:${repo}`,
    `source:${url}`,
    "summarization:mode:short",
    `summarization:language:${language}`,
  ];
  if (search && Array.isArray(search.evidence)) {
    evidence.push(...search.evidence);
  } else {
    evidence.push("web_search:no_results");
  }

  const lines = [preferredLine];
  if (search && search.content) {
    lines.push("");
    lines.push(
      language === "ru"
        ? "Другие найденные в интернете репозитории и сущности:"
        : "Other repositories and entities found online:",
    );
    lines.push("");
    lines.push(search.content);
  } else {
    lines.push("");
    lines.push(
      language === "ru"
        ? "Интернет-поиск по другим совпадениям не вернул результатов через доступные CORS-провайдеры."
        : "Web search for other matches returned no results through the available CORS providers.",
    );
  }

  return {
    intent: "project_lookup",
    content: lines.join("\n"),
    confidence: 0.9,
    evidence,
  };
}

async function tryProjectLookup(prompt, language, preferences) {
  const promotionEnabled = projectPromotionEnabled(preferences);
  const repo = repositoryFromPrompt(prompt);
  if (repo) {
    const promoted = promotionEnabled
      ? promotedProjectByRepo(repo.owner, repo.name)
      : null;
    if (promoted) {
      return renderPromotedProjectLookup(prompt, language, promoted);
    }
    return genericProjectLookupAnswer(prompt, language, repo, promotionEnabled);
  }

  const query = extractConceptQuery(prompt);
  if (!query) return null;
  const project = projectByAlias(query.termOriginal || query.term);
  if (!project) return null;
  if (promotionEnabled && isPromotedProject(project)) {
    return renderPromotedProjectLookup(prompt, language, project);
  }
  return genericProjectLookupAnswer(prompt, language, null, promotionEnabled);
}

function pickPrimaryProviderId(providers, sourceKind) {
  if (sourceKind === "wikidata") return "wikidata";
  if (sourceKind === "wikipedia") return "wikipedia";
  if (sourceKind === "wiktionary") return "wiktionary";
  if (sourceKind === "internet-archive") return "internet-archive";
  if (Array.isArray(providers) && providers.length > 0) {
    const sorted = providers.slice().sort(
      (a, b) => (WEB_SEARCH_PROVIDER_PRIORITY[a.id] || 999) - (WEB_SEARCH_PROVIDER_PRIORITY[b.id] || 999),
    );
    return sorted[0].id;
  }
  return "";
}

function cleanContextValue(value) {
  return String(value || "").replace(/\s+/g, " ").trim();
}

function evidenceFromUserContext(userContext) {
  if (!userContext || typeof userContext !== "object") return [];
  const evidence = [];
  const fields = [
    ["uiLanguage", "ui_language"],
    ["browserLanguage", "browser_language"],
    ["colorScheme", "color_scheme"],
    ["timeZone", "time_zone"],
    ["locationInference", "location_inference"],
  ];
  for (const [key, label] of fields) {
    const value = cleanContextValue(userContext[key]);
    if (value) evidence.push(`user_context:${label}:${value}`);
  }
  return evidence;
}

function attachUserContext(answer, userContext) {
  if (!answer || typeof answer !== "object") return answer;
  const evidence = evidenceFromUserContext(userContext);
  if (evidence.length === 0) return answer;
  const steps = Array.isArray(answer.steps) ? answer.steps.slice() : [];
  const detail = evidence
    .map((item) => item.replace(/^user_context:/, ""))
    .join(", ");
  steps.push({ step: "user_context", detail });
  return Object.assign({}, answer, {
    evidence: [
      ...(Array.isArray(answer.evidence) ? answer.evidence : []),
      ...evidence,
    ],
    steps,
  });
}

// Issue #153: every prompt should be formalized as a Subject-Verb-Object tuple
// regardless of source language. We emit a deterministic, offline formalization
// here (so the trace is stable even when no APIs are reachable) and, when a
// downstream handler resolves the object to a Wikidata/Wikipedia/Wiktionary
// item, we emit a second `formalize_resolved` step with the real ids. Ids use
// canonical prefixes: `Q<n>` / `P<n>` for Wikidata, `WP:<title>` for
// Wikipedia-only items, `WT:<word>` for Wiktionary-only items, `OP:<verb>` for
// the symbolic operation, and `@USER` for the implicit user subject.
const FORMALIZATION_VERBS = [
  // English
  { verb: "what are the steps to", op: "OP:procedure" },
  { verb: "show me how to", op: "OP:procedure" },
  { verb: "tell me how to", op: "OP:procedure" },
  { verb: "how should i", op: "OP:procedure" },
  { verb: "how could i", op: "OP:procedure" },
  { verb: "how would i", op: "OP:procedure" },
  { verb: "how can i", op: "OP:procedure" },
  { verb: "how do i", op: "OP:procedure" },
  { verb: "how to", op: "OP:procedure" },
  { verb: "search", op: "OP:search" },
  { verb: "find", op: "OP:search" },
  { verb: "lookup", op: "OP:lookup" },
  { verb: "look up", op: "OP:lookup" },
  { verb: "define", op: "OP:define" },
  { verb: "what is", op: "OP:define" },
  { verb: "who is", op: "OP:identify" },
  { verb: "explain", op: "OP:define" },
  { verb: "compute", op: "OP:compute" },
  { verb: "calculate", op: "OP:compute" },
  { verb: "hello", op: "OP:greet" },
  { verb: "hi", op: "OP:greet" },
  { verb: "goodbye", op: "OP:farewell" },
  { verb: "bye", op: "OP:farewell" },
  // Russian
  { verb: "найди", op: "OP:search" },
  { verb: "поищи", op: "OP:search" },
  { verb: "поиск", op: "OP:search" },
  { verb: "что такое", op: "OP:define" },
  { verb: "кто такой", op: "OP:identify" },
  { verb: "объясни", op: "OP:define" },
  { verb: "посчитай", op: "OP:compute" },
  { verb: "вычисли", op: "OP:compute" },
  { verb: "привет", op: "OP:greet" },
  { verb: "здравствуй", op: "OP:greet" },
  { verb: "пока", op: "OP:farewell" },
  { verb: "до свидания", op: "OP:farewell" },
  // Hindi
  { verb: "खोज", op: "OP:search" },
  { verb: "ढूंढ", op: "OP:search" },
  { verb: "क्या है", op: "OP:define" },
  { verb: "कौन है", op: "OP:identify" },
  { verb: "नमस्ते", op: "OP:greet" },
  { verb: "अलविदा", op: "OP:farewell" },
  // Chinese
  { verb: "搜索", op: "OP:search" },
  { verb: "查找", op: "OP:search" },
  { verb: "什么是", op: "OP:define" },
  { verb: "是谁", op: "OP:identify" },
  { verb: "你好", op: "OP:greet" },
  { verb: "再见", op: "OP:farewell" },
];

function exactFormalizationMatch(prompt, normalized) {
  const haystack = String(normalized || "").toLowerCase();
  const raw = String(prompt || "");
  const rawLower = String(prompt || "").toLowerCase();
  for (const { verb, op } of FORMALIZATION_VERBS) {
    if (haystack.startsWith(verb + " ") || haystack === verb) {
      return {
        op,
        verb,
        objectText: haystack === verb ? "" : normalized.slice(verb.length),
        interpretations: [],
      };
    }
    if (rawLower.startsWith(verb + " ") || rawLower === verb) {
      return {
        op,
        verb,
        objectText: rawLower === verb ? "" : raw.slice(verb.length),
        interpretations: [],
      };
    }
    if (haystack.includes(" " + verb + " ")) {
      return { op, verb, objectText: null, interpretations: [] };
    }
  }
  return null;
}

function fuzzyFormalizationMatch(prompt) {
  const matches = FORMALIZATION_VERBS
    .map((entry) => {
      const match = fuzzyPrefixMatch(prompt, entry.verb);
      return match ? Object.assign({ entry }, match) : null;
    })
    .filter(Boolean)
    .sort((left, right) =>
      left.typoCount - right.typoCount || right.end - left.end,
    );
  const best = matches[0];
  if (!best) return null;
  const peers = matches.filter(
    (match) => match.typoCount === best.typoCount && match.end === best.end,
  );
  if (peers.length > 1) {
    return {
      ambiguous: true,
      suggestions: peers.map((match) => match.entry.verb),
      interpretations: [],
    };
  }
  return {
    op: best.entry.op,
    verb: best.entry.verb,
    objectText: String(prompt || "").slice(best.end),
    interpretations: [best.interpretation],
  };
}

function detectFormalizationMatch(prompt, normalized) {
  return exactFormalizationMatch(prompt, normalized) || fuzzyFormalizationMatch(prompt);
}

function objectForFormalization(prompt, normalized, match) {
  // For search-style ops we extract the explicit query the same way the web
  // search handler does. For other ops we keep the prompt body that follows
  // the detected verb so the tuple shows what the user is asking about.
  const op = match && match.op;
  if (op === "OP:search" || op === "OP:lookup") {
    const query = extractWebSearchQuery(prompt, normalized);
    if (query) return query;
  }
  if (op === "OP:procedure") {
    const task = extractProceduralHowToTask(normalized);
    if (task) return task.task;
  }
  const haystack = String(normalized || "").toLowerCase();
  for (const { verb } of FORMALIZATION_VERBS) {
    if (haystack.startsWith(verb + " ")) {
      return cleanSearchQuery(normalized.slice(verb.length));
    }
  }
  if (match && typeof match.objectText === "string") {
    return cleanSearchQuery(match.objectText);
  }
  return cleanSearchQuery(normalized || "");
}

function virtualObjectId(term) {
  const trimmed = String(term || "").trim();
  if (!trimmed) return "?";
  return `?${trimmed}`;
}

function formatFormalizationTuple(parts) {
  return `(${parts.filter(Boolean).join(" ")})`;
}

function buildFormalization(prompt, normalized) {
  const match = detectFormalizationMatch(prompt, normalized);
  if (!match || match.ambiguous) {
    const fallback = normalized || "(empty)";
    return {
      raw: String(prompt || ""),
      subject: "@USER",
      verb: "OP:express",
      object: virtualObjectId(fallback),
      tuple: formatFormalizationTuple(["@USER", "OP:express", virtualObjectId(fallback)]),
      needsClarification: Boolean(match && match.ambiguous),
      suggestions: match && match.suggestions ? match.suggestions : [],
      interpretations: [],
    };
  }
  const object = objectForFormalization(prompt, normalized, match);
  return {
    raw: String(prompt || ""),
    subject: "@USER",
    verb: match.op,
    object: virtualObjectId(object),
    tuple: formatFormalizationTuple(["@USER", match.op, virtualObjectId(object)]),
    interpretations: match.interpretations || [],
  };
}

function formalizationDetail(formalization) {
  if (!formalization || typeof formalization !== "object") {
    return String(formalization || "(empty)");
  }
  const arrow = formalization.raw && formalization.tuple ? " -> " : "";
  return `${formalization.raw || ""}${arrow}${formalization.tuple || ""}`.trim();
}

function formalizationClarificationMessage(formalization, language) {
  const suggestions = Array.isArray(formalization && formalization.suggestions)
    ? formalization.suggestions
    : [];
  const rendered = suggestions.length > 0
    ? suggestions.map((item) => `"${item}"`).join(", ")
    : "one of the known commands";
  if (language === "ru") {
    return `Не уверен, как интерпретировать этот запрос. Вы имели в виду ${rendered}?`;
  }
  if (language === "zh") {
    return `我不确定如何解释这个请求。你是指 ${rendered} 吗?`;
  }
  if (language === "hi") {
    return `मुझे पक्का नहीं है कि इस अनुरोध को कैसे समझूं। क्या आपका मतलब ${rendered} था?`;
  }
  return `I am not sure how to interpret that request. Did you mean ${rendered}?`;
}

// Once a handler resolves the search object to a concrete entity, this helper
// folds the resolved id back into the original formalization so the trace
// shows the canonical (@USER OP:search Q<id>) tuple alongside the placeholder.
function resolveFormalizationWithId(formalization, resolvedId) {
  if (!formalization || !resolvedId) return null;
  const next = Object.assign({}, formalization, {
    object: resolvedId,
    tuple: formatFormalizationTuple([
      formalization.subject || "@USER",
      formalization.verb || "OP:express",
      resolvedId,
    ]),
  });
  return next;
}

async function solve(prompt, history, prefs, userContext = {}) {
  const preferences = prefs || {};
  const autoDefinitionFusion = definitionFusionByDefault(preferences);
  const steps = [];
  const toolCalls = [];
  const events = [`impulse:${prompt}`];
  steps.push({ step: "impulse", detail: prompt });
  const normalized = normalizePrompt(prompt);
  const formalization = buildFormalization(prompt, normalized);
  events.push(`formalization:${formalization.tuple}`);
  steps.push({
    step: "formalize",
    detail: formalizationDetail(formalization),
    formalization: {
      raw: formalization.raw,
      subject: formalization.subject,
      verb: formalization.verb,
      object: formalization.object,
      tuple: formalization.tuple,
      interpretations: formalization.interpretations || [],
    },
  });
  const language = detectLanguage(prompt);
  events.push(`language:${language}`);
  steps.push({ step: "detect_language", detail: language });
  // Issue #324: resolve which language should drive natural-language responses
  // (defaults to the detected message language).
  const responseLanguage = responseLanguageFor(language, preferences, userContext);
  if (responseLanguage !== language) {
    events.push(`response_language:${responseLanguage}`);
    steps.push({ step: "resolve_response_language", detail: responseLanguage });
  }

  // Issue #180: bundle the per-turn formalization context so every
  // handler hit can fold a resolved entity id back into the tuple and
  // every `finalize` call can emit a `deformalize` step that records the
  // symbolic → natural-language projection. The context is mutable so
  // resolvers can update `resolved` as new ids surface.
  const formalizationContext = {
    initial: formalization,
    resolved: null,
    language,
  };

  if (formalization.needsClarification) {
    events.push("formalization:ambiguous");
    steps.push({
      step: "clarify_formalization",
      detail: (formalization.suggestions || []).join(", "),
    });
    return finalize(events, steps, toolCalls, {
      intent: "clarification",
      content: formalizationClarificationMessage(formalization, language),
      confidence: 0.4,
      evidence: ["formalization:ambiguous"],
    }, formalizationContext);
  }

  const behaviorRule = tryBehaviorRules(prompt, normalized, history, preferences);
  if (behaviorRule) {
    events.push(`handler:${behaviorRule.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryBehaviorRules" });
    return finalize(events, steps, toolCalls, behaviorRule, formalizationContext);
  }

  if (isPunctuationOnlyPrompt(prompt)) {
    events.push("handler:clarification");
    events.push(`clarification:punctuation_only:${String(prompt).trim()}`);
    steps.push({ step: "dispatch_handler", detail: "tryPunctuationOnlyPrompt" });
    const trimmed = String(prompt).trim();
    return finalize(events, steps, toolCalls, {
      intent: "clarification",
      content: `I received only punctuation (\`${trimmed}\`). What would you like me to do next?`,
      confidence: 0.8,
      evidence: [
        "handler:clarification",
        "clarification:punctuation_only",
        `language:${language}`,
      ],
    }, formalizationContext);
  }

  const translation = await tryTranslation(prompt, normalized);
  if (translation) {
    events.push(`handler:${translation.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryTranslation" });
    return finalize(events, steps, toolCalls, translation, formalizationContext);
  }

  steps.push({ step: "invoke_tool", detail: "wikipedia_article_question" });
  const earlyWikiArticleQuestion = await tryWikipediaArticleQuestion(
    prompt,
    language,
    preferences,
  );
  if (earlyWikiArticleQuestion) {
    events.push(`handler:${earlyWikiArticleQuestion.intent}`);
    steps.push({
      step: "dispatch_handler",
      detail: "tryWikipediaArticleQuestion",
    });
    toolCalls.push({
      tool: "wikipedia_article_question",
      inputs: {
        prompt,
        language,
        query: earlyWikiArticleQuestion.query || "",
      },
      outputs: {
        intent: earlyWikiArticleQuestion.intent,
        confidence: earlyWikiArticleQuestion.confidence,
        formalizedObject: earlyWikiArticleQuestion.formalizedObject || "",
      },
    });
    return finalize(
      events,
      steps,
      toolCalls,
      earlyWikiArticleQuestion,
      formalizationContext,
    );
  }

  const githubRepoInfoRequest = githubRepositoryInfoRequest(prompt, normalized);
  if (githubRepoInfoRequest) {
    steps.push({
      step: "invoke_tool",
      detail: `github_repo_info:${repositorySlug(githubRepoInfoRequest)}`,
    });
    const githubRepoInfo = await tryGithubRepositoryInfo(
      githubRepoInfoRequest,
      language,
    );
    events.push(`handler:${githubRepoInfo.intent}`);
    steps.push({
      step: "dispatch_handler",
      detail: "tryGithubRepositoryInfo",
    });
    toolCalls.push({
      tool: "github_repo_info",
      inputs: {
        prompt,
        language,
        repository: repositorySlug(githubRepoInfoRequest),
      },
      outputs: {
        intent: githubRepoInfo.intent,
        confidence: githubRepoInfo.confidence,
      },
    });
    return finalize(events, steps, toolCalls, githubRepoInfo, formalizationContext);
  }

  const capabilities = tryCapabilities(prompt, normalized, preferences, history);
  if (capabilities) {
    events.push(`handler:${capabilities.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryCapabilities" });
    return finalize(events, steps, toolCalls, capabilities, formalizationContext);
  }

  const architecture = tryArchitectureExplanation(prompt, normalized);
  if (architecture) {
    events.push("handler:meta_explanation");
    steps.push({ step: "dispatch_handler", detail: "tryArchitectureExplanation" });
    return finalize(events, steps, toolCalls, architecture, formalizationContext);
  }

  if (isGreetingPrompt(normalized, prompt)) {
    events.push("rule:greeting");
    steps.push({ step: "match_rule", detail: "greeting" });
    const temperature = numericPreference(preferences.temperature, 0.7, 0, 1);
    const randomize = preferences.greetingVariations !== false && temperature > 0;
    return finalize(events, steps, toolCalls, {
      intent: "greeting",
      content: answerFor("greeting", language, { randomize: randomize }),
      confidence: 1.0,
      evidence: [
        "rule:greeting",
        `language:${language}`,
        `variation:${randomize ? "random" : "canonical"}`,
        `temperature:${temperature.toFixed(2)}`,
      ],
    }, formalizationContext);
  }
  if (isFarewellPrompt(normalized, prompt)) {
    events.push("rule:farewell");
    steps.push({ step: "match_rule", detail: "farewell" });
    return finalize(events, steps, toolCalls, {
      intent: "farewell",
      content: answerFor("farewell", language),
      confidence: 1.0,
      evidence: ["rule:farewell", `language:${language}`],
    }, formalizationContext);
  }
  if (isTestStatusPrompt(normalized, prompt)) {
    events.push("rule:test_status");
    steps.push({ step: "match_rule", detail: "test_status" });
    return finalize(events, steps, toolCalls, {
      intent: "test_status",
      content: answerFor("test_status", language),
      confidence: 1.0,
      evidence: ["rule:test_status", `language:${language}`],
    });
  }
  if (isCourtesyResponsePrompt(normalized, prompt)) {
    events.push("rule:courtesy_response");
    steps.push({ step: "match_rule", detail: "courtesy_response" });
    const courtesy = courtesyResponseFor(language, preferences);
    return finalize(events, steps, toolCalls, {
      intent: "courtesy_response",
      content: courtesy.content,
      confidence: 1.0,
      evidence: [
        "rule:courtesy_response",
        `language:${language}`,
        `variation:${courtesy.randomize ? "random" : "canonical"}`,
        `temperature:${courtesy.temperature.toFixed(2)}`,
        `follow_up_probability:${courtesy.followUpProbability.toFixed(2)}`,
        `follow_up:${courtesy.followUpIncluded ? "included" : "omitted"}`,
      ],
    });
  }
  const calculatorRateBasis = tryCalculatorRateBasis(normalized, language);
  if (calculatorRateBasis) {
    events.push(`handler:${calculatorRateBasis.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryCalculatorRateBasis" });
    return finalize(events, steps, toolCalls, calculatorRateBasis, formalizationContext);
  }
  if (isAssistantNamePrompt(normalized, prompt)) {
    events.push("rule:assistant_name");
    steps.push({ step: "match_rule", detail: "assistant_name" });
    const configuredName = normalizeAssistantNamePreference(preferences.assistantName);
    return finalize(events, steps, toolCalls, {
      intent: "assistant_name",
      content: assistantNameAnswer(language, preferences),
      confidence: 1.0,
      evidence: [
        "rule:assistant_name",
        `language:${language}`,
        `assistant_name:${configuredName ? "configured" : "not_set"}`,
      ],
    }, formalizationContext);
  }
  if (isIdentityPrompt(normalized, prompt)) {
    events.push("rule:identity");
    steps.push({ step: "match_rule", detail: "identity" });
    return finalize(events, steps, toolCalls, {
      intent: "identity",
      content: answerFor("identity", language),
      confidence: 1.0,
      evidence: ["rule:identity", `language:${language}`],
    }, formalizationContext);
  }

  // Issue #312: compute the write-program result once so a concrete program
  // request (a known language + task with a template) can take precedence over
  // the concept lookup, while the "unsupported" variant still falls back after
  // the definition/concept handlers. This mirrors the Rust solver, where
  // `SelectedRule::WriteProgram` is promoted above `handle_specialized_pattern`
  // so "напиши программу на Rust" is not answered as a "Rust" encyclopedia entry.
  let writeProgramResult;
  const writeProgram = () => {
    if (writeProgramResult === undefined) {
      writeProgramResult = tryWriteProgram(
        prompt,
        history,
        responseLanguage,
        preferences.blueprintComposition,
      );
    }
    return writeProgramResult;
  };
  const syncHandlers = [
    { name: "tryLinkNativeSynthesis", run: () => tryLinkNativeSynthesis(prompt, normalized) },
    { name: "tryHistorical", run: () => tryHistorical(prompt, history) },
    {
      name: "tryResearchComparisonTable",
      run: () => tryResearchComparisonTable(prompt, normalized, history),
    },
    { name: "tryBrainstormingRequest", run: () => tryBrainstormingRequest(prompt, normalized) },
    { name: "tryRoleplayRequest", run: () => tryRoleplayRequest(prompt, normalized) },
    { name: "tryKupiSlona", run: () => tryKupiSlona(prompt, normalized) },
    {
      name: "tryCalendarReasoning",
      run: () => tryCalendarReasoning(prompt, normalized, userContext),
    },
    {
      name: "tryProofRequest",
      run: () => tryProofRequest(prompt, normalized, language),
    },
    // Issue #135/#386: a Playwright-script request is more specific than the
    // generalized write_program recognizer. Since #386 taught
    // writeProgramParameters to recognize a program_kind ("скрипт"/"script")
    // requested by a program_request verb ("написать"/"write"), a bare
    // "напиши … playwright скрипт" now also looks like a write_program with no
    // task — so the Playwright handler must win first. This mirrors the Rust
    // dispatch, where try_playwright_script runs ahead of the SPECIALIZED_HANDLERS
    // group that owns write_program (src/solver.rs).
    {
      name: "tryPlaywrightScript",
      run: () => tryPlaywrightScript(prompt, preferences, language),
    },
    {
      name: "tryWriteProgramCoreference",
      run: () => {
        const hit = writeProgram();
        return hit &&
          hit.intent === "write_program" &&
          hit.evidence?.some((link) => link.startsWith("write_program_coreference_rewrite:"))
          ? hit
          : null;
      },
    },
    { name: "tryTextManipulation", run: () => tryTextManipulation(prompt, normalized) },
    { name: "tryProgramSynthesis", run: () => tryProgramSynthesis(prompt, normalized) },
    {
      name: "tryCompoundInterest",
      run: () => tryCompoundInterest(prompt, normalized, history),
    },
    { name: "tryArithmetic", run: () => tryArithmetic(prompt) },
    { name: "tryJavaScriptExecution", run: () => tryJavaScriptExecution(prompt) },
    {
      name: "tryWriteProgramConcrete",
      run: () => {
        const hit = writeProgram();
        return hit && hit.intent === "write_program" ? hit : null;
      },
    },
    {
      name: "tryDefinitionMerge",
      run: () => tryDefinitionMerge(prompt, { allowPlainConcept: autoDefinitionFusion }),
    },
    // Issue #341: keep a "test it / run it / show me" step inside the active
    // software-project dialogue instead of letting it resolve as a concept
    // lookup. Must run before tryConceptLookup and trySoftwareProjectRequest.
    {
      name: "trySoftwareProjectFollowup",
      run: () => trySoftwareProjectFollowup(prompt, history),
    },
    { name: "tryConceptLookup", run: () => tryConceptLookup(prompt) },
    { name: "tryWriteProgram", run: () => writeProgram() },
    { name: "trySoftwareProjectRequest", run: () => trySoftwareProjectRequest(prompt, history) },
  ];
  for (const handler of syncHandlers) {
    const hit = handler.run();
    if (hit) {
      events.push(`handler:${hit.intent}`);
      steps.push({ step: "dispatch_handler", detail: handler.name });
      if (Array.isArray(hit.steps)) {
        for (const step of hit.steps) steps.push(step);
      }
      if (Array.isArray(hit.trace)) {
        for (const event of hit.trace) events.push(event);
      }
      if (hit.intent === "javascript_execution" || hit.intent === "javascript_execution_error") {
        toolCalls.push({
          tool: "eval_js",
          inputs: { prompt },
          outputs: { intent: hit.intent, confidence: hit.confidence },
        });
      }
      if (
        hit.intent === "concept_lookup" ||
        hit.intent === "concept_lookup_in_context" ||
        hit.intent === "definition_merge"
      ) {
        toolCalls.push({
          tool: "concept_lookup",
          inputs: { prompt },
          outputs: { intent: hit.intent, confidence: hit.confidence },
        });
      }
      return finalize(events, steps, toolCalls, hit, formalizationContext);
    }
  }

  // Real-time fact reasoning: parse structured (relation, subject) queries, hit
  // the 1-week TTL cache, fall back to Wikidata/Wikipedia for any country or
  // entity. Cache warmed from `data/seed/facts.lino` so the test matrix and
  // offline browsers still answer instantly. The legacy substring-based
  // `tryFactLookup` remains as a fallback for non-relation seed facts
  // (e.g. who painted the Mona Lisa) until those are migrated to relations.
  steps.push({ step: "invoke_tool", detail: "fact_query" });
  const factQuery = await tryFactQuery(prompt, normalized, preferences);
  if (factQuery) {
    events.push(`handler:${factQuery.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryFactQuery" });
    if (Array.isArray(factQuery.trace)) {
      for (const event of factQuery.trace) events.push(event);
    }
    toolCalls.push({
      tool: "fact_query",
      inputs: { prompt, language },
      outputs: {
        intent: factQuery.intent,
        confidence: factQuery.confidence,
        formalizedObject: factQuery.formalizedObject || "",
      },
    });
    return finalize(events, steps, toolCalls, factQuery, formalizationContext);
  }

  const legacyFact = tryFactLookup(prompt, normalized);
  if (legacyFact) {
    events.push(`handler:${legacyFact.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryFactLookup" });
    return finalize(events, steps, toolCalls, legacyFact, formalizationContext);
  }

  steps.push({ step: "invoke_tool", detail: "project_lookup" });
  const projectLookup = await tryProjectLookup(prompt, language, preferences);
  if (projectLookup) {
    events.push(`handler:${projectLookup.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryProjectLookup" });
    toolCalls.push({
      tool: "project_lookup",
      inputs: { prompt, language },
      outputs: {
        intent: projectLookup.intent,
        confidence: projectLookup.confidence,
      },
    });
    return finalize(events, steps, toolCalls, projectLookup);
  }

  steps.push({ step: "invoke_tool", detail: "http_fetch" });
  const fetched = await tryFetch(prompt);
  if (fetched) {
    events.push(`handler:${fetched.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryFetch" });
    toolCalls.push({
      tool: "http_fetch",
      inputs: { prompt },
      outputs: { intent: fetched.intent, confidence: fetched.confidence, iframeUrl: fetched.iframeUrl || null },
    });
    return finalize(events, steps, toolCalls, fetched, formalizationContext);
  }

  steps.push({ step: "invoke_tool", detail: "url_navigate" });
  const navigated = await tryUrlNavigate(prompt);
  if (navigated) {
    events.push(`handler:${navigated.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryUrlNavigate" });
    toolCalls.push({
      tool: "url_navigate",
      inputs: { prompt },
      outputs: { intent: navigated.intent, confidence: navigated.confidence, iframeUrl: navigated.iframeUrl || null },
    });
    return finalize(events, steps, toolCalls, navigated, formalizationContext);
  }

  steps.push({ step: "invoke_tool", detail: "docs_method_explanation" });
  const docsMethod = tryDocsMethodExplanation(prompt, language);
  if (docsMethod) {
    events.push(`handler:${docsMethod.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryDocsMethodExplanation" });
    toolCalls.push({
      tool: "docs_method_explanation",
      inputs: { prompt, language, project: "pandas", method: "DataFrame.join" },
      outputs: {
        intent: docsMethod.intent,
        confidence: docsMethod.confidence,
        formalizedObject: docsMethod.formalizedObject || "",
      },
    });
    return finalize(events, steps, toolCalls, docsMethod, formalizationContext);
  }

  steps.push({ step: "invoke_tool", detail: "procedural_how_to" });
  const procedure = await tryProceduralHowTo(prompt, language);
  if (procedure) {
    events.push(`handler:${procedure.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryProceduralHowTo" });
    toolCalls.push({
      tool: "procedural_how_to",
      inputs: {
        prompt,
        language,
        query: procedure.query || "",
        wikihowCandidate: procedure.wikihowCandidate || "",
      },
      outputs: {
        intent: procedure.intent,
        confidence: procedure.confidence,
        formalizedObject: procedure.formalizedObject || "",
      },
    });
    return finalize(events, steps, toolCalls, procedure, formalizationContext);
  }

  steps.push({ step: "invoke_tool", detail: "web_search" });
  const webSearch = await tryWebSearch(prompt, language);
  if (webSearch) {
    events.push(`handler:${webSearch.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryWebSearch" });
    toolCalls.push({
      tool: "web_search",
      inputs: { prompt, language, query: webSearch.query || "" },
      outputs: {
        intent: webSearch.intent,
        confidence: webSearch.confidence,
        formalizedObject: webSearch.formalizedObject || "",
      },
    });
    return finalize(events, steps, toolCalls, webSearch, formalizationContext);
  }

  steps.push({ step: "invoke_tool", detail: "wikipedia_lookup" });
  const wiki = await tryWikipediaLookup(prompt, language, preferences);
  if (wiki) {
    events.push(`handler:${wiki.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryWikipediaLookup" });
    toolCalls.push({
      tool: "wikipedia_lookup",
      inputs: {
        prompt,
        language,
        guessProbability: numericPreference(
          preferences.guessProbability,
          0.8,
          0,
          1,
        ),
      },
      outputs: { intent: wiki.intent, confidence: wiki.confidence },
    });
    return finalize(events, steps, toolCalls, wiki, formalizationContext);
  }
  toolCalls.push({
    tool: "wikipedia_lookup",
    inputs: { prompt, language },
    outputs: { intent: "no_match" },
  });

  // Issue #69: "who is X" prompts that were not resolved by the local
  // knowledge base or Wikipedia should still return a question-typed response
  // (not "unknown") and offer a typo correction when the entity name is close
  // to a known variant.
  const whoIs = tryWhoIsQuestion(prompt);
  if (whoIs) {
    events.push(`handler:${whoIs.intent}`);
    steps.push({ step: "dispatch_handler", detail: "tryWhoIsQuestion" });
    return finalize(events, steps, toolCalls, whoIs, formalizationContext);
  }

  events.push("fallback:unknown");
  steps.push({ step: "fallback", detail: "unknown" });
  return finalize(events, steps, toolCalls, {
    intent: "unknown",
    content: unknownAnswerWithVariation(prompt, language),
    confidence: 0.1,
    evidence: ["fallback:unknown", `language:${language}`],
  }, formalizationContext);
}

// Issue #180: every handler hit flows through this helper so the trace shows
// the resolved-formalization fold (when the handler exposes a `formalizedObject`)
// followed by a uniform `deformalize` step that captures how the symbolic
// answer was projected into the natural-language `content`. Keeping the logic
// here means new handlers automatically participate in the architecture
// without having to repeat the bookkeeping.
function applyResolvedFormalization(events, steps, formalizationContext, answer) {
  if (!formalizationContext || !answer || !answer.formalizedObject) return;
  const resolved = resolveFormalizationWithId(
    formalizationContext.initial,
    answer.formalizedObject,
  );
  if (!resolved) return;
  // Skip the extra step when the placeholder already matched the resolved id
  // (e.g. cache hits where the formalization tuple already had a Q-id).
  if (resolved.tuple === formalizationContext.initial.tuple) return;
  formalizationContext.resolved = resolved;
  events.push(`formalization:resolved:${resolved.tuple}`);
  steps.push({
    step: "formalize_resolved",
    detail: formalizationDetail(resolved),
    formalization: {
      raw: resolved.raw,
      subject: resolved.subject,
      verb: resolved.verb,
      object: resolved.object,
      tuple: resolved.tuple,
    },
  });
}

function collectInterpretations(formalizationContext, answer) {
  const combined = [];
  const pushAll = (items) => {
    if (!Array.isArray(items)) return;
    for (const item of items) {
      if (!item || !item.original || !item.corrected) continue;
      combined.push({
        original: String(item.original),
        corrected: String(item.corrected),
      });
    }
  };
  pushAll(
    formalizationContext &&
      formalizationContext.initial &&
      formalizationContext.initial.interpretations,
  );
  pushAll(answer && answer.interpretations);
  const seen = new Set();
  return combined.filter((item) => {
    const key = `${item.original.toLowerCase()}\u0000${item.corrected.toLowerCase()}`;
    if (seen.has(key)) return false;
    seen.add(key);
    return true;
  });
}

function interpretationStatements(interpretations) {
  return interpretations
    .map((item) => `Interpreted "${item.original}" as "${item.corrected}".`)
    .join("\n");
}

function applyVisibleInterpretations(answer, interpretations) {
  if (!answer || interpretations.length === 0) return answer;
  const statements = interpretationStatements(interpretations);
  return Object.assign({}, answer, {
    content: `${statements}\n\n${String(answer.content || "")}`,
    evidence: [
      ...(Array.isArray(answer.evidence) ? answer.evidence : []),
      ...interpretations.map((item) => `interpretation:${item.original}->${item.corrected}`),
    ],
  });
}

function deformalizeProjection(formalizationContext, answer) {
  const tuple =
    (formalizationContext &&
      ((formalizationContext.resolved && formalizationContext.resolved.tuple) ||
        (formalizationContext.initial && formalizationContext.initial.tuple))) ||
    "(@USER OP:express ?)";
  const evidence = Array.isArray(answer.evidence) ? answer.evidence : [];
  const content = String(answer.content || "");
  const firstLine = content.split(/\r?\n/, 1)[0] || "";
  const projection = firstLine.length > 96 ? `${firstLine.slice(0, 96)}…` : firstLine;
  return {
    tuple,
    intent: answer.intent || "unknown",
    contentChars: content.length,
    evidenceCount: evidence.length,
    language:
      (formalizationContext && formalizationContext.language) ||
      answer.language ||
      "",
    summary: `${tuple} ⇒ ${answer.intent || "unknown"}: ${projection}`,
  };
}

function finalize(events, steps, toolCalls, answer, formalizationContext) {
  const interpretations = collectInterpretations(formalizationContext, answer);
  answer = applyVisibleInterpretations(answer, interpretations);
  applyResolvedFormalization(events, steps, formalizationContext, answer);
  const evidence = Array.isArray(answer.evidence) ? answer.evidence : [];
  const projection = deformalizeProjection(formalizationContext, answer);
  events.push(`deformalize:${projection.tuple}:${projection.intent}`);
  steps.push({
    step: "deformalize",
    detail: projection.summary,
    projection,
  });
  const trace = events.map((event) => `trace:${event}`);
  const result = {
    intent: answer.intent,
    content: answer.content,
    confidence: answer.confidence,
    evidence: [...evidence, ...trace],
    steps,
    toolCalls,
  };
  if (answer.iframeUrl) {
    result.iframeUrl = answer.iframeUrl;
  }
  if (answer.diagnostics) {
    result.diagnostics = answer.diagnostics;
  }
  return result;
}

let seedLoaded = false;

async function loadSeed() {
  if (seedLoaded) return;
  seedLoaded = true;
  if (typeof self.FormalAiSeed !== "object" || self.FormalAiSeed === null) {
    return;
  }
  try {
    const seed = await self.FormalAiSeed.loadAll();
    SEED_RAW = (seed && seed.raw) || {};
    if (seed && seed.responses) {
      const merged = {};
      const intents = new Set(
        Object.keys(MULTILINGUAL_ANSWERS).concat(Object.keys(seed.responses)),
      );
      intents.forEach((intent) => {
        const base = MULTILINGUAL_ANSWERS[intent] || {};
        const next = seed.responses[intent] || {};
        const byLanguage = {};
        const langs = new Set(Object.keys(base).concat(Object.keys(next)));
        langs.forEach((language) => {
          const incoming = next[language];
          if (incoming !== undefined) {
            byLanguage[language] = normalizeEntry(incoming, intent);
          } else {
            byLanguage[language] = normalizeEntry(base[language], intent);
          }
        });
        merged[intent] = byLanguage;
      });
      MULTILINGUAL_ANSWERS = merged;
    }
    if (Array.isArray(seed && seed.concepts) && seed.concepts.length > 0) {
      CONCEPTS = seed.concepts;
    }
    if (
      Array.isArray(seed && seed.conceptContexts) &&
      seed.conceptContexts.length > 0
    ) {
      CONCEPT_CONTEXTS = seed.conceptContexts;
    }
    if (Array.isArray(seed && seed.facts) && seed.facts.length > 0) {
      FACTS = seed.facts;
      warmFactCacheFromSeed();
    }
    if (Array.isArray(seed && seed.projects) && seed.projects.length > 0) {
      PROJECTS = seed.projects;
    }
    if (
      seed &&
      seed.brainstormSeeds &&
      Array.isArray(seed.brainstormSeeds.triggers) &&
      seed.brainstormSeeds.triggers.length > 0
    ) {
      BRAINSTORM_SEEDS = seed.brainstormSeeds;
    }
    if (
      seed &&
      seed.personas &&
      Array.isArray(seed.personas.triggers) &&
      seed.personas.triggers.length > 0
    ) {
      PERSONA_SEEDS = seed.personas;
    }
    if (Array.isArray(seed && seed.tools) && seed.tools.length > 0) {
      TOOLS = seed.tools;
    }
    if (seed && seed.agentInfo && typeof seed.agentInfo === "object") {
      AGENT_INFO = Object.assign({}, AGENT_INFO, seed.agentInfo);
    }
    if (Array.isArray(seed && seed.languageRules) && seed.languageRules.length > 0) {
      LANGUAGE_RULES = seed.languageRules
        .filter((rule) => rule && rule.language && rule.start && rule.end)
        .map((rule) => ({
          language: rule.language,
          start: Number(rule.start),
          end: Number(rule.end),
        }));
    }
    if (Array.isArray(seed && seed.promptPatterns) && seed.promptPatterns.length > 0) {
      PROMPT_PATTERNS = seed.promptPatterns;
    }
    if (
      seed &&
      seed.intentRouting &&
      Array.isArray(seed.intentRouting.intents) &&
      seed.intentRouting.intents.length > 0
    ) {
      INTENT_ROUTING = {
        intents: seed.intentRouting.intents,
        articlePrefixes:
          seed.intentRouting.articlePrefixes && seed.intentRouting.articlePrefixes.length
            ? seed.intentRouting.articlePrefixes
            : INTENT_ROUTING.articlePrefixes,
        tracePrefixes:
          seed.intentRouting.tracePrefixes && seed.intentRouting.tracePrefixes.length
            ? seed.intentRouting.tracePrefixes
            : INTENT_ROUTING.tracePrefixes,
      };
    }
  } catch (_error) {
    // Keep fallback tables on error.
  }
}

async function init() {
  if (wasm !== undefined) return;
  await loadSeed();
  try {
    const source = await fetch(withAssetVersion("formal_ai_worker.wasm"));
    const bytes = await source.arrayBuffer();
    const module = await WebAssembly.instantiate(bytes, {});
    wasm = module.instance.exports;
  } catch (_error) {
    wasm = null;
    mode = "js fallback";
  }
  postMessage({
    kind: "ready",
    mode,
    seed: {
      responseIntents: Object.keys(MULTILINGUAL_ANSWERS),
      conceptCount: CONCEPTS.length,
      conceptContextCount: CONCEPT_CONTEXTS.length,
      factCount: FACTS.length,
      projectCount: PROJECTS.length,
      brainstormCategoryCount: BRAINSTORM_SEEDS.categories.length,
      personaCount: PERSONA_SEEDS.personas.length,
      toolCount: TOOLS.length,
      files: Object.keys(SEED_RAW),
    },
  });
}

self.onmessage = async (event) => {
  await init();
  const data = event.data || {};
  if (data.kind === "seed_dump") {
    postMessage({
      kind: "seed_dump",
      requestId: data.requestId,
      raw: SEED_RAW,
      responses: MULTILINGUAL_ANSWERS,
      concepts: CONCEPTS,
      conceptContexts: CONCEPT_CONTEXTS,
      facts: FACTS,
      projects: PROJECTS,
      brainstormSeeds: BRAINSTORM_SEEDS,
      personas: PERSONA_SEEDS,
      tools: TOOLS,
      agentInfo: AGENT_INFO,
      languageRules: LANGUAGE_RULES,
      promptPatterns: PROMPT_PATTERNS,
    });
    return;
  }
  const prompt = data.prompt || "";
  const history = Array.isArray(data.history) ? data.history : [];
  const prefs = (data.prefs && typeof data.prefs === "object") ? data.prefs : {};
  const userContext =
    data.userContext && typeof data.userContext === "object"
      ? data.userContext
      : {};
  const answer = attachUserContext(
    await solve(prompt, history, prefs, userContext),
    userContext,
  );
  postMessage({
    kind: "message",
    requestId: data.requestId,
    intent: answer.intent,
    content: answer.content,
    confidence: answer.confidence,
    evidence: answer.evidence,
    steps: answer.steps,
    toolCalls: answer.toolCalls,
    iframeUrl: answer.iframeUrl || null,
    diagnostics: answer.diagnostics || null,
  });
};

init();