claude-brain 0.15.2 → 0.16.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 (249) hide show
  1. package/README.md +191 -191
  2. package/VERSION +1 -1
  3. package/assets/CLAUDE-unified.md +11 -11
  4. package/assets/CLAUDE.md +29 -11
  5. package/bunfig.toml +8 -8
  6. package/package.json +82 -82
  7. package/packs/backend/node.json +173 -173
  8. package/packs/core/javascript.json +176 -176
  9. package/packs/core/typescript.json +222 -222
  10. package/packs/frontend/react.json +254 -254
  11. package/packs/meta/testing.json +172 -172
  12. package/scripts/postinstall.mjs +341 -341
  13. package/src/automation/auto-context.ts +240 -240
  14. package/src/automation/decision-detector.ts +452 -452
  15. package/src/automation/index.ts +11 -11
  16. package/src/automation/phase12-manager.ts +456 -456
  17. package/src/automation/proactive-recall.ts +373 -373
  18. package/src/automation/project-detector.ts +310 -310
  19. package/src/automation/repo-scanner.ts +205 -205
  20. package/src/cli/auto-setup.ts +82 -82
  21. package/src/cli/bin.ts +209 -202
  22. package/src/cli/commands/chroma.ts +573 -573
  23. package/src/cli/commands/git-hook.ts +189 -189
  24. package/src/cli/commands/hooks.ts +213 -213
  25. package/src/cli/commands/init.ts +122 -122
  26. package/src/cli/commands/install-mcp.ts +92 -92
  27. package/src/cli/commands/pack.ts +197 -197
  28. package/src/cli/commands/refresh.ts +323 -0
  29. package/src/cli/commands/serve.ts +167 -173
  30. package/src/cli/commands/start.ts +42 -42
  31. package/src/cli/commands/uninstall-mcp.ts +41 -41
  32. package/src/cli/commands/update.ts +124 -121
  33. package/src/cli/diagnose.ts +4 -4
  34. package/src/cli/health-check.ts +4 -4
  35. package/src/cli/migrate-chroma.ts +106 -106
  36. package/src/cli/setup.ts +4 -4
  37. package/src/cli/ui/animations.ts +80 -80
  38. package/src/cli/ui/components.ts +82 -82
  39. package/src/cli/ui/index.ts +4 -4
  40. package/src/cli/ui/logo.ts +36 -36
  41. package/src/cli/ui/theme.ts +55 -55
  42. package/src/config/defaults.ts +50 -50
  43. package/src/config/home.ts +55 -55
  44. package/src/config/index.ts +7 -7
  45. package/src/config/loader.ts +166 -166
  46. package/src/config/migration.ts +76 -76
  47. package/src/config/schema.ts +360 -360
  48. package/src/config/validator.ts +184 -184
  49. package/src/config/watcher.ts +86 -86
  50. package/src/context/assembler.ts +398 -398
  51. package/src/context/cache-manager.ts +101 -101
  52. package/src/context/formatter.ts +84 -84
  53. package/src/context/hierarchy.ts +85 -85
  54. package/src/context/index.ts +83 -83
  55. package/src/context/progress-tracker.ts +174 -174
  56. package/src/context/standards-manager.ts +287 -287
  57. package/src/context/types.ts +252 -252
  58. package/src/context/validator.ts +58 -58
  59. package/src/diagnostics/index.ts +123 -123
  60. package/src/health/index.ts +229 -229
  61. package/src/hooks/brain-hook.ts +128 -112
  62. package/src/hooks/capture.ts +168 -205
  63. package/src/hooks/deduplicator.ts +72 -72
  64. package/src/hooks/git-capture.ts +109 -109
  65. package/src/hooks/git-hook-installer.ts +207 -207
  66. package/src/hooks/index.ts +20 -20
  67. package/src/hooks/installer.ts +194 -194
  68. package/src/hooks/passive-classifier.ts +404 -723
  69. package/src/hooks/queue.ts +129 -129
  70. package/src/hooks/session-tracker.ts +312 -275
  71. package/src/hooks/types.ts +47 -47
  72. package/src/index.ts +7 -7
  73. package/src/intelligence/cross-project/affinity.ts +162 -162
  74. package/src/intelligence/cross-project/generalizer.ts +283 -283
  75. package/src/intelligence/cross-project/index.ts +13 -13
  76. package/src/intelligence/cross-project/transfer.ts +201 -201
  77. package/src/intelligence/index.ts +24 -24
  78. package/src/intelligence/optimization/index.ts +10 -10
  79. package/src/intelligence/optimization/precompute.ts +202 -202
  80. package/src/intelligence/optimization/semantic-cache.ts +207 -207
  81. package/src/intelligence/prediction/context-anticipator.ts +198 -198
  82. package/src/intelligence/prediction/decision-predictor.ts +184 -184
  83. package/src/intelligence/prediction/index.ts +13 -13
  84. package/src/intelligence/prediction/recommender.ts +268 -268
  85. package/src/intelligence/reasoning/chain-retrieval.ts +247 -247
  86. package/src/intelligence/reasoning/counterfactual.ts +248 -248
  87. package/src/intelligence/reasoning/index.ts +13 -13
  88. package/src/intelligence/reasoning/synthesizer.ts +169 -169
  89. package/src/intelligence/temporal/evolution.ts +197 -197
  90. package/src/intelligence/temporal/index.ts +16 -16
  91. package/src/intelligence/temporal/query-processor.ts +190 -190
  92. package/src/intelligence/temporal/timeline.ts +259 -259
  93. package/src/intelligence/temporal/trends.ts +263 -263
  94. package/src/knowledge/entity-extractor.ts +416 -416
  95. package/src/knowledge/graph/builder.ts +185 -185
  96. package/src/knowledge/graph/linker.ts +201 -201
  97. package/src/knowledge/graph/memory-graph.ts +359 -359
  98. package/src/knowledge/graph/schema.ts +99 -99
  99. package/src/knowledge/graph/search.ts +168 -168
  100. package/src/knowledge/relationship-extractor.ts +108 -108
  101. package/src/memory/chroma/client.ts +174 -174
  102. package/src/memory/chroma/collection-manager.ts +94 -94
  103. package/src/memory/chroma/config.ts +57 -57
  104. package/src/memory/chroma/embeddings.ts +155 -155
  105. package/src/memory/chroma/index.ts +82 -82
  106. package/src/memory/chroma/migration.ts +270 -270
  107. package/src/memory/chroma/schemas.ts +69 -69
  108. package/src/memory/chroma/search.ts +315 -315
  109. package/src/memory/chroma/store.ts +741 -741
  110. package/src/memory/consolidation/archiver.ts +164 -164
  111. package/src/memory/consolidation/merger.ts +186 -186
  112. package/src/memory/consolidation/scorer.ts +138 -138
  113. package/src/memory/context-builder.ts +236 -236
  114. package/src/memory/database.ts +169 -169
  115. package/src/memory/embedding-utils.ts +156 -156
  116. package/src/memory/embeddings.ts +226 -226
  117. package/src/memory/episodic/detector.ts +108 -108
  118. package/src/memory/episodic/manager.ts +351 -351
  119. package/src/memory/episodic/summarizer.ts +179 -179
  120. package/src/memory/episodic/types.ts +52 -52
  121. package/src/memory/index.ts +582 -582
  122. package/src/memory/knowledge-extractor.ts +455 -455
  123. package/src/memory/learning.ts +378 -378
  124. package/src/memory/patterns.ts +396 -396
  125. package/src/memory/schema.ts +88 -88
  126. package/src/memory/search.ts +309 -309
  127. package/src/memory/store.ts +787 -787
  128. package/src/memory/types.ts +121 -121
  129. package/src/orchestrator/coordinator.ts +272 -272
  130. package/src/orchestrator/decision-logger.ts +228 -228
  131. package/src/orchestrator/event-emitter.ts +198 -198
  132. package/src/orchestrator/event-queue.ts +184 -184
  133. package/src/orchestrator/handlers/base-handler.ts +70 -70
  134. package/src/orchestrator/handlers/context-handler.ts +73 -73
  135. package/src/orchestrator/handlers/decision-handler.ts +204 -204
  136. package/src/orchestrator/handlers/index.ts +10 -10
  137. package/src/orchestrator/handlers/status-handler.ts +131 -131
  138. package/src/orchestrator/handlers/task-handler.ts +171 -171
  139. package/src/orchestrator/index.ts +275 -275
  140. package/src/orchestrator/task-parser.ts +284 -284
  141. package/src/orchestrator/types.ts +98 -98
  142. package/src/packs/index.ts +9 -9
  143. package/src/packs/loader.ts +134 -134
  144. package/src/packs/manager.ts +204 -204
  145. package/src/packs/ranker.ts +78 -78
  146. package/src/packs/types.ts +81 -81
  147. package/src/phase12/index.ts +5 -5
  148. package/src/retrieval/bm25/index.ts +300 -300
  149. package/src/retrieval/bm25/tokenizer.ts +184 -184
  150. package/src/retrieval/feedback/adaptive.ts +223 -223
  151. package/src/retrieval/feedback/index.ts +16 -16
  152. package/src/retrieval/feedback/metrics.ts +223 -223
  153. package/src/retrieval/feedback/store.ts +283 -283
  154. package/src/retrieval/fusion/index.ts +194 -194
  155. package/src/retrieval/fusion/rrf.ts +163 -163
  156. package/src/retrieval/index.ts +12 -12
  157. package/src/retrieval/pipeline.ts +375 -375
  158. package/src/retrieval/query/expander.ts +198 -198
  159. package/src/retrieval/query/index.ts +27 -27
  160. package/src/retrieval/query/intent-classifier.ts +236 -236
  161. package/src/retrieval/query/temporal-parser.ts +295 -295
  162. package/src/retrieval/reranker/index.ts +188 -188
  163. package/src/retrieval/reranker/model.ts +95 -95
  164. package/src/retrieval/service.ts +125 -125
  165. package/src/retrieval/types.ts +162 -162
  166. package/src/routing/entity-extractor.ts +428 -428
  167. package/src/routing/intent-classifier.ts +450 -436
  168. package/src/routing/response-filter.ts +261 -258
  169. package/src/routing/router.ts +1441 -1322
  170. package/src/routing/search-engine.ts +515 -475
  171. package/src/routing/types.ts +94 -94
  172. package/src/scripts/health-check.ts +118 -118
  173. package/src/scripts/setup.ts +122 -122
  174. package/src/server/handlers/call-tool.ts +156 -156
  175. package/src/server/handlers/index.ts +9 -9
  176. package/src/server/handlers/list-tools.ts +35 -35
  177. package/src/server/handlers/tools/analyze-decision-evolution.ts +151 -151
  178. package/src/server/handlers/tools/auto-remember.ts +200 -200
  179. package/src/server/handlers/tools/brain.ts +85 -85
  180. package/src/server/handlers/tools/create-project.ts +135 -135
  181. package/src/server/handlers/tools/detect-trends.ts +144 -144
  182. package/src/server/handlers/tools/find-cross-project-patterns.ts +168 -168
  183. package/src/server/handlers/tools/get-activity-log.ts +194 -194
  184. package/src/server/handlers/tools/get-code-standards.ts +124 -124
  185. package/src/server/handlers/tools/get-corrections.ts +154 -154
  186. package/src/server/handlers/tools/get-decision-timeline.ts +172 -172
  187. package/src/server/handlers/tools/get-episode.ts +103 -103
  188. package/src/server/handlers/tools/get-patterns.ts +158 -158
  189. package/src/server/handlers/tools/get-phase12-status.ts +63 -63
  190. package/src/server/handlers/tools/get-project-context.ts +75 -75
  191. package/src/server/handlers/tools/get-recommendations.ts +145 -145
  192. package/src/server/handlers/tools/index.ts +31 -31
  193. package/src/server/handlers/tools/init-project.ts +757 -757
  194. package/src/server/handlers/tools/list-episodes.ts +90 -90
  195. package/src/server/handlers/tools/list-projects.ts +125 -125
  196. package/src/server/handlers/tools/rate-memory.ts +101 -101
  197. package/src/server/handlers/tools/recall-similar.ts +87 -87
  198. package/src/server/handlers/tools/recognize-pattern.ts +126 -126
  199. package/src/server/handlers/tools/record-correction.ts +125 -125
  200. package/src/server/handlers/tools/remember-decision.ts +153 -153
  201. package/src/server/handlers/tools/schemas.ts +253 -253
  202. package/src/server/handlers/tools/search-knowledge-graph.ts +102 -102
  203. package/src/server/handlers/tools/smart-context.ts +146 -146
  204. package/src/server/handlers/tools/update-progress.ts +131 -131
  205. package/src/server/handlers/tools/what-if-analysis.ts +135 -135
  206. package/src/server/http-api.ts +693 -693
  207. package/src/server/index.ts +40 -40
  208. package/src/server/mcp-server.ts +283 -283
  209. package/src/server/providers/index.ts +7 -7
  210. package/src/server/providers/prompts.ts +327 -327
  211. package/src/server/providers/resources.ts +622 -622
  212. package/src/server/services.ts +468 -468
  213. package/src/server/types.ts +39 -39
  214. package/src/server/utils/error-handler.ts +155 -155
  215. package/src/server/utils/index.ts +13 -13
  216. package/src/server/utils/memory-indicator.ts +83 -83
  217. package/src/server/utils/request-context.ts +122 -122
  218. package/src/server/utils/response-formatter.ts +129 -129
  219. package/src/server/utils/validators.ts +210 -210
  220. package/src/setup/index.ts +48 -48
  221. package/src/setup/wizard.ts +461 -461
  222. package/src/tools/index.ts +24 -24
  223. package/src/tools/registry.ts +115 -115
  224. package/src/tools/schemas.test.ts +30 -30
  225. package/src/tools/schemas.ts +617 -617
  226. package/src/tools/types.ts +412 -412
  227. package/src/utils/circuit-breaker.ts +130 -130
  228. package/src/utils/cleanup.ts +34 -34
  229. package/src/utils/error-handler.ts +132 -132
  230. package/src/utils/error-messages.ts +60 -60
  231. package/src/utils/fallback.ts +45 -45
  232. package/src/utils/index.ts +54 -54
  233. package/src/utils/logger-utils.ts +80 -80
  234. package/src/utils/logger.ts +88 -88
  235. package/src/utils/phase12-helper.ts +56 -56
  236. package/src/utils/retry.ts +94 -94
  237. package/src/utils/timing.ts +47 -47
  238. package/src/utils/transaction.ts +63 -63
  239. package/src/vault/frontmatter.ts +264 -264
  240. package/src/vault/index.ts +318 -318
  241. package/src/vault/paths.ts +106 -106
  242. package/src/vault/query.ts +422 -422
  243. package/src/vault/reader.ts +264 -264
  244. package/src/vault/templates.ts +186 -186
  245. package/src/vault/types.ts +73 -73
  246. package/src/vault/watcher.ts +277 -277
  247. package/src/vault/writer.ts +413 -413
  248. package/tsconfig.json +30 -30
  249. package/src/cli/auto-update.ts +0 -157
