@shivaedev/quality 0.24.0 → 0.26.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 (275) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +71 -28
  3. package/dist/baseline/compare.js +1 -1
  4. package/dist/baseline/compare.js.map +1 -1
  5. package/dist/baseline/update.js +3 -3
  6. package/dist/baseline/update.js.map +1 -1
  7. package/dist/cli/args.d.ts +1 -3
  8. package/dist/cli/args.d.ts.map +1 -1
  9. package/dist/cli/args.js +5 -18
  10. package/dist/cli/args.js.map +1 -1
  11. package/dist/cli/fix.js +1 -1
  12. package/dist/cli/fix.js.map +1 -1
  13. package/dist/cli/lint.d.ts +1 -2
  14. package/dist/cli/lint.d.ts.map +1 -1
  15. package/dist/cli/lint.js +1 -2
  16. package/dist/cli/lint.js.map +1 -1
  17. package/dist/cli/messages.d.ts +2 -2
  18. package/dist/cli/messages.d.ts.map +1 -1
  19. package/dist/cli/messages.js +7 -3
  20. package/dist/cli/messages.js.map +1 -1
  21. package/dist/cli/migrate.js +1 -1
  22. package/dist/cli/migrate.js.map +1 -1
  23. package/dist/cli/migrateExceptions.js +1 -1
  24. package/dist/cli/migrateExceptions.js.map +1 -1
  25. package/dist/cli/program.js +1 -1
  26. package/dist/cli/program.js.map +1 -1
  27. package/dist/cli/{run-main.d.ts → runMain.d.ts} +1 -1
  28. package/dist/cli/runMain.d.ts.map +1 -0
  29. package/dist/cli/{run-main.js → runMain.js} +1 -1
  30. package/dist/cli/runMain.js.map +1 -0
  31. package/dist/cli.js +1 -1
  32. package/dist/cli.js.map +1 -1
  33. package/dist/config/decode.d.ts +0 -2
  34. package/dist/config/decode.d.ts.map +1 -1
  35. package/dist/config/decode.js +0 -8
  36. package/dist/config/decode.js.map +1 -1
  37. package/dist/config/resolve.d.ts +1 -3
  38. package/dist/config/resolve.d.ts.map +1 -1
  39. package/dist/config/resolve.js +1 -1
  40. package/dist/config/resolve.js.map +1 -1
  41. package/dist/config.d.ts +2 -2
  42. package/dist/config.d.ts.map +1 -1
  43. package/dist/decoded.d.ts +1 -1
  44. package/dist/decoded.d.ts.map +1 -1
  45. package/dist/decoded.js +1 -1
  46. package/dist/decoded.js.map +1 -1
  47. package/dist/engine/{baseline-file.d.ts → baselineFile.d.ts} +1 -1
  48. package/dist/engine/baselineFile.d.ts.map +1 -0
  49. package/dist/engine/{baseline-file.js → baselineFile.js} +1 -1
  50. package/dist/engine/baselineFile.js.map +1 -0
  51. package/dist/engine/evaluate.d.ts +0 -1
  52. package/dist/engine/evaluate.d.ts.map +1 -1
  53. package/dist/engine/evaluate.js +1 -2
  54. package/dist/engine/evaluate.js.map +1 -1
  55. package/dist/engine/{run-rules.d.ts → runRules.d.ts} +1 -1
  56. package/dist/engine/runRules.d.ts.map +1 -0
  57. package/dist/engine/{run-rules.js → runRules.js} +2 -2
  58. package/dist/engine/runRules.js.map +1 -0
  59. package/dist/engine/session.d.ts +1 -1
  60. package/dist/engine/session.d.ts.map +1 -1
  61. package/dist/engine/session.js +2 -2
  62. package/dist/engine/session.js.map +1 -1
  63. package/dist/engine/violation.d.ts +1 -1
  64. package/dist/engine/violation.d.ts.map +1 -1
  65. package/dist/engine/violation.js +1 -1
  66. package/dist/engine/violation.js.map +1 -1
  67. package/dist/hooks/preCommit.js +1 -1
  68. package/dist/hooks/preCommit.js.map +1 -1
  69. package/dist/imports/generated.js +1 -1
  70. package/dist/imports/generated.js.map +1 -1
  71. package/dist/imports/{pnpm-workspace.d.ts → pnpmWorkspacePatterns.d.ts} +1 -1
  72. package/dist/imports/pnpmWorkspacePatterns.d.ts.map +1 -0
  73. package/dist/imports/{pnpm-workspace.js → pnpmWorkspacePatterns.js} +1 -1
  74. package/dist/imports/pnpmWorkspacePatterns.js.map +1 -0
  75. package/dist/imports/resolve.js +1 -1
  76. package/dist/imports/resolve.js.map +1 -1
  77. package/dist/imports/workspace.js +1 -1
  78. package/dist/imports/workspace.js.map +1 -1
  79. package/dist/inventory/collect.js +1 -1
  80. package/dist/inventory/collect.js.map +1 -1
  81. package/dist/inventory/{ignore-scope.d.ts → ignoreScope.d.ts} +1 -1
  82. package/dist/inventory/ignoreScope.d.ts.map +1 -0
  83. package/dist/inventory/{ignore-scope.js → ignoreScope.js} +1 -1
  84. package/dist/inventory/ignoreScope.js.map +1 -0
  85. package/dist/inventory/walk.d.ts +1 -1
  86. package/dist/inventory/walk.d.ts.map +1 -1
  87. package/dist/inventory/walk.js +1 -1
  88. package/dist/inventory/walk.js.map +1 -1
  89. package/dist/manifests/sorted.js +1 -1
  90. package/dist/manifests/sorted.js.map +1 -1
  91. package/dist/report/render.d.ts +0 -2
  92. package/dist/report/render.d.ts.map +1 -1
  93. package/dist/report/render.js +6 -16
  94. package/dist/report/render.js.map +1 -1
  95. package/dist/report/stale.js +1 -1
  96. package/dist/report/stale.js.map +1 -1
  97. package/dist/rule.d.ts +1 -1
  98. package/dist/rule.d.ts.map +1 -1
  99. package/dist/rule.js +1 -1
  100. package/dist/rule.js.map +1 -1
  101. package/dist/rules/{built-in.d.ts → builtIn.d.ts} +2 -2
  102. package/dist/rules/builtIn.d.ts.map +1 -0
  103. package/dist/rules/{built-in.js → builtIn.js} +15 -13
  104. package/dist/rules/builtIn.js.map +1 -0
  105. package/dist/rules/comments/{pattern-rule.d.ts → definePattern.d.ts} +1 -1
  106. package/dist/rules/comments/definePattern.d.ts.map +1 -0
  107. package/dist/rules/comments/{pattern-rule.js → definePattern.js} +1 -1
  108. package/dist/rules/comments/definePattern.js.map +1 -0
  109. package/dist/rules/comments/{max-per-file.d.ts → maxPerFile.d.ts} +1 -1
  110. package/dist/rules/comments/maxPerFile.d.ts.map +1 -0
  111. package/dist/rules/comments/{max-per-file.js → maxPerFile.js} +1 -1
  112. package/dist/rules/comments/maxPerFile.js.map +1 -0
  113. package/dist/rules/comments/{no-banner.d.ts → noBanner.d.ts} +1 -1
  114. package/dist/rules/comments/noBanner.d.ts.map +1 -0
  115. package/dist/rules/comments/{no-banner.js → noBanner.js} +2 -2
  116. package/dist/rules/comments/noBanner.js.map +1 -0
  117. package/dist/rules/comments/{no-environment-pragma.d.ts → noEnvironmentPragma.d.ts} +1 -1
  118. package/dist/rules/comments/noEnvironmentPragma.d.ts.map +1 -0
  119. package/dist/rules/comments/{no-environment-pragma.js → noEnvironmentPragma.js} +2 -2
  120. package/dist/rules/comments/noEnvironmentPragma.js.map +1 -0
  121. package/dist/rules/comments/{no-jsdoc.d.ts → noJsdoc.d.ts} +1 -1
  122. package/dist/rules/comments/noJsdoc.d.ts.map +1 -0
  123. package/dist/rules/comments/{no-jsdoc.js → noJsdoc.js} +1 -1
  124. package/dist/rules/comments/noJsdoc.js.map +1 -0
  125. package/dist/rules/comments/{no-line-reference.d.ts → noLineReference.d.ts} +1 -1
  126. package/dist/rules/comments/noLineReference.d.ts.map +1 -0
  127. package/dist/rules/comments/{no-line-reference.js → noLineReference.js} +2 -2
  128. package/dist/rules/comments/noLineReference.js.map +1 -0
  129. package/dist/rules/comments/{no-pr-reference.d.ts → noPrReference.d.ts} +1 -1
  130. package/dist/rules/comments/noPrReference.d.ts.map +1 -0
  131. package/dist/rules/comments/{no-pr-reference.js → noPrReference.js} +2 -2
  132. package/dist/rules/comments/noPrReference.js.map +1 -0
  133. package/dist/rules/comments/{no-todo.d.ts → noTodo.d.ts} +1 -1
  134. package/dist/rules/comments/noTodo.d.ts.map +1 -0
  135. package/dist/rules/comments/{no-todo.js → noTodo.js} +2 -2
  136. package/dist/rules/comments/noTodo.js.map +1 -0
  137. package/dist/rules/{manifests-sorted.d.ts → manifestsSorted.d.ts} +1 -1
  138. package/dist/rules/manifestsSorted.d.ts.map +1 -0
  139. package/dist/rules/{manifests-sorted.js → manifestsSorted.js} +1 -1
  140. package/dist/rules/manifestsSorted.js.map +1 -0
  141. package/dist/rules/manifestsSourceFirst.d.ts +2 -0
  142. package/dist/rules/manifestsSourceFirst.d.ts.map +1 -0
  143. package/dist/rules/manifestsSourceFirst.js +43 -0
  144. package/dist/rules/manifestsSourceFirst.js.map +1 -0
  145. package/dist/rules/{max-lines.d.ts → maxLines.d.ts} +1 -1
  146. package/dist/rules/maxLines.d.ts.map +1 -0
  147. package/dist/rules/{max-lines.js → maxLines.js} +1 -1
  148. package/dist/rules/maxLines.js.map +1 -0
  149. package/dist/rules/suppressions/{biome-overrides.d.ts → biomeOverrides.d.ts} +1 -1
  150. package/dist/rules/suppressions/biomeOverrides.d.ts.map +1 -0
  151. package/dist/rules/suppressions/{biome-overrides.js → biomeOverrides.js} +1 -1
  152. package/dist/rules/suppressions/biomeOverrides.js.map +1 -0
  153. package/dist/rules/suppressions/{no-double-cast.d.ts → noDoubleCast.d.ts} +1 -1
  154. package/dist/rules/suppressions/noDoubleCast.d.ts.map +1 -0
  155. package/dist/rules/suppressions/{no-double-cast.js → noDoubleCast.js} +1 -1
  156. package/dist/rules/suppressions/noDoubleCast.js.map +1 -0
  157. package/dist/rules/suppressions/noIgnoreDeprecations.js +1 -1
  158. package/dist/rules/suppressions/noIgnoreDeprecations.js.map +1 -1
  159. package/dist/rules/suppressions/{no-inline.d.ts → noInline.d.ts} +1 -1
  160. package/dist/rules/suppressions/noInline.d.ts.map +1 -0
  161. package/dist/rules/suppressions/{no-inline.js → noInline.js} +2 -2
  162. package/dist/rules/suppressions/noInline.js.map +1 -0
  163. package/dist/rules/suppressions/{stylesheet-comments.d.ts → stylesheetComments.d.ts} +1 -1
  164. package/dist/rules/suppressions/stylesheetComments.d.ts.map +1 -0
  165. package/dist/rules/suppressions/{stylesheet-comments.js → stylesheetComments.js} +1 -1
  166. package/dist/rules/suppressions/stylesheetComments.js.map +1 -0
  167. package/dist/{standard-schema.d.ts → standardSchema.d.ts} +1 -1
  168. package/dist/standardSchema.d.ts.map +1 -0
  169. package/dist/{standard-schema.js → standardSchema.js} +1 -1
  170. package/dist/standardSchema.js.map +1 -0
  171. package/dist/testProjects.d.ts +1 -1
  172. package/dist/testProjects.d.ts.map +1 -1
  173. package/dist/testProjects.js +4 -4
  174. package/dist/testProjects.js.map +1 -1
  175. package/docs/debt-and-hooks.md +9 -38
  176. package/docs/north-star.md +0 -3
  177. package/package.json +2 -3
  178. package/src/baseline/compare.ts +1 -1
  179. package/src/baseline/update.ts +3 -3
  180. package/src/cli/args.ts +6 -21
  181. package/src/cli/fix.ts +1 -1
  182. package/src/cli/lint.ts +1 -3
  183. package/src/cli/messages.ts +7 -4
  184. package/src/cli/migrate.ts +1 -1
  185. package/src/cli/migrateExceptions.ts +1 -1
  186. package/src/cli/program.ts +1 -1
  187. package/src/cli.ts +1 -1
  188. package/src/config/decode.ts +0 -11
  189. package/src/config/resolve.ts +2 -2
  190. package/src/config.ts +2 -2
  191. package/src/decoded.ts +1 -1
  192. package/src/engine/evaluate.ts +1 -3
  193. package/src/engine/{run-rules.ts → runRules.ts} +1 -1
  194. package/src/engine/session.ts +2 -2
  195. package/src/engine/violation.ts +2 -2
  196. package/src/hooks/preCommit.ts +1 -1
  197. package/src/imports/generated.ts +1 -1
  198. package/src/imports/resolve.ts +1 -1
  199. package/src/imports/workspace.ts +1 -1
  200. package/src/inventory/collect.ts +1 -1
  201. package/src/inventory/walk.ts +1 -1
  202. package/src/manifests/sorted.ts +1 -1
  203. package/src/report/render.ts +6 -26
  204. package/src/report/stale.ts +1 -1
  205. package/src/rule.ts +1 -1
  206. package/src/rules/{built-in.ts → builtIn.ts} +14 -12
  207. package/src/rules/comments/{no-banner.ts → noBanner.ts} +1 -1
  208. package/src/rules/comments/{no-environment-pragma.ts → noEnvironmentPragma.ts} +1 -1
  209. package/src/rules/comments/{no-line-reference.ts → noLineReference.ts} +1 -1
  210. package/src/rules/comments/{no-pr-reference.ts → noPrReference.ts} +1 -1
  211. package/src/rules/comments/{no-todo.ts → noTodo.ts} +1 -1
  212. package/src/rules/manifestsSourceFirst.ts +48 -0
  213. package/src/rules/suppressions/noIgnoreDeprecations.ts +1 -1
  214. package/src/rules/suppressions/{no-inline.ts → noInline.ts} +1 -1
  215. package/src/testProjects.ts +4 -4
  216. package/dist/cli/run-main.d.ts.map +0 -1
  217. package/dist/cli/run-main.js.map +0 -1
  218. package/dist/engine/baseline-file.d.ts.map +0 -1
  219. package/dist/engine/baseline-file.js.map +0 -1
  220. package/dist/engine/run-rules.d.ts.map +0 -1
  221. package/dist/engine/run-rules.js.map +0 -1
  222. package/dist/imports/pnpm-workspace.d.ts.map +0 -1
  223. package/dist/imports/pnpm-workspace.js.map +0 -1
  224. package/dist/inventory/ignore-scope.d.ts.map +0 -1
  225. package/dist/inventory/ignore-scope.js.map +0 -1
  226. package/dist/rules/built-in.d.ts.map +0 -1
  227. package/dist/rules/built-in.js.map +0 -1
  228. package/dist/rules/comments/max-per-file.d.ts.map +0 -1
  229. package/dist/rules/comments/max-per-file.js.map +0 -1
  230. package/dist/rules/comments/no-banner.d.ts.map +0 -1
  231. package/dist/rules/comments/no-banner.js.map +0 -1
  232. package/dist/rules/comments/no-environment-pragma.d.ts.map +0 -1
  233. package/dist/rules/comments/no-environment-pragma.js.map +0 -1
  234. package/dist/rules/comments/no-jsdoc.d.ts.map +0 -1
  235. package/dist/rules/comments/no-jsdoc.js.map +0 -1
  236. package/dist/rules/comments/no-line-reference.d.ts.map +0 -1
  237. package/dist/rules/comments/no-line-reference.js.map +0 -1
  238. package/dist/rules/comments/no-pr-reference.d.ts.map +0 -1
  239. package/dist/rules/comments/no-pr-reference.js.map +0 -1
  240. package/dist/rules/comments/no-todo.d.ts.map +0 -1
  241. package/dist/rules/comments/no-todo.js.map +0 -1
  242. package/dist/rules/comments/pattern-rule.d.ts.map +0 -1
  243. package/dist/rules/comments/pattern-rule.js.map +0 -1
  244. package/dist/rules/manifests-sorted.d.ts.map +0 -1
  245. package/dist/rules/manifests-sorted.js.map +0 -1
  246. package/dist/rules/max-lines.d.ts.map +0 -1
  247. package/dist/rules/max-lines.js.map +0 -1
  248. package/dist/rules/suppressions/biome-overrides.d.ts.map +0 -1
  249. package/dist/rules/suppressions/biome-overrides.js.map +0 -1
  250. package/dist/rules/suppressions/no-double-cast.d.ts.map +0 -1
  251. package/dist/rules/suppressions/no-double-cast.js.map +0 -1
  252. package/dist/rules/suppressions/no-inline.d.ts.map +0 -1
  253. package/dist/rules/suppressions/no-inline.js.map +0 -1
  254. package/dist/rules/suppressions/stylesheet-comments.d.ts.map +0 -1
  255. package/dist/rules/suppressions/stylesheet-comments.js.map +0 -1
  256. package/dist/standard-schema.d.ts.map +0 -1
  257. package/dist/standard-schema.js.map +0 -1
  258. package/docs/modules.md +0 -274
  259. package/docs/naming.md +0 -130
  260. package/docs/roadmap.md +0 -37
  261. package/docs/rules.md +0 -297
  262. package/docs/tooling.md +0 -105
  263. /package/src/cli/{run-main.ts → runMain.ts} +0 -0
  264. /package/src/engine/{baseline-file.ts → baselineFile.ts} +0 -0
  265. /package/src/imports/{pnpm-workspace.ts → pnpmWorkspacePatterns.ts} +0 -0
  266. /package/src/inventory/{ignore-scope.ts → ignoreScope.ts} +0 -0
  267. /package/src/rules/comments/{pattern-rule.ts → definePattern.ts} +0 -0
  268. /package/src/rules/comments/{max-per-file.ts → maxPerFile.ts} +0 -0
  269. /package/src/rules/comments/{no-jsdoc.ts → noJsdoc.ts} +0 -0
  270. /package/src/rules/{manifests-sorted.ts → manifestsSorted.ts} +0 -0
  271. /package/src/rules/{max-lines.ts → maxLines.ts} +0 -0
  272. /package/src/rules/suppressions/{biome-overrides.ts → biomeOverrides.ts} +0 -0
  273. /package/src/rules/suppressions/{no-double-cast.ts → noDoubleCast.ts} +0 -0
  274. /package/src/rules/suppressions/{stylesheet-comments.ts → stylesheetComments.ts} +0 -0
  275. /package/src/{standard-schema.ts → standardSchema.ts} +0 -0
