@gspothq/cli 0.1.1 → 0.2.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 (205) hide show
  1. package/README.md +58 -11
  2. package/configurations/database/postgres/manifest.toml +51 -57
  3. package/configurations/database/postgres/rules/POSTGRES.md +14 -13
  4. package/configurations/framework/astro/manifest.toml +33 -35
  5. package/configurations/framework/astro/rules/ASTRO.md +2 -2
  6. package/configurations/framework/expo/manifest.toml +19 -19
  7. package/configurations/framework/express/manifest.toml +10 -4
  8. package/configurations/framework/express/rules/EXPRESS.md +9 -7
  9. package/configurations/framework/fastapi/manifest.toml +9 -3
  10. package/configurations/framework/fastapi/rules/FASTAPI.md +19 -18
  11. package/configurations/framework/nestjs/manifest.toml +12 -12
  12. package/configurations/framework/nestjs/rules/NESTJS.md +9 -9
  13. package/configurations/framework/nextjs/manifest.toml +39 -79
  14. package/configurations/framework/nextjs/rules/NEXTJS.md +9 -7
  15. package/configurations/framework/nextjs/tool-files/semgrep/nextjs.yml +35 -0
  16. package/configurations/framework/react/manifest.toml +33 -43
  17. package/configurations/framework/react/rules/REACT.md +14 -20
  18. package/configurations/framework/react-dom/manifest.toml +6 -6
  19. package/configurations/framework/react-native/manifest.toml +11 -11
  20. package/configurations/framework/react-native/rules/REACT-NATIVE.md +3 -5
  21. package/configurations/framework/site/manifest.toml +57 -110
  22. package/configurations/framework/site/rules/SITE.md +1 -1
  23. package/configurations/framework/svelte/manifest.toml +29 -31
  24. package/configurations/framework/svelte/rules/SVELTE.md +6 -6
  25. package/configurations/framework/vue/manifest.toml +37 -37
  26. package/configurations/framework/vue/rules/VUE.md +6 -6
  27. package/configurations/general/commits/manifest.toml +20 -84
  28. package/configurations/general/commits/rules/GIT.md +24 -13
  29. package/configurations/general/coverage/manifest.toml +1 -1
  30. package/configurations/general/dependencies/manifest.toml +47 -107
  31. package/configurations/general/dependencies/rules/DEPENDENCIES.md +13 -7
  32. package/configurations/general/docs/manifest.toml +28 -43
  33. package/configurations/general/docs/rules/DOCS.md +16 -9
  34. package/configurations/general/duplication/manifest.toml +12 -14
  35. package/configurations/general/engineering/manifest.toml +6 -2
  36. package/configurations/general/engineering/rules/agent/PLANNING.md +9 -6
  37. package/configurations/general/engineering/rules/agent/SUPPRESSIONS.md +20 -11
  38. package/configurations/general/engineering/rules/agent/TASKS.md +6 -2
  39. package/configurations/general/engineering/rules/agent/WORKING.md +34 -29
  40. package/configurations/general/engineering/rules/code/ACCESSIBILITY.md +9 -7
  41. package/configurations/general/engineering/rules/code/CLI.md +12 -9
  42. package/configurations/general/engineering/rules/code/COMMENTS.md +11 -1
  43. package/configurations/general/engineering/rules/code/CONFIGURATION.md +2 -0
  44. package/configurations/general/engineering/rules/code/ERRORS.md +5 -3
  45. package/configurations/general/engineering/rules/code/HTTP.md +9 -10
  46. package/configurations/general/engineering/rules/code/LOGGING.md +10 -9
  47. package/configurations/general/engineering/rules/code/TESTING.md +18 -11
  48. package/configurations/general/files/manifest.toml +45 -73
  49. package/configurations/general/files/rules/YAML.md +20 -10
  50. package/configurations/general/format/manifest.toml +53 -106
  51. package/configurations/general/gspot/manifest.toml +19 -39
  52. package/configurations/general/gspot/rules/GENERATED.md +14 -4
  53. package/configurations/general/licenses/manifest.toml +12 -14
  54. package/configurations/general/naming/defaults.json +14 -13
  55. package/configurations/general/naming/manifest.toml +17 -17
  56. package/configurations/general/naming/rules/NAMING.md +87 -67
  57. package/configurations/general/prose/manifest.toml +166 -25
  58. package/configurations/general/prose/rules/WRITING.md +6 -2
  59. package/configurations/general/repository/manifest.toml +12 -12
  60. package/configurations/general/secrets/manifest.toml +52 -73
  61. package/configurations/general/secrets/rules/SECRETS.md +3 -1
  62. package/configurations/general/security/manifest.toml +29 -52
  63. package/configurations/general/security/rules/SECURITY.md +8 -6
  64. package/configurations/general/spelling/manifest.toml +15 -25
  65. package/configurations/general/structure/manifest.toml +31 -31
  66. package/configurations/infrastructure/ansible/manifest.toml +15 -15
  67. package/configurations/infrastructure/docker/manifest.toml +55 -67
  68. package/configurations/infrastructure/docker/rules/DOCKER.md +15 -13
  69. package/configurations/infrastructure/github-actions/manifest.toml +21 -41
  70. package/configurations/infrastructure/github-actions/rules/GITHUB-ACTIONS.md +16 -12
  71. package/configurations/infrastructure/github-actions/tool-files/zizmor.yml +5 -0
  72. package/configurations/infrastructure/nginx/manifest.toml +20 -20
  73. package/configurations/infrastructure/nginx/rules/NGINX.md +5 -4
  74. package/configurations/infrastructure/openapi/manifest.toml +20 -20
  75. package/configurations/infrastructure/openapi/rules/OPENAPI.md +3 -1
  76. package/configurations/infrastructure/xcode/manifest.toml +55 -75
  77. package/configurations/infrastructure/xcode/rules/XCODE.md +5 -3
  78. package/configurations/language/bash/manifest.toml +89 -170
  79. package/configurations/language/bash/rules/BASH.md +79 -17
  80. package/configurations/language/bash/rules/LANGUAGE.md +30 -26
  81. package/configurations/language/bash/rules/OPERATIONS.md +10 -8
  82. package/configurations/language/bash/rules/SAFETY.md +39 -35
  83. package/configurations/language/css/manifest.toml +22 -61
  84. package/configurations/language/css/rules/CSS.md +21 -2
  85. package/configurations/language/css/rules/TAILWIND.md +7 -5
  86. package/configurations/language/html/manifest.toml +16 -35
  87. package/configurations/language/html/rules/HTML.md +23 -5
  88. package/configurations/language/javascript/eslint-runtime-names.json +66 -61
  89. package/configurations/language/javascript/eslint-runtime.mjs +118 -0
  90. package/configurations/language/javascript/manifest.toml +135 -207
  91. package/configurations/language/javascript/rules/BUN.md +2 -2
  92. package/configurations/language/javascript/rules/COMPONENTS.md +4 -4
  93. package/configurations/language/javascript/rules/DENO.md +1 -1
  94. package/configurations/language/javascript/rules/JAVASCRIPT.md +30 -17
  95. package/configurations/language/javascript/rules/NODE.md +2 -2
  96. package/configurations/language/javascript/rules/PLAYWRIGHT.md +10 -9
  97. package/configurations/language/markdown/manifest.toml +20 -51
  98. package/configurations/language/python/manifest.toml +231 -342
  99. package/configurations/language/python/rules/DESIGN.md +40 -33
  100. package/configurations/language/python/rules/FLOW.md +8 -6
  101. package/configurations/language/python/rules/PACKAGING.md +14 -7
  102. package/configurations/language/python/rules/PYTHON.md +83 -33
  103. package/configurations/language/python/rules/TYPING.md +25 -23
  104. package/configurations/language/sql/manifest.toml +19 -37
  105. package/configurations/language/sql/rules/SQL.md +90 -2
  106. package/configurations/language/swift/manifest.toml +67 -78
  107. package/configurations/language/swift/rules/SWIFT.md +138 -40
  108. package/configurations/language/swift/rules/SWIFTUI.md +11 -9
  109. package/configurations/language/swift/rules/UIKIT.md +21 -19
  110. package/configurations/language/typescript/manifest.toml +34 -34
  111. package/configurations/language/typescript/rules/TYPESCRIPT.md +62 -10
  112. package/configurations/library/drizzle/manifest.toml +25 -38
  113. package/configurations/library/drizzle/rules/DRIZZLE.md +4 -2
  114. package/configurations/library/react-hook-form/manifest.toml +4 -4
  115. package/configurations/library/react-hook-form/rules/REACT-HOOK-FORM.md +15 -13
  116. package/configurations/library/tanstack-query/manifest.toml +6 -6
  117. package/configurations/library/tanstack-query/rules/TANSTACK-QUERY.md +5 -3
  118. package/configurations/library/testing-library/manifest.toml +6 -6
  119. package/configurations/library/translations/manifest.toml +22 -22
  120. package/configurations/library/translations/rules/NEXT-INTL.md +6 -8
  121. package/configurations/library/translations/rules/TRANSLATIONS.md +22 -23
  122. package/configurations/library/trpc/manifest.toml +3 -3
  123. package/configurations/library/trpc/rules/TRPC.md +8 -6
  124. package/configurations/library/zod/manifest.toml +6 -6
  125. package/configurations/library/zod/rules/ZOD.md +4 -2
  126. package/configurations/library/zustand/manifest.toml +4 -4
  127. package/configurations/library/zustand/rules/ZUSTAND.md +16 -14
  128. package/configurations/platform/cloudflare/manifest.toml +28 -47
  129. package/configurations/platform/cloudflare/rules/CLOUDFLARE.md +11 -6
  130. package/configurations/platform/supabase/manifest.toml +48 -61
  131. package/configurations/platform/supabase/rules/SUPABASE.md +27 -28
  132. package/configurations/testing/jest/manifest.toml +21 -22
  133. package/configurations/testing/pytest/manifest.toml +28 -28
  134. package/configurations/testing/swift-tests/manifest.toml +18 -29
  135. package/configurations/testing/swift-tests/rules/SWIFT-TESTS.md +7 -5
  136. package/configurations/testing/vitest/manifest.toml +32 -32
  137. package/configurations/testing/vitest/rules/VITEST.md +3 -1
  138. package/dist/gspot.js +22297 -24707
  139. package/dist/{linkinator-program.js → linkinator-process.js} +5 -7
  140. package/dist/{purgecss-program.js → purgecss-process.js} +12 -12
  141. package/package.json +7 -9
  142. package/configurations/infrastructure/github-actions/zizmor.yml +0 -3
  143. package/configurations/language/bash/rules/NAMING.md +0 -62
  144. package/configurations/language/css/rules/NAMING.md +0 -17
  145. package/configurations/language/html/rules/NAMING.md +0 -16
  146. package/configurations/language/javascript/rules/NAMING.md +0 -31
  147. package/configurations/language/markdown/markdownlint-cli2.mjs +0 -19
  148. package/configurations/language/python/rules/NAMING.md +0 -53
  149. package/configurations/language/sql/rules/NAMING.md +0 -90
  150. package/configurations/language/swift/rules/NAMING.md +0 -88
  151. package/configurations/language/typescript/rules/NAMING.md +0 -73
  152. package/configurations/library/swift-snapshot-testing/manifest.toml +0 -32
  153. package/dist/THIRD-PARTY-NOTICES.md +0 -25
  154. package/dist/eslint-rule-levels.json +0 -10
  155. package/dist/tool-versions.json +0 -3
  156. package/gspot.schema.json +0 -45991
  157. /package/{dist/LICENSE.md → LICENSE.md} +0 -0
  158. /package/configurations/framework/express/{semgrep → tool-files/semgrep}/express.yml +0 -0
  159. /package/configurations/framework/fastapi/{semgrep → tool-files/semgrep}/fastapi.yml +0 -0
  160. /package/configurations/general/dependencies/{syncpack.json → tool-files/syncpack.json} +0 -0
  161. /package/configurations/general/prose/{vale → tool-files/vale}/styles/LICENSES.md +0 -0
  162. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/ampm.yml +0 -0
  163. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/conscious-language.yml +0 -0
  164. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/contractions.yml +0 -0
  165. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/currency.yml +0 -0
  166. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/dashes.yml +0 -0
  167. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/date-ordinals.yml +0 -0
  168. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/dates.yml +0 -0
  169. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/file-paths.yml +0 -0
  170. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/future.yml +0 -0
  171. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/hedging.yml +0 -0
  172. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/history.yml +0 -0
  173. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/idioms.yml +0 -0
  174. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/interface-verbs.yml +0 -0
  175. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/jargon.yml +0 -0
  176. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/leading-conjunctions.yml +0 -0
  177. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/link-text.yml +0 -0
  178. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/locations.yml +0 -0
  179. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/marketing.yml +0 -0
  180. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/merge-conflict-markers.yml +0 -0
  181. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/militaristic-language.yml +0 -0
  182. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/modals.yml +0 -0
  183. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/numbered-units.yml +0 -0
  184. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/obvious-fields.yml +0 -0
  185. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/ordinal-adverbs.yml +0 -0
  186. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/percentage-numbers.yml +0 -0
  187. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/placeholders.yml +0 -0
  188. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/product-centric-writing.yml +0 -0
  189. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/punctuated-headings.yml +0 -0
  190. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/self-reference.yml +0 -0
  191. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/session-identifiers.yml +0 -0
  192. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/since.yml +0 -0
  193. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/straight-quotes.yml +0 -0
  194. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/suspended-hyphens.yml +0 -0
  195. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/symbols.yml +0 -0
  196. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/time-ranges.yml +0 -0
  197. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/url-prepositions.yml +0 -0
  198. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/version-range.yml +0 -0
  199. /package/configurations/general/secrets/{gitleaks.toml → tool-files/gitleaks.toml} +0 -0
  200. /package/configurations/infrastructure/docker/{trivyignore → tool-files/trivyignore} +0 -0
  201. /package/configurations/language/bash/{semgrep → tool-files/semgrep}/bash.yml +0 -0
  202. /package/configurations/language/javascript/{semgrep → tool-files/semgrep}/javascript.yml +0 -0
  203. /package/configurations/language/swift/{semgrep → tool-files/semgrep}/swift.yml +0 -0
  204. /package/configurations/platform/cloudflare/{semgrep → tool-files/semgrep}/cloudflare.yml +0 -0
  205. /package/configurations/platform/supabase/{semgrep → tool-files/semgrep}/supabase.yml +0 -0