@@ -1,56 +1,56 @@
1
- /**
2
- * Phase 12 Helper
3
- * Utilities for checking Phase 12 availability
4
- * Allows Phase 6.5 to gracefully degrade if Phase 12 isn't fully implemented
5
- */
6
-
7
- import type { Phase12Manager } from '@/automation/phase12-manager'
8
-
9
- // Cache for Phase 12 availability check
10
- let phase12Available: boolean | null = null
11
-
12
- /**
13
- * Check if Phase 12 features are available
14
- */
15
- export function isPhase12Available(): boolean {
16
- if (phase12Available !== null) {
17
- return phase12Available
18
- }
19
-
20
- try {
21
- // Check if the module can be loaded
22
- require('@/automation/phase12-manager')
23
- phase12Available = true
24
- return true
25
- } catch {
26
- phase12Available = false
27
- return false
28
- }
29
- }
30
-
31
- /**
32
- * Get Phase 12 instance if available
33
- * Returns null if Phase 12 is not available or not initialized
34
- */
35
- export function getPhase12Instance(): Phase12Manager | null {
36
- try {
37
- // Import the service getter
38
- const { getPhase12Service, isServicesInitialized } = require('@/server/services')
39
-
40
- if (!isServicesInitialized()) {
41
- return null
42
- }
43
-
44
- return getPhase12Service()
45
- } catch {
46
- return null
47
- }
48
- }
49
-
50
- /**
51
- * Reset the Phase 12 availability cache
52
- * Useful for testing
53
- */
54
- export function resetPhase12Cache(): void {
55
- phase12Available = null
56
- }
1
+ /**
2
+ * Phase 12 Helper
3
+ * Utilities for checking Phase 12 availability
4
+ * Allows Phase 6.5 to gracefully degrade if Phase 12 isn't fully implemented
5
+ */
6
+
7
+ import type { Phase12Manager } from '@/automation/phase12-manager'
8
+
9
+ // Cache for Phase 12 availability check
10
+ let phase12Available: boolean | null = null
11
+
12
+ /**
13
+ * Check if Phase 12 features are available
14
+ */
15
+ export function isPhase12Available(): boolean {
16
+ if (phase12Available !== null) {
17
+ return phase12Available
18
+ }
19
+
20
+ try {
21
+ // Check if the module can be loaded
22
+ require('@/automation/phase12-manager')
23
+ phase12Available = true
24
+ return true
25
+ } catch {
26
+ phase12Available = false
27
+ return false
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Get Phase 12 instance if available
33
+ * Returns null if Phase 12 is not available or not initialized
34
+ */
35
+ export function getPhase12Instance(): Phase12Manager | null {
36
+ try {
37
+ // Import the service getter
38
+ const { getPhase12Service, isServicesInitialized } = require('@/server/services')
39
+
40
+ if (!isServicesInitialized()) {
41
+ return null
42
+ }
43
+
44
+ return getPhase12Service()
45
+ } catch {
46
+ return null
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Reset the Phase 12 availability cache
52
+ * Useful for testing
53
+ */
54
+ export function resetPhase12Cache(): void {
55
+ phase12Available = null
56
+ }
@@ -1,94 +1,94 @@
1
- import type { Logger } from 'pino'
2
-
3
- export interface RetryOptions {
4
- maxRetries: number
5
- initialDelay: number
6
- maxDelay: number
7
- backoffMultiplier: number
8
- retryCondition?: (error: Error) => boolean
9
- onRetry?: (error: Error, attempt: number) => void
10
- }
11
-
12
- export class RetryManager {
13
- private logger: Logger
14
-
15
- constructor(logger: Logger) {
16
- this.logger = logger.child({ component: 'retry-manager' })
17
- }
18
-
19
- async execute<T>(
20
- fn: () => Promise<T>,
21
- options: Partial<RetryOptions> = {}
22
- ): Promise<T> {
23
- const opts: RetryOptions = {
24
- maxRetries: 3,
25
- initialDelay: 1000,
26
- maxDelay: 30000,
27
- backoffMultiplier: 2,
28
- ...options
29
- }
30
-
31
- let lastError: Error | undefined
32
- let attempt = 0
33
-
34
- while (attempt <= opts.maxRetries) {
35
- try {
36
- return await fn()
37
-
38
- } catch (error) {
39
- lastError = error as Error
40
- attempt++
41
-
42
- if (attempt > opts.maxRetries) {
43
- this.logger.error(
44
- { error: lastError, attempts: attempt },
45
- 'Max retries exceeded'
46
- )
47
- throw lastError
48
- }
49
-
50
- if (opts.retryCondition && !opts.retryCondition(lastError)) {
51
- this.logger.debug(
52
- { error: lastError },
53
- 'Retry condition not met, not retrying'
54
- )
55
- throw lastError
56
- }
57
-
58
- const delay = Math.min(
59
- opts.initialDelay * Math.pow(opts.backoffMultiplier, attempt - 1),
60
- opts.maxDelay
61
- )
62
-
63
- this.logger.info(
64
- { error: lastError.message, attempt, delay },
65
- 'Retrying after delay'
66
- )
67
-
68
- if (opts.onRetry) {
69
- opts.onRetry(lastError, attempt)
70
- }
71
-
72
- await this.sleep(delay)
73
- }
74
- }
75
-
76
- throw lastError!
77
- }
78
-
79
- static isRetryableError(error: Error): boolean {
80
- if (error.message.includes('ECONNREFUSED')) return true
81
- if (error.message.includes('ETIMEDOUT')) return true
82
- if (error.message.includes('ENOTFOUND')) return true
83
- if (error.message.includes('SQLITE_BUSY')) return true
84
- if (error.message.includes('database is locked')) return true
85
- if (error.message.includes('EBUSY')) return true
86
- if (error.message.includes('EMFILE')) return true
87
-
88
- return false
89
- }
90
-
91
- private sleep(ms: number): Promise<void> {
92
- return new Promise(resolve => setTimeout(resolve, ms))
93
- }
94
- }
1
+ import type { Logger } from 'pino'
2
+
3
+ export interface RetryOptions {
4
+ maxRetries: number
5
+ initialDelay: number
6
+ maxDelay: number
7
+ backoffMultiplier: number
8
+ retryCondition?: (error: Error) => boolean
9
+ onRetry?: (error: Error, attempt: number) => void
10
+ }
11
+
12
+ export class RetryManager {
13
+ private logger: Logger
14
+
15
+ constructor(logger: Logger) {
16
+ this.logger = logger.child({ component: 'retry-manager' })
17
+ }
18
+
19
+ async execute<T>(
20
+ fn: () => Promise<T>,
21
+ options: Partial<RetryOptions> = {}
22
+ ): Promise<T> {
23
+ const opts: RetryOptions = {
24
+ maxRetries: 3,
25
+ initialDelay: 1000,
26
+ maxDelay: 30000,
27
+ backoffMultiplier: 2,
28
+ ...options
29
+ }
30
+
31
+ let lastError: Error | undefined
32
+ let attempt = 0
33
+
34
+ while (attempt <= opts.maxRetries) {
35
+ try {
36
+ return await fn()
37
+
38
+ } catch (error) {
39
+ lastError = error as Error
40
+ attempt++
41
+
42
+ if (attempt > opts.maxRetries) {
43
+ this.logger.error(
44
+ { error: lastError, attempts: attempt },
45
+ 'Max retries exceeded'
46
+ )
47
+ throw lastError
48
+ }
49
+
50
+ if (opts.retryCondition && !opts.retryCondition(lastError)) {
51
+ this.logger.debug(
52
+ { error: lastError },
53
+ 'Retry condition not met, not retrying'
54
+ )
55
+ throw lastError
56
+ }
57
+
58
+ const delay = Math.min(
59
+ opts.initialDelay * Math.pow(opts.backoffMultiplier, attempt - 1),
60
+ opts.maxDelay
61
+ )
62
+
63
+ this.logger.info(
64
+ { error: lastError.message, attempt, delay },
65
+ 'Retrying after delay'
66
+ )
67
+
68
+ if (opts.onRetry) {
69
+ opts.onRetry(lastError, attempt)
70
+ }
71
+
72
+ await this.sleep(delay)
73
+ }
74
+ }
75
+
76
+ throw lastError!
77
+ }
78
+
79
+ static isRetryableError(error: Error): boolean {
80
+ if (error.message.includes('ECONNREFUSED')) return true
81
+ if (error.message.includes('ETIMEDOUT')) return true
82
+ if (error.message.includes('ENOTFOUND')) return true
83
+ if (error.message.includes('SQLITE_BUSY')) return true
84
+ if (error.message.includes('database is locked')) return true
85
+ if (error.message.includes('EBUSY')) return true
86
+ if (error.message.includes('EMFILE')) return true
87
+
88
+ return false
89
+ }
90
+
91
+ private sleep(ms: number): Promise<void> {
92
+ return new Promise(resolve => setTimeout(resolve, ms))
93
+ }
94
+ }
@@ -1,47 +1,47 @@
1
- /**
2
- * Timing Utility
3
- * Phase 22: Wraps async operations with performance timing.
4
- * Logs warnings for operations exceeding 200ms.
5
- */
6
-
7
- const SLOW_THRESHOLD_MS = 200
8
-
9
- /**
10
- * Wrap an async operation with timing instrumentation.
11
- * Logs a warning if the operation exceeds 200ms.
12
- */
13
- export async function timed<T>(label: string, fn: () => Promise<T>): Promise<T> {
14
- const start = performance.now()
15
- try {
16
- const result = await fn()
17
- const elapsed = performance.now() - start
18
- if (elapsed > SLOW_THRESHOLD_MS) {
19
- // Use console.error to avoid interfering with MCP stdio
20
- console.error(`[SLOW] ${label}: ${Math.round(elapsed)}ms (budget: ${SLOW_THRESHOLD_MS}ms)`)
21
- }
22
- return result
23
- } catch (error) {
24
- const elapsed = performance.now() - start
25
- console.error(`[ERROR] ${label}: ${Math.round(elapsed)}ms — ${error instanceof Error ? error.message : 'unknown'}`)
26
- throw error
27
- }
28
- }
29
-
30
- /**
31
- * Synchronous version for non-async operations.
32
- */
33
- export function timedSync<T>(label: string, fn: () => T): T {
34
- const start = performance.now()
35
- try {
36
- const result = fn()
37
- const elapsed = performance.now() - start
38
- if (elapsed > SLOW_THRESHOLD_MS) {
39
- console.error(`[SLOW] ${label}: ${Math.round(elapsed)}ms (budget: ${SLOW_THRESHOLD_MS}ms)`)
40
- }
41
- return result
42
- } catch (error) {
43
- const elapsed = performance.now() - start
44
- console.error(`[ERROR] ${label}: ${Math.round(elapsed)}ms — ${error instanceof Error ? error.message : 'unknown'}`)
45
- throw error
46
- }
47
- }
1
+ /**
2
+ * Timing Utility
3
+ * Phase 22: Wraps async operations with performance timing.
4
+ * Logs warnings for operations exceeding 200ms.
5
+ */
6
+
7
+ const SLOW_THRESHOLD_MS = 200
8
+
9
+ /**
10
+ * Wrap an async operation with timing instrumentation.
11
+ * Logs a warning if the operation exceeds 200ms.
12
+ */
13
+ export async function timed<T>(label: string, fn: () => Promise<T>): Promise<T> {
14
+ const start = performance.now()
15
+ try {
16
+ const result = await fn()
17
+ const elapsed = performance.now() - start
18
+ if (elapsed > SLOW_THRESHOLD_MS) {
19
+ // Use console.error to avoid interfering with MCP stdio
20
+ console.error(`[SLOW] ${label}: ${Math.round(elapsed)}ms (budget: ${SLOW_THRESHOLD_MS}ms)`)
21
+ }
22
+ return result
23
+ } catch (error) {
24
+ const elapsed = performance.now() - start
25
+ console.error(`[ERROR] ${label}: ${Math.round(elapsed)}ms — ${error instanceof Error ? error.message : 'unknown'}`)
26
+ throw error
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Synchronous version for non-async operations.
32
+ */
33
+ export function timedSync<T>(label: string, fn: () => T): T {
34
+ const start = performance.now()
35
+ try {
36
+ const result = fn()
37
+ const elapsed = performance.now() - start
38
+ if (elapsed > SLOW_THRESHOLD_MS) {
39
+ console.error(`[SLOW] ${label}: ${Math.round(elapsed)}ms (budget: ${SLOW_THRESHOLD_MS}ms)`)
40
+ }
41
+ return result
42
+ } catch (error) {
43
+ const elapsed = performance.now() - start
44
+ console.error(`[ERROR] ${label}: ${Math.round(elapsed)}ms — ${error instanceof Error ? error.message : 'unknown'}`)
45
+ throw error
46
+ }
47
+ }
@@ -1,63 +1,63 @@
1
- import type { Logger } from 'pino'
2
-
3
- export class TransactionManager {
4
- private logger: Logger
5
- private operations: Array<() => Promise<void>> = []
6
- private rollbacks: Array<() => Promise<void>> = []
7
-
8
- constructor(logger: Logger) {
9
- this.logger = logger.child({ component: 'transaction-manager' })
10
- }
11
-
12
- add(
13
- operation: () => Promise<void>,
14
- rollback: () => Promise<void>
15
- ): void {
16
- this.operations.push(operation)
17
- this.rollbacks.unshift(rollback)
18
- }
19
-
20
- async execute(): Promise<void> {
21
- const executedCount = 0
22
-
23
- try {
24
- for (let i = 0; i < this.operations.length; i++) {
25
- await this.operations[i]()
26
- }
27
-
28
- this.logger.info(
29
- { operationCount: this.operations.length },
30
- 'Transaction completed successfully'
31
- )
32
-
33
- } catch (error) {
34
- this.logger.error(
35
- { error, executedCount },
36
- 'Transaction failed, rolling back'
37
- )
38
-
39
- await this.rollback()
40
- throw error
41
- }
42
- }
43
-
44
- private async rollback(): Promise<void> {
45
- for (const rollback of this.rollbacks) {
46
- try {
47
- await rollback()
48
- } catch (error) {
49
- this.logger.error(
50
- { error },
51
- 'Rollback operation failed'
52
- )
53
- }
54
- }
55
-
56
- this.logger.info('Rollback completed')
57
- }
58
-
59
- clear(): void {
60
- this.operations = []
61
- this.rollbacks = []
62
- }
63
- }
1
+ import type { Logger } from 'pino'
2
+
3
+ export class TransactionManager {
4
+ private logger: Logger
5
+ private operations: Array<() => Promise<void>> = []
6
+ private rollbacks: Array<() => Promise<void>> = []
7
+
8
+ constructor(logger: Logger) {
9
+ this.logger = logger.child({ component: 'transaction-manager' })
10
+ }
11
+
12
+ add(
13
+ operation: () => Promise<void>,
14
+ rollback: () => Promise<void>
15
+ ): void {
16
+ this.operations.push(operation)
17
+ this.rollbacks.unshift(rollback)
18
+ }
19
+
20
+ async execute(): Promise<void> {
21
+ const executedCount = 0
22
+
23
+ try {
24
+ for (let i = 0; i < this.operations.length; i++) {
25
+ await this.operations[i]()
26
+ }
27
+
28
+ this.logger.info(
29
+ { operationCount: this.operations.length },
30
+ 'Transaction completed successfully'
31
+ )
32
+
33
+ } catch (error) {
34
+ this.logger.error(
35
+ { error, executedCount },
36
+ 'Transaction failed, rolling back'
37
+ )
38
+
39
+ await this.rollback()
40
+ throw error
41
+ }
42
+ }
43
+
44
+ private async rollback(): Promise<void> {
45
+ for (const rollback of this.rollbacks) {
46
+ try {
47
+ await rollback()
48
+ } catch (error) {
49
+ this.logger.error(
50
+ { error },
51
+ 'Rollback operation failed'
52
+ )
53
+ }
54
+ }
55
+
56
+ this.logger.info('Rollback completed')
57
+ }
58
+
59
+ clear(): void {
60
+ this.operations = []
61
+ this.rollbacks = []
62
+ }
63
+ }