package/src/cli/args.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import { parseArgs } from "node:util";
2
2
  import { Result } from "effect";
3
- import type { WarningDetail } from "#report/render.ts";
4
- import { ADOPT_REMOVED, USAGE as COMMAND_USAGE } from "./messages.ts";
3
+ import { USAGE as COMMAND_USAGE, SUBCOMMANDS } from "./messages.ts";
5
4
 
6
5
  export type Command =
7
- | { readonly _tag: "Lint"; readonly config: string | undefined; readonly warnings: WarningDetail }
6
+ | { readonly _tag: "Lint"; readonly config: string | undefined }
8
7
  | { readonly _tag: "ExceptionsMigrate"; readonly config: string | undefined; readonly from: string | undefined }
9
8
  | { readonly _tag: "Fix"; readonly config: string | undefined }
10
9
  | { readonly _tag: "BaselineWrite"; readonly config: string | undefined; readonly rules: readonly string[] }
@@ -28,19 +27,12 @@ const OPTIONS = {
28
27
  help: { short: "h", type: "boolean" },
29
28
  rule: { multiple: true, type: "string" },
30
29
  staged: { type: "boolean" },
31
- warnings: { type: "string" },
32
30
  } as const;
33
31
 
34
32
  function usage(problem: string): Parsed {
35
33
  return { _tag: "Usage", problem };
36
34
  }