@@ -1,5 +1,7 @@
1
1
  # Testing
2
2
 
3
+ Read this rule when you write or change a test.
4
+
3
5
  Tests exist to catch bugs. A useful test fails when the behavior it covers breaks.
4
6
 
5
7
  ## Assertions
@@ -7,20 +9,23 @@ Tests exist to catch bugs. A useful test fails when the behavior it covers break
7
9
  - Use Arrange, Act, Assert. Test behavior, not private implementation details.
8
10
  - Assert exact values that the public interface defines, such as status codes, exit codes, and
9
11
  messages. Do not pin incidental configuration or internal representation.
10
- - Cover relevant empty and null inputs, limits, expected errors, and unexpected internal errors.
11
- - Assert every changed outcome: responses, stored rows, outbound requests, side effects, and logs.
12
- - A test has meaningful assertions; it does not merely prove that the code called a collaborator or
13
- that a mock returns the value supplied to it.
12
+ - Cover relevant empty and null inputs, limits, expected errors, and unexpected internal ones.
13
+ - Assert every changed result: responses, stored rows, outbound requests, side effects, and logs.
14
+ - A test has meaningful assertions; it does not only prove that the code called a collaborator or
15
+ that a mock returns its input.
14
16
  - Use snapshots only for stable data, and review every change to them.
