@rightkit/release 0.4.1 → 0.5.1

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.
@@ -19,7 +19,8 @@
19
19
  "@rightkit/doc-render": "0.2.1",
20
20
  "@rightkit/hooks": "0.1.2",
21
21
  "@rightkit/i18n": "0.2.0",
22
- "@rightkit/legal": "0.6.1",
22
+ "@rightkit/issues-tracker": "0.1.0",
23
+ "@rightkit/legal": "0.6.2",
23
24
  "@rightkit/legal-ui": "0.4.1",
24
25
  "@rightkit/license": "0.3.0",
25
26
  "@rightkit/logs": "0.1.6",
@@ -28,10 +29,10 @@
28
29
  "@rightkit/outdated": "0.2.0",
29
30
  "@rightkit/pdf-ui": "0.2.0",
30
31
  "@rightkit/platform-ui": "0.4.0",
31
- "@rightkit/qa": "0.5.2",
32
- "@rightkit/qa-chrome": "0.1.10",
32
+ "@rightkit/qa": "0.6.1",
33
+ "@rightkit/qa-chrome": "0.1.11",
33
34
  "@rightkit/react-shell": "0.7.2",
34
- "@rightkit/release": "0.4.1",
35
+ "@rightkit/release": "0.5.1",
35
36
  "@rightkit/settings-ui": "0.7.0",
36
37
  "@rightkit/tauri": "0.3.0",
37
38
  "@rightkit/tauri-shell": "0.1.2",
@@ -105,7 +106,8 @@
105
106
  "0.3.0",
106
107
  "0.3.1",
107
108
  "0.5.0",
108
- "0.6.0"
109
+ "0.6.0",
110
+ "0.6.1"
109
111
  ],
110
112
  "@rightkit/license": [
111
113
  "0.1.6",
@@ -220,7 +222,9 @@
220
222
  "0.2.173",
221
223
  "0.2.174",
222
224
  "0.3.0",
223
- "0.4.0"
225
+ "0.4.0",
226
+ "0.4.1",
227
+ "0.5.0"
224
228
  ],
225
229
  "@rightkit/qa": [
226
230
  "0.1.0",
@@ -243,7 +247,8 @@
243
247
  "0.4.8",
244
248
  "0.4.9",
245
249
  "0.5.0",
246
- "0.5.1"
250
+ "0.5.1",
251
+ "0.5.2"
247
252
  ],
248
253
  "@rightkit/app-shell": [
249
254
  "0.1.0",
@@ -360,7 +365,8 @@
360
365
  "0.1.4",
361
366
  "0.1.5",
362
367
  "0.1.6",
363
- "0.1.8"
368
+ "0.1.8",
369
+ "0.1.10"
364
370
  ],
365
371
  "@rightkit/updates": [
366
372
  "0.2.4"
@@ -424,63 +430,64 @@
424
430
  "rightkit-tauri": "0.1.0"
425
431
  },