37
35
 
38
- const SUBCOMMANDS: Readonly<Record<string, string>> = {
39
- baseline: "baseline takes write, prune, tighten or migrate.",
40
- exceptions: "exceptions takes migrate.",
41
- hooks: "hooks takes install, uninstall or pre-commit.",
42
- };
43
-
44
36
  function parsed(command: Command): Parsed {
45
37
  return { _tag: "Parsed", command };
46
38
  }
@@ -49,7 +41,7 @@ type Values = ReturnType<typeof parseArgs<{ options: typeof OPTIONS; allowPositi
49
41
 
50
42
  type Option = Exclude<keyof Values, "config" | "help">;
51
43
 
52
- const COMMAND_OPTIONS: readonly Option[] = ["against", "force", "from", "rule", "staged", "warnings"];
44
+ const COMMAND_OPTIONS: readonly Option[] = ["against", "force", "from", "rule", "staged"];
53
45
 
54
46
  const ACCEPTS: Readonly<Record<string, readonly Option[]>> = {
55
47
  "baseline migrate": ["from"],
@@ -61,7 +53,7 @@ const ACCEPTS: Readonly<Record<string, readonly Option[]>> = {
61
53
  "hooks install": ["force"],
62
54
  "hooks pre-commit": [],
63
55
  "hooks uninstall": [],
64
- lint: ["warnings"],
56
+ lint: [],
65
57
  };
66
58
 
67
59
  function misplaced(name: string, values: Values): string | undefined {
@@ -77,12 +69,8 @@ function ref(against: string | undefined, command: Command): Parsed {
77
69
  function commandFor(name: string, values: Values): Parsed {
78
70
  const config = values.config;
79
71
  switch (name) {
80
- case "lint": {
81
- const warnings = values.warnings ?? "summary";
82
- return warnings === "summary" || warnings === "all"
83
- ? parsed({ _tag: "Lint", config, warnings })
84
- : usage(`--warnings takes summary or all, not "${warnings}".`);
85
- }
72
+ case "lint":
73
+ return parsed({ _tag: "Lint", config });
86
74
  case "exceptions migrate":
87
75
  return parsed({ _tag: "ExceptionsMigrate", config, from: values.from });
88
76
  case "fix":
@@ -118,9 +106,6 @@ export function parseCommand(args: readonly string[]): Parsed {
118
106
  return parsed({ _tag: "Help" });
119
107
  }
120
108
  const name = [command, ...rest].join(" ");
121
- if (command === "adopt") {
122
- return usage(ADOPT_REMOVED);
123
- }
124
109
  if (ACCEPTS[name] === undefined) {
125
110
  const subcommands = SUBCOMMANDS[command];
126
111
  return usage(subcommands !== undefined && rest.length < 2 ? subcommands : `unknown command: ${name}`);
package/src/cli/fix.ts CHANGED
@@ -4,7 +4,7 @@ import { biomeReport, type Report } from "#biome/report.ts";
4
4
  import { loadConfig } from "#config/load.ts";
5
5
  import type { ExceptionDeclaration } from "#exceptions/declaration.ts";
6
6
  import { SetupFailure } from "#failure.ts";
7
- import { posix } from "#inventory/ignore-scope.ts";
7
+ import { posix } from "#inventory/ignoreScope.ts";
8
8
  import { walk } from "#inventory/walk.ts";
9
9
  import { sortManifests } from "#manifests/sorted.ts";
10
10
  import { plural } from "#report/plural.ts";
package/src/cli/lint.ts CHANGED
@@ -3,12 +3,11 @@ import { Console, Effect, type FileSystem } from "effect";
3
3
  import { evaluate, passes } from "#engine/evaluate.ts";
4
4
  import { openSession } from "#engine/session.ts";
5
5
  import { GateFailed, type SetupFailure } from "#failure.ts";
6
- import { render, type WarningDetail } from "#report/render.ts";
6
+ import { render } from "#report/render.ts";
7
7
 
8
8
  export const lint = Effect.fn("Cli.lint")(function* (
9
9
  cwd: string,
10
10
  config: string | undefined,
11
- warnings: WarningDetail,
12
11
  ): Effect.fn.Return<void, SetupFailure | GateFailed, FileSystem.FileSystem> {
13
12
  const session = yield* openSession(cwd, config);
14
13
  const outcome = evaluate(session.violations, session.registry, session.baseline.entries, session.config);
@@ -18,7 +17,6 @@ export const lint = Effect.fn("Cli.lint")(function* (
18
17
  checked: session.inventory.sources.length,
19
18
  descriptions: new Map(session.config.active.map((rule) => [rule.id, rule.description])),
20
19
  registry: session.config.exceptions.length === 0 ? session.config.registry : `${relative(session.config.root, session.config.file)} exceptions`,
21
- warnings,
22
20
  }),
23
21
  );
24
22
  if (!passes(outcome)) {
@@ -1,5 +1,5 @@
1
1
  export const USAGE = `Usage:
2
- quality lint [--config <file>] [--warnings summary|all]
2
+ quality lint [--config <file>]
3
3
  quality fix [--config <file>]
4
4
  quality exceptions migrate [--config <file>] [--from <registry>]
5
5
  quality baseline write [--config <file>] [--rule <id>]...
@@ -11,7 +11,7 @@ export const USAGE = `Usage:
11
11
  quality hooks pre-commit [--config <file>]
12
12
 
13
13
  lint Run every rule. Exits 1 on an error-level violation, a file over its baseline, a stale registry entry
14
- or a baseline entry for a rule that is off or unknown.
14
+ or a baseline entry for an unknown rule.
15
15
  fix Sort every package.json, apply Biome's lint fixes, unsafe ones included, its assist actions and formatting, then format again.
16
16
  exceptions migrate Move legacy registry entries and Biome declarations into quality.config.ts exceptions and remove matching root overrides.
17
17
  baseline write Record current error-level violations. Creates the baseline, or records the named rules again, replacing their entries.
@@ -27,5 +27,8 @@ hooks pre-commit What the hook runs: lint, then package.json scripts typecheck
27
27
  --against <ref> The branch the work merges into, whose merge base prune follows moves from. Defaults to origin/HEAD, then origin/main, then origin/master.
28
28
  Exit codes: 0 passed, 1 failed the gate, 2 could not run.`;
29
29
 
30
- export const ADOPT_REMOVED =
31
- "`quality adopt` was removed in 0.7.0. To record a rule's existing findings in the baseline, run `quality baseline write --rule <id>`; to apply the fixes Biome can make first, run `quality fix`.";
30
+ export const SUBCOMMANDS: Readonly<Record<string, string>> = {
31
+ baseline: "baseline takes write, prune, tighten or migrate.",
32
+ exceptions: "exceptions takes migrate.",
33
+ hooks: "hooks takes install, uninstall or pre-commit.",
34
+ };
@@ -4,7 +4,7 @@ import { encodeBaseline } from "#baseline/format.ts";
4
4
  import { convertLegacy, decodeLegacyBaseline, LEGACY_BASELINE } from "#baseline/legacy.ts";
5
5
  import { loadConfig } from "#config/load.ts";
6
6
  import { validOrFail } from "#decoded.ts";
7
- import { readInput } from "#engine/baseline-file.ts";
7
+ import { readInput } from "#engine/baselineFile.ts";
8
8
  import { scan } from "#engine/session.ts";
9
9
  import { SetupFailure } from "#failure.ts";
10
10
  import { writeText } from "#inventory/filesystem.ts";
@@ -2,7 +2,7 @@ import { join } from "node:path";
2
2
  import { Console, Effect, FileSystem } from "effect";
3
3
  import { loadConfig } from "#config/load.ts";
4
4
  import { validOrFail } from "#decoded.ts";
5
- import { readInput } from "#engine/baseline-file.ts";
5
+ import { readInput } from "#engine/baselineFile.ts";
6
6
  import { decodeExceptions, type ExceptionDeclaration } from "#exceptions/declaration.ts";
7
7
  import { migrateBiome } from "#exceptions/migrateBiome.ts";
8
8
  import { migrateConfig } from "#exceptions/migrateConfig.ts";
@@ -27,7 +27,7 @@ export const program = Effect.fn("Cli.program")(function* (args: readonly string
27
27
  case "Help":
28
28
  return yield* Console.log(USAGE);
29
29
  case "Lint":
30
- return yield* lint(cwd, command.config, command.warnings);
30
+ return yield* lint(cwd, command.config);
31
31
  case "Fix":
32
32
  return yield* fix(cwd, command.config);
33
33
  case "BaselineWrite":
package/src/cli.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import process from "node:process";
3
3
  import { program } from "#cli/program.ts";
4
- import { runMain } from "#cli/run-main.ts";
4
+ import { runMain } from "#cli/runMain.ts";
5
5
 
6
6
  runMain(program(process.argv.slice(2), { cwd: process.cwd(), launch: { options: process.execArgv, script: process.argv[1] ?? "" } }));
@@ -22,22 +22,11 @@ const Setting = Schema.Union([Level, Schema.Struct({ level: Schema.optionalKey(L
22
22
 
23
23
  const LocalRule = Schema.declare(isRule, { expected: "a rule made with defineRule" });
24
24
 
25
- const AdoptRemoved = Schema.Never.annotate({
26
- message: "removed in quality 0.7.0. Delete the key, and record a rule's existing findings with `quality baseline write --rule <id>`.",
27
- });
28
-
29
- const PreCommitRemoved = Schema.Never.annotate({
30
- message:
31
- "removed. Put repository checks in the package.json quality:commit script; the hook also runs typecheck when present. Use `quality baseline tighten --staged` explicitly to lower staged debt.",
32
- });
33
-
34
25
  const ConfigInput = Schema.Struct({
35
- adopt: Schema.optionalKey(AdoptRemoved),
36
26
  baseline: Schema.optionalKey(Schema.String),
37
27
  exceptions: Schema.optionalKey(Schema.Array(ExceptionDeclaration)),
38
28
  extensions: Schema.optionalKey(Schema.Array(Schema.String)),
39
29
  local: Schema.optionalKey(Schema.Array(LocalRule)),
40
- preCommit: Schema.optionalKey(PreCommitRemoved),
41
30
  registry: Schema.optionalKey(Schema.String),
42
31
  rules: Schema.optionalKey(Schema.Record(Schema.String, Setting)),
43
32
  sources: Schema.optionalKey(Schema.Array(Schema.String)),
@@ -1,9 +1,9 @@
1
1
  import { Effect } from "effect";
2
2
  import type { Decoded } from "#decoded.ts";
3
- import type { ActiveRule } from "#engine/run-rules.ts";
3
+ import type { ActiveRule } from "#engine/runRules.ts";
4
4
  import type { RuleIndex } from "#engine/violation.ts";
5
5
  import type { Rule } from "#rule.ts";
6
- import { builtInRules } from "#rules/built-in.ts";
6
+ import { builtInRules } from "#rules/builtIn.ts";
7
7
  import type { ConfigInput } from "./decode.ts";
8
8
 
9
9
  export interface ResolvedRules extends RuleIndex {
package/src/config.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { ExceptionDeclaration } from "#exceptions/declaration.ts";
2
- import type { builtInRules } from "#rules/built-in.ts";
2
+ import type { builtInRules } from "#rules/builtIn.ts";
3
3
  import type { Rule } from "./rule.ts";
4
4
 
5
- export type Level = "error" | "warn" | "off";
5
+ export type Level = "error";
6
6
 
7
7
  export type RuleSetting<TInput> = "error" | { readonly level?: "error"; readonly options?: TInput };
8
8
 
package/src/decoded.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Effect } from "effect";
2
2
  import { SetupFailure } from "./failure.ts";
3
- import { describeIssue, type StandardSchemaV1 } from "./standard-schema.ts";
3
+ import { describeIssue, type StandardSchemaV1 } from "./standardSchema.ts";
4
4
 
5
5
  export type Decoded<TValue> = { readonly _tag: "Valid"; readonly value: TValue } | { readonly _tag: "Invalid"; readonly issues: readonly string[] };
6
6
 
@@ -11,7 +11,6 @@ export interface Outcome {
11
11
  readonly regressions: readonly Regression[];
12
12
  readonly staleBaseline: readonly StaleBaselineEntry[];
13
13
  readonly staleRegistry: readonly StaleRegistryEntry[];
14
- readonly warnings: readonly Violation[];
15
14
  }
16
15
 
17
16
  export function evaluate(
@@ -25,13 +24,12 @@ export function evaluate(
25
24
  const kept = [...baselined.kept].sort(byLocation);
26
25
  return {
27
26
  baselined: baselined.baselined,
28
- errors: kept.filter((violation) => violation.level === "error"),
27
+ errors: kept,
29
28
  looseBaseline: baselined.loose,
30
29
  registered: registered.registered,
31
30
  regressions: baselined.regressions,
32
31
  staleBaseline: baselined.stale,
33
32
  staleRegistry: registered.stale,
34
- warnings: kept.filter((violation) => violation.level === "warn"),
35
33
  };
36
34
  }
37
35
 
@@ -1,7 +1,7 @@
1
1
  import { isAbsolute, relative } from "node:path";
2
2
  import { Effect } from "effect";
3
3
  import { SetupFailure } from "#failure.ts";
4
- import { posix } from "#inventory/ignore-scope.ts";
4
+ import { posix } from "#inventory/ignoreScope.ts";
5
5
  import type { Finding, Findings, RuleInputs } from "#rule.ts";
6
6
  import type { ActiveLevel, Violation } from "./violation.ts";
7
7
 
@@ -7,8 +7,8 @@ import { registryEntries } from "#exceptions/registryEntries.ts";
7
7
  import { SetupFailure } from "#failure.ts";
8
8
  import { collectInventory, type Inventory } from "#inventory/collect.ts";
9
9
  import { type FilesystemFailure, readOptionalText } from "#inventory/filesystem.ts";
10
- import { type BaselineFile, readBaseline, readInput } from "./baseline-file.ts";
11
- import { runRules } from "./run-rules.ts";
10
+ import { type BaselineFile, readBaseline, readInput } from "./baselineFile.ts";
11
+ import { runRules } from "./runRules.ts";
12
12
  import type { Violation } from "./violation.ts";
13
13
 
14
14
  export interface Session {
@@ -1,7 +1,7 @@
1
1
  import type { Level } from "#config.ts";
2
2
  import type { Finding } from "#rule.ts";
3
3
 
4
- export type ActiveLevel = "error" | "warn";
4
+ export type ActiveLevel = "error";
5
5
 
6
6
  export interface Violation extends Finding {
7
7
  readonly level: ActiveLevel;
@@ -56,5 +56,5 @@ export function unusedEntryProblem(index: RuleIndex, rule: string, unused: strin
56
56
  if (level === undefined) {
57
57
  return "names no known rule";
58
58
  }
59
- return level === "off" ? "names a rule that is off" : unused;
59
+ return unused;
60
60
  }
@@ -48,7 +48,7 @@ const runScript = Effect.fnUntraced(
48
48
  export const preCommitHook = Effect.fn("Hooks.preCommitHook")(function* (cwd: string, path: string | undefined) {
49
49
  const config = yield* loadConfig(cwd, path);
50
50
  const { manager, scripts } = yield* commitScripts(config.root);
51
- const linted = yield* lint(cwd, path, "summary").pipe(
51
+ const linted = yield* lint(cwd, path).pipe(
52
52
  Effect.as(true),
53
53
  Effect.catchTag("GateFailed", () => Effect.succeed(false)),
54
54
  );
@@ -1,7 +1,7 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { posix } from "node:path";
3
3
  import { promisify } from "node:util";
4
- import { emptyScope, type IgnoreScope, verdictFor, withIgnoreFile } from "#inventory/ignore-scope.ts";
4
+ import { emptyScope, type IgnoreScope, verdictFor, withIgnoreFile } from "#inventory/ignoreScope.ts";
5
5
  import type { RuleInputs } from "#rule.ts";
6
6
  import type { ImportGraph, UnresolvedImport } from "./graph.ts";
7
7
 
@@ -2,7 +2,7 @@ import { realpathSync } from "node:fs";
2
2
  import { isBuiltin } from "node:module";
3
3
  import { dirname, join, relative } from "node:path";
4
4
  import ts from "typescript";
5
- import { posix } from "#inventory/ignore-scope.ts";
5
+ import { posix } from "#inventory/ignoreScope.ts";
6
6
  import type { Ambient } from "./ambient.ts";
7
7
  import type { ImportRequest } from "./extract.ts";
8
8
  import type { Project } from "./projects.ts";
@@ -4,7 +4,7 @@ import { Effect } from "effect";
4
4
  import { manifestsIn } from "#manifests/sorted.ts";
5
5
  import type { RuleInputs } from "#rule.ts";
6
6
  import { globMatcher } from "./glob.ts";
7
- import { pnpmWorkspacePatterns } from "./pnpm-workspace.ts";
7
+ import { pnpmWorkspacePatterns } from "./pnpmWorkspacePatterns.ts";
8
8
 
9
9
  export interface WorkspacePackage {
10
10
  readonly directory: string;
@@ -3,7 +3,7 @@ import { Effect, FileSystem } from "effect";
3
3
  import ignore from "ignore";
4
4
  import type { SourceFile } from "#rule.ts";
5
5
  import { FilesystemFailure, orWhenAbsent, readRequiredText } from "./filesystem.ts";
6
- import { posix } from "./ignore-scope.ts";
6
+ import { posix } from "./ignoreScope.ts";
7
7
  import { scopeAbove, walk } from "./walk.ts";
8
8
 
9
9
  export interface InventoryScope {
@@ -1,7 +1,7 @@
1
1
  import { dirname, join, relative, sep } from "node:path";
2
2
  import { Effect, FileSystem } from "effect";
3
3
  import { FilesystemFailure, orWhenAbsent, readOptionalText } from "./filesystem.ts";
4
- import { emptyScope, type IgnoreScope, insideKept, verdictFor, withIgnoreFile } from "./ignore-scope.ts";
4
+ import { emptyScope, type IgnoreScope, insideKept, verdictFor, withIgnoreFile } from "./ignoreScope.ts";
5
5
  import { trackedPaths } from "./trackedPaths.ts";
6
6
 
7
7
  const SKIPPED = new Set([".git", "node_modules"]);
@@ -2,7 +2,7 @@ import { basename, join, relative } from "node:path";
2
2
  import { Effect, FileSystem } from "effect";
3
3
  import { sortPackageJson } from "sort-package-json";
4
4
  import { FilesystemFailure } from "#inventory/filesystem.ts";
5
- import { posix } from "#inventory/ignore-scope.ts";
5
+ import { posix } from "#inventory/ignoreScope.ts";
6
6
  import { walk } from "#inventory/walk.ts";
7
7
 
8
8
  export type Sorting = { readonly _tag: "Invalid" } | { readonly _tag: "Sorted" } | { readonly _tag: "Unsorted"; readonly sorted: string };
@@ -4,18 +4,13 @@ import { groupBy, keyOf, type Violation } from "#engine/violation.ts";
4
4
  import { plural } from "./plural.ts";
5
5
  import { staleSections } from "./stale.ts";
6
6
 
7
- export type WarningDetail = "summary" | "all";
8
-
9
7
  export interface ReportContext {
10
8
  readonly baseline: string;
11
9
  readonly checked: number;
12
10
  readonly descriptions: ReadonlyMap<string, string>;
13
11
  readonly registry: string;
14
- readonly warnings: WarningDetail;
15
12
  }
16
13
 
17
- const LISTED_FILES = 5;
18
-
19
14
  function locate(violation: Violation): string {
20
15
  return violation.line === undefined ? violation.file : `${violation.file}:${violation.line}`;
21
16
  }
@@ -24,9 +19,9 @@ function regressionNote(regression: Regression): string {
24
19
  return ` ${regression.entry.file} is over its baseline: ${regression.count} against ${regression.entry.count} baselined.`;
25
20
  }
26
21
 
27
- function heading(label: string, rule: string, violations: readonly Violation[], context: ReportContext): readonly string[] {
22
+ function heading(rule: string, violations: readonly Violation[], context: ReportContext): readonly string[] {
28
23
  const description = context.descriptions.get(rule);
29
- return [`${label} ${rule} (${violations.length})`, ...(description === undefined ? [] : [` ${description}`])];
24
+ return [`error ${rule} (${violations.length})`, ...(description === undefined ? [] : [` ${description}`])];
30
25
  }
31
26
 
32
27
  function detailed(violations: readonly Violation[], regressions: ReadonlyMap<string, Regression>): readonly string[] {
@@ -40,21 +35,9 @@ function detailed(violations: readonly Violation[], regressions: ReadonlyMap<str
40
35
  });
41
36
  }
42
37
 
43
- function summarized(violations: readonly Violation[]): readonly string[] {
44
- const files = [...groupBy(violations, (violation) => violation.file).entries()].sort(([, left], [, right]) => right.length - left.length);
45
- const listed = files.slice(0, LISTED_FILES).map(([file, inFile]) => `${file} (${inFile.length})`);
46
- const rest = files.length - listed.length;
47
- return [` ${listed.join(", ")}${rest > 0 ? `, and ${plural(rest, "more file", "more files")}` : ""}. --warnings all lists each one.`];
48
- }
49
-
50
- function ruleSections(
51
- label: string,
52
- violations: readonly Violation[],
53
- context: ReportContext,
54
- body: (inRule: readonly Violation[]) => readonly string[],
55
- ): readonly string[] {
38
+ function ruleSections(violations: readonly Violation[], context: ReportContext, regressions: ReadonlyMap<string, Regression>): readonly string[] {
56
39
  return [...groupBy(violations, (violation) => violation.rule).entries()].map(([rule, inRule]) =>
57
- [...heading(label, rule, inRule, context), ...body(inRule)].join("\n"),
40
+ [...heading(rule, inRule, context), ...detailed(inRule, regressions)].join("\n"),
58
41
  );
59
42
  }
60
43
 
@@ -68,14 +51,13 @@ function failures(outcome: Outcome): string {
68
51
 
69
52
  function summary(outcome: Outcome, context: ReportContext): string {
70
53
  const verdict = passes(outcome) ? "quality: passed" : `quality: failed with ${failures(outcome)}`;
71
- const warnings = outcome.warnings.length > 0 ? `; ${plural(outcome.warnings.length, "warning")} from rules still at warn` : "";
72
54
  const hidden = [
73
55
  ...(outcome.baselined > 0 ? [`${outcome.baselined} baselined`] : []),
74
56
  ...(outcome.registered > 0 ? [`${outcome.registered} registered`] : []),
75
57
  ];
76
58
  const suppressed =
77
59
  hidden.length === 0 ? "" : `; ${hidden.join(" and ")} ${outcome.baselined + outcome.registered === 1 ? "violation" : "violations"} not shown`;
78
- return `${verdict}${warnings}. ${plural(context.checked, "source file")} checked${suppressed}.`;
60
+ return `${verdict}. ${plural(context.checked, "source file")} checked${suppressed}.`;
79
61
  }
80
62
 
81
63
  function rerecord(outcome: Outcome): readonly string[] {
@@ -91,10 +73,8 @@ function rerecord(outcome: Outcome): readonly string[] {
91
73
 
92
74
  export function render(outcome: Outcome, context: ReportContext): string {
93
75
  const regressions = new Map(outcome.regressions.map((regression) => [keyOf(regression.entry.rule, regression.entry.file), regression]));
94
- const warningBody = context.warnings === "all" ? (inRule: readonly Violation[]) => detailed(inRule, regressions) : summarized;
95
76
  return [
96
- ...ruleSections("error", outcome.errors, context, (inRule) => detailed(inRule, regressions)),
97
- ...ruleSections("warn", outcome.warnings, context, warningBody),
77
+ ...ruleSections(outcome.errors, context, regressions),
98
78
  ...staleSections(outcome, context),
99
79
  summary(outcome, context),
100
80
  ...rerecord(outcome),
@@ -27,7 +27,7 @@ export function staleSections(outcome: Outcome, files: StaleFiles): readonly str
27
27
  ...section(
28
28
  "error",
29
29
  files.baseline,
30
- "An entry for a rule that is off or unknown covers nothing. Run `quality baseline prune` to drop it.",
30
+ "An entry for an unknown rule covers nothing. Run `quality baseline prune` to drop it.",
31
31
  outcome.staleBaseline.map(baselineLine),
32
32
  ),
33
33
  ...section(
package/src/rule.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { Bivariant } from "@shivaedev/types/bivariant.ts";
2
2
  import type { ExceptionDeclaration } from "#exceptions/declaration.ts";
3
- import { describeIssue, type StandardSchemaV1 } from "./standard-schema.ts";
3
+ import { describeIssue, type StandardSchemaV1 } from "./standardSchema.ts";
4
4
 
5
5
  export interface Finding {
6
6
  readonly count?: number | undefined;
@@ -1,10 +1,10 @@
1
- import { maxPerFile } from "#rules/comments/max-per-file.ts";
2
- import { noBanner } from "#rules/comments/no-banner.ts";
3
- import { noEnvironmentPragma } from "#rules/comments/no-environment-pragma.ts";
4
- import { noJsdoc } from "#rules/comments/no-jsdoc.ts";
5
- import { noLineReference } from "#rules/comments/no-line-reference.ts";
6
- import { noPrReference } from "#rules/comments/no-pr-reference.ts";
7
- import { noTodo } from "#rules/comments/no-todo.ts";
1
+ import { maxPerFile } from "#rules/comments/maxPerFile.ts";
2
+ import { noBanner } from "#rules/comments/noBanner.ts";
3
+ import { noEnvironmentPragma } from "#rules/comments/noEnvironmentPragma.ts";
4
+ import { noJsdoc } from "#rules/comments/noJsdoc.ts";
5
+ import { noLineReference } from "#rules/comments/noLineReference.ts";
6
+ import { noPrReference } from "#rules/comments/noPrReference.ts";
7
+ import { noTodo } from "#rules/comments/noTodo.ts";
8
8
  import { distinctCase } from "#rules/files/distinctCase.ts";
9
9
  import { folderNames } from "#rules/files/folderNames.ts";
10
10
  import { namedAfterExport } from "#rules/files/namedAfterExport.ts";
@@ -18,17 +18,18 @@ import { importsResolvable } from "#rules/imports/resolvable.ts";
18
18
  import { importsRuntime } from "#rules/imports/runtime.ts";
19
19
  import { storySetup } from "#rules/stories/setup.ts";
20
20
  import { storySpecs } from "#rules/stories/specs.ts";
21
- import { biomeOverrides } from "#rules/suppressions/biome-overrides.ts";
21
+ import { biomeOverrides } from "#rules/suppressions/biomeOverrides.ts";
22
22
  import { biomeRecommended } from "#rules/suppressions/biomeRecommended.ts";
23
- import { noDoubleCast } from "#rules/suppressions/no-double-cast.ts";
24
- import { noInline } from "#rules/suppressions/no-inline.ts";
23
+ import { noDoubleCast } from "#rules/suppressions/noDoubleCast.ts";
25
24
  import { noIgnoreDeprecations } from "#rules/suppressions/noIgnoreDeprecations.ts";
25
+ import { noInline } from "#rules/suppressions/noInline.ts";
26
26
  import { testsColocated } from "#rules/test-names/colocated.ts";
27
27
  import { testsFollow } from "#rules/test-names/follow.ts";
28
28
  import { biome } from "./biome.ts";
29
- import { manifestsSorted } from "./manifests-sorted.ts";
30
- import { maxLines } from "./max-lines.ts";
29
+ import { manifestsSorted } from "./manifestsSorted.ts";
30
+ import { manifestsSourceFirst } from "./manifestsSourceFirst.ts";
31
31
  import { maxDepth } from "./maxDepth.ts";
32
+ import { maxLines } from "./maxLines.ts";
32
33
  import { noBarrel } from "./noBarrel.ts";
33
34
 
34
35
  export const builtInRules = [
@@ -56,6 +57,7 @@ export const builtInRules = [
56
57
  importsAliased,
57
58
  noTestCode,
58
59
  manifestsSorted,
60
+ manifestsSourceFirst,
59
61
  namedAfterExport,
60
62
  folderNames,
61
63
  distinctCase,
@@ -1,4 +1,4 @@
1
- import { definePatternRule } from "./pattern-rule.ts";
1
+ import { definePatternRule } from "./definePattern.ts";
2
2
 
3
3
  const DIVIDER = "[-=*#~_+/\\\\─━═┄┈]{3,}";
4
4
 
@@ -1,4 +1,4 @@
1
- import { definePatternRule } from "./pattern-rule.ts";
1
+ import { definePatternRule } from "./definePattern.ts";
2
2
 
3
3
  export const noEnvironmentPragma = definePatternRule({
4
4
  description:
@@ -1,4 +1,4 @@
1
- import { definePatternRule } from "./pattern-rule.ts";
1
+ import { definePatternRule } from "./definePattern.ts";
2
2
 
3
3
  const SOURCE_EXTENSION =
4
4
  "(?:[cm]?[jt]sx?|json5?|mdx?|css|scss|less|html?|vue|svelte|astro|ya?ml|toml|sql|prisma|graphql|gql|go|rs|py|rb|java|kt|swift|sh)";
@@ -1,4 +1,4 @@
1
- import { definePatternRule } from "./pattern-rule.ts";
1
+ import { definePatternRule } from "./definePattern.ts";
2
2
 
3
3
  export const noPrReference = definePatternRule({
4
4
  description: "History belongs in version control, not in the code. State the reason itself, so the comment holds without the link.",
@@ -1,4 +1,4 @@
1
- import { definePatternRule } from "./pattern-rule.ts";
1
+ import { definePatternRule } from "./definePattern.ts";
2
2
 
3
3
  export const noTodo = definePatternRule({
4
4
  description: "A TODO in the code is never done. Do the work now, or track it where the repository tracks work.",
@@ -0,0 +1,48 @@
1
+ import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem";
2
+ import { Effect } from "effect";
3
+ import { manifestsIn } from "#manifests/sorted.ts";
4
+ import { defineRule, type Finding } from "#rule.ts";
5
+ import { entriesOf, itemsOf, type Json, member, parseJsonc } from "#rules/suppressions/biome/json.ts";
6
+
7
+ const CONDITION = "source";
8
+
9
+ function misplaced(path: string, field: string, node: Json): readonly Finding[] {
10
+ const conditions = entriesOf(node);
11
+ const first = conditions[0]?.[0];
12
+ const own: readonly Finding[] =
13
+ first === CONDITION || !conditions.some(([key]) => key === CONDITION)
14
+ ? []
15
+ : [
16
+ {
17
+ file: path,
18
+ line: node.line,
19
+ message: `Lists the "${CONDITION}" condition after "${first}" in ${field}. TypeScript takes the first condition that matches, so once built output exists it reads that instead of the sources the "${CONDITION}" condition names. Move "${CONDITION}" to the top of this condition block.`,
20
+ subject: field,
21
+ },
22
+ ];
23
+ const nested = [...conditions.map(([, value]) => value), ...itemsOf(node)];
24
+ return [...own, ...nested.flatMap((value) => misplaced(path, field, value))];
25
+ }
26
+
27
+ function findingsIn(path: string, text: string): readonly Finding[] {
28
+ const parsed = parseJsonc(path, text);
29
+ if (parsed._tag !== "Parsed") {
30
+ return [];
31
+ }
32
+ return ["exports", "imports"].flatMap((field) => {
33
+ const map = member(parsed.json, field);
34
+ return map === undefined ? [] : misplaced(path, field, map);
35
+ });
36
+ }
37
+
38
+ export const manifestsSourceFirst = defineRule({
39
+ check: async ({ readText, root }) => {
40
+ const manifests = await Effect.runPromise(manifestsIn(root).pipe(Effect.provide(NodeFileSystem.layer)));
41
+ const texts = await Promise.all(manifests.map(async (path) => ({ path, text: (await readText(path)) ?? "" })));
42
+ return texts.filter(({ text }) => text.includes(`"${CONDITION}"`)).flatMap(({ path, text }) => findingsIn(path, text));
43
+ },
44
+ description:
45
+ 'Every package.json condition block that names the "source" condition lists it first in exports and imports, so TypeScript reads the sources whether or not built output exists.',
46
+ id: "manifests/source-first",
47
+ registrable: false,
48
+ });
@@ -1,7 +1,7 @@
1
1
  import { relative } from "node:path";
2
2
  import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem";
3
3
  import { Effect } from "effect";
4
- import { posix } from "#inventory/ignore-scope.ts";
4
+ import { posix } from "#inventory/ignoreScope.ts";
5
5
  import { walk } from "#inventory/walk.ts";
6
6
  import { defineRule, type Finding } from "#rule.ts";
7
7
  import { member, parseJsonc } from "#rules/suppressions/biome/json.ts";
@@ -1,7 +1,7 @@
1
1
  import { defineRule, type Finding, type RuleInputs } from "#rule.ts";
2
2
  import { type SourceComment, scanComments } from "#rules/comments/scan.ts";
3
3
  import { suppressionIn } from "./directives.ts";
4
- import { STYLESHEET, stylesheetComments } from "./stylesheet-comments.ts";
4
+ import { STYLESHEET, stylesheetComments } from "./stylesheetComments.ts";
5
5
 
6
6
  const TYPE_TEST = /(?:(?:^|\/)typecheck\.test|\.typecheck\.(?:test|spec))\.[cm]?[jt]sx?$/u;
7
7