15
17
  - Do not add test-only authentication bypasses, magic headers, or bypass routes.
18
+ - Do not write a test that only repeats a constant, a table, or a configuration value. A test runs code and checks
19
+ its result.
20
+ - Do not export a function only so that a test can call it. Test it through the public function that uses it.
16
21
 
17
22
  ## Mocks
18
23
 
19
24
  - Mock only what leaves the process: network, filesystem, subprocesses, clock, and database.
20
25
  Never mock the code under test or provider SDK internals.
21
- - Mock the module that talks to the network or database. Use dependency injection when the
22
- code declares the dependencies. Replace that whole module rather than hiding selected behavior.
23
- - Keep mocks that affect the outcome in the arrange step. Reset or redefine shared mocks before
26
+ - Mock the module that calls the network or database. Use dependency injection when the
27
+ code declares the dependencies. Replace that whole module rather than hiding parts of its behavior.
28
+ - Keep mocks that affect the result in the arrange step. Reset or redefine shared mocks before
24
29
  each test; do not use surprising global auto-mocks.
25
30
  - Restore environment variables, globals, fake timers, and spies changed by a test.
26
31
 
@@ -28,10 +33,10 @@ Tests exist to catch bugs. A useful test fails when the behavior it covers break
28
33
 
29
34
  <!-- level: all -->
30
35
 
31
- - Follow the framework or runner's test layout and keep one layout in each repository.
32
- - Put builders, fakes, servers, and database support in the declared test support folder, never
36
+ - Follow the test layout of the framework or runner, and keep one per repository.
37
+ - Put builders, fakes, servers, and database code in the declared test support folder, never
33
38
  in `mocks/`, `helpers/`, or `utils/`. Support files contain no assertions or test blocks.
34
- - A test name states the scenario and expected outcome. Never use `test1`, `works`, `edge cases`,
39
+ - A test name states the scenario and expected result. Never use `test1`, `works`, `edge cases`,
35
40
  or `happy path`. Group tests by unit, then scenario.
36
41
  - Prefer role and label queries. Use a test ID last; name it in camelCase for its control, such
37
42
  as `submitButton`. Never put visible text, user data, or record IDs in it.
@@ -44,9 +49,11 @@ Tests exist to catch bugs. A useful test fails when the behavior it covers break
44
49
  in a shared database.
45
50
  - Do not share mutable IDs between tests or count unrelated data. Add unrelated records when a
46
51
  test must prove that the code leaves them unchanged.
