@rigour-labs/core 6.6.2 → 6.6.4
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/dist/deep/diff-tests/run.js +2 -12
- package/dist/firewall/firewall.test.js +4 -0
- package/dist/firewall/trusted-control.js +2 -2
- package/dist/firewall/typed-command.js +2 -1
- package/dist/gates/logic-drift-git-base.d.ts +9 -0
- package/dist/gates/logic-drift-git-base.js +16 -11
- package/dist/gates/runner.d.ts +3 -0
- package/dist/gates/runner.js +4 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +2 -2
- package/dist/hooks/session-state.d.ts +9 -0
- package/dist/hooks/session-state.js +37 -0
- package/dist/hooks/stop-review.d.ts +18 -11
- package/dist/hooks/stop-review.js +24 -8
- package/dist/hooks/templates.d.ts +8 -1
- package/dist/hooks/templates.js +19 -2
- package/dist/hooks/templates.test.js +12 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/review/baseline.d.ts +16 -0
- package/dist/review/baseline.js +96 -0
- package/dist/review/baseline.test.d.ts +1 -0
- package/dist/review/baseline.test.js +22 -0
- package/dist/review/branch-checks.d.ts +6 -0
- package/dist/review/branch-checks.js +83 -0
- package/dist/review/branch-checks.test.d.ts +1 -0
- package/dist/review/branch-checks.test.js +48 -0
- package/dist/review/code-patterns.test.d.ts +1 -0
- package/dist/review/code-patterns.test.js +84 -0
- package/dist/review/dead-code.test.d.ts +1 -0
- package/dist/review/dead-code.test.js +126 -0
- package/dist/review/duplicate-functions.d.ts +2 -0
- package/dist/review/duplicate-functions.js +98 -0
- package/dist/review/effectiveness.d.ts +3 -0
- package/dist/review/optional-params.d.ts +2 -0
- package/dist/review/optional-params.js +123 -0
- package/dist/review/orphan-files.d.ts +2 -0
- package/dist/review/orphan-files.js +125 -0
- package/dist/review/package-layout.d.ts +9 -0
- package/dist/review/package-layout.js +108 -0
- package/dist/review/query-patterns.d.ts +2 -0
- package/dist/review/query-patterns.js +153 -0
- package/dist/review/quiet.js +1 -1
- package/dist/review/review.d.ts +2 -0
- package/dist/review/review.js +29 -1
- package/dist/review/review.test.js +28 -2
- package/dist/review/reviewer.d.ts +55 -0
- package/dist/review/reviewer.js +224 -0
- package/dist/review/reviewer.test.d.ts +1 -0
- package/dist/review/reviewer.test.js +99 -0
- package/dist/review/test-files.d.ts +2 -0
- package/dist/review/test-files.js +4 -0
- package/dist/review/toolchain.d.ts +11 -0
- package/dist/review/toolchain.js +126 -0
- package/dist/review/toolchain.test.d.ts +1 -0
- package/dist/review/toolchain.test.js +67 -0
- package/dist/review/unused-exports.d.ts +4 -0
- package/dist/review/unused-exports.js +189 -0
- package/dist/settings.js +2 -3
- package/dist/storage/db.js +1 -2
- package/dist/storage/team-scope.d.ts +20 -0
- package/dist/storage/team-scope.js +32 -0
- package/dist/storage/team-scope.test.d.ts +1 -0
- package/dist/storage/team-scope.test.js +22 -0
- package/dist/storage/team-store.d.ts +5 -0
- package/dist/storage/team-store.js +42 -7
- package/dist/storage/team-sync-scope.test.d.ts +1 -0
- package/dist/storage/team-sync-scope.test.js +67 -0
- package/dist/telemetry/telemetry.js +5 -5
- package/dist/templates/universal-config.js +23 -0
- package/dist/types/index.d.ts +253 -6
- package/dist/types/index.js +27 -0
- package/dist/utils/installed-bin.d.ts +2 -0
- package/dist/utils/installed-bin.js +15 -0
- package/dist/utils/profile.d.ts +30 -0
- package/dist/utils/profile.js +116 -0
- package/dist/utils/profile.test.d.ts +1 -0
- package/dist/utils/profile.test.js +58 -0
- package/dist/utils/scanner.js +3 -1
- package/dist/utils/scanner.test.js +6 -2
- package/dist/utils/user-state.d.ts +3 -1
- package/dist/utils/user-state.js +6 -2
- package/package.json +10 -6
package/dist/types/index.d.ts
CHANGED
|
@@ -518,6 +518,52 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
518
518
|
enabled?: boolean | undefined;
|
|
519
519
|
registry?: string | undefined;
|
|
520
520
|
}>>>;
|
|
521
|
+
/** Exports the change adds that no other file names (review/unused-exports.ts). */
|
|
522
|
+
unused_exports: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
523
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
524
|
+
allow: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
525
|
+
}, "strip", z.ZodTypeAny, {
|
|
526
|
+
enabled: boolean;
|
|
527
|
+
allow: string[];
|
|
528
|
+
}, {
|
|
529
|
+
enabled?: boolean | undefined;
|
|
530
|
+
allow?: string[] | undefined;
|
|
531
|
+
}>>>;
|
|
532
|
+
/** Query shapes that cost production: offset paging in a loop, a time window with no upper bound (review/query-patterns.ts). */
|
|
533
|
+
query_patterns: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
534
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
535
|
+
}, "strip", z.ZodTypeAny, {
|
|
536
|
+
enabled: boolean;
|
|
537
|
+
}, {
|
|
538
|
+
enabled?: boolean | undefined;
|
|
539
|
+
}>>>;
|
|
540
|
+
/** A parameter the change adds as optional that only tests omit (review/optional-params.ts). */
|
|
541
|
+
optional_params: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
542
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
543
|
+
}, "strip", z.ZodTypeAny, {
|
|
544
|
+
enabled: boolean;
|
|
545
|
+
}, {
|
|
546
|
+
enabled?: boolean | undefined;
|
|
547
|
+
}>>>;
|
|
548
|
+
/** A changed function whose body duplicates another in the files the change touched (review/duplicate-functions.ts). */
|
|
549
|
+
duplicate_functions: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
550
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
551
|
+
}, "strip", z.ZodTypeAny, {
|
|
552
|
+
enabled: boolean;
|
|
553
|
+
}, {
|
|
554
|
+
enabled?: boolean | undefined;
|
|
555
|
+
}>>>;
|
|
556
|
+
/** Code files the change adds that nothing imports or runs (review/orphan-files.ts). */
|
|
557
|
+
orphan_files: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
558
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
559
|
+
allow: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
560
|
+
}, "strip", z.ZodTypeAny, {
|
|
561
|
+
enabled: boolean;
|
|
562
|
+
allow: string[];
|
|
563
|
+
}, {
|
|
564
|
+
enabled?: boolean | undefined;
|
|
565
|
+
allow?: string[] | undefined;
|
|
566
|
+
}>>>;
|
|
521
567
|
migration_order: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
522
568
|
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
523
569
|
dirs: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
@@ -955,6 +1001,23 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
955
1001
|
enabled: boolean;
|
|
956
1002
|
registry?: string | undefined;
|
|
957
1003
|
};
|
|
1004
|
+
unused_exports: {
|
|
1005
|
+
enabled: boolean;
|
|
1006
|
+
allow: string[];
|
|
1007
|
+
};
|
|
1008
|
+
query_patterns: {
|
|
1009
|
+
enabled: boolean;
|
|
1010
|
+
};
|
|
1011
|
+
optional_params: {
|
|
1012
|
+
enabled: boolean;
|
|
1013
|
+
};
|
|
1014
|
+
duplicate_functions: {
|
|
1015
|
+
enabled: boolean;
|
|
1016
|
+
};
|
|
1017
|
+
orphan_files: {
|
|
1018
|
+
enabled: boolean;
|
|
1019
|
+
allow: string[];
|
|
1020
|
+
};
|
|
958
1021
|
migration_order: {
|
|
959
1022
|
enabled: boolean;
|
|
960
1023
|
dirs: string[];
|
|
@@ -1210,6 +1273,23 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
1210
1273
|
enabled?: boolean | undefined;
|
|
1211
1274
|
registry?: string | undefined;
|
|
1212
1275
|
} | undefined;
|
|
1276
|
+
unused_exports?: {
|
|
1277
|
+
enabled?: boolean | undefined;
|
|
1278
|
+
allow?: string[] | undefined;
|
|
1279
|
+
} | undefined;
|
|
1280
|
+
query_patterns?: {
|
|
1281
|
+
enabled?: boolean | undefined;
|
|
1282
|
+
} | undefined;
|
|
1283
|
+
optional_params?: {
|
|
1284
|
+
enabled?: boolean | undefined;
|
|
1285
|
+
} | undefined;
|
|
1286
|
+
duplicate_functions?: {
|
|
1287
|
+
enabled?: boolean | undefined;
|
|
1288
|
+
} | undefined;
|
|
1289
|
+
orphan_files?: {
|
|
1290
|
+
enabled?: boolean | undefined;
|
|
1291
|
+
allow?: string[] | undefined;
|
|
1292
|
+
} | undefined;
|
|
1213
1293
|
migration_order?: {
|
|
1214
1294
|
enabled?: boolean | undefined;
|
|
1215
1295
|
dirs?: string[] | undefined;
|
|
@@ -1826,6 +1906,52 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
1826
1906
|
enabled?: boolean | undefined;
|
|
1827
1907
|
registry?: string | undefined;
|
|
1828
1908
|
}>>>;
|
|
1909
|
+
/** Exports the change adds that no other file names (review/unused-exports.ts). */
|
|
1910
|
+
unused_exports: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1911
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1912
|
+
allow: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
1913
|
+
}, "strip", z.ZodTypeAny, {
|
|
1914
|
+
enabled: boolean;
|
|
1915
|
+
allow: string[];
|
|
1916
|
+
}, {
|
|
1917
|
+
enabled?: boolean | undefined;
|
|
1918
|
+
allow?: string[] | undefined;
|
|
1919
|
+
}>>>;
|
|
1920
|
+
/** Query shapes that cost production: offset paging in a loop, a time window with no upper bound (review/query-patterns.ts). */
|
|
1921
|
+
query_patterns: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1922
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1923
|
+
}, "strip", z.ZodTypeAny, {
|
|
1924
|
+
enabled: boolean;
|
|
1925
|
+
}, {
|
|
1926
|
+
enabled?: boolean | undefined;
|
|
1927
|
+
}>>>;
|
|
1928
|
+
/** A parameter the change adds as optional that only tests omit (review/optional-params.ts). */
|
|
1929
|
+
optional_params: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1930
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1931
|
+
}, "strip", z.ZodTypeAny, {
|
|
1932
|
+
enabled: boolean;
|
|
1933
|
+
}, {
|
|
1934
|
+
enabled?: boolean | undefined;
|
|
1935
|
+
}>>>;
|
|
1936
|
+
/** A changed function whose body duplicates another in the files the change touched (review/duplicate-functions.ts). */
|
|
1937
|
+
duplicate_functions: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1938
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1939
|
+
}, "strip", z.ZodTypeAny, {
|
|
1940
|
+
enabled: boolean;
|
|
1941
|
+
}, {
|
|
1942
|
+
enabled?: boolean | undefined;
|
|
1943
|
+
}>>>;
|
|
1944
|
+
/** Code files the change adds that nothing imports or runs (review/orphan-files.ts). */
|
|
1945
|
+
orphan_files: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1946
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1947
|
+
allow: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
1948
|
+
}, "strip", z.ZodTypeAny, {
|
|
1949
|
+
enabled: boolean;
|
|
1950
|
+
allow: string[];
|
|
1951
|
+
}, {
|
|
1952
|
+
enabled?: boolean | undefined;
|
|
1953
|
+
allow?: string[] | undefined;
|
|
1954
|
+
}>>>;
|
|
1829
1955
|
migration_order: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1830
1956
|
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1831
1957
|
dirs: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
@@ -2263,6 +2389,23 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2263
2389
|
enabled: boolean;
|
|
2264
2390
|
registry?: string | undefined;
|
|
2265
2391
|
};
|
|
2392
|
+
unused_exports: {
|
|
2393
|
+
enabled: boolean;
|
|
2394
|
+
allow: string[];
|
|
2395
|
+
};
|
|
2396
|
+
query_patterns: {
|
|
2397
|
+
enabled: boolean;
|
|
2398
|
+
};
|
|
2399
|
+
optional_params: {
|
|
2400
|
+
enabled: boolean;
|
|
2401
|
+
};
|
|
2402
|
+
duplicate_functions: {
|
|
2403
|
+
enabled: boolean;
|
|
2404
|
+
};
|
|
2405
|
+
orphan_files: {
|
|
2406
|
+
enabled: boolean;
|
|
2407
|
+
allow: string[];
|
|
2408
|
+
};
|
|
2266
2409
|
migration_order: {
|
|
2267
2410
|
enabled: boolean;
|
|
2268
2411
|
dirs: string[];
|
|
@@ -2518,6 +2661,23 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2518
2661
|
enabled?: boolean | undefined;
|
|
2519
2662
|
registry?: string | undefined;
|
|
2520
2663
|
} | undefined;
|
|
2664
|
+
unused_exports?: {
|
|
2665
|
+
enabled?: boolean | undefined;
|
|
2666
|
+
allow?: string[] | undefined;
|
|
2667
|
+
} | undefined;
|
|
2668
|
+
query_patterns?: {
|
|
2669
|
+
enabled?: boolean | undefined;
|
|
2670
|
+
} | undefined;
|
|
2671
|
+
optional_params?: {
|
|
2672
|
+
enabled?: boolean | undefined;
|
|
2673
|
+
} | undefined;
|
|
2674
|
+
duplicate_functions?: {
|
|
2675
|
+
enabled?: boolean | undefined;
|
|
2676
|
+
} | undefined;
|
|
2677
|
+
orphan_files?: {
|
|
2678
|
+
enabled?: boolean | undefined;
|
|
2679
|
+
allow?: string[] | undefined;
|
|
2680
|
+
} | undefined;
|
|
2521
2681
|
migration_order?: {
|
|
2522
2682
|
enabled?: boolean | undefined;
|
|
2523
2683
|
dirs?: string[] | undefined;
|
|
@@ -2590,10 +2750,47 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2590
2750
|
review: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
2591
2751
|
/** Let heuristic gates decide the verdict too; by default only findings that prove a defect do (quiet.ts). */
|
|
2592
2752
|
include_heuristics: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
2753
|
+
/** Also report findings the base already had; by default only what the change introduced is (baseline.ts). */
|
|
2754
|
+
show_preexisting: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
2755
|
+
/** The GitHub account whose token fetches the pull request's previous review (`gh auth token --user`). */
|
|
2756
|
+
github_account: z.ZodOptional<z.ZodString>;
|
|
2757
|
+
/** The fresh reviewer (review/reviewer.ts): the person's own coding agent CLI, headless. `enabled` runs it at every push; `rigour review --reviewer` runs it on request. */
|
|
2758
|
+
reviewer: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
2759
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
2760
|
+
command: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
2761
|
+
model: z.ZodOptional<z.ZodString>;
|
|
2762
|
+
timeout_ms: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
2763
|
+
}, "strip", z.ZodTypeAny, {
|
|
2764
|
+
enabled: boolean;
|
|
2765
|
+
timeout_ms: number;
|
|
2766
|
+
command: string;
|
|
2767
|
+
model?: string | undefined;
|
|
2768
|
+
}, {
|
|
2769
|
+
enabled?: boolean | undefined;
|
|
2770
|
+
timeout_ms?: number | undefined;
|
|
2771
|
+
command?: string | undefined;
|
|
2772
|
+
model?: string | undefined;
|
|
2773
|
+
}>>>;
|
|
2593
2774
|
}, "strip", z.ZodTypeAny, {
|
|
2594
2775
|
include_heuristics: boolean;
|
|
2776
|
+
show_preexisting: boolean;
|
|
2777
|
+
reviewer: {
|
|
2778
|
+
enabled: boolean;
|
|
2779
|
+
timeout_ms: number;
|
|
2780
|
+
command: string;
|
|
2781
|
+
model?: string | undefined;
|
|
2782
|
+
};
|
|
2783
|
+
github_account?: string | undefined;
|
|
2595
2784
|
}, {
|
|
2596
2785
|
include_heuristics?: boolean | undefined;
|
|
2786
|
+
show_preexisting?: boolean | undefined;
|
|
2787
|
+
github_account?: string | undefined;
|
|
2788
|
+
reviewer?: {
|
|
2789
|
+
enabled?: boolean | undefined;
|
|
2790
|
+
timeout_ms?: number | undefined;
|
|
2791
|
+
command?: string | undefined;
|
|
2792
|
+
model?: string | undefined;
|
|
2793
|
+
} | undefined;
|
|
2597
2794
|
}>>>;
|
|
2598
2795
|
planned: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
2599
2796
|
ignore: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
@@ -2828,6 +3025,23 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2828
3025
|
enabled: boolean;
|
|
2829
3026
|
registry?: string | undefined;
|
|
2830
3027
|
};
|
|
3028
|
+
unused_exports: {
|
|
3029
|
+
enabled: boolean;
|
|
3030
|
+
allow: string[];
|
|
3031
|
+
};
|
|
3032
|
+
query_patterns: {
|
|
3033
|
+
enabled: boolean;
|
|
3034
|
+
};
|
|
3035
|
+
optional_params: {
|
|
3036
|
+
enabled: boolean;
|
|
3037
|
+
};
|
|
3038
|
+
duplicate_functions: {
|
|
3039
|
+
enabled: boolean;
|
|
3040
|
+
};
|
|
3041
|
+
orphan_files: {
|
|
3042
|
+
enabled: boolean;
|
|
3043
|
+
allow: string[];
|
|
3044
|
+
};
|
|
2831
3045
|
migration_order: {
|
|
2832
3046
|
enabled: boolean;
|
|
2833
3047
|
dirs: string[];
|
|
@@ -2876,6 +3090,14 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2876
3090
|
};
|
|
2877
3091
|
review: {
|
|
2878
3092
|
include_heuristics: boolean;
|
|
3093
|
+
show_preexisting: boolean;
|
|
3094
|
+
reviewer: {
|
|
3095
|
+
enabled: boolean;
|
|
3096
|
+
timeout_ms: number;
|
|
3097
|
+
command: string;
|
|
3098
|
+
model?: string | undefined;
|
|
3099
|
+
};
|
|
3100
|
+
github_account?: string | undefined;
|
|
2879
3101
|
};
|
|
2880
3102
|
planned: string[];
|
|
2881
3103
|
preset?: string | undefined;
|
|
@@ -3113,6 +3335,23 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
3113
3335
|
enabled?: boolean | undefined;
|
|
3114
3336
|
registry?: string | undefined;
|
|
3115
3337
|
} | undefined;
|
|
3338
|
+
unused_exports?: {
|
|
3339
|
+
enabled?: boolean | undefined;
|
|
3340
|
+
allow?: string[] | undefined;
|
|
3341
|
+
} | undefined;
|
|
3342
|
+
query_patterns?: {
|
|
3343
|
+
enabled?: boolean | undefined;
|
|
3344
|
+
} | undefined;
|
|
3345
|
+
optional_params?: {
|
|
3346
|
+
enabled?: boolean | undefined;
|
|
3347
|
+
} | undefined;
|
|
3348
|
+
duplicate_functions?: {
|
|
3349
|
+
enabled?: boolean | undefined;
|
|
3350
|
+
} | undefined;
|
|
3351
|
+
orphan_files?: {
|
|
3352
|
+
enabled?: boolean | undefined;
|
|
3353
|
+
allow?: string[] | undefined;
|
|
3354
|
+
} | undefined;
|
|
3116
3355
|
migration_order?: {
|
|
3117
3356
|
enabled?: boolean | undefined;
|
|
3118
3357
|
dirs?: string[] | undefined;
|
|
@@ -3161,6 +3400,14 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
3161
3400
|
} | undefined;
|
|
3162
3401
|
review?: {
|
|
3163
3402
|
include_heuristics?: boolean | undefined;
|
|
3403
|
+
show_preexisting?: boolean | undefined;
|
|
3404
|
+
github_account?: string | undefined;
|
|
3405
|
+
reviewer?: {
|
|
3406
|
+
enabled?: boolean | undefined;
|
|
3407
|
+
timeout_ms?: number | undefined;
|
|
3408
|
+
command?: string | undefined;
|
|
3409
|
+
model?: string | undefined;
|
|
3410
|
+
} | undefined;
|
|
3164
3411
|
} | undefined;
|
|
3165
3412
|
planned?: string[] | undefined;
|
|
3166
3413
|
}>;
|
|
@@ -3359,9 +3606,9 @@ export declare const ReportSchema: z.ZodObject<{
|
|
|
3359
3606
|
routed: number;
|
|
3360
3607
|
already_reviewed: number;
|
|
3361
3608
|
} | undefined;
|
|
3609
|
+
model?: string | undefined;
|
|
3362
3610
|
error?: string | undefined;
|
|
3363
3611
|
tier?: "deep" | "max" | "lite" | "legacy" | "cloud" | undefined;
|
|
3364
|
-
model?: string | undefined;
|
|
3365
3612
|
model_fallback?: boolean | undefined;
|
|
3366
3613
|
total_ms?: number | undefined;
|
|
3367
3614
|
files_analyzed?: number | undefined;
|
|
@@ -3387,9 +3634,9 @@ export declare const ReportSchema: z.ZodObject<{
|
|
|
3387
3634
|
routed: number;
|
|
3388
3635
|
already_reviewed: number;
|
|
3389
3636
|
} | undefined;
|
|
3637
|
+
model?: string | undefined;
|
|
3390
3638
|
error?: string | undefined;
|
|
3391
3639
|
tier?: "deep" | "max" | "lite" | "legacy" | "cloud" | undefined;
|
|
3392
|
-
model?: string | undefined;
|
|
3393
3640
|
model_fallback?: boolean | undefined;
|
|
3394
3641
|
total_ms?: number | undefined;
|
|
3395
3642
|
files_analyzed?: number | undefined;
|
|
@@ -3418,9 +3665,9 @@ export declare const ReportSchema: z.ZodObject<{
|
|
|
3418
3665
|
routed: number;
|
|
3419
3666
|
already_reviewed: number;
|
|
3420
3667
|
} | undefined;
|
|
3668
|
+
model?: string | undefined;
|
|
3421
3669
|
error?: string | undefined;
|
|
3422
3670
|
tier?: "deep" | "max" | "lite" | "legacy" | "cloud" | undefined;
|
|
3423
|
-
model?: string | undefined;
|
|
3424
3671
|
model_fallback?: boolean | undefined;
|
|
3425
3672
|
total_ms?: number | undefined;
|
|
3426
3673
|
files_analyzed?: number | undefined;
|
|
@@ -3461,9 +3708,9 @@ export declare const ReportSchema: z.ZodObject<{
|
|
|
3461
3708
|
routed: number;
|
|
3462
3709
|
already_reviewed: number;
|
|
3463
3710
|
} | undefined;
|
|
3711
|
+
model?: string | undefined;
|
|
3464
3712
|
error?: string | undefined;
|
|
3465
3713
|
tier?: "deep" | "max" | "lite" | "legacy" | "cloud" | undefined;
|
|
3466
|
-
model?: string | undefined;
|
|
3467
3714
|
model_fallback?: boolean | undefined;
|
|
3468
3715
|
total_ms?: number | undefined;
|
|
3469
3716
|
files_analyzed?: number | undefined;
|
|
@@ -3506,9 +3753,9 @@ export declare const ReportSchema: z.ZodObject<{
|
|
|
3506
3753
|
routed: number;
|
|
3507
3754
|
already_reviewed: number;
|
|
3508
3755
|
} | undefined;
|
|
3756
|
+
model?: string | undefined;
|
|
3509
3757
|
error?: string | undefined;
|
|
3510
3758
|
tier?: "deep" | "max" | "lite" | "legacy" | "cloud" | undefined;
|
|
3511
|
-
model?: string | undefined;
|
|
3512
3759
|
model_fallback?: boolean | undefined;
|
|
3513
3760
|
total_ms?: number | undefined;
|
|
3514
3761
|
files_analyzed?: number | undefined;
|
|
@@ -3569,9 +3816,9 @@ export declare const ReportSchema: z.ZodObject<{
|
|
|
3569
3816
|
routed: number;
|
|
3570
3817
|
already_reviewed: number;
|
|
3571
3818
|
} | undefined;
|
|
3819
|
+
model?: string | undefined;
|
|
3572
3820
|
error?: string | undefined;
|
|
3573
3821
|
tier?: "deep" | "max" | "lite" | "legacy" | "cloud" | undefined;
|
|
3574
|
-
model?: string | undefined;
|
|
3575
3822
|
model_fallback?: boolean | undefined;
|
|
3576
3823
|
total_ms?: number | undefined;
|
|
3577
3824
|
files_analyzed?: number | undefined;
|
package/dist/types/index.js
CHANGED
|
@@ -281,6 +281,22 @@ export const GatesSchema = z.object({
|
|
|
281
281
|
registry: z.string().optional(),
|
|
282
282
|
}).optional().default({}),
|
|
283
283
|
// A migration added on a branch that sorts before the newest one on the base (advisory, off by default).
|
|
284
|
+
/** Exports the change adds that no other file names (review/unused-exports.ts). */
|
|
285
|
+
unused_exports: z.object({
|
|
286
|
+
enabled: z.boolean().optional().default(true),
|
|
287
|
+
allow: z.array(z.string()).optional().default([]), // export names a tool loads by name
|
|
288
|
+
}).optional().default({}),
|
|
289
|
+
/** Query shapes that cost production: offset paging in a loop, a time window with no upper bound (review/query-patterns.ts). */
|
|
290
|
+
query_patterns: z.object({ enabled: z.boolean().optional().default(true) }).optional().default({}),
|
|
291
|
+
/** A parameter the change adds as optional that only tests omit (review/optional-params.ts). */
|
|
292
|
+
optional_params: z.object({ enabled: z.boolean().optional().default(true) }).optional().default({}),
|
|
293
|
+
/** A changed function whose body duplicates another in the files the change touched (review/duplicate-functions.ts). */
|
|
294
|
+
duplicate_functions: z.object({ enabled: z.boolean().optional().default(true) }).optional().default({}),
|
|
295
|
+
/** Code files the change adds that nothing imports or runs (review/orphan-files.ts). */
|
|
296
|
+
orphan_files: z.object({
|
|
297
|
+
enabled: z.boolean().optional().default(true),
|
|
298
|
+
allow: z.array(z.string()).optional().default([]), // globs for files a tool loads by path
|
|
299
|
+
}).optional().default({}),
|
|
284
300
|
migration_order: z.object({
|
|
285
301
|
enabled: z.boolean().optional().default(false),
|
|
286
302
|
dirs: z.array(z.string()).optional().default(['**/supabase/migrations']),
|
|
@@ -393,6 +409,17 @@ export const ConfigSchema = z.object({
|
|
|
393
409
|
review: z.object({
|
|
394
410
|
/** Let heuristic gates decide the verdict too; by default only findings that prove a defect do (quiet.ts). */
|
|
395
411
|
include_heuristics: z.boolean().optional().default(false),
|
|
412
|
+
/** Also report findings the base already had; by default only what the change introduced is (baseline.ts). */
|
|
413
|
+
show_preexisting: z.boolean().optional().default(false),
|
|
414
|
+
/** The GitHub account whose token fetches the pull request's previous review (`gh auth token --user`). */
|
|
415
|
+
github_account: z.string().optional(),
|
|
416
|
+
/** The fresh reviewer (review/reviewer.ts): the person's own coding agent CLI, headless. `enabled` runs it at every push; `rigour review --reviewer` runs it on request. */
|
|
417
|
+
reviewer: z.object({
|
|
418
|
+
enabled: z.boolean().optional().default(false),
|
|
419
|
+
command: z.string().optional().default('claude'),
|
|
420
|
+
model: z.string().optional(),
|
|
421
|
+
timeout_ms: z.number().optional().default(15 * 60_000),
|
|
422
|
+
}).optional().default({}),
|
|
396
423
|
}).optional().default({}),
|
|
397
424
|
planned: z.array(z.string()).optional().default([]),
|
|
398
425
|
ignore: z.array(z.string()).optional().default([]),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/** A tool the project installed itself, never a download: node_modules/.bin from `dir` up to `root`. */
|
|
4
|
+
export function installedBin(dir, root, name) {
|
|
5
|
+
for (let current = dir; current.startsWith(root); current = path.dirname(current)) {
|
|
6
|
+
for (const candidate of process.platform === 'win32' ? [`${name}.cmd`, name] : [name]) {
|
|
7
|
+
const bin = path.join(current, 'node_modules', '.bin', candidate);
|
|
8
|
+
if (fs.existsSync(bin))
|
|
9
|
+
return bin;
|
|
10
|
+
}
|
|
11
|
+
if (current === root)
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface RigourProfile {
|
|
2
|
+
name: string;
|
|
3
|
+
/** Path prefixes (`~/work/acme`) or origin remotes (`github.com/acme/*`). */
|
|
4
|
+
match: string[];
|
|
5
|
+
/** The home whose `.rigour/` holds this profile's state. */
|
|
6
|
+
home?: string;
|
|
7
|
+
team?: {
|
|
8
|
+
organization: string;
|
|
9
|
+
team: string;
|
|
10
|
+
actor: string;
|
|
11
|
+
/** The team's repositories; lessons from any other repository stay local. */
|
|
12
|
+
repositories?: string[];
|
|
13
|
+
/** A command that prints the team database URL (from a keychain, a vault); never stored in the file. */
|
|
14
|
+
databaseUrlCommand?: string;
|
|
15
|
+
};
|
|
16
|
+
/** The GitHub account whose token fetches pull request reviews. */
|
|
17
|
+
githubAccount?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Where profiles are listed: always the person's real home, never a profile's. */
|
|
20
|
+
export declare function profilesPath(): string;
|
|
21
|
+
export declare function readProfiles(): RigourProfile[];
|
|
22
|
+
export declare function writeProfiles(profiles: RigourProfile[]): void;
|
|
23
|
+
/** The first profile whose match fits `cwd`, by path or by origin remote. */
|
|
24
|
+
export declare function profileFor(cwd: string, profiles?: RigourProfile[]): RigourProfile | undefined;
|
|
25
|
+
/** Apply the profile for `cwd` to this process's environment; returns it, or undefined when none matches. */
|
|
26
|
+
export declare function applyProfile(cwd: string, profiles?: RigourProfile[]): RigourProfile | undefined;
|
|
27
|
+
/** Why this process must not act for `cwd` (it belongs to another profile than the one applied at start), or null. */
|
|
28
|
+
export declare function profileMismatch(cwd: string, profiles?: RigourProfile[]): string | null;
|
|
29
|
+
/** `git@github.com:acme/api.git` and `https://github.com/acme/api` both become `github.com/acme/api`. */
|
|
30
|
+
export declare function hostPath(remote: string): string;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profiles: one machine, many organizations.
|
|
3
|
+
*
|
|
4
|
+
* A person who works for more than one organization needs Rigour's memory, lessons and team
|
|
5
|
+
* database kept apart per organization, chosen by the repository, not by whichever server or shell
|
|
6
|
+
* happened to start. `~/.rigour/profiles.json` (or RIGOUR_PROFILES) lists profiles; the first whose
|
|
7
|
+
* `match` fits the repository (a path prefix, or an origin remote like `github.com/acme/*`) is
|
|
8
|
+
* applied before the rest of Rigour loads: its home becomes RIGOUR_HOME, and team settings come
|
|
9
|
+
* from the profile alone (any inherited from the shell are cleared, so another organization's team
|
|
10
|
+
* can never apply). A long-running server records the profile it started with, and refuses a call
|
|
11
|
+
* for a repository of another profile instead of answering it with the wrong home.
|
|
12
|
+
*
|
|
13
|
+
* Dependency-free on purpose: it runs before the rest of the package is imported.
|
|
14
|
+
*/
|
|
15
|
+
import { spawnSync } from 'child_process';
|
|
16
|
+
import fs from 'fs';
|
|
17
|
+
import os from 'os';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
const TEAM_ENV = ['RIGOUR_ORGANIZATION_ID', 'RIGOUR_TEAM_ID', 'RIGOUR_ACTOR_ID', 'RIGOUR_TEAM_REPOSITORIES', 'RIGOUR_TEAM_DATABASE_URL', 'RIGOUR_TEAM_DATABASE_URL_COMMAND', 'RIGOUR_TEAM_SEMANTIC'];
|
|
20
|
+
/** Where profiles are listed: always the person's real home, never a profile's. */
|
|
21
|
+
export function profilesPath() {
|
|
22
|
+
return process.env.RIGOUR_PROFILES || path.join(os.homedir(), '.rigour', 'profiles.json');
|
|
23
|
+
}
|
|
24
|
+
export function readProfiles() {
|
|
25
|
+
try {
|
|
26
|
+
const parsed = JSON.parse(fs.readFileSync(profilesPath(), 'utf8'));
|
|
27
|
+
return Array.isArray(parsed?.profiles) ? parsed.profiles.filter((p) => p && typeof p.name === 'string' && Array.isArray(p.match)) : [];
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function writeProfiles(profiles) {
|
|
34
|
+
fs.mkdirSync(path.dirname(profilesPath()), { recursive: true, mode: 0o700 });
|
|
35
|
+
fs.writeFileSync(profilesPath(), JSON.stringify({ profiles }, null, 2) + '\n', { mode: 0o600 });
|
|
36
|
+
}
|
|
37
|
+
/** The first profile whose match fits `cwd`, by path or by origin remote. */
|
|
38
|
+
export function profileFor(cwd, profiles = readProfiles()) {
|
|
39
|
+
if (profiles.length === 0)
|
|
40
|
+
return undefined;
|
|
41
|
+
const where = real(cwd);
|
|
42
|
+
const remote = originRemote(cwd);
|
|
43
|
+
return profiles.find(profile => profile.match.some(entry => isRemotePattern(entry)
|
|
44
|
+
? !!remote && remoteMatches(remote, entry)
|
|
45
|
+
: isInside(where, real(expandHome(entry)))));
|
|
46
|
+
}
|
|
47
|
+
/** Apply the profile for `cwd` to this process's environment; returns it, or undefined when none matches. */
|
|
48
|
+
export function applyProfile(cwd, profiles) {
|
|
49
|
+
const profile = profileFor(cwd, profiles);
|
|
50
|
+
if (!profile)
|
|
51
|
+
return undefined;
|
|
52
|
+
process.env.RIGOUR_PROFILE = profile.name;
|
|
53
|
+
if (profile.home)
|
|
54
|
+
process.env.RIGOUR_HOME = expandHome(profile.home);
|
|
55
|
+
for (const name of TEAM_ENV)
|
|
56
|
+
delete process.env[name];
|
|
57
|
+
if (profile.team) {
|
|
58
|
+
process.env.RIGOUR_ORGANIZATION_ID = profile.team.organization;
|
|
59
|
+
process.env.RIGOUR_TEAM_ID = profile.team.team;
|
|
60
|
+
process.env.RIGOUR_ACTOR_ID = profile.team.actor;
|
|
61
|
+
if (profile.team.repositories?.length)
|
|
62
|
+
process.env.RIGOUR_TEAM_REPOSITORIES = profile.team.repositories.join(',');
|
|
63
|
+
if (profile.team.databaseUrlCommand)
|
|
64
|
+
process.env.RIGOUR_TEAM_DATABASE_URL_COMMAND = profile.team.databaseUrlCommand;
|
|
65
|
+
}
|
|
66
|
+
if (profile.githubAccount)
|
|
67
|
+
process.env.RIGOUR_GITHUB_ACCOUNT = profile.githubAccount;
|
|
68
|
+
return profile;
|
|
69
|
+
}
|
|
70
|
+
/** Why this process must not act for `cwd` (it belongs to another profile than the one applied at start), or null. */
|
|
71
|
+
export function profileMismatch(cwd, profiles) {
|
|
72
|
+
const belongs = profileFor(cwd, profiles)?.name;
|
|
73
|
+
const running = process.env.RIGOUR_PROFILE;
|
|
74
|
+
if (belongs === running)
|
|
75
|
+
return null;
|
|
76
|
+
return `This repository belongs to the Rigour profile "${belongs ?? '(none)'}", but this server started as "${running ?? '(none)'}". `
|
|
77
|
+
+ 'Refusing so one profile\'s memory and team never reach another: start Rigour from this repository (or with RIGOUR_CWD set to it).';
|
|
78
|
+
}
|
|
79
|
+
function isRemotePattern(entry) {
|
|
80
|
+
return /^[a-z0-9.-]+\.[a-z]{2,}\//i.test(entry.replace(/^[a-z]+:\/\//i, ''));
|
|
81
|
+
}
|
|
82
|
+
function remoteMatches(remote, pattern) {
|
|
83
|
+
const want = hostPath(pattern);
|
|
84
|
+
return want.endsWith('/*') ? remote.startsWith(want.slice(0, -1)) : remote === want;
|
|
85
|
+
}
|
|
86
|
+
/** `git@github.com:acme/api.git` and `https://github.com/acme/api` both become `github.com/acme/api`. */
|
|
87
|
+
export function hostPath(remote) {
|
|
88
|
+
return remote.trim().toLowerCase()
|
|
89
|
+
.replace(/^[a-z][a-z0-9+.-]*:\/\//, '')
|
|
90
|
+
.replace(/^[^@/]+@/, '')
|
|
91
|
+
.replace(/^([^/:]+):(?!\d)/, '$1/')
|
|
92
|
+
.replace(/\/+$/, '')
|
|
93
|
+
.replace(/\.git$/, '');
|
|
94
|
+
}
|
|
95
|
+
function originRemote(cwd) {
|
|
96
|
+
const result = spawnSync('git', ['config', '--get', 'remote.origin.url'], { cwd, encoding: 'utf8' });
|
|
97
|
+
return result.status === 0 && result.stdout.trim() ? hostPath(result.stdout) : undefined;
|
|
98
|
+
}
|
|
99
|
+
function expandHome(entry) {
|
|
100
|
+
return entry.replace(/^~(?=$|[\\/])/, os.homedir());
|
|
101
|
+
}
|
|
102
|
+
/** The real path; for a path that does not exist yet, its nearest existing parent's real path plus the rest. */
|
|
103
|
+
function real(dir) {
|
|
104
|
+
const absolute = path.resolve(dir);
|
|
105
|
+
try {
|
|
106
|
+
return fs.realpathSync.native(absolute);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
const parent = path.dirname(absolute);
|
|
110
|
+
return parent === absolute ? absolute : path.join(real(parent), path.basename(absolute));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function isInside(child, parent) {
|
|
114
|
+
const relative = path.relative(parent, child);
|
|
115
|
+
return relative === '' || (!!relative && !relative.startsWith('..') && !path.isAbsolute(relative));
|
|
116
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
6
|
+
import { applyProfile, hostPath, profileFor, profileMismatch } from './profile.js';
|
|
7
|
+
let root;
|
|
8
|
+
const saved = { ...process.env };
|
|
9
|
+
const repo = (rel, remote) => {
|
|
10
|
+
const dir = path.join(root, rel);
|
|
11
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
12
|
+
execFileSync('git', ['init', '-q'], { cwd: dir });
|
|
13
|
+
if (remote)
|
|
14
|
+
execFileSync('git', ['remote', 'add', 'origin', remote], { cwd: dir });
|
|
15
|
+
return dir;
|
|
16
|
+
};
|
|
17
|
+
beforeEach(() => { root = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'profiles-'))); });
|
|
18
|
+
afterEach(() => { process.env = { ...saved }; fs.rmSync(root, { recursive: true, force: true }); });
|
|
19
|
+
describe('profiles', () => {
|
|
20
|
+
it('matches a repository by path prefix or by origin remote, first match winning', () => {
|
|
21
|
+
const byPath = repo('work/acme/api');
|
|
22
|
+
const byRemote = repo('elsewhere/web', 'git@github.com:Acme/web.git');
|
|
23
|
+
const other = repo('personal/tool', 'https://github.com/me/tool');
|
|
24
|
+
const profiles = [
|
|
25
|
+
{ name: 'acme-path', match: [path.join(root, 'work/acme')] },
|
|
26
|
+
{ name: 'acme-remote', match: ['github.com/acme/*'] },
|
|
27
|
+
];
|
|
28
|
+
expect(profileFor(path.join(byPath, 'src'), profiles)?.name).toBe('acme-path');
|
|
29
|
+
expect(profileFor(byRemote, profiles)?.name).toBe('acme-remote');
|
|
30
|
+
expect(profileFor(other, profiles)).toBeUndefined();
|
|
31
|
+
expect(profileFor(path.join(root, 'work/acme-evil'), profiles)).toBeUndefined();
|
|
32
|
+
expect(hostPath('https://GitHub.com/Acme/web.git/')).toBe('github.com/acme/web');
|
|
33
|
+
});
|
|
34
|
+
it("applies the profile's home and team, clearing team settings inherited from the shell", () => {
|
|
35
|
+
const dir = repo('work/acme/api');
|
|
36
|
+
process.env.RIGOUR_TEAM_DATABASE_URL = 'postgres://other-org';
|
|
37
|
+
process.env.RIGOUR_ORGANIZATION_ID = 'other-org';
|
|
38
|
+
applyProfile(dir, [{ name: 'acme', match: [path.join(root, 'work/acme')], home: path.join(root, 'acme-home'), githubAccount: 'acme-dev' }]);
|
|
39
|
+
expect(process.env.RIGOUR_HOME).toBe(path.join(root, 'acme-home'));
|
|
40
|
+
expect(process.env.RIGOUR_PROFILE).toBe('acme');
|
|
41
|
+
expect(process.env.RIGOUR_GITHUB_ACCOUNT).toBe('acme-dev');
|
|
42
|
+
expect(process.env.RIGOUR_TEAM_DATABASE_URL).toBeUndefined();
|
|
43
|
+
expect(process.env.RIGOUR_ORGANIZATION_ID).toBeUndefined();
|
|
44
|
+
applyProfile(dir, [{ name: 'acme', match: [dir], team: { organization: 'acme', team: 'web', actor: 'dev', repositories: ['github.com/acme/*'], databaseUrlCommand: 'echo url' } }]);
|
|
45
|
+
expect([process.env.RIGOUR_ORGANIZATION_ID, process.env.RIGOUR_TEAM_REPOSITORIES, process.env.RIGOUR_TEAM_DATABASE_URL_COMMAND]).toEqual(['acme', 'github.com/acme/*', 'echo url']);
|
|
46
|
+
});
|
|
47
|
+
it('refuses to act for a repository of another profile than the one the process started with', () => {
|
|
48
|
+
const acme = repo('work/acme/api');
|
|
49
|
+
const mine = repo('personal/tool');
|
|
50
|
+
const profiles = [{ name: 'acme', match: [path.join(root, 'work/acme')] }];
|
|
51
|
+
delete process.env.RIGOUR_PROFILE;
|
|
52
|
+
expect(profileMismatch(mine, profiles)).toBeNull();
|
|
53
|
+
expect(profileMismatch(acme, profiles)).toContain('belongs to the Rigour profile "acme"');
|
|
54
|
+
process.env.RIGOUR_PROFILE = 'acme';
|
|
55
|
+
expect(profileMismatch(acme, profiles)).toBeNull();
|
|
56
|
+
expect(profileMismatch(mine, profiles)).toContain('started as "acme"');
|
|
57
|
+
});
|
|
58
|
+
});
|
package/dist/utils/scanner.js
CHANGED
|
@@ -34,11 +34,13 @@ export class FileScanner {
|
|
|
34
34
|
const userIgnore = options.ignore || [];
|
|
35
35
|
const ignore = [...new Set([...this.DEFAULT_IGNORE, ...userIgnore])].map(toGlobSeparators);
|
|
36
36
|
const normalizedCwd = options.cwd.replace(/\\/g, '/');
|
|
37
|
-
|
|
37
|
+
// Sorted: the walk's order varies run to run, and a check that names "the first file" must name the same one.
|
|
38
|
+
const files = await globby(directoriesAsGlobs(normalizedCwd, patterns), {
|
|
38
39
|
cwd: normalizedCwd,
|
|
39
40
|
ignore: withDirectoryForms(ignore),
|
|
40
41
|
expandDirectories: false,
|
|
41
42
|
});
|
|
43
|
+
return files.sort();
|
|
42
44
|
}
|
|
43
45
|
/**
|
|
44
46
|
* Read file contents. When a FileSystemCache is provided, uses it for
|