@shivaedev/quality 0.31.0 → 0.32.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +19 -4
  3. package/dist/baseline/installDriver.d.ts +5 -0
  4. package/dist/baseline/installDriver.d.ts.map +1 -0
  5. package/dist/baseline/installDriver.js +11 -0
  6. package/dist/baseline/installDriver.js.map +1 -0
  7. package/dist/baseline/merge.d.ts +4 -0
  8. package/dist/baseline/merge.d.ts.map +1 -0
  9. package/dist/baseline/merge.js +28 -0
  10. package/dist/baseline/merge.js.map +1 -0
  11. package/dist/baseline/rewrite.d.ts.map +1 -1
  12. package/dist/baseline/rewrite.js +0 -1
  13. package/dist/baseline/rewrite.js.map +1 -1
  14. package/dist/baseline/shards.d.ts +13 -0
  15. package/dist/baseline/shards.d.ts.map +1 -0
  16. package/dist/baseline/shards.js +48 -0
  17. package/dist/baseline/shards.js.map +1 -0
  18. package/dist/cli/args.d.ts +8 -1
  19. package/dist/cli/args.d.ts.map +1 -1
  20. package/dist/cli/args.js +9 -0
  21. package/dist/cli/args.js.map +1 -1
  22. package/dist/cli/baseline.d.ts.map +1 -1
  23. package/dist/cli/baseline.js +6 -7
  24. package/dist/cli/baseline.js.map +1 -1
  25. package/dist/cli/messages.d.ts +1 -1
  26. package/dist/cli/messages.d.ts.map +1 -1
  27. package/dist/cli/messages.js +6 -2
  28. package/dist/cli/messages.js.map +1 -1
  29. package/dist/cli/migrate.d.ts.map +1 -1
  30. package/dist/cli/migrate.js +10 -6
  31. package/dist/cli/migrate.js.map +1 -1
  32. package/dist/cli/program.d.ts.map +1 -1
  33. package/dist/cli/program.js +6 -0
  34. package/dist/cli/program.js.map +1 -1
  35. package/dist/config/load.js +1 -1
  36. package/dist/engine/baselineFile.d.ts +2 -1
  37. package/dist/engine/baselineFile.d.ts.map +1 -1
  38. package/dist/engine/baselineFile.js +23 -6
  39. package/dist/engine/baselineFile.js.map +1 -1
  40. package/dist/imports/fences/reach.d.ts +5 -4
  41. package/dist/imports/fences/reach.d.ts.map +1 -1
  42. package/dist/imports/fences/reach.js +3 -2
  43. package/dist/imports/fences/reach.js.map +1 -1
  44. package/dist/rules/stories/unitTests.js +2 -2
  45. package/dist/rules/stories/unitTests.js.map +1 -1
  46. package/dist/rules/test-names/usesDom.d.ts.map +1 -1
  47. package/dist/rules/test-names/usesDom.js +11 -4
  48. package/dist/rules/test-names/usesDom.js.map +1 -1
  49. package/docs/debt-and-hooks.md +6 -3
  50. package/package.json +1 -1
  51. package/src/baseline/installDriver.ts +12 -0
  52. package/src/baseline/merge.ts +34 -0
  53. package/src/baseline/rewrite.ts +0 -1
  54. package/src/baseline/shards.ts +60 -0
  55. package/src/cli/args.ts +11 -0
  56. package/src/cli/baseline.ts +6 -10
  57. package/src/cli/messages.ts +6 -2
  58. package/src/cli/migrate.ts +10 -6
  59. package/src/cli/program.ts +6 -0
  60. package/src/config/load.ts +1 -1
  61. package/src/engine/baselineFile.ts +24 -7
  62. package/src/imports/fences/reach.ts +17 -11
  63. package/src/rules/stories/unitTests.ts +3 -3
  64. package/src/rules/test-names/usesDom.ts +11 -4
