@cratis/pi 0.0.1 → 2.0.1

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 (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +18 -37
  3. package/package/corpus/agents/backend-developer.md +125 -0
  4. package/package/corpus/agents/code-reviewer.md +165 -0
  5. package/package/corpus/agents/coordinator.md +163 -0
  6. package/package/corpus/agents/frontend-developer.md +246 -0
  7. package/package/corpus/agents/orchestrator.md +196 -0
  8. package/package/corpus/agents/performance-reviewer.md +109 -0
  9. package/package/corpus/agents/planner.md +145 -0
  10. package/package/corpus/agents/repository-investigation-reviewer.md +45 -0
  11. package/package/corpus/agents/repository-investigator.md +50 -0
  12. package/package/corpus/agents/security-reviewer.md +118 -0
  13. package/package/corpus/agents/slice-implementer.md +59 -0
  14. package/package/corpus/agents/spec-writer.md +149 -0
  15. package/package/corpus/harnesses/pi/extensions/cratis-hooks/index.ts +213 -0
  16. package/package/corpus/harnesses/pi/extensions/cratis-rules/index.ts +27 -0
  17. package/package/corpus/harnesses/pi/extensions/package.json +4 -0
  18. package/package/corpus/harnesses/pi/extensions/subagent/agents.ts +167 -0
  19. package/package/corpus/harnesses/pi/extensions/subagent/index.ts +352 -0
  20. package/package/corpus/hooks/README.md +434 -0
  21. package/package/corpus/hooks/agent-stop.md +49 -0
  22. package/package/corpus/hooks/pre-commit.md +47 -0
  23. package/package/corpus/hooks/scripts/cratis-guard-writes.sh +87 -0
  24. package/package/corpus/hooks/scripts/cratis-nuget-pins.txt +11 -0
  25. package/package/corpus/hooks/scripts/cratis-pattern-scan.sh +197 -0
  26. package/package/corpus/hooks/scripts/cratis-patterns.json +84 -0
  27. package/package/corpus/hooks/scripts/cratis-quality-gate.sh +219 -0
  28. package/package/corpus/hooks/scripts/hook-lib.sh +152 -0
  29. package/package/corpus/hooks/scripts/quality-gates.json +261 -0
  30. package/package/corpus/hooks/scripts/type-references-allowlist.txt +71 -0
  31. package/package/corpus/hooks/scripts/validate-package-imports.sh +166 -0
  32. package/package/corpus/hooks/scripts/validate-package-subpaths.sh +120 -0
  33. package/package/corpus/hooks/scripts/validate-type-references.sh +308 -0
  34. package/package/corpus/hooks/settings.template.json +40 -0
  35. package/package/corpus/prompts/add-business-rule.prompt.md +22 -0
  36. package/package/corpus/prompts/add-concept.prompt.md +17 -0
  37. package/package/corpus/prompts/add-ef-migration.prompt.md +24 -0
  38. package/package/corpus/prompts/add-projection.prompt.md +20 -0
  39. package/package/corpus/prompts/add-reactor.prompt.md +22 -0
  40. package/package/corpus/prompts/add-reducer.prompt.md +20 -0
  41. package/package/corpus/prompts/audit-hooks.prompt.md +15 -0
  42. package/package/corpus/prompts/check-doc-drift.prompt.md +21 -0
  43. package/package/corpus/prompts/code-review.prompt.md +9 -0
  44. package/package/corpus/prompts/new-feature.prompt.md +9 -0
  45. package/package/corpus/prompts/new-vertical-slice.prompt.md +18 -0
  46. package/package/corpus/prompts/review-pr.prompt.md +35 -0
  47. package/package/corpus/prompts/review-skill.prompt.md +16 -0
  48. package/package/corpus/prompts/scaffold-feature.prompt.md +16 -0
  49. package/package/corpus/prompts/ship-changes.prompt.md +20 -0
  50. package/package/corpus/prompts/verify-ai-setup.prompt.md +19 -0
  51. package/package/corpus/prompts/write-documentation.prompt.md +21 -0
  52. package/package/corpus/prompts/write-specs.prompt.md +22 -0
  53. package/package/corpus/rules/capability-is-not-authority.md +31 -0
  54. package/package/corpus/rules/code-quality.csharp.md +91 -0
  55. package/package/corpus/rules/code-quality.md +82 -0
  56. package/package/corpus/rules/code-quality.typescript.md +89 -0
  57. package/package/corpus/rules/components.md +207 -0
  58. package/package/corpus/rules/concepts.md +115 -0
  59. package/package/corpus/rules/csharp.md +269 -0
  60. package/package/corpus/rules/dialogs.md +264 -0
  61. package/package/corpus/rules/documentation-structure-and-formatting.md +148 -0
  62. package/package/corpus/rules/documentation.md +90 -0
  63. package/package/corpus/rules/editing-cratis-docs.md +69 -0
  64. package/package/corpus/rules/efcore.md +235 -0
  65. package/package/corpus/rules/efcore.specs.md +44 -0
  66. package/package/corpus/rules/exit-codes-and-wrappers.md +33 -0
  67. package/package/corpus/rules/framework.md +52 -0
  68. package/package/corpus/rules/frontend-quality.md +59 -0
  69. package/package/corpus/rules/frontend-testing.md +126 -0
  70. package/package/corpus/rules/general.md +305 -0
  71. package/package/corpus/rules/git-commits.md +138 -0
  72. package/package/corpus/rules/github-actions.md +92 -0
  73. package/package/corpus/rules/glossary.md +61 -0
  74. package/package/corpus/rules/guards-and-fuses.md +45 -0
  75. package/package/corpus/rules/local-work-artifacts.md +33 -0
  76. package/package/corpus/rules/managing-ai-rules.md +40 -0
  77. package/package/corpus/rules/orleans.md +50 -0
  78. package/package/corpus/rules/pull-requests.md +78 -0
  79. package/package/corpus/rules/react.md +195 -0
  80. package/package/corpus/rules/reactors.md +238 -0
  81. package/package/corpus/rules/rtk.md +37 -0
  82. package/package/corpus/rules/specs.csharp.md +139 -0
  83. package/package/corpus/rules/specs.md +132 -0
  84. package/package/corpus/rules/specs.scenarios.csharp.md +172 -0
  85. package/package/corpus/rules/specs.typescript.md +139 -0
  86. package/package/corpus/rules/storybook.md +84 -0
  87. package/package/corpus/rules/terminal-commands.md +19 -0
  88. package/package/corpus/rules/typescript.md +149 -0
  89. package/package/corpus/rules/verification-discipline.md +21 -0
  90. package/package/corpus/rules/vertical-slices.md +338 -0
  91. package/package/corpus/rules/web-fetching.md +11 -0
  92. package/package/corpus/rules/writing-correct-examples.md +35 -0
  93. package/package/corpus/rules/writing-cratis-docs.md +70 -0
  94. package/package/corpus/skills/cratis-engineering-csharp-conventions/LICENSE +2 -0
  95. package/package/corpus/skills/cratis-engineering-csharp-conventions/SKILL.md +131 -0
  96. package/package/corpus/skills/cratis-engineering-csharp-conventions/references/code-style.md +187 -0
  97. package/package/corpus/skills/cratis-engineering-csharp-conventions/references/domain-philosophy.md +91 -0
  98. package/package/corpus/skills/cratis-engineering-csharp-conventions/references/exceptions-logging-and-di.md +223 -0
  99. package/package/corpus/skills/cratis-engineering-decision-record/LICENSE +2 -0
  100. package/package/corpus/skills/cratis-engineering-decision-record/SKILL.md +133 -0
  101. package/package/corpus/skills/cratis-engineering-decision-record/references/record-format.md +107 -0
  102. package/package/corpus/skills/cratis-engineering-docs-authoring/LICENSE +2 -0
  103. package/package/corpus/skills/cratis-engineering-docs-authoring/SKILL.md +86 -0
  104. package/package/corpus/skills/cratis-engineering-docs-authoring/references/site-format.md +46 -0
  105. package/package/corpus/skills/cratis-engineering-effect-boundaries/LICENSE +2 -0
  106. package/package/corpus/skills/cratis-engineering-effect-boundaries/SKILL.md +130 -0
  107. package/package/corpus/skills/cratis-engineering-effect-boundaries/references/failure-archetypes.md +133 -0
  108. package/package/corpus/skills/cratis-fundamentals-concept/verification.json +8 -0
  109. package/package/profile-catalog.json +821 -0
  110. package/package.json +35 -13
  111. package/src/index.ts +80 -0
  112. /package/{skills → package/corpus/skills}/cratis-application-react-specifications/LICENSE +0 -0
  113. /package/{skills → package/corpus/skills}/cratis-application-react-specifications/SKILL.md +0 -0
  114. /package/{skills → package/corpus/skills}/cratis-application-slice-specifications/LICENSE +0 -0
  115. /package/{skills → package/corpus/skills}/cratis-application-slice-specifications/SKILL.md +0 -0
  116. /package/{skills → package/corpus/skills}/cratis-arc-authentication-authorization-and-identity/LICENSE +0 -0
  117. /package/{skills → package/corpus/skills}/cratis-arc-authentication-authorization-and-identity/SKILL.md +0 -0
  118. /package/{skills → package/corpus/skills}/cratis-arc-authentication-authorization-and-identity/references/authentication.md +0 -0
  119. /package/{skills → package/corpus/skills}/cratis-arc-authentication-authorization-and-identity/references/authorization.md +0 -0
  120. /package/{skills → package/corpus/skills}/cratis-arc-authentication-authorization-and-identity/references/frontend.md +0 -0
  121. /package/{skills → package/corpus/skills}/cratis-arc-authentication-authorization-and-identity/references/local-development.md +0 -0
  122. /package/{skills → package/corpus/skills}/cratis-arc-authentication-authorization-and-identity/references/tenancy.md +0 -0
  123. /package/{skills → package/corpus/skills}/cratis-arc-command/LICENSE +0 -0
  124. /package/{skills → package/corpus/skills}/cratis-arc-command/SKILL.md +0 -0
  125. /package/{skills → package/corpus/skills}/cratis-arc-command/references/command-result.md +0 -0
  126. /package/{skills → package/corpus/skills}/cratis-arc-command/references/handler-shapes.md +0 -0
  127. /package/{skills → package/corpus/skills}/cratis-arc-command/references/proxy-generation.md +0 -0
  128. /package/{skills → package/corpus/skills}/cratis-arc-command/references/read-model-injection.md +0 -0
  129. /package/{skills → package/corpus/skills}/cratis-arc-command-execution/LICENSE +0 -0
  130. /package/{skills → package/corpus/skills}/cratis-arc-command-execution/SKILL.md +0 -0
  131. /package/{skills → package/corpus/skills}/cratis-arc-command-validation/LICENSE +0 -0
  132. /package/{skills → package/corpus/skills}/cratis-arc-command-validation/SKILL.md +0 -0
  133. /package/{skills → package/corpus/skills}/cratis-arc-ef-core-migration/LICENSE +0 -0
  134. /package/{skills → package/corpus/skills}/cratis-arc-ef-core-migration/SKILL.md +0 -0
  135. /package/{skills → package/corpus/skills}/cratis-arc-observable-query-http/LICENSE +0 -0
  136. /package/{skills → package/corpus/skills}/cratis-arc-observable-query-http/SKILL.md +0 -0
  137. /package/{skills → package/corpus/skills}/cratis-arc-query-paging/LICENSE +0 -0
  138. /package/{skills → package/corpus/skills}/cratis-arc-query-paging/SKILL.md +0 -0
  139. /package/{skills → package/corpus/skills}/cratis-arc-react-page/LICENSE +0 -0
  140. /package/{skills → package/corpus/skills}/cratis-arc-react-page/SKILL.md +0 -0
  141. /package/{skills → package/corpus/skills}/cratis-arc-react-page/references/data-page.md +0 -0
  142. /package/{skills → package/corpus/skills}/cratis-arc-react-page/references/data-tables.md +0 -0
  143. /package/{skills → package/corpus/skills}/cratis-arc-react-page/references/dialogs.md +0 -0
  144. /package/{skills → package/corpus/skills}/cratis-arc-react-page/references/mvvm.md +0 -0
  145. /package/{skills → package/corpus/skills}/cratis-arc-react-page/references/queries-and-commands.md +0 -0
  146. /package/{skills → package/corpus/skills}/cratis-chronicle-cli-operations/LICENSE +0 -0
  147. /package/{skills → package/corpus/skills}/cratis-chronicle-cli-operations/SKILL.md +0 -0
  148. /package/{skills → package/corpus/skills}/cratis-chronicle-client-dotnet/LICENSE +0 -0
  149. /package/{skills → package/corpus/skills}/cratis-chronicle-client-dotnet/SKILL.md +0 -0
  150. /package/{skills → package/corpus/skills}/cratis-chronicle-client-elixir/LICENSE +0 -0
  151. /package/{skills → package/corpus/skills}/cratis-chronicle-client-elixir/SKILL.md +0 -0
  152. /package/{skills → package/corpus/skills}/cratis-chronicle-client-kotlin/LICENSE +0 -0
  153. /package/{skills → package/corpus/skills}/cratis-chronicle-client-kotlin/SKILL.md +0 -0
  154. /package/{skills → package/corpus/skills}/cratis-chronicle-client-typescript/LICENSE +0 -0
  155. /package/{skills → package/corpus/skills}/cratis-chronicle-client-typescript/SKILL.md +0 -0
  156. /package/{skills → package/corpus/skills}/cratis-chronicle-compliance/LICENSE +0 -0
  157. /package/{skills → package/corpus/skills}/cratis-chronicle-compliance/SKILL.md +0 -0
  158. /package/{skills → package/corpus/skills}/cratis-chronicle-event-constraints/LICENSE +0 -0
  159. /package/{skills → package/corpus/skills}/cratis-chronicle-event-constraints/SKILL.md +0 -0
  160. /package/{skills → package/corpus/skills}/cratis-chronicle-event-modeling/LICENSE +0 -0
  161. /package/{skills → package/corpus/skills}/cratis-chronicle-event-modeling/SKILL.md +0 -0
  162. /package/{skills → package/corpus/skills}/cratis-chronicle-event-specifications/LICENSE +0 -0
  163. /package/{skills → package/corpus/skills}/cratis-chronicle-event-specifications/SKILL.md +0 -0
  164. /package/{skills → package/corpus/skills}/cratis-chronicle-event-type-migration/LICENSE +0 -0
  165. /package/{skills → package/corpus/skills}/cratis-chronicle-event-type-migration/SKILL.md +0 -0
  166. /package/{skills → package/corpus/skills}/cratis-chronicle-mcp-inspection/LICENSE +0 -0
  167. /package/{skills → package/corpus/skills}/cratis-chronicle-mcp-inspection/SKILL.md +0 -0
  168. /package/{skills → package/corpus/skills}/cratis-chronicle-mcp-inspection/references/blocked-tools.md +0 -0
  169. /package/{skills → package/corpus/skills}/cratis-chronicle-mcp-inspection/references/observational-tools.md +0 -0
  170. /package/{skills → package/corpus/skills}/cratis-chronicle-multi-tenancy/LICENSE +0 -0
  171. /package/{skills → package/corpus/skills}/cratis-chronicle-multi-tenancy/SKILL.md +0 -0
  172. /package/{skills → package/corpus/skills}/cratis-chronicle-projection/LICENSE +0 -0
  173. /package/{skills → package/corpus/skills}/cratis-chronicle-projection/SKILL.md +0 -0
  174. /package/{skills → package/corpus/skills}/cratis-chronicle-projection/references/fluent-builder.md +0 -0
  175. /package/{skills → package/corpus/skills}/cratis-chronicle-projection/references/model-bound-attributes.md +0 -0
  176. /package/{skills → package/corpus/skills}/cratis-chronicle-reactor/LICENSE +0 -0
  177. /package/{skills → package/corpus/skills}/cratis-chronicle-reactor/SKILL.md +0 -0
  178. /package/{skills → package/corpus/skills}/cratis-chronicle-read-model/LICENSE +0 -0
  179. /package/{skills → package/corpus/skills}/cratis-chronicle-read-model/SKILL.md +0 -0
  180. /package/{skills → package/corpus/skills}/cratis-chronicle-read-model/references/queries.md +0 -0
  181. /package/{skills → package/corpus/skills}/cratis-chronicle-read-model-specifications/LICENSE +0 -0
  182. /package/{skills → package/corpus/skills}/cratis-chronicle-read-model-specifications/SKILL.md +0 -0
  183. /package/{skills → package/corpus/skills}/cratis-chronicle-reducer/LICENSE +0 -0
  184. /package/{skills → package/corpus/skills}/cratis-chronicle-reducer/SKILL.md +0 -0
  185. /package/{skills → package/corpus/skills}/cratis-chronicle-web-workbench/LICENSE +0 -0
  186. /package/{skills → package/corpus/skills}/cratis-chronicle-web-workbench/SKILL.md +0 -0
  187. /package/{skills → package/corpus/skills}/cratis-cli-terminal-workbench/LICENSE +0 -0
  188. /package/{skills → package/corpus/skills}/cratis-cli-terminal-workbench/SKILL.md +0 -0
  189. /package/{skills → package/corpus/skills}/cratis-code-review/LICENSE +0 -0
  190. /package/{skills → package/corpus/skills}/cratis-code-review/SKILL.md +0 -0
  191. /package/{skills → package/corpus/skills}/cratis-components-accessibility/LICENSE +0 -0
  192. /package/{skills → package/corpus/skills}/cratis-components-accessibility/SKILL.md +0 -0
  193. /package/{skills → package/corpus/skills}/cratis-components-schema-editor/LICENSE +0 -0
  194. /package/{skills → package/corpus/skills}/cratis-components-schema-editor/SKILL.md +0 -0
  195. /package/{skills → package/corpus/skills}/cratis-components-stepper-command-dialog/LICENSE +0 -0
  196. /package/{skills → package/corpus/skills}/cratis-components-stepper-command-dialog/SKILL.md +0 -0
  197. /package/{skills → package/corpus/skills}/cratis-components-styling/LICENSE +0 -0
  198. /package/{skills → package/corpus/skills}/cratis-components-styling/SKILL.md +0 -0
  199. /package/{skills → package/corpus/skills}/cratis-components-toolbar/LICENSE +0 -0
  200. /package/{skills → package/corpus/skills}/cratis-components-toolbar/SKILL.md +0 -0
  201. /package/{skills → package/corpus/skills}/cratis-documentation-writing/LICENSE +0 -0
  202. /package/{skills → package/corpus/skills}/cratis-documentation-writing/SKILL.md +0 -0
  203. /package/{skills → package/corpus/skills}/cratis-event-model-diagram/LICENSE +0 -0
  204. /package/{skills → package/corpus/skills}/cratis-event-model-diagram/SKILL.md +0 -0
  205. /package/{skills → package/corpus/skills}/cratis-fundamentals-concept/LICENSE +0 -0
  206. /package/{skills → package/corpus/skills}/cratis-fundamentals-concept/SKILL.md +0 -0
  207. /package/{skills → package/corpus/skills}/cratis-fundamentals-type-discovery/LICENSE +0 -0
  208. /package/{skills → package/corpus/skills}/cratis-fundamentals-type-discovery/SKILL.md +0 -0
  209. /package/{skills → package/corpus/skills}/cratis-governed-release-methodology/LICENSE +0 -0
  210. /package/{skills → package/corpus/skills}/cratis-governed-release-methodology/SKILL.md +0 -0
  211. /package/{skills → package/corpus/skills}/cratis-lens-browser-extension/LICENSE +0 -0
  212. /package/{skills → package/corpus/skills}/cratis-lens-browser-extension/SKILL.md +0 -0
  213. /package/{skills → package/corpus/skills}/cratis-performance-review/LICENSE +0 -0
  214. /package/{skills → package/corpus/skills}/cratis-performance-review/SKILL.md +0 -0
  215. /package/{skills → package/corpus/skills}/cratis-screenplay-model-authoring/LICENSE +0 -0
  216. /package/{skills → package/corpus/skills}/cratis-screenplay-model-authoring/SKILL.md +0 -0
  217. /package/{skills → package/corpus/skills}/cratis-security-review/LICENSE +0 -0
  218. /package/{skills → package/corpus/skills}/cratis-security-review/SKILL.md +0 -0
  219. /package/{skills → package/corpus/skills}/cratis-specification-by-example/LICENSE +0 -0
  220. /package/{skills → package/corpus/skills}/cratis-specification-by-example/SKILL.md +0 -0
  221. /package/{skills → package/corpus/skills}/cratis-specifications-csharp/LICENSE +0 -0
  222. /package/{skills → package/corpus/skills}/cratis-specifications-csharp/SKILL.md +0 -0
  223. /package/{skills → package/corpus/skills}/cratis-specifications-csharp/references/application-scenarios.md +0 -0
  224. /package/{skills → package/corpus/skills}/cratis-specifications-csharp/references/csharp-patterns.md +0 -0
  225. /package/{skills → package/corpus/skills}/cratis-specifications-csharp/references/integration-specs.md +0 -0
  226. /package/{skills → package/corpus/skills}/cratis-specifications-typescript/LICENSE +0 -0
  227. /package/{skills → package/corpus/skills}/cratis-specifications-typescript/SKILL.md +0 -0
  228. /package/{skills → package/corpus/skills}/cratis-specifications-typescript/references/typescript-patterns.md +0 -0
  229. /package/{skills → package/corpus/skills}/cratis-stage-rendering-and-sandbox/LICENSE +0 -0
  230. /package/{skills → package/corpus/skills}/cratis-stage-rendering-and-sandbox/SKILL.md +0 -0
  231. /package/{skills → package/corpus/skills}/cratis-studio-mcp-safety-guidance/LICENSE +0 -0
  232. /package/{skills → package/corpus/skills}/cratis-studio-mcp-safety-guidance/SKILL.md +0 -0
  233. /package/{skills → package/corpus/skills}/cratis-studio-mcp-safety-guidance/references/blocked-tools.md +0 -0
  234. /package/{skills → package/corpus/skills}/cratis-studio-mcp-safety-guidance/references/observational-tools.md +0 -0
@@ -0,0 +1,70 @@
1
+ ---
2
+ applyTo: "**/Documentation/**/*.{md,mdx}"
3
+ paths:
4
+ - "**/Documentation/**/*.md"
5
+ - "**/Documentation/**/*.mdx"
6
+ ---
7
+
8
+ # Writing Cratis documentation — tour voice and Starlight authoring
9
+
10
+ The Cratis docs must **take the reader on a tour, like a teacher** — the way [Marten](https://martendb.io), [Wolverine](https://wolverinefx.net), and [aspire.dev](https://aspire.dev) docs do — **not** state facts like a reference dump. The differentiator is pedagogical structure, not decoration. Match it.
11
+
12
+ ## The bar
13
+
14
+ - **Pain → relief.** Open by naming the friction the reader feels, then reveal the feature as the relief.
15
+ - **Why before how.** A reader who understands the reasoning handles edge cases the docs do not cover.
16
+ - **Active voice, present tense, second person.** “You append the event,” not “the event is appended.”
17
+ - **Be honest about limits.** A “when this is the wrong fit” section builds more trust than omitting the limits.
18
+
19
+ ## One page equals one Diátaxis type
20
+
21
+ | Type | Reader is… | Reads like |
22
+ |---|---|---|
23
+ | **Tutorial** | learning by doing | a guided lesson — each step produces a visible result |
24
+ | **How-to** | solving a specific problem | a recipe — assume competence, no teaching |
25
+ | **Explanation** | trying to understand | a discussion — concepts, trade-offs, *why*, a diagram |
26
+ | **Reference** | looking something up | a dictionary — exhaustive, terse, tables/signatures |
27
+
28
+ Never mix types. A tutorial padded with reference detail overwhelms; a how-to interrupted by concept digressions stops being a recipe. Diátaxis type does not imply a universal navigation bucket; bucket names are product-specific.
29
+
30
+ ## The tour-voice checklist
31
+
32
+ Apply this checklist to tutorials, getting-started pages, and explanations:
33
+
34
+ 1. **Open with a concrete scenario**, not a definition of the tool.
35
+ 2. **Name the friction first**, then the feature as its relief.
36
+ 3. **Use chronological verbs** such as define → append → project → query.
37
+ 4. **After every code block, explain the invisible** — what happens under the hood and why it matters.
38
+ 5. **Recap before pivoting** to the next concept.
39
+ 6. **Anticipate the reader's doubt** with a meaningful aside.
40
+ 7. **Show the result** — output, a resulting model, or another visible success signal.
41
+ 8. **Organize by workflow**, not alphabetically.
42
+ 9. **End each substantial section with the natural next step** when one exists.
43
+
44
+ Read a current, well-reviewed tutorial in the product or a closely related product before writing; do not assume one product's domain vocabulary fits every other product.
45
+
46
+ ## Use presentation to support the tour
47
+
48
+ Choose the simplest authoring surface that preserves the reading flow. Use steps for real procedures, tabs for genuine alternatives, asides for meaningful context or risk, and diagrams for non-trivial flows. Do not turn sequential cause-and-effect examples into tabs merely because they use different languages; hiding one side can make the explanation harder to follow.
49
+
50
+ Full-stack type safety is a differentiator, so show both the backend contract and generated frontend shape when both matter. Use `FullStackTabs` only when each pane remains understandable independently.
51
+
52
+ The raw Markdown mirror behind page actions such as “Copy Markdown” comes from synchronized Markdown/MDX rather than rendered HTML. Converter rewrites and normalized frontmatter are present, but component imports and JSX remain visible. Prefer plain Markdown unless a component adds real teaching value.
53
+
54
+ The exact Markdown/MDX boundary, aside semantics, component contracts, import paths, and rendering checks live in [Documentation Structure and Formatting](./documentation-structure-and-formatting.md). Do not duplicate or infer that rendering API here.
55
+
56
+ ## Two voices, connected products
57
+
58
+ - **Two voices per area:** the toured/educational layer and the terse, exhaustive reference. Narrative pages link *down* into the reference; the reference stays a dictionary.
59
+ - **Connect at the seams** rather than re-explaining. Show how neighboring products meet in the user's workflow and link to the glossary for shared terms.
60
+ - **Coming-from-X bridges** map new concepts to what the reader already knows without organizing the whole product around a competitor.
61
+
62
+ ## Before you call a page done
63
+
64
+ - Verify every framework API in a code example against real source — see [Writing Correct Code Examples](./writing-correct-examples.md). Readers paste snippets verbatim.
65
+ - The owning repository's local documentation gate passes when one exists; when available, the sibling Documentation site's full check has zero hard lint errors and zero broken rendered links attributable to the change.
66
+ - For a visual page, screenshot it in light **and** dark — see the `qa-cratis-docs` skill.
67
+
68
+ Study the **aspire.dev** docs for strong Starlight information architecture and tour writing.
69
+
70
+ The edit/sync/verify loop and source ownership live in [Editing Cratis Documentation](./editing-cratis-docs.md).
@@ -0,0 +1,2 @@
1
+ Copyright (c) Cratis. All rights reserved.
2
+ Licensed under the MIT license. See LICENSE file in the canonical Cratis/AI repository for the full license text.
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: cratis-engineering-csharp-conventions
3
+ description: Apply the Cratis C# house conventions when writing or reviewing C# in a Cratis repository - formatting, naming, records and primary constructors, nullable handling, XML documentation, custom exceptions, structured logging, dependency injection, and service lifetimes. Use for any "how should this be written" C# style question; defer product API decisions and specification authoring to their focused workflows.
4
+ license: LICENSE
5
+ ---
6
+
7
+ # Cratis C# engineering conventions
8
+
9
+ These are the house conventions Cratis maintainers apply across every
10
+ repository. They are **conventions**, not framework contracts: nothing here is
11
+ enforced by an analyzer unless this skill says so. Follow them for consistency;
12
+ do not claim the framework requires them.
13
+
14
+ ## Route near misses
15
+
16
+ - The question is what a Cratis product API *does*: resolve it against the
17
+ owning product repository, not against this style guide.
18
+ - The subject is a specification file: the specification conventions own the
19
+ `Establish`/`Because`/`should_` pattern and the `for_`/`when_` hierarchy.
20
+ - The subject is TypeScript or React: this skill covers C# only.
21
+ - The subject is repository structure or documentation: those are separate
22
+ workflows.
23
+
24
+ ## Quick reference
25
+
26
+ - Use current C# language features — records, primary constructors, pattern
27
+ matching, collection expressions.
28
+ - `var` over an explicit type; the right-hand side already names the type.
29
+ - File-scoped namespace declarations.
30
+ - `using` directives alphabetically sorted, single-line, unused ones removed.
31
+ - No regions. A file that needs them needs refactoring instead.
32
+ - No technical postfixes on type names: no `Impl`, `Service`, `Manager`,
33
+ `Handler`, `Base`, `Async`.
34
+ - No `Exception` suffix on exception types — `AuthorNotFound`, not
35
+ `AuthorNotFoundException`.
36
+ - Never throw a built-in exception type. Always define a domain exception.
37
+ - `record` for events, commands, read models, concepts, and DTOs.
38
+ - `is null` and `is not null` — never `== null` or `!= null`.
39
+ - Blank line before the opening `{` of every block.
40
+ - A final `return` sits on its own line.
41
+ - Private fields are `_camelCase`; interfaces take the `I` prefix.
42
+ - American English everywhere — initialize, behavior, color, serialize.
43
+ - Every file starts with the repository license header.
44
+
45
+ ## Formatting
46
+
47
+ ```csharp
48
+ // Copyright (c) Cratis. All rights reserved.
49
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
50
+
51
+ namespace <RootNamespace>.<Feature>;
52
+
53
+ using <Namespace>.<First>;
54
+ using <Namespace>.<Second>;
55
+
56
+ // Blank line before the opening brace of every block
57
+ if (<condition>)
58
+ {
59
+ <statement>;
60
+ }
61
+
62
+ // Expression-bodied form for simple members
63
+ public string <PropertyName> => $"{<First>} {<Second>}";
64
+
65
+ // The final return stands alone
66
+ public <ReturnType> <MethodName>()
67
+ {
68
+ var result = <expression>;
69
+
70
+ return result;
71
+ }
72
+ ```
73
+
74
+ ## Naming
75
+
76
+ | Artifact | Convention | Example |
77
+ | --- | --- | --- |
78
+ | Type, method, public member | PascalCase | `RegisterAuthor`, `AuthorId` |
79
+ | Private field | `_camelCase` | `_eventLog` |
80
+ | Local variable | camelCase | `authorId` |
81
+ | Interface | `I` prefix | `IEventLog` |
82
+ | Exception type | No `Exception` suffix | `AuthorNotFound` |
83
+ | Feature folder | Pluralized domain noun | `Authors/` |
84
+ | Concept file | The concept name | `AuthorId.cs` |
85
+
86
+ Avoid abbreviations unless they are universally known (`Id`, `Xml`, `Json`,
87
+ `Url`). Never add a prefix or postfix that names a technical role —
88
+ `Controller`, `ViewModel`, `Handler`, `Manager`, `Factory`, `Base`. Name after
89
+ the domain, not the pattern.
90
+
91
+ ## Where the detail lives
92
+
93
+ | Topic | Reference |
94
+ | --- | --- |
95
+ | Records, primary constructors, `var`, collections, nullable, async, pattern matching, XML documentation | [code-style.md](references/code-style.md) |
96
+ | Custom exceptions, structured logging, dependency injection, service lifetimes, implementation discovery | [exceptions-logging-and-di.md](references/exceptions-logging-and-di.md) |
97
+ | CUPID, cohesion over layers, ubiquitous language, immutability | [domain-philosophy.md](references/domain-philosophy.md) |
98
+
99
+ Read the reference that covers the decision at hand rather than all three.
100
+
101
+ ## The two rules most often got wrong
102
+
103
+ **`[Singleton]` is a narrow choice, not the default.** A singleton may not
104
+ depend on anything that belongs to a tenant, a user, or a request. Capturing a
105
+ scoped collaborator does not throw — it silently binds to the root scope's
106
+ default namespace forever and returns empty results. See
107
+ [exceptions-logging-and-di.md](references/exceptions-logging-and-di.md).
108
+
109
+ **Use `IInstancesOf<T>`, never `IEnumerable<T>`, to enumerate implementations of
110
+ an abstraction.** `IEnumerable<T>` only works when every implementation is
111
+ hand-registered, which defeats convention-based discovery.
112
+
113
+ ## Verify
114
+
115
+ - Every file carries the repository license header and a file-scoped namespace.
116
+ - `using` directives are sorted, single-line, and free of unused entries.
117
+ - No regions, no technical postfixes, no `Exception` suffix.
118
+ - Every thrown exception is a domain type deriving from `Exception` with a
119
+ meaningful message and an XML `<exception>` or `<summary>` doc starting with
120
+ "The exception that is thrown when".
121
+ - No `catch` block is empty or silently swallowing.
122
+ - Null checks use `is null` / `is not null`, and no defensive check contradicts a
123
+ non-nullable annotation.
124
+ - Every public type, method, property, and operator carries multiline XML
125
+ documentation with `<param>` and `<returns>` where applicable.
126
+ - No `[Singleton]` holds tenant-, user-, or request-bound state.
127
+ - No `services.Add*<TInterface, TImplementation>()` registers a type that exists
128
+ to be discovered by convention.
129
+ - Text is American English.
130
+ - The solution builds with zero warnings and zero errors, and the affected
131
+ specifications pass.
@@ -0,0 +1,187 @@
1
+ # C# code style
2
+
3
+ ## Records
4
+
5
+ Use `record` for every immutable data structure — events, commands, read
6
+ models, concepts, DTOs. Records supply value equality, immutability, and concise
7
+ syntax. A `record class` with `init`-only properties is equivalent when the type
8
+ also needs methods.
9
+
10
+ ```csharp
11
+ public record <EventName>(<ConceptType> <PropertyName>);
12
+
13
+ public record <ModelName>(<IdentityType> Id, <ConceptType> <PropertyName>);
14
+ ```
15
+
16
+ ## Primary constructors
17
+
18
+ Use primary constructors for all types. They remove the field-plus-constructor
19
+ ceremony.
20
+
21
+ ```csharp
22
+ // Preferred
23
+ public class <ClassName>(<CollaboratorType> <collaborator>)
24
+ {
25
+ public async Task <MethodName>(<ArgumentType> <argument>) =>
26
+ await <collaborator>.<Method>(<argument>);
27
+ }
28
+ ```
29
+
30
+ When a type genuinely needs field initialization logic and cannot use a primary
31
+ constructor, declare private fields with the `_camelCase` prefix.
32
+
33
+ ## `var`
34
+
35
+ Always use `var` for a local variable. The right-hand side already names the
36
+ type.
37
+
38
+ ```csharp
39
+ var <identifier> = <Factory>.New();
40
+ var <items> = <source>.Where(<predicate>).ToList();
41
+ ```
42
+
43
+ ## Expression-bodied members
44
+
45
+ Use expression-bodied form for simple members.
46
+
47
+ ```csharp
48
+ public string <PropertyName> => $"{<First>} {<Second>}";
49
+ public void <MethodName>(string <argument>) => <collaborator>.<Method>(<argument>);
50
+ ```
51
+
52
+ ## Collections
53
+
54
+ Return read-only sequence types from public APIs. Never expose a mutable
55
+ collection type — a caller could mutate state its owner is responsible for.
56
+
57
+ ```csharp
58
+ // Preferred
59
+ public IEnumerable<<ItemType>> <MethodName>() => <source>.ToList();
60
+ public IReadOnlyDictionary<<KeyType>, <ItemType>> <MethodName>() => <source>;
61
+
62
+ // Avoid on a public API
63
+ public List<<ItemType>> <MethodName>() => <source>;
64
+ public Dictionary<<KeyType>, <ItemType>> <MethodName>() => <source>;
65
+ ```
66
+
67
+ ## Nullable reference types
68
+
69
+ Embrace the type system — it is the first defense against null bugs. When an
70
+ annotation says a value cannot be null, trust it.
71
+
72
+ ```csharp
73
+ // Use is null / is not null
74
+ if (<value> is null) throw new <DomainException>();
75
+ if (<value> is not null) <statement>;
76
+
77
+ // Do not add a defensive check the annotation already guarantees
78
+ public void <MethodName>(<NonNullableType> <argument>)
79
+ {
80
+ <statement>;
81
+ }
82
+
83
+ // Add ! only where the compiler cannot see what you can prove
84
+ var <identifier> = <source>.FirstOrDefault(<predicate>)!;
85
+ ```
86
+
87
+ Never write `== null` or `!= null`.
88
+
89
+ ## Async
90
+
91
+ - Use `async`/`await`; return `Task` or `Task<T>`.
92
+ - Do not suffix a method with `Async` unless the suffix disambiguates an
93
+ overload.
94
+ - Never use `.Result` or `.Wait()`.
95
+
96
+ ```csharp
97
+ public async Task <MethodName>(<ArgumentType> <argument>) =>
98
+ await <collaborator>.<Method>(<argument>);
99
+
100
+ public async Task<<ResultType>?> <FindMethod>(<IdentityType> id) => <expression>;
101
+ ```
102
+
103
+ ## Immutability
104
+
105
+ Prefer immutable designs. Produce a modified copy with a `with` expression
106
+ rather than mutating in place.
107
+
108
+ ```csharp
109
+ var updated = <existing> with { <PropertyName> = <newValue> };
110
+ ```
111
+
112
+ The owner of state is responsible for its mutations. Do not return a mutable
113
+ object a caller could change behind the owner's back.
114
+
115
+ ## Pattern matching
116
+
117
+ Use pattern matching and switch expressions wherever they read better than a
118
+ branch chain.
119
+
120
+ ```csharp
121
+ if (<result> is <ResultType>.Success success)
122
+ return success.Value;
123
+
124
+ var <identifier> = <value> switch
125
+ {
126
+ <EnumType>.<Member> => <expression>,
127
+ <EnumType>.<OtherMember> => <expression>,
128
+ _ => <fallback>
129
+ };
130
+ ```
131
+
132
+ ## String interpolation
133
+
134
+ ```csharp
135
+ // Preferred
136
+ var message = $"<text> '{<value>}' <text>";
137
+
138
+ // Avoid
139
+ var message = string.Format("<text> '{0}' <text>", <value>);
140
+ var message = "<text> '" + <value> + "' <text>";
141
+ ```
142
+
143
+ ## Interface bodies
144
+
145
+ Omit the body of a member-less interface.
146
+
147
+ ```csharp
148
+ // Preferred
149
+ public interface <IMarkerName>;
150
+
151
+ // Avoid
152
+ public interface <IMarkerName> { }
153
+ ```
154
+
155
+ ## XML documentation
156
+
157
+ XML documentation is a public API's first impression. Every public type, method,
158
+ property, and operator carries it.
159
+
160
+ - `<summary>` is **always multiline** — opening and closing tags on their own
161
+ lines. Never cram it onto one line.
162
+ - Every method or operator with parameters includes a `<param name="…">` for
163
+ each one.
164
+ - Every non-void method or operator includes `<returns>`.
165
+ - Every method that throws documents it with `<exception cref="…">`.
166
+ - Cross-reference with `<see cref="…"/>` and `<paramref name="…"/>`.
167
+ - Keep summaries concise. Document only where it adds understanding beyond the
168
+ name.
169
+
170
+ ```csharp
171
+ /// <summary>
172
+ /// Represents <description>.
173
+ /// </summary>
174
+ /// <param name="<parameterName>">The <see cref="<ParameterType>"/> to <purpose>.</param>
175
+ public class <ClassName>(<ParameterType> <parameterName>) : <IInterfaceName>
176
+ {
177
+ /// <summary>
178
+ /// <Verb> the <subject>.
179
+ /// </summary>
180
+ /// <param name="<argumentName>">The <see cref="<ArgumentType>"/> to <purpose>.</param>
181
+ /// <returns>A <see cref="<ReturnType>"/> representing <description>.</returns>
182
+ public async Task<<ReturnType>> <MethodName>(<ArgumentType> <argumentName>)
183
+ {
184
+ <statement>;
185
+ }
186
+ }
187
+ ```
@@ -0,0 +1,91 @@
1
+ # Domain philosophy
2
+
3
+ ## CUPID characteristics
4
+
5
+ Cratis favors the CUPID characteristics over a strict SOLID reading:
6
+
7
+ | Letter | Characteristic | What it means |
8
+ | --- | --- | --- |
9
+ | **C** | Composable | Parts play nicely together with minimal coupling and can be assembled freely |
10
+ | **U** | Unix philosophy | Do one thing well — focused, single-purpose components |
11
+ | **P** | Predictable | Deterministic behavior, consistent output, no surprises |
12
+ | **I** | Idiomatic | Code feels natural for the language and its ecosystem |
13
+ | **D** | Domain-based | Domain vocabulary and structure, not technical vocabulary |
14
+
15
+ ## Cohesion over layers
16
+
17
+ Do not split code by technical role.
18
+
19
+ ```
20
+ # Avoid — layered by technical role
21
+ Models/
22
+ <Model>.cs
23
+ Controllers/
24
+ <Name>Controller.cs
25
+ Services/
26
+ <Name>Service.cs
27
+ Events/
28
+ <Name>Event.cs
29
+ ```
30
+
31
+ Group by feature instead, so everything that changes together lives together.
32
+ Feature folders sit directly under the source root; there is no `Features/`
33
+ wrapper.
34
+
35
+ ```
36
+ # Preferred — cohesive by feature
37
+ <Feature>/
38
+ <Behavior>/
39
+ <Behavior>.cs ← the backend artifacts for this behavior
40
+ <Behavior>.tsx ← its component
41
+ <OtherBehavior>/
42
+ <OtherBehavior>.cs
43
+ <OtherBehavior>.tsx
44
+ ```
45
+
46
+ Frontend and backend concerns naturally separate into different projects, but
47
+ each project keeps the cohesive feature structure inside it.
48
+
49
+ ## Ubiquitous language
50
+
51
+ Name after the domain concept, not the technical pattern.
52
+
53
+ | Domain-named | Tech-named |
54
+ | --- | --- |
55
+ | `Authors` | `AuthorController`, `AuthorManager` |
56
+ | `Registration` | `RegisterAuthorHandler`, `RegisterAuthorCommand` |
57
+ | `AuthorNotFound` | `AuthorNotFoundException`, `NotFoundException` |
58
+ | `AuthorId` | a raw `Guid authorId` |
59
+ | `Listing` | `GetAllAuthorsQuery` |
60
+
61
+ ## Pluralization
62
+
63
+ Features are groupings, so pluralize them consistently across folder, route, and
64
+ schema: `Authors/`, `/api/Authors/{authorId}`, an `Authors` schema.
65
+
66
+ ## Twelve-factor operability
67
+
68
+ Systems follow the twelve-factor guidance for scalability, maintainability, and
69
+ operability:
70
+
71
+ - Configuration comes from the environment, never hardcoded.
72
+ - Processes are stateless.
73
+ - Logs are treated as event streams.
74
+ - Setup is declarative so an environment can be replicated.
75
+
76
+ ## Frictionless dependencies
77
+
78
+ Healthy dependencies mean fast, independent releases. If two components must
79
+ have their releases coordinated, that is unhealthy coupling — address it through
80
+ events, an interface, or package versioning rather than accepting the lockstep.
81
+
82
+ ## Immutability and side effects
83
+
84
+ Favor immutable designs to reduce side effects:
85
+
86
+ - Records with `init`-only properties.
87
+ - Return a new instance rather than mutating an existing one.
88
+ - Expose `IEnumerable<T>` and `IReadOnlyDictionary<TKey, TValue>` from public
89
+ APIs, never a mutable collection.
90
+ - The owner of state is responsible for its mutations. Do not let a consumer
91
+ mutate internal state.