cfsa-antigravity 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +14 -0
  2. package/package.json +1 -1
  3. package/template/.agent/instructions/commands.md +8 -32
  4. package/template/.agent/instructions/example.md +21 -0
  5. package/template/.agent/instructions/patterns.md +3 -3
  6. package/template/.agent/instructions/tech-stack.md +71 -23
  7. package/template/.agent/instructions/workflow.md +12 -1
  8. package/template/.agent/rules/completion-checklist.md +6 -0
  9. package/template/.agent/rules/security-first.md +3 -3
  10. package/template/.agent/rules/vertical-slices.md +1 -1
  11. package/template/.agent/skill-library/MANIFEST.md +6 -0
  12. package/template/.agent/skill-library/stack/devops/git-advanced/SKILL.md +972 -0
  13. package/template/.agent/skill-library/stack/devops/git-workflow/SKILL.md +420 -0
  14. package/template/.agent/skills/api-versioning/SKILL.md +44 -298
  15. package/template/.agent/skills/api-versioning/references/typescript.md +157 -0
  16. package/template/.agent/skills/architecture-mapping/SKILL.md +13 -13
  17. package/template/.agent/skills/bootstrap-agents/SKILL.md +151 -152
  18. package/template/.agent/skills/clean-code/SKILL.md +64 -118
  19. package/template/.agent/skills/clean-code/references/typescript.md +126 -0
  20. package/template/.agent/skills/database-schema-design/SKILL.md +93 -317
  21. package/template/.agent/skills/database-schema-design/references/relational.md +228 -0
  22. package/template/.agent/skills/error-handling-patterns/SKILL.md +62 -557
  23. package/template/.agent/skills/error-handling-patterns/references/go.md +162 -0
  24. package/template/.agent/skills/error-handling-patterns/references/python.md +262 -0
  25. package/template/.agent/skills/error-handling-patterns/references/rust.md +112 -0
  26. package/template/.agent/skills/error-handling-patterns/references/typescript.md +178 -0
  27. package/template/.agent/skills/idea-extraction/SKILL.md +322 -224
  28. package/template/.agent/skills/logging-best-practices/SKILL.md +108 -767
  29. package/template/.agent/skills/logging-best-practices/references/go.md +49 -0
  30. package/template/.agent/skills/logging-best-practices/references/python.md +52 -0
  31. package/template/.agent/skills/logging-best-practices/references/typescript.md +215 -0
  32. package/template/.agent/skills/migration-management/SKILL.md +127 -311
  33. package/template/.agent/skills/migration-management/references/relational.md +214 -0
  34. package/template/.agent/skills/parallel-feature-development/SKILL.md +34 -43
  35. package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +1 -1
  36. package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +2 -2
  37. package/template/.agent/skills/pipeline-rubrics/references/scoring.md +1 -1
  38. package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +2 -1
  39. package/template/.agent/skills/prd-templates/SKILL.md +23 -6
  40. package/template/.agent/skills/prd-templates/references/be-spec-template.md +2 -2
  41. package/template/.agent/skills/prd-templates/references/decomposition-templates.md +2 -2
  42. package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +2 -0
  43. package/template/.agent/skills/prd-templates/references/fe-spec-template.md +1 -1
  44. package/template/.agent/skills/prd-templates/references/fractal-cx-template.md +58 -0
  45. package/template/.agent/skills/prd-templates/references/fractal-feature-template.md +93 -0
  46. package/template/.agent/skills/prd-templates/references/fractal-node-index-template.md +55 -0
  47. package/template/.agent/skills/prd-templates/references/ideation-crosscut-template.md +26 -47
  48. package/template/.agent/skills/prd-templates/references/ideation-index-template.md +47 -31
  49. package/template/.agent/skills/prd-templates/references/operational-templates.md +1 -1
  50. package/template/.agent/skills/prd-templates/references/placeholder-workflow-mapping.md +50 -21
  51. package/template/.agent/skills/prd-templates/references/skill-loading-protocol.md +32 -0
  52. package/template/.agent/skills/prd-templates/references/slice-completion-gates.md +29 -0
  53. package/template/.agent/skills/prd-templates/references/spec-coverage-sweep.md +3 -3
  54. package/template/.agent/skills/prd-templates/references/tdd-testing-policy.md +39 -0
  55. package/template/.agent/skills/prd-templates/references/vision-template.md +8 -8
  56. package/template/.agent/skills/regex-patterns/SKILL.md +122 -540
  57. package/template/.agent/skills/regex-patterns/references/go.md +44 -0
  58. package/template/.agent/skills/regex-patterns/references/javascript.md +63 -0
  59. package/template/.agent/skills/regex-patterns/references/python.md +77 -0
  60. package/template/.agent/skills/regex-patterns/references/rust.md +43 -0
  61. package/template/.agent/skills/resolve-ambiguity/SKILL.md +1 -1
  62. package/template/.agent/skills/session-continuity/SKILL.md +11 -9
  63. package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +2 -2
  64. package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +1 -1
  65. package/template/.agent/skills/session-continuity/protocols/05-session-close.md +1 -1
  66. package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +1 -1
  67. package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +57 -78
  68. package/template/.agent/skills/session-continuity/protocols/11-parallel-synthesis.md +1 -1
  69. package/template/.agent/skills/spec-writing/SKILL.md +1 -1
  70. package/template/.agent/skills/tdd-workflow/SKILL.md +94 -317
  71. package/template/.agent/skills/tdd-workflow/references/typescript.md +231 -0
  72. package/template/.agent/skills/testing-strategist/SKILL.md +74 -687
  73. package/template/.agent/skills/testing-strategist/references/typescript.md +328 -0
  74. package/template/.agent/skills/workflow-automation/SKILL.md +62 -154
  75. package/template/.agent/skills/workflow-automation/references/inngest.md +88 -0
  76. package/template/.agent/skills/workflow-automation/references/temporal.md +64 -0
  77. package/template/.agent/workflows/bootstrap-agents-fill.md +85 -143
  78. package/template/.agent/workflows/bootstrap-agents-provision.md +90 -107
  79. package/template/.agent/workflows/create-prd-architecture.md +23 -16
  80. package/template/.agent/workflows/create-prd-compile.md +11 -12
  81. package/template/.agent/workflows/create-prd-design-system.md +1 -1
  82. package/template/.agent/workflows/create-prd-security.md +9 -11
  83. package/template/.agent/workflows/create-prd-stack.md +10 -4
  84. package/template/.agent/workflows/create-prd.md +9 -9
  85. package/template/.agent/workflows/decompose-architecture-structure.md +4 -6
  86. package/template/.agent/workflows/decompose-architecture-validate.md +18 -1
  87. package/template/.agent/workflows/decompose-architecture.md +18 -3
  88. package/template/.agent/workflows/evolve-contract.md +11 -11
  89. package/template/.agent/workflows/evolve-feature-classify.md +14 -6
  90. package/template/.agent/workflows/ideate-discover.md +72 -107
  91. package/template/.agent/workflows/ideate-extract.md +84 -63
  92. package/template/.agent/workflows/ideate-validate.md +26 -22
  93. package/template/.agent/workflows/ideate.md +9 -9
  94. package/template/.agent/workflows/implement-slice-setup.md +25 -23
  95. package/template/.agent/workflows/implement-slice-tdd.md +73 -89
  96. package/template/.agent/workflows/implement-slice.md +4 -4
  97. package/template/.agent/workflows/plan-phase-preflight.md +6 -2
  98. package/template/.agent/workflows/plan-phase-write.md +6 -8
  99. package/template/.agent/workflows/remediate-pipeline-assess.md +2 -1
  100. package/template/.agent/workflows/resolve-ambiguity.md +2 -2
  101. package/template/.agent/workflows/update-architecture-map.md +22 -5
  102. package/template/.agent/workflows/validate-phase-quality.md +155 -0
  103. package/template/.agent/workflows/validate-phase-readiness.md +167 -0
  104. package/template/.agent/workflows/validate-phase.md +19 -157
  105. package/template/.agent/workflows/verify-infrastructure.md +10 -10
  106. package/template/.agent/workflows/write-architecture-spec-design.md +23 -14
  107. package/template/.agent/workflows/write-be-spec-classify.md +25 -21
  108. package/template/.agent/workflows/write-be-spec.md +1 -1
  109. package/template/.agent/workflows/write-fe-spec-classify.md +6 -12
  110. package/template/.agent/workflows/write-fe-spec-write.md +1 -1
  111. package/template/AGENTS.md +6 -2
  112. package/template/GEMINI.md +5 -3
  113. package/template/docs/README.md +10 -10
  114. package/template/docs/kit-architecture.md +126 -33
  115. package/template/docs/plans/ideation/README.md +8 -3
  116. package/template/.agent/skills/prd-templates/references/ideation-domain-template.md +0 -55
