@aicgen/aicgen 1.0.0-beta.1 → 1.0.0-beta.2

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 (136) hide show
  1. package/.vs/ProjectSettings.json +2 -2
  2. package/.vs/VSWorkspaceState.json +15 -15
  3. package/.vs/aicgen.slnx/v18/DocumentLayout.json +53 -53
  4. package/assets/icon.svg +33 -33
  5. package/bun.lock +0 -43
  6. package/data/architecture/microservices/api-gateway.md +56 -56
  7. package/data/devops/observability.md +73 -73
  8. package/dist/index.js +9299 -9299
  9. package/package.json +2 -2
  10. package/.claude/agents/architecture-reviewer.md +0 -88
  11. package/.claude/agents/guideline-checker.md +0 -73
  12. package/.claude/agents/security-auditor.md +0 -108
  13. package/.claude/guidelines/api-design.md +0 -645
  14. package/.claude/guidelines/architecture.md +0 -2503
  15. package/.claude/guidelines/best-practices.md +0 -618
  16. package/.claude/guidelines/code-style.md +0 -304
  17. package/.claude/guidelines/design-patterns.md +0 -573
  18. package/.claude/guidelines/devops.md +0 -226
  19. package/.claude/guidelines/error-handling.md +0 -413
  20. package/.claude/guidelines/language.md +0 -782
  21. package/.claude/guidelines/performance.md +0 -706
  22. package/.claude/guidelines/security.md +0 -583
  23. package/.claude/guidelines/testing.md +0 -568
  24. package/.claude/settings.json +0 -98
  25. package/.claude/settings.local.json +0 -8
  26. package/.eslintrc.json +0 -28
  27. package/.github/workflows/release.yml +0 -180
  28. package/.github/workflows/test.yml +0 -81
  29. package/CONTRIBUTING.md +0 -821
  30. package/dist/commands/init.d.ts +0 -8
  31. package/dist/commands/init.d.ts.map +0 -1
  32. package/dist/commands/init.js +0 -46
  33. package/dist/commands/init.js.map +0 -1
  34. package/dist/config/profiles.d.ts +0 -4
  35. package/dist/config/profiles.d.ts.map +0 -1
  36. package/dist/config/profiles.js +0 -30
  37. package/dist/config/profiles.js.map +0 -1
  38. package/dist/config/settings.d.ts +0 -7
  39. package/dist/config/settings.d.ts.map +0 -1
  40. package/dist/config/settings.js +0 -7
  41. package/dist/config/settings.js.map +0 -1
  42. package/dist/index.d.ts +0 -3
  43. package/dist/index.d.ts.map +0 -1
  44. package/dist/index.js.map +0 -1
  45. package/dist/models/guideline.d.ts +0 -15
  46. package/dist/models/guideline.d.ts.map +0 -1
  47. package/dist/models/guideline.js +0 -2
  48. package/dist/models/guideline.js.map +0 -1
  49. package/dist/models/preference.d.ts +0 -9
  50. package/dist/models/preference.d.ts.map +0 -1
  51. package/dist/models/preference.js +0 -2
  52. package/dist/models/preference.js.map +0 -1
  53. package/dist/models/profile.d.ts +0 -9
  54. package/dist/models/profile.d.ts.map +0 -1
  55. package/dist/models/profile.js +0 -2
  56. package/dist/models/profile.js.map +0 -1
  57. package/dist/models/project.d.ts +0 -13
  58. package/dist/models/project.d.ts.map +0 -1
  59. package/dist/models/project.js +0 -2
  60. package/dist/models/project.js.map +0 -1
  61. package/dist/services/ai/anthropic.d.ts +0 -7
  62. package/dist/services/ai/anthropic.d.ts.map +0 -1
  63. package/dist/services/ai/anthropic.js +0 -39
  64. package/dist/services/ai/anthropic.js.map +0 -1
  65. package/dist/services/generator.d.ts +0 -2
  66. package/dist/services/generator.d.ts.map +0 -1
  67. package/dist/services/generator.js +0 -4
  68. package/dist/services/generator.js.map +0 -1
  69. package/dist/services/learner.d.ts +0 -2
  70. package/dist/services/learner.d.ts.map +0 -1
  71. package/dist/services/learner.js +0 -4
  72. package/dist/services/learner.js.map +0 -1
  73. package/dist/services/scanner.d.ts +0 -3
  74. package/dist/services/scanner.d.ts.map +0 -1
  75. package/dist/services/scanner.js +0 -54
  76. package/dist/services/scanner.js.map +0 -1
  77. package/dist/utils/errors.d.ts +0 -15
  78. package/dist/utils/errors.d.ts.map +0 -1
  79. package/dist/utils/errors.js +0 -27
  80. package/dist/utils/errors.js.map +0 -1
  81. package/dist/utils/file.d.ts +0 -7
  82. package/dist/utils/file.d.ts.map +0 -1
  83. package/dist/utils/file.js +0 -32
  84. package/dist/utils/file.js.map +0 -1
  85. package/dist/utils/logger.d.ts +0 -6
  86. package/dist/utils/logger.d.ts.map +0 -1
  87. package/dist/utils/logger.js +0 -17
  88. package/dist/utils/logger.js.map +0 -1
  89. package/dist/utils/path.d.ts +0 -6
  90. package/dist/utils/path.d.ts.map +0 -1
  91. package/dist/utils/path.js +0 -14
  92. package/dist/utils/path.js.map +0 -1
  93. package/docs/planning/memory-lane.md +0 -83
  94. package/packaging/linux/aicgen.spec +0 -23
  95. package/packaging/linux/control +0 -9
  96. package/packaging/macos/scripts/postinstall +0 -12
  97. package/packaging/windows/setup.nsi +0 -92
  98. package/scripts/add-categories.ts +0 -87
  99. package/scripts/build-binary.ts +0 -46
  100. package/scripts/embed-data.ts +0 -105
  101. package/scripts/generate-version.ts +0 -150
  102. package/scripts/test-decompress.ts +0 -27
  103. package/scripts/test-extract.ts +0 -31
  104. package/src/__tests__/services/assistant-file-writer.test.ts +0 -400
  105. package/src/__tests__/services/guideline-loader.test.ts +0 -281
  106. package/src/__tests__/services/tarball-extraction.test.ts +0 -125
  107. package/src/commands/add-guideline.ts +0 -296
  108. package/src/commands/clear.ts +0 -61
  109. package/src/commands/guideline-selector.ts +0 -123
  110. package/src/commands/init.ts +0 -645
  111. package/src/commands/quick-add.ts +0 -586
  112. package/src/commands/remove-guideline.ts +0 -152
  113. package/src/commands/stats.ts +0 -49
  114. package/src/commands/update.ts +0 -240
  115. package/src/config.ts +0 -82
  116. package/src/embedded-data.ts +0 -1492
  117. package/src/index.ts +0 -67
  118. package/src/models/profile.ts +0 -24
  119. package/src/models/project.ts +0 -43
  120. package/src/services/assistant-file-writer.ts +0 -612
  121. package/src/services/config-generator.ts +0 -150
  122. package/src/services/config-manager.ts +0 -70
  123. package/src/services/data-source.ts +0 -248
  124. package/src/services/first-run-init.ts +0 -148
  125. package/src/services/guideline-loader.ts +0 -311
  126. package/src/services/hook-generator.ts +0 -178
  127. package/src/services/subagent-generator.ts +0 -310
  128. package/src/utils/banner.ts +0 -66
  129. package/src/utils/errors.ts +0 -27
  130. package/src/utils/file.ts +0 -67
  131. package/src/utils/formatting.ts +0 -172
  132. package/src/utils/logger.ts +0 -89
  133. package/src/utils/path.ts +0 -17
  134. package/src/utils/wizard-state.ts +0 -132
  135. package/tsconfig.json +0 -25
  136. /package/{CLAUDE.md → claude.md} +0 -0
