@deftai/directive-content 0.55.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 (250) hide show
  1. package/.agents/skills/deft/SKILL.md +6 -0
  2. package/.agents/skills/deft-directive-article-review/SKILL.md +11 -0
  3. package/.agents/skills/deft-directive-build/SKILL.md +10 -0
  4. package/.agents/skills/deft-directive-cost/SKILL.md +12 -0
  5. package/.agents/skills/deft-directive-debug/SKILL.md +13 -0
  6. package/.agents/skills/deft-directive-gh-arch/SKILL.md +11 -0
  7. package/.agents/skills/deft-directive-gh-slice/SKILL.md +10 -0
  8. package/.agents/skills/deft-directive-glossary/SKILL.md +10 -0
  9. package/.agents/skills/deft-directive-interview/SKILL.md +9 -0
  10. package/.agents/skills/deft-directive-pre-pr/SKILL.md +9 -0
  11. package/.agents/skills/deft-directive-refinement/SKILL.md +10 -0
  12. package/.agents/skills/deft-directive-release/SKILL.md +12 -0
  13. package/.agents/skills/deft-directive-review-cycle/SKILL.md +10 -0
  14. package/.agents/skills/deft-directive-setup/SKILL.md +10 -0
  15. package/.agents/skills/deft-directive-swarm/SKILL.md +10 -0
  16. package/.agents/skills/deft-directive-sync/SKILL.md +9 -0
  17. package/.agents/skills/deft-directive-triage/SKILL.md +9 -0
  18. package/.agents/skills/deft-directive-write-skill/SKILL.md +9 -0
  19. package/LICENSE.md +22 -0
  20. package/QUICK-START.md +167 -0
  21. package/UPGRADING.md +517 -0
  22. package/coding/build-output.md +28 -0
  23. package/coding/coding.md +235 -0
  24. package/coding/debugging.md +110 -0
  25. package/coding/holzmann.md +96 -0
  26. package/coding/hygiene.md +127 -0
  27. package/coding/security.md +158 -0
  28. package/coding/testing.md +162 -0
  29. package/coding/toolchain.md +44 -0
  30. package/commands.md +300 -0
  31. package/context/context.md +57 -0
  32. package/context/deterministic-split.md +67 -0
  33. package/context/examples.md +26 -0
  34. package/context/fractal-summaries.md +69 -0
  35. package/context/long-horizon.md +46 -0
  36. package/context/spec-deltas.md +177 -0
  37. package/context/tool-design.md +34 -0
  38. package/context/working-memory.md +62 -0
  39. package/contracts/boundary-maps.md +65 -0
  40. package/contracts/deterministic-questions.md +59 -0
  41. package/contracts/hierarchy.md +77 -0
  42. package/conventions/content-manifest.json +399 -0
  43. package/conventions/machine-generated-banner.md +130 -0
  44. package/conventions/references.md +120 -0
  45. package/conventions/rule-ownership.json +382 -0
  46. package/conventions/task-caching.md +43 -0
  47. package/conventions/vbrief-filenames.md +70 -0
  48. package/deployments/README.md +37 -0
  49. package/deployments/agentuity/README.md +138 -0
  50. package/deployments/agentuity/via-cli.md +380 -0
  51. package/deployments/agentuity/via-cloud.md +425 -0
  52. package/deployments/agentuity/via-github-actions.md +664 -0
  53. package/deployments/agentuity/via-gravity-network.md +606 -0
  54. package/deployments/agentuity/via-vpc.md +607 -0
  55. package/deployments/aws/README.md +38 -0
  56. package/deployments/aws/via-app-runner.md +612 -0
  57. package/deployments/aws/via-ecs-fargate.md +561 -0
  58. package/deployments/aws/via-elastic-beanstalk.md +628 -0
  59. package/deployments/aws/via-lambda.md +649 -0
  60. package/deployments/azure/README.md +37 -0
  61. package/deployments/azure/via-aks.md +390 -0
  62. package/deployments/azure/via-app-service.md +564 -0
  63. package/deployments/azure/via-container-apps.md +599 -0
  64. package/deployments/azure/via-functions.md +552 -0
  65. package/deployments/cloud-gov/README.md +63 -0
  66. package/deployments/cloud-gov/agents/compliance-docs.md +154 -0
  67. package/deployments/cloud-gov/agents.md +39 -0
  68. package/deployments/cloud-gov/cicd.md +64 -0
  69. package/deployments/cloud-gov/deployment.md +150 -0
  70. package/deployments/cloud-gov/logging.md +43 -0
  71. package/deployments/cloud-gov/manifest.md +121 -0
  72. package/deployments/cloud-gov/overview.md +58 -0
  73. package/deployments/cloud-gov/security.md +46 -0
  74. package/deployments/cloud-gov/services.md +72 -0
  75. package/deployments/cloud-gov/upstream/README.md +18 -0
  76. package/deployments/cloudflare/README.md +33 -0
  77. package/deployments/cloudflare/via-dashboard.md +83 -0
  78. package/deployments/cloudflare/via-git.md +90 -0
  79. package/deployments/cloudflare/via-github-actions.md +185 -0
  80. package/deployments/cloudflare/via-terraform.md +157 -0
  81. package/deployments/cloudflare/via-wrangler.md +165 -0
  82. package/deployments/fly-io/README.md +37 -0
  83. package/deployments/fly-io/via-dockerfile.md +648 -0
  84. package/deployments/fly-io/via-flyctl.md +653 -0
  85. package/deployments/fly-io/via-github-actions.md +695 -0
  86. package/deployments/fly-io/via-multi-region.md +598 -0
  87. package/deployments/google/README.md +34 -0
  88. package/deployments/google/via-app-engine.md +42 -0
  89. package/deployments/google/via-cloud-functions.md +23 -0
  90. package/deployments/google/via-cloud-run.md +330 -0
  91. package/deployments/google/via-gke.md +23 -0
  92. package/deployments/netlify/README.md +99 -0
  93. package/deployments/netlify/via-cli.md +17 -0
  94. package/deployments/netlify/via-functions.md +19 -0
  95. package/deployments/netlify/via-git.md +25 -0
  96. package/deployments/vercel/README.md +90 -0
  97. package/deployments/vercel/via-api.md +16 -0
  98. package/deployments/vercel/via-cli.md +17 -0
  99. package/deployments/vercel/via-git.md +24 -0
  100. package/docs/BROWNFIELD.md +179 -0
  101. package/docs/getting-started.md +137 -0
  102. package/docs/good-agents-md.md +137 -0
  103. package/events/README.md +89 -0
  104. package/events/event-record.schema.json +26 -0
  105. package/events/registry.json +166 -0
  106. package/events/registry.schema.json +71 -0
  107. package/glossary.md +145 -0
  108. package/incidents/README.md +81 -0
  109. package/incidents/_template.md +38 -0
  110. package/interfaces/cli.md +104 -0
  111. package/interfaces/rest.md +212 -0
  112. package/interfaces/tui.md +242 -0
  113. package/interfaces/web.md +123 -0
  114. package/languages/6502-DASM.md +132 -0
  115. package/languages/c.md +235 -0
  116. package/languages/commands.md +23 -0
  117. package/languages/cpp.md +132 -0
  118. package/languages/csharp.md +259 -0
  119. package/languages/dart.md +183 -0
  120. package/languages/delphi.md +218 -0
  121. package/languages/elixir.md +208 -0
  122. package/languages/go.md +78 -0
  123. package/languages/java.md +278 -0
  124. package/languages/javascript.md +163 -0
  125. package/languages/julia.md +175 -0
  126. package/languages/kotlin.md +193 -0
  127. package/languages/markdown.md +168 -0
  128. package/languages/mermaid.md +146 -0
  129. package/languages/officejs.md +392 -0
  130. package/languages/python.md +209 -0
  131. package/languages/r.md +163 -0
  132. package/languages/rust.md +216 -0
  133. package/languages/sql.md +216 -0
  134. package/languages/swift.md +153 -0
  135. package/languages/typescript.md +132 -0
  136. package/languages/vba.md +279 -0
  137. package/languages/vhdl.md +180 -0
  138. package/languages/visual-basic.md +151 -0
  139. package/languages/zig.md +196 -0
  140. package/meta/SOUL.md +27 -0
  141. package/meta/code-field.md +44 -0
  142. package/meta/morals.md +40 -0
  143. package/meta/philosophy.md +39 -0
  144. package/meta/project.md +49 -0
  145. package/meta/ralph.md +223 -0
  146. package/meta/security.md +80 -0
  147. package/meta/versioning.md +326 -0
  148. package/package.json +22 -0
  149. package/packs/lessons/lessons-pack-0.1.json +553 -0
  150. package/packs/patterns/patterns-pack-0.1.json +57 -0
  151. package/packs/rules/rules-pack-0.1.json +4767 -0
  152. package/packs/skills/skills-pack-0.1.json +262 -0
  153. package/packs/strategies/strategies-pack-0.1.json +167 -0
  154. package/packs/swarm-spec/swarm-spec-pack-0.1.json +17 -0
  155. package/patterns/executor-layer-credentials.md +227 -0
  156. package/patterns/llm-app.md +156 -0
  157. package/patterns/multi-agent.md +278 -0
  158. package/patterns/prompt-assembly-layer-ordering.md +154 -0
  159. package/patterns/role-as-overlay.md +179 -0
  160. package/platforms/2600.md +137 -0
  161. package/platforms/unity.md +329 -0
  162. package/references/composer-skill-porting.md +152 -0
  163. package/references/cost-models.md +163 -0
  164. package/references/ip-risk.md +246 -0
  165. package/references/plain-english-ux.md +275 -0
  166. package/resilience/context-pruning.md +67 -0
  167. package/resilience/continue-here.md +62 -0
  168. package/scm/changelog.md +276 -0
  169. package/scm/git.md +139 -0
  170. package/scm/github.md +265 -0
  171. package/secrets/.gitkeep +0 -0
  172. package/skills/deft-build/SKILL.md +20 -0
  173. package/skills/deft-directive-article-review/SKILL.md +156 -0
  174. package/skills/deft-directive-build/SKILL.md +302 -0
  175. package/skills/deft-directive-cost/SKILL.md +201 -0
  176. package/skills/deft-directive-debug/SKILL.md +140 -0
  177. package/skills/deft-directive-decompose/SKILL.md +96 -0
  178. package/skills/deft-directive-gh-arch/SKILL.md +160 -0
  179. package/skills/deft-directive-gh-slice/SKILL.md +199 -0
  180. package/skills/deft-directive-glossary/SKILL.md +118 -0
  181. package/skills/deft-directive-interview/SKILL.md +528 -0
  182. package/skills/deft-directive-pre-pr/SKILL.md +131 -0
  183. package/skills/deft-directive-probe/SKILL.md +127 -0
  184. package/skills/deft-directive-refinement/SKILL.md +403 -0
  185. package/skills/deft-directive-release/SKILL.md +266 -0
  186. package/skills/deft-directive-review-cycle/SKILL.md +401 -0
  187. package/skills/deft-directive-setup/SKILL.md +717 -0
  188. package/skills/deft-directive-swarm/SKILL.md +989 -0
  189. package/skills/deft-directive-sync/SKILL.md +288 -0
  190. package/skills/deft-directive-triage/SKILL.md +137 -0
  191. package/skills/deft-directive-write-skill/SKILL.md +169 -0
  192. package/skills/deft-interview/SKILL.md +16 -0
  193. package/skills/deft-pre-pr/SKILL.md +16 -0
  194. package/skills/deft-review-cycle/SKILL.md +16 -0
  195. package/skills/deft-roadmap-refresh/SKILL.md +16 -0
  196. package/skills/deft-setup/SKILL.md +20 -0
  197. package/skills/deft-swarm/SKILL.md +16 -0
  198. package/skills/deft-sync/SKILL.md +16 -0
  199. package/strategies/README.md +83 -0
  200. package/strategies/artifact-guards.md +85 -0
  201. package/strategies/bdd.md +115 -0
  202. package/strategies/brownfield.md +7 -0
  203. package/strategies/discuss.md +129 -0
  204. package/strategies/emit-hints.md +69 -0
  205. package/strategies/enterprise.md +193 -0
  206. package/strategies/interview.md +551 -0
  207. package/strategies/map.md +179 -0
  208. package/strategies/probe.md +151 -0
  209. package/strategies/rapid.md +155 -0
  210. package/strategies/research.md +155 -0
  211. package/strategies/roadmap.md +9 -0
  212. package/strategies/speckit.md +437 -0
  213. package/strategies/v0-20-contract.md +134 -0
  214. package/strategies/yolo.md +169 -0
  215. package/swarm/swarm.md +300 -0
  216. package/templates/COST-ESTIMATE.md +114 -0
  217. package/templates/PULL_REQUEST_TEMPLATE.md +35 -0
  218. package/templates/agent-prompt-preamble.md +409 -0
  219. package/templates/agents-entry.md +211 -0
  220. package/templates/agents-entry.placeholders.md +75 -0
  221. package/templates/embed.go +20 -0
  222. package/templates/embed_test.go +36 -0
  223. package/templates/make-spec-example.md +9 -0
  224. package/templates/make-spec.md +246 -0
  225. package/templates/project.md.template +52 -0
  226. package/templates/specification.md +1 -0
  227. package/templates/swarm-greptile-poller-prompt.md +556 -0
  228. package/templates/user.md.template +31 -0
  229. package/tools/RWLDL.md +80 -0
  230. package/tools/greptile.md +141 -0
  231. package/tools/installer.md +23 -0
  232. package/tools/taskfile-migration.md +32 -0
  233. package/tools/taskfile.md +185 -0
  234. package/tools/telemetry.md +285 -0
  235. package/vbrief/schemas/cache-meta.schema.json +137 -0
  236. package/vbrief/schemas/candidates.schema.json +130 -0
  237. package/vbrief/schemas/codebase-map.schema.json +213 -0
  238. package/vbrief/schemas/lessons-pack.schema.json +134 -0
  239. package/vbrief/schemas/patterns-pack.schema.json +84 -0
  240. package/vbrief/schemas/rules-pack.schema.json +105 -0
  241. package/vbrief/schemas/skills-pack.schema.json +94 -0
  242. package/vbrief/schemas/slices.schema.json +87 -0
  243. package/vbrief/schemas/strategies-pack.schema.json +89 -0
  244. package/vbrief/schemas/swarm-spec-pack.schema.json +84 -0
  245. package/vbrief/schemas/vbrief-core.schema.json +1022 -0
  246. package/vbrief/vbrief.md +684 -0
  247. package/verification/integration.md +76 -0
  248. package/verification/plan-checking.md +85 -0
  249. package/verification/uat.md +60 -0
  250. package/verification/verification.md +117 -0
