mdcontext 0.1.0 β†’ 0.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 (251) hide show
  1. package/.changeset/config.json +9 -9
  2. package/.claude/settings.local.json +25 -0
  3. package/.github/workflows/claude-code-review.yml +44 -0
  4. package/.github/workflows/claude.yml +85 -0
  5. package/CONTRIBUTING.md +186 -0
  6. package/NOTES/NOTES +44 -0
  7. package/README.md +206 -3
  8. package/biome.json +1 -1
  9. package/dist/chunk-23UPXDNL.js +3044 -0
  10. package/dist/chunk-2W7MO2DL.js +1366 -0
  11. package/dist/chunk-3NUAZGMA.js +1689 -0
  12. package/dist/chunk-7TOWB2XB.js +366 -0
  13. package/dist/chunk-7XOTOADQ.js +3065 -0
  14. package/dist/chunk-AH2PDM2K.js +3042 -0
  15. package/dist/chunk-BNXWSZ63.js +3742 -0
  16. package/dist/chunk-BTL5DJVU.js +3222 -0
  17. package/dist/chunk-HDHYG7E4.js +104 -0
  18. package/dist/chunk-HLR4KZBP.js +3234 -0
  19. package/dist/chunk-IP3FRFEB.js +1045 -0
  20. package/dist/chunk-KHU56VDO.js +3042 -0
  21. package/dist/chunk-KRYIFLQR.js +85 -89
  22. package/dist/chunk-LBSDNLEM.js +287 -0
  23. package/dist/chunk-MNTQ7HCP.js +2643 -0
  24. package/dist/chunk-MUJELQQ6.js +1387 -0
  25. package/dist/chunk-MXJGMSLV.js +2199 -0
  26. package/dist/chunk-N6QJGC3Z.js +2636 -0
  27. package/dist/chunk-OBELGBPM.js +1713 -0
  28. package/dist/chunk-OT7R5XTA.js +3192 -0
  29. package/dist/chunk-P7X4RA2T.js +106 -0
  30. package/dist/chunk-PIDUQNC2.js +3185 -0
  31. package/dist/chunk-POGCDIH4.js +3187 -0
  32. package/dist/chunk-PSIEOQGZ.js +3043 -0
  33. package/dist/chunk-PVRT3IHA.js +3238 -0
  34. package/dist/chunk-QNN4TT23.js +1430 -0
  35. package/dist/chunk-RE3R45RJ.js +3042 -0
  36. package/dist/chunk-S7E6TFX6.js +718 -657
  37. package/dist/chunk-SG6GLU4U.js +1378 -0
  38. package/dist/chunk-SJCDV2ST.js +274 -0
  39. package/dist/chunk-SYE5XLF3.js +104 -0
  40. package/dist/chunk-T5VLYBZD.js +103 -0
  41. package/dist/chunk-TOQB7VWU.js +3238 -0
  42. package/dist/chunk-VFNMZ4ZQ.js +3228 -0
  43. package/dist/chunk-VVTGZNBT.js +1533 -1423
  44. package/dist/chunk-W7Q4RFEV.js +104 -0
  45. package/dist/chunk-XTYYVRLO.js +3190 -0
  46. package/dist/chunk-Y6MDYVJD.js +3063 -0
  47. package/dist/cli/main.js +4072 -629
  48. package/dist/index.d.ts +420 -33
  49. package/dist/index.js +8 -15
  50. package/dist/mcp/server.js +103 -7
  51. package/dist/schema-BAWSG7KY.js +22 -0
  52. package/dist/schema-E3QUPL26.js +20 -0
  53. package/dist/schema-EHL7WUT6.js +20 -0
  54. package/docs/019-USAGE.md +44 -5
  55. package/docs/020-current-implementation.md +8 -8
  56. package/docs/021-DOGFOODING-FINDINGS.md +1 -1
  57. package/docs/CONFIG.md +1123 -0
  58. package/docs/ERRORS.md +383 -0
  59. package/docs/summarization.md +320 -0
  60. package/justfile +40 -0
  61. package/package.json +39 -33
  62. package/research/INDEX.md +315 -0
  63. package/research/code-review/README.md +90 -0
  64. package/research/code-review/cli-error-handling-review.md +979 -0
  65. package/research/code-review/code-review-validation-report.md +464 -0
  66. package/research/code-review/main-ts-review.md +1128 -0
  67. package/research/config-docs/SUMMARY.md +357 -0
  68. package/research/config-docs/TEST-RESULTS.md +776 -0
  69. package/research/config-docs/TODO.md +542 -0
  70. package/research/config-docs/analysis.md +744 -0
  71. package/research/config-docs/fix-validation.md +502 -0
  72. package/research/config-docs/help-audit.md +264 -0
  73. package/research/config-docs/help-system-analysis.md +890 -0
  74. package/research/frontmatter/COMMENTS-ARE-SKIPPED.md +149 -0
  75. package/research/frontmatter/LLM-CODE-NAVIGATION.md +276 -0
  76. package/research/issue-review.md +603 -0
  77. package/research/llm-summarization/agent-cli-tools-2026.md +1082 -0
  78. package/research/llm-summarization/alternative-providers-2026.md +1428 -0
  79. package/research/llm-summarization/anthropic-2026.md +367 -0
  80. package/research/llm-summarization/claude-cli-integration.md +1706 -0
  81. package/research/llm-summarization/cli-integration-patterns.md +3155 -0
  82. package/research/llm-summarization/openai-2026.md +473 -0
  83. package/research/llm-summarization/openai-compatible-providers-2026.md +1022 -0
  84. package/research/llm-summarization/opencode-cli-integration.md +1552 -0
  85. package/research/llm-summarization/prompt-engineering-2026.md +1426 -0
  86. package/research/llm-summarization/prototype-results.md +56 -0
  87. package/research/llm-summarization/provider-switching-patterns-2026.md +2153 -0
  88. package/research/llm-summarization/typescript-llm-libraries-2026.md +2436 -0
  89. package/research/mdcontext-pudding/00-EXECUTIVE-SUMMARY.md +282 -0
  90. package/research/mdcontext-pudding/01-index-embed.md +956 -0
  91. package/research/mdcontext-pudding/02-search-COMMANDS.md +142 -0
  92. package/research/mdcontext-pudding/02-search-SUMMARY.md +146 -0
  93. package/research/mdcontext-pudding/02-search.md +970 -0
  94. package/research/mdcontext-pudding/03-context.md +779 -0
  95. package/research/mdcontext-pudding/04-navigation-and-analytics.md +803 -0
  96. package/research/mdcontext-pudding/04-tree.md +704 -0
  97. package/research/mdcontext-pudding/05-config.md +1038 -0
  98. package/research/mdcontext-pudding/06-links-summary.txt +87 -0
  99. package/research/mdcontext-pudding/06-links.md +679 -0
  100. package/research/mdcontext-pudding/07-stats.md +693 -0
  101. package/research/mdcontext-pudding/BUG-FIX-PLAN.md +388 -0
  102. package/research/mdcontext-pudding/P0-BUG-VALIDATION.md +167 -0
  103. package/research/mdcontext-pudding/README.md +168 -0
  104. package/research/mdcontext-pudding/TESTING-SUMMARY.md +128 -0
  105. package/research/research-quality-review.md +834 -0
  106. package/research/semantic-search/embedding-text-analysis.md +156 -0
  107. package/research/semantic-search/multi-word-failure-reproduction.md +171 -0
  108. package/research/semantic-search/query-processing-analysis.md +207 -0
  109. package/research/semantic-search/root-cause-and-solution.md +114 -0
  110. package/research/semantic-search/threshold-validation-report.md +69 -0
  111. package/research/semantic-search/vector-search-analysis.md +63 -0
  112. package/research/test-path-issues.md +276 -0
  113. package/review/ALP-76/1-error-type-design.md +962 -0
  114. package/review/ALP-76/2-error-handling-patterns.md +906 -0
  115. package/review/ALP-76/3-error-presentation.md +624 -0
  116. package/review/ALP-76/4-test-coverage.md +625 -0
  117. package/review/ALP-76/5-migration-completeness.md +440 -0
  118. package/review/ALP-76/6-effect-best-practices.md +755 -0
  119. package/scripts/apply-branch-protection.sh +47 -0
  120. package/scripts/branch-protection-templates.json +79 -0
  121. package/scripts/prototype-summarization.ts +346 -0
  122. package/scripts/rebuild-hnswlib.js +32 -37
  123. package/scripts/setup-branch-protection.sh +64 -0
  124. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/active-provider.json +7 -0
  125. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.json +541 -0
  126. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.meta.json +5 -0
  127. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/config.json +8 -0
  128. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
  129. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
  130. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/documents.json +60 -0
  131. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/links.json +13 -0
  132. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/sections.json +1197 -0
  133. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/configuration-management.md +99 -0
  134. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/distributed-systems.md +92 -0
  135. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/error-handling.md +78 -0
  136. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/failure-automation.md +55 -0
  137. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/job-context.md +69 -0
  138. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/process-orchestration.md +99 -0
  139. package/src/cli/argv-preprocessor.test.ts +2 -2
  140. package/src/cli/cli.test.ts +230 -33
  141. package/src/cli/commands/config-cmd.ts +642 -0
  142. package/src/cli/commands/context.ts +97 -9
  143. package/src/cli/commands/duplicates.ts +122 -0
  144. package/src/cli/commands/embeddings.ts +529 -0
  145. package/src/cli/commands/index-cmd.ts +210 -30
  146. package/src/cli/commands/index.ts +3 -0
  147. package/src/cli/commands/search.ts +894 -64
  148. package/src/cli/commands/stats.ts +3 -0
  149. package/src/cli/commands/tree.ts +26 -5
  150. package/src/cli/config-layer.ts +176 -0
  151. package/src/cli/error-handler.test.ts +235 -0
  152. package/src/cli/error-handler.ts +655 -0
  153. package/src/cli/flag-schemas.ts +66 -0
  154. package/src/cli/help.ts +209 -7
  155. package/src/cli/main.ts +348 -58
  156. package/src/cli/options.ts +10 -0
  157. package/src/cli/shared-error-handling.ts +199 -0
  158. package/src/cli/utils.ts +150 -17
  159. package/src/config/file-provider.test.ts +320 -0
  160. package/src/config/file-provider.ts +273 -0
  161. package/src/config/index.ts +72 -0
  162. package/src/config/integration.test.ts +667 -0
  163. package/src/config/precedence.test.ts +277 -0
  164. package/src/config/precedence.ts +451 -0
  165. package/src/config/schema.test.ts +414 -0
  166. package/src/config/schema.ts +603 -0
  167. package/src/config/service.test.ts +320 -0
  168. package/src/config/service.ts +243 -0
  169. package/src/config/testing.test.ts +264 -0
  170. package/src/config/testing.ts +110 -0
  171. package/src/core/types.ts +6 -33
  172. package/src/duplicates/detector.test.ts +183 -0
  173. package/src/duplicates/detector.ts +414 -0
  174. package/src/duplicates/index.ts +18 -0
  175. package/src/embeddings/embedding-namespace.test.ts +300 -0
  176. package/src/embeddings/embedding-namespace.ts +947 -0
  177. package/src/embeddings/heading-boost.test.ts +222 -0
  178. package/src/embeddings/hnsw-build-options.test.ts +198 -0
  179. package/src/embeddings/hyde.test.ts +272 -0
  180. package/src/embeddings/hyde.ts +264 -0
  181. package/src/embeddings/index.ts +2 -0
  182. package/src/embeddings/openai-provider.ts +332 -83
  183. package/src/embeddings/pricing.json +22 -0
  184. package/src/embeddings/provider-constants.ts +204 -0
  185. package/src/embeddings/provider-errors.test.ts +967 -0
  186. package/src/embeddings/provider-errors.ts +565 -0
  187. package/src/embeddings/provider-factory.test.ts +240 -0
  188. package/src/embeddings/provider-factory.ts +225 -0
  189. package/src/embeddings/provider-integration.test.ts +788 -0
  190. package/src/embeddings/query-preprocessing.test.ts +187 -0
  191. package/src/embeddings/semantic-search-threshold.test.ts +508 -0
  192. package/src/embeddings/semantic-search.ts +780 -93
  193. package/src/embeddings/types.ts +293 -16
  194. package/src/embeddings/vector-store.ts +486 -77
  195. package/src/embeddings/voyage-provider.ts +313 -0
  196. package/src/errors/errors.test.ts +845 -0
  197. package/src/errors/index.ts +533 -0
  198. package/src/index/ignore-patterns.test.ts +354 -0
  199. package/src/index/ignore-patterns.ts +305 -0
  200. package/src/index/indexer.ts +286 -48
  201. package/src/index/storage.ts +94 -30
  202. package/src/index/types.ts +40 -2
  203. package/src/index/watcher.ts +67 -9
  204. package/src/index.ts +22 -0
  205. package/src/integration/search-keyword.test.ts +678 -0
  206. package/src/mcp/server.ts +135 -6
  207. package/src/parser/parser.ts +18 -19
  208. package/src/parser/section-filter.test.ts +277 -0
  209. package/src/parser/section-filter.ts +125 -3
  210. package/src/search/__tests__/hybrid-search.test.ts +650 -0
  211. package/src/search/bm25-store.ts +366 -0
  212. package/src/search/cross-encoder.test.ts +253 -0
  213. package/src/search/cross-encoder.ts +406 -0
  214. package/src/search/fuzzy-search.test.ts +419 -0
  215. package/src/search/fuzzy-search.ts +273 -0
  216. package/src/search/hybrid-search.ts +448 -0
  217. package/src/search/path-matcher.test.ts +276 -0
  218. package/src/search/path-matcher.ts +33 -0
  219. package/src/search/searcher.test.ts +99 -1
  220. package/src/search/searcher.ts +189 -67
  221. package/src/search/wink-bm25.d.ts +30 -0
  222. package/src/summarization/cli-providers/claude.ts +202 -0
  223. package/src/summarization/cli-providers/detection.test.ts +273 -0
  224. package/src/summarization/cli-providers/detection.ts +118 -0
  225. package/src/summarization/cli-providers/index.ts +8 -0
  226. package/src/summarization/cost.test.ts +139 -0
  227. package/src/summarization/cost.ts +102 -0
  228. package/src/summarization/error-handler.test.ts +127 -0
  229. package/src/summarization/error-handler.ts +111 -0
  230. package/src/summarization/index.ts +102 -0
  231. package/src/summarization/pipeline.test.ts +498 -0
  232. package/src/summarization/pipeline.ts +231 -0
  233. package/src/summarization/prompts.test.ts +269 -0
  234. package/src/summarization/prompts.ts +133 -0
  235. package/src/summarization/provider-factory.test.ts +396 -0
  236. package/src/summarization/provider-factory.ts +178 -0
  237. package/src/summarization/types.ts +184 -0
  238. package/src/summarize/summarizer.ts +104 -35
  239. package/src/types/huggingface-transformers.d.ts +66 -0
  240. package/tests/fixtures/cli/.mdcontext/active-provider.json +7 -0
  241. package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
  242. package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
  243. package/tests/fixtures/cli/.mdcontext/indexes/documents.json +4 -4
  244. package/tests/fixtures/cli/.mdcontext/indexes/sections.json +14 -0
  245. package/tests/integration/embed-index.test.ts +712 -0
  246. package/tests/integration/search-context.test.ts +469 -0
  247. package/tests/integration/search-semantic.test.ts +522 -0
  248. package/vitest.config.ts +1 -6
  249. package/AGENTS.md +0 -46
  250. package/tests/fixtures/cli/.mdcontext/vectors.bin +0 -0
  251. package/tests/fixtures/cli/.mdcontext/vectors.meta.json +0 -1264