426
432
  "stagedCargo": {
427
- "rightkit-agent-tools": "0.2.1",
433
+ "rightkit-agent-tools": "0.3.0",
428
434
  "rightkit-agents": "0.2.0",
429
435
  "rightkit-android": "0.3.0",
430
436
  "rightkit-app-settings": "0.3.0",
431
437
  "rightkit-asr": "0.3.0",
432
438
  "rightkit-audio": "0.3.1",
433
- "rightkit-automation": "0.5.0",
439
+ "rightkit-automation": "0.6.0",
434
440
  "rightkit-browser": "0.3.5",
435
441
  "rightkit-cache": "0.2.3",
436
442
  "rightkit-channel-memory": "0.2.1",
437
- "rightkit-child-process": "0.5.4",
443
+ "rightkit-child-process": "0.5.5",
438
444
  "rightkit-compose": "0.2.0",
439
445
  "rightkit-contracts": "0.1.7",
440
- "rightkit-crash": "0.3.4",
441
- "rightkit-credentials": "0.3.1",
446
+ "rightkit-crash": "0.3.6",
447
+ "rightkit-credentials": "0.4.2",
442
448
  "rightkit-crypto": "0.1.0",
443
- "rightkit-daemon": "0.3.1",
444
- "rightkit-db": "0.5.0",
445
- "rightkit-device": "0.3.1",
446
- "rightkit-docs": "0.1.1",
447
- "rightkit-embed": "0.6.0",
449
+ "rightkit-daemon": "0.4.0",
450
+ "rightkit-db": "0.5.1",
451
+ "rightkit-device": "0.4.0",
452
+ "rightkit-docs": "0.1.2",
453
+ "rightkit-embed": "0.6.1",
448
454
  "rightkit-ffmpeg": "0.2.10",
449
455
  "rightkit-file-watch": "0.4.1",
450
456
  "rightkit-fs": "0.4.6",
451
- "rightkit-fsindex": "0.4.1",
457
+ "rightkit-fsindex": "0.5.0",
452
458
  "rightkit-google-identity": "0.2.0",
453
459
  "rightkit-hooks": "0.2.0",
454
460
  "rightkit-hotkeys": "0.1.2",
455
461
  "rightkit-http": "0.3.8",
456
462
  "rightkit-identity": "0.1.0",
457
- "rightkit-job-queue": "0.4.1",
463
+ "rightkit-job-queue": "0.5.0",
458
464
  "rightkit-license": "0.2.4",
459
465
  "rightkit-llm": "0.3.0",
460
466
  "rightkit-logs": "0.3.5",
461
467
  "rightkit-mcp": "0.7.0",
462
- "rightkit-models": "0.5.0",
468
+ "rightkit-models": "0.5.1",
463
469
  "rightkit-motion": "0.2.0",
464
- "rightkit-oauth": "0.9.0",
470
+ "rightkit-oauth": "0.10.0",
465
471
  "rightkit-ocr": "0.2.3",
466
472
  "rightkit-onnx": "0.2.7",
467
- "rightkit-overlay": "0.1.2",
468
- "rightkit-ownership": "0.3.1",
469
- "rightkit-pdf": "0.3.2",
473
+ "rightkit-overlay": "0.2.0",
474
+ "rightkit-overlay-win": "0.1.0",
475
+ "rightkit-ownership": "0.4.0",
476
+ "rightkit-pdf": "0.3.3",
470
477
  "rightkit-platform-rules": "0.1.0",
471
478
  "rightkit-playback": "0.3.0",
472
- "rightkit-qa": "0.7.1",
473
- "rightkit-qa-driver": "0.6.0",
479
+ "rightkit-qa": "0.8.0",
480
+ "rightkit-qa-driver": "0.7.0",
474
481
  "rightkit-record": "0.3.3",
475
482
  "rightkit-review": "0.4.0",
476
- "rightkit-sandbox": "0.5.0",
483
+ "rightkit-sandbox": "0.6.0",
477
484
  "rightkit-search": "0.4.0",
478
485
  "rightkit-send": "0.2.0",
479
486
  "rightkit-sidecar": "0.3.0",
480
487
  "rightkit-speech-client": "0.4.0",
481
488
  "rightkit-spend": "0.2.0",
482
489
  "rightkit-sync": "0.2.2",
483
- "rightkit-tauri-shell": "0.4.0",
490
+ "rightkit-tauri-shell": "0.5.0",
484
491
  "rightkit-time": "0.1.0",
485
492
  "rightkit-transcript": "0.4.0",
486
493
  "rightkit-tts": "0.2.3",
@@ -506,65 +513,66 @@
506
513
  },