package/languages/r.md ADDED
@@ -0,0 +1,163 @@
1
+ # R Standards
2
+
3
+ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
4
+
5
+ **⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md)
6
+
7
+ **Stack**: R 4.3+, tidyverse; Packages: devtools/usethis; Testing: testthat 3; Docs: roxygen2; Lint: lintr; Style: styler
8
+
9
+ ## Standards
10
+
11
+ ### Documentation
12
+ - ! roxygen2 comments (`#'`) for all exported functions, classes, and datasets
13
+ - ! Document `@param`, `@return`, `@examples`, `@export` for public functions
14
+ - ! Include a `README.Rmd` or `README.md` for packages
15
+ - ~ Use `@seealso` and `@family` to cross-reference related functions
16
+
17
+ ### Testing
18
+ See [testing.md](../coding/testing.md).
19
+
20
+ - ! Use testthat 3 (`test_that()`, `expect_*()`)
21
+ - ! Place tests in `tests/testthat/`; files: `test-*.R`
22
+ - ~ Use snapshot tests (`expect_snapshot()`) for complex output
23
+
24
+ ### Coverage
25
+ - ! ≥85% coverage (measured via covr)
26
+ - ! Count R/\*
27
+ - ! Exclude entry points, generated files, vignettes
28
+
29
+ ### Style
30
+ - ! Follow [Tidyverse Style Guide](https://style.tidyverse.org/)
31
+ - ! Use lintr for static analysis (project `.lintr` config checked in)
32
+ - ! Use styler for auto-formatting
33
+ - ! 2-space indentation, no tabs
34
+ - ! Line length ≤80 characters
35
+
36
+ ### Naming Conventions
37
+ - ! `snake_case` for functions, variables, and file names: `read_data()`, `user_count`
38
+ - ! `PascalCase` for R6/S4 class names: `DataProcessor`, `ModelConfig`
39
+ - ! `UPPER_SNAKE_CASE` for true constants
40
+ - ! Prefix internal/non-exported functions with `.`: `.validate_input()`
41
+ - ⊗ Dots in function names for new code (`read.csv` style): use `snake_case`
42
+ - ⊗ Single-letter variable names except in math/formula contexts (`x`, `y`, `n`)
43
+
44
+ ### Types & Data
45
+ - ! Use tibbles (`tibble`/`data.frame`) over lists for tabular data
46
+ - ! Use explicit types: `integer(1)`, `character(0)`, `logical(1)` for scalars
47
+ - ~ Use `rlang::check_required()` / `rlang::abort()` for argument validation
48
+ - ~ Use named lists or S3/R6 classes for structured non-tabular data
49
+ - ⊗ Use `T`/`F` — always spell out `TRUE`/`FALSE`
50
+ - ⊗ Rely on partial argument matching
51
+
52
+ ### Functions
53
+ - ! Pure functions preferred: same inputs → same outputs, no side effects
54
+ - ! One function per purpose; keep under 50 lines where practical
55
+ - ! Use `...` (dots) deliberately; document what they pass to
56
+ - ⊗ Modify global state from inside functions (`<<-`, `assign()` to `.GlobalEnv`)
57
+ - ~ Use `invisible()` for functions called for side effects that return invisibly
58
+ - ~ Use `tryCatch()` / `withCallingHandlers()` for error handling
59
+
60
+ ### Dependencies
61
+ - ! Minimize dependencies; use `Imports` not `Depends` in DESCRIPTION
62
+ - ! Pin major versions in `renv.lock` for reproducibility
63
+ - ! Use `renv` for project-level dependency isolation
64
+ - ⊗ Use `library()` inside package code — use `::` or `@importFrom`
65
+ - ~ Use `Suggests` for test/vignette-only dependencies
66
+
67
+ ### Vectorization & Performance
68
+ - ! Prefer vectorized operations over explicit loops
69
+ - ~ Use `purrr::map()` family for functional iteration
70
+ - ~ Use `data.table` or `dplyr` for data manipulation (not base `for` loops on data frames)
71
+ - ≉ Use `apply()` family when `purrr` or vectorized alternatives exist
72
+ - ≉ Grow vectors in a loop (`c(vec, new_elem)`) — pre-allocate instead
73
+
74
+ ### Pipelines
75
+ - ! Use native pipe `|>` (R 4.1+) or `%>%` from magrittr
76
+ - ! Keep pipe chains readable (one operation per line)
77
+ - ≉ Pipe chains longer than 10 steps — extract into named intermediate variables or functions
78
+ - ~ Use `.data` and `.env` pronouns in tidy evaluation for clarity
79
+
80
+ ### Reproducibility
81
+ - ! Use `renv` for project dependency snapshots
82
+ - ! Set `set.seed()` before any stochastic operation; document seed in reports
83
+ - ! Use relative paths; ⊗ absolute paths or `setwd()`
84
+ - ~ Use `here::here()` for project-relative paths
85
+ - ~ Use Quarto or R Markdown for reproducible reports
86
+
87
+ ### Security
88
+ - ⊗ Hardcode secrets or credentials in source
89
+ - ! Validate/sanitize all external inputs (file paths, user data, API responses)
90
+ - ~ Use `.Renviron` for secrets; load via `Sys.getenv()`
91
+
92
+ ### Telemetry
93
+ - ~ Structured logging (logger, futile.logger) for production
94
+ - ? OpenTelemetry (via REST/Python bridge) for distributed tracing
95
+
96
+ ## Commands
97
+
98
+ See [commands.md](./commands.md).
99
+
100
+ ## Patterns
101
+
102
+ ### Testing (testthat 3)
103
+ ```r
104
+ test_that("calculate_mean returns correct mean", {
105
+ expect_equal(calculate_mean(c(1, 2, 3)), 2)
106
+ expect_equal(calculate_mean(c(10, 20)), 15)
107
+ })
108
+
109
+ test_that("calculate_mean errors on non-numeric input", {
110
+ expect_error(calculate_mean("abc"), "must be numeric")
111
+ })
112
+
113
+ test_that("calculate_mean handles NA with na.rm", {
114
+ expect_equal(calculate_mean(c(1, NA, 3), na.rm = TRUE), 2)
115
+ expect_equal(calculate_mean(c(1, NA, 3), na.rm = FALSE), NA_real_)
116
+ })
117
+ ```
118
+
119
+ ### roxygen2 Documentation
120
+ ```r
121
+ #' @param x Numeric vector. @param weights Numeric vector (same length). @param na.rm Remove NAs?
122
+ #' @return Single numeric. @export
123
+ weighted_mean <- function(x, weights, na.rm = FALSE) {
124
+ stopifnot(is.numeric(x), is.numeric(weights), length(x) == length(weights))
125
+ if (na.rm) { keep <- !is.na(x) & !is.na(weights); x <- x[keep]; weights <- weights[keep] }
126
+ sum(x * weights) / sum(weights)
127
+ }
128
+ ```
129
+
130
+ ### Tidy Pipeline
131
+ ```r
132
+ summary_by_group <- raw_data |>
133
+ filter(!is.na(value)) |> group_by(category) |>
134
+ summarise(mean_val = mean(value), n = n(), .groups = "drop") |>
135
+ arrange(desc(mean_val))
136
+ ```
137
+
138
+ ### Error Handling (rlang)
139
+ ```r
140
+ read_config <- function(path) {
141
+ if (!file.exists(path)) rlang::abort(paste0("Config not found: ", path), class = "config_not_found_error")
142
+ tryCatch(yaml::read_yaml(path), error = function(e) rlang::abort("Failed to parse config", parent = e))
143
+ }
144
+ ```
145
+
146
+ ## Anti-Patterns
147
+
148
+ Items marked ⊗ in Standards above are not repeated here.
149
+
150
+ - ≉ **Dot-separated names** (`my.function`): Use `snake_case`
151
+ - ≉ **`sapply()`**: Use `vapply()` or `purrr::map_*()`
152
+ - ≉ **Pipe chains >10 steps**: Extract named intermediates
153
+
154
+ ## Compliance Checklist
155
+
156
+ - ! roxygen2 docs on all exported functions
157
+ - ! See [testing.md](../coding/testing.md) for testing requirements
158
+ - ! testthat 3 for unit tests; ≥85% coverage via covr
159
+ - ! lintr + styler configured and enforced
160
+ - ! Tidyverse style; `snake_case` naming; `TRUE`/`FALSE` spelled out
161
+ - ! `renv` for dependency reproducibility
162
+ - ⊗ `T`/`F`, `<<-`, `setwd()`, `library()` in packages, absolute paths
163
+ - ! Run `task check` before commit
@@ -0,0 +1,216 @@
1
+ # Rust Standards
2
+
3
+ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
4
+
5
+ **⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md)
6
+
7
+ **Stack**: Rust (latest stable); Build: Cargo; Testing: built-in `#[test]` + proptest; Lint: clippy; Format: rustfmt; Docs: rustdoc
8
+
9
+ ## Standards
10
+
11
+ ### Documentation
12
+ - ! rustdoc comments (`///`) on all public items (functions, structs, enums, traits, modules)
13
+ - ! Include `# Examples` section with runnable doc-tests for public API
14
+ - ! Module-level docs (`//!`) explaining purpose and usage
15
+ - ~ Use `# Errors`, `# Panics`, `# Safety` sections where applicable
16
+ - ⊗ `#[allow(missing_docs)]` on public items without justification
17
+
18
+ ### Testing
19
+ See [testing.md](../coding/testing.md).
20
+
21
+ - ! Unit tests in `#[cfg(test)] mod tests` at bottom of each module
22
+ - ! Integration tests in `tests/` directory for public API
23
+ - ! Use `#[should_panic]` or `assert!(result.is_err())` for error cases
24
+ - ~ Use proptest or quickcheck for property-based testing
25
+ - ~ Use doc-tests as living examples (they run during `cargo test`)
26
+
27
+ ### Coverage
28
+ - ! ≥80% coverage (measured via cargo-tarpaulin or llvm-cov)
29
+ - ! Count src/**
30
+ - ! Exclude main.rs entry points, generated code, build scripts
31
+
32
+ ### Style
33
+ - ! Run rustfmt on all code (project `rustfmt.toml` checked in)
34
+ - ! Run clippy with `#![deny(clippy::all)]` at crate level
35
+ - ! `#![deny(clippy::pedantic)]` for library crates
36
+ - ! 4-space indentation (rustfmt default)
37
+ - ! Line length ≤100 characters
38
+ - ~ Use `#![warn(clippy::nursery)]` for additional catches
39
+
40
+ ### Naming Conventions
41
+ - ! `snake_case` for functions, methods, variables, modules, crate names
42
+ - ! `PascalCase` for types (structs, enums, traits), type parameters
43
+ - ! `SCREAMING_SNAKE_CASE` for constants and statics
44
+ - ! Prefix lifetime parameters with `'`: `'a`, `'input`
45
+ - ! Trait names: prefer adjective/verb forms: `Display`, `Iterator`, `Send`
46
+ - ⊗ Hungarian notation or type prefixes
47
+ - ~ Getter methods: use field name directly (`fn name(&self)` not `fn get_name`)
48
+
49
+ ### Ownership & Borrowing
50
+ - ! Prefer borrowing (`&T`, `&mut T`) over cloning
51
+ - ! Use `Clone` only when ownership transfer is truly needed
52
+ - ! Prefer `&str` over `String` in function parameters
53
+ - ! Prefer `&[T]` over `Vec<T>` in function parameters
54
+ - ⊗ `.unwrap()` or `.expect()` in library code — return `Result` or `Option`
55
+ - ~ Use `Cow<'_, str>` when a function may or may not need to allocate
56
+ - ≉ Excessive `.clone()` to appease the borrow checker — redesign ownership
57
+
58
+ ### Error Handling
59
+ - ! Use `Result<T, E>` for recoverable errors; define custom error types
60
+ - ! Use `thiserror` for library error types; `anyhow` for application error types
61
+ - ! Implement `std::error::Error` for all custom error types
62
+ - ! Use `?` operator for error propagation
63
+ - ⊗ `.unwrap()` in production code (except after infallible checks with comments)
64
+ - ⊗ `panic!()` for expected error conditions
65
+ - ~ Use `#[must_use]` on functions returning `Result` or important values
66
+
67
+ ### Concurrency
68
+ - ! Use `Send` + `Sync` bounds correctly; understand their implications
69
+ - ! Prefer channels (`mpsc`, `crossbeam`) over shared mutable state
70
+ - ! Use `Arc<Mutex<T>>` or `Arc<RwLock<T>>` when shared state is necessary
71
+ - ⊗ `unsafe` to circumvent Send/Sync bounds
72
+ - ~ Use `tokio` or `async-std` for async I/O; avoid mixing runtimes
73
+ - ~ Prefer `RwLock` over `Mutex` for read-heavy workloads
74
+
75
+ ### Unsafe Code
76
+ - ! Minimize `unsafe` blocks; isolate behind safe abstractions
77
+ - ! Document `# Safety` section explaining invariants for every `unsafe fn`
78
+ - ! Document `// SAFETY:` comment on every `unsafe` block explaining why it's sound
79
+ - ⊗ `unsafe` without clear justification and safety proof
80
+ - ~ Use `#![forbid(unsafe_code)]` for crates that don't need it
81
+
82
+ ### Dependencies
83
+ - ! Pin dependencies in `Cargo.lock` (always commit for binaries)
84
+ - ! Audit dependencies with `cargo-audit`
85
+ - ! Minimize dependency count; prefer `std` library functionality
86
+ - ~ Use `cargo-deny` to enforce license and duplicate dependency policies
87
+ - ≉ `*` version specifiers in `Cargo.toml`
88
+
89
+ ### Performance
90
+ - ! Use iterators and zero-cost abstractions over manual loops where idiomatic
91
+ - ! Prefer stack allocation; use `Box<T>` only when heap is necessary
92
+ - ~ Use `#[inline]` sparingly and only with benchmarks to justify
93
+ - ~ Profile with `criterion` for benchmarks; `perf` or `flamegraph` for profiling
94
+ - ≉ Premature optimization over readability
95
+
96
+ ### Macros
97
+ - ~ Prefer functions and generics over macros when possible
98
+ - ! Document all `macro_rules!` with examples
99
+ - ! Keep macro complexity minimal; extract logic into functions
100
+ - ⊗ Macros that generate non-obvious control flow
101
+
102
+ ### Security
103
+ - ⊗ Hardcode secrets or credentials in source
104
+ - ! Validate all external inputs (file paths, network data, user input)
105
+ - ! Use `secrecy` crate for sensitive values (keys, tokens)
106
+ - ~ Use `zeroize` for clearing secrets from memory
107
+
108
+ ### Telemetry
109
+ - ~ Use `tracing` crate for structured, async-aware logging
110
+ - ~ Use `tracing-opentelemetry` for distributed tracing
111
+ - ? Use `metrics` crate for Prometheus-compatible metrics
112
+
113
+ ## Commands
114
+
115
+ See [commands.md](./commands.md).
116
+
117
+ ## Patterns
118
+
119
+ ### Error Handling (thiserror)
120
+ ```rust
121
+ #[derive(Debug, thiserror::Error)]
122
+ pub enum AppError {
123
+ #[error("config not found: {path}")] ConfigNotFound { path: String },
124
+ #[error("invalid config: {0}")] InvalidConfig(String),
125
+ #[error(transparent)] Io(#[from] std::io::Error),
126
+ }
127
+
128
+ pub fn load_config(path: &str) -> Result<Config, AppError> {
129
+ if !std::path::Path::new(path).exists() {
130
+ return Err(AppError::ConfigNotFound { path: path.to_string() });
131
+ }
132
+ let content = std::fs::read_to_string(path)?;
133
+ parse_config(&content).map_err(AppError::InvalidConfig)
134
+ }
135
+ ```
136
+
137
+ ### Testing (Table-Driven)
138
+ ```rust
139
+ #[cfg(test)]
140
+ mod tests {
141
+ use super::*;
142
+ #[test]
143
+ fn test_parse_amount() {
144
+ let cases = [("100", Ok(100)), ("0", Ok(0)), ("-5", Err("negative")), ("abc", Err("invalid"))];
145
+ for (input, expected) in cases {
146
+ match expected {
147
+ Ok(val) => assert_eq!(parse_amount(input).unwrap(), val, "{input}"),
148
+ Err(msg) => assert!(parse_amount(input).unwrap_err().to_string().contains(msg), "{input}"),
149
+ }
150
+ }
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Builder Pattern
156
+ ```rust
157
+ #[derive(Debug, Default)]
158
+ pub struct RequestBuilder { url: String, timeout: Option<u64>, headers: Vec<(String, String)> }
159
+
160
+ impl RequestBuilder {
161
+ pub fn new(url: impl Into<String>) -> Self { Self { url: url.into(), ..Default::default() } }
162
+ pub fn timeout(mut self, secs: u64) -> Self { self.timeout = Some(secs); self }
163
+ pub fn header(mut self, k: impl Into<String>, v: impl Into<String>) -> Self {
164
+ self.headers.push((k.into(), v.into())); self
165
+ }
166
+ pub fn build(self) -> Result<Request, BuildError> { Ok(Request { /* ... */ }) }
167
+ }
168
+ ```
169
+
170
+ ### Structured Logging (tracing)
171
+ ```rust
172
+ #[instrument(skip(db), fields(user_id = %user_id))]
173
+ pub async fn get_user(db: &Pool, user_id: i64) -> Result<User, AppError> {
174
+ info!("fetching user");
175
+ let user = db.query_one("SELECT ...", &[&user_id]).await?;
176
+ if user.is_inactive() { warn!("inactive user accessed"); }
177
+ Ok(user)
178
+ }
179
+ ```
180
+
181
+ ## Anti-Patterns
182
+
183
+ Items marked ⊗ in Standards above are not repeated here.
184
+
185
+ - ≉ **`Arc<Mutex<T>>` as first resort**: Consider channels/message passing
186
+ - ≉ **Stringly-typed errors**: Use `thiserror`
187
+ - ≉ **God-struct with many `Option` fields**: Use builder pattern or state types
188
+ - ≉ **`Box<dyn Error>` in libraries**: Define specific error enums
189
+
190
+ ## Hygiene
191
+
192
+ **Types:**
193
+ - ⊗ `dyn Any` or `Box<dyn Any>` where a concrete type or typed trait object is knowable
194
+ - ⊗ `#[allow(unused)]` or `#[allow(dead_code)]` attributes to suppress rather than remove dead code
195
+
196
+ **Error handling:**
197
+ - ⊗ `.unwrap()` or `.expect()` outside test code — use `?` or explicit match
198
+ - ⊗ `let _ = result` to silently ignore a `Result` or `Option` — handle or document why safe
199
+ - ⊗ Match arms `_ => {}` or `Err(_) => {}` that swallow errors without logging or propagating
200
+
201
+ **Dead code:**
202
+ - ~ `cargo check` warns on unused items; `cargo clippy` detects dead helpers and unreachable branches
203
+ - ~ Use `cargo +nightly udeps` to detect unused dependencies in `Cargo.toml`
204
+ - ⊗ Commented-out code — delete; version control preserves history
205
+
206
+ ## Compliance Checklist
207
+
208
+ - ! rustdoc on all public items with examples
209
+ - ! See [testing.md](../coding/testing.md) for testing requirements
210
+ - ! Unit + integration tests; ≥80% coverage
211
+ - ! rustfmt + clippy (pedantic for libs) enforced
212
+ - ! Custom error types via thiserror/anyhow; no `.unwrap()` in production
213
+ - ! `unsafe` minimized, documented, and justified
214
+ - ! `Cargo.lock` committed (binaries); `cargo-audit` clean
215
+ - ⊗ `.unwrap()`, `panic!()`, unguarded `unsafe`, excessive `.clone()`
216
+ - ! Run `task check` before commit
@@ -0,0 +1,216 @@
1
+ # SQL Standards
2
+
3
+ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
4
+
5
+ **⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md)
6
+
7
+ **Stack**: ANSI SQL (dialect-agnostic defaults); Adapts to: PostgreSQL, MySQL/MariaDB, SQL Server, SQLite, Oracle; Migrations: Flyway / Liquibase / framework-native; Lint: sqlfluff
8
+
9
+ ## Standards
10
+
11
+ ### Documentation
12
+ - ! Comment every non-trivial query, view, function, and stored procedure
13
+ - ! Document purpose, parameters, and return values for stored procedures/functions
14
+ - ! Include a data dictionary or schema docs for every database
15
+ - ~ Use inline comments (`--`) for clause-level explanations in complex queries
16
+
17
+ ### Testing
18
+ See [testing.md](../coding/testing.md).
19
+
20
+ - ! Test migrations up and down (rollback)
21
+ - ! Test stored procedures, functions, and triggers with known inputs/outputs
22
+ - ~ Use test fixtures or seed data scripts for reproducible integration tests
23
+ - ~ Test edge cases: NULLs, empty sets, boundary values, large datasets
24
+
25
+ ### Style & Formatting
26
+ - ! UPPERCASE for SQL keywords: `SELECT`, `FROM`, `WHERE`, `JOIN`, `INSERT`, `UPDATE`
27
+ - ! Lowercase for identifiers (tables, columns, aliases): `users`, `created_at`
28
+ - ! One clause per line for readability (`SELECT`, `FROM`, `WHERE`, `JOIN` each on own line)
29
+ - ! Indent continuation lines (subqueries, `AND`/`OR`, `CASE` branches)
30
+ - ! Use sqlfluff (or equivalent) for automated linting
31
+ - ! Line length ≤120 characters
32
+ - ~ Align `ON` clauses vertically when multiple joins are present
33
+
34
+ ### Naming Conventions
35
+ - ! `snake_case` for all identifiers: tables, columns, indexes, constraints
36
+ - ! Singular nouns for table names: `user`, `order`, `product` (not `users`, `orders`)
37
+ - ! Descriptive column names: `created_at`, `is_active`, `total_amount`
38
+ - ! Prefix boolean columns with `is_`, `has_`, or `can_`: `is_active`, `has_shipped`
39
+ - ! Name primary keys `id` or `{table}_id`; foreign keys `{referenced_table}_id`
40
+ - ! Name indexes: `ix_{table}_{column(s)}`
41
+ - ! Name constraints: `pk_{table}`, `fk_{table}_{ref_table}`, `uq_{table}_{column}`, `ck_{table}_{rule}`
42
+ - ⊗ Reserved words as identifiers (even if quoted)
43
+ - ⊗ Abbreviations in names unless universally understood (`id`, `url`, `ip`)
44
+
45
+ ### Queries
46
+ - ! Use explicit column lists — ⊗ `SELECT *` in application code or views
47
+ - ! Use explicit `JOIN` syntax — ⊗ implicit joins (comma-separated `FROM`)
48
+ - ! Qualify column names with table aliases in multi-table queries
49
+ - ! Use short, meaningful aliases: `u` for `user`, `o` for `order`
50
+ - ! Use `COALESCE()` over vendor-specific null functions (`NVL`, `IFNULL`) where portable
51
+ - ~ Use CTEs (`WITH`) for complex queries instead of deeply nested subqueries
52
+ - ~ Use `EXISTS` over `IN` for correlated subqueries (better optimizer hints)
53
+ - ≉ `SELECT DISTINCT` to mask duplicate-producing joins — fix the join instead
54
+ - ≉ `ORDER BY` column position (`ORDER BY 1, 2`) — use column names
55
+
56
+ ### Parameterization & Security
57
+ - ! Use parameterized queries / prepared statements for all dynamic values
58
+ - ⊗ String concatenation for query building (SQL injection vector)
59
+ - ⊗ Interpolating user input directly into SQL
60
+ - ! Validate and sanitize inputs at the application layer before query execution
61
+ - ! Apply least-privilege: application accounts get only required permissions
62
+ - ~ Use row-level security (RLS) where supported for multi-tenant data
63
+
64
+ ### Schema Design
65
+ - ! Every table has a primary key
66
+ - ! Use appropriate data types: don't store dates as strings, money as floats, etc.
67
+ - ! Define foreign key constraints for referential integrity
68
+ - ! Add `NOT NULL` constraints where business logic requires a value
69
+ - ! Add `CHECK` constraints for domain validation (e.g., `CHECK (quantity >= 0)`)
70
+ - ~ Normalize to 3NF minimum; denormalize deliberately with documentation
71
+ - ~ Add `created_at` and `updated_at` timestamps to mutable tables
72
+ - ~ Use `UUID` or `BIGINT` for primary keys (prefer `UUID` for distributed systems)
73
+ - ≉ Store JSON blobs where relational columns would serve better
74
+ - ⊗ Use `FLOAT`/`DOUBLE` for monetary values — use `DECIMAL`/`NUMERIC`
75
+
76
+ ### Indexing
77
+ - ! Index all foreign key columns
78
+ - ! Index columns used in `WHERE`, `JOIN`, `ORDER BY` if query frequency justifies it
79
+ - ! Review and document index strategy per table
80
+ - ~ Use composite indexes that match query patterns (leftmost prefix rule)
81
+ - ~ Use partial/filtered indexes for frequently queried subsets
82
+ - ≉ Over-index: each index adds write overhead — justify with query patterns
83
+ - ⊗ Index every column "just in case"
84
+
85
+ ### Migrations
86
+ - ! Use versioned, sequential migration files (not ad-hoc DDL)
87
+ - ! Every migration must be reversible (up + down)
88
+ - ! Test migrations against a copy of production schema before deploying
89
+ - ! Use transactions for DDL where supported (PostgreSQL)
90
+ - ~ Use idempotent migrations (`IF NOT EXISTS`, `IF EXISTS`) for resilience
91
+ - ⊗ Modify or delete previously applied migration files
92
+
93
+ ### Transactions & Concurrency
94
+ - ! Use explicit transactions for multi-statement operations
95
+ - ! Keep transactions as short as possible
96
+ - ! Choose appropriate isolation level for the use case
97
+ - ~ Use `SELECT ... FOR UPDATE` when reading rows that will be updated
98
+ - ⊗ Long-running transactions that hold locks across user interactions
99
+ - ⊗ Implicit autocommit for multi-step business operations
100
+
101
+ ### Performance
102
+ - ! Use `EXPLAIN` / `EXPLAIN ANALYZE` to validate query plans for critical queries
103
+ - ! Avoid N+1 query patterns — use joins or batch queries
104
+ - ! Paginate large result sets (`LIMIT`/`OFFSET` or keyset pagination)
105
+ - ~ Prefer keyset pagination (`WHERE id > ?`) over `OFFSET` for large tables
106
+ - ~ Use materialized views or caching for expensive, infrequently-changing aggregations
107
+ - ≉ Functions on indexed columns in `WHERE` clauses (defeats index usage)
108
+ - ⊗ Cartesian joins (missing `ON` / `WHERE` clause)
109
+ - ⊗ Unbounded `SELECT` without `LIMIT` on large tables in application code
110
+
111
+ ### Stored Procedures & Functions
112
+ - ~ Keep business logic in the application layer; use procedures for data-intensive ops
113
+ - ! Document parameters, return types, and side effects
114
+ - ! Handle errors explicitly (`RAISE` / `SIGNAL` / `THROW`)
115
+ - ⊗ Deeply nested stored procedure call chains (hard to debug and test)
116
+
117
+ ### Telemetry
118
+ - ~ Log slow queries (configure slow query log threshold)
119
+ - ~ Monitor index usage and table bloat
120
+ - ? Use query tagging (comments with trace IDs) for distributed tracing
121
+
122
+ ## Commands
123
+
124
+ ```bash
125
+ task db:migrate # Run pending migrations
126
+ task db:rollback # Roll back last migration
127
+ task db:seed # Load seed/fixture data
128
+ task db:reset # Drop, create, migrate, seed
129
+ task db:lint # Lint SQL with sqlfluff (or `task sql:lint`)
130
+ task db:format # Format SQL with sqlfluff fix (or `task sql:fmt`)
131
+ task db:schema # Dump current schema
132
+ task quality # All quality checks
133
+ ```
134
+
135
+ **Note**: Single-language projects ! use generic names. Multi-language projects ! use namespaced names. See [taskfile.md](../tools/taskfile.md#naming-conventions).
136
+
137
+ ## Patterns
138
+
139
+ ### Parameterized Query (Application Code)
140
+ ```sql
141
+ -- CORRECT: parameterized
142
+ SELECT id, email, created_at
143
+ FROM user
144
+ WHERE email = $1
145
+ AND is_active = TRUE;
146
+
147
+ -- Framework equivalent (pseudocode):
148
+ -- db.query("SELECT id, email FROM user WHERE email = $1", [user_email])
149
+ ```
150
+
151
+ ### CTE for Readability
152
+ ```sql
153
+ WITH active_orders AS (
154
+ SELECT o.user_id, COUNT(*) AS order_count, SUM(o.total_amount) AS total_spent
155
+ FROM order AS o
156
+ WHERE o.status = 'active'
157
+ AND o.created_at >= CURRENT_DATE - INTERVAL '30 days'
158
+ GROUP BY o.user_id
159
+ )
160
+ SELECT u.id, u.email, ao.order_count, ao.total_spent
161
+ FROM user AS u
162
+ INNER JOIN active_orders AS ao ON ao.user_id = u.id
163
+ WHERE ao.total_spent > 100.00
164
+ ORDER BY ao.total_spent DESC;
165
+ ```
166
+
167
+ ### Migration (Flyway-style)
168
+ ```sql
169
+ -- V2__add_user_preferences.sql
170
+
171
+ -- Up
172
+ CREATE TABLE IF NOT EXISTS user_preference (
173
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
174
+ user_id UUID NOT NULL REFERENCES user (id) ON DELETE CASCADE,
175
+ key VARCHAR(100) NOT NULL,
176
+ value TEXT,
177
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
178
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
179
+ CONSTRAINT uq_user_preference_key UNIQUE (user_id, key)
180
+ );
181
+
182
+ CREATE INDEX ix_user_preference_user_id ON user_preference (user_id);
183
+
184
+ -- Down (in separate file or rollback section)
185
+ -- DROP TABLE IF EXISTS user_preference;
186
+ ```
187
+
188
+ ### Keyset Pagination
189
+ ```sql
190
+ -- Efficient pagination for large tables (avoids OFFSET scan)
191
+ SELECT id, email, created_at
192
+ FROM user
193
+ WHERE created_at < $1 -- last seen timestamp
194
+ AND id < $2 -- tiebreaker
195
+ ORDER BY created_at DESC, id DESC
196
+ LIMIT 25;
197
+ ```
198
+
199
+ ## Anti-Patterns
200
+
201
+ Items marked ⊗ in Standards above are not repeated here.
202
+
203
+ - ≉ **`HAVING` without `GROUP BY`**: Use `WHERE` for row-level filters
204
+ - ≉ **Nested subqueries >2 levels deep**: Refactor with CTEs
205
+ - ≉ **`NOT IN` with nullable columns**: Use `NOT EXISTS` instead (NULL semantics)
206
+
207
+ ## Compliance Checklist
208
+
209
+ - ! Parameterized queries for all user-facing data access
210
+ - ! Explicit column lists, explicit `JOIN` syntax, qualified column names
211
+ - ! Primary key on every table; foreign keys with constraints
212
+ - ! Versioned migrations; tested up and down
213
+ - ! `EXPLAIN ANALYZE` reviewed for high-traffic queries
214
+ - ! sqlfluff lint passes; keywords uppercase, identifiers lowercase `snake_case`
215
+ - ⊗ `SELECT *`, implicit joins, string concatenation in queries, `FLOAT` for money
216
+ - ! Run `task db:lint` before commit