@@ -1 +1 @@
1
- {"version":3,"file":"program.js","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"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"}
@@ -36,7 +36,7 @@ function biomeDeclarations(config) {
36
36
  function resolved(root, file, config, rules) {
37
37
  return {
38
38
  ...rules,
39
- baseline: config.baseline ?? "quality/baseline.jsonl",
39
+ baseline: config.baseline ?? "quality-baseline.jsonl",
40
40
  biomeDeclarations: biomeDeclarations(config),
41
41
  exceptions: config.exceptions ?? [],
42
42
  exclude: [],
@@ -1,10 +1,11 @@
1
1
  import { Effect, type FileSystem } from "effect";
2
2
  import { type BaselineEntry } from "#baseline/format.ts";
3
+ import { type Shard } from "#baseline/shards.ts";
3
4
  import type { ResolvedConfig } from "#config/load.ts";
4
5
  import { SetupFailure } from "#failure.ts";
5
6
  export interface BaselineFile {
6
7
  readonly entries: readonly BaselineEntry[];
7
- readonly raw: string | undefined;
8
+ readonly files: ReadonlyMap<string, Shard>;
8
9
  }
9
10
  export declare function readInput(root: string, path: string): Effect.Effect<string | undefined, SetupFailure, FileSystem.FileSystem>;
10
11
  export declare const readBaseline: (config: ResolvedConfig) => Effect.Effect<BaselineFile, SetupFailure, FileSystem.FileSystem>;
@@ -1 +1 @@
1
- {"version":3,"file":"baselineFile.d.ts","sourceRoot":"","sources":["../../src/engine/baselineFile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,qBAAqB,CAAC;AAEzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,CAE5H;AAED,eAAO,MAAM,YAAY,8FAUvB,CAAC"}
1
+ {"version":3,"file":"baselineFile.d.ts","sourceRoot":"","sources":["../../src/engine/baselineFile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,qBAAqB,CAAC;AAEzE,OAAO,EAAE,KAAK,KAAK,EAAuB,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC3C;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,CAE5H;AAED,eAAO,MAAM,YAAY,8FA0BvB,CAAC"}
@@ -2,6 +2,7 @@ import { join } from "node:path";
2
2
  import { Effect } from "effect";
3
3
  import { decodeBaseline } from "#baseline/format.ts";
4
4
  import { LEGACY_BASELINE } from "#baseline/legacy.ts";
5
+ import { shardOf, shardPaths } from "#baseline/shards.ts";
5
6
  import { validOrFail } from "#decoded.ts";
6
7
  import { SetupFailure } from "#failure.ts";
7
8
  import { readOptionalText } from "#inventory/filesystem.ts";
@@ -9,12 +10,28 @@ export function readInput(root, path) {
9
10
  return Effect.mapError(readOptionalText(join(root, path)), (failure) => new SetupFailure({ message: failure.message }));
10
11
  }
11
12
  export const readBaseline = Effect.fn("Engine.readBaseline")(function* (config) {
12
- const raw = yield* readInput(config.root, config.baseline);
13
- if (raw === undefined && config.baseline !== LEGACY_BASELINE && (yield* readInput(config.root, LEGACY_BASELINE)) !== undefined) {
14
- return yield* new SetupFailure({
15
- message: `${LEGACY_BASELINE} holds a baseline in the earlier JSON format. Run \`quality baseline migrate\` to move it to ${config.baseline}.`,
16
- });
13
+ const files = new Map();
14
+ for (const path of yield* shardPaths(config).pipe(Effect.mapError((error) => new SetupFailure({ message: error.message })))) {
15
+ const raw = yield* readInput(config.root, path);
16
+ if (raw === undefined) {
17
+ continue;
18
+ }
19
+ const entries = yield* validOrFail(path, yield* Effect.promise(() => decodeBaseline(raw)));
20
+ for (const entry of entries) {
21
+ const expected = shardOf(entry.file, config.baseline);
22
+ if (expected !== path) {
23
+ return yield* new SetupFailure({ message: `${entry.file} belongs in ${expected}, not ${path}.` });
24
+ }
25
+ }
26
+ files.set(path, { entries, raw });
17
27
  }
18
- return { entries: yield* validOrFail(config.baseline, yield* Effect.promise(() => decodeBaseline(raw))), raw };
28
+ for (const source of ["quality/baseline.jsonl", LEGACY_BASELINE]) {
29
+ if (source !== config.baseline && (yield* readInput(config.root, source)) !== undefined) {
30
+ return yield* new SetupFailure({
31
+ message: `${source} holds an earlier baseline. Run \`quality baseline migrate --from ${source}\` to move it to ${config.baseline} and package shards.`,
32
+ });
33
+ }
34
+ }
35
+ return { entries: [...files.values()].flatMap((file) => file.entries), files };
19
36
  });
20
37
  //# sourceMappingURL=baselineFile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"baselineFile.js","sourceRoot":"","sources":["../../src/engine/baselineFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAmB,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAsB,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAO5D,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IACnD,OAAO,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AACzH,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,EACrE,MAAsB;IAEtB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3D,IAAI,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,KAAK,eAAe,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAChI,OAAO,KAAK,CAAC,CAAC,IAAI,YAAY,CAAC;YAC9B,OAAO,EAAE,GAAG,eAAe,gGAAgG,MAAM,CAAC,QAAQ,GAAG;SAC7I,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;AAChH,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"baselineFile.js","sourceRoot":"","sources":["../../src/engine/baselineFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAmB,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAsB,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAc,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAO5D,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IACnD,OAAO,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AACzH,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,EACrE,MAAsB;IAEtB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7H,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACvB,SAAS;QACV,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3F,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YACtD,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACvB,OAAO,KAAK,CAAC,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,eAAe,QAAQ,SAAS,IAAI,GAAG,EAAE,CAAC,CAAC;YACnG,CAAC;QACF,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,CAAC,wBAAwB,EAAE,eAAe,CAAC,EAAE,CAAC;QAClE,IAAI,MAAM,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YACzF,OAAO,KAAK,CAAC,CAAC,IAAI,YAAY,CAAC;gBAC9B,OAAO,EAAE,GAAG,MAAM,qEAAqE,MAAM,oBAAoB,MAAM,CAAC,QAAQ,sBAAsB;aACtJ,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;AAChF,CAAC,CAAC,CAAC"}
@@ -1,8 +1,9 @@
1
1
  import type { ImportEdge } from "#imports/graph.ts";
2
2
  import type { Endpoint } from "#imports/resolve.ts";
3
3
  import type { Matcher } from "./match.ts";
4
- export interface Reached {
4
+ export interface Reached<TMatch = unknown> {
5
5
  readonly line: number;
6
+ readonly match: TMatch;
6
7
  readonly path: readonly string[];
7
8
  readonly target: Endpoint;
8
9
  }
@@ -12,10 +13,10 @@ export interface Trail {
12
13
  }
13
14
  export declare function labelOf(endpoint: Endpoint): string;
14
15
  export declare function outgoing(edges: readonly ImportEdge[]): ReadonlyMap<string, readonly ImportEdge[]>;
15
- export interface Walked {
16
- readonly reached: readonly Reached[];
16
+ export interface Walked<TMatch = unknown> {
17
+ readonly reached: readonly Reached<TMatch>[];
17
18
  readonly visited: ReadonlyMap<string, Trail>;
18
19
  }
19
- export declare function walkFrom(start: string, edgesFrom: ReadonlyMap<string, readonly ImportEdge[]>, forbidden: Matcher): Walked;
20
+ export declare function walkFrom<TMatch>(start: string, edgesFrom: ReadonlyMap<string, readonly ImportEdge[]>, forbidden: (endpoint: Endpoint) => TMatch | undefined): Walked<TMatch>;
20
21
  export declare function reachedFrom(start: string, edgesFrom: ReadonlyMap<string, readonly ImportEdge[]>, forbidden: Matcher): readonly Reached[];
21
22
  //# sourceMappingURL=reach.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../../../src/imports/fences/reach.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC1B;AAED,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAMlD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,CAQjG;AAoBD,MAAM,WAAW,MAAM;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC7C;AAGD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CASzH;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,GAAG,SAAS,OAAO,EAAE,CAExI"}
1
+ {"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../../../src/imports/fences/reach.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,OAAO,CAAC,MAAM,GAAG,OAAO;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC1B;AAED,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAMlD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,CAQjG;AAqBD,MAAM,WAAW,MAAM,CAAC,MAAM,GAAG,OAAO;IACvC,QAAQ,CAAC,OAAO,EAAE,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC7C;AAGD,wBAAgB,QAAQ,CAAC,MAAM,EAC9B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,EACrD,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,GAAG,SAAS,GACnD,MAAM,CAAC,MAAM,CAAC,CAShB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,GAAG,SAAS,OAAO,EAAE,CAExI"}
@@ -17,8 +17,9 @@ export function outgoing(edges) {
17
17
  function follow(walk, before, edge) {
18
18
  const label = labelOf(edge.to);
19
19
  const trail = { line: before.path.length === 1 ? edge.line : before.line, path: [...before.path, label] };
20
- if (walk.forbidden(edge.to)) {
21
- walk.reached.set(label, walk.reached.get(label) ?? { ...trail, target: edge.to });
20
+ const match = walk.forbidden(edge.to);
21
+ if (match) {
22
+ walk.reached.set(label, walk.reached.get(label) ?? { ...trail, match, target: edge.to });
22
23
  }
23
24
  else if (edge.to.kind === "file" && !walk.trails.has(edge.to.path)) {
24
25
  walk.trails.set(edge.to.path, trail);
@@ -1 +1 @@
1
- {"version":3,"file":"reach.js","sourceRoot":"","sources":["../../../src/imports/fences/reach.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reach.js","sourceRoot":"","sources":["../../../src/imports/fences/reach.ts"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@ function reachFinding(file, reached) {
26
26
  return {
27
27
  file,
28
28
  line: reached.line,
29
- message: `Is a unit test but reaches ${engineOf(reached.target) ?? "an engine"} (${labelOf(reached.target)}) through ${reached.path.join(" -> ")}. A unit test reaches no engine, directly or through what it imports. ${KIT} ${repair(reached.path)}`,
29
+ message: `Is a unit test but reaches ${reached.match} (${labelOf(reached.target)}) through ${reached.path.join(" -> ")}. A unit test reaches no engine, directly or through what it imports. ${KIT} ${repair(reached.path)}`,
30
30
  };
31
31
  }
32
32
  function standMessage(stand) {
@@ -65,7 +65,7 @@ export function unitTests(graph, sources) {
65
65
  const edgesFrom = runtimeEdges(graph);
66
66
  const byPath = new Map(sources.map((source) => [source.path, source]));
67
67
  return (file) => {
68
- const walked = walkFrom(file, edgesFrom, (endpoint) => engineOf(endpoint) !== undefined);
68
+ const walked = walkFrom(file, edgesFrom, engineOf);
69
69
  const checked = [...walked.visited].filter(([module]) => module === file || isTestSupport(module));
70
70
  return [
71
71
  ...[...walked.reached].sort((a, b) => a.line - b.line).map((reached) => reachFinding(file, reached)),
@@ -1 +1 @@
1
- {"version":3,"file":"unitTests.js","sourceRoot":"","sources":["../../../src/rules/stories/unitTests.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unitTests.js","sourceRoot":"","sources":["../../../src/rules/stories/unitTests.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"usesDom.d.ts","sourceRoot":"","sources":["../../../src/rules/test-names/usesDom.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAiB3C,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAGjD"}
1
+ {"version":3,"file":"usesDom.d.ts","sourceRoot":"","sources":["../../../src/rules/test-names/usesDom.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAiB3C,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAUjD"}
@@ -2,17 +2,24 @@ import ts from "typescript";
2
2
  import { parse } from "#rules/syntax.ts";
3
3
  const DOM_GLOBALS = new Set(["document", "window"]);
4
4
  const TESTING_LIBRARY = "@testing-library/";
5
- function touchesDom(node) {
5
+ function touchesDom(node, checker) {
6
6
  if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
7
7
  return node.moduleSpecifier.text.startsWith(TESTING_LIBRARY);
8
8
  }
9
9
  if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && DOM_GLOBALS.has(node.expression.text)) {
10
- return true;
10
+ return (checker.getSymbolAtLocation(node.expression)?.declarations ?? []).length === 0;
11
11
  }
12
- return ts.forEachChild(node, touchesDom) ?? false;
12
+ return ts.forEachChild(node, (child) => touchesDom(child, checker)) ?? false;
13
13
  }
14
14
  export function usesDom(file) {
15
15
  const source = parse(file);
16
- return source === undefined ? false : touchesDom(source);
16
+ if (source === undefined) {
17
+ return false;
18
+ }
19
+ const options = { allowJs: true, noLib: true, noResolve: true };
20
+ const host = ts.createCompilerHost(options);
21
+ host.getSourceFile = (path) => (path === source.fileName ? source : undefined);
22
+ const checker = ts.createProgram([source.fileName], options, host).getTypeChecker();
23
+ return touchesDom(source, checker);
17
24
  }
18
25
  //# sourceMappingURL=usesDom.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usesDom.js","sourceRoot":"","sources":["../../../src/rules/test-names/usesDom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEzE,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAE5C,SAAS,UAAU,CAAC,IAAa;IAChC,IAAI,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9E,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtH,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,KAAK,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAgB;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"usesDom.js","sourceRoot":"","sources":["../../../src/rules/test-names/usesDom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEzE,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAE5C,SAAS,UAAU,CAAC,IAAa,EAAE,OAAuB;IACzD,IAAI,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9E,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtH,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAgB;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAuB,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACpF,MAAM,IAAI,GAAG,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;IACpF,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC"}
@@ -9,23 +9,26 @@ The [README](../README.md) introduces the gate. This page explains how the basel
9
9
  {"path":"src/server/db.ts","rule":"structure/max-lines","count":262}
10
10
  ```
11
11
 
12
- The baseline is a JSON Lines file with one entry per line: the violations of one rule in one file. `count` is how many violations the file may have. For a rule that counts occurrences, such as `comments/no-jsdoc`, that is the number of occurrences. For a rule with a limit, it is the amount over the limit: the entry above lets `src/server/db.ts` have 412 lines under a limit of 150. A new baseline is sorted by path and then rule. Later edits preserve unrelated lines, including their formatting and order, so the diff shows the entries that changed.
12
+ The baseline is sharded: `packages/<package>/quality-baseline.jsonl` holds paths inside that package, and the root `quality-baseline.jsonl` holds all other paths. Packages without entries have no file. Each shard is JSON Lines with one entry per line: the violations of one rule in one file. `count` is how many violations the file may have. For a rule that counts occurrences, such as `comments/no-jsdoc`, that is the number of occurrences. For a rule with a limit, it is the amount over the limit: the entry above lets `src/server/db.ts` have 412 lines under a limit of 150. A new baseline is sorted by path and then rule. Later edits preserve unrelated lines, including their formatting and order, so the diff shows the entries that changed.
13
13
 
14
14
  `quality lint` fails when a baselined file has more violations than its `count`; the report then lists all of that file's violations for the rule. A file at or below its entry passes. An entry that allows more than is left, including a file with no violations left, is listed as a note and does not fail, so fixing debt never breaks the build; `tighten` and `prune` lower it. An entry for an unknown rule fails until it is pruned.
15
15
 
16
16
  - `quality baseline write` records every error-level violation when there is no baseline yet. Once a baseline exists it refuses, unless `--rule <id>` names the rules to record: it then replaces the entries of those rules with what the files have now, and leaves every other entry as it is.
17
17
  - `quality baseline tighten` lowers and removes the entries of files changed since `HEAD`, and with `--staged`, of the files staged for the next commit. It carries the entry of a file that git sees as moved to the new path. Every other line stays byte for byte.
18
18
  - `quality baseline prune` does the same for every entry. It carries the entries of files moved since the merge base (see `--against` under [Command line](../README.md#command-line)), and prunes without following moves outside a git work tree.
19
- - `quality baseline migrate` moves a baseline from the earlier JSON format, `quality/baseline.json` or the file `--from` names, to the configured file, and removes the old one. An old entry that stored a size, such as a line count, becomes that size less the rule's current limit; an entry whose file is now within the limit is dropped.
19
+ - `quality baseline migrate` moves a baseline from the earlier JSON format, `quality/baseline.json` or the file `--from` names, to the root and package shards, and removes the old one. `--from quality/baseline.jsonl` splits a single JSON Lines baseline without changing its counts. An old entry that stored a size, such as a line count, becomes that size less the rule's current limit; an entry whose file is now within the limit is dropped.
20
20
 
21
21
  Neither `tighten` nor `prune` ever adds or raises an entry. They lower an entry to what its file has now, and remove it when that is 0. A moved file's entry keeps the lower of its old count and what the file has now. A move is seen when both of its sides are tracked, as after `git mv`; git's rename detection decides what counts as a move.
22
22
 
23
+ Git merges shards through the driver described in the [README](../README.md#baseline-merges). `quality baseline install-driver` configures the current checkout; deletions win and retained counts take the minimum.
24
+
23
25
  ### Pre-commit
24
26
 
25
27
  Lowering entries in the commit that fixes them keeps the baseline current. Run these commands explicitly before committing:
26
28
 
27
29
  ```sh
28
- quality baseline tighten --staged && git add quality/baseline.jsonl
30
+ quality baseline tighten --staged
31
+ git add -- '**/quality-baseline.jsonl' quality-baseline.jsonl
29
32
  quality lint
30
33
  ```
31
34
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/quality",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
4
  "description": "Repository quality gate with typed rules, a baseline of existing debt and a registry of reasoned exceptions",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/quality#readme",
6
6
  "bugs": {
@@ -0,0 +1,12 @@
1
+ import { Console, Effect } from "effect";
2
+ import type { SetupFailure } from "#failure.ts";
3
+ import { type Git, gitOrFail } from "#git/command.ts";
4
+ import { hookCommand, type Launch, shellWords } from "#hooks/command.ts";
5
+
6
+ export const installDriver = Effect.fn("Baseline.installDriver")(function* (cwd: string, launch: Launch): Effect.fn.Return<void, SetupFailure, Git> {
7
+ const root = (yield* gitOrFail(cwd, ["rev-parse", "--show-toplevel"])).trim();
8
+ const command = hookCommand(root, launch, undefined);
9
+ const driver = `${shellWords([...command.runner, command.launcher, "baseline", "merge"])} "%O" "%A" "%B"`;
10
+ yield* gitOrFail(root, ["config", "--local", "merge.quality-baseline.driver", driver]);
11
+ yield* Console.log("quality: configured the repository-local quality-baseline merge driver.");
12
+ });
@@ -0,0 +1,34 @@
1
+ import { Effect, FileSystem } from "effect";
2
+ import { type BaselineEntry, decodeBaseline, encodeBaseline } from "#baseline/format.ts";
3
+ import { validOrFail } from "#decoded.ts";
4
+ import { keyOf } from "#engine/violation.ts";
5
+ import { SetupFailure } from "#failure.ts";
6
+
7
+ function mergeEntries(base: readonly BaselineEntry[], ours: readonly BaselineEntry[], theirs: readonly BaselineEntry[]): readonly BaselineEntry[] {
8
+ const original = new Set(base.map((entry) => keyOf(entry.rule, entry.file)));
9
+ const left = new Map(ours.map((entry) => [keyOf(entry.rule, entry.file), entry]));
10
+ const right = new Map(theirs.map((entry) => [keyOf(entry.rule, entry.file), entry]));
11
+ return [...new Set([...left.keys(), ...right.keys()])].flatMap((key) => {
12
+ const a = left.get(key);
13
+ const b = right.get(key);
14
+ if (original.has(key) && (a === undefined || b === undefined)) {
15
+ return [];
16
+ }
17
+ const entry = a ?? b;
18
+ return entry === undefined ? [] : [{ ...entry, count: Math.min(a?.count ?? entry.count, b?.count ?? entry.count) }];
19
+ });
20
+ }
21
+
22
+ export const mergeBaseline = Effect.fn("Baseline.mergeBaseline")(
23
+ function* (base: string, ours: string, theirs: string) {
24
+ const fs = yield* FileSystem.FileSystem;
25
+ const entries = yield* Effect.forEach([base, ours, theirs], (path) =>
26
+ Effect.gen(function* () {
27
+ const raw = yield* fs.readFileString(path);
28
+ return yield* validOrFail(path, yield* Effect.promise(() => decodeBaseline(raw)));
29
+ }),
30
+ );
31
+ yield* fs.writeFileString(ours, encodeBaseline(mergeEntries(entries[0] ?? [], entries[1] ?? [], entries[2] ?? [])));
32
+ },
33
+ Effect.mapError((failure) => new SetupFailure({ message: failure.message })),
34
+ );
@@ -6,7 +6,6 @@ interface Row {
6
6
  readonly text: string;
7
7
  }
8
8
 
9
- // An untouched entry keeps its exact line and a new one goes before the first line that sorts after it, so two branches conflict only on the same or neighbouring entries.
10
9
  export function rewriteBaseline(raw: string | undefined, before: readonly BaselineEntry[], after: readonly BaselineEntry[]): string {
11
10
  const wanted = new Map(after.map((entry) => [keyOf(entry.rule, entry.file), entry]));
12
11
  const lines = linesOf(raw);
@@ -0,0 +1,60 @@
1
+ import { join } from "node:path";
2
+ import { Effect, FileSystem } from "effect";
3
+ import type { BaselineEntry } from "#baseline/format.ts";
4
+ import { rewriteBaseline } from "#baseline/rewrite.ts";
5
+ import type { ResolvedConfig } from "#config/load.ts";
6
+ import { SetupFailure } from "#failure.ts";
7
+ import { orWhenAbsent, writeText } from "#inventory/filesystem.ts";
8
+
9
+ export const SHARD_NAME = "quality-baseline.jsonl";
10
+
11
+ export interface Shard {
12
+ readonly entries: readonly BaselineEntry[];
13
+ readonly raw: string;
14
+ }
15
+
16
+ export function shardOf(file: string, rootFile: string): string {
17
+ const [folder, name, ...rest] = file.split("/");
18
+ return folder === "packages" && name !== undefined && rest.length > 0 ? `packages/${name}/${SHARD_NAME}` : rootFile;
19
+ }
20
+
21
+ export const shardPaths = Effect.fn("Baseline.shardPaths")(function* (config: ResolvedConfig) {
22
+ const fs = yield* FileSystem.FileSystem;
23
+ const folder = join(config.root, "packages");
24
+ const names = yield* orWhenAbsent(folder, fs.readDirectory(folder), []);
25
+ const paths = [config.baseline];
26
+ for (const name of names) {
27
+ if ((yield* fs.stat(join(folder, name))).type === "Directory") {
28
+ paths.push(`packages/${name}/${SHARD_NAME}`);
29
+ }
30
+ }
31
+ return paths;
32
+ });
33
+
34
+ export const saveShards = Effect.fn("Baseline.saveShards")(
35
+ function* (config: ResolvedConfig, before: ReadonlyMap<string, Shard>, entries: readonly BaselineEntry[]) {
36
+ const fs = yield* FileSystem.FileSystem;
37
+ const grouped = new Map<string, BaselineEntry[]>();
38
+ for (const entry of entries) {
39
+ const path = shardOf(entry.file, config.baseline);
40
+ const group = grouped.get(path) ?? [];
41
+ group.push(entry);
42
+ grouped.set(path, group);
43
+ }
44
+ for (const path of new Set([...before.keys(), ...grouped.keys()])) {
45
+ const old = before.get(path);
46
+ const next = grouped.get(path) ?? [];
47
+ if (next.length === 0) {
48
+ if (old !== undefined) {
49
+ yield* fs.remove(join(config.root, path));
50
+ }
51
+ } else {
52
+ const text = rewriteBaseline(old?.raw, old?.entries ?? [], next);
53
+ if (text !== old?.raw) {
54
+ yield* writeText(join(config.root, path), text);
55
+ }
56
+ }
57
+ }
58
+ },
59
+ Effect.mapError((failure) => new SetupFailure({ message: failure.message })),
60
+ );
package/src/cli/args.ts CHANGED
@@ -6,6 +6,8 @@ export type Command =
6
6
  | { readonly _tag: "Lint"; readonly config: string | undefined }
7
7
  | { readonly _tag: "ExceptionsMigrate"; readonly config: string | undefined; readonly from: string | undefined }
8
8
  | { readonly _tag: "Fix"; readonly config: string | undefined }
9
+ | { readonly _tag: "BaselineMerge"; readonly base: string; readonly ours: string; readonly theirs: string }
10
+ | { readonly _tag: "BaselineInstallDriver" }
9
11
  | { readonly _tag: "BaselineWrite"; readonly config: string | undefined; readonly rules: readonly string[] }
10
12
  | { readonly _tag: "BaselinePrune"; readonly config: string | undefined; readonly against: string | undefined }
11
13
  | { readonly _tag: "BaselineTighten"; readonly config: string | undefined; readonly staged: boolean }
@@ -45,6 +47,7 @@ type Option = Exclude<keyof Values, "config" | "help">;
45
47
  const COMMAND_OPTIONS: readonly Option[] = ["against", "force", "from", "rule", "staged"];
46
48
 
47
49
  const ACCEPTS: Readonly<Record<string, readonly Option[]>> = {
50
+ "baseline install-driver": [],
48
51
  "baseline migrate": ["from"],
49
52
  "baseline prune": ["against"],
50
53
  "baseline tighten": ["staged"],
@@ -77,6 +80,8 @@ function commandFor(name: string, values: Values): Parsed {
77
80
  return parsed({ _tag: "ExceptionsMigrate", config, from: values.from });
78
81
  case "fix":
79
82
  return parsed({ _tag: "Fix", config });
83
+ case "baseline install-driver":
84
+ return parsed({ _tag: "BaselineInstallDriver" });
80
85
  case "baseline write":
81
86
  return parsed({ _tag: "BaselineWrite", config, rules: values.rule ?? [] });
82
87
  case "baseline prune":
@@ -109,6 +114,12 @@ export function parseCommand(args: readonly string[]): Parsed {
109
114
  if (values.help === true || command === "help") {
110
115
  return parsed({ _tag: "Help" });
111
116
  }
117
+ if (command === "baseline" && rest[0] === "merge") {
118
+ const [, base, ours, theirs] = rest;
119
+ return rest.length === 4 && base !== undefined && ours !== undefined && theirs !== undefined
120
+ ? parsed({ _tag: "BaselineMerge", base, ours, theirs })
121
+ : usage("baseline merge takes <ancestor> <current> <other>.");
122
+ }
112
123
  const name = [command, ...rest].join(" ");
113
124
  if (ACCEPTS[name] === undefined) {
114
125
  const subcommands = SUBCOMMANDS[command];
@@ -1,19 +1,14 @@
1
- import { join } from "node:path";
2
1
  import { Console, Effect, type FileSystem } from "effect";
3
2
  import type { BaselineEntry } from "#baseline/format.ts";
4
- import { rewriteBaseline } from "#baseline/rewrite.ts";
3
+ import { saveShards } from "#baseline/shards.ts";
5
4
  import { adopt, type Pruned, prune, type Scope } from "#baseline/update.ts";
6
5
  import { openSession, type Session } from "#engine/session.ts";
7
6
  import { applyRegistry } from "#exceptions/registry.ts";
8
7
  import { SetupFailure } from "#failure.ts";
9
- import { writeText } from "#inventory/filesystem.ts";
10
8
  import { plural } from "#report/plural.ts";
11
9
 
12
10
  function save(session: Session, entries: readonly BaselineEntry[]): Effect.Effect<void, SetupFailure, FileSystem.FileSystem> {
13
- return Effect.mapError(
14
- writeText(join(session.config.root, session.config.baseline), rewriteBaseline(session.baseline.raw, session.baseline.entries, entries)),
15
- (failure) => new SetupFailure({ message: failure.message }),
16
- );
11
+ return saveShards(session.config, session.baseline.files, entries);
17
12
  }
18
13
 
19
14
  function unregistered(session: Session) {
@@ -26,7 +21,7 @@ export const writeBaseline = Effect.fn("Cli.writeBaseline")(function* (
26
21
  rules: readonly string[],
27
22
  ): Effect.fn.Return<void, SetupFailure, FileSystem.FileSystem> {
28
23
  const session = yield* openSession(cwd, config);
29
- const existing = session.baseline.raw === undefined ? undefined : session.baseline.entries;
24
+ const existing = session.baseline.files.size === 0 ? undefined : session.baseline.entries;
30
25
  const adoption = adopt(existing, rules, unregistered(session), session.config);
31
26
  if (adoption._tag === "Refused") {
32
27
  return yield* new SetupFailure({ message: `baseline write refused:\n${adoption.reasons.map((reason) => ` - ${reason}`).join("\n")}` });
@@ -54,11 +49,12 @@ export const shrinkBaseline = Effect.fn("Cli.shrinkBaseline")(function* <TRequir
54
49
  scopeOf: (session: Session) => Effect.Effect<Scope, SetupFailure, TRequirements>,
55
50
  ): Effect.fn.Return<void, SetupFailure, FileSystem.FileSystem | TRequirements> {
56
51
  const session = yield* openSession(cwd, config);
57
- if (session.baseline.raw === undefined) {
52
+ if (session.baseline.files.size === 0) {
58
53
  return yield* Console.log(`quality: no baseline at ${session.config.baseline}; nothing to lower.`);
59
54
  }
60
55
  const pruned = prune(session.baseline.entries, unregistered(session), session.config, yield* scopeOf(session));
61
- if (pruned.removed === 0 && pruned.lowered === 0 && pruned.moved === 0) {
56
+ const emptyShard = [...session.baseline.files.values()].some((file) => file.entries.length === 0);
57
+ if (pruned.removed === 0 && pruned.lowered === 0 && pruned.moved === 0 && !emptyShard) {
62
58
  return yield* Console.log(`quality: ${session.config.baseline} is current.`);
63
59
  }
64
60
  yield* save(session, pruned.entries);
@@ -2,6 +2,8 @@ export const USAGE = `Usage:
2
2
  quality lint [--config <file>]
3
3
  quality fix [--config <file>]
4
4
  quality exceptions migrate [--config <file>] [--from <registry>]
5
+ quality baseline merge <ancestor> <current> <other>
6
+ quality baseline install-driver
5
7
  quality baseline write [--config <file>] [--rule <id>]...
6
8
  quality baseline prune [--config <file>] [--against <ref>]
7
9
  quality baseline tighten [--config <file>] [--staged]
@@ -15,10 +17,12 @@ lint Run every rule. Exits 1 on an error-level violation, a file ov
15
17
  or a baseline entry for an unknown rule.
16
18
  fix Sort every package.json, apply Biome's lint fixes, unsafe ones included, its assist actions and formatting, then format again.
17
19
  exceptions migrate Move legacy registry entries and Biome declarations into quality.config.ts exceptions and remove matching root overrides.
20
+ baseline merge Merge Git baseline versions into <current>: deletions win and counts take the minimum.
21
+ baseline install-driver Configure only the repository-local merge.quality-baseline.driver setting.
18
22
  baseline write Record current error-level violations. Creates the baseline, or records the named rules again, replacing their entries.
19
23
  baseline prune Drop fixed debt, lower entries to what is left and carry entries to files git saw move. Never adds or raises an entry.
20
24
  baseline tighten Prune only the entries of files changed since HEAD, or with --staged, in the index.
21
- baseline migrate Move a baseline from the earlier JSON format (--from, quality/baseline.json by default) to the configured file.
25
+ baseline migrate Move a JSON or JSON Lines baseline (--from, quality/baseline.json by default) into root and package shards.
22
26
  hooks install Install the git pre-commit hook, shared by every worktree, that runs hooks pre-commit. Keeps a hook that is not quality's
23
27
  unless --force replaces it.
24
28
  hooks uninstall Remove quality's pre-commit hook. Keeps a hook that is not quality's.
@@ -30,7 +34,7 @@ hooks pre-commit What the hook runs: lint, then package.json scripts typecheck
30
34
  Exit codes: 0 passed, 1 failed the gate, 2 could not run.`;
31
35
 
32
36
  export const SUBCOMMANDS: Readonly<Record<string, string>> = {
33
- baseline: "baseline takes write, prune, tighten or migrate.",
37
+ baseline: "baseline takes write, prune, tighten, migrate, merge or install-driver.",
34
38
  exceptions: "exceptions takes migrate.",
35
39
  hooks: "hooks takes install, uninstall, status or pre-commit.",
36
40
  };
@@ -1,13 +1,13 @@
1
1
  import { join } from "node:path";
2
2
  import { Console, Effect, FileSystem } from "effect";
3
- import { encodeBaseline } from "#baseline/format.ts";
3
+ import { decodeBaseline } from "#baseline/format.ts";
4
4
  import { convertLegacy, decodeLegacyBaseline, LEGACY_BASELINE } from "#baseline/legacy.ts";
5
+ import { saveShards, shardPaths } from "#baseline/shards.ts";
5
6
  import { loadConfig } from "#config/load.ts";
6
7
  import { validOrFail } from "#decoded.ts";
7
8
  import { readInput } from "#engine/baselineFile.ts";
8
9
  import { scan } from "#engine/session.ts";
9
10
  import { SetupFailure } from "#failure.ts";
10
- import { writeText } from "#inventory/filesystem.ts";
11
11
  import { plural } from "#report/plural.ts";
12
12
 
13
13
  export const migrateBaseline = Effect.fn("Cli.migrateBaseline")(function* (
@@ -17,17 +17,21 @@ export const migrateBaseline = Effect.fn("Cli.migrateBaseline")(function* (
17
17
  ): Effect.fn.Return<void, SetupFailure, FileSystem.FileSystem> {
18
18
  const config = yield* loadConfig(cwd, configPath);
19
19
  const source = from ?? LEGACY_BASELINE;
20
- if (source === config.baseline || (yield* readInput(config.root, config.baseline)) !== undefined) {
20
+ const paths = yield* shardPaths(config).pipe(Effect.mapError((error) => new SetupFailure({ message: error.message })));
21
+ const existing = yield* Effect.forEach(paths, (path) => readInput(config.root, path));
22
+ if (source === config.baseline || existing.some((text) => text !== undefined)) {
21
23
  return yield* new SetupFailure({ message: `${config.baseline} already exists. Migrate into a baseline file that does not exist yet.` });
22
24
  }
23
25
  const raw = yield* readInput(config.root, source);
24
26
  if (raw === undefined) {
25
27
  return yield* new SetupFailure({ message: `no baseline at ${source} to migrate. Name it with --from <file>.` });
26
28
  }
27
- const legacy = yield* validOrFail(source, yield* Effect.promise(() => decodeLegacyBaseline(raw)));
28
- const entries = convertLegacy(legacy, (yield* scan(config)).violations);
29
+ const legacy = source.endsWith(".jsonl")
30
+ ? yield* validOrFail(source, yield* Effect.promise(() => decodeBaseline(raw)))
31
+ : yield* validOrFail(source, yield* Effect.promise(() => decodeLegacyBaseline(raw)));
32
+ const entries = source.endsWith(".jsonl") ? legacy : convertLegacy(legacy, (yield* scan(config)).violations);
29
33
  const fs = yield* FileSystem.FileSystem;
30
- const written = Effect.andThen(writeText(join(config.root, config.baseline), encodeBaseline(entries)), fs.remove(join(config.root, source)));
34
+ const written = Effect.andThen(saveShards(config, new Map(), entries), fs.remove(join(config.root, source)));
31
35
  yield* Effect.mapError(written, (failure) => new SetupFailure({ message: failure.message }));
32
36
  const fixed = legacy.length - entries.length;
33
37
  const dropped = fixed > 0 ? `, dropping ${plural(fixed, "fixed entry", "fixed entries")}` : "";
@@ -1,4 +1,6 @@
1
1
  import { Console, Effect } from "effect";
2
+ import { installDriver } from "#baseline/installDriver.ts";
3
+ import { mergeBaseline } from "#baseline/merge.ts";
2
4
  import { parseCommand, USAGE } from "#cli/args.ts";
3
5
  import { writeBaseline } from "#cli/baseline.ts";
4
6
  import { fix } from "#cli/fix.ts";
@@ -31,6 +33,10 @@ export const program = Effect.fn("Cli.program")(function* (args: readonly string
31
33
  return yield* lint(cwd, command.config);
32
34
  case "Fix":
33
35
  return yield* fix(cwd, command.config);
36
+ case "BaselineMerge":
37
+ return yield* mergeBaseline(command.base, command.ours, command.theirs);
38
+ case "BaselineInstallDriver":
39
+ return yield* installDriver(cwd, launch);
34
40
  case "BaselineWrite":
35
41
  return yield* writeBaseline(cwd, command.config, command.rules);
36
42
  case "BaselinePrune":
@@ -49,7 +49,7 @@ function biomeDeclarations(config: ConfigInput): readonly Declaration[] {
49
49
  function resolved(root: string, file: string, config: ConfigInput, rules: ResolvedRules): ResolvedConfig {
50
50
  return {
51
51
  ...rules,
52
- baseline: config.baseline ?? "quality/baseline.jsonl",
52
+ baseline: config.baseline ?? "quality-baseline.jsonl",
53
53
  biomeDeclarations: biomeDeclarations(config),
54
54
  exceptions: config.exceptions ?? [],
55
55
  exclude: [],