47
- - Use unique queue names, event IDs, operation IDs, or correlation IDs for event-driven tests.
52
+ - Use unique queue names and event, operation, or correlation IDs for event-driven tests.
48
53
  Never purge shared queues or tables as a substitute for isolated data.
49
54
  - Do not use fixed sleeps. Use bounded polling, fake timers, or a signal that proves completion.
55
+ - Test data does not copy the current version of the project or of a tool. Read the version from the dependency
56
+ file, or use a value outside real releases, such as `0.0.0-test`.
50
57
 
51
58
  ## Network and providers
52
59
 
@@ -1,141 +1,113 @@
1
1
  allowed_words = ["JSON", "TOML", "YAML"]
2
+
2
3
  [configuration]
3
- title = "JSON, YAML, TOML, and XML files"
4
4
  always_selected = true
5
- description = "Checks JSON, YAML, TOML, XML, and related formats. Its tool files configure the tools that read these files."
5
+ description = "Checks JSON, YAML, TOML, XML, and related formats, and writes a tool file for each checker."
6
+ title = "JSON, YAML, TOML, and XML files"
6
7
 
7
8
  [files]
8
9
  extensions = [".json", ".jsonc", ".json5", ".yaml", ".yml", ".toml", ".xml"]
9
10
 
10
11
  [[tool]]
11
- name = "taplo"
12
- version = "0.10.0"
13
- min_version = "0.9.0"
14
- mise = "taplo"
15
12
  brew = "taplo"
16
13
  cargo = "taplo-cli"
14
+ min_version = "0.9.0"
15
+ mise = "taplo"
16
+ name = "taplo"
17
+ replace = ["taplo.toml", ".taplo.toml"]
18
+ version = "0.10.0"
17
19
  # No npm pin: the npm build of Taplo checks no file on Windows, so every platform takes the native release.
18
20
  github = { name = "tamasfe/taplo", version = "0.10.0" }
19
- [[tool.replace]]
20
- file = "taplo.toml"
21
- shared = false
22
-
23
- [[tool.replace]]
24
- file = ".taplo.toml"
25
- shared = false
26
21
 
27
22
  [[tool]]
28
- name = "yamllint"
29
- version = "1.38.0"
23
+ brew = "yamllint"
30
24
  mise = "pipx:yamllint"
25
+ name = "yamllint"
31
26
  pypi = "yamllint"
32
- brew = "yamllint"
33
- [[tool.replace]]
34
- file = ".yamllint"
35
- shared = false
36
-
37
- [[tool.replace]]
38
- file = ".yamllint.yml"
39
- shared = false
40
-
41
- [[tool.replace]]
42
- file = ".yamllint.yaml"
43
- shared = false
27
+ replace = [".yamllint", ".yamllint.yml", ".yamllint.yaml"]
28
+ version = "1.38.0"
44
29
 
45
30
  [[tool]]
31
+ mise = "npm:v8r"
46
32
  name = "v8r"
33
+ npm = "v8r"
47
34
  requires = ["ajv"]
48
35
  version = "6.1.0"
49
- mise = "npm:v8r"
50
- npm = "v8r"
51
36
 
52
37
  # v8r imports this optional peer when it loads ajv-draft-04. Tool projects must install it.
53
38
 
54
39
  [[tool]]
55
- name = "ajv"
56
40
  kind = "library"
57
- version = "8.20.0"
41
+ name = "ajv"
58
42
  npm = "ajv"
43
+ version = "8.20.0"
59
44
 
60
45
  [[tool]]
46
+ apt = "libxml2-utils"
47
+ brew = "libxml2"
61
48
  name = "xmllint"
62
49
  system = true
63
- brew = "libxml2"
64
- apt = "libxml2-utils"
65
50
 
66
51
  [[tool_file]]
67
52
  target = ".gspot/config/taplo.toml"
68
53
  tool = "taplo"
69
54
 
70
55
  [[tool_file]]
56
+ per_scope = true
71
57
  target = ".gspot/config/yamllint.yml"
72
58
  tool = "yamllint"
73
- per_scope = true
74
- rule_keys = ["rules"]
75
59
 
76
60
  [[tool_file]]
77
61
  target = ".gspot/config/v8r.yml"
78
62
  tool = "v8r"
79
63
 
80
64
  [[check]]
81
- name = "taplo"
82
- example = "The TOML line `enabled =` lacks a value and reports a parse error. Use `enabled = true` when the setting is a boolean."
83
- level = "recommended"
84
- stage = "commit"
85
- command = ["taplo", "check", "--config", "{tool_file:taplo}", "--colors", "never", "{files}"]
65
+ command = ["taplo", "fmt", "--config", "{tool_file:taplo}", "--colors", "never", "--check", "--diff", "{files}"]
66
+ example = "The TOML line `enabled=true` differs from the taplo output. Run `gspot check --fix` to get `enabled = true`."
86
67
  files = { extensions = [".toml"] }
87
- output = { format = "regex", pattern = "^\\s*┌─ (?<file>(?:[A-Za-z]:)?[^:]+):(?<line>\\d+):(?<column>\\d+)$", message = "The file does not parse as TOML." }
88
- summary = "Parses every TOML file with taplo; the schema check runs at push through v8r."
89
- why = "A TOML file that does not parse stops the tool that reads it at the worst moment."
90
- help = "Fix the line taplo names."
91
-
92
- [[check]]
93
- name = "taplo-format"
94
- example = "The TOML assignment `enabled=true` differs from the configured formatter output. Run the formatter to obtain `enabled = true` and rerun."
68
+ fix = ["taplo", "fmt", "--config", "{tool_file:taplo}", "--colors", "never", "{files}"]
69
+ help = "Run `gspot check --fix`."
95
70
  level = "recommended"
71
+ name = "taplo-format"
72
+ output = { format = "regex", pattern = "^(?:\\s*┌─ (?<file>(?:[A-Za-z]:)?[^:]+):(?<line>\\d+):(?<column>\\d+)|--- a/(?<file>.+)|ERROR taplo:format_files: the file is not properly formatted path=\"(?<file>[^\"]+)\")$", message = "The file does not parse as TOML, or it is not in the format of the configured TOML settings.", fixable = "^(?:--- a/|ERROR taplo:format_files)" }
96
73
  stage = "commit"