@@ -0,0 +1,162 @@
1
+ # Go Error Handling Patterns
2
+
3
+ Language-specific patterns for the `error-handling-patterns` skill. Read `SKILL.md` first for universal methodology.
4
+
5
+ ---
6
+
7
+ ## Explicit Error Returns
8
+
9
+ ```go
10
+ // Basic error handling
11
+ func getUser(id string) (*User, error) {
12
+ user, err := db.QueryUser(id)
13
+ if err != nil {
14
+ return nil, fmt.Errorf("failed to query user: %w", err)
15
+ }
16
+ if user == nil {
17
+ return nil, errors.New("user not found")
18
+ }
19
+ return user, nil
20
+ }
21
+
22
+ // Custom error types
23
+ type ValidationError struct {
24
+ Field string
25
+ Message string
26
+ }
27
+
28
+ func (e *ValidationError) Error() string {
29
+ return fmt.Sprintf("validation failed for %s: %s", e.Field, e.Message)
30
+ }
31
+
32
+ // Sentinel errors for comparison
33
+ var (
34
+ ErrNotFound = errors.New("not found")
35
+ ErrUnauthorized = errors.New("unauthorized")
36
+ ErrInvalidInput = errors.New("invalid input")
37
+ )
38
+ ```
39
+
40
+ ## Error Checking and Wrapping
41
+
42
+ ```go
43
+ // Error checking with errors.Is
44
+ user, err := getUser("123")
45
+ if err != nil {
46
+ if errors.Is(err, ErrNotFound) {
47
+ // Handle not found
48
+ } else {
49
+ // Handle other errors
50
+ }
51
+ }
52
+
53
+ // Error wrapping preserves the chain
54
+ func processUser(id string) error {
55
+ user, err := getUser(id)
56
+ if err != nil {
57
+ return fmt.Errorf("process user failed: %w", err)
58
+ }
59
+ // Process user
60
+ return nil
61
+ }
62
+
63
+ // Unwrap to specific error types
64
+ err := processUser("123")
65
+ if err != nil {
66
+ var valErr *ValidationError
67
+ if errors.As(err, &valErr) {
68
+ fmt.Printf("Validation error: %s\n", valErr.Field)
69
+ }
70
+ }
71
+ ```
72
+
73
+ ## Defer for Cleanup
74
+
75
+ ```go
76
+ func readFile(path string) (string, error) {
77
+ f, err := os.Open(path)
78
+ if err != nil {
79
+ return "", fmt.Errorf("open file: %w", err)
80
+ }
81
+ defer f.Close() // Always runs, even on error
82
+
83
+ data, err := io.ReadAll(f)
84
+ if err != nil {
85
+ return "", fmt.Errorf("read file: %w", err)
86
+ }
87
+ return string(data), nil
88
+ }
89
+
90
+ // Defer with error handling
91
+ func writeData(path string, data []byte) (err error) {
92
+ f, err := os.Create(path)
93
+ if err != nil {
94
+ return fmt.Errorf("create file: %w", err)
95
+ }
96
+ defer func() {
97
+ closeErr := f.Close()
98
+ if err == nil {
99
+ err = closeErr
100
+ }
101
+ }()
102
+
103
+ _, err = f.Write(data)
104
+ return err
105
+ }
106
+ ```
107
+
108
+ ## Panic and Recover
109
+
110
+ ```go
111
+ // Panic for unrecoverable errors (programming bugs)
112
+ func mustParseConfig(path string) Config {
113
+ cfg, err := parseConfig(path)
114
+ if err != nil {
115
+ panic(fmt.Sprintf("config parse failed: %v", err))
116
+ }
117
+ return cfg
118
+ }
119
+
120
+ // Recover in middleware/handlers to prevent crashes
121
+ func recoveryMiddleware(next http.Handler) http.Handler {
122
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
123
+ defer func() {
124
+ if err := recover(); err != nil {
125
+ log.Printf("panic recovered: %v\n%s", err, debug.Stack())
126
+ http.Error(w, "Internal Server Error", 500)
127
+ }
128
+ }()
129
+ next.ServeHTTP(w, r)
130
+ })
131
+ }
132
+ ```
133
+
134
+ ## Error Groups for Concurrent Operations
135
+
136
+ ```go
137
+ import "golang.org/x/sync/errgroup"
138
+
139
+ func fetchAllData(ctx context.Context) (*AllData, error) {
140
+ g, ctx := errgroup.WithContext(ctx)
141
+ var users []User
142
+ var orders []Order
143
+
144
+ g.Go(func() error {
145
+ var err error
146
+ users, err = fetchUsers(ctx)
147
+ return err
148
+ })
149
+
150
+ g.Go(func() error {
151
+ var err error
152
+ orders, err = fetchOrders(ctx)
153
+ return err
154
+ })
155
+
156
+ if err := g.Wait(); err != nil {
157
+ return nil, fmt.Errorf("fetch all data: %w", err)
158
+ }
159
+
160
+ return &AllData{Users: users, Orders: orders}, nil
161
+ }
162
+ ```
@@ -0,0 +1,262 @@
1
+ # Python Error Handling Patterns
2
+
3
+ Language-specific patterns for the `error-handling-patterns` skill. Read `SKILL.md` first for universal methodology.
4
+
5
+ ---
6
+
7
+ ## Custom Exception Hierarchy
8
+
9
+ ```python
10
+ class ApplicationError(Exception):
11
+ """Base exception for all application errors."""
12
+ def __init__(self, message: str, code: str = None, details: dict = None):
13
+ super().__init__(message)
14
+ self.code = code
15
+ self.details = details or {}
16
+ self.timestamp = datetime.utcnow()
17
+
18
+ class ValidationError(ApplicationError):
19
+ """Raised when validation fails."""
20
+ pass
21
+
22
+ class NotFoundError(ApplicationError):
23
+ """Raised when resource not found."""
24
+ pass
25
+
26
+ class ExternalServiceError(ApplicationError):
27
+ """Raised when external service fails."""
28
+ def __init__(self, message: str, service: str, **kwargs):
29
+ super().__init__(message, **kwargs)
30
+ self.service = service
31
+
32
+ # Usage
33
+ def get_user(user_id: str) -> User:
34
+ user = db.query(User).filter_by(id=user_id).first()
35
+ if not user:
36
+ raise NotFoundError(
37
+ f"User not found",
38
+ code="USER_NOT_FOUND",
39
+ details={"user_id": user_id}
40
+ )
41
+ return user
42
+ ```
43
+
44
+ ## Context Managers for Cleanup
45
+
46
+ ```python
47
+ from contextlib import contextmanager
48
+
49
+ @contextmanager
50
+ def database_transaction(session):
51
+ """Ensure transaction is committed or rolled back."""
52
+ try:
53
+ yield session
54
+ session.commit()
55
+ except Exception as e:
56
+ session.rollback()
57
+ raise
58
+ finally:
59
+ session.close()
60
+
61
+ # Usage
62
+ with database_transaction(db.session) as session:
63
+ user = User(name="Alice")
64
+ session.add(user)
65
+ # Automatic commit or rollback
66
+ ```
67
+
68
+ ## Retry with Exponential Backoff
69
+
70
+ ```python
71
+ import time
72
+ from functools import wraps
73
+ from typing import TypeVar, Callable
74
+
75
+ T = TypeVar('T')
76
+
77
+ def retry(
78
+ max_attempts: int = 3,
79
+ backoff_factor: float = 2.0,
80
+ exceptions: tuple = (Exception,)
81
+ ):
82
+ """Retry decorator with exponential backoff."""
83
+ def decorator(func: Callable[..., T]) -> Callable[..., T]:
84
+ @wraps(func)
85
+ def wrapper(*args, **kwargs) -> T:
86
+ last_exception = None
87
+ for attempt in range(max_attempts):
88
+ try:
89
+ return func(*args, **kwargs)
90
+ except exceptions as e:
91
+ last_exception = e
92
+ if attempt < max_attempts - 1:
93
+ sleep_time = backoff_factor ** attempt
94
+ time.sleep(sleep_time)
95
+ continue
96
+ raise
97
+ raise last_exception
98
+ return wrapper
99
+ return decorator
100
+
101
+ # Usage
102
+ @retry(max_attempts=3, exceptions=(NetworkError,))
103
+ def fetch_data(url: str) -> dict:
104
+ response = requests.get(url, timeout=5)
105
+ response.raise_for_status()
106
+ return response.json()
107
+ ```
108
+
109
+ ## Circuit Breaker
110
+
111
+ ```python
112
+ from enum import Enum
113
+ from datetime import datetime, timedelta
114
+ from typing import Callable, TypeVar
115
+
116
+ T = TypeVar('T')
117
+
118
+ class CircuitState(Enum):
119
+ CLOSED = "closed" # Normal operation
120
+ OPEN = "open" # Failing, reject requests
121
+ HALF_OPEN = "half_open" # Testing if recovered
122
+
123
+ class CircuitBreaker:
124
+ def __init__(
125
+ self,
126
+ failure_threshold: int = 5,
127
+ timeout: timedelta = timedelta(seconds=60),
128
+ success_threshold: int = 2
129
+ ):
130
+ self.failure_threshold = failure_threshold
131
+ self.timeout = timeout
132
+ self.success_threshold = success_threshold
133
+ self.failure_count = 0
134
+ self.success_count = 0
135
+ self.state = CircuitState.CLOSED
136
+ self.last_failure_time = None
137
+
138
+ def call(self, func: Callable[[], T]) -> T:
139
+ if self.state == CircuitState.OPEN:
140
+ if datetime.now() - self.last_failure_time > self.timeout:
141
+ self.state = CircuitState.HALF_OPEN
142
+ self.success_count = 0
143
+ else:
144
+ raise Exception("Circuit breaker is OPEN")
145
+
146
+ try:
147
+ result = func()
148
+ self.on_success()
149
+ return result
150
+ except Exception as e:
151
+ self.on_failure()
152
+ raise
153
+
154
+ def on_success(self):
155
+ self.failure_count = 0
156
+ if self.state == CircuitState.HALF_OPEN:
157
+ self.success_count += 1
158
+ if self.success_count >= self.success_threshold:
159
+ self.state = CircuitState.CLOSED
160
+ self.success_count = 0
161
+
162
+ def on_failure(self):
163
+ self.failure_count += 1
164
+ self.last_failure_time = datetime.now()
165
+ if self.failure_count >= self.failure_threshold:
166
+ self.state = CircuitState.OPEN
167
+
168
+ # Usage
169
+ circuit_breaker = CircuitBreaker()
170
+
171
+ def fetch_data():
172
+ return circuit_breaker.call(lambda: external_api.get_data())
173
+ ```
174
+
175
+ ## Graceful Degradation
176
+
177
+ ```python
178
+ from typing import Optional, Callable, TypeVar
179
+
180
+ T = TypeVar('T')
181
+
182
+ def with_fallback(
183
+ primary: Callable[[], T],
184
+ fallback: Callable[[], T],
185
+ log_error: bool = True
186
+ ) -> T:
187
+ """Try primary function, fall back to fallback on error."""
188
+ try:
189
+ return primary()
190
+ except Exception as e:
191
+ if log_error:
192
+ logger.error(f"Primary function failed: {e}")
193
+ return fallback()
194
+
195
+ # Usage
196
+ def get_user_profile(user_id: str) -> UserProfile:
197
+ return with_fallback(
198
+ primary=lambda: fetch_from_cache(user_id),
199
+ fallback=lambda: fetch_from_database(user_id)
200
+ )
201
+
202
+ # Multiple fallbacks
203
+ def get_exchange_rate(currency: str) -> float:
204
+ return (
205
+ try_function(lambda: api_provider_1.get_rate(currency))
206
+ or try_function(lambda: api_provider_2.get_rate(currency))
207
+ or try_function(lambda: cache.get_rate(currency))
208
+ or DEFAULT_RATE
209
+ )
210
+
211
+ def try_function(func: Callable[[], Optional[T]]) -> Optional[T]:
212
+ try:
213
+ return func()
214
+ except Exception:
215
+ return None
216
+ ```
217
+
218
+ ## Comprehensive Example
219
+
220
+ ```python
221
+ def process_order(order_id: str) -> Order:
222
+ """Process order with comprehensive error handling."""
223
+ try:
224
+ # Validate input
225
+ if not order_id:
226
+ raise ValidationError("Order ID is required")
227
+
228
+ # Fetch order
229
+ order = db.get_order(order_id)
230
+ if not order:
231
+ raise NotFoundError("Order", order_id)
232
+
233
+ # Process payment
234
+ try:
235
+ payment_result = payment_service.charge(order.total)
236
+ except PaymentServiceError as e:
237
+ # Log and wrap external service error
238
+ logger.error(f"Payment failed for order {order_id}: {e}")
239
+ raise ExternalServiceError(
240
+ f"Payment processing failed",
241
+ service="payment_service",
242
+ details={"order_id": order_id, "amount": order.total}
243
+ ) from e
244
+
245
+ # Update order
246
+ order.status = "completed"
247
+ order.payment_id = payment_result.id
248
+ db.save(order)
249
+
250
+ return order
251
+
252
+ except ApplicationError:
253
+ # Re-raise known application errors
254
+ raise
255
+ except Exception as e:
256
+ # Log unexpected errors
257
+ logger.exception(f"Unexpected error processing order {order_id}")
258
+ raise ApplicationError(
259
+ "Order processing failed",
260
+ code="INTERNAL_ERROR"
261
+ ) from e
262
+ ```
@@ -0,0 +1,112 @@
1
+ # Rust Error Handling Patterns
2
+
3
+ Language-specific patterns for the `error-handling-patterns` skill. Read `SKILL.md` first for universal methodology.
4
+
5
+ ---
6
+
7
+ ## Result and Option Types
8
+
9
+ ```rust
10
+ use std::fs::File;
11
+ use std::io::{self, Read};
12
+
13
+ // Result type for operations that can fail
14
+ fn read_file(path: &str) -> Result<String, io::Error> {
15
+ let mut file = File::open(path)?; // ? operator propagates errors
16
+ let mut contents = String::new();
17
+ file.read_to_string(&mut contents)?;
18
+ Ok(contents)
19
+ }
20
+
21
+ // Custom error types
22
+ #[derive(Debug)]
23
+ enum AppError {
24
+ Io(io::Error),
25
+ Parse(std::num::ParseIntError),
26
+ NotFound(String),
27
+ Validation(String),
28
+ }
29
+
30
+ impl From<io::Error> for AppError {
31
+ fn from(error: io::Error) -> Self {
32
+ AppError::Io(error)
33
+ }
34
+ }
35
+
36
+ // Using custom error type
37
+ fn read_number_from_file(path: &str) -> Result<i32, AppError> {
38
+ let contents = read_file(path)?; // Auto-converts io::Error
39
+ let number = contents.trim().parse()
40
+ .map_err(AppError::Parse)?; // Explicitly convert ParseIntError
41
+ Ok(number)
42
+ }
43
+
44
+ // Option for nullable values
45
+ fn find_user(id: &str) -> Option<User> {
46
+ users.iter().find(|u| u.id == id).cloned()
47
+ }
48
+
49
+ // Combining Option and Result
50
+ fn get_user_age(id: &str) -> Result<u32, AppError> {
51
+ find_user(id)
52
+ .ok_or_else(|| AppError::NotFound(id.to_string()))
53
+ .map(|user| user.age)
54
+ }
55
+ ```
56
+
57
+ ## Error Crate Patterns
58
+
59
+ For production Rust applications, consider using error crates:
60
+
61
+ - **`thiserror`** — derive macro for custom error types with automatic `Display` and `From` implementations
62
+ - **`anyhow`** — flexible error type for applications (not libraries) with context chaining
63
+ - **`eyre`** — enhanced error reporting with `color-eyre` for human-readable error output
64
+
65
+ ```rust
66
+ // With thiserror
67
+ use thiserror::Error;
68
+
69
+ #[derive(Error, Debug)]
70
+ enum AppError {
71
+ #[error("IO error: {0}")]
72
+ Io(#[from] io::Error),
73
+
74
+ #[error("Parse error: {0}")]
75
+ Parse(#[from] std::num::ParseIntError),
76
+
77
+ #[error("Resource not found: {0}")]
78
+ NotFound(String),
79
+
80
+ #[error("Validation failed: {0}")]
81
+ Validation(String),
82
+ }
83
+
84
+ // With anyhow (application code)
85
+ use anyhow::{Context, Result};
86
+
87
+ fn process_config(path: &str) -> Result<Config> {
88
+ let contents = std::fs::read_to_string(path)
89
+ .context("Failed to read config file")?;
90
+ let config: Config = serde_json::from_str(&contents)
91
+ .context("Failed to parse config JSON")?;
92
+ Ok(config)
93
+ }
94
+ ```
95
+
96
+ ## Panic vs Result
97
+
98
+ ```rust
99
+ // Use Result for expected, recoverable errors
100
+ fn parse_input(s: &str) -> Result<i32, ParseIntError> {
101
+ s.parse()
102
+ }
103
+
104
+ // Use panic for programming bugs / invariant violations
105
+ fn get_element(v: &[i32], index: usize) -> i32 {
106
+ // This is a bug if index is out of bounds — crash is correct
107
+ v[index]
108
+ }
109
+
110
+ // Use .expect() with a message for "should never fail" cases
111
+ let config = load_config().expect("Config file must exist at startup");
112
+ ```
@@ -0,0 +1,178 @@
1
+ # TypeScript/JavaScript Error Handling Patterns
2
+
3
+ Language-specific patterns for the `error-handling-patterns` skill. Read `SKILL.md` first for universal methodology.
4
+
5
+ ---
6
+
7
+ ## Custom Error Classes
8
+
9
+ ```typescript
10
+ class ApplicationError extends Error {
11
+ constructor(
12
+ message: string,
13
+ public code: string,
14
+ public statusCode: number = 500,
15
+ public details?: Record<string, any>,
16
+ ) {
17
+ super(message);
18
+ this.name = this.constructor.name;
19
+ Error.captureStackTrace(this, this.constructor);
20
+ }
21
+ }
22
+
23
+ class ValidationError extends ApplicationError {
24
+ constructor(message: string, details?: Record<string, any>) {
25
+ super(message, "VALIDATION_ERROR", 400, details);
26
+ }
27
+ }
28
+
29
+ class NotFoundError extends ApplicationError {
30
+ constructor(resource: string, id: string) {
31
+ super(`${resource} not found`, "NOT_FOUND", 404, { resource, id });
32
+ }
33
+ }
34
+
35
+ // Usage
36
+ function getUser(id: string): User {
37
+ const user = users.find((u) => u.id === id);
38
+ if (!user) {
39
+ throw new NotFoundError("User", id);
40
+ }
41
+ return user;
42
+ }
43
+ ```
44
+
45
+ ## Result Type Pattern
46
+
47
+ ```typescript
48
+ // Result type for explicit error handling
49
+ type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
50
+
51
+ // Helper functions
52
+ function Ok<T>(value: T): Result<T, never> {
53
+ return { ok: true, value };
54
+ }
55
+
56
+ function Err<E>(error: E): Result<never, E> {
57
+ return { ok: false, error };
58
+ }
59
+
60
+ // Usage
61
+ function parseJSON<T>(json: string): Result<T, SyntaxError> {
62
+ try {
63
+ const value = JSON.parse(json) as T;
64
+ return Ok(value);
65
+ } catch (error) {
66
+ return Err(error as SyntaxError);
67
+ }
68
+ }
69
+
70
+ // Consuming Result
71
+ const result = parseJSON<User>(userJson);
72
+ if (result.ok) {
73
+ console.log(result.value.name);
74
+ } else {
75
+ console.error("Parse failed:", result.error.message);
76
+ }
77
+
78
+ // Chaining Results
79
+ function chain<T, U, E>(
80
+ result: Result<T, E>,
81
+ fn: (value: T) => Result<U, E>,
82
+ ): Result<U, E> {
83
+ return result.ok ? fn(result.value) : result;
84
+ }
85
+ ```
86
+
87
+ ## Async Error Handling
88
+
89
+ ```typescript
90
+ // Async/await with proper error handling
91
+ async function fetchUserOrders(userId: string): Promise<Order[]> {
92
+ try {
93
+ const user = await getUser(userId);
94
+ const orders = await getOrders(user.id);
95
+ return orders;
96
+ } catch (error) {
97
+ if (error instanceof NotFoundError) {
98
+ return []; // Return empty array for not found
99
+ }
100
+ if (error instanceof NetworkError) {
101
+ // Retry logic
102
+ return retryFetchOrders(userId);
103
+ }
104
+ // Re-throw unexpected errors
105
+ throw error;
106
+ }
107
+ }
108
+
109
+ // Promise error handling
110
+ function fetchData(url: string): Promise<Data> {
111
+ return fetch(url)
112
+ .then((response) => {
113
+ if (!response.ok) {
114
+ throw new NetworkError(`HTTP ${response.status}`);
115
+ }
116
+ return response.json();
117
+ })
118
+ .catch((error) => {
119
+ console.error("Fetch failed:", error);
120
+ throw error;
121
+ });
122
+ }
123
+ ```
124
+
125
+ ## Error Aggregation
126
+
127
+ ```typescript
128
+ class ErrorCollector {
129
+ private errors: Error[] = [];
130
+
131
+ add(error: Error): void {
132
+ this.errors.push(error);
133
+ }
134
+
135
+ hasErrors(): boolean {
136
+ return this.errors.length > 0;
137
+ }
138
+
139
+ getErrors(): Error[] {
140
+ return [...this.errors];
141
+ }
142
+
143
+ throw(): never {
144
+ if (this.errors.length === 1) {
145
+ throw this.errors[0];
146
+ }
147
+ throw new AggregateError(
148
+ this.errors,
149
+ `${this.errors.length} errors occurred`,
150
+ );
151
+ }
152
+ }
153
+
154
+ // Usage: Validate multiple fields
155
+ function validateUser(data: any): User {
156
+ const errors = new ErrorCollector();
157
+
158
+ if (!data.email) {
159
+ errors.add(new ValidationError("Email is required"));
160
+ } else if (!isValidEmail(data.email)) {
161
+ errors.add(new ValidationError("Email is invalid"));
162
+ }
163
+
164
+ if (!data.name || data.name.length < 2) {
165
+ errors.add(new ValidationError("Name must be at least 2 characters"));
166
+ }
167
+
168
+ if (!data.age || data.age < 18) {
169
+ errors.add(new ValidationError("Age must be 18 or older"));
170
+ }
171
+
172
+ if (errors.hasErrors()) {
173
+ errors.throw();
174
+ }
175
+
176
+ return data as User;
177
+ }
178
+ ```