mstro-app 0.5.1 → 0.5.6

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 (283) hide show
  1. package/PRIVACY.md +9 -9
  2. package/README.md +71 -28
  3. package/bin/commands/config.js +1 -1
  4. package/bin/mstro.js +55 -4
  5. package/dist/server/cli/eta-estimator.d.ts +55 -0
  6. package/dist/server/cli/eta-estimator.d.ts.map +1 -0
  7. package/dist/server/cli/eta-estimator.js +222 -0
  8. package/dist/server/cli/eta-estimator.js.map +1 -0
  9. package/dist/server/cli/headless/claude-invoker-process.d.ts.map +1 -1
  10. package/dist/server/cli/headless/claude-invoker-process.js +9 -1
  11. package/dist/server/cli/headless/claude-invoker-process.js.map +1 -1
  12. package/dist/server/cli/headless/mcp-config.d.ts +22 -5
  13. package/dist/server/cli/headless/mcp-config.d.ts.map +1 -1
  14. package/dist/server/cli/headless/mcp-config.js +7 -5
  15. package/dist/server/cli/headless/mcp-config.js.map +1 -1
  16. package/dist/server/cli/headless/runner.d.ts.map +1 -1
  17. package/dist/server/cli/headless/runner.js +19 -0
  18. package/dist/server/cli/headless/runner.js.map +1 -1
  19. package/dist/server/cli/headless/stall-assessor.d.ts +50 -0
  20. package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
  21. package/dist/server/cli/headless/stall-assessor.js +64 -9
  22. package/dist/server/cli/headless/stall-assessor.js.map +1 -1
  23. package/dist/server/cli/headless/tool-watchdog.d.ts +21 -0
  24. package/dist/server/cli/headless/tool-watchdog.d.ts.map +1 -1
  25. package/dist/server/cli/headless/tool-watchdog.js +19 -12
  26. package/dist/server/cli/headless/tool-watchdog.js.map +1 -1
  27. package/dist/server/cli/headless/types.d.ts +16 -1
  28. package/dist/server/cli/headless/types.d.ts.map +1 -1
  29. package/dist/server/cli/improvisation-history-store.d.ts.map +1 -1
  30. package/dist/server/cli/improvisation-history-store.js +5 -1
  31. package/dist/server/cli/improvisation-history-store.js.map +1 -1
  32. package/dist/server/cli/improvisation-output-queue.d.ts +5 -1
  33. package/dist/server/cli/improvisation-output-queue.d.ts.map +1 -1
  34. package/dist/server/cli/improvisation-output-queue.js +30 -7
  35. package/dist/server/cli/improvisation-output-queue.js.map +1 -1
  36. package/dist/server/cli/improvisation-session-manager.d.ts +35 -0
  37. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
  38. package/dist/server/cli/improvisation-session-manager.js +58 -1
  39. package/dist/server/cli/improvisation-session-manager.js.map +1 -1
  40. package/dist/server/cli/improvisation-types.d.ts +9 -0
  41. package/dist/server/cli/improvisation-types.d.ts.map +1 -1
  42. package/dist/server/cli/improvisation-types.js.map +1 -1
  43. package/dist/server/cli/retry/retry-runner-factory.d.ts.map +1 -1
  44. package/dist/server/cli/retry/retry-runner-factory.js +1 -0
  45. package/dist/server/cli/retry/retry-runner-factory.js.map +1 -1
  46. package/dist/server/engines/EngineEvent.d.ts +126 -0
  47. package/dist/server/engines/EngineEvent.d.ts.map +1 -0
  48. package/dist/server/engines/EngineEvent.js +11 -0
  49. package/dist/server/engines/EngineEvent.js.map +1 -0
  50. package/dist/server/engines/claude/ClaudeCodeEngine.d.ts +47 -0
  51. package/dist/server/engines/claude/ClaudeCodeEngine.d.ts.map +1 -0
  52. package/dist/server/engines/claude/ClaudeCodeEngine.js +338 -0
  53. package/dist/server/engines/claude/ClaudeCodeEngine.js.map +1 -0
  54. package/dist/server/engines/factory.d.ts +21 -0
  55. package/dist/server/engines/factory.d.ts.map +1 -0
  56. package/dist/server/engines/factory.js +152 -0
  57. package/dist/server/engines/factory.js.map +1 -0
  58. package/dist/server/engines/opencode/OpenCodeEngine.d.ts +148 -0
  59. package/dist/server/engines/opencode/OpenCodeEngine.d.ts.map +1 -0
  60. package/dist/server/engines/opencode/OpenCodeEngine.js +630 -0
  61. package/dist/server/engines/opencode/OpenCodeEngine.js.map +1 -0
  62. package/dist/server/engines/opencode/OpenCodeServerManager.d.ts +172 -0
  63. package/dist/server/engines/opencode/OpenCodeServerManager.d.ts.map +1 -0
  64. package/dist/server/engines/opencode/OpenCodeServerManager.js +390 -0
  65. package/dist/server/engines/opencode/OpenCodeServerManager.js.map +1 -0
  66. package/dist/server/engines/opencode/model-catalog.d.ts +94 -0
  67. package/dist/server/engines/opencode/model-catalog.d.ts.map +1 -0
  68. package/dist/server/engines/opencode/model-catalog.js +141 -0
  69. package/dist/server/engines/opencode/model-catalog.js.map +1 -0
  70. package/dist/server/engines/types.d.ts +146 -0
  71. package/dist/server/engines/types.d.ts.map +1 -0
  72. package/dist/server/engines/types.js +4 -0
  73. package/dist/server/engines/types.js.map +1 -0
  74. package/dist/server/index.js +9 -2
  75. package/dist/server/index.js.map +1 -1
  76. package/dist/server/mcp/bouncer-haiku.d.ts +17 -4
  77. package/dist/server/mcp/bouncer-haiku.d.ts.map +1 -1
  78. package/dist/server/mcp/bouncer-haiku.js +8 -124
  79. package/dist/server/mcp/bouncer-haiku.js.map +1 -1
  80. package/dist/server/mcp/bouncer-integration.d.ts +45 -0
  81. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
  82. package/dist/server/mcp/bouncer-integration.js +69 -5
  83. package/dist/server/mcp/bouncer-integration.js.map +1 -1
  84. package/dist/server/mcp/classifier/BouncerClassifier.d.ts +34 -0
  85. package/dist/server/mcp/classifier/BouncerClassifier.d.ts.map +1 -0
  86. package/dist/server/mcp/classifier/BouncerClassifier.js +4 -0
  87. package/dist/server/mcp/classifier/BouncerClassifier.js.map +1 -0
  88. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.d.ts +17 -0
  89. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.d.ts.map +1 -0
  90. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js +142 -0
  91. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js.map +1 -0
  92. package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.d.ts +68 -0
  93. package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.d.ts.map +1 -0
  94. package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.js +182 -0
  95. package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.js.map +1 -0
  96. package/dist/server/mcp/classifier/factory.d.ts +70 -0
  97. package/dist/server/mcp/classifier/factory.d.ts.map +1 -0
  98. package/dist/server/mcp/classifier/factory.js +155 -0
  99. package/dist/server/mcp/classifier/factory.js.map +1 -0
  100. package/dist/server/mcp/server.js +52 -0
  101. package/dist/server/mcp/server.js.map +1 -1
  102. package/dist/server/routes/index.d.ts +1 -0
  103. package/dist/server/routes/index.d.ts.map +1 -1
  104. package/dist/server/routes/index.js +1 -0
  105. package/dist/server/routes/index.js.map +1 -1
  106. package/dist/server/routes/internal.d.ts +16 -0
  107. package/dist/server/routes/internal.d.ts.map +1 -0
  108. package/dist/server/routes/internal.js +94 -0
  109. package/dist/server/routes/internal.js.map +1 -0
  110. package/dist/server/services/plan/agent-resolver.d.ts +26 -0
  111. package/dist/server/services/plan/agent-resolver.d.ts.map +1 -0
  112. package/dist/server/services/plan/agent-resolver.js +102 -0
  113. package/dist/server/services/plan/agent-resolver.js.map +1 -0
  114. package/dist/server/services/plan/composer.d.ts.map +1 -1
  115. package/dist/server/services/plan/composer.js +59 -11
  116. package/dist/server/services/plan/composer.js.map +1 -1
  117. package/dist/server/services/plan/executor.d.ts.map +1 -1
  118. package/dist/server/services/plan/executor.js +3 -1
  119. package/dist/server/services/plan/executor.js.map +1 -1
  120. package/dist/server/services/plan/issue-prompt-builder.d.ts.map +1 -1
  121. package/dist/server/services/plan/issue-prompt-builder.js +33 -1
  122. package/dist/server/services/plan/issue-prompt-builder.js.map +1 -1
  123. package/dist/server/services/plan/parser-core.d.ts.map +1 -1
  124. package/dist/server/services/plan/parser-core.js +1 -0
  125. package/dist/server/services/plan/parser-core.js.map +1 -1
  126. package/dist/server/services/plan/types.d.ts +1 -0
  127. package/dist/server/services/plan/types.d.ts.map +1 -1
  128. package/dist/server/services/runtime-info.d.ts +3 -0
  129. package/dist/server/services/runtime-info.d.ts.map +1 -0
  130. package/dist/server/services/runtime-info.js +21 -0
  131. package/dist/server/services/runtime-info.js.map +1 -0
  132. package/dist/server/services/settings.d.ts +76 -2
  133. package/dist/server/services/settings.d.ts.map +1 -1
  134. package/dist/server/services/settings.js +127 -4
  135. package/dist/server/services/settings.js.map +1 -1
  136. package/dist/server/services/websocket/ask-user-question-bridge.d.ts +32 -0
  137. package/dist/server/services/websocket/ask-user-question-bridge.d.ts.map +1 -0
  138. package/dist/server/services/websocket/ask-user-question-bridge.js +115 -0
  139. package/dist/server/services/websocket/ask-user-question-bridge.js.map +1 -0
  140. package/dist/server/services/websocket/git-branch-handlers.d.ts.map +1 -1
  141. package/dist/server/services/websocket/git-branch-handlers.js +19 -6
  142. package/dist/server/services/websocket/git-branch-handlers.js.map +1 -1
  143. package/dist/server/services/websocket/handler.d.ts +25 -1
  144. package/dist/server/services/websocket/handler.d.ts.map +1 -1
  145. package/dist/server/services/websocket/handler.js +84 -2
  146. package/dist/server/services/websocket/handler.js.map +1 -1
  147. package/dist/server/services/websocket/quality-complexity.d.ts.map +1 -1
  148. package/dist/server/services/websocket/quality-complexity.js +78 -26
  149. package/dist/server/services/websocket/quality-complexity.js.map +1 -1
  150. package/dist/server/services/websocket/quality-eta.d.ts +47 -0
  151. package/dist/server/services/websocket/quality-eta.d.ts.map +1 -0
  152. package/dist/server/services/websocket/quality-eta.js +110 -0
  153. package/dist/server/services/websocket/quality-eta.js.map +1 -0
  154. package/dist/server/services/websocket/quality-grading.d.ts +27 -4
  155. package/dist/server/services/websocket/quality-grading.d.ts.map +1 -1
  156. package/dist/server/services/websocket/quality-grading.js +369 -201
  157. package/dist/server/services/websocket/quality-grading.js.map +1 -1
  158. package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -1
  159. package/dist/server/services/websocket/quality-handlers.js +145 -7
  160. package/dist/server/services/websocket/quality-handlers.js.map +1 -1
  161. package/dist/server/services/websocket/quality-operations.d.ts +34 -0
  162. package/dist/server/services/websocket/quality-operations.d.ts.map +1 -0
  163. package/dist/server/services/websocket/quality-operations.js +47 -0
  164. package/dist/server/services/websocket/quality-operations.js.map +1 -0
  165. package/dist/server/services/websocket/quality-persistence.d.ts +9 -0
  166. package/dist/server/services/websocket/quality-persistence.d.ts.map +1 -1
  167. package/dist/server/services/websocket/quality-persistence.js +10 -0
  168. package/dist/server/services/websocket/quality-persistence.js.map +1 -1
  169. package/dist/server/services/websocket/quality-review-agent.d.ts +1 -1
  170. package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -1
  171. package/dist/server/services/websocket/quality-review-agent.js +105 -56
  172. package/dist/server/services/websocket/quality-review-agent.js.map +1 -1
  173. package/dist/server/services/websocket/quality-service.d.ts +9 -1
  174. package/dist/server/services/websocket/quality-service.d.ts.map +1 -1
  175. package/dist/server/services/websocket/quality-service.js +334 -14
  176. package/dist/server/services/websocket/quality-service.js.map +1 -1
  177. package/dist/server/services/websocket/quality-tools.d.ts +21 -0
  178. package/dist/server/services/websocket/quality-tools.d.ts.map +1 -1
  179. package/dist/server/services/websocket/quality-tools.js +49 -0
  180. package/dist/server/services/websocket/quality-tools.js.map +1 -1
  181. package/dist/server/services/websocket/quality-types.d.ts +35 -2
  182. package/dist/server/services/websocket/quality-types.d.ts.map +1 -1
  183. package/dist/server/services/websocket/quality-types.js +1 -1
  184. package/dist/server/services/websocket/quality-types.js.map +1 -1
  185. package/dist/server/services/websocket/session-handlers.d.ts +3 -1
  186. package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
  187. package/dist/server/services/websocket/session-handlers.js +60 -9
  188. package/dist/server/services/websocket/session-handlers.js.map +1 -1
  189. package/dist/server/services/websocket/session-history.js +3 -0
  190. package/dist/server/services/websocket/session-history.js.map +1 -1
  191. package/dist/server/services/websocket/session-initialization.d.ts.map +1 -1
  192. package/dist/server/services/websocket/session-initialization.js +158 -42
  193. package/dist/server/services/websocket/session-initialization.js.map +1 -1
  194. package/dist/server/services/websocket/session-registry.d.ts +25 -0
  195. package/dist/server/services/websocket/session-registry.d.ts.map +1 -1
  196. package/dist/server/services/websocket/session-registry.js +19 -0
  197. package/dist/server/services/websocket/session-registry.js.map +1 -1
  198. package/dist/server/services/websocket/settings-handlers.d.ts +1 -1
  199. package/dist/server/services/websocket/settings-handlers.d.ts.map +1 -1
  200. package/dist/server/services/websocket/settings-handlers.js +35 -4
  201. package/dist/server/services/websocket/settings-handlers.js.map +1 -1
  202. package/dist/server/services/websocket/tab-broadcast.d.ts +7 -2
  203. package/dist/server/services/websocket/tab-broadcast.d.ts.map +1 -1
  204. package/dist/server/services/websocket/tab-broadcast.js +10 -2
  205. package/dist/server/services/websocket/tab-broadcast.js.map +1 -1
  206. package/dist/server/services/websocket/tab-event-buffer.d.ts +97 -8
  207. package/dist/server/services/websocket/tab-event-buffer.d.ts.map +1 -1
  208. package/dist/server/services/websocket/tab-event-buffer.js +138 -12
  209. package/dist/server/services/websocket/tab-event-buffer.js.map +1 -1
  210. package/dist/server/services/websocket/tab-event-replay.d.ts +29 -13
  211. package/dist/server/services/websocket/tab-event-replay.d.ts.map +1 -1
  212. package/dist/server/services/websocket/tab-event-replay.js +55 -2
  213. package/dist/server/services/websocket/tab-event-replay.js.map +1 -1
  214. package/dist/server/services/websocket/tab-handlers.d.ts +9 -1
  215. package/dist/server/services/websocket/tab-handlers.d.ts.map +1 -1
  216. package/dist/server/services/websocket/tab-handlers.js +47 -2
  217. package/dist/server/services/websocket/tab-handlers.js.map +1 -1
  218. package/dist/server/services/websocket/types.d.ts +67 -7
  219. package/dist/server/services/websocket/types.d.ts.map +1 -1
  220. package/dist/server/services/websocket/types.js +12 -6
  221. package/dist/server/services/websocket/types.js.map +1 -1
  222. package/package.json +5 -3
  223. package/server/cli/eta-estimator.ts +249 -0
  224. package/server/cli/headless/claude-invoker-process.ts +9 -1
  225. package/server/cli/headless/mcp-config.ts +30 -5
  226. package/server/cli/headless/runner.ts +21 -0
  227. package/server/cli/headless/stall-assessor.ts +93 -0
  228. package/server/cli/headless/tool-watchdog.ts +21 -0
  229. package/server/cli/headless/types.ts +16 -1
  230. package/server/cli/improvisation-history-store.ts +4 -1
  231. package/server/cli/improvisation-output-queue.ts +29 -7
  232. package/server/cli/improvisation-session-manager.ts +63 -1
  233. package/server/cli/improvisation-types.ts +9 -0
  234. package/server/cli/retry/retry-runner-factory.ts +1 -0
  235. package/server/engines/EngineEvent.ts +156 -0
  236. package/server/engines/claude/ClaudeCodeEngine.ts +404 -0
  237. package/server/engines/factory.ts +176 -0
  238. package/server/engines/opencode/OpenCodeEngine.ts +786 -0
  239. package/server/engines/opencode/OpenCodeServerManager.ts +577 -0
  240. package/server/engines/opencode/model-catalog.ts +217 -0
  241. package/server/engines/types.ts +173 -0
  242. package/server/index.ts +9 -1
  243. package/server/mcp/bouncer-haiku.ts +21 -145
  244. package/server/mcp/bouncer-integration.ts +107 -5
  245. package/server/mcp/classifier/BouncerClassifier.ts +40 -0
  246. package/server/mcp/classifier/ClaudeBouncerClassifier.ts +189 -0
  247. package/server/mcp/classifier/OpenCodeBouncerClassifier.ts +305 -0
  248. package/server/mcp/classifier/factory.ts +195 -0
  249. package/server/mcp/server.ts +57 -0
  250. package/server/routes/index.ts +1 -0
  251. package/server/routes/internal.ts +112 -0
  252. package/server/services/plan/agent-resolver.ts +115 -0
  253. package/server/services/plan/agents/code-review.md +38 -8
  254. package/server/services/plan/composer.ts +63 -11
  255. package/server/services/plan/executor.ts +3 -1
  256. package/server/services/plan/issue-prompt-builder.ts +39 -1
  257. package/server/services/plan/parser-core.ts +1 -0
  258. package/server/services/plan/types.ts +4 -0
  259. package/server/services/runtime-info.ts +24 -0
  260. package/server/services/settings.ts +161 -4
  261. package/server/services/websocket/ask-user-question-bridge.ts +148 -0
  262. package/server/services/websocket/git-branch-handlers.ts +20 -6
  263. package/server/services/websocket/handler.ts +89 -2
  264. package/server/services/websocket/quality-complexity.ts +80 -26
  265. package/server/services/websocket/quality-eta.ts +155 -0
  266. package/server/services/websocket/quality-grading.ts +445 -222
  267. package/server/services/websocket/quality-handlers.ts +153 -7
  268. package/server/services/websocket/quality-operations.ts +72 -0
  269. package/server/services/websocket/quality-persistence.ts +17 -0
  270. package/server/services/websocket/quality-review-agent.ts +154 -64
  271. package/server/services/websocket/quality-service.ts +361 -13
  272. package/server/services/websocket/quality-tools.ts +51 -0
  273. package/server/services/websocket/quality-types.ts +41 -2
  274. package/server/services/websocket/session-handlers.ts +67 -10
  275. package/server/services/websocket/session-history.ts +3 -0
  276. package/server/services/websocket/session-initialization.ts +189 -46
  277. package/server/services/websocket/session-registry.ts +37 -0
  278. package/server/services/websocket/settings-handlers.ts +41 -4
  279. package/server/services/websocket/tab-broadcast.ts +10 -2
  280. package/server/services/websocket/tab-event-buffer.ts +143 -11
  281. package/server/services/websocket/tab-event-replay.ts +70 -3
  282. package/server/services/websocket/tab-handlers.ts +53 -5
  283. package/server/services/websocket/types.ts +85 -7