97
- command = ["taplo", "fmt", "--config", "{tool_file:taplo}", "--colors", "never", "--check", "--diff", "{files}"]
98
- fix = ["taplo", "fmt", "--config", "{tool_file:taplo}", "--colors", "never", "{files}"]
99
- files = { extensions = [".toml"] }
100
- output = { format = "regex", pattern = "^(?:--- a/(?<file>.+)|ERROR taplo:format_files: the file is not properly formatted path=\"(?<file>[^\"]+)\")$", message = "The file is not formatted with the configured TOML settings." }
101
- summary = "Checks that every TOML file is formatted the way taplo formats it with the shared settings."
74
+ summary = "Checks that every TOML file parses and matches the taplo output under the shared settings."
102
75
  why = "One formatter keeps a diff about the values, not the spacing."
103
- help = "Run gspot check --fix."
104
76
 
105
77
  [[check]]
106
- name = "yamllint"
107
- example = "Two `enabled` keys in the same YAML mapping report a duplicate-key finding. Keep the one intended value and remove the duplicate."
108
- level = "recommended"
109
- stage = "commit"
110
78
  command = ["yamllint", "-c", "{tool_file:yamllint}", "-f", "parsable", "-s", "{files}"]
79
+ example = "Two `enabled` keys in one YAML mapping report a duplicate key. Keep one, and delete the other."
111
80
  files = { extensions = [".yaml", ".yml"] }
81
+ help = "Fix the line yamllint names, or change rule options with `gspot set tools.yamllint.rules`."
82
+ level = "recommended"
83
+ name = "yamllint"
112
84
  output = { format = "regex", pattern = "^(?<file>[^:]+):(?<line>\\d+):(?<column>\\d+): \\[(?:error|warning)\\] (?<message>.*?)(?: \\((?<rule>[a-z-]+)\\))?$" }
85
+ stage = "commit"
113
86
  summary = "Parses every YAML file and checks its indentation, keys, and values with yamllint."
114
87
  why = "A YAML file that parses to the wrong shape fails silently: a duplicated key wins, a stray tab changes the nesting."
115
- help = "Fix the line yamllint names, or set the rule's options with gspot set tools.yamllint.rules."
116
88
 
117
89
  [[check]]
118
- name = "v8r"
119
- example = "A governed JSON file with a string where its selected schema requires a boolean reports a schema mismatch. Replace the value with the intended boolean and rerun against the same schema."
120
- level = "recommended"
121
- stage = "push"
122
- needs = ["network"]
123
90
  command = ["v8r", "--output-format", "text", "{files}"]
124
91
  env = { V8R_CONFIG_FILE = "{tool_file:v8r}" }
92
+ example = "A JSON file with a string where its schema requires a boolean reports a mismatch. Replace the string with `true` or `false`."
125
93
  files = { extensions = [".json", ".jsonc", ".yaml", ".yml", ".toml"] }
126
- output = { format = "regex", pattern = "^(?<file>[^#\\s]+)#(?<message>.+)$" }
127
- summary = "Validates every tool file that has a known schema against it: package.json, tsconfig.json, mise, workflows and the rest of the SchemaStore catalog."
128
- why = "A key the schema refuses is a setting that never applies, and nobody finds out until the behavior it was meant to change does not change."
129
94
  help = "Fix the key v8r names, or map the file to its schema under tools.v8r.schema."
95
+ level = "recommended"
96
+ name = "v8r"
97
+ needs = ["network"]
98
+ output = { format = "regex", pattern = "^(?<file>[^#\\s]+)#(?<message>.+)$" }
99
+ stage = "push"
100
+ summary = "Validates each file that matches a SchemaStore schema, such as package.json, tsconfig.json, mise files, and workflows."
101
+ why = "A key the schema rejects never takes effect, and nobody notices until the expected behavior fails to appear."
130
102
 
131
103
  [[check]]
132
- name = "xmllint"
133
- example = "The XML text `<settings><enabled>true</settings>` has mismatched tags. Close the child element as `<enabled>true</enabled>` before closing `settings`."
134
- level = "recommended"
135
- stage = "commit"
136
104
  command = ["xmllint", "--noout", "{files}"]
105
+ example = "The XML text `<settings><enabled>true</settings>` has mismatched tags. Close the child element as `<enabled>true</enabled>` before closing `settings`."
137
106
  files = { extensions = [".xml", ".storyboard", ".xib"] }
107
+ help = "Fix the line xmllint names."
108
+ level = "recommended"
109
+ name = "xmllint"
138
110
  output = { format = "regex", pattern = "^(?<file>[^:]+):(?<line>\\d+): (?<message>.*)$" }
111
+ stage = "commit"
139
112
  summary = "Parses every XML file with xmllint."
140
- why = "Malformed XML is refused by the reader at the worst moment."
141
- help = "Fix the line xmllint names."
113
+ why = "A parser rejects malformed XML at the worst moment."
@@ -1,19 +1,29 @@
1
1
  # YAML
2
2
 
3
- Rules for every `.yml` and `.yaml` file.
3
+ Read this rule when you change a `.yml` or `.yaml` file.
4
4
 
5
5
  - Keep one document per file unless the consumer requires a stream.