@@ -0,0 +1,625 @@
1
+ # Test Coverage Review: ALP-76 Consolidated Error Handling
2
+
3
+ **Reviewer**: Claude Sonnet 4.5
4
+ **Date**: 2026-01-24
5
+ **Branch**: nancy-ALP-76 worktree
6
+ **Issue**: ALP-76 - Consolidated Error Handling
7
+
8
+ ---
9
+
10
+ ## Executive Summary
11
+
12
+ **Overall Assessment**: ⚠️ **PARTIAL PASS** - Core error types have excellent unit test coverage, but integration testing and production error flow verification are insufficient.
13
+
14
+ ### Acceptance Criteria Status
15
+
16
+ | Criterion | Status | Notes |
17
+ |-----------|--------|-------|
18
+ | All domain errors use Data.TaggedError | βœ… PASS | All 14 error types properly defined |
19
+ | No silent error swallowing | ⚠️ PARTIAL | One intentional case documented, but no tests verify no regressions |
20
+ | Error presentation only at CLI boundary | βœ… PASS | Clean separation verified |
21
+ | catchTag pattern used exhaustively | ⚠️ PARTIAL | Used correctly, but not all error paths tested |
22
+ | Tests verify error type discrimination | ⚠️ PARTIAL | Unit tests good, integration tests missing |
23
+
24
+ ### Key Findings
25
+
26
+ **Strengths:**
27
+ - Comprehensive unit tests for error types (50 tests, 610 lines)
28
+ - Every error type has construction, _tag, code, and catchTag tests
29
+ - Error formatter has complete Match.exhaustive coverage
30
+ - Error codes tested for uniqueness and format
31
+
32
+ **Critical Gaps:**
33
+ 1. No integration tests for error flows through commands
34
+ 2. Silent error swallowing not regression-tested
35
+ 3. Error recovery scenarios untested
36
+ 4. Type compiler enforcement not verified in tests
37
+
38
+ ---
39
+
40
+ ## 1. Error Type Discrimination Tests
41
+
42
+ ### 1.1 Unit Test Coverage (GOOD)
43
+
44
+ **Location**: `/Users/alphab/Dev/LLM/DEV/mdcontext/worktrees/nancy-ALP-76/src/errors/errors.test.ts`
45
+
46
+ All 14 error types have comprehensive unit tests:
47
+
48
+ ```typescript
49
+ // File System Errors (4 types)
50
+ βœ… FileReadError - lines 41-89
51
+ βœ… FileWriteError - lines 91-113
52
+ βœ… DirectoryCreateError - lines 115-125
53
+ βœ… DirectoryWalkError - lines 127-137
54
+
55
+ // Parse Errors (1 type)
56
+ βœ… ParseError - lines 143-169
57
+
58
+ // API Key Errors (2 types)
59
+ βœ… ApiKeyMissingError - lines 175-210
60
+ βœ… ApiKeyInvalidError - lines 212-232
61
+
62
+ // Embedding Errors (1 type with 5 sub-reasons)
63
+ βœ… EmbeddingError - lines 238-312
64
+ - RateLimit, QuotaExceeded, Network, ModelError, Unknown
65
+
66
+ // Index Errors (3 types)
67
+ βœ… IndexNotFoundError - lines 318-330
68
+ βœ… IndexCorruptedError - lines 332-361
69
+ βœ… IndexBuildError - lines 363-373
70
+
71
+ // Search Errors (2 types)
72
+ βœ… DocumentNotFoundError - lines 379-399
73
+ βœ… EmbeddingsNotFoundError - lines 401-417
74
+
75
+ // Vector Store Errors (1 type)
76
+ βœ… VectorStoreError - lines 423-441
77
+
78
+ // Config Errors (1 type)
79
+ βœ… ConfigError - lines 447-467
80
+
81
+ // Watch Errors (1 type)
82
+ βœ… WatchError - lines 473-483
83
+
84
+ // CLI Errors (1 type)
85
+ βœ… CliValidationError - lines 489-515
86
+ ```
87
+
88
+ **Test Quality**:
89
+ - Each error tests `_tag` correctness for catchTag discrimination
90
+ - Error code getters verified (both constant and dynamic)
91
+ - Data field preservation tested
92
+ - Cause chain preservation tested (for errors with cause field)
93
+ - catchTag integration tested with Effect.runPromise
94
+ - Dynamic message generation tested (for errors with computed messages)
95
+
96
+ ### 1.2 Integration Test Coverage (WEAK)
97
+
98
+ **catchTags Integration Test** (lines 521-554):
99
+ ```typescript
100
+ βœ… Tests multiple error types with catchTags (FileReadError, ApiKeyMissingError, IndexNotFoundError)
101
+ ```
102
+
103
+ However, this is the **only** integration test for catchTags. Missing:
104
+ - No tests for commands actually using catchTags
105
+ - No tests for error handler (formatError/createErrorHandler)
106
+ - No tests verifying exhaustive matching works
107
+
108
+ ### 1.3 Type Compiler Tests (MISSING)
109
+
110
+ **Gap**: No tests verify that TypeScript compiler catches:
111
+ - Missing error cases in catchTags
112
+ - Invalid error tags
113
+ - Non-exhaustive error handling
114
+
115
+ **Recommendation**: Add type-level tests or document compiler verification process.
116
+
117
+ ---
118
+
119
+ ## 2. Coverage Analysis
120
+
121
+ ### 2.1 Error Path Coverage
122
+
123
+ **Good Coverage**:
124
+ - βœ… Error construction and data preservation (100%)
125
+ - βœ… Error code mapping (100%)
126
+ - βœ… catchTag discrimination (tested for 3 error types)
127
+ - βœ… Dynamic message generation (for 4 error types)
128
+
129
+ **Weak Coverage**:
130
+ - ⚠️ Error formatter (formatError) - **0 dedicated tests**
131
+ - ⚠️ Error display (displayError) - **0 tests**
132
+ - ⚠️ createErrorHandler - **0 tests**
133
+ - ⚠️ Real error flows through commands - **2 basic tests only**
134
+
135
+ ### 2.2 Production Error Usage
136
+
137
+ **Analysis of catchTags Usage in Production Code**:
138
+
139
+ Found 6 uses of catchTags/catchTag in production:
140
+
141
+ 1. **search.ts:350-361** - Handles IndexNotFoundError gracefully (with logging)
142
+ 2. **search.ts:392-404** - Handles ApiKeyMissingError, ApiKeyInvalidError
143
+ 3. **search.ts:473-485** - Duplicate of #2 (different code path)
144
+ 4. **index-cmd.ts:250-260** - Handles IndexNotFoundError (with logging)
145
+ 5. **index-cmd.ts:303-313** - Handles ApiKeyMissingError, ApiKeyInvalidError
146
+ 6. **vector-store.ts** - Uses catchTag for VectorStoreError
147
+
148
+ **Test Coverage for These Paths**: ❌ **NONE**
149
+
150
+ No integration tests verify these error handling paths work correctly.
151
+
152
+ ### 2.3 Silent Error Swallowing
153
+
154
+ **Found 1 Instance** (properly documented):
155
+
156
+ ```typescript
157
+ // src/summarize/summarizer.ts:537-543
158
+ // Note: catchAll is intentional - measureReduction is a utility function
159
+ // where failures should return default values (no reduction) rather than throw
160
+ const result = await Effect.runPromise(
161
+ summarizeFile(filePath, { level }).pipe(
162
+ Effect.catchAll(() => Effect.succeed(null)),
163
+ ),
164
+ )
165
+ ```
166
+
167
+ **Status**: βœ… This is properly documented and intentional (utility function that should degrade gracefully).
168
+
169
+ **Gap**: ⚠️ No test verifies this behavior or prevents regression to silent swallowing elsewhere.
170
+
171
+ ### 2.4 CLI Error Handling
172
+
173
+ **E2E Tests** (`src/cli/cli.test.ts`):
174
+ - βœ… 222 tests total, 50 related to errors
175
+ - ⚠️ Only 2 explicit error handling tests:
176
+ - "handles non-existent file gracefully" (line 356)
177
+ - "handles non-existent directory gracefully" (line 363)
178
+ - βœ… Tests only verify error output contains "error|not found|no such"
179
+ - ❌ No tests for specific error types or error codes
180
+
181
+ **Missing**:
182
+ - No tests for API key errors
183
+ - No tests for index corruption scenarios
184
+ - No tests for embedding errors
185
+ - No tests verify error codes are displayed
186
+ - No tests verify suggestions are shown
187
+
188
+ ---
189
+
190
+ ## 3. Test Quality Assessment
191
+
192
+ ### 3.1 Meaningful Tests (GOOD)
193
+
194
+ Tests go beyond type checking and verify actual behavior:
195
+
196
+ **Example - ApiKeyMissingError** (lines 186-192):
197
+ ```typescript
198
+ it('generates dynamic message', () => {
199
+ const error = new ApiKeyMissingError({
200
+ provider: 'openai',
201
+ envVar: 'OPENAI_API_KEY',
202
+ })
203
+ expect(error.message).toBe('OPENAI_API_KEY not set')
204
+ })
205
+ ```
206
+
207
+ **Example - EmbeddingError reason mapping** (lines 247-290):
208
+ Tests each reason maps to correct error code dynamically.
209
+
210
+ **Example - catchTag integration** (lines 78-88):
211
+ ```typescript
212
+ it('can be caught with catchTag', async () => {
213
+ const effect = Effect.fail(
214
+ new FileReadError({ path: '/test.md', message: 'error' }),
215
+ )
216
+ const result = await Effect.runPromise(
217
+ effect.pipe(
218
+ Effect.catchTag('FileReadError', (e) => Effect.succeed(e.path)),
219
+ ),
220
+ )
221
+ expect(result).toBe('/test.md')
222
+ })
223
+ ```
224
+
225
+ ### 3.2 Error Recovery Scenarios (WEAK)
226
+
227
+ **Tested Recovery Scenarios**:
228
+ - βœ… catchTag returns success with data (3 error types tested)
229
+ - βœ… catchTags handles multiple error types (1 integration test)
230
+
231
+ **Missing Recovery Scenarios**:
232
+ - ❌ Retrying after rate limit error
233
+ - ❌ Falling back to keyword search after embedding error
234
+ - ❌ Creating index when IndexNotFoundError occurs
235
+ - ❌ Error recovery in watch mode
236
+ - ❌ Partial success scenarios (e.g., some files fail, others succeed)
237
+
238
+ ### 3.3 Edge Cases (PARTIAL)
239
+
240
+ **Good Coverage**:
241
+ - βœ… Optional fields (ParseError path/line/column, ConfigError field)
242
+ - βœ… Cause chain preservation
243
+ - βœ… Unknown embedding error reasons (catch-all)
244
+ - βœ… Error code uniqueness (lines 561-565)
245
+
246
+ **Missing Edge Cases**:
247
+ - ❌ Very long error messages
248
+ - ❌ Nested cause chains
249
+ - ❌ Concurrent errors in parallel operations
250
+ - ❌ Error during error handling (meta-errors)
251
+ - ❌ Unicode/special characters in paths/messages
252
+
253
+ ---
254
+
255
+ ## 4. Regression Prevention
256
+
257
+ ### 4.1 Anti-Pattern Detection (WEAK)
258
+
259
+ **Tests That Would Catch Regressions**:
260
+ - βœ… Error code uniqueness test (prevents duplicate codes)
261
+ - βœ… Error code format test (prevents invalid formats)
262
+ - βœ… Match.exhaustive in formatter (compiler catches missing cases)
263
+
264
+ **Missing Regression Tests**:
265
+ - ❌ No test prevents adding catchAll(() => succeed(null)) without logging
266
+ - ❌ No test verifies all error constructors use TaggedError
267
+ - ❌ No test prevents throwing Error instead of failing with typed error
268
+ - ❌ No test prevents error formatting in business logic
269
+
270
+ ### 4.2 Constructor Pattern (VERIFIED)
271
+
272
+ **OpenAI Provider Constructor Fix** (GOOD):
273
+
274
+ ```typescript
275
+ // src/embeddings/openai-provider.ts:43-68
276
+ private constructor(apiKey: string, options: OpenAIProviderOptions = {}) {
277
+ // Private constructor cannot throw
278
+ }
279
+
280
+ static create(options: OpenAIProviderOptions = {}): Effect.Effect<OpenAIProvider, ApiKeyMissingError> {
281
+ const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY
282
+ if (!apiKey) {
283
+ return Effect.fail(new ApiKeyMissingError({...}))
284
+ }
285
+ return Effect.succeed(new OpenAIProvider(apiKey, options))
286
+ }
287
+ ```
288
+
289
+ βœ… Private constructor + static factory pattern correctly implemented.
290
+
291
+ **Test Coverage**: ❌ No test verifies this pattern works or prevents regression.
292
+
293
+ ### 4.3 Silent Failure Tests (MISSING)
294
+
295
+ **Current State**: Found 1 intentional silent failure (documented).
296
+
297
+ **Gap**: No tests verify:
298
+ - No new silent failures introduced
299
+ - Existing silent failure has correct behavior
300
+ - Errors are logged before being swallowed
301
+
302
+ ---
303
+
304
+ ## 5. Identified Gaps
305
+
306
+ ### 5.1 Critical Gaps
307
+
308
+ 1. **Error Handler Not Tested**
309
+ - File: `src/cli/error-handler.ts` (444 lines)
310
+ - Functions: `formatError`, `displayError`, `displayErrorDebug`, `createErrorHandler`
311
+ - Coverage: **0 dedicated tests**
312
+ - Risk: High - this is the CLI boundary where all errors are formatted
313
+
314
+ 2. **Command Error Flows Not Tested**
315
+ - 6 production uses of catchTags found
316
+ - 0 integration tests verify these work
317
+ - Risk: High - errors may not be caught correctly in production
318
+
319
+ 3. **OpenAI Provider Factory Not Tested**
320
+ - Static factory pattern implemented to fix constructor issue
321
+ - No test verifies ApiKeyMissingError is returned correctly
322
+ - Risk: Medium - could regress to throwing constructor
323
+
324
+ 4. **Error Recovery Not Tested**
325
+ - Fallback logic in search command (semantic β†’ keyword)
326
+ - Auto-indexing logic
327
+ - Risk: Medium - recovery may silently fail
328
+
329
+ ### 5.2 Important Gaps
330
+
331
+ 5. **Partial Success Scenarios**
332
+ - Indexing multiple files where some fail
333
+ - Batch embedding operations
334
+ - Risk: Medium - may lose data without user awareness
335
+
336
+ 6. **Error Code Display**
337
+ - E2E tests don't verify error codes shown
338
+ - No test for debug mode error display
339
+ - Risk: Low - but affects user experience
340
+
341
+ 7. **Silent Failure Regression Prevention**
342
+ - No automated check for new catchAll(() => succeed(null))
343
+ - Risk: Low - but was a major issue to fix
344
+
345
+ ### 5.3 Minor Gaps
346
+
347
+ 8. **Edge Cases**
348
+ - Unicode in paths
349
+ - Very long messages
350
+ - Nested cause chains
351
+ - Risk: Low - rare scenarios
352
+
353
+ 9. **Type-Level Verification**
354
+ - No test that compiler catches invalid error handling
355
+ - Risk: Low - TypeScript will catch at build time
356
+
357
+ ---
358
+
359
+ ## 6. Recommendations for Additional Tests
360
+
361
+ ### 6.1 High Priority (Must Have)
362
+
363
+ #### Test 1: Error Handler Formatting
364
+ ```typescript
365
+ // test/cli/error-handler.test.ts
366
+ describe('formatError', () => {
367
+ it('formats FileReadError correctly', () => {
368
+ const error = new FileReadError({
369
+ path: '/test.md',
370
+ message: 'ENOENT: no such file',
371
+ })
372
+ const formatted = formatError(error)
373
+ expect(formatted.code).toBe('E100')
374
+ expect(formatted.message).toContain('/test.md')
375
+ expect(formatted.exitCode).toBe(EXIT_CODE.SYSTEM_ERROR)
376
+ expect(formatted.suggestions).toBeDefined()
377
+ })
378
+
379
+ // Test all 14 error types...
380
+ })
381
+ ```
382
+
383
+ **Coverage**: Test formatError for all error types
384
+ **Estimate**: ~15 test cases
385
+
386
+ #### Test 2: Command Error Flow Integration
387
+ ```typescript
388
+ // test/cli/commands/search.test.ts
389
+ describe('search command error handling', () => {
390
+ it('handles IndexNotFoundError with helpful message', async () => {
391
+ // Mock index loading to fail
392
+ const result = await runCommand('search "test" /nonexistent')
393
+ expect(result.exitCode).toBe(1)
394
+ expect(result.stderr).toContain('E400')
395
+ expect(result.stderr).toContain('mdcontext index')
396
+ })
397
+
398
+ it('handles ApiKeyMissingError in semantic search', async () => {
399
+ // Test error when embeddings requested but no API key
400
+ })
401
+
402
+ it('falls back to keyword search when embeddings missing', async () => {
403
+ // Test graceful degradation
404
+ })
405
+ })
406
+ ```
407
+
408
+ **Coverage**: Test error paths in index, search, context commands
409
+ **Estimate**: ~20 test cases
410
+
411
+ #### Test 3: OpenAI Provider Factory
412
+ ```typescript
413
+ // test/embeddings/openai-provider.test.ts
414
+ describe('OpenAIProvider.create', () => {
415
+ it('returns ApiKeyMissingError when no key provided', async () => {
416
+ delete process.env.OPENAI_API_KEY
417
+ const result = await Effect.runPromise(
418
+ OpenAIProvider.create().pipe(
419
+ Effect.either
420
+ )
421
+ )
422
+ expect(result._tag).toBe('Left')
423
+ expect(result.left._tag).toBe('ApiKeyMissingError')
424
+ })
425
+
426
+ it('succeeds when API key provided', async () => {
427
+ const result = await Effect.runPromise(
428
+ OpenAIProvider.create({ apiKey: 'test-key' })
429
+ )
430
+ expect(result.name).toContain('openai')
431
+ })
432
+ })
433
+ ```
434
+
435
+ **Coverage**: Test factory pattern works correctly
436
+ **Estimate**: 3 test cases
437
+
438
+ ### 6.2 Medium Priority (Should Have)
439
+
440
+ #### Test 4: Error Recovery Scenarios
441
+ ```typescript
442
+ describe('error recovery', () => {
443
+ it('retries after transient network error', async () => {
444
+ // Mock network failure then success
445
+ })
446
+
447
+ it('falls back to keyword search after embedding error', async () => {
448
+ // Test fallback logic
449
+ })
450
+
451
+ it('continues indexing after single file failure', async () => {
452
+ // Test partial success
453
+ })
454
+ })
455
+ ```
456
+
457
+ **Coverage**: Test recovery and fallback logic
458
+ **Estimate**: ~10 test cases
459
+
460
+ #### Test 5: Error Code Display in E2E
461
+ ```typescript
462
+ describe('error display', () => {
463
+ it('shows error code in output', async () => {
464
+ const result = await runCommand('tree /nonexistent', { expectError: true })
465
+ expect(result.stderr).toMatch(/\[E\d{3}\]/)
466
+ })
467
+
468
+ it('shows suggestions for common errors', async () => {
469
+ const result = await runCommand('search "test"', { expectError: true })
470
+ expect(result.stderr).toContain('mdcontext index')
471
+ })
472
+ })
473
+ ```
474
+
475
+ **Coverage**: Verify error formatting in actual CLI output
476
+ **Estimate**: ~8 test cases
477
+
478
+ #### Test 6: Silent Failure Verification
479
+ ```typescript
480
+ describe('error logging', () => {
481
+ it('logs warning when catchAll used in estimateEmbeddingCost', async () => {
482
+ // Verify logged warning appears
483
+ })
484
+
485
+ it('utility function returns null on failure with documented reason', async () => {
486
+ // Test measureReduction fallback behavior
487
+ })
488
+ })
489
+ ```
490
+
491
+ **Coverage**: Test intentional silent failures are logged
492
+ **Estimate**: 2 test cases
493
+
494
+ ### 6.3 Low Priority (Nice to Have)
495
+
496
+ #### Test 7: Edge Cases
497
+ ```typescript
498
+ describe('error edge cases', () => {
499
+ it('handles very long error messages', () => {
500
+ const longMessage = 'x'.repeat(10000)
501
+ const error = new FileReadError({ path: '/test', message: longMessage })
502
+ const formatted = formatError(error)
503
+ expect(formatted.message).toBeDefined()
504
+ })
505
+
506
+ it('handles unicode in file paths', () => {
507
+ const error = new FileReadError({ path: '/path/with/Γ©mojis/πŸŽ‰.md', message: 'error' })
508
+ expect(formatError(error).message).toContain('πŸŽ‰')
509
+ })
510
+
511
+ it('preserves nested cause chains', () => {
512
+ const root = new Error('root cause')
513
+ const middle = new Error('middle', { cause: root })
514
+ const error = new FileReadError({ path: '/test', message: 'top', cause: middle })
515
+ expect(error.cause).toBe(middle)
516
+ })
517
+ })
518
+ ```
519
+
520
+ **Coverage**: Unusual but possible scenarios
521
+ **Estimate**: ~5 test cases
522
+
523
+ ---
524
+
525
+ ## 7. Summary Statistics
526
+
527
+ ### Current Test Coverage
528
+
529
+ | Category | Tests | Lines | Quality |
530
+ |----------|-------|-------|---------|
531
+ | Error Type Unit Tests | 50 | 610 | Excellent |
532
+ | Integration Tests | 1 | ~15 | Weak |
533
+ | E2E Error Tests | 2 | ~20 | Basic |
534
+ | **Total Error Tests** | **53** | **~645** | **Good** |
535
+
536
+ ### Recommended Additional Tests
537
+
538
+ | Priority | Category | Est. Tests | Est. Lines |
539
+ |----------|----------|------------|------------|
540
+ | High | Error Handler | 15 | ~300 |
541
+ | High | Command Integration | 20 | ~500 |
542
+ | High | Provider Factory | 3 | ~50 |
543
+ | Medium | Error Recovery | 10 | ~250 |
544
+ | Medium | Error Display E2E | 8 | ~150 |
545
+ | Medium | Silent Failure | 2 | ~40 |
546
+ | Low | Edge Cases | 5 | ~100 |
547
+ | **Total** | **63** | **~1,390** |
548
+
549
+ **Combined Total**: 116 error-related tests (~2,035 lines)
550
+
551
+ ---
552
+
553
+ ## 8. Final Assessment
554
+
555
+ ### Strengths
556
+ 1. βœ… Comprehensive unit test coverage for all error types
557
+ 2. βœ… Every error type has construction, _tag, code, and catchTag tests
558
+ 3. βœ… Error formatter uses Match.exhaustive for compiler safety
559
+ 4. βœ… OpenAI provider constructor issue properly fixed with factory pattern
560
+ 5. βœ… Silent error swallowing minimized and documented
561
+
562
+ ### Critical Issues
563
+ 1. ❌ Error handler has 0 dedicated tests (444 lines untested)
564
+ 2. ❌ Production catchTags usage not integration tested (6 instances)
565
+ 3. ❌ OpenAI factory pattern not tested (regression risk)
566
+ 4. ❌ Error recovery scenarios not tested
567
+ 5. ❌ No regression prevention for silent failures
568
+
569
+ ### Recommendation
570
+
571
+ **PASS with Major Conditions**:
572
+
573
+ The error handling **implementation** is excellent. The error handling **test coverage** is incomplete.
574
+
575
+ **Required before merge to main**:
576
+ 1. Add error handler tests (formatError, displayError) - **HIGH PRIORITY**
577
+ 2. Add command integration tests for error flows - **HIGH PRIORITY**
578
+ 3. Add OpenAI factory tests - **HIGH PRIORITY**
579
+
580
+ **Required before declaring complete**:
581
+ 4. Add error recovery tests - **MEDIUM PRIORITY**
582
+ 5. Add error display E2E tests - **MEDIUM PRIORITY**
583
+
584
+ **Recommended**:
585
+ 6. Add automated check for catchAll without logging (linter rule or test)
586
+ 7. Document test strategy for error handling in TESTING.md
587
+
588
+ ### Test Coverage Grade: **B-** (73/100)
589
+
590
+ - Unit tests: A+ (95/100)
591
+ - Integration tests: C (40/100)
592
+ - E2E tests: D+ (45/100)
593
+ - Regression prevention: C- (50/100)
594
+
595
+ **With recommended tests implemented: A- (88/100)**
596
+
597
+ ---
598
+
599
+ ## Appendix: Code References
600
+
601
+ ### Error Definitions
602
+ - Error types: `/Users/alphab/Dev/LLM/DEV/mdcontext/worktrees/nancy-ALP-76/src/errors/index.ts` (lines 1-484)
603
+ - Error codes: Lines 90-129
604
+
605
+ ### Error Handling
606
+ - Error handler: `/Users/alphab/Dev/LLM/DEV/mdcontext/worktrees/nancy-ALP-76/src/cli/error-handler.ts` (lines 1-444)
607
+ - Error formatter: Lines 74-287
608
+ - createErrorHandler: Lines 376-395
609
+
610
+ ### Production Usage
611
+ - search.ts catchTags: Lines 350-361, 392-404, 473-485
612
+ - index-cmd.ts catchTags: Lines 250-260, 303-313
613
+ - vector-store.ts catchTag: (not read in detail)
614
+
615
+ ### Tests
616
+ - Error unit tests: `/Users/alphab/Dev/LLM/DEV/mdcontext/worktrees/nancy-ALP-76/src/errors/errors.test.ts` (610 lines)
617
+ - CLI E2E tests: `/Users/alphab/Dev/LLM/DEV/mdcontext/worktrees/nancy-ALP-76/src/cli/cli.test.ts` (error tests at lines 355-369)
618
+
619
+ ### Silent Error Handling
620
+ - Documented catchAll: `/Users/alphab/Dev/LLM/DEV/mdcontext/worktrees/nancy-ALP-76/src/summarize/summarizer.ts` (lines 537-543)
621
+
622
+ ---
623
+
624
+ **Review Complete**
625
+ Next recommended action: Implement high-priority tests (Error Handler, Command Integration, Provider Factory)