@intellectif/lk-core 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @intellectif/lk-core
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 722de91: Node 22 is the floor, and the published `engines` says so.
8
+
9
+ Both packages declared `engines: { node: '>=20' }` while CI stopped testing Node 20 in `e17f5fa` (pnpm 11 compatibility) and Node 20 itself reached end of life in April 2026. A support claim nothing verifies is worse than a narrow one: it invites an install onto a runtime no test has touched for months. The floor is now `>=22`, which is what CI has actually been proving all along — Node 22 (the LTS most consumers run) and Node 24 (the Node the Release job builds the published tarball on).
10
+
11
+ If you are still on Node 20, this is the release to stop at; nothing here changes behaviour on a supported runtime.
12
+
3
13
  ## 0.10.1
4
14
 
5
15
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectif/lk-core",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "Framework-free assessment core: Zod activity schemas, pure scoring, rubric & deferred grading, weighted assessment composition, exam attempt plans, and xAPI 1.0.3.",
5
5
  "keywords": [
6
6
  "assessment",
@@ -92,7 +92,7 @@
92
92
  "license": "MIT",
93
93
  "sideEffects": false,
94
94
  "engines": {
95
- "node": ">=20"
95
+ "node": ">=22"
96
96
  },
97
97
  "scripts": {
98
98
  "build": "tsup",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$comment": "Grade-stability corpus for @intellectif/lk-core. Generated by scripts/generate-vectors.mjs from the built package; never edit expectations by hand. Replay with vectors/replay.mjs. See vectors/README.md.",
3
3
  "corpusVersion": 1,
4
- "frozenFrom": "@intellectif/lk-core@0.8.1",
4
+ "frozenFrom": "@intellectif/lk-core@0.10.1",
5
5
  "vectors": [
6
6
  {
7
7
  "args": [
@@ -1319,6 +1319,861 @@
1319
1319
  "id": "score/fib/partial/two-of-three",
1320
1320
  "note": "A non-terminating ratio (2/3), pinned exactly rather than approximately."
1321
1321
  },
1322
+ {
1323
+ "args": [
1324
+ "fill-in-the-blanks",
1325
+ {
1326
+ "blanks": [
1327
+ {
1328
+ "acceptedAnswers": ["a"],
1329
+ "id": "b1"
1330
+ },
1331
+ {
1332
+ "acceptedAnswers": ["the"],
1333
+ "id": "b2"
1334
+ },
1335
+ {
1336
+ "acceptedAnswers": ["the"],
1337
+ "id": "b3"
1338
+ }
1339
+ ],
1340
+ "id": "fib-articles",
1341
+ "passage": "We bought {{b1}} lamp for {{b2}} study and {{b3}} hall.",
1342
+ "schemaVersion": "1.0",
1343
+ "scoringStrategy": "all-or-nothing",
1344
+ "title": "Articles",
1345
+ "type": "fill-in-the-blanks"
1346
+ },
1347
+ {
1348
+ "answers": {
1349
+ "b1": "a",
1350
+ "b2": "the",
1351
+ "b3": "the"
1352
+ },
1353
+ "type": "fill-in-the-blanks"
1354
+ }
1355
+ ],
1356
+ "expect": {
1357
+ "details": [
1358
+ {
1359
+ "correct": true,
1360
+ "correctResponse": ["a"],
1361
+ "itemId": "b1",
1362
+ "learnerResponse": ["a"],
1363
+ "outcome": "correct",
1364
+ "weight": 1
1365
+ },
1366
+ {
1367
+ "correct": true,
1368
+ "correctResponse": ["the"],
1369
+ "itemId": "b2",
1370
+ "learnerResponse": ["the"],
1371
+ "outcome": "correct",
1372
+ "weight": 1
1373
+ },
1374
+ {
1375
+ "correct": true,
1376
+ "correctResponse": ["the"],
1377
+ "itemId": "b3",
1378
+ "learnerResponse": ["the"],
1379
+ "outcome": "correct",
1380
+ "weight": 1
1381
+ }
1382
+ ],
1383
+ "feedback": null,
1384
+ "maxScore": 1,
1385
+ "passed": true,
1386
+ "score": 1
1387
+ },
1388
+ "fn": "score",
1389
+ "id": "score/fib/all-or-nothing/every-blank-right"
1390
+ },
1391
+ {
1392
+ "args": [
1393
+ "fill-in-the-blanks",
1394
+ {
1395
+ "blanks": [],
1396
+ "id": "fib-articles",
1397
+ "passage": "Nothing to fill.",
1398
+ "schemaVersion": "1.0",
1399
+ "scoringStrategy": "all-or-nothing",
1400
+ "title": "Articles",
1401
+ "type": "fill-in-the-blanks"
1402
+ },
1403
+ {
1404
+ "answers": {},
1405
+ "type": "fill-in-the-blanks"
1406
+ }
1407
+ ],
1408
+ "expect": {
1409
+ "details": [],
1410
+ "feedback": null,
1411
+ "maxScore": 1,
1412
+ "passed": true,
1413
+ "score": 1
1414
+ },
1415
+ "fn": "score",
1416
+ "id": "score/fib/all-or-nothing/empty-blank-list"
1417
+ },
1418
+ {
1419
+ "args": [
1420
+ "gap-select",
1421
+ {
1422
+ "banks": [
1423
+ {
1424
+ "choices": [
1425
+ {
1426
+ "id": "of",
1427
+ "text": "of"
1428
+ },
1429
+ {
1430
+ "id": "from",
1431
+ "text": "from"
1432
+ },
1433
+ {
1434
+ "id": "to",
1435
+ "text": "to"
1436
+ },
1437
+ {
1438
+ "id": "on",
1439
+ "text": "on"
1440
+ }
1441
+ ],
1442
+ "id": "prep"
1443
+ }
1444
+ ],
1445
+ "gaps": [
1446
+ {
1447
+ "bankId": "prep",
1448
+ "correctChoiceId": "from",
1449
+ "id": "a"
1450
+ },
1451
+ {
1452
+ "bankId": "prep",
1453
+ "correctChoiceId": "from",
1454
+ "id": "b"
1455
+ }
1456
+ ],
1457
+ "id": "gs-prepositions",
1458
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1459
+ "schemaVersion": "1.0",
1460
+ "scoringStrategy": "partial",
1461
+ "title": "Prepositions",
1462
+ "type": "gap-select"
1463
+ },
1464
+ {
1465
+ "selections": {
1466
+ "a": "from",
1467
+ "b": "from"
1468
+ },
1469
+ "type": "gap-select"
1470
+ }
1471
+ ],
1472
+ "expect": {
1473
+ "details": [
1474
+ {
1475
+ "correct": true,
1476
+ "correctResponse": ["from"],
1477
+ "itemId": "a",
1478
+ "learnerResponse": ["from"],
1479
+ "outcome": "correct",
1480
+ "weight": 1
1481
+ },
1482
+ {
1483
+ "correct": true,
1484
+ "correctResponse": ["from"],
1485
+ "itemId": "b",
1486
+ "learnerResponse": ["from"],
1487
+ "outcome": "correct",
1488
+ "weight": 1
1489
+ }
1490
+ ],
1491
+ "feedback": null,
1492
+ "maxScore": 1,
1493
+ "passed": true,
1494
+ "score": 1
1495
+ },
1496
+ "fn": "score",
1497
+ "id": "score/gs/partial/both-right"
1498
+ },
1499
+ {
1500
+ "args": [
1501
+ "gap-select",
1502
+ {
1503
+ "banks": [
1504
+ {
1505
+ "choices": [
1506
+ {
1507
+ "id": "of",
1508
+ "text": "of"
1509
+ },
1510
+ {
1511
+ "id": "from",
1512
+ "text": "from"
1513
+ },
1514
+ {
1515
+ "id": "to",
1516
+ "text": "to"
1517
+ },
1518
+ {
1519
+ "id": "on",
1520
+ "text": "on"
1521
+ }
1522
+ ],
1523
+ "id": "prep"
1524
+ }
1525
+ ],
1526
+ "gaps": [
1527
+ {
1528
+ "bankId": "prep",
1529
+ "correctChoiceId": "from",
1530
+ "id": "a"
1531
+ },
1532
+ {
1533
+ "bankId": "prep",
1534
+ "correctChoiceId": "from",
1535
+ "id": "b"
1536
+ }
1537
+ ],
1538
+ "id": "gs-prepositions",
1539
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1540
+ "schemaVersion": "1.0",
1541
+ "scoringStrategy": "partial",
1542
+ "title": "Prepositions",
1543
+ "type": "gap-select"
1544
+ },
1545
+ {
1546
+ "selections": {
1547
+ "a": "from",
1548
+ "b": "to"
1549
+ },
1550
+ "type": "gap-select"
1551
+ }
1552
+ ],
1553
+ "expect": {
1554
+ "details": [
1555
+ {
1556
+ "correct": true,
1557
+ "correctResponse": ["from"],
1558
+ "itemId": "a",
1559
+ "learnerResponse": ["from"],
1560
+ "outcome": "correct",
1561
+ "weight": 1
1562
+ },
1563
+ {
1564
+ "correct": false,
1565
+ "correctResponse": ["from"],
1566
+ "itemId": "b",
1567
+ "learnerResponse": ["to"],
1568
+ "outcome": "incorrect",
1569
+ "weight": 1
1570
+ }
1571
+ ],
1572
+ "feedback": null,
1573
+ "maxScore": 1,
1574
+ "passed": false,
1575
+ "score": 0.5
1576
+ },
1577
+ "fn": "score",
1578
+ "id": "score/gs/partial/one-right"
1579
+ },
1580
+ {
1581
+ "args": [
1582
+ "gap-select",
1583
+ {
1584
+ "banks": [
1585
+ {
1586
+ "choices": [
1587
+ {
1588
+ "id": "of",
1589
+ "text": "of"
1590
+ },
1591
+ {
1592
+ "id": "from",
1593
+ "text": "from"
1594
+ },
1595
+ {
1596
+ "id": "to",
1597
+ "text": "to"
1598
+ },
1599
+ {
1600
+ "id": "on",
1601
+ "text": "on"
1602
+ }
1603
+ ],
1604
+ "id": "prep"
1605
+ }
1606
+ ],
1607
+ "gaps": [
1608
+ {
1609
+ "bankId": "prep",
1610
+ "correctChoiceId": "from",
1611
+ "id": "a"
1612
+ },
1613
+ {
1614
+ "bankId": "prep",
1615
+ "correctChoiceId": "from",
1616
+ "id": "b"
1617
+ }
1618
+ ],
1619
+ "id": "gs-prepositions",
1620
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1621
+ "schemaVersion": "1.0",
1622
+ "scoringStrategy": "partial",
1623
+ "title": "Prepositions",
1624
+ "type": "gap-select"
1625
+ },
1626
+ {
1627
+ "selections": {
1628
+ "a": "from"
1629
+ },
1630
+ "type": "gap-select"
1631
+ }
1632
+ ],
1633
+ "expect": {
1634
+ "details": [
1635
+ {
1636
+ "correct": true,
1637
+ "correctResponse": ["from"],
1638
+ "itemId": "a",
1639
+ "learnerResponse": ["from"],
1640
+ "outcome": "correct",
1641
+ "weight": 1
1642
+ },
1643
+ {
1644
+ "correct": false,
1645
+ "correctResponse": ["from"],
1646
+ "itemId": "b",
1647
+ "learnerResponse": [""],
1648
+ "outcome": "incorrect-omission",
1649
+ "weight": 1
1650
+ }
1651
+ ],
1652
+ "feedback": null,
1653
+ "maxScore": 1,
1654
+ "passed": false,
1655
+ "score": 0.5
1656
+ },
1657
+ "fn": "score",
1658
+ "id": "score/gs/partial/unanswered-gap"
1659
+ },
1660
+ {
1661
+ "args": [
1662
+ "gap-select",
1663
+ {
1664
+ "banks": [
1665
+ {
1666
+ "choices": [
1667
+ {
1668
+ "id": "of",
1669
+ "text": "of"
1670
+ },
1671
+ {
1672
+ "id": "from",
1673
+ "text": "from"
1674
+ },
1675
+ {
1676
+ "id": "to",
1677
+ "text": "to"
1678
+ },
1679
+ {
1680
+ "id": "on",
1681
+ "text": "on"
1682
+ }
1683
+ ],
1684
+ "id": "prep"
1685
+ }
1686
+ ],
1687
+ "gaps": [
1688
+ {
1689
+ "bankId": "prep",
1690
+ "correctChoiceId": "from",
1691
+ "id": "a"
1692
+ },
1693
+ {
1694
+ "bankId": "prep",
1695
+ "correctChoiceId": "from",
1696
+ "id": "b"
1697
+ }
1698
+ ],
1699
+ "id": "gs-prepositions",
1700
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1701
+ "schemaVersion": "1.0",
1702
+ "scoringStrategy": "partial",
1703
+ "title": "Prepositions",
1704
+ "type": "gap-select"
1705
+ },
1706
+ {
1707
+ "selections": {
1708
+ "a": "from",
1709
+ "b": ""
1710
+ },
1711
+ "type": "gap-select"
1712
+ }
1713
+ ],
1714
+ "expect": {
1715
+ "details": [
1716
+ {
1717
+ "correct": true,
1718
+ "correctResponse": ["from"],
1719
+ "itemId": "a",
1720
+ "learnerResponse": ["from"],
1721
+ "outcome": "correct",
1722
+ "weight": 1
1723
+ },
1724
+ {
1725
+ "correct": false,
1726
+ "correctResponse": ["from"],
1727
+ "itemId": "b",
1728
+ "learnerResponse": [""],
1729
+ "outcome": "incorrect-omission",
1730
+ "weight": 1
1731
+ }
1732
+ ],
1733
+ "feedback": null,
1734
+ "maxScore": 1,
1735
+ "passed": false,
1736
+ "score": 0.5
1737
+ },
1738
+ "fn": "score",
1739
+ "id": "score/gs/partial/empty-string-is-unanswered"
1740
+ },
1741
+ {
1742
+ "args": [
1743
+ "gap-select",
1744
+ {
1745
+ "banks": [
1746
+ {
1747
+ "choices": [
1748
+ {
1749
+ "id": "of",
1750
+ "text": "of"
1751
+ },
1752
+ {
1753
+ "id": "from",
1754
+ "text": "from"
1755
+ },
1756
+ {
1757
+ "id": "to",
1758
+ "text": "to"
1759
+ },
1760
+ {
1761
+ "id": "on",
1762
+ "text": "on"
1763
+ }
1764
+ ],
1765
+ "id": "prep"
1766
+ }
1767
+ ],
1768
+ "gaps": [
1769
+ {
1770
+ "bankId": "prep",
1771
+ "correctChoiceId": "from",
1772
+ "id": "a"
1773
+ },
1774
+ {
1775
+ "bankId": "prep",
1776
+ "correctChoiceId": "from",
1777
+ "id": "b"
1778
+ }
1779
+ ],
1780
+ "id": "gs-prepositions",
1781
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1782
+ "schemaVersion": "1.0",
1783
+ "scoringStrategy": "partial",
1784
+ "title": "Prepositions",
1785
+ "type": "gap-select"
1786
+ },
1787
+ {
1788
+ "selections": {
1789
+ "a": "smuggled",
1790
+ "b": "from"
1791
+ },
1792
+ "type": "gap-select"
1793
+ }
1794
+ ],
1795
+ "expect": {
1796
+ "details": [
1797
+ {
1798
+ "correct": false,
1799
+ "correctResponse": ["from"],
1800
+ "itemId": "a",
1801
+ "learnerResponse": ["smuggled"],
1802
+ "outcome": "incorrect-omission",
1803
+ "weight": 1
1804
+ },
1805
+ {
1806
+ "correct": true,
1807
+ "correctResponse": ["from"],
1808
+ "itemId": "b",
1809
+ "learnerResponse": ["from"],
1810
+ "outcome": "correct",
1811
+ "weight": 1
1812
+ }
1813
+ ],
1814
+ "feedback": null,
1815
+ "maxScore": 1,
1816
+ "passed": false,
1817
+ "score": 0.5
1818
+ },
1819
+ "fn": "score",
1820
+ "id": "score/gs/partial/choice-never-offered"
1821
+ },
1822
+ {
1823
+ "args": [
1824
+ "gap-select",
1825
+ {
1826
+ "banks": [
1827
+ {
1828
+ "choices": [
1829
+ {
1830
+ "id": "of",
1831
+ "text": "of"
1832
+ },
1833
+ {
1834
+ "id": "from",
1835
+ "text": "from"
1836
+ },
1837
+ {
1838
+ "id": "to",
1839
+ "text": "to"
1840
+ },
1841
+ {
1842
+ "id": "on",
1843
+ "text": "on"
1844
+ }
1845
+ ],
1846
+ "id": "prep"
1847
+ }
1848
+ ],
1849
+ "gaps": [
1850
+ {
1851
+ "bankId": "prep",
1852
+ "correctChoiceId": "from",
1853
+ "id": "a"
1854
+ },
1855
+ {
1856
+ "bankId": "prep",
1857
+ "correctChoiceId": "from",
1858
+ "id": "b"
1859
+ }
1860
+ ],
1861
+ "id": "gs-prepositions",
1862
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1863
+ "schemaVersion": "1.0",
1864
+ "scoringStrategy": "all-or-nothing",
1865
+ "title": "Prepositions",
1866
+ "type": "gap-select"
1867
+ },
1868
+ {
1869
+ "selections": {
1870
+ "a": "from",
1871
+ "b": "from"
1872
+ },
1873
+ "type": "gap-select"
1874
+ }
1875
+ ],
1876
+ "expect": {
1877
+ "details": [
1878
+ {
1879
+ "correct": true,
1880
+ "correctResponse": ["from"],
1881
+ "itemId": "a",
1882
+ "learnerResponse": ["from"],
1883
+ "outcome": "correct",
1884
+ "weight": 1
1885
+ },
1886
+ {
1887
+ "correct": true,
1888
+ "correctResponse": ["from"],
1889
+ "itemId": "b",
1890
+ "learnerResponse": ["from"],
1891
+ "outcome": "correct",
1892
+ "weight": 1
1893
+ }
1894
+ ],
1895
+ "feedback": null,
1896
+ "maxScore": 1,
1897
+ "passed": true,
1898
+ "score": 1
1899
+ },
1900
+ "fn": "score",
1901
+ "id": "score/gs/all-or-nothing/both-right"
1902
+ },
1903
+ {
1904
+ "args": [
1905
+ "gap-select",
1906
+ {
1907
+ "banks": [
1908
+ {
1909
+ "choices": [
1910
+ {
1911
+ "id": "of",
1912
+ "text": "of"
1913
+ },
1914
+ {
1915
+ "id": "from",
1916
+ "text": "from"
1917
+ },
1918
+ {
1919
+ "id": "to",
1920
+ "text": "to"
1921
+ },
1922
+ {
1923
+ "id": "on",
1924
+ "text": "on"
1925
+ }
1926
+ ],
1927
+ "id": "prep"
1928
+ }
1929
+ ],
1930
+ "gaps": [
1931
+ {
1932
+ "bankId": "prep",
1933
+ "correctChoiceId": "from",
1934
+ "id": "a"
1935
+ },
1936
+ {
1937
+ "bankId": "prep",
1938
+ "correctChoiceId": "from",
1939
+ "id": "b"
1940
+ }
1941
+ ],
1942
+ "id": "gs-prepositions",
1943
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1944
+ "schemaVersion": "1.0",
1945
+ "scoringStrategy": "all-or-nothing",
1946
+ "title": "Prepositions",
1947
+ "type": "gap-select"
1948
+ },
1949
+ {
1950
+ "selections": {
1951
+ "a": "from",
1952
+ "b": "to"
1953
+ },
1954
+ "type": "gap-select"
1955
+ }
1956
+ ],
1957
+ "expect": {
1958
+ "details": [
1959
+ {
1960
+ "correct": true,
1961
+ "correctResponse": ["from"],
1962
+ "itemId": "a",
1963
+ "learnerResponse": ["from"],
1964
+ "outcome": "correct",
1965
+ "weight": 1
1966
+ },
1967
+ {
1968
+ "correct": false,
1969
+ "correctResponse": ["from"],
1970
+ "itemId": "b",
1971
+ "learnerResponse": ["to"],
1972
+ "outcome": "incorrect",
1973
+ "weight": 1
1974
+ }
1975
+ ],
1976
+ "feedback": null,
1977
+ "maxScore": 1,
1978
+ "passed": false,
1979
+ "score": 0
1980
+ },
1981
+ "fn": "score",
1982
+ "id": "score/gs/all-or-nothing/one-wrong"
1983
+ },
1984
+ {
1985
+ "args": [
1986
+ "gap-select",
1987
+ {
1988
+ "gaps": [
1989
+ {
1990
+ "choices": [
1991
+ {
1992
+ "id": "blue",
1993
+ "text": "blue"
1994
+ },
1995
+ {
1996
+ "id": "red",
1997
+ "text": "red"
1998
+ }
1999
+ ],
2000
+ "correctChoiceId": "blue",
2001
+ "id": "a"
2002
+ }
2003
+ ],
2004
+ "id": "gs-prepositions",
2005
+ "passage": "The sky is {{a}}.",
2006
+ "schemaVersion": "1.0",
2007
+ "scoringStrategy": "partial",
2008
+ "title": "Prepositions",
2009
+ "type": "gap-select"
2010
+ },
2011
+ {
2012
+ "selections": {
2013
+ "a": "blue"
2014
+ },
2015
+ "type": "gap-select"
2016
+ }
2017
+ ],
2018
+ "expect": {
2019
+ "details": [
2020
+ {
2021
+ "correct": true,
2022
+ "correctResponse": ["blue"],
2023
+ "itemId": "a",
2024
+ "learnerResponse": ["blue"],
2025
+ "outcome": "correct",
2026
+ "weight": 1
2027
+ }
2028
+ ],
2029
+ "feedback": null,
2030
+ "maxScore": 1,
2031
+ "passed": true,
2032
+ "score": 1
2033
+ },
2034
+ "fn": "score",
2035
+ "id": "score/gs/own-choices-not-a-bank"
2036
+ },
2037
+ {
2038
+ "args": [
2039
+ "gap-select",
2040
+ {
2041
+ "banks": [],
2042
+ "gaps": [
2043
+ {
2044
+ "bankId": "prep",
2045
+ "correctChoiceId": "from",
2046
+ "id": "a"
2047
+ },
2048
+ {
2049
+ "bankId": "prep",
2050
+ "correctChoiceId": "from",
2051
+ "id": "b"
2052
+ }
2053
+ ],
2054
+ "id": "gs-prepositions",
2055
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
2056
+ "schemaVersion": "1.0",
2057
+ "scoringStrategy": "partial",
2058
+ "title": "Prepositions",
2059
+ "type": "gap-select"
2060
+ },
2061
+ {
2062
+ "selections": {
2063
+ "a": "from",
2064
+ "b": "from"
2065
+ },
2066
+ "type": "gap-select"
2067
+ }
2068
+ ],
2069
+ "expect": {
2070
+ "details": [
2071
+ {
2072
+ "correct": false,
2073
+ "correctResponse": ["from"],
2074
+ "itemId": "a",
2075
+ "learnerResponse": ["from"],
2076
+ "outcome": "incorrect-omission",
2077
+ "weight": 1
2078
+ },
2079
+ {
2080
+ "correct": false,
2081
+ "correctResponse": ["from"],
2082
+ "itemId": "b",
2083
+ "learnerResponse": ["from"],
2084
+ "outcome": "incorrect-omission",
2085
+ "weight": 1
2086
+ }
2087
+ ],
2088
+ "feedback": null,
2089
+ "maxScore": 1,
2090
+ "passed": false,
2091
+ "score": 0
2092
+ },
2093
+ "fn": "score",
2094
+ "id": "score/gs/missing-bank-scores-zero"
2095
+ },
2096
+ {
2097
+ "args": [
2098
+ {
2099
+ "banks": [
2100
+ {
2101
+ "choices": [
2102
+ {
2103
+ "id": "of",
2104
+ "text": "of"
2105
+ },
2106
+ {
2107
+ "id": "from",
2108
+ "text": "from"
2109
+ },
2110
+ {
2111
+ "id": "to",
2112
+ "text": "to"
2113
+ },
2114
+ {
2115
+ "id": "on",
2116
+ "text": "on"
2117
+ }
2118
+ ],
2119
+ "id": "prep"
2120
+ }
2121
+ ],
2122
+ "gaps": [
2123
+ {
2124
+ "bankId": "prep",
2125
+ "correctChoiceId": "from",
2126
+ "id": "a"
2127
+ },
2128
+ {
2129
+ "bankId": "prep",
2130
+ "correctChoiceId": "from",
2131
+ "id": "b"
2132
+ }
2133
+ ],
2134
+ "id": "gs-prepositions",
2135
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
2136
+ "schemaVersion": "1.0",
2137
+ "scoringStrategy": "partial",
2138
+ "title": "Prepositions",
2139
+ "type": "gap-select"
2140
+ },
2141
+ {
2142
+ "selections": {
2143
+ "a": "from",
2144
+ "b": "from"
2145
+ },
2146
+ "type": "gap-select"
2147
+ }
2148
+ ],
2149
+ "expect": {
2150
+ "details": [
2151
+ {
2152
+ "correct": true,
2153
+ "correctResponse": ["from"],
2154
+ "itemId": "a",
2155
+ "learnerResponse": ["from"],
2156
+ "outcome": "correct",
2157
+ "weight": 1
2158
+ },
2159
+ {
2160
+ "correct": true,
2161
+ "correctResponse": ["from"],
2162
+ "itemId": "b",
2163
+ "learnerResponse": ["from"],
2164
+ "outcome": "correct",
2165
+ "weight": 1
2166
+ }
2167
+ ],
2168
+ "feedback": null,
2169
+ "maxScore": 1,
2170
+ "passed": true,
2171
+ "score": 1,
2172
+ "status": "scored"
2173
+ },
2174
+ "fn": "evaluate",
2175
+ "id": "evaluate/gs/scored"
2176
+ },
1322
2177
  {
1323
2178
  "args": [
1324
2179
  "fill-in-the-blanks",
@@ -2838,6 +3693,51 @@
2838
3693
  "id": "matchText/policy/levenshtein-1-single-character-hazard",
2839
3694
  "note": "Deliberate and documented: distance 1 against a one-character answer accepts ANY single character."
2840
3695
  },
3696
+ {
3697
+ "args": ["a", "ab", 2],
3698
+ "expect": 1,
3699
+ "fn": "levenshteinDistance",
3700
+ "id": "levenshteinDistance/one-char-vs-longer"
3701
+ },
3702
+ {
3703
+ "args": ["ab", "a", 2],
3704
+ "expect": 1,
3705
+ "fn": "levenshteinDistance",
3706
+ "id": "levenshteinDistance/longer-vs-one-char"
3707
+ },
3708
+ {
3709
+ "args": ["a", "b", 2],
3710
+ "expect": 1,
3711
+ "fn": "levenshteinDistance",
3712
+ "id": "levenshteinDistance/one-char-each"
3713
+ },
3714
+ {
3715
+ "args": ["", "a", 2],
3716
+ "expect": 1,
3717
+ "fn": "levenshteinDistance",
3718
+ "id": "levenshteinDistance/empty-vs-one-char"
3719
+ },
3720
+ {
3721
+ "args": ["a", "", 2],
3722
+ "expect": 1,
3723
+ "fn": "levenshteinDistance",
3724
+ "id": "levenshteinDistance/one-char-vs-empty"
3725
+ },
3726
+ {
3727
+ "args": [
3728
+ "a",
3729
+ ["b"],
3730
+ {
3731
+ "levenshtein": 1
3732
+ }
3733
+ ],
3734
+ "expect": {
3735
+ "matched": true,
3736
+ "via": "fuzzy"
3737
+ },
3738
+ "fn": "matchText",
3739
+ "id": "matchText/levenshtein/one-char-typo"
3740
+ },
2841
3741
  {
2842
3742
  "args": ["kitten", "sitting", 10],
2843
3743
  "expect": 3,
@@ -4914,6 +5814,125 @@
4914
5814
  "fn": "outcomeFromGrade",
4915
5815
  "id": "outcomeFromGrade/lifts-a-grade"
4916
5816
  },
5817
+ {
5818
+ "args": [
5819
+ [
5820
+ {
5821
+ "id": "a",
5822
+ "items": [
5823
+ {
5824
+ "outcome": {
5825
+ "details": [],
5826
+ "feedback": null,
5827
+ "maxScore": 1,
5828
+ "passed": true,
5829
+ "score": 1,
5830
+ "status": "scored"
5831
+ },
5832
+ "points": 1,
5833
+ "slotId": "a1"
5834
+ }
5835
+ ],
5836
+ "title": "Reading",
5837
+ "weight": 1
5838
+ }
5839
+ ],
5840
+ {
5841
+ "passThreshold": 0.7,
5842
+ "rounding": {
5843
+ "dp": 2,
5844
+ "mode": "half-up"
5845
+ }
5846
+ }
5847
+ ],
5848
+ "expect": {
5849
+ "passFailureReason": null,
5850
+ "passed": true,
5851
+ "pendingSlotIds": [],
5852
+ "score": 1,
5853
+ "sections": [
5854
+ {
5855
+ "appliedThreshold": null,
5856
+ "earnedPoints": 1,
5857
+ "gradedMaxPoints": 1,
5858
+ "id": "a",
5859
+ "maxPoints": 1,
5860
+ "normalizedWeight": 1,
5861
+ "passed": true,
5862
+ "pendingSlotIds": [],
5863
+ "score": 1,
5864
+ "title": "Reading",
5865
+ "unscorableSlotIds": [],
5866
+ "weight": 1
5867
+ }
5868
+ ],
5869
+ "status": "final",
5870
+ "unscorableSlotIds": []
5871
+ },
5872
+ "fn": "composeAssessmentScore",
5873
+ "id": "composeAssessmentScore/section-with-title"
5874
+ },
5875
+ {
5876
+ "args": [
5877
+ [
5878
+ {
5879
+ "id": "a",
5880
+ "items": [
5881
+ {
5882
+ "outcome": {
5883
+ "feedback": null,
5884
+ "grade": {
5885
+ "feedback": null,
5886
+ "maxScore": 0.5,
5887
+ "passed": true,
5888
+ "score": 0.4
5889
+ },
5890
+ "maxScore": 0.5,
5891
+ "passed": true,
5892
+ "score": 0.4,
5893
+ "status": "graded"
5894
+ },
5895
+ "points": 1,
5896
+ "slotId": "a1"
5897
+ }
5898
+ ],
5899
+ "weight": 1
5900
+ }
5901
+ ],
5902
+ {
5903
+ "passThreshold": 0.7,
5904
+ "rounding": {
5905
+ "dp": 2,
5906
+ "mode": "half-up"
5907
+ }
5908
+ }
5909
+ ],
5910
+ "expect": {
5911
+ "passFailureReason": null,
5912
+ "passed": true,
5913
+ "pendingSlotIds": [],
5914
+ "score": 0.8,
5915
+ "sections": [
5916
+ {
5917
+ "appliedThreshold": null,
5918
+ "earnedPoints": 0.8,
5919
+ "gradedMaxPoints": 1,
5920
+ "id": "a",
5921
+ "maxPoints": 1,
5922
+ "normalizedWeight": 1,
5923
+ "passed": true,
5924
+ "pendingSlotIds": [],
5925
+ "score": 0.8,
5926
+ "unscorableSlotIds": [],
5927
+ "weight": 1
5928
+ }
5929
+ ],
5930
+ "status": "final",
5931
+ "unscorableSlotIds": []
5932
+ },
5933
+ "fn": "composeAssessmentScore",
5934
+ "id": "composeAssessmentScore/graded/max-score-below-one"
5935
+ },
4917
5936
  {
4918
5937
  "args": [
4919
5938
  [