@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,14 +1,16 @@
1
1
  # Bash Operations
2
2
 
3
+ Read this rule when you write a deployment, publishing, or remote shell script.
4
+
3
5
  ## Module ownership and visibility
4
6
 
5
7
  <!-- level: all -->
6
8
 
7
- Each file owns one cohesive responsibility, and the directory supplies the family name.
9
+ Each file owns one cohesive responsibility, and the folder supplies the family name.
8
10
 
9
11
  - A sourced public function carries its family name, such as `release_prepare` or
10
12
  `cache_read_state`.
11
- - A function with one caller lives in the caller's file.
13
+ - Keep a function with one caller in the same file as the call.
12
14
 
13
15
  ## Deployment and publishing pipelines
14
16
 
@@ -16,11 +18,11 @@ Deployment, publishing, and long-running scripts separate validation, planning,
16
18
  execution, readiness checks, and cleanup.
17
19
 
18
20
  - Fail before any work when the script lacks a required input, command, file, host, or secret.
19
- - Name the target explicitly: never infer production, a remote, a host, or an artifact from a
21
+ - State the target explicitly: never infer production, a remote, a host, or an artifact from a
20
22
  branch name without a confirmation or a CI contract.
21
23
  - A destructive or remote action asks for confirmation unless CI owns the guard.
22
24
  - Use idempotent commands and stop at the first failed required step.
23
- - Check readiness after deploying or publishing, and print diagnostics a person can act on.
25
+ - Check readiness after deploying or publishing, and print messages a person can act on.
24
26
  - Keep rollback and cleanup explicit, and delete no artifact or result as a side effect.
25
27
  - Log enough to reconstruct what happened, without secrets.
26
28
 