6
- - Quote strings that YAML otherwise reinterprets: `yes`, `no`, `on`, `off`, `null`, `~`,
7
- version numbers such as `1.10`, octal-looking values, and anything starting with `*`, `&`, `!`,
8
- `%`, `@`, or a backtick.
9
- - Keep anchors and aliases inside one file. Name them for what they carry. No merge keys
10
- across documents.
11
- - Long strings use a block scalar, `|` or `>`, rather than a quoted string with escapes.
6
+ - Quote a string value that YAML otherwise reads as another type: `yes`, `no`, `on`, `off`, `null`, `~`, a version
7
+ such as `1.10`, an octal-looking number, and text that starts with `*`, `&`, `!`, `%`, `@`, or a backtick.
8
+ - Name each anchor for what it holds, such as `&checkout-options`. Do not keep a name that a tool generated, such as
9
+ `&a1`.
10
+ - Do not use merge keys, `<<:`. YAML 1.2 does not define them, and some readers ignore them.
11
+ - Write a long string as a block scalar, `|` or `>`, not as a quoted string with escapes.
12
+
13
+ ## Comments
14
+
15
+ - Put a comment that describes the whole file at the top, above the first key. Do not put it after `name:`
16
+ or between two top-level keys.
17
+ - Put a comment about one key on the line above it, at the same indentation.
18
+ - Do not add a comment at the end of a line. Allow a version comment only after a pinned commit, such as
19
+ `uses: jdx/mise-action@<sha> # v5.1.1`.
20
+ - When the format has a description field, such as `description` in `action.yml`, put the text there, not in a
21
+ comment.
22
+ - A comment describes the current file. Do not write work status in a comment, such as "jobs stay paused."
12
23
 
13
24
  ## Organization
14
25
 
15
26
  <!-- level: all -->
16
27
 
17
- - Order keys as the consumer documents, then alphabetically. Do not reorder keys in a file
18
- you did not otherwise change.
19
- - Use `.yml` for GitHub workflows, `compose.yaml` for Compose, and `.yaml` elsewhere.
28
+ - Order keys as the consumer documents them, then alphabetically. Reorder keys only in a file that you also change for another reason.
29
+ - Use the `.yml` extension. Keep a file name that a tool requires, such as `compose.yaml` or `pnpm-workspace.yaml`.
@@ -2,151 +2,98 @@ allowed_words = ["Prettier"]
2
2
 
3
3
  [configuration]
4
4
  always_selected = true
5
+ description = "A single `[format]` block for every formatter, so Prettier, shfmt, Ruff, and markdownlint use the same indentation."
5
6
  title = "Format"
6
- description = "One [format] block every formatter reads, so indentation cannot disagree between Prettier, shfmt, Ruff, and markdownlint."
7
7
 
8
8
  [files]