@@ -0,0 +1,110 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // ── Heuristic constants ──────────────────────────────────────
3
+ //
4
+ // Numbers tuned against typical TypeScript codebases (mstro cli/server/web)
5
+ // observed in the wild — see history.json for the corpus. Treat them as
6
+ // reasonable defaults that the history-based path will quickly correct once
7
+ // real durations land in storage.
8
+ /** Per-file overhead for a CLI scan (linting, formatting, file/function-length checks). */
9
+ const SCAN_PER_FILE_MS = 250;
10
+ /** Per-1000-LOC overhead for a CLI scan, dominated by `tsc --noEmit` on TS projects. */
11
+ const SCAN_PER_KLOC_MS = 800;
12
+ /** Fixed overhead per scan: tool detection, file collection, score computation. */
13
+ const SCAN_FIXED_MS = 8_000;
14
+ /** Floor — the smallest "I'm doing something" we should ever show. */
15
+ const SCAN_MIN_MS = 5_000;
16
+ /** Per-file overhead for the AI code-review agent (Claude Read calls, validation). */
17
+ const REVIEW_PER_FILE_MS = 1_200;
18
+ /** Per-1000-LOC overhead for the AI code-review agent. */
19
+ const REVIEW_PER_KLOC_MS = 2_500;
20
+ /** Fixed overhead per review: Claude spawn, prompt building, persistence. */
21
+ const REVIEW_FIXED_MS = 25_000;
22
+ /** Floor for the review estimate. */
23
+ const REVIEW_MIN_MS = 30_000;
24
+ // ── History smoothing ────────────────────────────────────────
25
+ //
26
+ // Use the last few real durations for the same directory and weight them by
27
+ // recency. A single one-off slow run shouldn't dominate the estimate, but
28
+ // fresh data should outweigh stale data (codebase grew, machine got faster,
29
+ // etc.).
30
+ const MAX_HISTORY_SAMPLES = 5;
31
+ function recentDurations(history, dirPath, field) {
32
+ const values = [];
33
+ // Walk newest → oldest; only consider entries that actually touched this directory.
34
+ for (let i = history.length - 1; i >= 0 && values.length < MAX_HISTORY_SAMPLES; i--) {
35
+ const entry = history[i];
36
+ if (!entry.directories.some((d) => d.path === dirPath))
37
+ continue;
38
+ const v = entry[field];
39
+ if (typeof v === 'number' && v > 0)
40
+ values.push(v);
41
+ }
42
+ return values;
43
+ }
44
+ /**
45
+ * Weighted average favouring newer samples. Weights are 1, 2, 3, 4, 5 for the
46
+ * 5 most-recent runs (newest first → highest weight) — a "this run mostly
47
+ * matters" curve that still smooths over a single anomaly.
48
+ */
49
+ function weightedRecentAverage(values) {
50
+ if (values.length === 0)
51
+ return null;
52
+ let weightSum = 0;
53
+ let valueSum = 0;
54
+ // values[0] is newest, so its weight is `values.length`.
55
+ for (let i = 0; i < values.length; i++) {
56
+ const w = values.length - i;
57
+ valueSum += values[i] * w;
58
+ weightSum += w;
59
+ }
60
+ return weightSum > 0 ? valueSum / weightSum : null;
61
+ }
62
+ /**
63
+ * Heuristic estimate for a CLI scan when we have no history. Combines a fixed
64
+ * floor with per-file + per-KLOC components — `tsc --noEmit` and lint scale
65
+ * with codebase size, so scaling on both files and lines maps reality better
66
+ * than scaling on either alone.
67
+ */
68
+ export function heuristicScanMs({ files, lines }) {
69
+ const kloc = Math.max(0, lines) / 1_000;
70
+ const raw = SCAN_FIXED_MS + files * SCAN_PER_FILE_MS + kloc * SCAN_PER_KLOC_MS;
71
+ return Math.max(SCAN_MIN_MS, Math.round(raw));
72
+ }
73
+ /** Heuristic estimate for the AI review agent when we have no history. */
74
+ export function heuristicReviewMs({ files, lines }) {
75
+ const kloc = Math.max(0, lines) / 1_000;
76
+ const raw = REVIEW_FIXED_MS + files * REVIEW_PER_FILE_MS + kloc * REVIEW_PER_KLOC_MS;
77
+ return Math.max(REVIEW_MIN_MS, Math.round(raw));
78
+ }
79
+ /**
80
+ * Best-available ETA for a CLI scan. Prefers a weighted average of recent
81
+ * durations for this exact directory; falls back to the heuristic when no
82
+ * timing history exists.
83
+ */
84
+ export function estimateScanMs(size, history, dirPath) {
85
+ const recent = recentDurations(history, dirPath, 'scanDurationMs');
86
+ const fromHistory = weightedRecentAverage(recent);
87
+ if (fromHistory !== null)
88
+ return Math.max(SCAN_MIN_MS, Math.round(fromHistory));
89
+ return heuristicScanMs(size);
90
+ }
91
+ /** Best-available ETA for the AI code-review agent. Same fallback shape as `estimateScanMs`. */
92
+ export function estimateReviewMs(size, history, dirPath) {
93
+ const recent = recentDurations(history, dirPath, 'reviewDurationMs');
94
+ const fromHistory = weightedRecentAverage(recent);
95
+ if (fromHistory !== null)
96
+ return Math.max(REVIEW_MIN_MS, Math.round(fromHistory));
97
+ return heuristicReviewMs(size);
98
+ }
99
+ /**
100
+ * Estimate codebase size from a directory using the same fast traversal the
101
+ * scan itself uses. Pulled out as a thin wrapper so the handler can call it
102
+ * before kicking off the scan to compute an initial ETA.
103
+ */
104
+ export async function estimateCodebaseSize(dirPath) {
105
+ const { collectSourceFiles } = await import('./quality-tools.js');
106
+ const files = await collectSourceFiles(dirPath, dirPath);
107
+ const lines = files.reduce((sum, f) => sum + f.lines, 0);
108
+ return { files: files.length, lines };
109
+ }
110
+ //# sourceMappingURL=quality-eta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality-eta.js","sourceRoot":"","sources":["../../../../server/services/websocket/quality-eta.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,10 @@
1
1
  export type DimensionName = 'security' | 'reliability' | 'maintainability';
