@yuaone/core 0.8.4 → 0.9.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 (95) hide show
  1. package/README.md +73 -2
  2. package/dist/agent-loop.d.ts +8 -0
  3. package/dist/agent-loop.d.ts.map +1 -1
  4. package/dist/agent-loop.js +34 -0
  5. package/dist/agent-loop.js.map +1 -1
  6. package/dist/dag-orchestrator.d.ts +3 -0
  7. package/dist/dag-orchestrator.d.ts.map +1 -1
  8. package/dist/dag-orchestrator.js +1 -0
  9. package/dist/dag-orchestrator.js.map +1 -1
  10. package/dist/execution-engine.d.ts.map +1 -1
  11. package/dist/execution-engine.js +1 -0
  12. package/dist/execution-engine.js.map +1 -1
  13. package/dist/index.d.ts +5 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +7 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/language-detector.d.ts.map +1 -1
  18. package/dist/language-detector.js +43 -122
  19. package/dist/language-detector.js.map +1 -1
  20. package/dist/language-registry.d.ts +45 -0
  21. package/dist/language-registry.d.ts.map +1 -0
  22. package/dist/language-registry.js +893 -0
  23. package/dist/language-registry.js.map +1 -0
  24. package/dist/llm-client.d.ts +7 -0
  25. package/dist/llm-client.d.ts.map +1 -1
  26. package/dist/llm-client.js +58 -8
  27. package/dist/llm-client.js.map +1 -1
  28. package/dist/skill-loader.d.ts +9 -16
  29. package/dist/skill-loader.d.ts.map +1 -1
  30. package/dist/skill-loader.js +116 -52
  31. package/dist/skill-loader.js.map +1 -1
  32. package/dist/skill-mode-bridge.d.ts +17 -0
  33. package/dist/skill-mode-bridge.d.ts.map +1 -0
  34. package/dist/skill-mode-bridge.js +27 -0
  35. package/dist/skill-mode-bridge.js.map +1 -0
  36. package/dist/skills/code-review.md +58 -0
  37. package/dist/skills/debug.md +45 -0
  38. package/dist/skills/languages/python.md +89 -0
  39. package/dist/skills/languages/react.md +86 -0
  40. package/dist/skills/languages/typescript.md +110 -0
  41. package/dist/skills/plan.md +49 -0
  42. package/dist/skills/refactor.md +46 -0
  43. package/dist/skills/security-scan.md +59 -0
  44. package/dist/skills/skills/code-review.md +58 -0
  45. package/dist/skills/skills/debug.md +45 -0
  46. package/dist/skills/skills/languages/bash.md +74 -0
  47. package/dist/skills/skills/languages/c.md +76 -0
  48. package/dist/skills/skills/languages/cpp.md +75 -0
  49. package/dist/skills/skills/languages/csharp.md +77 -0
  50. package/dist/skills/skills/languages/cuda.md +80 -0
  51. package/dist/skills/skills/languages/dart.md +75 -0
  52. package/dist/skills/skills/languages/docker.md +80 -0
  53. package/dist/skills/skills/languages/elixir.md +80 -0
  54. package/dist/skills/skills/languages/gdscript.md +80 -0
  55. package/dist/skills/skills/languages/go.md +77 -0
  56. package/dist/skills/skills/languages/haskell.md +80 -0
  57. package/dist/skills/skills/languages/java.md +77 -0
  58. package/dist/skills/skills/languages/javascript.md +73 -0
  59. package/dist/skills/skills/languages/kotlin.md +75 -0
  60. package/dist/skills/skills/languages/lua.md +79 -0
  61. package/dist/skills/skills/languages/php.md +73 -0
  62. package/dist/skills/skills/languages/python.md +89 -0
  63. package/dist/skills/skills/languages/r.md +80 -0
  64. package/dist/skills/skills/languages/react.md +86 -0
  65. package/dist/skills/skills/languages/ruby.md +78 -0
  66. package/dist/skills/skills/languages/rust.md +77 -0
  67. package/dist/skills/skills/languages/solidity.md +81 -0
  68. package/dist/skills/skills/languages/sql.md +74 -0
  69. package/dist/skills/skills/languages/svelte.md +74 -0
  70. package/dist/skills/skills/languages/swift.md +74 -0
  71. package/dist/skills/skills/languages/terraform.md +80 -0
  72. package/dist/skills/skills/languages/typescript.md +110 -0
  73. package/dist/skills/skills/languages/verilog.md +80 -0
  74. package/dist/skills/skills/languages/vue.md +73 -0
  75. package/dist/skills/skills/plan.md +49 -0
  76. package/dist/skills/skills/refactor.md +46 -0
  77. package/dist/skills/skills/security-scan.md +59 -0
  78. package/dist/skills/skills/test-driven.md +51 -0
  79. package/dist/skills/test-driven.md +51 -0
  80. package/dist/strategy-selector.d.ts +11 -0
  81. package/dist/strategy-selector.d.ts.map +1 -0
  82. package/dist/strategy-selector.js +85 -0
  83. package/dist/strategy-selector.js.map +1 -0
  84. package/dist/sub-agent.d.ts +3 -0
  85. package/dist/sub-agent.d.ts.map +1 -1
  86. package/dist/sub-agent.js +10 -0
  87. package/dist/sub-agent.js.map +1 -1
  88. package/dist/system-prompt.d.ts +2 -0
  89. package/dist/system-prompt.d.ts.map +1 -1
  90. package/dist/system-prompt.js +469 -94
  91. package/dist/system-prompt.js.map +1 -1
  92. package/dist/types.d.ts +3 -0
  93. package/dist/types.d.ts.map +1 -1
  94. package/dist/types.js.map +1 -1
  95. package/package.json +2 -2