9
9
  extensions = [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs", ".jsx", ".json", ".jsonc", ".json5", ".md", ".mdx", ".css", ".scss", ".html", ".yml", ".yaml", ".vue", ".graphql"]
10
10
  prettier_plugins = true
11
11
 
12
12
  [[tool]]
13
- name = "prettier"
14
13
  crash_pattern = "\\[error\\] (?:No parser|Cannot find|Invalid)"
15
- version = "3.8.1"
14
+ name = "prettier"
16
15
  npm = "prettier"
17
- [[tool.replace]]
18
- file = ".prettierrc"
19
- shared = false
20
-
21
- [[tool.replace]]
22
- file = ".prettierrc.json"
23
- shared = false
24
-
25
- [[tool.replace]]
26
- file = ".prettierrc.yml"
27
- shared = false
28
-
29
- [[tool.replace]]
30
- file = ".prettierrc.yaml"
31
- shared = false
32
-
33
- [[tool.replace]]
34
- file = ".prettierrc.json5"
35
- shared = false
36
-
37
- [[tool.replace]]
38
- file = ".prettierrc.js"
39
- shared = false
40
-
41
- [[tool.replace]]
42
- file = "prettier.config.js"
43
- shared = false
44
-
45
- [[tool.replace]]
46
- file = ".prettierrc.ts"
47
- shared = false
48
-
49
- [[tool.replace]]
50
- file = "prettier.config.ts"
51
- shared = false
52
-
53
- [[tool.replace]]
54
- file = ".prettierrc.mjs"
55
- shared = false
56
-
57
- [[tool.replace]]
58
- file = "prettier.config.mjs"
59
- shared = false
60
-
61
- [[tool.replace]]
62
- file = ".prettierrc.mts"
63
- shared = false
64
-
65
- [[tool.replace]]
66
- file = "prettier.config.mts"
67
- shared = false
68
-
69
- [[tool.replace]]
70
- file = ".prettierrc.cjs"
71
- shared = false
72
-
73
- [[tool.replace]]
74
- file = "prettier.config.cjs"
75
- shared = false
76
-
77
- [[tool.replace]]
78
- file = ".prettierrc.cts"
79
- shared = false
80
-
81
- [[tool.replace]]
82
- file = "prettier.config.cts"
83
- shared = false
84
-
85
- [[tool.replace]]
86
- file = ".prettierrc.toml"
87
- shared = false
88
-
89
- [[tool.replace]]
90
- file = ".prettierignore"
91
- shared = false
16
+ replace = [".prettierrc", ".prettierrc.json", ".prettierrc.yml", ".prettierrc.yaml", ".prettierrc.json5", ".prettierrc.js", "prettier.config.js", ".prettierrc.ts", "prettier.config.ts", ".prettierrc.mjs", "prettier.config.mjs", ".prettierrc.mts", "prettier.config.mts", ".prettierrc.cjs", "prettier.config.cjs", ".prettierrc.cts", "prettier.config.cts", ".prettierrc.toml", ".prettierignore"]
17
+ version = "3.8.1"
92
18
 
93
- [[tool.replace]]
19
+ [[tool.replace_key]]
94
20
  file = "package.json"
95
21
  key = "prettier"
96
- shared = true
97
22
 
98
- [[tool.replace]]
23
+ [[tool.replace_key]]
99
24
  file = "package.yaml"
100
25
  key = "prettier"
101
- shared = true
102
26
 
103
27
  [[tool]]
104
- name = "editorconfig-checker"
105
- version = "3.4.0"
106
- env = { EC_VERSION = "v3.4.0" }
107
- npm = { name = "editorconfig-checker", version = "7.0.0" }
108
- mise = { name = "npm:editorconfig-checker", version = "7.0.0" }
109
28
  brew = "editorconfig-checker"
110
29
  github = { name = "editorconfig-checker/editorconfig-checker", version = "v3.4.0" }
111
- [[tool.replace]]
112
- file = ".editorconfig"
113
- shared = false
30
+ mise = { name = "github:editorconfig-checker/editorconfig-checker", version = "3.4.0", options = { rename_exe = "editorconfig-checker" } }
31
+ name = "editorconfig-checker"
32
+ replace = [".editorconfig"]
33
+ version = "3.4.0"
114
34
 
115
35
  [[tool_file]]
116
36
  target = ".editorconfig"
117
37
  tool = ["editorconfig-checker", "prettier"]
118
38
 
119
39
  [[tool_file]]
40
+ pointer = { path = "prettier.config.mjs", when = { configuration = "javascript" }, body = '''
41
+ import { readFileSync } from 'node:fs';
42
+ import { dirname, isAbsolute, relative, resolve } from 'node:path';
43
+ import { fileURLToPath } from 'node:url';
44
+
45
+ const toolFile = new URL({target_json}, import.meta.url);
46
+ const options = JSON.parse(readFileSync(toolFile, 'utf8'));
47
+ const folder = dirname(fileURLToPath(toolFile));
48
+ const root = dirname(fileURLToPath(import.meta.url));
49
+ const movePattern = (pattern) => {
50
+ const negated = pattern.startsWith('!');
51
+ const value = negated ? pattern.slice(1) : pattern;
52
+ if (!value.includes('/') || isAbsolute(value)) return pattern;
53
+ return (negated ? '!' : '') + relative(root, resolve(folder, value)).replaceAll('\\', '/');
54
+ };
55
+ const moveSelectors = (selectors) => Array.isArray(selectors) ? selectors.map(movePattern) : movePattern(selectors);
56
+ if (options.plugins !== undefined) {
57
+ options.plugins = options.plugins.map((plugin) => plugin.startsWith('.') ? fileURLToPath(new URL(plugin, toolFile)) : plugin);
58
+ }
59
+ if (options.overrides !== undefined) {
60
+ options.overrides = options.overrides.map((entry) => ({
61
+ ...entry,
62
+ files: moveSelectors(entry.files),
63
+ ...(entry.excludeFiles === undefined ? {} : { excludeFiles: moveSelectors(entry.excludeFiles) }),
64
+ }));
65
+ }
66
+ export default options;
67
+ ''' }
120
68
  target = ".gspot/config/prettier.json"
121
69
  tool = "prettier"
122
- pointer = { path = "prettier.config.mjs", when = { configuration = "javascript" } }
123
70
 
124
71
  [[tool_file]]
125
72
  target = ".prettierignore"
126
73
  tool = "prettier"
127
74
 
128
75
  [[check]]
129
- name = "prettier"
130
- example = "A selected JavaScript file containing `const value={enabled:true};` differs from the configured Prettier output. Run the formatter and retain its spacing and wrapping changes before rerunning."
131
- level = "recommended"
132
- stage = "commit"
133
76
  command = ["prettier", "--check", "--config", "{tool_file:prettier}", "--ignore-path", ".prettierignore", "--log-level", "warn", "{files}"]
77
+ example = "A JavaScript file with `const value={enabled:true};` differs from the Prettier output. Run `gspot check --fix` to format it."
134
78
  exit_codes = [1]
135
79
  fix = ["prettier", "--write", "--config", "{tool_file:prettier}", "--ignore-path", ".prettierignore", "--log-level", "warn", "{files}"]
136
- output = { format = "regex", pattern = "^\\[warn\\] (?<file>[^\\s].*[^\\s.])$", message = "This file is not formatted the way Prettier formats it." }
137
- summary = "Checks that every file Prettier formats is already formatted that way."
80
+ help = "Run `gspot check --fix` to format every file, or `prettier --write` on one file."
81
+ level = "recommended"
82
+ name = "prettier"
83
+ output = { format = "regex", pattern = "^\\[warn\\] (?<file>[^\\s].*[^\\s.])$", message = "Not formatted the way Prettier formats it." }
84
+ stage = "commit"
85
+ summary = "Checks each file Prettier handles for unformatted code."
138
86
  why = "Formatting by hand differs by editor; one formatter keeps diffs about the change and not the spacing."
139
- help = "Run gspot check --fix to format every file, or prettier --write on one file."
140
87
 
141
88
  [[check]]
142
- name = "editorconfig-checker"
143
- example = "A file containing CRLF line endings when `.editorconfig` requires LF reports a line-ending finding. Save it with LF endings and rerun. Use the exact configured indentation and final-newline settings as well."
144
- level = "recommended"
145
- stage = "commit"
146
89
  command = ["editorconfig-checker", "-no-color", "-disable-indentation", "{files}"]
147
- tool = "editorconfig-checker"
90
+ example = "A file with CRLF line endings under an `.editorconfig` that requires LF reports a finding. Save it with LF endings."
148
91
  files = { paths = ["**"] }
149
- output = { format = "grouped", file_pattern = "^(?<file>.+):$", pattern = "^\\s+(?:(?<line>\\d+)(?:-\\d+)?: )?(?<message>\\S.*)$" }
150
- summary = "Checks line endings, final newlines and trailing whitespace in every file against .editorconfig."
151
- why = "These rules cover the files no formatter touches, so a stray tab or missing newline never lands in a diff. Indentation is the formatters' job and is not checked here."
152
92
  help = "Fix the line the checker names; most editors apply .editorconfig on save."
93
+ level = "recommended"
94
+ name = "editorconfig-checker"
95
+ output = { format = "grouped", file_pattern = "^(?<file>.+):$", pattern = "^\\s+(?:(?<line>\\d+)(?:-\\d+)?: )?(?<message>\\S.*)$" }
96
+ stage = "commit"
97
+ summary = "Checks line endings, final newlines, and trailing whitespace in every file against .editorconfig."
98
+ tool = "editorconfig-checker"
99
+ why = "These rules cover the files no formatter touches, so a stray tab or missing newline never lands in a diff. The formatters handle indentation."
@@ -1,65 +1,45 @@
1
1
  allowed_words = ["gspot"]
2
+
2
3
  [configuration]
3
- title = "gspot"
4
4
  always_selected = true
5
- description = "Checks gspot.toml and generated files, checks suppression reasons with gspot/suppressions, and requires Node.js as a system tool."
5
+ description = "Checks gspot.toml, generated files, and suppression reasons, and requires Node.js as a system tool."
6
+ title = "gspot"
6
7
 
7
8
  [[tool]]
8
- name = "node"
9
+ brew = "node@24"
9
10
  install_hint = "Install Node.js 24.2.0 or newer. On macOS, run brew install node@24. On Windows, run winget install OpenJS.NodeJS.LTS."
10
11
  min_version = "24.2.0"
11
- version_command = ["--version"]
12
+ name = "node"
12
13
  system = true
13
- brew = "node@24"
14
+ version_command = ["--version"]
14
15
  winget = "OpenJS.NodeJS.LTS"
15
16
 
16
17
  [[check]]
17
- name = "settings-format"
18
- example = "A hand-edited gspot.toml with separated tables reports a layout finding. Run gspot check --fix --only gspot/settings-format to regroup its tables and retain their comments."
18
+ example = "An edit by hand to a tool file under `.gspot/config/` reports drift. Move the change into gspot.toml, then run `gspot apply`."
19
+ help = "Change gspot.toml, then run `gspot apply`. After a merge, run `gspot apply`, followed by `gspot install`."
19
20
  level = "recommended"
20
- stage = "commit"
21
- files = { paths = ["gspot.toml"] }
22
- summary = "Keeps gspot.toml formatted."
23
- why = "One settings layout keeps related settings and their reasons together."
24
- help = "Run gspot check --fix --only gspot/settings-format."
25
-
26
- [[check]]
27
21
  name = "generated-files"
28
- example = "A file under `.gspot/config/` edited by hand differs from what gspot writes from gspot.toml and reports drift. Change the settings in gspot.toml and run gspot apply, or move the edited file aside so apply writes it again."
29
- level = "recommended"
30
- stage = "commit"
31
22
  runs = "once"
32
- summary = "Compares every generated file with what gspot writes from the settings: a changed, missing, or stray file, or one with merge conflict markers, is a finding."
33
- why = "A generated file that no longer matches the settings runs a tool with settings nobody chose."
34
- help = "Change the settings in gspot.toml, then run gspot apply. After a merge, run gspot apply and then gspot install."
23
+ stage = "commit"
24
+ summary = "Compares generated files with the settings and reports changed, missing, and stray ones, and any with merge conflict markers."
25
+ why = "A generated file that drifts from gspot.toml runs a tool with settings nobody chose."
35
26
 
36
27
  [[check]]
37
- name = "unused-entries"
38
- example = "An `[[ignore]]` entry for `bash/shellcheck` with `paths = [\"nowhere/**\"]` reports `unmatched-pattern` when that path matches no selected file. Remove the obsolete entry or correct its path to the actual exception, preserving its reason."
28
+ example = "An `[[ignore]]` record with `paths = [\"nowhere/**\"]` that matches no file reports `unmatched-pattern`. Remove the record, or correct its path and keep the reason."
29
+ help = "Remove the record or correct its path."
39
30
  level = "recommended"
40
- stage = "commit"
31
+ name = "unmatched-patterns"
41
32
  runs = "once"
33
+ stage = "commit"
42
34
  summary = "Checks settings path patterns against tracked files."
43
35
  why = "An ignore or declaration that matches nothing misleads the next reader."
44
- help = "Remove the entry or correct its path."
45
36
 
46
37
  [[check]]
47
- name = "settings"
48
- example = "An unknown setting or a loosened limit without a reason reports its gspot.toml key path. Correct the declaration or record the required reason."
38
+ example = "An `eslint-disable-next-line` comment without a reason reports a finding. Fix the code and remove the comment, or append `-- reason: ...` that explains the exception."
39
+ help = "Fix the finding and remove the suppression, or add a reason in the syntax of the tool. Never suppress a size or complexity limit: split the code by its steps, or ask the user to raise it in gspot.toml."
49
40
  level = "recommended"
50
- stage = "commit"
51
- runs = "once"
52
- files = { paths = ["gspot.toml"] }
53
- summary = "Checks the captured gspot.toml declarations for invalid settings and missing reasons."
54
- why = "A setting no check reads, or an unexplained loosening, can leave repository settings unenforced."
55
- help = "Fix the gspot.toml key the finding names, and give each loosened value a reason."
56
-
57
- [[check]]
58
41
  name = "suppressions"
59
- example = "An `eslint-disable-next-line` comment without a reason reports an unexplained suppression. Fix the underlying finding and remove the suppression, or append a specific `-- reason: ...` explanation of the required exception."
60
- level = "recommended"
61
- stage = "commit"
62
42
  runs = "once"
63
- summary = "Checks suppression reasons; Semgrep and Vale directives are refused outright."
43
+ stage = "commit"
44
+ summary = "Reports suppressions with no reason, any that lift a size or complexity limit, and Semgrep or Vale directives."
64
45
  why = "A suppression with no reason hides a finding nobody reviewed."
65
- help = "Use the tool's suppression syntax to write a meaningful reason, or fix the finding and remove the suppression."
@@ -1,10 +1,20 @@
1
1
  # Generated Code
2
2
 
3
- - Never edit a generated file by hand. Change the source or the generator and regenerate
4
- through its generation command.
3
+ Read this rule when you change a generated file, or the code that writes one.
4
+
5
+ - Never edit a generated file by hand. Change the source or the generator, and rerun its
6
+ command.
5
7
  - Mark generated paths in `.gitattributes` with `linguist-generated`; for example,
6
- `output/** linguist-generated`. Where the format allows comments, add a header that names the
7
- generation command. A folder named `generated/` does not make its files generated.
8
+ `output/** linguist-generated`. A folder named `generated/` does not make its files generated.
8
9
  - A generated file equals a fresh run of its command. A difference shows a defect in the change.
9
10
  - Do not commit build output (`dist/`, `coverage/`, compiled assets) unless the deployment reads
10
11
  it from the repository, and then declare it.
12
+
13
+ ## Readable output
14
+
15
+ - Where the format allows comments, start the file with a header. Name the generator and the command that writes
16
+ it. Add one line that states the file's purpose.
17
+ - Group the items of a generated list, such as an ignore file, under a comment that states their purpose, one
18
+ section per source. Write each item once.
19
+ - Write one item per line, in a stable order. Use the formatter's layout.
20
+ - Keep code that a program runs in a source file that the checks read, not in a string inside the generator.