@vaporsoft/orc 0.1.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 (223) hide show
  1. package/LICENSE +6 -0
  2. package/README.md +178 -0
  3. package/dist/bin/orc.d.ts +3 -0
  4. package/dist/bin/orc.d.ts.map +1 -0
  5. package/dist/bin/orc.js +4 -0
  6. package/dist/bin/orc.js.map +1 -0
  7. package/dist/src/cli.d.ts +6 -0
  8. package/dist/src/cli.d.ts.map +1 -0
  9. package/dist/src/cli.js +28 -0
  10. package/dist/src/cli.js.map +1 -0
  11. package/dist/src/commands/init.d.ts +6 -0
  12. package/dist/src/commands/init.d.ts.map +1 -0
  13. package/dist/src/commands/init.js +58 -0
  14. package/dist/src/commands/init.js.map +1 -0
  15. package/dist/src/commands/start.d.ts +17 -0
  16. package/dist/src/commands/start.d.ts.map +1 -0
  17. package/dist/src/commands/start.js +146 -0
  18. package/dist/src/commands/start.js.map +1 -0
  19. package/dist/src/constants.d.ts +18 -0
  20. package/dist/src/constants.d.ts.map +1 -0
  21. package/dist/src/constants.js +42 -0
  22. package/dist/src/constants.js.map +1 -0
  23. package/dist/src/core/comment-categorizer.d.ts +20 -0
  24. package/dist/src/core/comment-categorizer.d.ts.map +1 -0
  25. package/dist/src/core/comment-categorizer.js +208 -0
  26. package/dist/src/core/comment-categorizer.js.map +1 -0
  27. package/dist/src/core/comment-fetcher.d.ts +37 -0
  28. package/dist/src/core/comment-fetcher.d.ts.map +1 -0
  29. package/dist/src/core/comment-fetcher.js +138 -0
  30. package/dist/src/core/comment-fetcher.js.map +1 -0
  31. package/dist/src/core/daemon.d.ts +92 -0
  32. package/dist/src/core/daemon.d.ts.map +1 -0
  33. package/dist/src/core/daemon.js +896 -0
  34. package/dist/src/core/daemon.js.map +1 -0
  35. package/dist/src/core/fix-executor.d.ts +50 -0
  36. package/dist/src/core/fix-executor.d.ts.map +1 -0
  37. package/dist/src/core/fix-executor.js +374 -0
  38. package/dist/src/core/fix-executor.js.map +1 -0
  39. package/dist/src/core/git-manager.d.ts +44 -0
  40. package/dist/src/core/git-manager.d.ts.map +1 -0
  41. package/dist/src/core/git-manager.js +230 -0
  42. package/dist/src/core/git-manager.js.map +1 -0
  43. package/dist/src/core/pilot-config.d.ts +18 -0
  44. package/dist/src/core/pilot-config.d.ts.map +1 -0
  45. package/dist/src/core/pilot-config.js +76 -0
  46. package/dist/src/core/pilot-config.js.map +1 -0
  47. package/dist/src/core/progress-store.d.ts +32 -0
  48. package/dist/src/core/progress-store.d.ts.map +1 -0
  49. package/dist/src/core/progress-store.js +106 -0
  50. package/dist/src/core/progress-store.js.map +1 -0
  51. package/dist/src/core/repo-config.d.ts +11 -0
  52. package/dist/src/core/repo-config.d.ts.map +1 -0
  53. package/dist/src/core/repo-config.js +168 -0
  54. package/dist/src/core/repo-config.js.map +1 -0
  55. package/dist/src/core/session-controller.d.ts +61 -0
  56. package/dist/src/core/session-controller.d.ts.map +1 -0
  57. package/dist/src/core/session-controller.js +926 -0
  58. package/dist/src/core/session-controller.js.map +1 -0
  59. package/dist/src/core/thread-responder.d.ts +28 -0
  60. package/dist/src/core/thread-responder.d.ts.map +1 -0
  61. package/dist/src/core/thread-responder.js +193 -0
  62. package/dist/src/core/thread-responder.js.map +1 -0
  63. package/dist/src/core/worktree-manager.d.ts +26 -0
  64. package/dist/src/core/worktree-manager.d.ts.map +1 -0
  65. package/dist/src/core/worktree-manager.js +189 -0
  66. package/dist/src/core/worktree-manager.js.map +1 -0
  67. package/dist/src/github/gh-client.d.ts +57 -0
  68. package/dist/src/github/gh-client.d.ts.map +1 -0
  69. package/dist/src/github/gh-client.js +236 -0
  70. package/dist/src/github/gh-client.js.map +1 -0
  71. package/dist/src/github/queries.d.ts +9 -0
  72. package/dist/src/github/queries.d.ts.map +1 -0
  73. package/dist/src/github/queries.js +152 -0
  74. package/dist/src/github/queries.js.map +1 -0
  75. package/dist/src/github/types.d.ts +114 -0
  76. package/dist/src/github/types.d.ts.map +1 -0
  77. package/dist/src/github/types.js +3 -0
  78. package/dist/src/github/types.js.map +1 -0
  79. package/dist/src/tui/App.d.ts +8 -0
  80. package/dist/src/tui/App.d.ts.map +1 -0
  81. package/dist/src/tui/App.js +407 -0
  82. package/dist/src/tui/App.js.map +1 -0
  83. package/dist/src/tui/components/ActivityPane.d.ts +7 -0
  84. package/dist/src/tui/components/ActivityPane.d.ts.map +1 -0
  85. package/dist/src/tui/components/ActivityPane.js +10 -0
  86. package/dist/src/tui/components/ActivityPane.js.map +1 -0
  87. package/dist/src/tui/components/DetailPanel.d.ts +15 -0
  88. package/dist/src/tui/components/DetailPanel.d.ts.map +1 -0
  89. package/dist/src/tui/components/DetailPanel.js +137 -0
  90. package/dist/src/tui/components/DetailPanel.js.map +1 -0
  91. package/dist/src/tui/components/DrillInOverlay.d.ts +13 -0
  92. package/dist/src/tui/components/DrillInOverlay.d.ts.map +1 -0
  93. package/dist/src/tui/components/DrillInOverlay.js +85 -0
  94. package/dist/src/tui/components/DrillInOverlay.js.map +1 -0
  95. package/dist/src/tui/components/ExpandedContent.d.ts +10 -0
  96. package/dist/src/tui/components/ExpandedContent.d.ts.map +1 -0
  97. package/dist/src/tui/components/ExpandedContent.js +99 -0
  98. package/dist/src/tui/components/ExpandedContent.js.map +1 -0
  99. package/dist/src/tui/components/Header.d.ts +12 -0
  100. package/dist/src/tui/components/Header.d.ts.map +1 -0
  101. package/dist/src/tui/components/Header.js +35 -0
  102. package/dist/src/tui/components/Header.js.map +1 -0
  103. package/dist/src/tui/components/HelpBar.d.ts +2 -0
  104. package/dist/src/tui/components/HelpBar.d.ts.map +1 -0
  105. package/dist/src/tui/components/HelpBar.js +11 -0
  106. package/dist/src/tui/components/HelpBar.js.map +1 -0
  107. package/dist/src/tui/components/KeybindLegend.d.ts +7 -0
  108. package/dist/src/tui/components/KeybindLegend.d.ts.map +1 -0
  109. package/dist/src/tui/components/KeybindLegend.js +53 -0
  110. package/dist/src/tui/components/KeybindLegend.js.map +1 -0
  111. package/dist/src/tui/components/LogPane.d.ts +11 -0
  112. package/dist/src/tui/components/LogPane.d.ts.map +1 -0
  113. package/dist/src/tui/components/LogPane.js +31 -0
  114. package/dist/src/tui/components/LogPane.js.map +1 -0
  115. package/dist/src/tui/components/SessionList.d.ts +14 -0
  116. package/dist/src/tui/components/SessionList.d.ts.map +1 -0
  117. package/dist/src/tui/components/SessionList.js +31 -0
  118. package/dist/src/tui/components/SessionList.js.map +1 -0
  119. package/dist/src/tui/components/SessionRow.d.ts +10 -0
  120. package/dist/src/tui/components/SessionRow.d.ts.map +1 -0
  121. package/dist/src/tui/components/SessionRow.js +52 -0
  122. package/dist/src/tui/components/SessionRow.js.map +1 -0
  123. package/dist/src/tui/components/SettingsPanel.d.ts +8 -0
  124. package/dist/src/tui/components/SettingsPanel.d.ts.map +1 -0
  125. package/dist/src/tui/components/SettingsPanel.js +191 -0
  126. package/dist/src/tui/components/SettingsPanel.js.map +1 -0
  127. package/dist/src/tui/components/StatusBadge.d.ts +9 -0
  128. package/dist/src/tui/components/StatusBadge.d.ts.map +1 -0
  129. package/dist/src/tui/components/StatusBadge.js +52 -0
  130. package/dist/src/tui/components/StatusBadge.js.map +1 -0
  131. package/dist/src/tui/components/Toolbar.d.ts +5 -0
  132. package/dist/src/tui/components/Toolbar.d.ts.map +1 -0
  133. package/dist/src/tui/components/Toolbar.js +2 -0
  134. package/dist/src/tui/components/Toolbar.js.map +1 -0
  135. package/dist/src/tui/components/comment-constants.d.ts +4 -0
  136. package/dist/src/tui/components/comment-constants.d.ts.map +1 -0
  137. package/dist/src/tui/components/comment-constants.js +15 -0
  138. package/dist/src/tui/components/comment-constants.js.map +1 -0
  139. package/dist/src/tui/hooks/logFlushUtils.d.ts +15 -0
  140. package/dist/src/tui/hooks/logFlushUtils.d.ts.map +1 -0
  141. package/dist/src/tui/hooks/logFlushUtils.js +33 -0
  142. package/dist/src/tui/hooks/logFlushUtils.js.map +1 -0
  143. package/dist/src/tui/hooks/useBranchLogs.d.ts +7 -0
  144. package/dist/src/tui/hooks/useBranchLogs.d.ts.map +1 -0
  145. package/dist/src/tui/hooks/useBranchLogs.js +58 -0
  146. package/dist/src/tui/hooks/useBranchLogs.js.map +1 -0
  147. package/dist/src/tui/hooks/useDaemonState.d.ts +19 -0
  148. package/dist/src/tui/hooks/useDaemonState.d.ts.map +1 -0
  149. package/dist/src/tui/hooks/useDaemonState.js +152 -0
  150. package/dist/src/tui/hooks/useDaemonState.js.map +1 -0
  151. package/dist/src/tui/hooks/useInitialDiscovery.d.ts +8 -0
  152. package/dist/src/tui/hooks/useInitialDiscovery.d.ts.map +1 -0
  153. package/dist/src/tui/hooks/useInitialDiscovery.js +31 -0
  154. package/dist/src/tui/hooks/useInitialDiscovery.js.map +1 -0
  155. package/dist/src/tui/hooks/useLogBuffer.d.ts +7 -0
  156. package/dist/src/tui/hooks/useLogBuffer.d.ts.map +1 -0
  157. package/dist/src/tui/hooks/useLogBuffer.js +52 -0
  158. package/dist/src/tui/hooks/useLogBuffer.js.map +1 -0
  159. package/dist/src/tui/hooks/useNextCheckCountdown.d.ts +7 -0
  160. package/dist/src/tui/hooks/useNextCheckCountdown.d.ts.map +1 -0
  161. package/dist/src/tui/hooks/useNextCheckCountdown.js +42 -0
  162. package/dist/src/tui/hooks/useNextCheckCountdown.js.map +1 -0
  163. package/dist/src/tui/hooks/useTerminalFocus.d.ts +9 -0
  164. package/dist/src/tui/hooks/useTerminalFocus.d.ts.map +1 -0
  165. package/dist/src/tui/hooks/useTerminalFocus.js +43 -0
  166. package/dist/src/tui/hooks/useTerminalFocus.js.map +1 -0
  167. package/dist/src/tui/theme.d.ts +32 -0
  168. package/dist/src/tui/theme.d.ts.map +1 -0
  169. package/dist/src/tui/theme.js +61 -0
  170. package/dist/src/tui/theme.js.map +1 -0
  171. package/dist/src/types/config.d.ts +35 -0
  172. package/dist/src/types/config.d.ts.map +1 -0
  173. package/dist/src/types/config.js +14 -0
  174. package/dist/src/types/config.js.map +1 -0
  175. package/dist/src/types/index.d.ts +107 -0
  176. package/dist/src/types/index.d.ts.map +1 -0
  177. package/dist/src/types/index.js +3 -0
  178. package/dist/src/types/index.js.map +1 -0
  179. package/dist/src/utils/concurrency.d.ts +7 -0
  180. package/dist/src/utils/concurrency.d.ts.map +1 -0
  181. package/dist/src/utils/concurrency.js +26 -0
  182. package/dist/src/utils/concurrency.js.map +1 -0
  183. package/dist/src/utils/format.d.ts +2 -0
  184. package/dist/src/utils/format.d.ts.map +1 -0
  185. package/dist/src/utils/format.js +8 -0
  186. package/dist/src/utils/format.js.map +1 -0
  187. package/dist/src/utils/logger.d.ts +39 -0
  188. package/dist/src/utils/logger.d.ts.map +1 -0
  189. package/dist/src/utils/logger.js +120 -0
  190. package/dist/src/utils/logger.js.map +1 -0
  191. package/dist/src/utils/notify.d.ts +6 -0
  192. package/dist/src/utils/notify.d.ts.map +1 -0
  193. package/dist/src/utils/notify.js +15 -0
  194. package/dist/src/utils/notify.js.map +1 -0
  195. package/dist/src/utils/open-terminal.d.ts +12 -0
  196. package/dist/src/utils/open-terminal.d.ts.map +1 -0
  197. package/dist/src/utils/open-terminal.js +93 -0
  198. package/dist/src/utils/open-terminal.js.map +1 -0
  199. package/dist/src/utils/process.d.ts +14 -0
  200. package/dist/src/utils/process.d.ts.map +1 -0
  201. package/dist/src/utils/process.js +36 -0
  202. package/dist/src/utils/process.js.map +1 -0
  203. package/dist/src/utils/project-detector.d.ts +12 -0
  204. package/dist/src/utils/project-detector.d.ts.map +1 -0
  205. package/dist/src/utils/project-detector.js +123 -0
  206. package/dist/src/utils/project-detector.js.map +1 -0
  207. package/dist/src/utils/quoting.d.ts +15 -0
  208. package/dist/src/utils/quoting.d.ts.map +1 -0
  209. package/dist/src/utils/quoting.js +39 -0
  210. package/dist/src/utils/quoting.js.map +1 -0
  211. package/dist/src/utils/retry.d.ts +14 -0
  212. package/dist/src/utils/retry.d.ts.map +1 -0
  213. package/dist/src/utils/retry.js +41 -0
  214. package/dist/src/utils/retry.js.map +1 -0
  215. package/dist/src/utils/settings.d.ts +14 -0
  216. package/dist/src/utils/settings.d.ts.map +1 -0
  217. package/dist/src/utils/settings.js +21 -0
  218. package/dist/src/utils/settings.js.map +1 -0
  219. package/dist/src/utils/time.d.ts +2 -0
  220. package/dist/src/utils/time.d.ts.map +1 -0
  221. package/dist/src/utils/time.js +5 -0
  222. package/dist/src/utils/time.js.map +1 -0
  223. package/package.json +73 -0
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Uses the Claude Code SDK to classify PR review comments by severity.
3
+ * Piggybacks on Claude Code's existing authentication (no separate API key needed).
4
+ */
5
+ import { query } from "@anthropic-ai/claude-agent-sdk";
6
+ import { logger } from "../utils/logger.js";
7
+ const ANALYSIS_PROMPT = `You are a code review comment analyzer. Given a PR review comment and its surrounding diff context, determine whether the comment is actionable and should be fixed.
8
+
9
+ Classify the comment into one of these categories:
10
+ - must_fix: Clear bug, security issue, or breaking change that must be addressed
11
+ - should_fix: Valid improvement suggestion, style issue, or reasonable request (includes dead code, unused exports, unnecessary complexity)
12
+ - nice_to_have: Minor suggestion that could be skipped without issue
13
+ - needs_clarification: The comment raises a potentially valid concern but is too ambiguous to act on — you cannot determine what specific change the reviewer wants, or whether the concern applies without more context from the reviewer
14
+ - false_positive: The reviewer is factually wrong — the issue they describe does not exist in the code (e.g. they misread the code, the problem is already handled elsewhere, or the suggestion would break correct behavior)
15
+
16
+ ## Bias toward technical correctness
17
+
18
+ When a reviewer raises a concern that involves a real failure mode — data corruption, race conditions, missing transactions, incorrect error handling, silent data loss, security holes — lean toward should_fix or must_fix even if the current code "works most of the time." The fact that a bug is unlikely does not make the suggestion low-priority. Correctness concerns are cheap to fix now and expensive to debug later.
19
+
20
+ However, do NOT blindly escalate large architectural refactors that have no concrete failure mode. If a reviewer is pushing a pattern preference (e.g. "rewrite this to use the repository pattern", "this should use event sourcing") without identifying a specific bug or failure scenario, that is nice_to_have at most. The test: can the reviewer point to a realistic scenario where the current code produces a wrong result or fails? If yes, it's should_fix or higher. If the argument is purely about code aesthetics or architectural philosophy, it's nice_to_have.
21
+
22
+ ## Guarding against false dismissals
23
+
24
+ Be rigorous about false_positive. A comment is only a false positive if the reviewer's factual claim is incorrect. These are NOT false positives:
25
+ - Dead code or unused methods (even if they "might be useful later" — that is speculative)
26
+ - Style or naming improvements (these are valid suggestions)
27
+ - Requests to remove unnecessary complexity
28
+ - Suggestions the reviewer is correct about but that seem low-priority
29
+
30
+ When in doubt between false_positive and should_fix, choose should_fix.
31
+ When in doubt between nice_to_have and should_fix, consider whether a real failure mode exists.
32
+
33
+ Respond with JSON only (no markdown fences):
34
+ {
35
+ "confidence": <0.0-1.0>,
36
+ "category": "<must_fix|should_fix|nice_to_have|needs_clarification|false_positive>",
37
+ "reasoning": "<brief explanation>",
38
+ "suggestedAction": "<what the fix should do>",
39
+ "clarificationQuestion": "<only when category is needs_clarification: a specific, concise question to ask the reviewer>"
40
+ }`;
41
+ export class CommentCategorizer {
42
+ cwd;
43
+ confidenceThreshold;
44
+ constructor(cwd, confidenceThreshold = 0.75) {
45
+ this.cwd = cwd;
46
+ this.confidenceThreshold = confidenceThreshold;
47
+ }
48
+ async categorize(comments, abortSignal) {
49
+ const results = [];
50
+ let totalCostUsd = 0;
51
+ let totalInputTokens = 0;
52
+ let totalOutputTokens = 0;
53
+ for (const { thread, rawThread } of comments) {
54
+ if (abortSignal?.aborted)
55
+ break;
56
+ // Conversation comments lack diff context — delegate verification to fix executor
57
+ if (thread.path === "(conversation)") {
58
+ results.push({
59
+ threadId: thread.threadId,
60
+ path: thread.path,
61
+ line: thread.line,
62
+ body: thread.body,
63
+ author: thread.author,
64
+ diffHunk: thread.diffHunk,
65
+ category: "verify_and_fix",
66
+ confidence: 1.0,
67
+ reasoning: "Conversation comment — delegating verification to fix executor",
68
+ suggestedAction: "Verify and fix if applicable",
69
+ });
70
+ continue;
71
+ }
72
+ try {
73
+ const { analysis, costUsd, inputTokens, outputTokens } = await this.classifyComment(thread, abortSignal);
74
+ totalCostUsd += costUsd;
75
+ totalInputTokens += inputTokens;
76
+ totalOutputTokens += outputTokens;
77
+ // Cap clarifications at one round per thread: if Orc has already asked
78
+ // a clarification question, promote to should_fix instead of asking again.
79
+ // We detect prior clarification by looking for the signature marker in
80
+ // any previous Orc reply (rawThread contains all comments including Orc's).
81
+ const hasAskedClarification = rawThread?.comments.nodes.some((c) => /^\*Orc — needs_clarification \(confidence: [\d.]+\)\*$/m.test(c.body));
82
+ if (analysis.category === "needs_clarification" && hasAskedClarification) {
83
+ analysis.category = "should_fix";
84
+ analysis.reasoning = `[follow-up received — attempting fix] ${analysis.reasoning}`;
85
+ delete analysis.clarificationQuestion;
86
+ }
87
+ // Override low-confidence inline comments to verify_and_fix
88
+ // (but not needs_clarification — those should stay as-is)
89
+ if (analysis.confidence < this.confidenceThreshold &&
90
+ analysis.category !== "must_fix" &&
91
+ analysis.category !== "needs_clarification") {
92
+ results.push({
93
+ threadId: thread.threadId,
94
+ path: thread.path,
95
+ line: thread.line,
96
+ body: thread.body,
97
+ author: thread.author,
98
+ diffHunk: thread.diffHunk,
99
+ category: "verify_and_fix",
100
+ confidence: analysis.confidence,
101
+ reasoning: `[low confidence — verify] ${analysis.reasoning}`,
102
+ suggestedAction: analysis.suggestedAction,
103
+ });
104
+ }
105
+ else {
106
+ results.push({
107
+ threadId: thread.threadId,
108
+ path: thread.path,
109
+ line: thread.line,
110
+ body: thread.body,
111
+ author: thread.author,
112
+ diffHunk: thread.diffHunk,
113
+ ...analysis,
114
+ });
115
+ }
116
+ }
117
+ catch (err) {
118
+ logger.warn(`Failed to categorize comment ${thread.id}: ${err}`);
119
+ results.push({
120
+ threadId: thread.threadId,
121
+ path: thread.path,
122
+ line: thread.line,
123
+ body: thread.body,
124
+ author: thread.author,
125
+ diffHunk: thread.diffHunk,
126
+ confidence: 0.5,
127
+ category: "should_fix",
128
+ reasoning: "Analysis failed, defaulting to should_fix",
129
+ suggestedAction: thread.body,
130
+ });
131
+ }
132
+ }
133
+ return { comments: results, costUsd: totalCostUsd, inputTokens: totalInputTokens, outputTokens: totalOutputTokens };
134
+ }
135
+ async classifyComment(thread, abortSignal) {
136
+ const userMessage = `## File: ${thread.path}${thread.line ? ` (line ${thread.line})` : ""}
137
+
138
+ ### Diff Context:
139
+ \`\`\`
140
+ ${thread.diffHunk}
141
+ \`\`\`
142
+
143
+ ### Review Comment (by @${thread.author}):
144
+ ${thread.body}`;
145
+ const prompt = `${ANALYSIS_PROMPT}\n\n${userMessage}`;
146
+ let resultText = "";
147
+ let costUsd = 0;
148
+ let inputTokens = 0;
149
+ let outputTokens = 0;
150
+ const ac = new AbortController();
151
+ if (abortSignal) {
152
+ abortSignal.addEventListener("abort", () => ac.abort(), { once: true });
153
+ }
154
+ const stream = query({
155
+ prompt,
156
+ options: {
157
+ maxTurns: 1,
158
+ allowedTools: [],
159
+ permissionMode: "bypassPermissions",
160
+ cwd: this.cwd,
161
+ abortController: ac,
162
+ },
163
+ });
164
+ for await (const message of stream) {
165
+ if (message.type === "result") {
166
+ const result = message;
167
+ costUsd = result.total_cost_usd ?? 0;
168
+ inputTokens = result.usage?.input_tokens ?? 0;
169
+ outputTokens = result.usage?.output_tokens ?? 0;
170
+ if (result.subtype === "success") {
171
+ resultText = result.result;
172
+ }
173
+ }
174
+ }
175
+ // Strip markdown fences if present
176
+ const cleaned = resultText.replace(/^```(?:json)?\n?/m, "").replace(/\n?```$/m, "").trim();
177
+ try {
178
+ const parsed = JSON.parse(cleaned);
179
+ return {
180
+ analysis: {
181
+ confidence: Number(parsed.confidence),
182
+ category: parsed.category,
183
+ reasoning: parsed.reasoning,
184
+ suggestedAction: parsed.suggestedAction,
185
+ ...(parsed.clarificationQuestion ? { clarificationQuestion: parsed.clarificationQuestion } : {}),
186
+ },
187
+ costUsd,
188
+ inputTokens,
189
+ outputTokens,
190
+ };
191
+ }
192
+ catch {
193
+ logger.warn(`Failed to parse categorization response: ${cleaned}`);
194
+ return {
195
+ analysis: {
196
+ confidence: 0.5,
197
+ category: "should_fix",
198
+ reasoning: "Failed to parse analysis response",
199
+ suggestedAction: thread.body,
200
+ },
201
+ costUsd,
202
+ inputTokens,
203
+ outputTokens,
204
+ };
205
+ }
206
+ }
207
+ }
208
+ //# sourceMappingURL=comment-categorizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-categorizer.js","sourceRoot":"","sources":["../../../src/core/comment-categorizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Fetches review comments from GitHub — both inline review threads
3
+ * and top-level PR conversation comments.
4
+ * Filters out resolved, outdated, and already-replied-to comments.
5
+ *
6
+ * Since Orc runs under the user's own GitHub account, we can't
7
+ * detect bot replies by author login. Instead we detect them by the
8
+ * "Orc" signature in the comment body.
9
+ */
10
+ import { GHClient } from "../github/gh-client.js";
11
+ import type { GHReviewThread } from "../github/types.js";
12
+ import type { ReviewThread } from "../types/index.js";
13
+ export interface FetchedComment {
14
+ thread: ReviewThread;
15
+ /** Present for inline review threads, null for PR conversation comments. */
16
+ rawThread: GHReviewThread | null;
17
+ }
18
+ export interface ThreadCounts {
19
+ resolved: number;
20
+ total: number;
21
+ }
22
+ export declare class CommentFetcher {
23
+ private ghClient;
24
+ private prNumber;
25
+ private branch;
26
+ constructor(ghClient: GHClient, prNumber: number, _botLogin: string, branch: string);
27
+ /** Fetch actionable comments and thread counts in a single pass. */
28
+ fetchWithCounts(): Promise<{
29
+ comments: FetchedComment[];
30
+ threadCounts: ThreadCounts;
31
+ }>;
32
+ /** Fetch all actionable comments: unresolved review threads + PR conversation comments. */
33
+ fetch(): Promise<FetchedComment[]>;
34
+ private filterActionableThreads;
35
+ private fetchPRConversationComments;
36
+ }
37
+ //# sourceMappingURL=comment-fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-fetcher.d.ts","sourceRoot":"","sources":["../../../src/core/comment-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAmBtD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,YAAY,CAAC;IACrB,4EAA4E;IAC5E,SAAS,EAAE,cAAc,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAMnF,oEAAoE;IAC9D,eAAe,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;QAAC,YAAY,EAAE,YAAY,CAAA;KAAE,CAAC;IAuB5F,2FAA2F;IACrF,KAAK,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAKxC,OAAO,CAAC,uBAAuB;YAqDjB,2BAA2B;CA+C1C"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Fetches review comments from GitHub — both inline review threads
3
+ * and top-level PR conversation comments.
4
+ * Filters out resolved, outdated, and already-replied-to comments.
5
+ *
6
+ * Since Orc runs under the user's own GitHub account, we can't
7
+ * detect bot replies by author login. Instead we detect them by the
8
+ * "Orc" signature in the comment body.
9
+ */
10
+ import { logger } from "../utils/logger.js";
11
+ import { containsQuotedComment } from "../utils/quoting.js";
12
+ /** Signature Orc leaves in every reply — e.g. "*Orc — bug_fix (confidence: 0.95)*" */
13
+ const BOT_SIGNATURE_RE = /^\*Orc — .+ \(confidence: [\d.]+\)\*$/m;
14
+ function isOrcReply(body) {
15
+ return BOT_SIGNATURE_RE.test(body);
16
+ }
17
+ /** Comments that are just bot mentions/commands (e.g. "@cursor review"). Not review feedback. */
18
+ function isBotCommand(body) {
19
+ const trimmed = body.trim();
20
+ // Matches "@something" optionally followed by a single word — e.g. "@cursor review", "@copilot fix"
21
+ return /^@\w+(\s+\w+)?$/.test(trimmed);
22
+ }
23
+ export class CommentFetcher {
24
+ ghClient;
25
+ prNumber;
26
+ branch;
27
+ constructor(ghClient, prNumber, _botLogin, branch) {
28
+ this.ghClient = ghClient;
29
+ this.prNumber = prNumber;
30
+ this.branch = branch;
31
+ }
32
+ /** Fetch actionable comments and thread counts in a single pass. */
33
+ async fetchWithCounts() {
34
+ const [allThreads, prComments] = await Promise.all([
35
+ this.ghClient.getReviewThreads(this.prNumber),
36
+ this.fetchPRConversationComments(),
37
+ ]);
38
+ // Count resolved/total from the full unfiltered list
39
+ let resolved = 0;
40
+ for (const thread of allThreads) {
41
+ if (thread.isResolved)
42
+ resolved++;
43
+ }
44
+ const threadCounts = { resolved, total: allThreads.length };
45
+ // Filter to actionable threads (same logic as fetchReviewThreads)
46
+ const threadComments = this.filterActionableThreads(allThreads);
47
+ const comments = [...threadComments, ...prComments];
48
+ logger.info(`Fetched ${comments.length} comments (${threadComments.length} inline, ${prComments.length} conversation)`, this.branch);
49
+ return { comments, threadCounts };
50
+ }
51
+ /** Fetch all actionable comments: unresolved review threads + PR conversation comments. */
52
+ async fetch() {
53
+ const { comments } = await this.fetchWithCounts();
54
+ return comments;
55
+ }
56
+ filterActionableThreads(threads) {
57
+ const results = [];
58
+ for (const thread of threads) {
59
+ if (thread.isResolved || thread.isOutdated)
60
+ continue;
61
+ const firstComment = thread.comments.nodes[0];
62
+ if (!firstComment)
63
+ continue;
64
+ // Skip threads where Orc has replied AND no new reviewer
65
+ // comments appeared after that reply. If a reviewer responds
66
+ // after Orc's last reply (keeping the thread unresolved), the
67
+ // thread should be picked up again.
68
+ const lastOrcReplyAt = thread.comments.nodes
69
+ .filter((c) => isOrcReply(c.body))
70
+ .reduce((latest, c) => (!latest || c.createdAt > latest ? c.createdAt : latest), null);
71
+ if (lastOrcReplyAt !== null &&
72
+ !thread.comments.nodes.some((c) => !isOrcReply(c.body) && c.createdAt > lastOrcReplyAt)) {
73
+ logger.debug(`Skipping thread ${thread.id} — already replied`, this.branch);
74
+ continue;
75
+ }
76
+ const body = thread.comments.nodes
77
+ .filter((c) => !isOrcReply(c.body))
78
+ .map((c) => c.body)
79
+ .join("\n\n---\n\n");
80
+ results.push({
81
+ thread: {
82
+ id: firstComment.id,
83
+ threadId: thread.id,
84
+ path: firstComment.path,
85
+ line: firstComment.line,
86
+ body,
87
+ author: firstComment.author.login,
88
+ isResolved: thread.isResolved,
89
+ diffHunk: firstComment.diffHunk,
90
+ createdAt: firstComment.createdAt,
91
+ },
92
+ rawThread: thread,
93
+ });
94
+ }
95
+ return results;
96
+ }
97
+ async fetchPRConversationComments() {
98
+ const comments = await this.ghClient.getPRComments(this.prNumber);
99
+ const results = [];
100
+ for (const comment of comments) {
101
+ // Skip Orc's own replies
102
+ if (isOrcReply(comment.body))
103
+ continue;
104
+ // Skip bot commands like "@cursor review" — not review feedback
105
+ if (isBotCommand(comment.body)) {
106
+ logger.debug(`Skipping PR comment ${comment.id} — bot command`, this.branch);
107
+ continue;
108
+ }
109
+ // Check if a later Orc reply addresses this specific comment.
110
+ // Orc quotes the original comment body in its replies, so match on
111
+ // that rather than a blanket timestamp comparison (which would
112
+ // falsely shadow unrelated comments posted before any Orc reply).
113
+ const alreadyReplied = comments.some((c) => isOrcReply(c.body) &&
114
+ c.createdAt > comment.createdAt &&
115
+ containsQuotedComment(c.body, comment.body));
116
+ if (alreadyReplied) {
117
+ logger.debug(`Skipping PR comment ${comment.id} — already replied`, this.branch);
118
+ continue;
119
+ }
120
+ results.push({
121
+ thread: {
122
+ id: comment.id,
123
+ threadId: comment.id,
124
+ path: "(conversation)",
125
+ line: null,
126
+ body: comment.body,
127
+ author: comment.author.login,
128
+ isResolved: false,
129
+ diffHunk: "",
130
+ createdAt: comment.createdAt,
131
+ },
132
+ rawThread: null,
133
+ });
134
+ }
135
+ return results;
136
+ }
137
+ }
138
+ //# sourceMappingURL=comment-fetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-fetcher.js","sourceRoot":"","sources":["../../../src/core/comment-fetcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Always-on daemon that discovers open PRs authored by the current user.
3
+ * PRs are discovered but not auto-started — the TUI controls which to run.
4
+ * Also fetches unresolved comment counts for the TUI badge.
5
+ */
6
+ import { EventEmitter } from "node:events";
7
+ import { SessionController } from "./session-controller.js";
8
+ import { type ThreadCounts } from "./comment-fetcher.js";
9
+ import { ProgressStore } from "./progress-store.js";
10
+ import type { Config } from "../types/config.js";
11
+ import type { BranchState, CIStatus, FailedCheck, ReviewThread, SessionMode } from "../types/index.js";
12
+ import type { GHPullRequest } from "../github/types.js";
13
+ export declare class Daemon extends EventEmitter {
14
+ private config;
15
+ private cwd;
16
+ private ghClient;
17
+ private worktreeManager;
18
+ private progressStore;
19
+ private sessions;
20
+ private discoveredPRs;
21
+ private commentCounts;
22
+ private commentThreads;
23
+ private threadCounts;
24
+ private lastStates;
25
+ private mergedPRs;
26
+ private ciStatuses;
27
+ private ciFailedChecks;
28
+ private conflictStatuses;
29
+ private running;
30
+ private abortController;
31
+ private botLogin;
32
+ private cachedNotificationSettings;
33
+ private isInitialDiscovery;
34
+ private nextCheckAt;
35
+ private skipNextSleep;
36
+ constructor(config: Config, cwd: string);
37
+ getProgressStore(): ProgressStore;
38
+ getSessions(): Map<string, SessionController>;
39
+ getDiscoveredPRs(): Map<string, GHPullRequest>;
40
+ getCommentCounts(): Map<string, number>;
41
+ getCommentThreads(): Map<string, ReviewThread[]>;
42
+ getThreadCounts(): Map<string, ThreadCounts>;
43
+ getLastStates(): Map<string, BranchState>;
44
+ getMergedPRs(): Map<string, {
45
+ pr: GHPullRequest;
46
+ mergedAt: number;
47
+ }>;
48
+ clearMergedPRs(): void;
49
+ hasCompletedInitialDiscovery(): boolean;
50
+ getNextCheckAt(): number | null;
51
+ getConfig(): Config;
52
+ updateConfig(partial: Partial<Config>): void;
53
+ getCIStatuses(): Map<string, CIStatus>;
54
+ getCIFailedChecks(): Map<string, FailedCheck[]>;
55
+ getConflictStatuses(): Map<string, string[]>;
56
+ private maybeNotify;
57
+ refreshNotificationSettings(): void;
58
+ isRunning(branch: string): boolean;
59
+ run(): Promise<void>;
60
+ refreshNow(): Promise<void>;
61
+ startBranch(branch: string, mode?: SessionMode): Promise<void>;
62
+ stopBranch(branch: string): Promise<void>;
63
+ startAll(mode?: SessionMode): Promise<void>;
64
+ watchBranch(branch: string): Promise<void>;
65
+ watchAll(): Promise<void>;
66
+ rebaseBranch(branch: string): Promise<void>;
67
+ /** Plain git rebase — no Claude. Reports conflicts without resolving them. */
68
+ rebaseBranchPlain(branch: string): Promise<void>;
69
+ resolveConflicts(branch: string, always: boolean): void;
70
+ dismissConflictResolution(branch: string): void;
71
+ stopAll(): Promise<void>;
72
+ private cancellableSleep;
73
+ stop(): Promise<void>;
74
+ private discover;
75
+ private updateCommentCounts;
76
+ private launchSession;
77
+ private teardownSession;
78
+ private cleanupSession;
79
+ private setOptimisticStatus;
80
+ private makeErrorState;
81
+ private getCurrentBranch;
82
+ /** Extract CI check statuses from PR data (embedded in the discovery query). */
83
+ private updateCIStatusesFromPRs;
84
+ private updateCIStatus;
85
+ /** Set status to "ready" for branches with CI passing and 0 unresolved comments. */
86
+ private updateReadyStatuses;
87
+ /** Detect merge conflicts with base branch for all discovered PRs not actively running. */
88
+ private updateConflictStatuses;
89
+ /** Fetch the pushed branch and update the local ref so git log stays current. */
90
+ private syncMainRepo;
91
+ }
92
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/core/daemon.ts"],"names":[],"mappings":"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"}