2
- export type Grade = 'A' | 'B' | 'C' | 'D' | 'F' | 'N/A';
2
+ /**
3
+ * Letter grades. New code emits all variants except `'D'` (kept only for
4
+ * legacy reports persisted before the +/- rollout). See quality-types.ts for
5
+ * the score-band reference.
6
+ */
7
+ export type Grade = 'A+' | 'A' | 'A-' | 'B+' | 'B' | 'B-' | 'C+' | 'C' | 'C-' | 'D' | 'F+' | 'F' | 'F-' | 'N/A';
3
8
  type Severity = 'critical' | 'high' | 'medium' | 'low';
4
9
  export interface DimensionScore {
5
10
  name: DimensionName;
@@ -30,9 +35,27 @@ export interface QualityRating {
30
35
  */
31
36
  export declare function categoryToDimension(category: string): DimensionName;
32
37
  /**
33
- * Score-to-grade conversion used by legacy callers that still operate on a
34
- * single 0-100 number. The new multi-dimensional path computes grades
35
- * directly from finding shape; this remains for backward compatibility.
38
+ * Convert a 0-100 score to the full letter grade including +/- modifier.
39
+ *
40
+ * Within an A/B/C band, the band is split into thirds:
41
+ * X- bottom third (e.g., A-: 90-92)
42
+ * X middle third (e.g., A : 93-96)
43
+ * X+ top third (e.g., A+: 97-100)
44
+ *
45
+ * The F band uses two slices instead of three because there is no academic
46
+ * "F0" anchor and the user wanted F+/F/F-:
47
+ * F- 0-55 "critically broken"
48
+ * F 56-64 "broken"
49
+ * F+ 65-69 "barely failing"
50
+ *
51
+ * Compile/critical-severity hard caps are applied separately, not by score.
52
+ */
53
+ export declare function scoreToGrade(score: number): Grade;
54
+ /**
55
+ * Legacy single-letter conversion. Returns the *base* grade only (no
56
+ * modifier) for compatibility with callers that pre-date the +/- rollout
57
+ * (`scoreBreakdown.categoryPenalties[].grade`, etc.). New surfaces should
58
+ * call `scoreToGrade()` instead.
36
59
  */
37
60
  export declare function gradeFromScore(score: number): Grade;
38
61
  export declare function computeQualityRating(allFindings: Array<{
@@ -1 +1 @@
1
- {"version":3,"file":"quality-grading.d.ts","sourceRoot":"","sources":["../../../../server/services/websocket/quality-grading.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAC3E,MAAM,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC;AACxD,KAAK,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,QAAQ,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IACzC,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB;AAmBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAKnE;AAMD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAMnD;AAyaD,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1D,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;IAAE,mBAAmB,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAA;CAAE,GACnF,aAAa,CA6Bf"}
1
+ {"version":3,"file":"quality-grading.d.ts","sourceRoot":"","sources":["../../../../server/services/websocket/quality-grading.ts"],"names":[],"mappings":"AAqCA,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAE3E;;;;GAIG;AACH,MAAM,MAAM,KAAK,GACb,IAAI,GAAG,GAAG,GAAG,IAAI,GACjB,IAAI,GAAG,GAAG,GAAG,IAAI,GACjB,IAAI,GAAG,GAAG,GAAG,IAAI,GACjB,GAAG,GACH,IAAI,GAAG,GAAG,GAAG,IAAI,GACjB,KAAK,CAAC;AAKV,KAAK,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,QAAQ,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IACzC,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB;AAmBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAKnE;AA2BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAajD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAInD;AAgiBD,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1D,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;IAAE,mBAAmB,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAA;CAAE,GACnF,aAAa,CAiCf"}