@@ -44,9 +46,9 @@ confirm_exact() {
44
46
  ## Remote commands
45
47
 
46
48
  Copy a reviewed script to the remote host and invoke it with arguments. SSH joins its arguments
47
- into one remote shell string, so local quoting does not keep remote argument boundaries. Validate
48
- host, user, service, and path values before using them, never build a remote command from user
49
- input, and give every remote call that can hang a timeout.
49
+ into one remote shell string, so local quoting does not keep their boundaries. Validate host,
50
+ user, service, and path values before you use them. Never build a remote command from user
51
+ input. Give every remote call that can hang a timeout.
50
52
 
51
53
  Good, for a remote Bash login shell:
52
54
 
@@ -58,7 +60,7 @@ ssh -- "${host}" "${remote_command}"
58
60
  ## Persisted state
59
61
 
60
62
  Never `source` generated state or pass it to `bash -c`. Write state in a fixed data format with an
61
- exact key schema to a restricted file in the destination folder, and replace the previous state
63
+ exact key schema to a restricted file in the destination folder. Replace the previous version
62
64
  with an atomic `mv`. A reader treats a malformed, duplicate, or unknown key as an error.
63
65
 
64
66
  ## Retries
@@ -1,11 +1,12 @@
1
1
  # Bash Safety
2
2
 
3
+ Read this rule when a shell script runs commands, handles paths, downloads files, or deletes files.
4
+
3
5
  ## Calling commands
4
6
 
5
- Use fixed command names with argument arrays, never strings built from input, and a script
6
- never passes untrusted input to a shell. Never use `bash -lc` in repository scripts, and a
7
- function that runs a caller-supplied command takes the command and its arguments after
8
- `shift` and invokes `"$@"`.
7
+ Use fixed command names with argument arrays, never strings built from input. Never pass
8
+ untrusted input to a shell. Never use `bash -lc` in repository scripts. A function that runs a
9
+ caller-supplied command takes it and its arguments after `shift` and invokes `"$@"`.
9
10
 
10
11
  Check uncommon commands with `command -v` before a long-running, destructive, publishing, or
11
12
  error-handling path depends on them. Prefer builtins and parameter expansion to external
@@ -28,14 +29,14 @@ require_command() {
28
29
 
29
30
  ## Processes and privilege
30
31
 
31
- Treat process names as advisory information, never authorization. Stop and restart paths stop only
32
- process ids recorded by the owning script family, found through the service manager, a `PID` file, or
33
- `pgrep -x`, never `ps | grep`. A script that starts background jobs saves each `PID`, waits for
34
- each, captures each status, and writes per-job output to separate files. It bounds its
32
+ Treat process names as advisory information, never authorization. Stop and restart paths kill only
33
+ process ids that the owning script family recorded, found through the service manager, a `PID` file, or
34
+ `pgrep -x`, never `ps | grep`. A script that starts background jobs saves every `PID`, waits for
35
+ each job, captures its status, and writes its output to a separate file. It bounds its
35
36
  fan-out and kills owned children on `INT`, `TERM`, and `EXIT`. `sudo command > file` redirects
36
37
  as the current user, and a glob in `sudo command /path/*` expands before `sudo` runs.
37
- Privileged writes go through `sudo tee`, and keep a privileged shell string as a fixed literal
38
- with no input.
38
+ Send privileged writes through `sudo tee`, and keep the shell string you pass to `sudo` a fixed
39
+ literal with no input.
39
40
 
40
41
  ```bash
41
42
  generate_config | sudo tee /etc/service/config >/dev/null
@@ -74,7 +75,7 @@ with ad hoc `grep | sed | awk` unless the script controls the input and the form
74
75
  Prefer machine output modes such as JSON, `NUL`, or explicit format flags and never parse process lists,
75
76
  pretty tables, progress bars, or localized text by fixed field numbers. Quote `tr` character
76
77
  classes and pin `LC_ALL=C` when converting case. macOS and GNU `sed -i` differ; a committed
77
- script rewrites through a temporary file unless its documentation restricts it to one platform.
78
+ script rewrites through a temporary file unless its documentation restricts it to one system.
78
79
 
79
80
  ```bash
80
81
  # get_service_url: Prints a required nonempty service URL from JSON configuration.
@@ -89,9 +90,9 @@ get_service_url() {
89
90
 
90
91
  ## Network
91
92
 
92
- Downloads use `curl --fail --show-error --silent --location` into an explicit file, with
93
- tool-native timeouts such as `--connect-timeout` plus `--max-time`, or SSH `ConnectTimeout`, rather
94
- than GNU `timeout`, which macOS lacks. Download executable content, verify it against an
93
+ Download with `curl --fail --show-error --silent --location` into an explicit file. Set timeouts
94
+ with the options of the tool, such as `--connect-timeout` plus `--max-time`, or SSH `ConnectTimeout`.
95
+ Do not use GNU `timeout`, which macOS lacks. Download executable content, verify it against an
95
96
  independently obtained checksum or signature, and only then run it.
96
97
 
97
98
  ```bash
@@ -132,19 +133,19 @@ require_env() {
132
133
 
133
134
  ## Temporary files, locks, and cleanup
134
135
 
135
- Temporary paths come from `mktemp` or `mktemp -d` under the system or an explicit project
136
- temp directory, never from predictable names. Register cleanup immediately after creation.
136
+ Create temporary paths with `mktemp` or `mktemp -d` under the system location or a dedicated
137
+ project folder, never with predictable names. Register cleanup immediately after creation.
137
138
  Put downloaded, copied, or generated content in a temporary file, validate it with the real
138
139
  parser, and replace the destination with `mv`. The file keeps the restrictive permissions
139
140
  `mktemp` gave it unless deployment needs others. Remove failed artifacts unless the script
140
- documents keeping them. Acquire locks atomically with a `mkdir` lock directory holding
141
- the owner `PID` or with `noclobber` redirection, never with a `test` followed by a create.
141
+ documents keeping them. Acquire a lock atomically with `mkdir` on a folder that stores the holder
142
+ `PID`, or with `noclobber` redirection, never with a `test` followed by a create.
142
143
 
143
144
  Stop commands remove only what the script created. Validate a cleanup path from
144
145
  input or persistent state against its permitted root. Reject empty values, `/`,
145
- the repository root, `$HOME`, symlinks, and anything outside the owner. Keep a `mktemp -d` result
146
+ the repository root, `$HOME`, symlinks, and anything outside the folder the script created. Keep a `mktemp -d` result
146
147
  exactly. Never widen the path to its neighbors. `|| true` never follows a destructive
147
- command or a required installation, publishing, build, or runtime command.
148
+ step or a required installation, publishing, build, or runtime command.
148
149
 
149
150
  ```bash
150
151
  downloaded_file="$(mktemp "${config_file}.XXXXXX")" || exit 1
@@ -165,11 +166,12 @@ printf '%s\n' "$$" >"${lock_dir}/pid" || {
165
166
  trap 'rm -f -- "${lock_dir}/pid"; rmdir -- "${lock_dir}"' EXIT
166
167
  ```
167
168
 
168
- Put recursive deletes in one script, and accept that script with an `[[ignore]]` record for `bash/safety`.
169
- Validate its cleanup path against the owner root:
169
+ Put recursive deletes in one script. To accept the `bash/safety` finding for that script, follow the suppression
170
+ rules.
171
+ Validate its cleanup path against the approved root folder:
170
172
 
171
173
  ```bash
172
- # remove_build_dir: Removes the build child of the approved owner directory.
174
+ # remove_build_dir: Removes the build child of the approved root folder.
173
175
  remove_build_dir() {
174
176
  local owner_root build_dir
175
177
 
@@ -186,10 +188,9 @@ remove_build_dir() {
186
188
 
187
189
  macOS and BSD
188
190
  differ from GNU in `sed`, `date`, `readlink`, `mktemp`, `stat`, `xargs`, and `grep`; keep a
189
- platform-specific branch with the operation that owns it. Handle `realpath` and `date`
190
- parsing differences. macOS `/bin/bash` uses an old Bash version,
191
- Linux-only utilities need checks in macOS-compatible scripts, and CI does not share the
192
- developer's `PATH`. Symlink-aware absolute paths come from `pwd -P` after `cd`, or from
191
+ system-specific branch with the operation that owns it. Handle `realpath` and `date`
192
+ parsing differences. macOS `/bin/bash` runs an old Bash version. Linux-only utilities need
193
+ checks in scripts that also run on macOS. CI does not share the `PATH` of the developer. Symlink-aware absolute paths come from `pwd -P` after `cd`, or from
193
194
  product-owned application code.
194
195
 
195
196
  ## Verification and debugging
@@ -198,13 +199,15 @@ Run the configured syntax, ShellCheck, and shfmt commands. Run destructive or pr
198
199
  only in a throwaway environment.
199
200
 
200
201
  Production scripts gain no test-only flags, branches, or command replacements. When
201
- debugging, start from the exact error and line Bash reports, run `bash -n` and ShellCheck,
202
+ debugging, start from the exact error and line Bash reports. Run `bash -n` and ShellCheck,
202
203
  reduce to the smallest reproducing block, and expose invisible characters with
203
- `printf '%q\n'`. Trace with `bash -x` or a local `set -x` block with a `PS4` naming file, line, and function,
204
- only while diagnosing, never around secrets, and never commit broad tracing, `trap DEBUG`, or stepping
204
+ `printf '%q\n'`.
205
+
206
+ Trace with `bash -x` or a local `set -x` block whose `PS4` names file, line, and function,
207
+ only while you debug. Never commit broad tracing, `trap DEBUG`, or stepping
205
208
  code. Bash 4.4 supports `BASH_XTRACEFD`. A debug helper preserves the status it diagnoses.
206
209
 
207
- Common causes follow. `unexpected EOF` indicates an unmatched quote, an unterminated here document,
210
+ `unexpected EOF` indicates an unmatched quote, an unterminated here document,
208
211
  a missing `fi`, `done`, or `esac`, or a CRLF ending hiding the delimiter.
209
212
 
210
213
  `too many arguments` indicates an unquoted expansion inside `[ ... ]`. `event not found` indicates interactive history expansion
@@ -213,10 +216,11 @@ Failure before the shebang indicates a byte order mark (BOM) or CRLF.
213
216
 
214
217
  ## Refactoring existing scripts
215
218
 
216
- Read the whole script and its sourced libraries, identify the caller interface: local, CI,
217
- remote host, or package script, and preserve behavior before changing style. Fix quoting and
218
- argument arrays near the touched logic, and add explicit checks around dangerous commands.
219
- Share a helper across the script family only when it has a real shared contract. Do not
219
+ Read the whole script and its sourced libraries. Identify the caller interface: local, CI,
220
+ remote host, or package script. Preserve behavior before you change style.
221
+
222
+ Fix quoting and argument arrays near the touched logic, and add explicit checks around dangerous commands.
223
+ Share a helper across the script family only when it has a real common contract. Do not
220
224
  convert a large script in one pass or change shebangs across a family without verifying the
221
225
  runtime. Run the narrow shell lint and format command before the broader checks. Move complex script
222
226
  logic into application code and call it directly.
@@ -1,7 +1,8 @@
1
1
  allowed_words = ["CSS"]
2
+
2
3
  [configuration]
4
+ description = "CSS files and style blocks in Vue and Svelte components: Stylelint with the standard rules, Prettier for layout, and module classes both defined and used. SCSS gets formatting only."
3
5
  title = "CSS"
4
- description = "CSS files and the style blocks of Vue and Svelte components: Stylelint with the standard rules, Prettier for layout, and CSS module classes that are both defined and used. SCSS receives formatting only."
5
6
 
6
7
  [detect]
7
8
  extensions = [".css", ".vue", ".svelte"]
@@ -9,90 +10,50 @@ extensions = [".css", ".vue", ".svelte"]
9
10
  [files]
10
11
  extensions = [".css"]
11
12
 
13
+ [rules]
14
+ "TAILWIND.md" = { dependencies = ["tailwindcss"] }
15
+
12
16
  [[tool]]
13
17
  name = "stylelint"
18
+ npm = "stylelint"
19
+ replace = [".stylelintrc", ".stylelintrc.json", ".stylelintrc.js", ".stylelintrc.cjs", ".stylelintrc.mjs", ".stylelintrc.yml", ".stylelintrc.yaml", "stylelint.config.js", "stylelint.config.cjs", "stylelint.config.mjs"]
14
20
  suppression = { marker = "^(?:/\\*|//)\\s*stylelint-disable(?:-next-line|-line)?(?=\\s|$)", reason = " -- (?<reason>\\S(?:[\\s\\S]*?\\S)?)\\s*(?:\\*/)?$" }
15
21
  version = "16.23.1"
16
- npm = "stylelint"
17
- [[tool.replace]]
18
- file = ".stylelintrc"
19
- shared = false
20
-
21
- [[tool.replace]]
22
- file = ".stylelintrc.json"
23
- shared = false
24
-
25
- [[tool.replace]]
26
- file = ".stylelintrc.js"
27
- shared = false
28
-
29
- [[tool.replace]]
30
- file = ".stylelintrc.cjs"
31
- shared = false
32
-
33
- [[tool.replace]]
34
- file = ".stylelintrc.mjs"
35
- shared = false
36
22
 
37
- [[tool.replace]]
38
- file = ".stylelintrc.yml"
39
- shared = false
40
-
41
- [[tool.replace]]
42
- file = ".stylelintrc.yaml"
43
- shared = false
44
-
45
- [[tool.replace]]
46
- file = "stylelint.config.js"
47
- shared = false
48
-
49
- [[tool.replace]]
50
- file = "stylelint.config.cjs"
51
- shared = false
52
-
53
- [[tool.replace]]
54
- file = "stylelint.config.mjs"
55
- shared = false
56
-
57
- [[tool.replace]]
23
+ [[tool.replace_key]]
58
24
  file = "package.json"
59
25
  key = "stylelint"
60
26
  redirect = true
61
- shared = true
62
27
 
63
28
  [[tool]]
64
- name = "stylelint-config-standard"
65
29
  kind = "library"
66
- version = "39.0.0"
30
+ name = "stylelint-config-standard"
67
31
  npm = "stylelint-config-standard"
32
+ version = "39.0.0"
68
33
 
69
34
  [[tool]]
70
- name = "postcss-html"
71
35
  kind = "library"
72
- version = "2.0.0"
36
+ name = "postcss-html"
73
37
  npm = "postcss-html"
38
+ version = "2.0.0"
74
39
 
75
40
  [[tool_file]]
76
- target = ".gspot/config/stylelint.json"
77
- tool = "stylelint"
78
- rule_keys = ["rules"]
79
41
  per_scope = true
80
42
  pointer = { path = ".stylelintrc.json", body = "{\n \"extends\": \"{target}\"\n}\n" }
43
+ target = ".gspot/config/stylelint.json"
44
+ tool = "stylelint"
81
45
 
82
46
  [[check]]
83
- name = "stylelint"
84
- tool = ["stylelint", "stylelint-config-standard"]
85
- example = "The declaration `color: #ggg` uses an invalid hexadecimal color and reports a Stylelint finding. Replace it with a valid intended color such as `#abc`."
86
- level = "recommended"
87
- stage = "commit"
88
47
  command = ["stylelint", "--config", "{tool_file:stylelint}", "--config-basedir", "{root}/.gspot", "--formatter", "unix", "--allow-empty-input", "{files}"]
89
- fix = ["stylelint", "--config", "{tool_file:stylelint}", "--config-basedir", "{root}/.gspot", "--fix", "--allow-empty-input", "{files}"]
48
+ example = "The declaration `color: #ggg` holds an invalid hex value and reports a finding. Replace it with a valid one such as `#abc`."
90
49
  exit_codes = [2]
91
50
  files = { extensions = [".css", ".vue", ".svelte"] }
51
+ fix = ["stylelint", "--config", "{tool_file:stylelint}", "--config-basedir", "{root}/.gspot", "--fix", "--allow-empty-input", "{files}"]
52
+ help = "Run `gspot check --fix` for the rules that fix themselves. Turn one rule off with `gspot ignore css/stylelint --rule <name> --reason \"<why>\"`."
53
+ level = "recommended"
54
+ name = "stylelint"
92
55
  output = { format = "regex", pattern = "^(?<file>.+?):(?<line>\\d+):(?<column>\\d+): (?<message>.*) \\((?<rule>[\\w/@-]+)\\) \\[\\w+\\]$" }
56
+ stage = "commit"
93
57
  summary = "Lints every stylesheet with the standard stylelint rules: unknown properties, overridden selectors, and invalid values."
94
- why = "A browser skips a declaration it cannot read without a word, so a typo in a property ships as a missing style."
95
- help = "Run gspot check --fix for the rules that fix themselves. Turn one rule off with gspot ignore css/stylelint --rule `<name>` --reason \"`<why>`\"."
96
-
97
- [rules]
98
- "TAILWIND.md" = { dependencies = ["tailwindcss"] }
58
+ tool = ["stylelint", "stylelint-config-standard"]
59
+ why = "A browser silently skips a declaration it cannot parse, so a typo in a property ships as a missing style."
@@ -1,5 +1,7 @@
1
1
  # CSS
2
2
 
3
+ Read this rule when you change a stylesheet.
4
+
3
5
  ## Correctness and accessibility
4
6
 
5
7
  - Use logical properties where layout follows the writing direction.
@@ -9,7 +11,7 @@
9
11
 
10
12
  <!-- level: all -->
11
13
 
12
- - Keep shared color, spacing, type, radius, and motion tokens in one owner.
14
+ - Keep shared color, spacing, type, radius, and motion tokens in one file.
13
15
  - Keep feature styles with their component or import them through the stylesheet entry.
14
16
  - Order rules from general styles to component states.
15
17
 
@@ -18,7 +20,7 @@
18
20
  <!-- level: all -->
19
21
 
20
22
  - Prefer class selectors with low specificity.
21
- - Prefer grid and flexbox for layout. Keep flow content in normal document flow.
23
+ - Prefer grid and flexbox for layout. Keep content in normal document flow.
22
24
 
23
25
  ## Files
24
26
 
@@ -26,3 +28,20 @@
26
28
 
27
29
  - Keep presentation in stylesheets or framework-owned component style blocks.
28
30
  - Let the framework own style scoping rather than duplicating selectors manually.
31
+
32
+ ## Naming
33
+
34
+ ### Selector and file names
35
+
36
+ <!-- level: all -->
37
+
38
+ - Name classes for the component or state, such as `order-card`, `order-card-title`, `is-active`, or `has-error`.
39
+ - A state class starts with `is-` or `has-`. A script toggles it. Never style it alone.
40
+ - Custom properties name the role of the value, not its appearance:
41
+ `--color-surface`, `--space-2`, `--font-size-body`, never `--blue` or `--big-margin`.
42
+ - Theme overrides reuse the same property names under their selector and add no new ones.
43
+ - Keyframe names describe the motion, such as `fade-in` or `slide-from-start`.
44
+ - Name stylesheet files for what they hold, such as `order-card.css`,
45
+ `tokens.css`, or `layout.css`.
46
+ - When the project uses a utility system, keep its class names. Do not write your own utility classes
47
+ beside it.
@@ -1,13 +1,15 @@
1
1
  # Tailwind CSS
2
2
 
3
+ Read this rule when you change Tailwind CSS classes or configuration.
4
+
3
5
  ## Generated styles
4
6
 
5
7
  - Verify that source detection covers templates and content containing class names. Tailwind CSS 4
6
- detects sources automatically; register excluded sources with `@source`. Tailwind CSS 3 uses
8
+ detects sources automatically; register excluded ones with `@source`. Tailwind CSS 3 uses
7
9
  `content` configuration.
8
10
  - Keep complete class names in source so the scanner can find them.
9
11
  - Preserve the application's configured dark-mode strategy.
10
- - When the project configures a class-ordering formatter plugin, let that formatter own ordering.
12
+ - When the project configures a formatter plugin that sorts classes, let it own the order.
11
13
 
12
14
  Use the [source detection documentation](https://tailwindcss.com/docs/detecting-classes-in-source-files)
13
15
  for the installed major version.
@@ -17,10 +19,10 @@ for the installed major version.
17
19
  <!-- level: all -->
18
20
 
19
21
  - Use theme tokens for colors, spacing, radii, fonts, and breakpoints. Explain deliberate values
20
- outside those tokens at their owner.
22
+ outside those tokens where the code uses them.
21
23
  - Compose component styles with utility classes. Keep reusable theme and utility declarations
22
- in their configured style owner.
24
+ in the configured stylesheet.
23
25
  - Use the project's adopted class-merging function when conditional utilities conflict.
24
26
  Do not introduce a separate merging implementation.
25
27
  - Avoid handwritten CSS that duplicates an existing utility without a component requirement.
26
- - Follow the installed Tailwind version's syntax for custom utilities, variants, and plugins.
28
+ - Follow the syntax of the installed Tailwind version for custom utilities, variants, and plugins.
@@ -1,59 +1,40 @@
1
1
  allowed_words = ["HTML"]
2
+
2
3
  [configuration]
4
+ description = "HTML files: html-validate for structure and accessibility, and no inline script or handler."
3
5
  title = "HTML"
4
- description = "HTML files: html-validate for structure and accessibility, no inline script or handler, and templates that hold placeholders in place of copy."
5
6
 
6
7
  [files]
7
8
  extensions = [".html", ".htm"]
8
9
 
9
10
  [[tool]]
10
11
  name = "html-validate"
12
+ npm = "html-validate"
13
+ replace = [".htmlvalidate.json", ".htmlvalidate.js", ".htmlvalidate.cjs"]
11
14
  suppression = { marker = "^<!--\\s*\\[?html-validate-disable(?:-next|-block)?(?=\\s|\\]|$)", reason = "(?: -- |: )(?<reason>\\S(?:[\\s\\S]*?\\S)?)\\s*\\]?\\s*(?:--!?>)?$" }
12
15
  version = "11.6.1"
13
- npm = "html-validate"
14
- [[tool.replace]]
15
- file = ".htmlvalidate.json"
16
- shared = false
17
-
18
- [[tool.replace]]
19
- file = ".htmlvalidate.js"
20
- shared = false
21
-
22
- [[tool.replace]]
23
- file = ".htmlvalidate.cjs"
24
- shared = false
25
16
 
26
17
  [[tool_file]]
18
+ check = "html/html-validate"
27
19
  target = ".gspot/config/html-validate-source.json"
28
20
  tool = "html-validate"
29
- check = "html/validate"
30
- rule_keys = ["rules"]
31
21
 
32
22
  [[check]]
33
- name = "validate"
34
- example = "An `<img src=\"logo.png\">` element without alternative text reports an accessibility finding under the configured rules. Add meaningful `alt` text, or an empty `alt` value for a decorative image."
35
- level = "recommended"
36
- stage = "commit"
37
23
  command = ["html-validate", "--config", "{tool_file:html-validate-source}", "--formatter", "json", "{files}"]
24
+ example = "An `<img src=\"logo.png\">` without alternative text reports a finding. Add `alt` text, or leave it empty for a decorative image."
25
+ help = "Change the markup the way the rule page says. Turn one rule off with `gspot ignore html/html-validate --rule <name> --reason \"<why>\"`."
26
+ level = "recommended"
27
+ name = "html-validate"
38
28
  output = { format = "json", children = "messages", fields = { file = "filePath", line = "line", column = "column", rule = "ruleId", message = "message" } }
39
- summary = "Validates every HTML file: elements where they may sit, required attributes, text alternatives, and one style for void elements."
40
- why = "A browser repairs broken markup in its own way, and a screen reader reads what the repair left."
41
- help = "Change the markup the way the rule page says. Turn one rule off with gspot ignore html/validate --rule `<name>` --reason \"`<why>`\"."
42
-
43
- [[check]]
44
- name = "scripts"
45
- example = "A button using an inline `onclick` attribute reports embedded executable code. Remove the attribute and attach the event listener from a separate script file."
46
- level = "all"
47
29
  stage = "commit"
48
- summary = "Refuses executable inline script, event handler attributes, and executable script or data URLs in HTML files."
49
- why = "A content security policy that allows inline script allows an injected one too, so the policy only holds when the pages hold none."
50
- help = "Move the script into a file, and attach the handler from that file. Structured data of type application/ld+json stays inline."
30
+ summary = "Validates HTML files for nesting, required attributes, text alternatives, and one style for void elements."
31
+ why = "Each browser repairs broken markup differently, and a screen reader announces only what remains."
51
32
 
52
33
  [[check]]
53
- name = "template-text"
54
- example = "Text written into a file listed in html.templates reports a literal. Move the text to its content file and use a placeholder in the template."
34
+ example = "A button with an inline `onclick` attribute reports a finding. Remove it, and attach the listener from a script file."
35
+ help = "Move the script into its own file, and attach the handler there. Structured data of type `application/ld+json` stays inline."
55
36
  level = "all"
37
+ name = "scripts"
56
38
  stage = "commit"
57
- summary = "In the template files named by html.templates, checks that text a person reads is a placeholder and never a literal."
58
- why = "Copy written into a template is copy no translator and no content file ever sees."
59
- help = "Replace the text with a placeholder and put the words in the content file. Remove files that are not templates from html.templates."
39
+ summary = "Reports inline scripts, event handler attributes, and executable URLs in HTML files."
40
+ why = "A content security policy can block injected code only when the pages carry no inline script."
@@ -1,18 +1,19 @@
1
1
  # HTML
2
2
 
3
+ Read this rule when you change HTML or an HTML template.
4
+
3
5
  ## Document
4
6
 
5
- - `<html lang="...">` names the page language; set `dir` for a right-to-left language.
7
+ - `<html lang="...">` names the page language; set `dir` for right-to-left text.
6
8
  - One `<title>` that names the page, a `<meta name="viewport">`, and a `<meta charset="utf-8">`
7
9
  first in `<head>`.
8
10
  - Landmarks such as `header`, `nav`, `main`, `footer`, and `aside` structure the page. One `main`.
9
11
 
10
12
  ## Elements
11
13
 
12
- - Use the element that means the thing: `button` for actions, `a` for navigation with a real
13
- `href`, `nav` for navigation, `ul` and `ol` for lists, `table` for data, `time` with `datetime`
14
- for dates, `figure` and `figcaption` for captioned media.
15
- - Never a `div` or `span` with a click handler standing in for a button or link.
14
+ - Use the element that means the thing: `button` for actions, `a` with a real `href` for links,
15
+ and `nav` for navigation. Use `ul` and `ol` for lists, `table` for data, `time` with `datetime`
16
+ for dates, and `figure` and `figcaption` for captioned media.
16
17
  - `target="_blank"` links carry `rel="noopener"`.
17
18
 
18
19
  ## Script safety
@@ -25,3 +26,20 @@
25
26
 
26
27
  - A template stays declarative: no logic beyond conditionals and loops the engine provides.
27
28
  - Generate deterministic HTML: the same inputs produce byte-identical output.
29
+
30
+ ## Naming
31
+
32
+ ### Route and attribute names
33
+
34
+ <!-- level: all -->
35
+
36
+ - Use kebab-case file names that match the public route: `about-us.html`, `pricing/index.html`.
37
+ Folder routes end in `index.html` in generated output.
38
+ - Name public route segments in lowercase kebab-case with no trailing slash ambiguity: one
39
+ canonical form, with the other redirected.
40
+ - Use `id` attributes for anchors, labels, and descriptions, not for styling.
41
+ - Name `data-*` attributes in kebab-case for their value, such as `data-device-class`.
42
+ - Placeholders follow the engine's convention and name the value.
43
+ - Name content files for the route or topic they serve, such as `content/legal/privacy.md`.
44
+ - Name asset files in kebab-case for their subject and role, such as `hero-phone-dark.webp`. Never use
45
+ `image1.png` or `final-v2.svg`. Generate hashed names rather than writing them by hand.