@@ -1,226 +0,0 @@
1
- # DevOps
2
-
3
- # CI/CD Practices
4
-
5
- ## Continuous Integration
6
-
7
- Run on every commit:
8
-
9
- ```yaml
10
- # .github/workflows/ci.yml
11
- name: CI
12
- on: [push, pull_request]
13
-
14
- jobs:
15
- build:
16
- runs-on: ubuntu-latest
17
- steps:
18
- - uses: actions/checkout@v4
19
- - uses: actions/setup-node@v4
20
- with:
21
- node-version: '20'
22
- cache: 'npm'
23
- - run: npm ci
24
- - run: npm run lint
25
- - run: npm run typecheck
26
- - run: npm test
27
- - run: npm run build
28
- ```
29
-
30
- ## Continuous Deployment
31
-
32
- Deploy automatically after CI passes:
33
-
34
- ```yaml
35
- deploy:
36
- needs: build
37
- if: github.ref == 'refs/heads/main'
38
- runs-on: ubuntu-latest
39
- steps:
40
- - uses: actions/checkout@v4
41
- - run: npm ci
42
- - run: npm run build
43
- - run: npm run deploy
44
- env:
45
- DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
46
- ```
47
-
48
- ## Deployment Strategies
49
-
50
- ### Blue-Green Deployment
51
- Run two identical environments, switch traffic instantly.
52
-
53
- ### Canary Releases
54
- Route small percentage of traffic to new version first.
55
-
56
- ### Rolling Updates
57
- Gradually replace instances with new version.
58
-
59
- ## Best Practices
60
-
61
- - Run fast tests first, slow tests later
62
- - Cache dependencies between runs
63
- - Use matrix builds for multiple versions/platforms
64
- - Keep secrets in secure storage
65
- - Automate database migrations
66
- - Include rollback procedures
67
- - Monitor deployments with health checks
68
- - Use feature flags for safer releases
69
-
70
-
71
- ---
72
-
73
- # DevOps Practices
74
-
75
- ## Infrastructure as Code
76
-
77
- ```text
78
- # Define infrastructure as code (e.g., Terraform, Pulumi)
79
-
80
- Resource S3Bucket "app-bucket":
81
- Access: Private
82
- Versioning: Enabled
83
-
84
- Resource LambdaFunction "api":
85
- Runtime: Node.js / Python / Go
86
- Handler: index.handler
87
- Code: ./dist
88
- ```
89
-
90
- ## Containerization
91
-
92
- ```dockerfile
93
- # Build Stage
94
- FROM base-image AS builder
95
- WORKDIR /app
96
- COPY dependency-files ./
97
- RUN install-dependencies
98
- COPY source-code .
99
- RUN build-application
100
-
101
- # Runtime Stage
102
- FROM runtime-image
103
- WORKDIR /app
104
- COPY --from=builder /app/dist ./dist
105
- EXPOSE 8080
106
- CMD ["run", "application"]
107
- ```
108
-
109
- ## Observability
110
-
111
- ### Logging
112
- ```json
113
- {
114
- "level": "info",
115
- "message": "Order created",
116
- "orderId": "ord_123",
117
- "customerId": "cust_456",
118
- "total": 99.99,
119
- "timestamp": "2023-10-27T10:00:00Z"
120
- }
121
- ```
122
-
123
- ### Metrics
124
- ```text
125
- Metrics.Increment("orders.created")
126
- Metrics.Histogram("order.value", total)
127
- Metrics.Timing("order.processing_time", duration)
128
- ```
129
-
130
- ### Health Checks
131
- ```text
132
- GET /health
133
- Response 200 OK:
134
- {
135
- "status": "healthy",
136
- "version": "1.2.3",
137
- "uptime": 3600
138
- }
139
- ```
140
-
141
- ## Best Practices
142
-
143
- - Version control all infrastructure
144
- - Use immutable infrastructure
145
- - Implement proper secret management
146
- - Set up alerting for critical metrics
147
- - Use structured logging (JSON)
148
- - Include correlation IDs for tracing
149
- - Document runbooks for incidents
150
-
151
-
152
- ---
153
-
154
- # Observability
155
-
156
- ## Overview
157
-
158
- Observability is the ability to understand the internal state of a system by examining its outputs. In modern distributed systems, it goes beyond simple monitoring to include logging, metrics, and tracing.
159
-
160
- ## Three Pillars
161
-
162
- ### 1. Structured Logging
163
-
164
- Logs should be machine-readable (JSON) and contain context.
165
-
166
- ```json
167
- // ✅ Good: Structured JSON logging
168
- {
169
- "level": "info",
170
- "message": "Order processed",
171
- "orderId": "ord_123",
172
- "userId": "user_456",
173
- "amount": 99.99,
174
- "durationMs": 145,
175
- "status": "success"
176
- }
177
- ```
178
- ```text
179
- // ❌ Bad: Unstructured text
180
- "Order processed: ord_123 for user_456"
181
- ```
182
-
183
- ### 2. Metrics
184
-
185
- Aggregatable data points for identifying trends and health.
186
-
187
- - **Counters**: Total requests, error counts (`http_requests_total`)
188
- - **Gauges**: Queue depth, memory usage (`memory_usage_bytes`)
189
- - **Histograms**: Request latency distribution (`http_request_duration_seconds`)
190
-
191
- ### 3. Distributed Tracing
192
-
193
- Tracking requests as they propagate through services.
194
-
195
- - **Trace ID**: Unique ID for the entire request chain
196
- - **Span ID**: Unique ID for a specific operation
197
- - **Context Propagation**: Passing IDs between services (e.g., W3C Trace Context)
198
-
199
- ## Implementation Strategy
200
-
201
- ### OpenTelemetry (OTel)
202
-
203
- Use OpenTelemetry as the vendor-neutral standard for collecting telemetry data.
204
-
205
- ```text
206
- # Initialize OpenTelemetry SDK
207
- SDK.Configure({
208
- TraceExporter: Console/OTLP,
209
- Instrumentations: [Http, Database, Grpc]
210
- })
211
- SDK.Start()
212
- ```
213
-
214
- ### Health Checks
215
-
216
- Expose standard health endpoints:
217
-
218
- - `/health/live`: Is the process running? (Liveness)
219
- - `/health/ready`: Can it accept traffic? (Readiness)
220
- - `/health/startup`: Has it finished initializing? (Startup)
221
-
222
- ## Alerting Best Practices
223
-
224
- - **Alert on Symptoms, not Causes**: "High Error Rate" (Symptom) vs "CPU High" (Cause).
225
- - **Golden Signals**: Latency, Traffic, Errors, Saturation.
226
- - **Actionable**: Every alert should require a specific human action.
@@ -1,413 +0,0 @@
1
- # Error Handling
2
-
3
- # Error Handling Strategy
4
-
5
- ## Custom Error Classes
6
-
7
- ```typescript
8
- class AppError extends Error {
9
- constructor(
10
- message: string,
11
- public statusCode: number = 500,
12
- public code: string = 'INTERNAL_ERROR',
13
- public details?: unknown
14
- ) {
15
- super(message);
16
- this.name = this.constructor.name;
17
- Error.captureStackTrace(this, this.constructor);
18
- }
19
- }
20
-
21
- class NotFoundError extends AppError {
22
- constructor(resource: string, id: string) {
23
- super(`${resource} with id ${id} not found`, 404, 'NOT_FOUND', { resource, id });
24
- }
25
- }
26
-
27
- class ValidationError extends AppError {
28
- constructor(message: string, details: unknown) {
29
- super(message, 400, 'VALIDATION_ERROR', details);
30
- }
31
- }
32
-
33
- // Usage
34
- if (!user) {
35
- throw new NotFoundError('User', userId);
36
- }
37
- ```
38
-
39
- ## Never Swallow Errors
40
-
41
- ```typescript
42
- // ❌ Silent failure - dangerous!
43
- try {
44
- await criticalOperation();
45
- } catch (error) {
46
- // Error ignored
47
- }
48
-
49
- // ✅ Log and handle appropriately
50
- try {
51
- await criticalOperation();
52
- } catch (error) {
53
- logger.error('Critical operation failed', { error });
54
- throw error; // Or handle gracefully
55
- }
56
- ```
57
-
58
- ## Specific Error Messages
59
-
60
- ```typescript
61
- // ❌ Not actionable
62
- throw new Error('Something went wrong');
63
-
64
- // ✅ Specific and actionable
65
- throw new ValidationError('Email must be a valid email address', {
66
- field: 'email',
67
- value: userInput.email
68
- });
69
- ```
70
-
71
- ## Centralized Error Handler
72
-
73
- ```typescript
74
- // Express error middleware
75
- app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
76
- if (err instanceof AppError) {
77
- return res.status(err.statusCode).json({
78
- error: {
79
- message: err.message,
80
- code: err.code,
81
- details: err.details
82
- }
83
- });
84
- }
85
-
86
- // Log unexpected errors
87
- console.error('Unexpected error:', err);
88
-
89
- // Don't expose internal details
90
- res.status(500).json({
91
- error: {
92
- message: 'Internal server error',
93
- code: 'INTERNAL_ERROR'
94
- }
95
- });
96
- });
97
- ```
98
-
99
- ## Async Error Wrapper
100
-
101
- ```typescript
102
- // Wrap async handlers to catch errors automatically
103
- const asyncHandler = (fn: RequestHandler) => {
104
- return (req: Request, res: Response, next: NextFunction) => {
105
- Promise.resolve(fn(req, res, next)).catch(next);
106
- };
107
- };
108
-
109
- // Usage
110
- app.get('/users/:id', asyncHandler(async (req, res) => {
111
- const user = await getUser(req.params.id);
112
- res.json(user);
113
- }));
114
- ```
115
-
116
- ## Result Type Pattern
117
-
118
- ```typescript
119
- type Result<T, E = Error> =
120
- | { success: true; value: T }
121
- | { success: false; error: E };
122
-
123
- function parseJSON<T>(json: string): Result<T, string> {
124
- try {
125
- return { success: true, value: JSON.parse(json) };
126
- } catch {
127
- return { success: false, error: 'Invalid JSON' };
128
- }
129
- }
130
-
131
- // Usage - forces explicit error handling
132
- const result = parseJSON<User>(data);
133
- if (result.success) {
134
- console.log(result.value.name);
135
- } else {
136
- console.error(result.error);
137
- }
138
- ```
139
-
140
- ## Error Boundaries (React)
141
-
142
- ```typescript
143
- class ErrorBoundary extends React.Component {
144
- state = { hasError: false };
145
-
146
- static getDerivedStateFromError(error: Error) {
147
- return { hasError: true };
148
- }
149
-
150
- componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
151
- logger.error('UI Error', { error, errorInfo });
152
- }
153
-
154
- render() {
155
- if (this.state.hasError) {
156
- return <FallbackUI />;
157
- }
158
- return this.props.children;
159
- }
160
- }
161
- ```
162
-
163
- ## Retry with Limits
164
-
165
- ```typescript
166
- // ❌ Infinite retries
167
- while (true) {
168
- try {
169
- await operation();
170
- break;
171
- } catch (error) {
172
- // Retry forever - exhausts resources
173
- }
174
- }
175
-
176
- // ✅ Limited retries with backoff
177
- const maxRetries = 3;
178
- for (let i = 0; i < maxRetries; i++) {
179
- try {
180
- await operation();
181
- break;
182
- } catch (error) {
183
- if (i === maxRetries - 1) throw error;
184
- await sleep(Math.pow(2, i) * 1000); // Exponential backoff
185
- }
186
- }
187
- ```
188
-
189
-
190
- ---
191
-
192
- # Error Handling Basics
193
-
194
- ## Throwing Errors
195
-
196
- Use `throw` to signal when something goes wrong.
197
-
198
- ```pseudocode
199
- function divide(a, b):
200
- if b == 0:
201
- throw Error("Cannot divide by zero")
202
- return a / b
203
- ```
204
-
205
- ## Try-Catch
206
-
207
- Use `try-catch` to handle errors gracefully.
208
-
209
- ```pseudocode
210
- try:
211
- result = divide(10, 0)
212
- print(result)
213
- catch error:
214
- print("Error:", error.message)
215
- // Continue with fallback behavior
216
- ```
217
-
218
- ## Always Provide Error Messages
219
-
220
- Make error messages clear and actionable.
221
-
222
- ```pseudocode
223
- // ❌ Bad: Vague error
224
- throw Error("Invalid")
225
-
226
- // ✅ Good: Specific error
227
- throw Error("Email must be a valid email address")
228
-
229
- // ✅ Good: Include context
230
- throw Error("User with ID " + userId + " not found")
231
- ```
232
-
233
- ## Async Error Handling
234
-
235
- Always use try-catch with async operations.
236
-
237
- ```pseudocode
238
- async function loadUser(id):
239
- try:
240
- user = await fetchUser(id)
241
- return user
242
- catch error:
243
- log("Failed to load user:", error)
244
- throw error // Re-throw if caller should know
245
- ```
246
-
247
- ## When to Catch Errors
248
-
249
- ### Catch When You Can Handle It
250
-
251
- ```pseudocode
252
- // ✅ Good: Can provide fallback
253
- async function getUserName(id):
254
- try:
255
- user = await fetchUser(id)
256
- return user.name
257
- catch error:
258
- return "Unknown User" // Fallback value
259
- ```
260
-
261
- ### Don't Catch If You Can't Handle
262
-
263
- ```pseudocode
264
- // ❌ Bad: Catching but doing nothing
265
- try:
266
- await criticalOperation()
267
- catch error:
268
- // Empty catch - error lost!
269
-
270
- // ✅ Good: Let it propagate
271
- await criticalOperation() // Caller will handle
272
- ```
273
-
274
- ## Validate Input Early
275
-
276
- Check for problems before they cause errors.
277
-
278
- ```pseudocode
279
- function createUser(email, age):
280
- // Validate inputs first
281
- if email is empty:
282
- throw Error("Email is required")
283
-
284
- if not email.contains("@"):
285
- throw Error("Email must be valid")
286
-
287
- if age < 0:
288
- throw Error("Age cannot be negative")
289
-
290
- // Now proceed with creation
291
- return { email: email, age: age }
292
- ```
293
-
294
- ## Logging Errors
295
-
296
- Always log errors for debugging.
297
-
298
- ```pseudocode
299
- try:
300
- await processPayment(orderId)
301
- catch error:
302
- // Log with context
303
- log("Payment processing failed:", {
304
- orderId: orderId,
305
- error: error.message,
306
- timestamp: currentTime()
307
- })
308
- throw error
309
- ```
310
-
311
- ## Error Handling Patterns
312
-
313
- ### Return Error Status
314
-
315
- ```pseudocode
316
- function parseNumber(input):
317
- num = parseInt(input)
318
- if isNaN(num):
319
- return null // Indicate failure without throwing
320
- return num
321
-
322
- // Usage
323
- result = parseNumber(userInput)
324
- if result is null:
325
- print("Invalid number")
326
- else:
327
- print("Number:", result)
328
- ```
329
-
330
- ### Return Success/Error Object
331
-
332
- ```pseudocode
333
- function safeDivide(a, b):
334
- if b == 0:
335
- return { success: false, error: "Cannot divide by zero" }
336
- return { success: true, data: a / b }
337
-
338
- // Usage
339
- result = safeDivide(10, 2)
340
- if result.success:
341
- print("Result:", result.data)
342
- else:
343
- print("Error:", result.error)
344
- ```
345
-
346
- ## Common Mistakes
347
-
348
- ### Don't Swallow Errors
349
-
350
- ```pseudocode
351
- // ❌ Bad: Error disappears
352
- try:
353
- await importantOperation()
354
- catch error:
355
- // Nothing here - error lost!
356
-
357
- // ✅ Good: Log at minimum
358
- try:
359
- await importantOperation()
360
- catch error:
361
- log("Operation failed:", error)
362
- throw error // Or handle appropriately
363
- ```
364
-
365
- ### Don't Use Errors for Flow Control
366
-
367
- ```pseudocode
368
- // ❌ Bad: Using errors for normal logic
369
- try:
370
- user = findUser(id)
371
- // ...
372
- catch error:
373
- // User not found - this is expected, not an error!
374
-
375
- // ✅ Good: Return null for expected cases
376
- user = findUser(id)
377
- if user is null:
378
- print("User not found")
379
- return
380
- ```
381
-
382
- ### Don't Throw Non-Error Objects
383
-
384
- ```pseudocode
385
- // ❌ Bad
386
- throw "Something went wrong" // String
387
- throw { code: 500 } // Plain object
388
-
389
- // ✅ Good
390
- throw Error("Something went wrong")
391
- ```
392
-
393
- ## Best Practices
394
-
395
- 1. **Fail fast** - Validate input early and throw immediately
396
- 2. **Be specific** - Provide detailed, actionable error messages
397
- 3. **Log errors** - Always log for debugging
398
- 4. **Don't hide errors** - Let them propagate if you can't handle them
399
- 5. **Clean up resources** - Close connections, files in finally blocks
400
-
401
- ```pseudocode
402
- file = null
403
- try:
404
- file = await openFile("data.txt")
405
- await processFile(file)
406
- catch error:
407
- log("File processing failed:", error)
408
- throw error
409
- finally:
410
- // Always runs, even if error thrown
411
- if file is not null:
412
- await file.close()
413
- ```