@@ -0,0 +1,77 @@
1
+ ## Identity
2
+ - domain: csharp
3
+ - type: language
4
+ - confidence: 0.95
5
+
6
+ # C# — Error Pattern Reference
7
+
8
+ Read the full compiler error including the CS error code and the stack trace. C#'s compiler messages are precise and the `CS` error code narrows the problem category immediately.
9
+
10
+ ## Error Code Quick Reference
11
+ - **CS0103** — The name 'x' does not exist in the current context.
12
+ - **CS0019** — Operator cannot be applied to operands of type.
13
+ - **CS1998** — Async method lacks 'await' operators (sync disguised as async).
14
+ - **CS4014** — Call not awaited — fire and forget.
15
+ - **CS0246** — Type or namespace not found (missing using directive or assembly).
16
+ - **CS0266** — Cannot implicitly convert — explicit cast required.
17
+ - **CS8600** — Converting null literal or possible null value to non-nullable type.
18
+ - **CS8602** — Dereference of a possibly null reference.
19
+ - **CS8618** — Non-nullable field must contain a non-null value when exiting constructor.
20
+ - **NullReferenceException** — Runtime null dereference.
21
+
22
+ ## Known Error Patterns
23
+
24
+ ### Pattern: NullReferenceException
25
+
26
+ - **symptom**: `System.NullReferenceException: Object reference not set to an instance of an object` at a specific stack frame
27
+ - **cause**: A reference-type variable is `null` when a member access (method, property, indexer) is attempted. Common sources: uninitialized properties, LINQ `FirstOrDefault()` returning null, missing dependency injection registration, uninitialized optional fields.
28
+ - **strategy**: 1. Read the stack trace line. 2. Identify which object is null — use the NullReferenceException helper in .NET 6+ which names the null variable. 3. Trace backwards to where the variable was assigned. 4. Add a null check using the null-conditional operator `x?.Method()` or null coalescing `x ?? defaultValue`. 5. For method parameters, use `ArgumentNullException.ThrowIfNull(param)` at method entry. 6. Enable nullable reference types (`<Nullable>enable</Nullable>`) in the project to get CS8602 compile-time warnings.
29
+ - **toolSequence**: file_read (stack trace line) → grep (variable assignment) → file_edit (add null check or enable nullable)
30
+ - **pitfall**: Do NOT add `!` (null-forgiving operator) to suppress CS8602 warnings without proof — it silences the warning but keeps the runtime crash.
31
+
32
+ ### Pattern: async void (fire-and-forget)
33
+
34
+ - **symptom**: Exceptions thrown inside `async void` methods silently crash the application or are swallowed. `CS1998` warning on async methods without await. Errors not catchable at the call site.
35
+ - **cause**: `async void` methods cannot be awaited, so exceptions propagate to the synchronization context and crash the app (in most contexts) or are silently lost. They are intended only for event handlers.
36
+ - **strategy**: 1. Grep for `async void` in the codebase. 2. For all non-event-handler `async void` methods, change the return type to `async Task`. 3. Update call sites to `await` the returned `Task`. 4. For event handlers that must be `async void`, wrap the body in try-catch: `try { await DoWorkAsync(); } catch (Exception ex) { _logger.LogError(ex, ...); }`. 5. Use `Task.Run` for fire-and-forget scenarios and log exceptions: `_ = Task.Run(async () => { try { await work(); } catch (ex) { log(ex); } });`.
37
+ - **toolSequence**: grep (`async void`) → file_read (each occurrence) → file_edit (change to `async Task` or add try-catch wrapper)
38
+ - **pitfall**: Do NOT change event handlers (`Button_Click`, `OnReceived`) from `async void` to `async Task` — the event system requires `void` return. Wrap the body instead.
39
+
40
+ ### Pattern: LINQ deferred execution surprise
41
+
42
+ - **symptom**: A LINQ query appears to produce different results on multiple enumerations, or is re-executed (including side effects) every time it is iterated. Database queries run more times than expected.
43
+ - **cause**: LINQ queries (`Where`, `Select`, `OrderBy`, etc.) return `IEnumerable<T>` which is evaluated lazily — the query runs again each time the sequence is enumerated. Storing an `IQueryable` or `IEnumerable` and iterating it multiple times re-executes the underlying operation.
44
+ - **strategy**: 1. Find LINQ queries that are iterated more than once (look for multiple `foreach`, `Count()`, `ToList()` calls on the same variable). 2. Materialize the query exactly once with `.ToList()` or `.ToArray()` when the results will be used multiple times. 3. For EF Core queries, always call `.ToList()` or `.ToListAsync()` before the DbContext scope ends. 4. Be explicit: if single enumeration is intentional, document it; if multiple, materialize.
45
+ - **toolSequence**: grep (variable name used in multiple enumerations) → file_read → file_edit (add `.ToList()` after first enumeration)
46
+ - **pitfall**: Do NOT call `.ToList()` on every LINQ query blindly — for large datasets piped into further LINQ operators, deferred execution is more memory-efficient. Materialize only when the result is reused.
47
+
48
+ ### Pattern: IDisposable not disposed (missing using statement)
49
+
50
+ - **symptom**: Memory/handle leak; `ObjectDisposedException` thrown after the object is used later; resource exhaustion (too many open file handles, database connections).
51
+ - **cause**: Objects implementing `IDisposable` (StreamReader, HttpClient, DbContext, SqlConnection, etc.) are not disposed when done. Their resources (file handles, network sockets, unmanaged memory) are not freed until the finalizer runs — which may be never or much later.
52
+ - **strategy**: 1. Grep for `new StreamReader`, `new SqlConnection`, `new HttpClient`, etc. — anything implementing `IDisposable`. 2. Wrap each in a `using` statement: `using var reader = new StreamReader(path);` (C# 8+) or `using (var reader = new StreamReader(path)) { ... }`. 3. For class-level `IDisposable` fields, implement `IDisposable` on the containing class and dispose fields in `Dispose()`. 4. For `HttpClient`, do NOT create one per request — use a singleton or `IHttpClientFactory` to avoid socket exhaustion.
53
+ - **toolSequence**: grep (`new .*Disposable\|new Stream\|new SqlConnection\|new DbContext`) → file_read → file_edit (wrap in `using` statement)
54
+ - **pitfall**: Do NOT create a new `HttpClient` inside a `using` block per request — `HttpClient` is designed to be reused; disposing it per request causes socket exhaustion.
55
+
56
+ ### Pattern: ambiguous method overload
57
+
58
+ - **symptom**: `CS0121: The call is ambiguous between the following methods or properties: 'Foo(int)' and 'Foo(long)'`
59
+ - **cause**: Two or more overloads are equally applicable for the given arguments. Common causes: numeric literal promotion (int can match both int and long), implicit conversions, optional parameters making two overloads identical in call site.
60
+ - **strategy**: 1. Read the two (or more) ambiguous overloads listed in the error. 2. Make the call explicit by casting the argument to the desired type: `Foo((int)value)` or `Foo((long)value)`. 3. If you own the overloaded methods and the ambiguity is a design problem, rename or consolidate the overloads. 4. For extension method ambiguity, use a static method call syntax to specify the type explicitly: `Extensions.Foo(obj, arg)`.
61
+ - **toolSequence**: file_read (error line) → grep (overload definitions) → file_edit (add explicit cast at call site)
62
+ - **pitfall**: Do NOT remove one of the overloads without checking all call sites — removing an overload may break other callers that relied on it.
63
+
64
+ ## Verification
65
+ Run: `dotnet build` or `msbuild /p:Configuration=Debug`
66
+ - Exit 0 = no compile errors.
67
+ - For tests: `dotnet test`
68
+ - For nullable analysis: ensure `<Nullable>enable</Nullable>` in .csproj
69
+
70
+ ## Validation Checklist
71
+ - [ ] `dotnet build` exits 0 with no errors
72
+ - [ ] No `async void` except event handlers (all others return `Task`)
73
+ - [ ] All `IDisposable` objects wrapped in `using` statements
74
+ - [ ] LINQ queries materialized with `.ToList()` when iterated multiple times
75
+ - [ ] Nullable reference types enabled; no `!` null-forgiving without proof
76
+ - [ ] Method overload ambiguities resolved with explicit casts
77
+ - [ ] `HttpClient` reused via DI / `IHttpClientFactory`, not created per request
@@ -0,0 +1,80 @@
1
+ ## Identity
2
+ - domain: cuda
3
+ - type: language
4
+ - confidence: 0.90
5
+
6
+ # CUDA — Error Pattern Reference
7
+
8
+ Read the exact CUDA error code and the line from `cudaGetLastError()` or the assertion. CUDA errors are asynchronous — the error may surface on a different CUDA call than the one that caused it.
9
+
10
+ ## Error Code Quick Reference
11
+ - **cudaErrorIllegalAddress (700)** — Out-of-bounds memory access inside a kernel.
12
+ - **cudaErrorLaunchFailure (4)** — Kernel launch configuration invalid or device exception.
13
+ - **cudaErrorInvalidValue (1)** — Null pointer or invalid argument passed to CUDA API.
14
+ - **cudaErrorMemoryAllocation (2)** — cudaMalloc failed; GPU out of memory.
15
+ - **cudaErrorNoKernelImageForDevice (209)** — Kernel compiled for different GPU architecture.
16
+ - **cudaErrorSynchronizationError** — cudaDeviceSynchronize() found a pending kernel error.
17
+ - **cudaErrorInvalidDeviceFunction** — Kernel function pointer is invalid or not compiled for device.
18
+ - **CUDA_ERROR_NOT_INITIALIZED** — cuInit() not called before cu* API calls (Driver API).
19
+
20
+ ## Known Error Patterns
21
+
22
+ ### CUDA_ERROR_ILLEGAL_ADDRESS — Out-of-Bounds Memory Access
23
+ - **Symptom**: `cudaErrorIllegalAddress` on `cudaDeviceSynchronize()` or `cudaMemcpy`; Nsight Compute shows "Memory access fault". The error appears after the actual faulty kernel launch.
24
+ - **Cause**: A thread accesses device memory outside allocated bounds. Common causes: wrong index calculation (`blockIdx.x * blockDim.x + threadIdx.x` exceeds array size), pointer arithmetic error, or accessing freed device memory.
25
+ - **Strategy**: 1. Add bounds checks inside the kernel: `if (idx >= N) return;` at the kernel entry. 2. Use CUDA Compute Sanitizer: `compute-sanitizer --tool memcheck ./my_program` — it pinpoints the exact line and thread. 3. Verify index calculation: `size_t idx = blockIdx.x * blockDim.x + threadIdx.x;` — ensure total threads >= N but kernel guards against idx >= N. 4. Check that `cudaMalloc` allocated sufficient bytes: `N * sizeof(float)` not just `N`. 5. After launch, always call `cudaDeviceSynchronize()` and check its return value during debugging.
26
+ - **Tool sequence**: file_read (kernel code) → file_edit (add bounds check `if (idx >= N) return`) → shell_exec (`compute-sanitizer ./program`)
27
+ - **Pitfall**: Do NOT disable bounds checking in production without proving the launch configuration always generates valid indices — off-by-one in grid size causes silent data corruption.
28
+
29
+ ### Race Condition — Missing __syncthreads()
30
+ - **Symptom**: Non-deterministic results; kernel produces correct output on small inputs but fails on large ones; different runs of the same program give different answers.
31
+ - **Cause**: Threads in the same block share shared memory but execute independently. Without `__syncthreads()`, some threads may read shared memory values written by other threads that have not completed their write yet.
32
+ - **Strategy**: 1. Identify every pattern where threads write to shared memory and other threads subsequently read from it. 2. Place `__syncthreads()` between the write phase and the read phase. 3. Ensure `__syncthreads()` is called by ALL threads in the block — placing it inside a conditional (`if (threadIdx.x < N) __syncthreads()`) causes a deadlock if some threads skip it. 4. For reduction operations, use warp-level primitives (`__shfl_down_sync`) for the last 32 threads instead of `__syncthreads()`.
33
+ - **Tool sequence**: grep (`__shared__`) → file_read (kernel) → file_edit (add __syncthreads() between write and read phases)
34
+ - **Pitfall**: Do NOT put `__syncthreads()` inside a branch that only some threads take — all threads in the block must reach the barrier or the program deadlocks.
35
+
36
+ ### GPU Memory Leak — cudaMalloc Not Freed
37
+ - **Symptom**: GPU memory usage grows with each iteration; eventually `cudaMalloc` returns `cudaErrorMemoryAllocation`; `nvidia-smi` shows GPU memory at 100%.
38
+ - **Cause**: Device memory allocated with `cudaMalloc` is not freed with `cudaFree` when no longer needed. Unlike CPU memory, CUDA does not have automatic garbage collection — every `cudaMalloc` needs a matching `cudaFree`.
39
+ - **Strategy**: 1. Grep all `cudaMalloc` calls and verify each has a corresponding `cudaFree` in all exit paths (including error paths). 2. Use RAII wrappers: Thrust `thrust::device_vector` auto-frees on destruction, or write a simple CUDA RAII class. 3. Use Compute Sanitizer memcheck: `compute-sanitizer --leak-check full ./program` to detect unreleased memory. 4. In error handling, ensure `cudaFree` is called before returning even on error paths.
40
+ - **Tool sequence**: grep (`cudaMalloc`) → file_read → file_edit (add cudaFree in all exit paths or convert to RAII wrapper)
41
+ - **Pitfall**: Do NOT call `cudaFree(nullptr)` expecting it to be a no-op in all contexts — while CUDA spec says it is safe, some older driver versions behave differently. Explicitly track which pointers need freeing.
42
+
43
+ ### Kernel Launch Failure — Block/Grid Size Mismatch
44
+ - **Symptom**: `cudaErrorLaunchFailure` or `cudaErrorInvalidValue` immediately after kernel invocation; sometimes silent failure with zero output.
45
+ - **Cause**: Invalid launch configuration: `blockDim.x` exceeds device maximum (usually 1024), `gridDim.x` exceeds `INT_MAX` for 1D grids, total registers per block exceeded, or shared memory requested exceeds device limit (typically 48KB or 96KB).
46
+ - **Strategy**: 1. Query device limits: `cudaDeviceGetAttribute(&maxThreadsPerBlock, cudaDevAttrMaxThreadsPerBlock, device)`. 2. Print the launch configuration before the `<<<>>>` call to verify dimensions. 3. For large N, calculate grid: `int gridSize = (N + blockSize - 1) / blockSize;` where `blockSize <= 1024`. 4. Check shared memory: `size_t sharedMem = blockSize * sizeof(float); if (sharedMem > 49152) { /* reduce blockSize */ }`. 5. Use `cudaOccupancyMaxPotentialBlockSize()` to auto-tune block size for maximum occupancy.
47
+ - **Tool sequence**: file_read (kernel launch) → file_edit (add device property query + bounds check on blockSize/gridSize)
48
+ - **Pitfall**: Do NOT hardcode `blockSize = 1024` — older or embedded GPU devices may have lower limits. Always query and validate against device properties.
49
+
50
+ ### Device/Host Memory Confusion — Dereferencing Device Pointer on CPU
51
+ - **Symptom**: Segfault or access violation in CPU code; `cudaMemcpy` direction is wrong; kernel receives a host pointer and crashes with illegal address.
52
+ - **Cause**: Device pointers (from `cudaMalloc`) cannot be dereferenced on the host. Host pointers (from `malloc` or stack) cannot be passed directly to kernels as array pointers. Passing a host pointer where a device pointer is expected causes `CUDA_ERROR_ILLEGAL_ADDRESS`.
53
+ - **Strategy**: 1. Use a clear naming convention: `d_` prefix for device pointers (`d_input`, `d_output`), `h_` prefix for host pointers. 2. Before any kernel call, verify all array arguments are device pointers obtained from `cudaMalloc`. 3. For data transfer: host→device is `cudaMemcpy(d_ptr, h_ptr, size, cudaMemcpyHostToDevice)`; device→host is the reverse. 4. Use Unified Memory (`cudaMallocManaged`) during debugging to eliminate explicit transfers and isolate logic errors.
54
+ - **Tool sequence**: grep (`cudaMalloc`, `cudaMemcpy`) → file_read → file_edit (add d_/h_ naming convention + verify memcpy directions)
55
+ - **Pitfall**: Do NOT use `cudaMallocManaged` in performance-critical production code — unified memory adds overhead from page migration. Use it only for prototyping or debugging.
56
+
57
+ ### Missing Error Check — Silent CUDA Failure
58
+ - **Symptom**: Program runs without crashing but produces incorrect results; errors go undetected because CUDA API calls are not checked.
59
+ - **Cause**: CUDA API functions return `cudaError_t` — if not checked, errors are silently ignored. Kernel launches return void — errors only surface on the next synchronization point.
60
+ - **Strategy**: 1. Wrap all CUDA calls with a macro: `#define CUDA_CHECK(call) { cudaError_t err = (call); if (err != cudaSuccess) { fprintf(stderr, "CUDA error %s at %s:%d\n", cudaGetErrorString(err), __FILE__, __LINE__); exit(1); } }`. 2. After every kernel launch, add `CUDA_CHECK(cudaGetLastError()); CUDA_CHECK(cudaDeviceSynchronize());` during development. 3. Remove synchronize calls in production (they serialize execution) but keep `cudaGetLastError()` checks.
61
+ - **Tool sequence**: grep (`cudaMalloc`, `cudaMemcpy`, kernel launches) → file_edit (wrap all calls with CUDA_CHECK macro)
62
+ - **Pitfall**: Do NOT only check `cudaDeviceSynchronize()` at the end of a large function — by then, you have lost information about which specific operation failed.
63
+
64
+ ## Verification
65
+ Run: `compute-sanitizer --tool memcheck ./your_program`
66
+ - No memory errors, no out-of-bounds accesses = clean run.
67
+ - Profile with Nsight Systems: `nsys profile ./your_program` — check for unintended synchronizations and memory transfer bottlenecks.
68
+ - `nvidia-smi` should show GPU memory returning to baseline after program exit.
69
+
70
+ ## Validation Checklist
71
+ - [ ] All kernels have bounds check: `if (idx >= N) return;`
72
+ - [ ] `__syncthreads()` placed between shared memory writes and reads
73
+ - [ ] `__syncthreads()` never inside a conditional branch
74
+ - [ ] Every `cudaMalloc` has a corresponding `cudaFree` in all code paths
75
+ - [ ] All CUDA API calls wrapped with error checking macro
76
+ - [ ] `cudaDeviceSynchronize()` + `cudaGetLastError()` called after kernels during debugging
77
+ - [ ] Device pointers use `d_` prefix, host pointers use `h_` prefix
78
+ - [ ] Launch configuration validated against `cudaDevAttrMaxThreadsPerBlock`
79
+ - [ ] `compute-sanitizer --tool memcheck` passes with no errors
80
+ - [ ] Shared memory usage per block verified to be within device limit
@@ -0,0 +1,75 @@
1
+ ## Identity
2
+ - domain: dart
3
+ - type: language
4
+ - confidence: 0.95
5
+
6
+ # Dart / Flutter — Error Pattern Reference
7
+
8
+ Read the full Dart analyzer error and the Flutter stack trace. Flutter errors often include a widget ancestry chain — read it to find where the bad state originates.
9
+
10
+ ## Error Code Quick Reference
11
+ - **Null check operator used on a null value** — `!` used on null (null safety violation at runtime).
12
+ - **setState() called after dispose()** — State method called on unmounted widget.
13
+ - **A build function returned null** — Widget build() returned null instead of a Widget.
14
+ - **'context' is not a valid BuildContext** — BuildContext used across async gap.
15
+ - **type 'X' is not a subtype of type 'Y'** — Type mismatch from platform channel or JSON.
16
+ - **Late initialization error: LateInitializationError** — `late` variable read before assignment.
17
+ - **RenderFlex overflowed** — Layout overflow (not a Dart error, but a Flutter render error).
18
+ - **MissingPluginException** — Platform channel plugin not registered.
19
+
20
+ ## Known Error Patterns
21
+
22
+ ### Pattern: Null safety migration (late keyword misuse)
23
+
24
+ - **symptom**: `LateInitializationError: Field 'x' has not been initialized.` at runtime, or `Null check operator used on a null value` — despite null safety being enabled
25
+ - **cause**: The `late` keyword promises to the compiler that a variable will be initialized before its first read — but there is no runtime enforcement until the read happens. If the variable is read in a code path that runs before initialization, it crashes.
26
+ - **strategy**: 1. Find the `late` variable declaration. 2. Trace all code paths to its first read — check `initState`, async callbacks, and conditional initialization. 3. If initialization depends on async work, use a nullable type (`String?`) and guard reads with `if (x != null)` or `?`. 4. For `late` fields initialized in `initState`, ensure `initState` runs before the first build that reads them. 5. Replace `late` with proper initialization in the constructor or with a nullable type if initialization is not guaranteed.
27
+ - **toolSequence**: grep (`late `) → file_read (variable and its first read) → file_edit (replace with nullable or ensure guaranteed initialization)
28
+ - **pitfall**: Do NOT use `late` for all non-nullable fields just to satisfy the analyzer — it moves the error from compile time to runtime.
29
+
30
+ ### Pattern: setState after dispose
31
+
32
+ - **symptom**: `setState() called after dispose()` — Flutter prints this as a warning/error in debug mode; in release mode, it may silently corrupt state or crash
33
+ - **cause**: An async operation (HTTP call, Timer, animation) completes and calls `setState()` after the widget has been removed from the tree (disposed). The `State` object is still referenced by the callback closure.
34
+ - **strategy**: 1. Find async operations (HTTP calls, `Future.delayed`, `Timer`, stream subscriptions) inside `State` classes. 2. Add a mounted check before `setState`: `if (mounted) setState(() { ... });`. 3. Cancel timers and stream subscriptions in `dispose()`. 4. For `Future` callbacks, capture the result and check mounted: `final data = await fetchData(); if (!mounted) return; setState(() { _data = data; });`. 5. For streams, store the `StreamSubscription` and call `subscription.cancel()` in `dispose()`.
35
+ - **toolSequence**: grep (`setState`) → file_read (async context around each call) → file_edit (add `if (mounted)` guard) + file_edit (cancel subscriptions in dispose)
36
+ - **pitfall**: Do NOT omit the `dispose()` override — always cancel timers, animations, and stream subscriptions in `dispose()`.
37
+
38
+ ### Pattern: widget rebuild loop (setState in build)
39
+
40
+ - **symptom**: Widget rebuilds continuously (high CPU, hot reload doesn't settle, "build called 60 times/sec" in profile). Often caused by calling `setState` inside `build` or in a listener that triggers rebuild which triggers the listener again.
41
+ - **cause**: Calling `setState()` during a `build()` call, or setting up a listener in `build()` that immediately fires and calls `setState()`, causing an infinite loop of rebuilds.
42
+ - **strategy**: 1. Check the `build()` method for any direct `setState()` calls — remove them. 2. Move listener setup to `initState()` so it runs once. 3. For `addListener` patterns, ensure the listener does not call `setState` synchronously in the first frame. 4. Use `WidgetsBinding.instance.addPostFrameCallback(() { setState(() {}); })` when state update must happen after a build. 5. For `AnimationController`, initialize in `initState`, not in `build`.
43
+ - **toolSequence**: file_read (build method) → grep (`setState` inside build) → file_edit (move initialization to initState)
44
+ - **pitfall**: Do NOT use `setState` inside `build` — use `initState`, `didUpdateWidget`, or `addPostFrameCallback` for post-build state updates.
45
+
46
+ ### Pattern: async gap (BuildContext across async)
47
+
48
+ - **symptom**: `Don't use 'BuildContext's across async gaps` — lint warning. In release builds, may cause `FlutterError` or incorrect navigation/dialog behavior when context is no longer valid.
49
+ - **cause**: After an `await` point, the widget may have been disposed or rebuilt, making the captured `BuildContext` stale. Using it for `Navigator.push`, `showDialog`, `ScaffoldMessenger.of(context)`, etc., can fail silently or crash.
50
+ - **strategy**: 1. Find every `await` inside event handlers or async methods that also use `context`. 2. Check the `use_build_context_synchronously` lint — enable it in `analysis_options.yaml`. 3. Before the `await`, save any context-dependent values (e.g., `Navigator.of(context)` → `final nav = Navigator.of(context);`). 4. After the `await`, add a `if (!mounted) return;` check before using `context` again. 5. Use `ref` (Riverpod) or BLoC events that don't capture context for post-async navigation.
51
+ - **toolSequence**: grep (`await`) in widget files → file_read (context usage after await) → file_edit (save navigator before await, add mounted check)
52
+ - **pitfall**: Do NOT suppress the lint with `// ignore:` — it exists to prevent real crashes. Fix the async context usage instead.
53
+
54
+ ### Pattern: platform channel type mismatch
55
+
56
+ - **symptom**: `type 'int' is not a subtype of type 'double'` or `PlatformException: argument type 'LinkedHashMap<Object?, Object?>' is not a subtype of type 'Map<String, dynamic>'` — from platform channel callbacks
57
+ - **cause**: Platform channel (MethodChannel, EventChannel) passes types that differ between Dart and the native platform. Android/iOS may return `int` where Dart expects `double`, or a generic `Map<Object?, Object?>` where `Map<String, dynamic>` is expected. The codec does not automatically coerce types.
58
+ - **strategy**: 1. Read the exact types in the error message. 2. Cast the received value explicitly: `(result as num).toDouble()` for int/double mismatch. 3. For Map type issues, cast recursively: `Map<String, dynamic>.from(result as Map)`. 4. For nested maps, use a deep-cast helper or `jsonDecode(jsonEncode(result))` to normalize types. 5. Add type validation at the channel boundary with descriptive error messages.
59
+ - **toolSequence**: file_read (channel callback) → file_edit (add explicit cast with `.from()` or `as num`)
60
+ - **pitfall**: Do NOT use `dynamic` throughout the app to avoid casts — cast once at the channel boundary and use typed models internally.
61
+
62
+ ## Verification
63
+ Run: `flutter analyze` and `dart analyze`
64
+ - `flutter analyze` exit 0 = no analyzer errors.
65
+ - For tests: `flutter test`
66
+ - For build: `flutter build apk --debug` or `flutter build ios --debug`
67
+
68
+ ## Validation Checklist
69
+ - [ ] `flutter analyze` exits 0 with no errors
70
+ - [ ] All `setState` calls guarded with `if (mounted)` when in async callbacks
71
+ - [ ] All `late` variables have guaranteed initialization path before first read
72
+ - [ ] No `setState` inside `build()` — initialization moved to `initState`
73
+ - [ ] `context` not used after `await` without mounted check
74
+ - [ ] Platform channel values cast explicitly at the boundary
75
+ - [ ] `StreamSubscription`, `Timer`, and `AnimationController` cancelled/disposed in `dispose()`
@@ -0,0 +1,80 @@
1
+ ## Identity
2
+ - domain: docker
3
+ - type: language
4
+ - confidence: 0.90
5
+
6
+ # Docker — Error Pattern Reference
7
+
8
+ Read the exact build error output and layer number first. Docker errors are often caused by layer ordering, missing context files, or base image issues — not the instruction itself.
9
+
10
+ ## Error Code Quick Reference
11
+ - **"no such file or directory"** — COPY/ADD source path doesn't exist in build context.
12
+ - **"failed to solve: failed to read dockerfile"** — Dockerfile not found at specified path.
13
+ - **"exec format error"** — Binary built for wrong architecture (arm vs amd64).
14
+ - **"permission denied"** — File permission issue inside container, often USER switch.
15
+ - **"layer does not exist"** — Corrupted local image cache; `docker system prune` needed.
16
+ - **"Dockerfile parse error"** — Syntax error in instruction (e.g., missing space after FROM).
17
+ - **"unknown instruction"** — Typo in Dockerfile instruction keyword.
18
+
19
+ ## Known Error Patterns
20
+
21
+ ### Image Layer Bloat — RUN apt-get Without Cleanup
22
+ - **Symptom**: Final image size is hundreds of MB larger than expected; `docker history <image>` shows a single large layer.
23
+ - **Cause**: `RUN apt-get update && apt-get install -y <pkg>` creates a layer that includes the package index and cached `.deb` files. If `apt-get clean && rm -rf /var/lib/apt/lists/*` is in a separate `RUN` instruction, the bloat layer is already committed and cannot be removed.
24
+ - **Strategy**: 1. Run `docker history <image> --no-trunc` to find the bloated layer. 2. Merge all apt operations into a single `RUN` instruction ending with `&& apt-get clean && rm -rf /var/lib/apt/lists/*`. 3. Check if a smaller base image is appropriate (`alpine` vs `ubuntu`). 4. Use multi-stage builds to copy only the final artifact, leaving build tools behind.
25
+ - **Tool sequence**: shell_exec (`docker history`) → file_read (Dockerfile) → file_edit (merge RUN commands + cleanup)
26
+ - **Pitfall**: Do NOT put cleanup in a separate `RUN` layer — Docker layers are immutable, and a cleanup layer only adds overhead without reducing size.
27
+
28
+ ### Non-Root User Missing — Security Risk
29
+ - **Symptom**: Container process runs as UID 0 (root); security scanners flag the image; Kubernetes PSP/PSA rejects it.
30
+ - **Cause**: No `USER` instruction in the Dockerfile. Default user is root, which means a compromised process inside the container has root privileges on the host filesystem if volumes are mounted.
31
+ - **Strategy**: 1. Grep the Dockerfile for `USER` instruction. 2. Before the final CMD/ENTRYPOINT, add: `RUN groupadd -r appuser && useradd -r -g appuser appuser` then `USER appuser`. 3. Ensure all application files are readable by this user (`COPY --chown=appuser:appuser . .`). 4. If the app needs specific capabilities (e.g., binding to port <1024), use `setcap` rather than running as root.
32
+ - **Tool sequence**: grep (`USER`) → file_read (Dockerfile) → file_edit (add user creation and USER instruction)
33
+ - **Pitfall**: Do NOT set `USER 0` to fix permission errors — that defeats the purpose. Fix the file permissions or use `--chown` in COPY instead.
34
+
35
+ ### COPY vs ADD Confusion — Unexpected Behavior
36
+ - **Symptom**: Tar archives are auto-extracted when they should be copied as-is; remote URLs fail or succeed unexpectedly.
37
+ - **Cause**: `ADD` has two special behaviors that `COPY` does not: (1) it auto-extracts local tar archives, (2) it accepts URLs. Using `ADD` for regular files is confusing and considered bad practice by Docker best practices.
38
+ - **Strategy**: 1. Grep all `ADD` instructions in the Dockerfile. 2. Replace `ADD <local-file> <dest>` with `COPY <local-file> <dest>` unless tar auto-extraction is explicitly needed. 3. For remote URL downloads, use `RUN curl -o <dest> <url>` instead of `ADD <url>` — gives more control over the download (checksums, error handling). 4. Only use `ADD` when intentionally extracting a local tar archive.
39
+ - **Tool sequence**: grep (`^ADD `) → file_read (Dockerfile) → file_edit (replace ADD with COPY or RUN curl)
40
+ - **Pitfall**: Do NOT use `ADD` for everything just because it seems more powerful — the implicit auto-extraction is a common source of bugs when archive filenames change.
41
+
42
+ ### Build Context Too Large — .dockerignore Missing
43
+ - **Symptom**: `docker build` is slow to start; "Sending build context to Docker daemon" reports gigabytes; `node_modules` or `.git` is sent to the daemon.
44
+ - **Cause**: Docker sends the entire build context directory to the daemon before processing the Dockerfile. Without a `.dockerignore` file, `node_modules`, `.git`, `dist`, large data files, and secrets are all included.
45
+ - **Strategy**: 1. Check if `.dockerignore` exists in the build context directory. 2. Create or update `.dockerignore` to exclude: `node_modules`, `.git`, `*.log`, `dist`, `.env*`, `__pycache__`, `.pytest_cache`, coverage reports, and any large binary assets. 3. Verify: run `docker build` again and check the "Sending build context" line — it should be kilobytes or a few megabytes. 4. Never COPY secrets (`.env`, credentials) into an image — use Docker secrets or build args.
46
+ - **Tool sequence**: shell_exec (`ls .dockerignore`) → file_edit (create/update .dockerignore) → shell_exec (docker build, check context size)
47
+ - **Pitfall**: Do NOT add `.dockerignore` entries after `COPY . .` instructions — the ignore happens at context-sending time, not at COPY time. Both must be correct.
48
+
49
+ ### Health Check Missing — Orchestrator Cannot Detect Unhealthy Containers
50
+ - **Symptom**: Container shows as `Up` but application is not responding; Kubernetes/ECS marks pods healthy when they are not; rolling deployments shift traffic to broken instances.
51
+ - **Cause**: No `HEALTHCHECK` instruction in the Dockerfile. Without it, Docker only checks if the process is running (PID exists), not if the application is actually serving requests.
52
+ - **Strategy**: 1. Grep the Dockerfile for `HEALTHCHECK`. 2. Add a health check appropriate for the service type: HTTP services: `HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD curl -f http://localhost:8080/health || exit 1`. TCP services: `CMD nc -z localhost 8080`. Custom scripts: `CMD ["/app/healthcheck.sh"]`. 3. Ensure the health endpoint is lightweight and does not trigger side effects. 4. Test: `docker inspect --format='{{.State.Health}}' <container>`.
53
+ - **Tool sequence**: grep (`HEALTHCHECK`) → file_read (Dockerfile) → file_edit (add HEALTHCHECK instruction)
54
+ - **Pitfall**: Do NOT use a health check that exercises a database query unless the app genuinely requires DB connectivity at startup — this causes false unhealthy states during DB maintenance.
55
+
56
+ ### Layer Cache Invalidation — Dependency Install Repeated
57
+ - **Symptom**: `npm install` or `pip install` runs every build even when dependencies haven't changed; builds take minutes instead of seconds.
58
+ - **Cause**: `COPY . .` before `RUN npm install` copies all source files first. Any source change invalidates the cache at that layer, causing npm install to re-run. Docker cache works top-to-bottom — each instruction invalidates all subsequent layers.
59
+ - **Strategy**: 1. Read the Dockerfile and identify where dependency manifests are copied vs. source files. 2. Restructure: copy ONLY the dependency manifests first (`COPY package.json package-lock.json ./`), run the install, THEN copy source (`COPY . .`). 3. This way the install layer is only invalidated when manifests change, not on every source edit.
60
+ - **Tool sequence**: file_read (Dockerfile) → file_edit (reorder COPY and RUN install instructions)
61
+ - **Pitfall**: Do NOT copy `package.json` and `package-lock.json` in the same instruction as all other files — split the COPY into two instructions.
62
+
63
+ ## Verification
64
+ Run: `docker build -t test-image . && docker run --rm test-image`
65
+ - Successful build and run = baseline passing.
66
+ - Check image size: `docker images test-image` — compare against expected baseline.
67
+ - Run Hadolint: `hadolint Dockerfile` — no warnings at DL3 level or above.
68
+ - Inspect layers: `docker history test-image --no-trunc`
69
+
70
+ ## Validation Checklist
71
+ - [ ] `.dockerignore` exists and excludes `node_modules`, `.git`, `.env*`, large binaries
72
+ - [ ] All `RUN apt-get install` instructions include `&& apt-get clean && rm -rf /var/lib/apt/lists/*`
73
+ - [ ] Non-root `USER` instruction present before CMD/ENTRYPOINT
74
+ - [ ] `COPY` used instead of `ADD` for local files that are not tar archives
75
+ - [ ] `HEALTHCHECK` instruction present with appropriate interval and timeout
76
+ - [ ] Dependency manifests copied before source files (layer cache optimization)
77
+ - [ ] Multi-stage build used if build tools should not be in the final image
78
+ - [ ] No secrets or `.env` files copied into the image
79
+ - [ ] Base image pinned to a specific digest or version tag, not `latest`
80
+ - [ ] Hadolint passes with no high-severity warnings
@@ -0,0 +1,80 @@
1
+ ## Identity
2
+ - domain: elixir
3
+ - type: language
4
+ - confidence: 0.90
5
+
6
+ # Elixir — Error Pattern Reference
7
+
8
+ Read the exact exception type, message, and stacktrace. Elixir errors are structured — the module, function, and arity in the stacktrace tell you exactly where the failure occurred.
9
+
10
+ ## Error Code Quick Reference
11
+ - **FunctionClauseError** — No function clause matched the given arguments.
12
+ - **MatchError** — Pattern match failed in `=` or `case`/`with`.
13
+ - **UndefinedFunctionError** — Module or function not found (missing import, wrong arity).
14
+ - **ArgumentError** — Invalid argument to a function (often nil where value expected).
15
+ - **KeyError** — Key not found in map (use `Map.get/3` with default instead of `map[key]!`).
16
+ - **RuntimeError** — Explicit `raise "message"` or `raise RuntimeError, message: "..."`.
17
+ - **EXIT from #PID** — A linked/monitored process crashed; check the reason.
18
+ - **** (Ecto.NoResultsError)** — `Repo.get!` or `Repo.one!` found no records.
19
+
20
+ ## Known Error Patterns
21
+
22
+ ### GenServer Timeout — handle_call/cast Not Returning
23
+ - **Symptom**: `** (exit) exited in: GenServer.call/3 with reason: :timeout`; caller process crashes after 5000ms default timeout; server appears unresponsive.
24
+ - **Cause**: `handle_call/3` is blocking on a slow operation (database query, HTTP request, file I/O) and does not return within the timeout. Or `handle_call` is calling another GenServer which itself is blocked, creating a deadlock.
25
+ - **Strategy**: 1. Read the `handle_call` implementation for the timed-out message type. 2. Move slow operations out of `handle_call`: reply immediately with `:noreply`, spawn a task, and send the result back via `GenServer.reply/2`. 3. For truly long operations, increase the timeout: `GenServer.call(server, msg, 30_000)`. 4. Use `Task.async/await` or `Task.Supervisor` for concurrent work. 5. Avoid chained `GenServer.call` between processes that can form circular waits.
26
+ - **Tool sequence**: grep (`handle_call`, `GenServer.call`) → file_read → file_edit (extract slow work to Task, use cast + send instead of call)
27
+ - **Pitfall**: Do NOT increase timeout indefinitely as the primary fix — a timed-out call indicates a design issue. The GenServer's inbox continues to fill while it's blocked.
28
+
29
+ ### Process Leak — No Supervision Tree
30
+ - **Symptom**: Memory usage grows over time; `Process.list() |> length` increases; `:observer.start()` shows thousands of processes with no parents.
31
+ - **Cause**: Processes spawned with `spawn/1` or `Task.start/1` are not supervised. If they crash, they leave no trace. If they leak, nothing cleans them up. Long-running work done in unsupervised processes accumulates.
32
+ - **Strategy**: 1. Grep all `spawn(`, `Task.start(`, and `Process.spawn(` calls. 2. Replace fire-and-forget tasks with `Task.Supervisor.start_child(MyApp.TaskSupervisor, fn -> ... end)`. 3. For recurring workers, use `GenServer` under a `Supervisor`. 4. Define a supervision tree in `application.ex` and add all long-lived processes to it. 5. Use `DynamicSupervisor` for runtime-spawned processes.
33
+ - **Tool sequence**: grep (`spawn(`, `Task\.start(`) → file_read → file_edit (replace with Task.Supervisor or add to supervision tree)
34
+ - **Pitfall**: Do NOT add processes to a supervision tree without understanding restart strategies — a `one_for_all` supervisor will restart all children when one crashes.
35
+
36
+ ### Pattern Match Failure — FunctionClauseError
37
+ - **Symptom**: `** (FunctionClauseError) no function clause matching in MyModule.my_fun/2`; occurs at runtime even though the function is defined.
38
+ - **Cause**: The function has multiple clauses with pattern matches in the arguments. The call arguments don't match any clause. Common causes: nil passed where a struct is expected, wrong map keys, incorrect atom.
39
+ - **Strategy**: 1. Read the full error — it shows the arguments that failed to match. 2. Read all clauses of the function in order — Elixir matches top to bottom. 3. Add a catch-all clause at the bottom for graceful error handling: `def my_fun(arg), do: {:error, {:unexpected_argument, arg}}`. 4. Use `IO.inspect(args, label: "my_fun args")` temporarily to log incoming values. 5. If nil is possible, add a nil-handling clause before the main clause.
40
+ - **Tool sequence**: file_read (all clauses of the failing function) → file_edit (add missing clause or fix call site to pass correct arguments)
41
+ - **Pitfall**: Do NOT add a catch-all clause that silently ignores errors — always return an error tuple or raise with context so the problem is visible.
42
+
43
+ ### Ecto Changeset Validation Error Ignored
44
+ - **Symptom**: Data is saved to the database with invalid or incomplete values; validation rules defined in the changeset have no effect; tests pass but production data is corrupted.
45
+ - **Cause**: The result of `Repo.insert/2` or `Repo.update/2` returns `{:error, changeset}` on validation failure, but the caller only pattern-matches the success case: `{:ok, record} = Repo.insert(changeset)`. The match error causes a crash, or the error is ignored entirely.
46
+ - **Strategy**: 1. Grep all `Repo.insert`, `Repo.update`, `Repo.delete` calls. 2. Verify each uses a `case` or `with` expression that handles both `{:ok, record}` and `{:error, changeset}`. 3. Never use `Repo.insert!` in production code paths that can fail validation — use `Repo.insert/2` with explicit error handling. 4. In Phoenix controllers, use `render(conn, :new, changeset: changeset)` to re-render the form with errors.
47
+ - **Tool sequence**: grep (`Repo\.insert`, `Repo\.update`) → file_read → file_edit (add case/with error handling)
48
+ - **Pitfall**: Do NOT use `{:ok, _} = Repo.insert!(...)` — `insert!` raises on failure. Use `insert/2` + case expression for user-facing operations.
49
+
50
+ ### Atom Exhaustion — Dynamic Atom Creation
51
+ - **Symptom**: `** (SystemLimitError) a system limit has been reached`; BEAM VM crashes after processing many unique strings as atoms; memory grows until VM limit (~1 million atoms by default).
52
+ - **Cause**: Atoms in Elixir are never garbage collected. Converting arbitrary user input to atoms with `String.to_atom/1` or `:erlang.binary_to_atom/2` exhausts the atom table. This is a denial-of-service vector if user input drives atom creation.
53
+ - **Strategy**: 1. Grep all `String.to_atom(`, `:erlang.binary_to_atom(`, and `:"#{var}"` interpolations. 2. Replace with `String.to_existing_atom/1` for known atoms (raises if atom doesn't exist — safe). 3. For map keys from external data (JSON, APIs), use string keys instead of atom keys. 4. Use `Jason.decode!(json, keys: :strings)` instead of `keys: :atoms` for JSON parsing. 5. For finite, known sets of atoms, define a conversion function with a `case` statement.
54
+ - **Tool sequence**: grep (`String\.to_atom`, `binary_to_atom`) → file_read → file_edit (replace with String.to_existing_atom or keep as strings)
55
+ - **Pitfall**: Do NOT use `String.to_existing_atom/1` for user input that could send arbitrary strings — it still creates atoms at compile time for every match clause, and it raises on unknown atoms which may be handled incorrectly.
56
+
57
+ ### Hot Code Reload State Loss — GenServer State Schema Change
58
+ - **Symptom**: After deploying a new version, GenServer crashes immediately with `FunctionClauseError` or `MatchError` on the state; rollback restores stability.
59
+ - **Cause**: The state data structure of a GenServer was changed (e.g., a map field added/removed, a struct field renamed) without implementing `code_change/3`. Old processes running the old code have state in the old format; new code expects the new format.
60
+ - **Strategy**: 1. Implement `code_change/3` in the GenServer to migrate old state to new state format. 2. For OTP releases, use `:sys.replace_state/2` during deployment to update running processes. 3. Prefer maps over structs for GenServer state to allow forward compatibility. 4. During blue-green deployments, drain old processes before starting new ones.
61
+ - **Tool sequence**: file_read (GenServer module) → file_edit (add code_change/3 with state migration)
62
+ - **Pitfall**: Do NOT rely on process restart (via supervisor) alone to fix state schema changes — the new process will start with empty/default state, losing all in-memory data.
63
+
64
+ ## Verification
65
+ Run: `mix compile --warnings-as-errors && mix test`
66
+ - All tests must pass with zero compilation warnings.
67
+ - Run dialyzer: `mix dialyzer` — no type errors.
68
+ - Check supervision tree: `Application.started_applications()` and `:observer.start()`.
69
+
70
+ ## Validation Checklist
71
+ - [ ] All `Repo.insert/update/delete` calls handle `{:error, changeset}` case
72
+ - [ ] No `String.to_atom/1` called with user input or external data
73
+ - [ ] All long-lived processes are under a supervision tree
74
+ - [ ] No `spawn/1` without corresponding supervisor or `Task.Supervisor`
75
+ - [ ] All `GenServer.call/3` callers handle `:timeout` gracefully
76
+ - [ ] `mix dialyzer` passes with no type errors
77
+ - [ ] All function clauses have a catch-all or explicit error-returning clause
78
+ - [ ] No blocking I/O inside `handle_call/3` — use async reply pattern
79
+ - [ ] `code_change/3` implemented for GenServers with non-trivial state
80
+ - [ ] `mix test --cover` shows all critical paths covered
@@ -0,0 +1,80 @@
1
+ ## Identity
2
+ - domain: gdscript
3
+ - type: language
4
+ - confidence: 0.88
5
+
6
+ # GDScript — Error Pattern Reference
7
+
8
+ Read the exact Godot error output including script path, line number, and the full message. GDScript errors often come from the editor Output panel or runtime debugger — check both.
9
+
10
+ ## Error Code Quick Reference
11
+ - **"Invalid get index 'x' on base 'null instance'"** — Accessing property on a null node reference.
12
+ - **"Node not found: 'NodePath'"** — get_node() path is wrong or the node doesn't exist yet.
13
+ - **"Cannot call method 'connect' on null value"** — Signal target node is null.
14
+ - **"Nonexistent signal 'signal_name'"** — Signal not defined or misspelled.
15
+ - **"Type mismatch: expected built-in 'int', got 'String'"** — Export variable type mismatch in inspector.
16
+ - **"Parse error: expected 'end of statement', got..."** — Indentation or syntax error.
17
+ - **"Function 'func_name' already has a body"** — Duplicate function definition.
18
+ - **"Identifier 'name' is not declared"** — Variable used before declaration or out of scope.
19
+
20
+ ## Known Error Patterns
21
+
22
+ ### Signal Not Connected — connect() Missing
23
+ - **Symptom**: An event (button press, timer timeout, area entered) fires but nothing happens; no error is shown. Or `Error: Signal 'pressed' is already connected` on duplicate connects.
24
+ - **Cause**: The signal was defined with `signal my_signal` or exists on a node (e.g., `Button.pressed`) but `connect()` was never called, or it was connected in the wrong node's `_ready()`. In Godot 4, the callable syntax changed from `connect("signal_name", self, "method_name")` to `signal_name.connect(method)`.
25
+ - **Strategy**: 1. Grep the script for the signal name to find where it should be connected. 2. Verify `connect()` is called in `_ready()` of the node that owns the signal or a parent. 3. In Godot 4, use `$NodeName.signal_name.connect(_on_signal)` syntax. 4. Alternatively, connect signals in the Godot editor (Scene panel → Node tab → Signals) and check the editor connection icons. 5. Add `assert($NodeName != null)` before connect calls to catch null nodes early.
26
+ - **Tool sequence**: grep (`connect(`, `signal `) → file_read → file_edit (add connect() call in _ready())
27
+ - **Pitfall**: Do NOT connect signals inside `_process()` or `_physics_process()` — you will create thousands of duplicate connections per second, causing severe performance degradation.
28
+
29
+ ### Null Node Reference — get_node Path Wrong
30
+ - **Symptom**: `Invalid get index 'x' on base 'null instance'` or `Node not found: 'Player/Weapon'`; crash occurs the moment a node is accessed.
31
+ - **Cause**: `get_node("path")` or `$NodePath` shorthand points to a node that doesn't exist at that path, was renamed, or was not yet added to the scene tree when `_ready()` ran.
32
+ - **Strategy**: 1. Open the scene in the Godot editor and verify the exact node path using the Scene tree panel. 2. Check for typos in the path — paths are case-sensitive. 3. If the node is added dynamically, access it after it is added, not in `_ready()`. 4. Use `@onready var node = $NodePath` (Godot 4) or `onready var node = $NodePath` (Godot 3) to defer node lookup to scene tree entry. 5. Add null checks: `if node != null:` before accessing properties.
33
+ - **Tool sequence**: file_read (script) → shell_exec (check scene .tscn file for node names) → file_edit (fix path or add @onready)
34
+ - **Pitfall**: Do NOT use `get_node()` in `_init()` — the node is not in the scene tree yet. Always use `_ready()` or `@onready` for node references.
35
+
36
+ ### _ready vs _init Timing Issue — Node Not in Tree
37
+ - **Symptom**: Accessing sibling nodes, calling `get_parent()`, or reading export variables in `_init()` returns null or wrong values; works fine when moved to `_ready()`.
38
+ - **Cause**: `_init()` is called when the object is created in memory, before it is added to the scene tree. `_ready()` is called after the node and all its children have entered the scene tree. Scene-dependent operations must be in `_ready()`.
39
+ - **Strategy**: 1. Grep for `_init()` functions in scripts. 2. Identify any node access, `get_node()`, `get_parent()`, or signal connections inside `_init()`. 3. Move scene-dependent initialization to `_ready()`. 4. Keep `_init()` for pure in-memory object initialization (setting default values for non-node properties). 5. For class instantiation via `ClassName.new(args)`, pass data through `_init()` parameters only — do not access the tree.
40
+ - **Tool sequence**: grep (`func _init`) → file_read → file_edit (move scene access to _ready())
41
+ - **Pitfall**: Do NOT add `await get_tree().process_frame` in `_init()` to "wait" for the tree — use `_ready()` which is guaranteed to fire after tree entry.
42
+
43
+ ### Export Variable Type Mismatch — Inspector Corruption
44
+ - **Symptom**: `Type mismatch: expected int, got String`; inspector shows wrong value type; game behavior is wrong even though code looks correct.
45
+ - **Cause**: The `@export` variable type annotation was changed after the scene was saved. The `.tscn` scene file stores the serialized value in the old type. On load, Godot tries to assign the old value to the new type.
46
+ - **Strategy**: 1. Open the `.tscn` file in a text editor and find the serialized property value. 2. Correct the value to match the new type (e.g., change `"10"` to `10` for int). 3. Or reset the property in the Godot inspector by right-clicking and selecting "Reset to Default". 4. When changing export types, always update all scenes that use the script. 5. Use `@export_enum` for string enums instead of raw strings to avoid type confusion.
47
+ - **Tool sequence**: file_read (.tscn file) → file_edit (fix serialized property type) → shell_exec (open in Godot to verify)
48
+ - **Pitfall**: Do NOT ignore type mismatch warnings — Godot may silently coerce the value, leading to subtle bugs (e.g., `"0"` being truthy when `0` is falsy).
49
+
50
+ ### Scene Instancing Memory Leak — queue_free Missing
51
+ - **Symptom**: Game stutters over time; memory usage grows with every level load; profiler shows thousands of orphaned nodes.
52
+ - **Cause**: Dynamically instanced scenes (via `PackedScene.instantiate()`) are added to the tree but never removed. When the parent scene is unloaded, child instances are orphaned if not properly freed. Circular references between nodes also prevent garbage collection.
53
+ - **Strategy**: 1. For every `instantiate()` and `add_child()` call, verify there is a corresponding `queue_free()` or `remove_child()` + `free()` call when the instance is no longer needed. 2. For bullets, enemies, and particles: use an object pool instead of instantiating/freeing per-frame. 3. Connect the `tree_exited` signal to a cleanup function. 4. Use Godot's built-in profiler (Debug → Monitors) to track node count over time. 5. Avoid keeping references to freed nodes — use `is_instance_valid(node)` before accessing.
54
+ - **Tool sequence**: grep (`instantiate()`, `add_child(`) → file_read → file_edit (add queue_free() in appropriate lifecycle location)
55
+ - **Pitfall**: Do NOT call `free()` directly on nodes that are in the scene tree — use `queue_free()` which safely defers deletion to the end of the current frame.
56
+
57
+ ### Infinite Loop in _process — Frame Freeze
58
+ - **Symptom**: Game freezes completely; editor becomes unresponsive; CPU spikes to 100%.
59
+ - **Cause**: A `while` loop or recursive call inside `_process()` or `_physics_process()` never terminates. These callbacks are called every frame and must return quickly.
60
+ - **Strategy**: 1. Grep for `while` loops and deep recursion inside `_process` and `_physics_process`. 2. Convert iterative work to state machines that progress one step per frame. 3. For async work, use `await` with signals or coroutines. 4. Add a frame counter or timeout as a safety valve: `if iterations > MAX_ITERATIONS: break`.
61
+ - **Tool sequence**: grep (`func _process`, `func _physics_process`) → file_read → file_edit (convert while loop to state machine or coroutine)
62
+ - **Pitfall**: Do NOT use `while true: await get_tree().process_frame` in production logic — use proper state machines or timers.
63
+
64
+ ## Verification
65
+ Run the scene in the Godot editor with the Debugger panel open.
66
+ - No errors or warnings in the Output panel on startup.
67
+ - Memory usage (Debug → Monitors → Memory Used) should remain stable over time.
68
+ - Frame rate should be consistent — check Debug → Monitors → FPS.
69
+
70
+ ## Validation Checklist
71
+ - [ ] All signals are connected in `_ready()`, not `_init()` or `_process()`
72
+ - [ ] All `get_node()` / `$Node` references verified against the actual scene tree
73
+ - [ ] `@onready` used for node references that must exist when ready
74
+ - [ ] All dynamically instantiated scenes have a corresponding `queue_free()` path
75
+ - [ ] No scene-dependent code in `_init()`
76
+ - [ ] Export variable types match the values serialized in `.tscn` files
77
+ - [ ] No `while` loops in `_process()` that could block the frame
78
+ - [ ] `is_instance_valid()` used before accessing potentially freed node references
79
+ - [ ] Memory monitor checked for leaks during extended play sessions
80
+ - [ ] No duplicate signal connections (check with `is_connected()` guard if connecting dynamically)
@@ -0,0 +1,77 @@
1
+ ## Identity
2
+ - domain: go
3
+ - type: language
4
+ - confidence: 0.95
5
+
6
+ # Go — Error Pattern Reference
7
+
8
+ Read the exact compiler error message first. Go errors are terse but precise — the line number, symbol name, and package path are always actionable.
9
+
10
+ ## Error Code Quick Reference
11
+ - **declared and not used** — Variable declared but never read. Remove or use it.
12
+ - **undefined: X** — Symbol not found in scope. Missing import or typo.
13
+ - **cannot use X as type Y** — Type mismatch in assignment or function call.
14
+ - **nil pointer dereference** — Accessing a field/method on a nil pointer.
15
+ - **too many arguments in call** / **not enough arguments** — Arity mismatch.
16
+ - **imported and not used** — Import declared but no symbol from it used.
17
+ - **interface does not implement** — Missing method(s) for interface satisfaction.
18
+ - **context deadline exceeded** — Context timed out before operation completed.
19
+ - **goroutine leak** — goroutine blocked forever on channel or lock.
20
+ - **data race** — Two goroutines accessing same memory without synchronization.
21
+
22
+ ## Known Error Patterns
23
+
24
+ ### Pattern: declared and not used
25
+
26
+ - **symptom**: `./main.go:12:5: x declared and not used`
27
+ - **cause**: Go requires every declared variable to be read at least once. Assigning to `_` or simply not reading the variable causes a compile error.
28
+ - **strategy**: 1. Read the line where the variable is declared. 2. Determine if the variable is genuinely unused — delete it. 3. If the value is needed for a side effect only (e.g., error return), assign to `_`: `_ = val`. 4. If the variable was meant to be used elsewhere, trace where it should be consumed and add the usage.
29
+ - **toolSequence**: file_read (declaration line) → file_edit (remove or assign to `_`)
30
+ - **pitfall**: Do NOT assign everything to `_` indiscriminately. If the value is an error, silently discarding it hides real failures.
31
+
32
+ ### Pattern: undefined: X (import path / symbol)
33
+
34
+ - **symptom**: `./main.go:8:10: undefined: SomeFunc` or `undefined: pkg.SomeType`
35
+ - **cause**: Either (a) the import path is wrong, (b) the package is not added to go.mod, (c) the symbol is unexported (lowercase), or (d) there is a typo in the symbol name.
36
+ - **strategy**: 1. Grep for the symbol definition in the project. 2. If found, check whether the import path matches the directory path. 3. If not found, check go.mod for the module — run `go get module@version` if missing. 4. If the symbol starts with a lowercase letter it is unexported — use the exported version or define a wrapper.
37
+ - **toolSequence**: grep (symbol name) → file_read (go.mod) → shell_exec (`go get <module>`) → file_edit (fix import path or symbol name)
38
+ - **pitfall**: Do NOT confuse package name with directory name — Go package name is the `package` declaration inside the file, not the directory.
39
+
40
+ ### Pattern: goroutine leak (missing defer cancel)
41
+
42
+ - **symptom**: Memory grows unboundedly over time; `runtime.NumGoroutine()` keeps increasing. Often paired with `context.WithCancel` or `context.WithTimeout` never cancelled.
43
+ - **cause**: Every `context.WithCancel` or `context.WithTimeout` allocates resources that are only freed when the cancel function is called. If `cancel()` is never called (or called only in the non-error path), the goroutine and timer leak.
44
+ - **strategy**: 1. Grep for `context.WithCancel` and `context.WithTimeout` in the file. 2. Verify that immediately after each call there is a `defer cancel()`. 3. Place `defer cancel()` on the very next line after the `ctx, cancel :=` assignment — before any error-returning calls. 4. Verify with `go vet` and the `context` linter.
45
+ - **toolSequence**: grep (`WithCancel\|WithTimeout`) → file_read → file_edit (add `defer cancel()` immediately after assignment)
46
+ - **pitfall**: Do NOT place `defer cancel()` inside an `if err == nil` block — that leaves it uncalled on the error path.
47
+
48
+ ### Pattern: nil pointer dereference
49
+
50
+ - **symptom**: `panic: runtime error: invalid memory address or nil pointer dereference` with a goroutine stack trace.
51
+ - **cause**: A pointer, interface, map, slice, or channel variable is `nil` when a field or method is accessed on it. Common sources: uninitialized struct fields, function returning `nil` error value cast to an interface, or a map not initialized with `make`.
52
+ - **strategy**: 1. Read the stack trace line number to find the exact dereference. 2. Trace backwards to where the variable was assigned — check every code path, including early returns. 3. Add a nil guard: `if ptr == nil { return fmt.Errorf("...") }`. 4. For maps, ensure initialization: `m = make(map[K]V)`. 5. For interfaces, avoid `var err error; return err` when the concrete type is nil but the interface is non-nil.
53
+ - **toolSequence**: file_read (panic line from stack trace) → grep (variable assignment) → file_edit (add nil check or initialize)
54
+ - **pitfall**: Do NOT confuse a nil interface with a nil pointer inside the interface. A `(*MyType)(nil)` stored in an `error` interface is NOT nil at the interface level.
55
+
56
+ ### Pattern: interface satisfaction error
57
+
58
+ - **symptom**: `*MyStruct does not implement MyInterface (missing method Foo)` or `cannot use *MyStruct as type MyInterface`
59
+ - **cause**: The concrete type is missing one or more methods required by the interface, the receiver type is wrong (pointer vs value), or the method signature differs (parameter or return type mismatch).
60
+ - **strategy**: 1. Read the interface definition (grep the interface name). 2. List all required methods. 3. Grep for the method on the concrete type. 4. If missing, implement it. 5. If receiver is value but interface requires pointer (or vice versa), adjust the method receiver or the assignment (`&myStruct{}`). 6. Add a compile-time check: `var _ MyInterface = (*MyStruct)(nil)`.
61
+ - **toolSequence**: grep (interface name) → file_read → grep (method name on struct) → file_edit (implement missing method or fix receiver)
62
+ - **pitfall**: Do NOT implement the method on the value receiver when the interface is satisfied only by the pointer receiver — only `*T` satisfies both pointer and value receiver methods, not the other way around.
63
+
64
+ ## Verification
65
+ Run: `go build ./...` and `go vet ./...`
66
+ - `go build` exit 0 = no compile errors.
67
+ - `go vet` exit 0 = no common correctness issues.
68
+ - For race detection: `go test -race ./...`
69
+
70
+ ## Validation Checklist
71
+ - [ ] `go build ./...` exits 0 with no output
72
+ - [ ] `go vet ./...` exits 0 with no output
73
+ - [ ] Every `context.WithCancel` / `context.WithTimeout` is immediately followed by `defer cancel()`
74
+ - [ ] No nil pointer dereferences — all pointers nil-checked before use
75
+ - [ ] Interface satisfaction verified (either compiler confirms or explicit `var _ I = (*T)(nil)` check)
76
+ - [ ] No imported packages unused; no variables declared but unused
77
+ - [ ] Maps initialized with `make()` before write