@cubis/foundry 0.3.71 → 0.3.73
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.
- package/CHANGELOG.md +23 -2
- package/dist/cli/core.js +9 -22
- package/dist/cli/core.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/core.ts +13 -22
- package/workflows/powers/accessibility/POWER.md +83 -94
- package/workflows/powers/accessibility/SKILL.md +82 -94
- package/workflows/powers/agent-design/POWER.md +201 -0
- package/workflows/powers/agent-design/SKILL.md +198 -0
- package/workflows/powers/agent-design/references/clarification-patterns.md +153 -0
- package/workflows/powers/agent-design/references/skill-testing.md +164 -0
- package/workflows/powers/agent-design/references/workflow-patterns.md +226 -0
- package/workflows/powers/agentic-eval/POWER.md +62 -0
- package/workflows/powers/agentic-eval/SKILL.md +59 -0
- package/workflows/powers/agentic-eval/references/rubric-and-regression-checklist.md +11 -0
- package/workflows/powers/api-designer/POWER.md +43 -71
- package/workflows/powers/api-designer/SKILL.md +43 -71
- package/workflows/powers/api-patterns/POWER.md +42 -56
- package/workflows/powers/api-patterns/SKILL.md +42 -57
- package/workflows/powers/architecture-designer/POWER.md +43 -60
- package/workflows/powers/architecture-designer/SKILL.md +43 -60
- package/workflows/powers/ask-questions-if-underspecified/POWER.md +51 -3
- package/workflows/powers/auth-architect/POWER.md +69 -0
- package/workflows/powers/auth-architect/SKILL.md +66 -0
- package/workflows/powers/auth-architect/references/session-token-policy-checklist.md +45 -0
- package/workflows/powers/behavioral-modes/POWER.md +100 -9
- package/workflows/powers/c-pro/POWER.md +105 -0
- package/workflows/powers/c-pro/SKILL.md +102 -0
- package/workflows/powers/c-pro/references/build-systems-and-toolchains.md +148 -0
- package/workflows/powers/c-pro/references/common-ub-and-portability.md +166 -0
- package/workflows/powers/c-pro/references/debugging-with-sanitizers.md +205 -0
- package/workflows/powers/c-pro/references/memory-safety-and-build-checklist.md +60 -0
- package/workflows/powers/c-pro/references/posix-and-platform-apis.md +244 -0
- package/workflows/powers/changelog-generator/POWER.md +127 -63
- package/workflows/powers/changelog-generator/SKILL.md +126 -63
- package/workflows/powers/ci-cd-pipelines/POWER.md +156 -0
- package/workflows/powers/ci-cd-pipelines/SKILL.md +153 -0
- package/workflows/powers/ci-cd-pipelines/references/github-actions-patterns.md +160 -0
- package/workflows/powers/ci-cd-pipelines/references/pipeline-security-checklist.md +57 -0
- package/workflows/powers/cli-developer/POWER.md +152 -95
- package/workflows/powers/cli-developer/SKILL.md +152 -95
- package/workflows/powers/cpp-pro/POWER.md +111 -0
- package/workflows/powers/cpp-pro/SKILL.md +108 -0
- package/workflows/powers/cpp-pro/references/concurrency-primitives.md +266 -0
- package/workflows/powers/cpp-pro/references/move-semantics-and-value-types.md +149 -0
- package/workflows/powers/cpp-pro/references/performance-and-profiling.md +191 -0
- package/workflows/powers/cpp-pro/references/raii-and-modern-cpp-checklist.md +87 -0
- package/workflows/powers/cpp-pro/references/template-and-concepts-patterns.md +205 -0
- package/workflows/powers/csharp-pro/POWER.md +47 -22
- package/workflows/powers/csharp-pro/SKILL.md +47 -22
- package/workflows/powers/dart-pro/POWER.md +68 -0
- package/workflows/powers/dart-pro/SKILL.md +65 -0
- package/workflows/powers/dart-pro/references/isolate-and-concurrency.md +180 -0
- package/workflows/powers/dart-pro/references/null-safety-and-async-patterns.md +133 -0
- package/workflows/powers/dart-pro/references/package-structure-and-linting.md +193 -0
- package/workflows/powers/dart-pro/references/sealed-records-patterns.md +173 -0
- package/workflows/powers/dart-pro/references/testing-and-mocking.md +235 -0
- package/workflows/powers/database-design/POWER.md +47 -33
- package/workflows/powers/database-design/SKILL.md +47 -33
- package/workflows/powers/database-optimizer/POWER.md +43 -64
- package/workflows/powers/database-optimizer/SKILL.md +43 -64
- package/workflows/powers/database-skills/POWER.md +59 -93
- package/workflows/powers/database-skills/SKILL.md +59 -93
- package/workflows/powers/debugging-strategies/POWER.md +69 -0
- package/workflows/powers/debugging-strategies/SKILL.md +66 -0
- package/workflows/powers/debugging-strategies/references/reproduce-isolate-verify-checklist.md +42 -0
- package/workflows/powers/deep-research/POWER.md +67 -0
- package/workflows/powers/deep-research/SKILL.md +64 -0
- package/workflows/powers/deep-research/references/multi-round-research-loop.md +80 -0
- package/workflows/powers/design-system-builder/POWER.md +130 -116
- package/workflows/powers/design-system-builder/SKILL.md +130 -116
- package/workflows/powers/devops-engineer/POWER.md +120 -57
- package/workflows/powers/devops-engineer/SKILL.md +120 -57
- package/workflows/powers/docker-kubernetes/POWER.md +94 -0
- package/workflows/powers/docker-kubernetes/SKILL.md +91 -0
- package/workflows/powers/docker-kubernetes/references/dockerfile-optimization-checklist.md +35 -0
- package/workflows/powers/docker-kubernetes/references/kubernetes-deployment-patterns.md +59 -0
- package/workflows/powers/documentation-templates/POWER.md +158 -127
- package/workflows/powers/documentation-templates/SKILL.md +158 -127
- package/workflows/powers/drizzle-expert/POWER.md +66 -0
- package/workflows/powers/drizzle-expert/SKILL.md +63 -0
- package/workflows/powers/drizzle-expert/references/runtime-pairing-matrix.md +16 -0
- package/workflows/powers/drizzle-expert/references/schema-and-migration-playbook.md +18 -0
- package/workflows/powers/error-ux-observability/POWER.md +144 -131
- package/workflows/powers/error-ux-observability/SKILL.md +143 -131
- package/workflows/powers/fastapi-expert/POWER.md +46 -60
- package/workflows/powers/fastapi-expert/SKILL.md +46 -60
- package/workflows/powers/firebase/POWER.md +65 -0
- package/workflows/powers/firebase/SKILL.md +62 -0
- package/workflows/powers/firebase/references/platform-routing.md +16 -0
- package/workflows/powers/firebase/references/rules-and-indexes-checklist.md +11 -0
- package/workflows/powers/flutter-design-system/POWER.md +63 -0
- package/workflows/powers/flutter-design-system/SKILL.md +60 -0
- package/workflows/powers/flutter-design-system/references/shared-widgets.md +29 -0
- package/workflows/powers/flutter-design-system/references/tokens-and-theme.md +34 -0
- package/workflows/powers/flutter-drift/POWER.md +65 -0
- package/workflows/powers/flutter-drift/SKILL.md +62 -0
- package/workflows/powers/flutter-drift/references/migrations.md +22 -0
- package/workflows/powers/flutter-drift/references/query-patterns.md +26 -0
- package/workflows/powers/flutter-feature/POWER.md +65 -0
- package/workflows/powers/flutter-feature/SKILL.md +62 -0
- package/workflows/powers/flutter-feature/references/architecture-rules.md +85 -0
- package/workflows/powers/flutter-feature/references/composite-provider.md +58 -0
- package/workflows/powers/flutter-feature/references/outbox-pattern.md +87 -0
- package/workflows/powers/flutter-feature/references/testing-patterns.md +218 -0
- package/workflows/powers/flutter-go-router/POWER.md +64 -0
- package/workflows/powers/flutter-go-router/SKILL.md +61 -0
- package/workflows/powers/flutter-go-router/references/guards-and-deeplinks.md +20 -0
- package/workflows/powers/flutter-go-router/references/typed-routes.md +27 -0
- package/workflows/powers/flutter-offline-sync/POWER.md +62 -0
- package/workflows/powers/flutter-offline-sync/SKILL.md +59 -0
- package/workflows/powers/flutter-offline-sync/references/outbox-full.md +44 -0
- package/workflows/powers/flutter-repository/POWER.md +64 -0
- package/workflows/powers/flutter-repository/SKILL.md +61 -0
- package/workflows/powers/flutter-repository/references/drift-patterns.md +21 -0
- package/workflows/powers/flutter-repository/references/retrofit-patterns.md +20 -0
- package/workflows/powers/flutter-riverpod/POWER.md +70 -0
- package/workflows/powers/flutter-riverpod/SKILL.md +67 -0
- package/workflows/powers/flutter-riverpod/references/async-and-mutations.md +19 -0
- package/workflows/powers/flutter-riverpod/references/async-lifecycle.md +19 -0
- package/workflows/powers/flutter-riverpod/references/provider-selection.md +20 -0
- package/workflows/powers/flutter-riverpod/references/testing.md +21 -0
- package/workflows/powers/flutter-riverpod/references/version-matrix.md +24 -0
- package/workflows/powers/flutter-state-machine/POWER.md +62 -0
- package/workflows/powers/flutter-state-machine/SKILL.md +59 -0
- package/workflows/powers/flutter-state-machine/references/app-state-contract.md +23 -0
- package/workflows/powers/flutter-state-machine/references/ui-rendering.md +14 -0
- package/workflows/powers/flutter-testing/POWER.md +64 -0
- package/workflows/powers/flutter-testing/SKILL.md +61 -0
- package/workflows/powers/flutter-testing/references/offline-sync-tests.md +16 -0
- package/workflows/powers/flutter-testing/references/test-layers.md +33 -0
- package/workflows/powers/frontend-code-review/POWER.md +137 -0
- package/workflows/powers/frontend-code-review/SKILL.md +134 -0
- package/workflows/powers/frontend-code-review/references/common-antipatterns.md +86 -0
- package/workflows/powers/frontend-code-review/references/performance-budgets.md +56 -0
- package/workflows/powers/frontend-code-review/references/review-checklists.md +47 -0
- package/workflows/powers/frontend-design/POWER.md +163 -362
- package/workflows/powers/frontend-design/SKILL.md +163 -362
- package/workflows/powers/game-development/POWER.md +57 -140
- package/workflows/powers/game-development/SKILL.md +57 -140
- package/workflows/powers/geo-fundamentals/POWER.md +64 -126
- package/workflows/powers/geo-fundamentals/SKILL.md +64 -127
- package/workflows/powers/git-workflow/POWER.md +135 -0
- package/workflows/powers/git-workflow/SKILL.md +132 -0
- package/workflows/powers/git-workflow/references/pr-review-checklist.md +63 -0
- package/workflows/powers/golang-pro/POWER.md +46 -35
- package/workflows/powers/golang-pro/SKILL.md +46 -35
- package/workflows/powers/graphql-architect/POWER.md +44 -62
- package/workflows/powers/graphql-architect/SKILL.md +44 -62
- package/workflows/powers/i18n-localization/POWER.md +118 -103
- package/workflows/powers/i18n-localization/SKILL.md +118 -103
- package/workflows/powers/java-pro/POWER.md +47 -22
- package/workflows/powers/java-pro/SKILL.md +47 -22
- package/workflows/powers/javascript-pro/POWER.md +47 -34
- package/workflows/powers/javascript-pro/SKILL.md +47 -34
- package/workflows/powers/kotlin-pro/POWER.md +46 -23
- package/workflows/powers/kotlin-pro/SKILL.md +46 -23
- package/workflows/powers/legacy-modernizer/POWER.md +43 -60
- package/workflows/powers/legacy-modernizer/SKILL.md +43 -60
- package/workflows/powers/mcp-builder/POWER.md +65 -0
- package/workflows/powers/mcp-builder/SKILL.md +62 -0
- package/workflows/powers/mcp-builder/references/testing-and-evals.md +17 -0
- package/workflows/powers/mcp-builder/references/transport-and-tool-design.md +17 -0
- package/workflows/powers/microservices-architect/POWER.md +43 -70
- package/workflows/powers/microservices-architect/SKILL.md +43 -70
- package/workflows/powers/mobile-design/POWER.md +110 -345
- package/workflows/powers/mobile-design/SKILL.md +110 -345
- package/workflows/powers/mongodb/POWER.md +67 -0
- package/workflows/powers/mongodb/SKILL.md +64 -0
- package/workflows/powers/mongodb/references/mongodb-checklist.md +20 -0
- package/workflows/powers/mysql/POWER.md +67 -0
- package/workflows/powers/mysql/SKILL.md +64 -0
- package/workflows/powers/mysql/references/mysql-checklist.md +20 -0
- package/workflows/powers/neki/POWER.md +67 -0
- package/workflows/powers/neki/SKILL.md +64 -0
- package/workflows/powers/neki/references/neki-checklist.md +18 -0
- package/workflows/powers/nestjs-expert/POWER.md +45 -91
- package/workflows/powers/nestjs-expert/SKILL.md +45 -91
- package/workflows/powers/nextjs-developer/POWER.md +51 -44
- package/workflows/powers/nextjs-developer/SKILL.md +51 -44
- package/workflows/powers/nodejs-best-practices/POWER.md +48 -29
- package/workflows/powers/nodejs-best-practices/SKILL.md +48 -29
- package/workflows/powers/observability/POWER.md +109 -0
- package/workflows/powers/observability/SKILL.md +106 -0
- package/workflows/powers/observability/references/alerting-and-slo-checklist.md +87 -0
- package/workflows/powers/observability/references/opentelemetry-setup-guide.md +121 -0
- package/workflows/powers/openai-docs/POWER.md +61 -0
- package/workflows/powers/openai-docs/SKILL.md +58 -0
- package/workflows/powers/openai-docs/references/official-source-playbook.md +10 -0
- package/workflows/powers/performance-profiling/POWER.md +61 -114
- package/workflows/powers/performance-profiling/SKILL.md +61 -114
- package/workflows/powers/php-pro/POWER.md +116 -0
- package/workflows/powers/php-pro/SKILL.md +113 -0
- package/workflows/powers/php-pro/references/architecture-and-di.md +239 -0
- package/workflows/powers/php-pro/references/modern-php-features.md +189 -0
- package/workflows/powers/php-pro/references/performance-and-deployment.md +197 -0
- package/workflows/powers/php-pro/references/php84-strict-typing-checklist.md +161 -0
- package/workflows/powers/php-pro/references/testing-and-static-analysis.md +235 -0
- package/workflows/powers/playwright-e2e/POWER.md +85 -0
- package/workflows/powers/playwright-e2e/SKILL.md +82 -0
- package/workflows/powers/playwright-e2e/references/locator-trace-flake-checklist.md +80 -0
- package/workflows/powers/postgres/POWER.md +67 -0
- package/workflows/powers/postgres/SKILL.md +64 -0
- package/workflows/powers/postgres/references/postgres-checklist.md +20 -0
- package/workflows/powers/prompt-engineer/POWER.md +47 -30
- package/workflows/powers/prompt-engineer/SKILL.md +47 -30
- package/workflows/powers/python-pro/POWER.md +47 -36
- package/workflows/powers/python-pro/SKILL.md +47 -36
- package/workflows/powers/react-best-practices/POWER.md +56 -33
- package/workflows/powers/react-best-practices/SKILL.md +56 -33
- package/workflows/powers/react-expert/POWER.md +47 -37
- package/workflows/powers/react-expert/SKILL.md +47 -37
- package/workflows/powers/redis/POWER.md +67 -0
- package/workflows/powers/redis/SKILL.md +64 -0
- package/workflows/powers/redis/references/redis-checklist.md +19 -0
- package/workflows/powers/ruby-pro/POWER.md +118 -0
- package/workflows/powers/ruby-pro/SKILL.md +115 -0
- package/workflows/powers/ruby-pro/references/modern-ruby-features.md +189 -0
- package/workflows/powers/ruby-pro/references/object-design-patterns.md +220 -0
- package/workflows/powers/ruby-pro/references/performance-and-profiling.md +224 -0
- package/workflows/powers/ruby-pro/references/ruby-concurrency-and-testing.md +190 -0
- package/workflows/powers/ruby-pro/references/testing-and-rspec.md +236 -0
- package/workflows/powers/rust-pro/POWER.md +45 -31
- package/workflows/powers/rust-pro/SKILL.md +45 -31
- package/workflows/powers/security-engineer/POWER.md +129 -0
- package/workflows/powers/security-engineer/SKILL.md +126 -0
- package/workflows/powers/seo-fundamentals/POWER.md +59 -102
- package/workflows/powers/seo-fundamentals/SKILL.md +59 -102
- package/workflows/powers/serverless-patterns/POWER.md +171 -0
- package/workflows/powers/serverless-patterns/SKILL.md +168 -0
- package/workflows/powers/skill-creator/POWER.md +90 -0
- package/workflows/powers/skill-creator/SKILL.md +87 -0
- package/workflows/powers/skill-creator/references/platform-formats.md +181 -0
- package/workflows/powers/skill-creator/references/schemas.md +430 -0
- package/workflows/powers/spec-miner/POWER.md +49 -57
- package/workflows/powers/spec-miner/SKILL.md +49 -57
- package/workflows/powers/sqlite/POWER.md +67 -0
- package/workflows/powers/sqlite/SKILL.md +64 -0
- package/workflows/powers/sqlite/references/sqlite-checklist.md +19 -0
- package/workflows/powers/sre-engineer/POWER.md +123 -64
- package/workflows/powers/sre-engineer/SKILL.md +123 -64
- package/workflows/powers/static-analysis/POWER.md +121 -77
- package/workflows/powers/static-analysis/SKILL.md +121 -77
- package/workflows/powers/stripe-best-practices/POWER.md +140 -17
- package/workflows/powers/stripe-best-practices/SKILL.md +139 -17
- package/workflows/powers/supabase/POWER.md +67 -0
- package/workflows/powers/supabase/SKILL.md +64 -0
- package/workflows/powers/supabase/references/supabase-checklist.md +19 -0
- package/workflows/powers/swift-pro/POWER.md +118 -0
- package/workflows/powers/swift-pro/SKILL.md +115 -0
- package/workflows/powers/swift-pro/references/concurrency-patterns.md +165 -0
- package/workflows/powers/swift-pro/references/protocol-and-generics.md +172 -0
- package/workflows/powers/swift-pro/references/sendable-and-isolation.md +116 -0
- package/workflows/powers/swift-pro/references/swift-concurrency-and-protocols.md +260 -0
- package/workflows/powers/swift-pro/references/testing-and-packages.md +192 -0
- package/workflows/powers/tailwind-patterns/POWER.md +71 -240
- package/workflows/powers/tailwind-patterns/SKILL.md +71 -240
- package/workflows/powers/testing-patterns/POWER.md +155 -10
- package/workflows/powers/testing-patterns/SKILL.md +155 -10
- package/workflows/powers/typescript-pro/POWER.md +47 -38
- package/workflows/powers/typescript-pro/SKILL.md +47 -38
- package/workflows/powers/vitess/POWER.md +67 -0
- package/workflows/powers/vitess/SKILL.md +64 -0
- package/workflows/powers/vitess/references/vitess-checklist.md +19 -0
- package/workflows/powers/vulnerability-scanner/POWER.md +146 -10
- package/workflows/powers/vulnerability-scanner/SKILL.md +146 -10
- package/workflows/powers/web-perf/POWER.md +43 -170
- package/workflows/powers/web-perf/SKILL.md +43 -170
- package/workflows/powers/webapp-testing/POWER.md +43 -164
- package/workflows/powers/webapp-testing/SKILL.md +43 -164
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/rules/GEMINI.md +65 -42
- package/workflows/workflows/agent-environment-setup/platforms/claude/rules/CLAUDE.md +8 -6
- package/workflows/workflows/agent-environment-setup/platforms/codex/rules/AGENTS.md +65 -41
- package/workflows/workflows/agent-environment-setup/platforms/copilot/rules/copilot-instructions.md +8 -6
- package/workflows/workflows/agent-environment-setup/shared/rules/STEERING.md +9 -8
- package/workflows/workflows/agent-environment-setup/shared/rules/overrides/codex.md +1 -1
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Ruby Concurrency and Testing
|
|
2
|
+
|
|
3
|
+
## Ractor patterns (Ruby 3.0+)
|
|
4
|
+
|
|
5
|
+
### Basic Ractor usage
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
# CPU-bound parallel computation
|
|
9
|
+
ractors = 4.times.map do |i|
|
|
10
|
+
Ractor.new(i) do |id|
|
|
11
|
+
# Each Ractor has its own isolated memory
|
|
12
|
+
heavy_computation(id)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
results = ractors.map(&:take) # Collect results
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- Ractors provide true parallelism by isolating memory between execution contexts.
|
|
20
|
+
- Only shareable objects can be sent between Ractors: frozen objects, `Ractor.make_shareable(obj)`.
|
|
21
|
+
- Use `Ractor.yield` / `Ractor.receive` for message-passing between Ractors.
|
|
22
|
+
|
|
23
|
+
### Ractor constraints
|
|
24
|
+
|
|
25
|
+
| Allowed | Not allowed |
|
|
26
|
+
| -------------------------------- | --------------------------------------------- |
|
|
27
|
+
| Frozen strings, numbers, symbols | Mutable strings, arrays, hashes |
|
|
28
|
+
| `Ractor.make_shareable(obj)` | Class variables shared across Ractors |
|
|
29
|
+
| `Ractor::MovedObject` transfer | Global variables (`$stdout` is special-cased) |
|
|
30
|
+
|
|
31
|
+
- Most gems are NOT Ractor-safe. Test thoroughly before using Ractors with external libraries.
|
|
32
|
+
- Prefer Ractors for compute-heavy, isolated work (parsing, image processing, data transformation).
|
|
33
|
+
|
|
34
|
+
## Fiber and Async patterns
|
|
35
|
+
|
|
36
|
+
### Fiber-based concurrency
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
require 'async'
|
|
40
|
+
|
|
41
|
+
Async do |task|
|
|
42
|
+
# I/O-bound concurrent operations
|
|
43
|
+
response1 = task.async { HTTP.get("https://api.example.com/users") }
|
|
44
|
+
response2 = task.async { HTTP.get("https://api.example.com/posts") }
|
|
45
|
+
|
|
46
|
+
users = response1.wait
|
|
47
|
+
posts = response2.wait
|
|
48
|
+
end
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- Fibers run on a single thread — no thread-safety concerns for shared state.
|
|
52
|
+
- Use the `async` gem for production fiber-based I/O concurrency.
|
|
53
|
+
- Ideal for I/O-bound work: HTTP requests, database queries, file operations.
|
|
54
|
+
- Not suitable for CPU-bound work — use Ractors or process-based parallelism instead.
|
|
55
|
+
|
|
56
|
+
### Thread safety primitives
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
mutex = Mutex.new
|
|
60
|
+
counter = 0
|
|
61
|
+
|
|
62
|
+
threads = 10.times.map do
|
|
63
|
+
Thread.new do
|
|
64
|
+
mutex.synchronize { counter += 1 }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
threads.each(&:join)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- Use `Mutex#synchronize` for critical sections. Never call `lock`/`unlock` manually.
|
|
71
|
+
- Use `Queue` for thread-safe producer/consumer patterns.
|
|
72
|
+
- Use `Monitor` when you need reentrant locking (same thread can re-acquire the lock).
|
|
73
|
+
- Prefer `Concurrent::Map` (from concurrent-ruby) over `Hash` with manual locking.
|
|
74
|
+
|
|
75
|
+
## Background job patterns
|
|
76
|
+
|
|
77
|
+
### Sidekiq best practices
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
class UserNotificationJob
|
|
81
|
+
include Sidekiq::Job
|
|
82
|
+
sidekiq_options queue: :default, retry: 3
|
|
83
|
+
|
|
84
|
+
def perform(user_id, event_type)
|
|
85
|
+
user = User.find(user_id)
|
|
86
|
+
NotificationService.new(user).send(event_type)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- Pass only primitive arguments (IDs, strings). Never pass ActiveRecord objects — they can't be serialized safely.
|
|
92
|
+
- Set explicit retry counts. Use dead-letter queues for permanently failed jobs.
|
|
93
|
+
- Keep jobs idempotent — they may run more than once due to retries.
|
|
94
|
+
- Use separate queues for different priority levels (`:critical`, `:default`, `:low`).
|
|
95
|
+
|
|
96
|
+
## Testing strategy
|
|
97
|
+
|
|
98
|
+
### RSpec structure
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
RSpec.describe UserService do
|
|
102
|
+
describe "#create" do
|
|
103
|
+
subject(:result) { described_class.new(repo:).create(params) }
|
|
104
|
+
|
|
105
|
+
let(:repo) { instance_double(UserRepository) }
|
|
106
|
+
let(:params) { { name: "Alice", email: "alice@example.com" } }
|
|
107
|
+
|
|
108
|
+
context "with valid params" do
|
|
109
|
+
before { allow(repo).to receive(:save).and_return(user) }
|
|
110
|
+
let(:user) { build(:user, **params) }
|
|
111
|
+
|
|
112
|
+
it { is_expected.to be_success }
|
|
113
|
+
it { expect(result.value).to have_attributes(name: "Alice") }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context "with duplicate email" do
|
|
117
|
+
before { allow(repo).to receive(:save).and_raise(UniqueViolation) }
|
|
118
|
+
|
|
119
|
+
it { is_expected.to be_failure }
|
|
120
|
+
it { expect(result.error).to include("already exists") }
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- Use `describe` for the class/method, `context` for scenarios, `it` for assertions.
|
|
127
|
+
- Use `instance_double` for strict mocking — fails if the mocked method doesn't exist.
|
|
128
|
+
- Use `let` for lazy setup, `let!` for eager setup, `before` for side effects.
|
|
129
|
+
|
|
130
|
+
### Factory patterns
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
FactoryBot.define do
|
|
134
|
+
factory :user do
|
|
135
|
+
name { Faker::Name.name }
|
|
136
|
+
email { Faker::Internet.email }
|
|
137
|
+
role { :member }
|
|
138
|
+
|
|
139
|
+
trait :admin do
|
|
140
|
+
role { :admin }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
trait :with_posts do
|
|
144
|
+
after(:create) do |user|
|
|
145
|
+
create_list(:post, 3, author: user)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- Use traits for variations instead of separate factories.
|
|
153
|
+
- Prefer `build` (in-memory) over `create` (persisted) in unit tests for speed.
|
|
154
|
+
- Use `build_stubbed` for the fastest option when persistence behavior isn't under test.
|
|
155
|
+
|
|
156
|
+
## Gem dependency audit
|
|
157
|
+
|
|
158
|
+
### Bundler security workflow
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Check for known vulnerabilities
|
|
162
|
+
bundle audit check --update
|
|
163
|
+
|
|
164
|
+
# List outdated gems (direct dependencies only)
|
|
165
|
+
bundle outdated --only-explicit
|
|
166
|
+
|
|
167
|
+
# Generate dependency graph
|
|
168
|
+
bundle viz --format=svg
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- Run `bundle audit` in CI. Block deploys on critical findings.
|
|
172
|
+
- Update gems in small batches: `bundle update gem_name` + run full test suite.
|
|
173
|
+
- Review changelogs before major version bumps — breaking changes often affect behavior silently.
|
|
174
|
+
- Use `Gemfile` groups (`:development`, `:test`) to keep production dependencies minimal.
|
|
175
|
+
|
|
176
|
+
### Type checking with Sorbet
|
|
177
|
+
|
|
178
|
+
```ruby
|
|
179
|
+
# typed: strict
|
|
180
|
+
extend T::Sig
|
|
181
|
+
|
|
182
|
+
sig { params(name: String, age: Integer).returns(User) }
|
|
183
|
+
def create_user(name, age)
|
|
184
|
+
User.new(name:, age:)
|
|
185
|
+
end
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
- Use `typed: strict` for new files, `typed: true` as a minimum for existing files.
|
|
189
|
+
- Generate RBI files for gems: `tapioca gem` for type stubs.
|
|
190
|
+
- Run `srb tc` in CI alongside tests.
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Testing and RSpec Patterns
|
|
2
|
+
|
|
3
|
+
## RSpec Structure
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
# spec/services/create_order_spec.rb
|
|
7
|
+
RSpec.describe CreateOrder do
|
|
8
|
+
subject(:service) { described_class.new(order_repo:, pricing:, notifier:) }
|
|
9
|
+
|
|
10
|
+
let(:order_repo) { instance_double(OrderRepository) }
|
|
11
|
+
let(:pricing) { instance_double(PricingService) }
|
|
12
|
+
let(:notifier) { instance_double(EmailNotifier) }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
allow(order_repo).to receive(:save)
|
|
16
|
+
allow(notifier).to receive(:order_created)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "#call" do
|
|
20
|
+
context "with valid items" do
|
|
21
|
+
let(:items) { [build(:line_item, quantity: 2)] }
|
|
22
|
+
|
|
23
|
+
before do
|
|
24
|
+
allow(pricing).to receive(:calculate).and_return(Money.new(amount: 1999, currency: "USD"))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "creates an order" do
|
|
28
|
+
result = service.call(customer: build(:user), items:)
|
|
29
|
+
|
|
30
|
+
expect(result).to be_success
|
|
31
|
+
expect(result.value).to be_a(Order)
|
|
32
|
+
expect(result.value.total.amount).to eq(1999)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "saves to repository" do
|
|
36
|
+
service.call(customer: build(:user), items:)
|
|
37
|
+
expect(order_repo).to have_received(:save).once
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "notifies customer" do
|
|
41
|
+
service.call(customer: build(:user), items:)
|
|
42
|
+
expect(notifier).to have_received(:order_created).once
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "with empty items" do
|
|
47
|
+
it "returns failure" do
|
|
48
|
+
result = service.call(customer: build(:user), items: [])
|
|
49
|
+
expect(result).to be_failure
|
|
50
|
+
expect(result.error).to include("empty")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Shared Examples
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
# spec/support/shared_examples/authenticatable.rb
|
|
61
|
+
RSpec.shared_examples "authenticatable" do
|
|
62
|
+
describe "#authenticate" do
|
|
63
|
+
it "returns true for correct password" do
|
|
64
|
+
subject.password = "secret123"
|
|
65
|
+
expect(subject.authenticate("secret123")).to be true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "returns false for wrong password" do
|
|
69
|
+
subject.password = "secret123"
|
|
70
|
+
expect(subject.authenticate("wrong")).to be false
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Usage in specs
|
|
76
|
+
RSpec.describe User do
|
|
77
|
+
subject { build(:user) }
|
|
78
|
+
it_behaves_like "authenticatable"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
RSpec.describe AdminUser do
|
|
82
|
+
subject { build(:admin_user) }
|
|
83
|
+
it_behaves_like "authenticatable"
|
|
84
|
+
end
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Request Specs (API Testing)
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
RSpec.describe "Orders API", type: :request do
|
|
91
|
+
let(:user) { create(:user) }
|
|
92
|
+
let(:headers) { { "Authorization" => "Bearer #{user.auth_token}" } }
|
|
93
|
+
|
|
94
|
+
describe "POST /api/orders" do
|
|
95
|
+
let(:valid_params) do
|
|
96
|
+
{
|
|
97
|
+
order: {
|
|
98
|
+
items: [{ product_id: create(:product).id, quantity: 2 }],
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context "with valid params" do
|
|
104
|
+
it "creates order and returns 201" do
|
|
105
|
+
post "/api/orders", params: valid_params, headers:, as: :json
|
|
106
|
+
|
|
107
|
+
expect(response).to have_http_status(:created)
|
|
108
|
+
expect(json_response["order"]["id"]).to be_present
|
|
109
|
+
expect(Order.count).to eq(1)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context "without auth" do
|
|
114
|
+
it "returns 401" do
|
|
115
|
+
post "/api/orders", params: valid_params, as: :json
|
|
116
|
+
expect(response).to have_http_status(:unauthorized)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context "with invalid params" do
|
|
121
|
+
it "returns 422 with errors" do
|
|
122
|
+
post "/api/orders", params: { order: { items: [] } }, headers:, as: :json
|
|
123
|
+
|
|
124
|
+
expect(response).to have_http_status(:unprocessable_entity)
|
|
125
|
+
expect(json_response["errors"]).to include("items")
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Helper
|
|
132
|
+
def json_response
|
|
133
|
+
JSON.parse(response.body)
|
|
134
|
+
end
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## FactoryBot Strategies
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
# spec/factories/users.rb
|
|
141
|
+
FactoryBot.define do
|
|
142
|
+
factory :user do
|
|
143
|
+
sequence(:email) { |n| "user#{n}@example.com" }
|
|
144
|
+
name { Faker::Name.name }
|
|
145
|
+
role { :viewer }
|
|
146
|
+
password { "password123" }
|
|
147
|
+
|
|
148
|
+
trait :admin do
|
|
149
|
+
role { :admin }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
trait :with_orders do
|
|
153
|
+
transient do
|
|
154
|
+
order_count { 3 }
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
after(:create) do |user, evaluator|
|
|
158
|
+
create_list(:order, evaluator.order_count, customer: user)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Usage
|
|
165
|
+
build(:user) # in-memory, no DB
|
|
166
|
+
create(:user, :admin) # persisted admin
|
|
167
|
+
create(:user, :with_orders, order_count: 5) # with associated orders
|
|
168
|
+
attributes_for(:user) # hash of attributes
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Test Doubles
|
|
172
|
+
|
|
173
|
+
```ruby
|
|
174
|
+
# instance_double — verifies methods exist on the real class
|
|
175
|
+
repo = instance_double(OrderRepository)
|
|
176
|
+
allow(repo).to receive(:find_by_id).with(1).and_return(order)
|
|
177
|
+
allow(repo).to receive(:save).and_return(true)
|
|
178
|
+
|
|
179
|
+
# class_double
|
|
180
|
+
api_class = class_double(ExternalApi, fetch: response)
|
|
181
|
+
|
|
182
|
+
# spy — record calls, verify after
|
|
183
|
+
notifier = spy("notifier")
|
|
184
|
+
service.call(notifier:)
|
|
185
|
+
expect(notifier).to have_received(:notify).with(hash_including(type: :order_created))
|
|
186
|
+
|
|
187
|
+
# Stub chain
|
|
188
|
+
allow(User).to receive_message_chain(:active, :where, :order).and_return(users)
|
|
189
|
+
# Prefer extracting a query object over long stub chains
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## SimpleCov Configuration
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
# spec/spec_helper.rb (must be at the very top)
|
|
196
|
+
require "simplecov"
|
|
197
|
+
|
|
198
|
+
SimpleCov.start do
|
|
199
|
+
add_filter "/spec/"
|
|
200
|
+
add_filter "/config/"
|
|
201
|
+
add_filter "/vendor/"
|
|
202
|
+
|
|
203
|
+
add_group "Services", "app/services"
|
|
204
|
+
add_group "Models", "app/models"
|
|
205
|
+
add_group "Controllers", "app/controllers"
|
|
206
|
+
|
|
207
|
+
minimum_coverage 80
|
|
208
|
+
minimum_coverage_by_file 50
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# CI integration
|
|
212
|
+
if ENV["CI"]
|
|
213
|
+
require "simplecov-cobertura"
|
|
214
|
+
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
|
|
215
|
+
end
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## CI Test Pipeline
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Gemfile
|
|
222
|
+
group :test do
|
|
223
|
+
gem "rspec-rails"
|
|
224
|
+
gem "factory_bot_rails"
|
|
225
|
+
gem "faker"
|
|
226
|
+
gem "simplecov"
|
|
227
|
+
gem "webmock" # stub external HTTP
|
|
228
|
+
gem "vcr" # record/replay HTTP
|
|
229
|
+
gem "rubocop-rspec" # RSpec-specific linting
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# CI script
|
|
233
|
+
bundle exec rubocop --parallel # lint
|
|
234
|
+
bundle exec rspec --format documentation # tests
|
|
235
|
+
bundle audit check # vulnerability scan
|
|
236
|
+
```
|
|
@@ -2,51 +2,65 @@
|
|
|
2
2
|
---
|
|
3
3
|
inclusion: manual
|
|
4
4
|
name: "rust-pro"
|
|
5
|
-
description: "Use for modern Rust systems/services with stable 1.
|
|
5
|
+
description: "Use for modern Rust systems/services with stable 1.94-era patterns, async correctness, and performance-focused design."
|
|
6
6
|
license: MIT
|
|
7
7
|
metadata:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
stack: "rust"
|
|
12
|
-
baseline: "Rust stable 1.91"
|
|
8
|
+
author: cubis-foundry
|
|
9
|
+
version: "2.0"
|
|
10
|
+
compatibility: Claude Code, Codex, GitHub Copilot
|
|
13
11
|
---
|
|
14
12
|
|
|
15
13
|
# Rust Pro
|
|
16
14
|
|
|
17
|
-
##
|
|
15
|
+
## Purpose
|
|
18
16
|
|
|
19
|
-
-
|
|
20
|
-
|
|
17
|
+
Expert-level guidance for modern Rust development covering high-reliability services, CLIs, and systems components. Focuses on ownership and lifetime design, async correctness with cancellation safety, explicit error modeling, and performance optimization through profiling discipline.
|
|
18
|
+
|
|
19
|
+
## When to Use
|
|
20
|
+
|
|
21
|
+
- Building high-reliability services, CLIs, and systems components in Rust.
|
|
22
|
+
- Solving ownership, lifetime, and borrowing design problems.
|
|
21
23
|
- Optimizing memory safety and runtime performance together.
|
|
22
24
|
|
|
23
|
-
##
|
|
25
|
+
## Instructions
|
|
26
|
+
|
|
27
|
+
1. **Define ownership and error model first** — design data flow so each value has one clear owner. Clone only when shared ownership is genuinely required. Keep borrow scopes tight. Use `Cow<'_, T>` when a function sometimes needs to allocate and sometimes can borrow. Avoid lifetime annotations in public APIs unless the caller truly controls the borrowed data's scope.
|
|
28
|
+
|
|
29
|
+
2. **Choose async runtime and crates intentionally** — use `tokio` as the default async runtime. Pin to a specific runtime version in `Cargo.lock`. Make every async function cancellation-safe: dropping a future must not corrupt state. Use `tokio::select!` with care because the unselected branch is dropped and state mutations before `.await` are lost.
|
|
30
|
+
|
|
31
|
+
3. **Model errors as enums with context** — use `thiserror` for library error enums exposed in public APIs; `anyhow` for application-level error propagation. Use `?` for propagation with `.context()` / `.with_context()` at layer boundaries. Map foreign errors into domain types at crate boundaries. Do not use `.unwrap()` or `.expect()` outside tests and provably-infallible paths because they cause panics in production. Do not leak dependency error types across crate boundaries because it couples consumers to transitive dependencies.
|
|
32
|
+
|
|
33
|
+
4. **Design traits and types for the problem** — model closed variant sets with enums and exhaustive `match`. Use trait objects (`dyn Trait`) only at plugin or boundary points. Implement `From`/`Into` for natural conversions, `TryFrom`/`TryInto` for fallible ones. Keep trait surfaces small. Use newtype wrappers (`struct UserId(u64)`) to prevent primitive type confusion.
|
|
34
|
+
|
|
35
|
+
5. **Implement in small composable modules** — use `tokio`/`axum`/`tower` patterns for service work. Use `tower` middleware for timeouts, rate limits, and retries at the service boundary. Separate transport DTOs from domain types. Keep `Send + Sync` bounds explicit in trait objects and spawned tasks.
|
|
36
|
+
|
|
37
|
+
6. **Keep `unsafe` minimal and documented** — document invariants for every `unsafe` block. Prefer safe abstractions. Do not use premature `unsafe` optimization because the compiler and optimizer handle most cases.
|
|
38
|
+
|
|
39
|
+
7. **Verify with tests, clippy, and formatting** — maintain `rustfmt` + `clippy` clean in CI. Use `cargo test` and targeted benchmarks. Make task cancellation, retries, and error chains visible in `tracing` instrumentation. Prefer iterator/trait composition over macro-heavy complexity.
|
|
40
|
+
|
|
41
|
+
8. **Profile before low-level optimization** — measure allocations, lock contention, and tail latency before unsafe or low-level tuning. Bound work queues and connection pools explicitly. Do not use unbounded `tokio::spawn` fan-out without backpressure because it exhausts resources. Do not use `Arc<Mutex<T>>` when a channel-based ownership transfer would be clearer because it adds unnecessary contention. Do not use global mutable state for request data because it creates race conditions.
|
|
42
|
+
|
|
43
|
+
## Output Format
|
|
24
44
|
|
|
25
|
-
|
|
26
|
-
2. Choose async/runtime crates intentionally.
|
|
27
|
-
3. Implement small composable modules.
|
|
28
|
-
4. Verify with tests, clippy, and formatting.
|
|
29
|
-
5. Profile before low-level optimization.
|
|
45
|
+
Produces Rust code with explicit ownership design, structured error enums, cancellation-safe async patterns, and bounded concurrency. Includes trait-based abstractions and newtype wrappers where applicable.
|
|
30
46
|
|
|
31
|
-
##
|
|
47
|
+
## References
|
|
32
48
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
49
|
+
| File | Load when |
|
|
50
|
+
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `references/ownership-and-borrowing.md` | Ownership transfer, borrow scope design, lifetime annotations, or `Cow`/`Arc` tradeoffs need detail. |
|
|
52
|
+
| `references/async-safety-patterns.md` | Cancellation safety, `select!` pitfalls, structured concurrency, or runtime configuration need detail. |
|
|
53
|
+
| `references/error-handling-design.md` | Error enum design, `thiserror`/`anyhow` layering, context chains, or foreign error mapping need detail. |
|
|
54
|
+
| `references/trait-design-patterns.md` | Trait object vs enum dispatch, newtype patterns, `From`/`Into` design, or generic constraints need detail. |
|
|
55
|
+
| `references/unsafe-and-ffi-guide.md` | Unsafe blocks, FFI boundaries, raw pointer invariants, or soundness documentation need detail. |
|
|
38
56
|
|
|
39
|
-
##
|
|
57
|
+
## Scripts
|
|
40
58
|
|
|
41
|
-
|
|
42
|
-
- Model domain states with enums and exhaustive matching.
|
|
43
|
-
- Use `Arc` + interior mutability only when ownership alternatives fail.
|
|
44
|
-
- Keep borrow scopes tight to improve readability and compile times.
|
|
45
|
-
- Separate transport DTOs from domain types.
|
|
59
|
+
No helper scripts are required for this skill right now. Keep execution in `SKILL.md` and `references/` unless repeated automation becomes necessary.
|
|
46
60
|
|
|
47
|
-
##
|
|
61
|
+
## Examples
|
|
48
62
|
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
63
|
+
- "Design the error type hierarchy for this multi-crate workspace with thiserror for libraries and anyhow at the application layer."
|
|
64
|
+
- "Refactor this async handler to be cancellation-safe when using tokio::select! with shared state."
|
|
65
|
+
- "Implement a bounded worker pool with backpressure using tokio channels and a semaphore."
|
|
52
66
|
````
|
|
@@ -1,49 +1,63 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "rust-pro"
|
|
3
|
-
description: "Use for modern Rust systems/services with stable 1.
|
|
3
|
+
description: "Use for modern Rust systems/services with stable 1.94-era patterns, async correctness, and performance-focused design."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
stack: "rust"
|
|
10
|
-
baseline: "Rust stable 1.91"
|
|
6
|
+
author: cubis-foundry
|
|
7
|
+
version: "2.0"
|
|
8
|
+
compatibility: Claude Code, Codex, GitHub Copilot
|
|
11
9
|
---
|
|
12
10
|
|
|
13
11
|
# Rust Pro
|
|
14
12
|
|
|
15
|
-
##
|
|
13
|
+
## Purpose
|
|
16
14
|
|
|
17
|
-
-
|
|
18
|
-
|
|
15
|
+
Expert-level guidance for modern Rust development covering high-reliability services, CLIs, and systems components. Focuses on ownership and lifetime design, async correctness with cancellation safety, explicit error modeling, and performance optimization through profiling discipline.
|
|
16
|
+
|
|
17
|
+
## When to Use
|
|
18
|
+
|
|
19
|
+
- Building high-reliability services, CLIs, and systems components in Rust.
|
|
20
|
+
- Solving ownership, lifetime, and borrowing design problems.
|
|
19
21
|
- Optimizing memory safety and runtime performance together.
|
|
20
22
|
|
|
21
|
-
##
|
|
23
|
+
## Instructions
|
|
24
|
+
|
|
25
|
+
1. **Define ownership and error model first** — design data flow so each value has one clear owner. Clone only when shared ownership is genuinely required. Keep borrow scopes tight. Use `Cow<'_, T>` when a function sometimes needs to allocate and sometimes can borrow. Avoid lifetime annotations in public APIs unless the caller truly controls the borrowed data's scope.
|
|
26
|
+
|
|
27
|
+
2. **Choose async runtime and crates intentionally** — use `tokio` as the default async runtime. Pin to a specific runtime version in `Cargo.lock`. Make every async function cancellation-safe: dropping a future must not corrupt state. Use `tokio::select!` with care because the unselected branch is dropped and state mutations before `.await` are lost.
|
|
28
|
+
|
|
29
|
+
3. **Model errors as enums with context** — use `thiserror` for library error enums exposed in public APIs; `anyhow` for application-level error propagation. Use `?` for propagation with `.context()` / `.with_context()` at layer boundaries. Map foreign errors into domain types at crate boundaries. Do not use `.unwrap()` or `.expect()` outside tests and provably-infallible paths because they cause panics in production. Do not leak dependency error types across crate boundaries because it couples consumers to transitive dependencies.
|
|
30
|
+
|
|
31
|
+
4. **Design traits and types for the problem** — model closed variant sets with enums and exhaustive `match`. Use trait objects (`dyn Trait`) only at plugin or boundary points. Implement `From`/`Into` for natural conversions, `TryFrom`/`TryInto` for fallible ones. Keep trait surfaces small. Use newtype wrappers (`struct UserId(u64)`) to prevent primitive type confusion.
|
|
32
|
+
|
|
33
|
+
5. **Implement in small composable modules** — use `tokio`/`axum`/`tower` patterns for service work. Use `tower` middleware for timeouts, rate limits, and retries at the service boundary. Separate transport DTOs from domain types. Keep `Send + Sync` bounds explicit in trait objects and spawned tasks.
|
|
34
|
+
|
|
35
|
+
6. **Keep `unsafe` minimal and documented** — document invariants for every `unsafe` block. Prefer safe abstractions. Do not use premature `unsafe` optimization because the compiler and optimizer handle most cases.
|
|
36
|
+
|
|
37
|
+
7. **Verify with tests, clippy, and formatting** — maintain `rustfmt` + `clippy` clean in CI. Use `cargo test` and targeted benchmarks. Make task cancellation, retries, and error chains visible in `tracing` instrumentation. Prefer iterator/trait composition over macro-heavy complexity.
|
|
38
|
+
|
|
39
|
+
8. **Profile before low-level optimization** — measure allocations, lock contention, and tail latency before unsafe or low-level tuning. Bound work queues and connection pools explicitly. Do not use unbounded `tokio::spawn` fan-out without backpressure because it exhausts resources. Do not use `Arc<Mutex<T>>` when a channel-based ownership transfer would be clearer because it adds unnecessary contention. Do not use global mutable state for request data because it creates race conditions.
|
|
40
|
+
|
|
41
|
+
## Output Format
|
|
22
42
|
|
|
23
|
-
|
|
24
|
-
2. Choose async/runtime crates intentionally.
|
|
25
|
-
3. Implement small composable modules.
|
|
26
|
-
4. Verify with tests, clippy, and formatting.
|
|
27
|
-
5. Profile before low-level optimization.
|
|
43
|
+
Produces Rust code with explicit ownership design, structured error enums, cancellation-safe async patterns, and bounded concurrency. Includes trait-based abstractions and newtype wrappers where applicable.
|
|
28
44
|
|
|
29
|
-
##
|
|
45
|
+
## References
|
|
30
46
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
47
|
+
| File | Load when |
|
|
48
|
+
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
49
|
+
| `references/ownership-and-borrowing.md` | Ownership transfer, borrow scope design, lifetime annotations, or `Cow`/`Arc` tradeoffs need detail. |
|
|
50
|
+
| `references/async-safety-patterns.md` | Cancellation safety, `select!` pitfalls, structured concurrency, or runtime configuration need detail. |
|
|
51
|
+
| `references/error-handling-design.md` | Error enum design, `thiserror`/`anyhow` layering, context chains, or foreign error mapping need detail. |
|
|
52
|
+
| `references/trait-design-patterns.md` | Trait object vs enum dispatch, newtype patterns, `From`/`Into` design, or generic constraints need detail. |
|
|
53
|
+
| `references/unsafe-and-ffi-guide.md` | Unsafe blocks, FFI boundaries, raw pointer invariants, or soundness documentation need detail. |
|
|
36
54
|
|
|
37
|
-
##
|
|
55
|
+
## Scripts
|
|
38
56
|
|
|
39
|
-
|
|
40
|
-
- Model domain states with enums and exhaustive matching.
|
|
41
|
-
- Use `Arc` + interior mutability only when ownership alternatives fail.
|
|
42
|
-
- Keep borrow scopes tight to improve readability and compile times.
|
|
43
|
-
- Separate transport DTOs from domain types.
|
|
57
|
+
No helper scripts are required for this skill right now. Keep execution in `SKILL.md` and `references/` unless repeated automation becomes necessary.
|
|
44
58
|
|
|
45
|
-
##
|
|
59
|
+
## Examples
|
|
46
60
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
61
|
+
- "Design the error type hierarchy for this multi-crate workspace with thiserror for libraries and anyhow at the application layer."
|
|
62
|
+
- "Refactor this async handler to be cancellation-safe when using tokio::select! with shared state."
|
|
63
|
+
- "Implement a bounded worker pool with backpressure using tokio channels and a semaphore."
|