507
514
  "registry": {
508
515
  "cargo": {
509
- "rightkit-agent-tools": "0.2.0",
516
+ "rightkit-agent-tools": "0.3.0",
510
517
  "rightkit-agents": "0.2.0",
511
- "rightkit-android": "0.2.0",
518
+ "rightkit-android": "0.3.0",
512
519
  "rightkit-app-settings": "0.3.0",
513
- "rightkit-asr": "0.2.4",
520
+ "rightkit-asr": "0.3.0",
514
521
  "rightkit-audio": "0.3.1",
515
- "rightkit-automation": "0.5.0",
522
+ "rightkit-automation": "0.6.0",
516
523
  "rightkit-browser": "0.3.4",
517
524
  "rightkit-cache": "0.2.3",
518
525
  "rightkit-channel-memory": "0.2.1",
519
- "rightkit-child-process": "0.5.4",
526
+ "rightkit-child-process": "0.5.5",
520
527
  "rightkit-compose": "0.2.0",
521
528
  "rightkit-contracts": "0.1.7",
522
529
  "rightkit-control": "0.3.0",
523
- "rightkit-crash": "0.3.4",
524
- "rightkit-credentials": "0.3.0",
530
+ "rightkit-crash": "0.3.6",
531
+ "rightkit-credentials": "0.4.2",
525
532
  "rightkit-crypto": "0.1.0",
526
- "rightkit-daemon": "0.3.0",
533
+ "rightkit-daemon": "0.4.0",
527
534
  "rightkit-db": "0.5.1",
528
- "rightkit-device": "0.3.1",
529
- "rightkit-docs": "0.1.1",
530
- "rightkit-embed": "0.6.0",
531
- "rightkit-ffmpeg": "0.2.9",
535
+ "rightkit-device": "0.4.0",
536
+ "rightkit-docs": "0.1.2",
537
+ "rightkit-embed": "0.6.1",
538
+ "rightkit-ffmpeg": "0.2.10",
532
539
  "rightkit-file-watch": "0.4.1",
533
540
  "rightkit-framed-sidecar": "0.2.0",
534
541
  "rightkit-fs": "0.4.6",
535
- "rightkit-fsindex": "0.4.1",
536
- "rightkit-google-identity": "0.1.0",
542
+ "rightkit-fsindex": "0.5.0",
543
+ "rightkit-google-identity": "0.2.0",
537
544
  "rightkit-hooks": "0.2.0",
538
545
  "rightkit-hotkeys": "0.1.2",
539
546
  "rightkit-http": "0.3.8",
540
547
  "rightkit-identity": "0.1.0",
541
- "rightkit-job-queue": "0.4.0",
548
+ "rightkit-job-queue": "0.5.0",
542
549
  "rightkit-jobs": "0.3.0",
543
- "rightkit-license": "0.2.3",
550
+ "rightkit-license": "0.2.4",
544
551
  "rightkit-llm": "0.3.0",
545
552
  "rightkit-logs": "0.3.5",
546
553
  "rightkit-mcp": "0.7.0",
547
554
  "rightkit-media": "0.2.6",
548
- "rightkit-models": "0.4.4",
549
- "rightkit-motion": "0.1.0",
550
- "rightkit-oauth": "0.9.0",
555
+ "rightkit-models": "0.5.1",
556
+ "rightkit-motion": "0.2.0",
557
+ "rightkit-oauth": "0.10.0",
551
558
  "rightkit-ocr": "0.2.3",
552
- "rightkit-onnx": "0.2.6",
559
+ "rightkit-onnx": "0.2.7",
553
560
  "rightkit-ort": "0.2.3",
554
- "rightkit-overlay": "0.1.2",
555
- "rightkit-ownership": "0.3.1",
556
- "rightkit-pdf": "0.3.2",
561
+ "rightkit-overlay": "0.2.0",
562
+ "rightkit-overlay-win": "0.1.0",
563
+ "rightkit-ownership": "0.4.0",
564
+ "rightkit-pdf": "0.3.3",
557
565
  "rightkit-platform-rules": "0.1.0",
558
- "rightkit-playback": "0.2.2",
566
+ "rightkit-playback": "0.3.0",
559
567
  "rightkit-process": "0.4.0",
560
- "rightkit-qa": "0.7.1",
561
- "rightkit-qa-driver": "0.6.0",
568
+ "rightkit-qa": "0.8.0",
569
+ "rightkit-qa-driver": "0.7.0",
562
570
  "rightkit-qts": "0.2.6",
563
571
  "rightkit-qts-ggml": "0.1.2",
564
572
  "rightkit-qts-ggml-sys": "0.1.2",
565
- "rightkit-record": "0.3.2",
573
+ "rightkit-record": "0.3.3",
566
574
  "rightkit-review": "0.4.0",
567
- "rightkit-sandbox": "0.5.0",
575
+ "rightkit-sandbox": "0.6.0",
568
576
  "rightkit-search": "0.4.0",
569
577
  "rightkit-secrets": "0.2.0",
570
578
  "rightkit-send": "0.2.0",
@@ -572,11 +580,11 @@
572
580
  "rightkit-settings": "0.2.0",
573
581
  "rightkit-shell": "0.3.0",
574
582
  "rightkit-sidecar": "0.3.0",
575
- "rightkit-speech-client": "0.3.6",
576
- "rightkit-spend": "0.1.1",
583
+ "rightkit-speech-client": "0.4.0",
584
+ "rightkit-spend": "0.2.0",
577
585
  "rightkit-sync": "0.2.2",
578
586
  "rightkit-tauri": "0.1.3",
579
- "rightkit-tauri-shell": "0.4.0",
587
+ "rightkit-tauri-shell": "0.5.0",
580
588
  "rightkit-time": "0.1.0",
581
589
  "rightkit-transcript": "0.4.0",
582
590
  "rightkit-tts": "0.2.3",
@@ -584,33 +592,34 @@
584
592
  "rightkit-tts-qwen-sys": "0.1.2",
585
593
  "rightkit-typeset": "0.1.0",
586
594
  "rightkit-vad": "0.1.2",
587
- "rightkit-vault": "0.1.0",
595
+ "rightkit-vault": "0.2.0",
588
596
  "rightkit-watch": "0.4.0",
589
597
  "rightkit-workflow": "0.2.0"
590
598
  },
591
599
  "npm": {
592
600
  "@rightkit/app-shell": "0.6.2",
593
- "@rightkit/app-update": "0.4.0",
601
+ "@rightkit/app-update": "0.4.1",
594
602
  "@rightkit/ax": "0.3.2",
595
603
  "@rightkit/ci": "0.3.0",
596
604
  "@rightkit/doc-render": "0.2.1",
597
605
  "@rightkit/git": "0.2.42",
598
606
  "@rightkit/hooks": "0.1.2",
599
607
  "@rightkit/i18n": "0.2.0",
600
- "@rightkit/legal": "0.6.1",
608
+ "@rightkit/issues-tracker": "0.1.0",
609
+ "@rightkit/legal": "0.6.2",
601
610
  "@rightkit/legal-ui": "0.4.1",
602
611
  "@rightkit/license": "0.3.0",
603
- "@rightkit/logs": "0.1.5",
612
+ "@rightkit/logs": "0.1.6",
604
613
  "@rightkit/media-ui": "0.3.4",
605
614
  "@rightkit/onboarding": "0.6.3",
606
615
  "@rightkit/outdated": "0.2.0",
607
616
  "@rightkit/pdf-ui": "0.2.0",
608
617
  "@rightkit/platform-ui": "0.4.0",
609
- "@rightkit/qa": "0.5.2",
610
- "@rightkit/qa-chrome": "0.1.10",
618
+ "@rightkit/qa": "0.6.1",
619
+ "@rightkit/qa-chrome": "0.1.11",
611
620
  "@rightkit/react-shell": "0.7.2",
612
- "@rightkit/release": "0.4.0",
613
- "@rightkit/settings-ui": "0.6.1",
621
+ "@rightkit/release": "0.5.0",
622
+ "@rightkit/settings-ui": "0.7.0",
614
623
  "@rightkit/shell": "0.1.1",
615
624
  "@rightkit/tauri": "0.3.0",
616
625
  "@rightkit/tauri-shell": "0.1.2",
@@ -621,7 +630,8 @@
621
630
  "legacyCargo": {
622
631
  "rightkit-ownership": [
623
632
  "0.2.0",
624
- "0.2.1"
633
+ "0.2.1",
634
+ "0.3.1"
625
635
  ],
626
636
  "rightkit-browser": [
627
637
  "0.2.0",
@@ -666,7 +676,8 @@
666
676
  "0.3.1",
667
677
  "0.3.2",
668
678
  "0.4.0",
669
- "0.5.0"
679
+ "0.5.0",
680
+ "0.6.0"
670
681
  ],
671
682
  "rightkit-jobs": [
672
683
  "0.2.1",
@@ -735,7 +746,8 @@
735
746
  "0.6.0",
736
747
  "0.6.1",
737
748
  "0.6.4",
738
- "0.7.0"
749
+ "0.7.0",
750
+ "0.7.1"
739
751
  ],
740
752
  "rightkit-sandbox": [
741
753
  "0.1.0",
@@ -829,7 +841,8 @@
829
841
  ],
830
842
  "rightkit-pdf": [
831
843
  "0.1.0",
832
- "0.3.0"
844
+ "0.3.0",
845
+ "0.3.2"
833
846
  ],
834
847
  "rightkit-speech-client": [
835
848
  "0.3.0",
@@ -845,7 +858,9 @@
845
858
  "0.2.2",
846
859
  "0.3.0",
847
860
  "0.3.2",
848
- "0.3.3"
861
+ "0.3.3",
862
+ "0.3.4",
863
+ "0.3.5"
849
864
  ],
850
865
  "rightkit-qts-ggml-sys": [
851
866
  "0.1.0",
@@ -855,7 +870,8 @@
855
870
  "0.1.0",
856
871
  "0.2.0",
857
872
  "0.2.1",
858
- "0.3.0"
873
+ "0.3.0",
874
+ "0.4.1"
859
875
  ],
860
876
  "rightkit-asr": [
861
877
  "0.0.2",
@@ -918,7 +934,8 @@
918
934
  "0.3.1",
919
935
  "0.4.0",
920
936
  "0.4.1",
921
- "0.5.0"
937
+ "0.5.0",
938
+ "0.6.0"
922
939
  ],
923
940
  "rightkit-agent-tools": [
924
941
  "0.1.2",
@@ -941,7 +958,8 @@
941
958
  "0.5.0",
942
959
  "0.5.1",
943
960
  "0.5.2",
944
- "0.5.3"
961
+ "0.5.3",
962
+ "0.5.4"
945
963
  ],
946
964
  "rightkit-hotkeys": [
947
965
  "0.1.0",
@@ -965,7 +983,8 @@
965
983
  "0.2.1"
966
984
  ],
967
985
  "rightkit-overlay": [
968
- "0.1.1"
986
+ "0.1.1",
987
+ "0.1.2"
969
988
  ],
970
989
  "rightkit-app-settings": [
971
990
  "0.2.0",
@@ -984,7 +1003,9 @@
984
1003
  "rightkit-credentials": [
985
1004
  "0.2.0",
986
1005
  "0.2.1",
987
- "0.3.0"
1006
+ "0.3.0",
1007
+ "0.4.0",
1008
+ "0.4.1"
988
1009
  ],
989
1010
  "rightkit-review": [
990
1011
  "0.2.0"
@@ -995,7 +1016,8 @@
995
1016
  "rightkit-device": [
996
1017
  "0.1.3",
997
1018
  "0.2.0",
998
- "0.3.0"
1019
+ "0.3.0",
1020
+ "0.3.1"
999
1021
  ],
1000
1022
  "rightkit-onnx": [
1001
1023
  "0.2.3",
@@ -1010,7 +1032,8 @@
1010
1032
  "0.2.0"
1011
1033
  ],
1012
1034
  "rightkit-docs": [
1013
- "0.1.0"
1035
+ "0.1.0",
1036
+ "0.1.1"
1014
1037
  ],
1015
1038
  "rightkit-tts-qwen": [
1016
1039
  "0.2.6"
@@ -21,6 +21,10 @@
21
21
  "ceilings": null,
22
22
  "requiredScale": null
23
23
  },
24
+ "rightkit-crash": {
25
+ "ceilings": null,
26
+ "requiredScale": null
27
+ },
24
28
  "rightkit-embed": {
25
29
  "ceilings": null,
26
30
  "requiredScale": null
@@ -41,6 +45,10 @@
41
45
  "ceilings": null,
42
46
  "requiredScale": null
43
47
  },
48
+ "rightkit-overlay-win": {
49
+ "ceilings": null,
50
+ "requiredScale": null
51
+ },
44
52
  "rightkit-record": {
45
53
  "ceilings": null,
46
54
  "requiredScale": null
@@ -0,0 +1,107 @@
1
+ // Canonical JSON and the scan-set digest, shared by the scanner (deterministic-scans.mjs) and the credentialed
2
+ // receipt verifiers (scripts/ci/scan-receipt.mjs). No imports beyond node:crypto, by design.
3
+ import crypto from "node:crypto";
4
+
5
+ const sha256 = (value) => crypto.createHash("sha256").update(value).digest("hex");
6
+
7
+ /** Deterministic JSON: object keys sorted, no undefined, no non-finite numbers. */
8
+ export function canonicalJson(value) {
9
+ if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
10
+ if (typeof value === "number") {
11
+ if (!Number.isFinite(value)) throw new TypeError("canonicalJson: non-finite number");
12
+ return JSON.stringify(value);
13
+ }
14
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
15
+ if (typeof value === "object") {
16
+ const keys = Object.keys(value).sort();
17
+ for (const key of keys) if (value[key] === undefined) throw new TypeError(`canonicalJson: undefined at ${key}`);
18
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
19
+ }
20
+ throw new TypeError(`canonicalJson: unsupported ${typeof value}`);
21
+ }
22
+
23
+ /** Digest of a scan set: the sorted (id, class, command) of every entry. Plan items and result rows agree. */
24
+ export function digestScanSet(entries) {
25
+ const rows = entries.map((e) => [String(e.id), String(e.class), String(e.command)]).sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
26
+ return sha256(canonicalJson(rows));
27
+ }
28
+
29
+ // ---- required scan ids ---------------------------------------------------------------------------------
30
+ // The one place the scan ids that belong to a crate are spelled, shared by planScans (deterministic-scans.mjs) and by the
31
+ // credentialed verifiers (scripts/ci/scan-receipt.mjs), so a verifier recomputes what a receipt must contain from the
32
+ // authenticated source and never trusts the plan the producer recorded. Dependency-free by design (see the header).
33
+
34
+ export const rustScanId = Object.freeze({
35
+ check: (name) => `check:${name}`,
36
+ checkFeatures: (name, index) => `check-features:${name}:${index}`,
37
+ clippy: (name, count, index) => (count === 1 ? `clippy:${name}` : `clippy:${name}:${index}`),
38
+ doc: (name) => `doc:${name}`,
39
+ testRust: (name, count, index) => `test:rust:${name}${count === 1 ? "" : `:${index}`}`,
40
+ testRustSerial: (name, count, index) => `test:rust-serial:${name}${count === 1 ? "" : `:${index}`}`,
41
+ packageList: (name) => `cargo-package-list:${name}`,
42
+ changelog: (name) => `changelog-version:${name}`,
43
+ });
44
+
45
+ /**
46
+ * A crate's compile feature plan exactly as CI's gate runs it (ci/gate.config.json rust.<crate>): `lintSets` (clippy; default
47
+ * features when none), whether a default `check` is needed (no lint set covers default features), and the `checkSets` that
48
+ * remain (none when a lint set already uses --all-features).
49
+ */
50
+ export function rustCratePlan(own = {}) {
51
+ const lintSets = Array.isArray(own?.featureSets) && own.featureSets.length ? own.featureSets : [[]];
52
+ const defaultCheck = !lintSets.some((set) => set.length === 0);
53
+ const checkSets = (lintSets.some((set) => set.includes("--all-features")) ? [] : (Array.isArray(own?.checkFeatureSets) ? own.checkFeatureSets : [["--all-features"]])).filter((set) => set.length);
54
+ return { lintSets, defaultCheck, checkSets };
55
+ }
56
+
57
+ /** Scan ids every scan of the whole repository always has when it holds Rust units (cargo.toml, workflows, YAML, JSON and licences). */
58
+ export const WORKSPACE_SCAN_IDS = Object.freeze(["cargo-metadata", "cargo-deny", "cargo-audit", "actionlint", "yaml-parse", "toml-parse", "json-parse", "license", "secret-scan"]);
59
+ /** Prefixes at least one scan id must carry (rustfmt groups by edition, so its exact ids depend on the files). */
60
+ export const REQUIRED_SCAN_PREFIXES = Object.freeze(["rustfmt:"]);
61
+
62
+ /**
63
+ * The scan ids a LOCAL scan record must contain, each with status pass, for these publishable Rust `units` ([names], crates/<name>).
64
+ * `exists(repoPath)` answers from the AUTHENTICATED source (never from the record): src/lib.rs decides `doc`, CHANGELOG.md decides
65
+ * `changelog-version`, and the repository's own ci/advisory-exceptions.json, ownership catalog and docs generator decide theirs.
66
+ * `crateFeatures` is ci/gate.config.json `rust`. `includeTests` adds the per-feature-set test scans. Extra scans in a record are
67
+ * allowed; a missing one is not. planScans builds its ids from the same helpers, and a test holds the two in agreement.
68
+ */
69
+ export function requiredScanIds({ units, crateFeatures = {}, exists, includeTests = false }) {
70
+ if (!Array.isArray(units) || units.length === 0 || !units.every((n) => typeof n === "string" && n)) throw new TypeError("requiredScanIds: units must be a non-empty array of names");
71
+ if (typeof exists !== "function") throw new TypeError("requiredScanIds: exists(repoPath) is required");
72
+ const ids = new Set(WORKSPACE_SCAN_IDS);
73
+ if (exists("ci/advisory-exceptions.json")) ids.add("advisory-exceptions");
74
+ if (exists("packages/release/rightkit-ownership.json") && exists("crates/rightkit-ownership/catalog/ownership-catalog.json")) ids.add("ownership-catalog");
75
+ if (exists("scripts/generate-index.mjs")) ids.add("generated-docs");
76
+ for (const name of units) {
77
+ const own = crateFeatures?.[name] ?? {};
78
+ const { lintSets, defaultCheck, checkSets } = rustCratePlan(own);
79
+ ids.add(rustScanId.packageList(name));
80
+ if (exists(`crates/${name}/CHANGELOG.md`)) ids.add(rustScanId.changelog(name));
81
+ if (defaultCheck) ids.add(rustScanId.check(name));
82
+ checkSets.forEach((_set, i) => ids.add(rustScanId.checkFeatures(name, i)));
83
+ lintSets.forEach((_set, i) => ids.add(rustScanId.clippy(name, lintSets.length, i)));
84
+ if (exists(`crates/${name}/src/lib.rs`)) ids.add(rustScanId.doc(name));
85
+ if (includeTests) {
86
+ lintSets.forEach((_set, i) => {
87
+ ids.add(rustScanId.testRust(name, lintSets.length, i));
88
+ if (own.alsoSerial) ids.add(rustScanId.testRustSerial(name, lintSets.length, i));
89
+ });
90
+ }
91
+ }
92
+ return [...ids].sort();
93
+ }
94
+
95
+ /** Why `rows` (a record's scans) do not contain every required id with status pass; empty when they do. */
96
+ export function requiredScanProblems(rows, required, prefixes = REQUIRED_SCAN_PREFIXES) {
97
+ const byId = new Map();
98
+ for (const row of Array.isArray(rows) ? rows : []) if (row && typeof row.id === "string") byId.set(row.id, row);
99
+ const problems = [];
100
+ for (const id of required) {
101
+ const row = byId.get(id);
102
+ if (!row) problems.push(`required scan ${id} is missing`);
103
+ else if (row.status !== "pass") problems.push(`required scan ${id} is ${row.status}`);
104
+ }
105
+ for (const prefix of prefixes) if (![...byId.values()].some((row) => row.id.startsWith(prefix) && row.status === "pass")) problems.push(`no passing ${prefix}* scan`);
106
+ return problems;
107
+ }