@intellectif/lk-core 0.17.0 → 0.18.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.
@@ -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": 2,
4
- "frozenFrom": "@intellectif/lk-core@0.13.1",
4
+ "frozenFrom": "@intellectif/lk-core@0.17.0",
5
5
  "vectors": [
6
6
  {
7
7
  "args": [
@@ -8328,6 +8328,124 @@
8328
8328
  "id": "gradeFromRubric/unscorable/infinite-weight",
8329
8329
  "ignore": ["reason"]
8330
8330
  },
8331
+ {
8332
+ "args": [
8333
+ [
8334
+ {
8335
+ "name": "A",
8336
+ "score": 0,
8337
+ "weight": 2
8338
+ },
8339
+ {
8340
+ "name": "B",
8341
+ "score": 1,
8342
+ "weight": -1
8343
+ }
8344
+ ]
8345
+ ],
8346
+ "expect": {
8347
+ "reason": "Criterion \"B\" has weight -1; a weight must be zero or more.",
8348
+ "unscorable": true
8349
+ },
8350
+ "fn": "gradeFromRubric",
8351
+ "id": "gradeFromRubric/unscorable/negative-weight-pulls-total-down",
8352
+ "ignore": ["reason"]
8353
+ },
8354
+ {
8355
+ "args": [
8356
+ [
8357
+ {
8358
+ "name": "A",
8359
+ "score": 1,
8360
+ "weight": 2
8361
+ },
8362
+ {
8363
+ "name": "B",
8364
+ "score": 0,
8365
+ "weight": -1
8366
+ }
8367
+ ]
8368
+ ],
8369
+ "expect": {
8370
+ "reason": "Criterion \"B\" has weight -1; a weight must be zero or more.",
8371
+ "unscorable": true
8372
+ },
8373
+ "fn": "gradeFromRubric",
8374
+ "id": "gradeFromRubric/unscorable/negative-weight-pushes-total-up",
8375
+ "ignore": ["reason"]
8376
+ },
8377
+ {
8378
+ "args": [
8379
+ [
8380
+ {
8381
+ "name": "A",
8382
+ "score": 1,
8383
+ "weight": 1e308
8384
+ },
8385
+ {
8386
+ "name": "B",
8387
+ "score": 0,
8388
+ "weight": 1e308
8389
+ }
8390
+ ]
8391
+ ],
8392
+ "expect": {
8393
+ "reason": "The weighted total is not a finite number, so no grade can be produced.",
8394
+ "unscorable": true
8395
+ },
8396
+ "fn": "gradeFromRubric",
8397
+ "id": "gradeFromRubric/unscorable/weight-sum-overflows",
8398
+ "ignore": ["reason"]
8399
+ },
8400
+ {
8401
+ "args": [
8402
+ [
8403
+ {
8404
+ "name": "Task",
8405
+ "score": 0.8,
8406
+ "weight": 1
8407
+ },
8408
+ {
8409
+ "name": "Grammar",
8410
+ "notApplicable": true,
8411
+ "score": 0.1,
8412
+ "weight": -1
8413
+ },
8414
+ {
8415
+ "band": "B2",
8416
+ "name": "Style",
8417
+ "weight": -1
8418
+ }
8419
+ ]
8420
+ ],
8421
+ "expect": {
8422
+ "criteria": [
8423
+ {
8424
+ "name": "Task",
8425
+ "score": 0.8,
8426
+ "weight": 1
8427
+ },
8428
+ {
8429
+ "name": "Grammar",
8430
+ "notApplicable": true,
8431
+ "score": 0.1,
8432
+ "weight": -1
8433
+ },
8434
+ {
8435
+ "band": "B2",
8436
+ "name": "Style",
8437
+ "weight": -1
8438
+ }
8439
+ ],
8440
+ "feedback": null,
8441
+ "maxScore": 1,
8442
+ "passed": true,
8443
+ "score": 0.8
8444
+ },
8445
+ "fn": "gradeFromRubric",
8446
+ "id": "gradeFromRubric/negative-weight-outside-the-arithmetic-ignored",
8447
+ "note": "A weight is read only where it enters the arithmetic, as score and maxScore are: not applicable and band-only criteria keep being ignored."
8448
+ },
8331
8449
  {
8332
8450
  "args": [
8333
8451
  [
@@ -8372,30 +8490,1160 @@
8372
8490
  ],
8373
8491
  "expect": {
8374
8492
  "passFailureReason": null,
8375
- "passed": true,
8376
- "pendingSlotIds": [],
8377
- "score": 0.75,
8493
+ "passed": null,
8494
+ "pendingSlotIds": ["a1"],
8495
+ "rejectedSlotIds": ["a1"],
8496
+ "score": 1,
8378
8497
  "sections": [
8379
8498
  {
8380
8499
  "appliedThreshold": null,
8381
- "earnedPoints": 3,
8382
- "gradedMaxPoints": 4,
8500
+ "earnedPoints": 2,
8501
+ "gradedMaxPoints": 2,
8383
8502
  "id": "a",
8384
8503
  "maxPoints": 4,
8385
8504
  "normalizedWeight": 1,
8386
8505
  "passed": true,
8387
- "pendingSlotIds": [],
8388
- "score": 0.75,
8506
+ "pendingSlotIds": ["a1"],
8507
+ "rejectedSlotIds": ["a1"],
8508
+ "score": 1,
8389
8509
  "unscorableSlotIds": [],
8390
8510
  "weight": 1
8391
8511
  }
8392
8512
  ],
8393
- "status": "final",
8513
+ "status": "provisional",
8394
8514
  "unscorableSlotIds": []
8395
8515
  },
8396
8516
  "fn": "composeAssessmentScore",
8397
8517
  "id": "composeAssessmentScore/item-max-score-zero",
8398
- "note": "An outcome claiming maxScore 0 is read against 1 rather than divided by zero."
8518
+ "note": "An outcome claiming maxScore 0 is not a grade. Until 0.18 it was read against 1 (0.5 counted as 0.5 and the result went final); it is now held provisional and reported in rejectedSlotIds. Re-frozen deliberately: the one existing vector the change moves."
8519
+ },
8520
+ {
8521
+ "args": [
8522
+ {
8523
+ "feedback": "Excellent.",
8524
+ "maxScore": 1,
8525
+ "passed": true,
8526
+ "score": {
8527
+ "$number": "NaN"
8528
+ }
8529
+ }
8530
+ ],
8531
+ "expect": {
8532
+ "maxScore": 1,
8533
+ "reason": "grade_rejected",
8534
+ "rejectedGrade": {
8535
+ "feedback": "Excellent.",
8536
+ "maxScore": 1,
8537
+ "passed": true,
8538
+ "score": {
8539
+ "$number": "NaN"
8540
+ }
8541
+ },
8542
+ "status": "deferred"
8543
+ },
8544
+ "fn": "outcomeFromGrade",
8545
+ "id": "outcomeFromGrade/rejected/nan-score",
8546
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8547
+ },
8548
+ {
8549
+ "args": [
8550
+ {
8551
+ "feedback": "Excellent.",
8552
+ "maxScore": 1,
8553
+ "passed": true,
8554
+ "score": {
8555
+ "$number": "Infinity"
8556
+ }
8557
+ }
8558
+ ],
8559
+ "expect": {
8560
+ "maxScore": 1,
8561
+ "reason": "grade_rejected",
8562
+ "rejectedGrade": {
8563
+ "feedback": "Excellent.",
8564
+ "maxScore": 1,
8565
+ "passed": true,
8566
+ "score": {
8567
+ "$number": "Infinity"
8568
+ }
8569
+ },
8570
+ "status": "deferred"
8571
+ },
8572
+ "fn": "outcomeFromGrade",
8573
+ "id": "outcomeFromGrade/rejected/infinite-score",
8574
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8575
+ },
8576
+ {
8577
+ "args": [
8578
+ {
8579
+ "feedback": "Excellent.",
8580
+ "maxScore": 0,
8581
+ "passed": true,
8582
+ "score": 0
8583
+ }
8584
+ ],
8585
+ "expect": {
8586
+ "maxScore": 1,
8587
+ "reason": "grade_rejected",
8588
+ "rejectedGrade": {
8589
+ "feedback": "Excellent.",
8590
+ "maxScore": 0,
8591
+ "passed": true,
8592
+ "score": 0
8593
+ },
8594
+ "status": "deferred"
8595
+ },
8596
+ "fn": "outcomeFromGrade",
8597
+ "id": "outcomeFromGrade/rejected/zero-max-score",
8598
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8599
+ },
8600
+ {
8601
+ "args": [
8602
+ {
8603
+ "feedback": "Excellent.",
8604
+ "maxScore": 1,
8605
+ "passed": true,
8606
+ "score": -0.5
8607
+ }
8608
+ ],
8609
+ "expect": {
8610
+ "maxScore": 1,
8611
+ "reason": "grade_rejected",
8612
+ "rejectedGrade": {
8613
+ "feedback": "Excellent.",
8614
+ "maxScore": 1,
8615
+ "passed": true,
8616
+ "score": -0.5
8617
+ },
8618
+ "status": "deferred"
8619
+ },
8620
+ "fn": "outcomeFromGrade",
8621
+ "id": "outcomeFromGrade/rejected/negative-score",
8622
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8623
+ },
8624
+ {
8625
+ "args": [
8626
+ {
8627
+ "feedback": "Excellent.",
8628
+ "maxScore": 1,
8629
+ "passed": true,
8630
+ "score": 85
8631
+ }
8632
+ ],
8633
+ "expect": {
8634
+ "maxScore": 1,
8635
+ "reason": "grade_rejected",
8636
+ "rejectedGrade": {
8637
+ "feedback": "Excellent.",
8638
+ "maxScore": 1,
8639
+ "passed": true,
8640
+ "score": 85
8641
+ },
8642
+ "status": "deferred"
8643
+ },
8644
+ "fn": "outcomeFromGrade",
8645
+ "id": "outcomeFromGrade/rejected/raw-points-85-of-1",
8646
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8647
+ },
8648
+ {
8649
+ "args": [
8650
+ {
8651
+ "feedback": "Excellent.",
8652
+ "maxScore": 1,
8653
+ "passed": true,
8654
+ "score": 1.000000002
8655
+ }
8656
+ ],
8657
+ "expect": {
8658
+ "maxScore": 1,
8659
+ "reason": "grade_rejected",
8660
+ "rejectedGrade": {
8661
+ "feedback": "Excellent.",
8662
+ "maxScore": 1,
8663
+ "passed": true,
8664
+ "score": 1.000000002
8665
+ },
8666
+ "status": "deferred"
8667
+ },
8668
+ "fn": "outcomeFromGrade",
8669
+ "id": "outcomeFromGrade/rejected/just-past-float-noise",
8670
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8671
+ },
8672
+ {
8673
+ "args": [
8674
+ {
8675
+ "feedback": "Excellent.",
8676
+ "maxScore": 1,
8677
+ "passed": true,
8678
+ "score": -1e-10
8679
+ }
8680
+ ],
8681
+ "expect": {
8682
+ "maxScore": 1,
8683
+ "reason": "grade_rejected",
8684
+ "rejectedGrade": {
8685
+ "feedback": "Excellent.",
8686
+ "maxScore": 1,
8687
+ "passed": true,
8688
+ "score": -1e-10
8689
+ },
8690
+ "status": "deferred"
8691
+ },
8692
+ "fn": "outcomeFromGrade",
8693
+ "id": "outcomeFromGrade/rejected/a-hair-below-zero",
8694
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8695
+ },
8696
+ {
8697
+ "args": [
8698
+ {
8699
+ "feedback": "Excellent.",
8700
+ "maxScore": 1,
8701
+ "passed": true,
8702
+ "score": "0.85"
8703
+ }
8704
+ ],
8705
+ "expect": {
8706
+ "maxScore": 1,
8707
+ "reason": "grade_rejected",
8708
+ "rejectedGrade": {
8709
+ "feedback": "Excellent.",
8710
+ "maxScore": 1,
8711
+ "passed": true,
8712
+ "score": "0.85"
8713
+ },
8714
+ "status": "deferred"
8715
+ },
8716
+ "fn": "outcomeFromGrade",
8717
+ "id": "outcomeFromGrade/rejected/numeric-string-score",
8718
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8719
+ },
8720
+ {
8721
+ "args": [
8722
+ {
8723
+ "feedback": "Excellent.",
8724
+ "maxScore": -1,
8725
+ "passed": true,
8726
+ "score": 0.5
8727
+ }
8728
+ ],
8729
+ "expect": {
8730
+ "maxScore": 1,
8731
+ "reason": "grade_rejected",
8732
+ "rejectedGrade": {
8733
+ "feedback": "Excellent.",
8734
+ "maxScore": -1,
8735
+ "passed": true,
8736
+ "score": 0.5
8737
+ },
8738
+ "status": "deferred"
8739
+ },
8740
+ "fn": "outcomeFromGrade",
8741
+ "id": "outcomeFromGrade/rejected/negative-max-score",
8742
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8743
+ },
8744
+ {
8745
+ "args": [
8746
+ {
8747
+ "feedback": "Excellent.",
8748
+ "maxScore": {
8749
+ "$number": "NaN"
8750
+ },
8751
+ "passed": true,
8752
+ "score": 0.5
8753
+ }
8754
+ ],
8755
+ "expect": {
8756
+ "maxScore": 1,
8757
+ "reason": "grade_rejected",
8758
+ "rejectedGrade": {
8759
+ "feedback": "Excellent.",
8760
+ "maxScore": {
8761
+ "$number": "NaN"
8762
+ },
8763
+ "passed": true,
8764
+ "score": 0.5
8765
+ },
8766
+ "status": "deferred"
8767
+ },
8768
+ "fn": "outcomeFromGrade",
8769
+ "id": "outcomeFromGrade/rejected/nan-max-score",
8770
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8771
+ },
8772
+ {
8773
+ "args": [
8774
+ {
8775
+ "feedback": "Excellent.",
8776
+ "maxScore": {
8777
+ "$number": "Infinity"
8778
+ },
8779
+ "passed": true,
8780
+ "score": 0.5
8781
+ }
8782
+ ],
8783
+ "expect": {
8784
+ "maxScore": 1,
8785
+ "reason": "grade_rejected",
8786
+ "rejectedGrade": {
8787
+ "feedback": "Excellent.",
8788
+ "maxScore": {
8789
+ "$number": "Infinity"
8790
+ },
8791
+ "passed": true,
8792
+ "score": 0.5
8793
+ },
8794
+ "status": "deferred"
8795
+ },
8796
+ "fn": "outcomeFromGrade",
8797
+ "id": "outcomeFromGrade/rejected/infinite-max-score",
8798
+ "note": "Not a grade: returned as deferred with reason grade_rejected and the record kept verbatim on rejectedGrade, never mirrored as graded."
8799
+ },
8800
+ {
8801
+ "args": [
8802
+ {
8803
+ "feedback": "Excellent.",
8804
+ "maxScore": 1,
8805
+ "passed": true,
8806
+ "score": 0
8807
+ }
8808
+ ],
8809
+ "expect": {
8810
+ "feedback": "Excellent.",
8811
+ "grade": {
8812
+ "feedback": "Excellent.",
8813
+ "maxScore": 1,
8814
+ "passed": true,
8815
+ "score": 0
8816
+ },
8817
+ "maxScore": 1,
8818
+ "passed": true,
8819
+ "score": 0,
8820
+ "status": "graded"
8821
+ },
8822
+ "fn": "outcomeFromGrade",
8823
+ "id": "outcomeFromGrade/accepted/exactly-zero",
8824
+ "note": "In range, so mirrored exactly as before, unclamped. Float noise is up to one part in a billion above maxScore; 1 past 1e9 is that edge exactly."
8825
+ },
8826
+ {
8827
+ "args": [
8828
+ {
8829
+ "feedback": "Excellent.",
8830
+ "maxScore": 1,
8831
+ "passed": true,
8832
+ "score": 1.0000000001
8833
+ }
8834
+ ],
8835
+ "expect": {
8836
+ "feedback": "Excellent.",
8837
+ "grade": {
8838
+ "feedback": "Excellent.",
8839
+ "maxScore": 1,
8840
+ "passed": true,
8841
+ "score": 1.0000000001
8842
+ },
8843
+ "maxScore": 1,
8844
+ "passed": true,
8845
+ "score": 1.0000000001,
8846
+ "status": "graded"
8847
+ },
8848
+ "fn": "outcomeFromGrade",
8849
+ "id": "outcomeFromGrade/accepted/float-noise-above-one",
8850
+ "note": "In range, so mirrored exactly as before, unclamped. Float noise is up to one part in a billion above maxScore; 1 past 1e9 is that edge exactly."
8851
+ },
8852
+ {
8853
+ "args": [
8854
+ {
8855
+ "feedback": "Excellent.",
8856
+ "maxScore": 1000000000,
8857
+ "passed": true,
8858
+ "score": 1000000001
8859
+ }
8860
+ ],
8861
+ "expect": {
8862
+ "feedback": "Excellent.",
8863
+ "grade": {
8864
+ "feedback": "Excellent.",
8865
+ "maxScore": 1000000000,
8866
+ "passed": true,
8867
+ "score": 1000000001
8868
+ },
8869
+ "maxScore": 1000000000,
8870
+ "passed": true,
8871
+ "score": 1000000001,
8872
+ "status": "graded"
8873
+ },
8874
+ "fn": "outcomeFromGrade",
8875
+ "id": "outcomeFromGrade/accepted/exact-edge-of-float-noise",
8876
+ "note": "In range, so mirrored exactly as before, unclamped. Float noise is up to one part in a billion above maxScore; 1 past 1e9 is that edge exactly."
8877
+ },
8878
+ {
8879
+ "args": [
8880
+ [
8881
+ {
8882
+ "id": "a",
8883
+ "items": [
8884
+ {
8885
+ "outcome": {
8886
+ "details": [],
8887
+ "feedback": null,
8888
+ "maxScore": 1,
8889
+ "passed": true,
8890
+ "score": 1,
8891
+ "status": "scored"
8892
+ },
8893
+ "points": 1,
8894
+ "slotId": "a1"
8895
+ },
8896
+ {
8897
+ "outcome": {
8898
+ "feedback": null,
8899
+ "grade": {
8900
+ "feedback": null,
8901
+ "maxScore": 1,
8902
+ "passed": false,
8903
+ "score": {
8904
+ "$number": "NaN"
8905
+ }
8906
+ },
8907
+ "maxScore": 1,
8908
+ "passed": false,
8909
+ "score": {
8910
+ "$number": "NaN"
8911
+ },
8912
+ "status": "graded"
8913
+ },
8914
+ "points": 1,
8915
+ "slotId": "a2"
8916
+ }
8917
+ ],
8918
+ "weight": 1
8919
+ }
8920
+ ],
8921
+ {
8922
+ "passThreshold": 0.7,
8923
+ "rounding": {
8924
+ "dp": 2,
8925
+ "mode": "half-up"
8926
+ }
8927
+ }
8928
+ ],
8929
+ "expect": {
8930
+ "passFailureReason": null,
8931
+ "passed": null,
8932
+ "pendingSlotIds": ["a2"],
8933
+ "rejectedSlotIds": ["a2"],
8934
+ "score": 1,
8935
+ "sections": [
8936
+ {
8937
+ "appliedThreshold": null,
8938
+ "earnedPoints": 1,
8939
+ "gradedMaxPoints": 1,
8940
+ "id": "a",
8941
+ "maxPoints": 2,
8942
+ "normalizedWeight": 1,
8943
+ "passed": true,
8944
+ "pendingSlotIds": ["a2"],
8945
+ "rejectedSlotIds": ["a2"],
8946
+ "score": 1,
8947
+ "unscorableSlotIds": [],
8948
+ "weight": 1
8949
+ }
8950
+ ],
8951
+ "status": "provisional",
8952
+ "unscorableSlotIds": []
8953
+ },
8954
+ "fn": "composeAssessmentScore",
8955
+ "id": "composeAssessmentScore/rejected/nan-grade",
8956
+ "note": "Was final with a NaN score (null in JSON) and a passing section scored null. Now provisional, passed null, the slot pending and rejected."
8957
+ },
8958
+ {
8959
+ "args": [
8960
+ [
8961
+ {
8962
+ "id": "a",
8963
+ "items": [
8964
+ {
8965
+ "outcome": {
8966
+ "details": [],
8967
+ "feedback": null,
8968
+ "maxScore": 1,
8969
+ "passed": true,
8970
+ "score": 1,
8971
+ "status": "scored"
8972
+ },
8973
+ "points": 1,
8974
+ "slotId": "a1"
8975
+ },
8976
+ {
8977
+ "outcome": {
8978
+ "feedback": null,
8979
+ "grade": {
8980
+ "feedback": null,
8981
+ "maxScore": 1,
8982
+ "passed": true,
8983
+ "score": {
8984
+ "$number": "Infinity"
8985
+ }
8986
+ },
8987
+ "maxScore": 1,
8988
+ "passed": true,
8989
+ "score": {
8990
+ "$number": "Infinity"
8991
+ },
8992
+ "status": "graded"
8993
+ },
8994
+ "points": 1,
8995
+ "slotId": "a2"
8996
+ }
8997
+ ],
8998
+ "weight": 1
8999
+ }
9000
+ ],
9001
+ {
9002
+ "passThreshold": 0.7,
9003
+ "rounding": {
9004
+ "dp": 2,
9005
+ "mode": "half-up"
9006
+ }
9007
+ }
9008
+ ],
9009
+ "expect": {
9010
+ "passFailureReason": null,
9011
+ "passed": null,
9012
+ "pendingSlotIds": ["a2"],
9013
+ "rejectedSlotIds": ["a2"],
9014
+ "score": 1,
9015
+ "sections": [
9016
+ {
9017
+ "appliedThreshold": null,
9018
+ "earnedPoints": 1,
9019
+ "gradedMaxPoints": 1,
9020
+ "id": "a",
9021
+ "maxPoints": 2,
9022
+ "normalizedWeight": 1,
9023
+ "passed": true,
9024
+ "pendingSlotIds": ["a2"],
9025
+ "rejectedSlotIds": ["a2"],
9026
+ "score": 1,
9027
+ "unscorableSlotIds": [],
9028
+ "weight": 1
9029
+ }
9030
+ ],
9031
+ "status": "provisional",
9032
+ "unscorableSlotIds": []
9033
+ },
9034
+ "fn": "composeAssessmentScore",
9035
+ "id": "composeAssessmentScore/rejected/infinite-grade"
9036
+ },
9037
+ {
9038
+ "args": [
9039
+ [
9040
+ {
9041
+ "id": "a",
9042
+ "items": [
9043
+ {
9044
+ "outcome": {
9045
+ "details": [],
9046
+ "feedback": null,
9047
+ "maxScore": 1,
9048
+ "passed": true,
9049
+ "score": 1,
9050
+ "status": "scored"
9051
+ },
9052
+ "points": 1,
9053
+ "slotId": "a1"
9054
+ },
9055
+ {
9056
+ "outcome": {
9057
+ "feedback": null,
9058
+ "grade": {
9059
+ "feedback": null,
9060
+ "maxScore": 1,
9061
+ "passed": true,
9062
+ "score": 85
9063
+ },
9064
+ "maxScore": 1,
9065
+ "passed": true,
9066
+ "score": 85,
9067
+ "status": "graded"
9068
+ },
9069
+ "points": 1,
9070
+ "slotId": "a2"
9071
+ }
9072
+ ],
9073
+ "weight": 1
9074
+ }
9075
+ ],
9076
+ {
9077
+ "passThreshold": 0.7,
9078
+ "rounding": {
9079
+ "dp": 2,
9080
+ "mode": "half-up"
9081
+ },
9082
+ "sectionThreshold": 0.6
9083
+ }
9084
+ ],
9085
+ "expect": {
9086
+ "passFailureReason": null,
9087
+ "passed": null,
9088
+ "pendingSlotIds": ["a2"],
9089
+ "rejectedSlotIds": ["a2"],
9090
+ "score": 1,
9091
+ "sections": [
9092
+ {
9093
+ "appliedThreshold": 0.6,
9094
+ "earnedPoints": 1,
9095
+ "gradedMaxPoints": 1,
9096
+ "id": "a",
9097
+ "maxPoints": 2,
9098
+ "normalizedWeight": 1,
9099
+ "passed": true,
9100
+ "pendingSlotIds": ["a2"],
9101
+ "rejectedSlotIds": ["a2"],
9102
+ "score": 1,
9103
+ "unscorableSlotIds": [],
9104
+ "weight": 1
9105
+ }
9106
+ ],
9107
+ "status": "provisional",
9108
+ "unscorableSlotIds": []
9109
+ },
9110
+ "fn": "composeAssessmentScore",
9111
+ "id": "composeAssessmentScore/rejected/raw-points-85-of-1",
9112
+ "note": "Was final, score 43, passed. A grader returning raw points against maxScore 1 is out of contract."
9113
+ },
9114
+ {
9115
+ "args": [
9116
+ [
9117
+ {
9118
+ "id": "a",
9119
+ "items": [
9120
+ {
9121
+ "outcome": {
9122
+ "details": [],
9123
+ "feedback": null,
9124
+ "maxScore": 1,
9125
+ "passed": true,
9126
+ "score": 1,
9127
+ "status": "scored"
9128
+ },
9129
+ "points": 1,
9130
+ "slotId": "a1"
9131
+ },
9132
+ {
9133
+ "outcome": {
9134
+ "feedback": null,
9135
+ "grade": {
9136
+ "feedback": null,
9137
+ "maxScore": 1,
9138
+ "passed": false,
9139
+ "score": -0.5
9140
+ },
9141
+ "maxScore": 1,
9142
+ "passed": false,
9143
+ "score": -0.5,
9144
+ "status": "graded"
9145
+ },
9146
+ "points": 1,
9147
+ "slotId": "a2"
9148
+ }
9149
+ ],
9150
+ "weight": 1
9151
+ }
9152
+ ],
9153
+ {
9154
+ "passThreshold": 0.7,
9155
+ "rounding": {
9156
+ "dp": 2,
9157
+ "mode": "half-up"
9158
+ }
9159
+ }
9160
+ ],
9161
+ "expect": {
9162
+ "passFailureReason": null,
9163
+ "passed": null,
9164
+ "pendingSlotIds": ["a2"],
9165
+ "rejectedSlotIds": ["a2"],
9166
+ "score": 1,
9167
+ "sections": [
9168
+ {
9169
+ "appliedThreshold": null,
9170
+ "earnedPoints": 1,
9171
+ "gradedMaxPoints": 1,
9172
+ "id": "a",
9173
+ "maxPoints": 2,
9174
+ "normalizedWeight": 1,
9175
+ "passed": true,
9176
+ "pendingSlotIds": ["a2"],
9177
+ "rejectedSlotIds": ["a2"],
9178
+ "score": 1,
9179
+ "unscorableSlotIds": [],
9180
+ "weight": 1
9181
+ }
9182
+ ],
9183
+ "status": "provisional",
9184
+ "unscorableSlotIds": []
9185
+ },
9186
+ "fn": "composeAssessmentScore",
9187
+ "id": "composeAssessmentScore/rejected/negative-grade"
9188
+ },
9189
+ {
9190
+ "args": [
9191
+ [
9192
+ {
9193
+ "id": "a",
9194
+ "items": [
9195
+ {
9196
+ "outcome": {
9197
+ "details": [],
9198
+ "feedback": null,
9199
+ "maxScore": 1,
9200
+ "passed": true,
9201
+ "score": 1,
9202
+ "status": "scored"
9203
+ },
9204
+ "points": 1,
9205
+ "slotId": "a1"
9206
+ },
9207
+ {
9208
+ "outcome": {
9209
+ "feedback": null,
9210
+ "grade": {
9211
+ "feedback": null,
9212
+ "maxScore": 0,
9213
+ "passed": true,
9214
+ "score": 0.3
9215
+ },
9216
+ "maxScore": 0,
9217
+ "passed": true,
9218
+ "score": 0.3,
9219
+ "status": "graded"
9220
+ },
9221
+ "points": 1,
9222
+ "slotId": "a2"
9223
+ }
9224
+ ],
9225
+ "weight": 1
9226
+ }
9227
+ ],
9228
+ {
9229
+ "passThreshold": 0.7,
9230
+ "rounding": {
9231
+ "dp": 2,
9232
+ "mode": "half-up"
9233
+ }
9234
+ }
9235
+ ],
9236
+ "expect": {
9237
+ "passFailureReason": null,
9238
+ "passed": null,
9239
+ "pendingSlotIds": ["a2"],
9240
+ "rejectedSlotIds": ["a2"],
9241
+ "score": 1,
9242
+ "sections": [
9243
+ {
9244
+ "appliedThreshold": null,
9245
+ "earnedPoints": 1,
9246
+ "gradedMaxPoints": 1,
9247
+ "id": "a",
9248
+ "maxPoints": 2,
9249
+ "normalizedWeight": 1,
9250
+ "passed": true,
9251
+ "pendingSlotIds": ["a2"],
9252
+ "rejectedSlotIds": ["a2"],
9253
+ "score": 1,
9254
+ "unscorableSlotIds": [],
9255
+ "weight": 1
9256
+ }
9257
+ ],
9258
+ "status": "provisional",
9259
+ "unscorableSlotIds": []
9260
+ },
9261
+ "fn": "composeAssessmentScore",
9262
+ "id": "composeAssessmentScore/rejected/failing-grade-out-of-zero",
9263
+ "note": "Why rejected is not unscorable: dropping this failing grade would record the attempt as a final pass on the other item alone."
9264
+ },
9265
+ {
9266
+ "args": [
9267
+ [
9268
+ {
9269
+ "id": "a",
9270
+ "items": [
9271
+ {
9272
+ "outcome": {
9273
+ "details": [],
9274
+ "feedback": null,
9275
+ "maxScore": 1,
9276
+ "passed": true,
9277
+ "score": 1,
9278
+ "status": "scored"
9279
+ },
9280
+ "points": 1,
9281
+ "slotId": "a1"
9282
+ },
9283
+ {
9284
+ "outcome": {
9285
+ "details": [],
9286
+ "feedback": null,
9287
+ "maxScore": 0,
9288
+ "passed": false,
9289
+ "score": 0,
9290
+ "status": "scored"
9291
+ },
9292
+ "points": 1,
9293
+ "slotId": "a2"
9294
+ }
9295
+ ],
9296
+ "weight": 1
9297
+ }
9298
+ ],
9299
+ {
9300
+ "passThreshold": 0.7,
9301
+ "rounding": {
9302
+ "dp": 2,
9303
+ "mode": "half-up"
9304
+ }
9305
+ }
9306
+ ],
9307
+ "expect": {
9308
+ "passFailureReason": null,
9309
+ "passed": null,
9310
+ "pendingSlotIds": ["a2"],
9311
+ "rejectedSlotIds": ["a2"],
9312
+ "score": 1,
9313
+ "sections": [
9314
+ {
9315
+ "appliedThreshold": null,
9316
+ "earnedPoints": 1,
9317
+ "gradedMaxPoints": 1,
9318
+ "id": "a",
9319
+ "maxPoints": 2,
9320
+ "normalizedWeight": 1,
9321
+ "passed": true,
9322
+ "pendingSlotIds": ["a2"],
9323
+ "rejectedSlotIds": ["a2"],
9324
+ "score": 1,
9325
+ "unscorableSlotIds": [],
9326
+ "weight": 1
9327
+ }
9328
+ ],
9329
+ "status": "provisional",
9330
+ "unscorableSlotIds": []
9331
+ },
9332
+ "fn": "composeAssessmentScore",
9333
+ "id": "composeAssessmentScore/rejected/zero-out-of-zero",
9334
+ "note": "Nothing out of nothing is still out of 0: maxScore must be above 0, not merely at least 0."
9335
+ },
9336
+ {
9337
+ "args": [
9338
+ [
9339
+ {
9340
+ "id": "a",
9341
+ "items": [
9342
+ {
9343
+ "outcome": {
9344
+ "details": [],
9345
+ "feedback": null,
9346
+ "maxScore": 1,
9347
+ "passed": true,
9348
+ "score": 1,
9349
+ "status": "scored"
9350
+ },
9351
+ "points": 1,
9352
+ "slotId": "a1"
9353
+ },
9354
+ {
9355
+ "outcome": {
9356
+ "maxScore": 1,
9357
+ "reason": "grade_rejected",
9358
+ "rejectedGrade": {
9359
+ "feedback": null,
9360
+ "maxScore": 1,
9361
+ "passed": true,
9362
+ "score": 85
9363
+ },
9364
+ "status": "deferred"
9365
+ },
9366
+ "points": 1,
9367
+ "slotId": "a2"
9368
+ },
9369
+ {
9370
+ "outcome": {
9371
+ "maxScore": 1,
9372
+ "reason": "requires_async_grading",
9373
+ "status": "deferred"
9374
+ },
9375
+ "points": 1,
9376
+ "slotId": "a3"
9377
+ }
9378
+ ],
9379
+ "weight": 1
9380
+ }
9381
+ ],
9382
+ {
9383
+ "passThreshold": 0.7,
9384
+ "rounding": {
9385
+ "dp": 2,
9386
+ "mode": "half-up"
9387
+ }
9388
+ }
9389
+ ],
9390
+ "expect": {
9391
+ "passFailureReason": null,
9392
+ "passed": null,
9393
+ "pendingSlotIds": ["a2", "a3"],
9394
+ "rejectedSlotIds": ["a2"],
9395
+ "score": 1,
9396
+ "sections": [
9397
+ {
9398
+ "appliedThreshold": null,
9399
+ "earnedPoints": 1,
9400
+ "gradedMaxPoints": 1,
9401
+ "id": "a",
9402
+ "maxPoints": 3,
9403
+ "normalizedWeight": 1,
9404
+ "passed": true,
9405
+ "pendingSlotIds": ["a2", "a3"],
9406
+ "rejectedSlotIds": ["a2"],
9407
+ "score": 1,
9408
+ "unscorableSlotIds": [],
9409
+ "weight": 1
9410
+ }
9411
+ ],
9412
+ "status": "provisional",
9413
+ "unscorableSlotIds": []
9414
+ },
9415
+ "fn": "composeAssessmentScore",
9416
+ "id": "composeAssessmentScore/rejected/outcome-from-grade-refusal",
9417
+ "note": "The outcome outcomeFromGrade now returns for a refused record: pending AND rejected. An ordinary deferred slot is pending only."
9418
+ },
9419
+ {
9420
+ "args": [
9421
+ [
9422
+ {
9423
+ "id": "a",
9424
+ "items": [
9425
+ {
9426
+ "outcome": {
9427
+ "details": [],
9428
+ "feedback": null,
9429
+ "maxScore": 1,
9430
+ "passed": false,
9431
+ "score": 0.5,
9432
+ "status": "scored"
9433
+ },
9434
+ "points": 1,
9435
+ "slotId": "a1"
9436
+ }
9437
+ ],
9438
+ "weight": 1
9439
+ },
9440
+ {
9441
+ "id": "b",
9442
+ "items": [
9443
+ {
9444
+ "outcome": {
9445
+ "feedback": null,
9446
+ "grade": {
9447
+ "feedback": null,
9448
+ "maxScore": 1,
9449
+ "passed": true,
9450
+ "score": 85
9451
+ },
9452
+ "maxScore": 1,
9453
+ "passed": true,
9454
+ "score": 85,
9455
+ "status": "graded"
9456
+ },
9457
+ "points": 1,
9458
+ "slotId": "b1"
9459
+ },
9460
+ {
9461
+ "outcome": {
9462
+ "details": [],
9463
+ "feedback": null,
9464
+ "maxScore": 1,
9465
+ "passed": true,
9466
+ "score": 1,
9467
+ "status": "scored"
9468
+ },
9469
+ "points": 1,
9470
+ "slotId": "b2"
9471
+ }
9472
+ ],
9473
+ "weight": 1
9474
+ }
9475
+ ],
9476
+ {
9477
+ "passThreshold": 0.7,
9478
+ "rounding": {
9479
+ "dp": 2,
9480
+ "mode": "half-up"
9481
+ }
9482
+ }
9483
+ ],
9484
+ "expect": {
9485
+ "passFailureReason": null,
9486
+ "passed": null,
9487
+ "pendingSlotIds": ["b1"],
9488
+ "rejectedSlotIds": ["b1"],
9489
+ "score": 0.75,
9490
+ "sections": [
9491
+ {
9492
+ "appliedThreshold": null,
9493
+ "earnedPoints": 0.5,
9494
+ "gradedMaxPoints": 1,
9495
+ "id": "a",
9496
+ "maxPoints": 1,
9497
+ "normalizedWeight": 0.5,
9498
+ "passed": true,
9499
+ "pendingSlotIds": [],
9500
+ "score": 0.5,
9501
+ "unscorableSlotIds": [],
9502
+ "weight": 1
9503
+ },
9504
+ {
9505
+ "appliedThreshold": null,
9506
+ "earnedPoints": 1,
9507
+ "gradedMaxPoints": 1,
9508
+ "id": "b",
9509
+ "maxPoints": 2,
9510
+ "normalizedWeight": 0.5,
9511
+ "passed": true,
9512
+ "pendingSlotIds": ["b1"],
9513
+ "rejectedSlotIds": ["b1"],
9514
+ "score": 1,
9515
+ "unscorableSlotIds": [],
9516
+ "weight": 1
9517
+ }
9518
+ ],
9519
+ "status": "provisional",
9520
+ "unscorableSlotIds": []
9521
+ },
9522
+ "fn": "composeAssessmentScore",
9523
+ "id": "composeAssessmentScore/rejected/named-on-its-own-section"
9524
+ },
9525
+ {
9526
+ "args": [
9527
+ [
9528
+ {
9529
+ "id": "a",
9530
+ "items": [
9531
+ {
9532
+ "outcome": {
9533
+ "feedback": null,
9534
+ "grade": {
9535
+ "feedback": null,
9536
+ "maxScore": 1,
9537
+ "passed": true,
9538
+ "score": 1.0000000001
9539
+ },
9540
+ "maxScore": 1,
9541
+ "passed": true,
9542
+ "score": 1.0000000001,
9543
+ "status": "graded"
9544
+ },
9545
+ "points": 1,
9546
+ "slotId": "a1"
9547
+ }
9548
+ ],
9549
+ "weight": 1
9550
+ }
9551
+ ],
9552
+ {
9553
+ "passThreshold": 0.7,
9554
+ "rounding": {
9555
+ "dp": 2,
9556
+ "mode": "half-up"
9557
+ }
9558
+ }
9559
+ ],
9560
+ "expect": {
9561
+ "passFailureReason": null,
9562
+ "passed": true,
9563
+ "pendingSlotIds": [],
9564
+ "score": 1,
9565
+ "sections": [
9566
+ {
9567
+ "appliedThreshold": null,
9568
+ "earnedPoints": 1.0000000001,
9569
+ "gradedMaxPoints": 1,
9570
+ "id": "a",
9571
+ "maxPoints": 1,
9572
+ "normalizedWeight": 1,
9573
+ "passed": true,
9574
+ "pendingSlotIds": [],
9575
+ "score": 1,
9576
+ "unscorableSlotIds": [],
9577
+ "weight": 1
9578
+ }
9579
+ ],
9580
+ "status": "final",
9581
+ "unscorableSlotIds": []
9582
+ },
9583
+ "fn": "composeAssessmentScore",
9584
+ "id": "composeAssessmentScore/accepted/float-noise-above-one",
9585
+ "note": "A hair over 1 is float noise: counted, final, and its earned points unclamped, exactly as before."
9586
+ },
9587
+ {
9588
+ "args": [
9589
+ [
9590
+ {
9591
+ "id": "a",
9592
+ "items": [
9593
+ {
9594
+ "outcome": {
9595
+ "feedback": null,
9596
+ "grade": {
9597
+ "feedback": null,
9598
+ "maxScore": 1000000000,
9599
+ "passed": true,
9600
+ "score": 1000000001
9601
+ },
9602
+ "maxScore": 1000000000,
9603
+ "passed": true,
9604
+ "score": 1000000001,
9605
+ "status": "graded"
9606
+ },
9607
+ "points": 1,
9608
+ "slotId": "a1"
9609
+ }
9610
+ ],
9611
+ "weight": 1
9612
+ }
9613
+ ],
9614
+ {
9615
+ "passThreshold": 0.7,
9616
+ "rounding": {
9617
+ "dp": 2,
9618
+ "mode": "half-up"
9619
+ }
9620
+ }
9621
+ ],
9622
+ "expect": {
9623
+ "passFailureReason": null,
9624
+ "passed": true,
9625
+ "pendingSlotIds": [],
9626
+ "score": 1,
9627
+ "sections": [
9628
+ {
9629
+ "appliedThreshold": null,
9630
+ "earnedPoints": 1.000000001,
9631
+ "gradedMaxPoints": 1,
9632
+ "id": "a",
9633
+ "maxPoints": 1,
9634
+ "normalizedWeight": 1,
9635
+ "passed": true,
9636
+ "pendingSlotIds": [],
9637
+ "score": 1,
9638
+ "unscorableSlotIds": [],
9639
+ "weight": 1
9640
+ }
9641
+ ],
9642
+ "status": "final",
9643
+ "unscorableSlotIds": []
9644
+ },
9645
+ "fn": "composeAssessmentScore",
9646
+ "id": "composeAssessmentScore/accepted/exact-edge-of-float-noise"
8399
9647
  },
8400
9648
  {
8401
9649
  "args": [