@in-the-loop-labs/pair-review 1.0.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 (91) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +371 -0
  3. package/bin/git-diff-lines +146 -0
  4. package/bin/pair-review.js +49 -0
  5. package/package.json +71 -0
  6. package/public/css/ai-summary-modal.css +183 -0
  7. package/public/css/pr.css +8698 -0
  8. package/public/css/repo-settings.css +891 -0
  9. package/public/css/styles.css +479 -0
  10. package/public/favicon.png +0 -0
  11. package/public/index.html +1104 -0
  12. package/public/js/components/AIPanel.js +1639 -0
  13. package/public/js/components/AISummaryModal.js +278 -0
  14. package/public/js/components/AnalysisConfigModal.js +684 -0
  15. package/public/js/components/ConfirmDialog.js +227 -0
  16. package/public/js/components/PreviewModal.js +344 -0
  17. package/public/js/components/ProgressModal.js +678 -0
  18. package/public/js/components/ReviewModal.js +531 -0
  19. package/public/js/components/SplitButton.js +382 -0
  20. package/public/js/components/StatusIndicator.js +265 -0
  21. package/public/js/components/SuggestionNavigator.js +489 -0
  22. package/public/js/components/Toast.js +166 -0
  23. package/public/js/local.js +1580 -0
  24. package/public/js/modules/analysis-history.js +940 -0
  25. package/public/js/modules/comment-manager.js +643 -0
  26. package/public/js/modules/diff-renderer.js +585 -0
  27. package/public/js/modules/file-comment-manager.js +1242 -0
  28. package/public/js/modules/gap-coordinates.js +190 -0
  29. package/public/js/modules/hunk-parser.js +358 -0
  30. package/public/js/modules/line-tracker.js +386 -0
  31. package/public/js/modules/panel-resizer.js +228 -0
  32. package/public/js/modules/storage-cleanup.js +36 -0
  33. package/public/js/modules/suggestion-manager.js +692 -0
  34. package/public/js/pr.js +3503 -0
  35. package/public/js/repo-settings.js +691 -0
  36. package/public/js/utils/file-order.js +87 -0
  37. package/public/js/utils/markdown.js +97 -0
  38. package/public/js/utils/suggestion-ui.js +55 -0
  39. package/public/js/utils/tier-icons.js +25 -0
  40. package/public/local.html +460 -0
  41. package/public/pr.html +329 -0
  42. package/public/repo-settings.html +243 -0
  43. package/src/ai/analyzer.js +2592 -0
  44. package/src/ai/claude-cli.js +153 -0
  45. package/src/ai/claude-provider.js +261 -0
  46. package/src/ai/codex-provider.js +361 -0
  47. package/src/ai/copilot-provider.js +345 -0
  48. package/src/ai/gemini-provider.js +375 -0
  49. package/src/ai/index.js +47 -0
  50. package/src/ai/prompts/baseline/_meta.json +14 -0
  51. package/src/ai/prompts/baseline/level1/balanced.js +239 -0
  52. package/src/ai/prompts/baseline/level1/fast.js +194 -0
  53. package/src/ai/prompts/baseline/level1/thorough.js +319 -0
  54. package/src/ai/prompts/baseline/level2/balanced.js +248 -0
  55. package/src/ai/prompts/baseline/level2/fast.js +201 -0
  56. package/src/ai/prompts/baseline/level2/thorough.js +367 -0
  57. package/src/ai/prompts/baseline/level3/balanced.js +280 -0
  58. package/src/ai/prompts/baseline/level3/fast.js +220 -0
  59. package/src/ai/prompts/baseline/level3/thorough.js +459 -0
  60. package/src/ai/prompts/baseline/orchestration/balanced.js +259 -0
  61. package/src/ai/prompts/baseline/orchestration/fast.js +213 -0
  62. package/src/ai/prompts/baseline/orchestration/thorough.js +446 -0
  63. package/src/ai/prompts/config.js +52 -0
  64. package/src/ai/prompts/index.js +267 -0
  65. package/src/ai/prompts/shared/diff-instructions.js +50 -0
  66. package/src/ai/prompts/shared/output-schema.js +179 -0
  67. package/src/ai/prompts/shared/valid-files.js +37 -0
  68. package/src/ai/provider.js +260 -0
  69. package/src/config.js +139 -0
  70. package/src/database.js +2284 -0
  71. package/src/git/gitattributes.js +207 -0
  72. package/src/git/worktree.js +688 -0
  73. package/src/github/client.js +893 -0
  74. package/src/github/parser.js +247 -0
  75. package/src/local-review.js +691 -0
  76. package/src/main.js +987 -0
  77. package/src/routes/analysis.js +897 -0
  78. package/src/routes/comments.js +534 -0
  79. package/src/routes/config.js +250 -0
  80. package/src/routes/local.js +1728 -0
  81. package/src/routes/pr.js +1164 -0
  82. package/src/routes/shared.js +218 -0
  83. package/src/routes/worktrees.js +500 -0
  84. package/src/server.js +295 -0
  85. package/src/utils/diff-annotator.js +414 -0
  86. package/src/utils/instructions.js +33 -0
  87. package/src/utils/json-extractor.js +107 -0
  88. package/src/utils/line-validation.js +183 -0
  89. package/src/utils/logger.js +142 -0
  90. package/src/utils/paths.js +161 -0
  91. package/src/utils/stats-calculator.js +86 -0
@@ -0,0 +1,248 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ /**
3
+ * Level 2 Balanced Prompt - File Context Analysis
4
+ *
5
+ * This is the canonical baseline prompt for Level 2 analysis (file context).
6
+ * It uses tagged XML format to enable machine-readable optimization.
7
+ *
8
+ * Optimizations applied:
9
+ * - Added emphasis markers (**>>> CRITICAL: ... <<<**) for output requirements
10
+ * - Added explicit skip guidance for files without issues
11
+ * - Consolidated redundant focus areas
12
+ * - Restructured guidelines with clear priority ordering
13
+ *
14
+ * Section categories:
15
+ * - locked: Cannot be modified by variants (data integrity)
16
+ * - required: Must be present, content can be rephrased
17
+ * - optional: Can be removed entirely if unhelpful
18
+ */
19
+
20
+ // Note: Shared sections (valid-files, output-schema, diff-instructions) exist in ../shared/
21
+ // for future variant generation and consistency checking. Baseline prompts are self-contained
22
+ // with their own embedded section content to avoid runtime dependencies.
23
+
24
+ /**
25
+ * Tagged prompt template for Level 2 Balanced analysis
26
+ *
27
+ * Placeholders:
28
+ * - {{reviewIntro}} - Review introduction line
29
+ * - {{prContext}} - PR context section
30
+ * - {{customInstructions}} - Custom instructions section (optional)
31
+ * - {{lineNumberGuidance}} - Line number guidance section
32
+ * - {{generatedFiles}} - Generated files exclusion section (optional)
33
+ * - {{validFiles}} - List of valid files for suggestions
34
+ */
35
+ const taggedPrompt = `<section name="role" required="true">
36
+ {{reviewIntro}}
37
+ </section>
38
+
39
+ <section name="pr-context" locked="true">
40
+ {{prContext}}
41
+ </section>
42
+
43
+ <section name="custom-instructions" optional="true">
44
+ {{customInstructions}}
45
+ </section>
46
+
47
+ <section name="level-header" required="true">
48
+ # Level 2 Review - Analyze File Context
49
+ </section>
50
+
51
+ <section name="line-number-guidance" required="true">
52
+ {{lineNumberGuidance}}
53
+ </section>
54
+
55
+ <section name="generated-files" optional="true">
56
+ {{generatedFiles}}
57
+ </section>
58
+
59
+ <section name="valid-files" locked="true">
60
+ ## Valid Files for Suggestions
61
+ ONLY create suggestions for files in this list:
62
+ {{validFiles}}
63
+
64
+ Do NOT create suggestions for files not in this list. If no issues are found, return fewer suggestions - that's perfectly acceptable.
65
+ </section>
66
+
67
+ <section name="analysis-process" required="true">
68
+ ## Analysis Process
69
+ For each file with changes:
70
+ 1. Run the annotated diff tool to see changes with line numbers
71
+ 2. Read the full file content when context is needed
72
+ 3. Analyze how changes fit within the file's structure
73
+ 4. Focus on file-level patterns and consistency
74
+ 5. **Skip files where no file-level issues are found** - efficiency matters
75
+ </section>
76
+
77
+ <section name="focus-areas" required="true">
78
+ ## Focus Areas
79
+ Look for:
80
+ - Inconsistencies within files (naming, patterns, error handling)
81
+ - Missing related changes (if one part changed, what else should?)
82
+ - Security vulnerabilities in file context
83
+ - Style violations or pattern deviations
84
+ - Design pattern consistency
85
+ - Documentation completeness for file-level changes
86
+ - Good practices worth praising
87
+ </section>
88
+
89
+ <section name="available-commands" required="true">
90
+ ## Available Commands (READ-ONLY)
91
+ - Annotated diff tool (preferred for viewing changes with line numbers)
92
+ - \`cat -n <file>\` to view files with line numbers
93
+ - grep, find, ls commands as needed
94
+
95
+ Do NOT modify files. Your role is strictly to analyze and report findings.
96
+
97
+ Note: You may use parallel read-only Tasks to examine multiple files simultaneously.
98
+ </section>
99
+
100
+ <section name="output-schema" locked="true">
101
+ ## Output Format
102
+
103
+ **>>> CRITICAL: Output ONLY valid JSON. No markdown, no \`\`\`json blocks. Start with { end with }. <<<**
104
+
105
+ {
106
+ "level": 2,
107
+ "suggestions": [{
108
+ "file": "path/to/file",
109
+ "line": 42,
110
+ "old_or_new": "NEW",
111
+ "type": "bug|improvement|praise|suggestion|design|performance|security|code-style",
112
+ "title": "Brief title",
113
+ "description": "Explanation mentioning why full file context was needed",
114
+ "suggestion": "How to fix/improve (omit for praise items)",
115
+ "confidence": 0.0-1.0
116
+ }],
117
+ "fileLevelSuggestions": [{
118
+ "file": "path/to/file",
119
+ "type": "bug|improvement|praise|suggestion|design|performance|security|code-style",
120
+ "title": "File-level concern",
121
+ "description": "File-level observation (architecture, organization, naming, etc.)",
122
+ "suggestion": "How to address (omit for praise items)",
123
+ "confidence": 0.0-1.0
124
+ }],
125
+ "summary": "Brief summary of file context findings"
126
+ }
127
+ </section>
128
+
129
+ <section name="diff-instructions" required="true">
130
+ ## Line Number Reference (old_or_new field)
131
+ - **"NEW"** (default): For ADDED [+] lines and CONTEXT lines
132
+ - **"OLD"**: ONLY for DELETED [-] lines
133
+
134
+ Context lines exist in both old and new files - always use "NEW" for them.
135
+ When unsure, use "NEW" - it's correct for the vast majority of cases.
136
+ </section>
137
+
138
+ <section name="file-level-guidance" optional="true">
139
+ ## Line-Level vs File-Level Suggestions
140
+ Prefer line-level comments when issues can be anchored to specific lines. Use file-level suggestions only for observations that truly apply to the entire file.
141
+
142
+ File-level suggestions are appropriate for:
143
+ - Overall file architecture or organization
144
+ - Module naming conventions
145
+ - Missing tests for the file
146
+ - File structure improvements
147
+ - Module-level design patterns
148
+
149
+ File-level suggestions should NOT have a line number.
150
+ </section>
151
+
152
+ <section name="guidelines" required="true">
153
+ ## Guidelines
154
+
155
+ **Priority rules:**
156
+ 1. Skip files with no issues when considering full file context
157
+ 2. Anchor suggestions to specific lines when possible
158
+ 3. Use fileLevelSuggestions only for true file-wide concerns
159
+ 4. Focus on issues that require understanding full file context
160
+
161
+ **Output rules:**
162
+ - For "praise": omit the suggestion field
163
+ - For other types: include specific, actionable suggestions
164
+
165
+ **Confidence calibration:**
166
+ - High (0.8+): Clear issues you're certain about
167
+ - Medium (0.5-0.79): Likely issues with some uncertainty
168
+ - Lower: Prefer to omit marginal suggestions
169
+ </section>`;
170
+
171
+ /**
172
+ * Section definitions with metadata
173
+ * Used for parsing and validation
174
+ */
175
+ const sections = [
176
+ { name: 'role', required: true },
177
+ { name: 'pr-context', locked: true },
178
+ { name: 'custom-instructions', optional: true },
179
+ { name: 'level-header', required: true },
180
+ { name: 'line-number-guidance', required: true },
181
+ { name: 'generated-files', optional: true },
182
+ { name: 'valid-files', locked: true },
183
+ { name: 'analysis-process', required: true },
184
+ { name: 'focus-areas', required: true },
185
+ { name: 'available-commands', required: true },
186
+ { name: 'output-schema', locked: true },
187
+ { name: 'diff-instructions', required: true },
188
+ { name: 'file-level-guidance', optional: true },
189
+ { name: 'guidelines', required: true }
190
+ ];
191
+
192
+ /**
193
+ * Default section order for Level 2 Balanced
194
+ */
195
+ const defaultOrder = [
196
+ 'role',
197
+ 'pr-context',
198
+ 'custom-instructions',
199
+ 'level-header',
200
+ 'line-number-guidance',
201
+ 'generated-files',
202
+ 'valid-files',
203
+ 'analysis-process',
204
+ 'focus-areas',
205
+ 'available-commands',
206
+ 'output-schema',
207
+ 'diff-instructions',
208
+ 'file-level-guidance',
209
+ 'guidelines'
210
+ ];
211
+
212
+ /**
213
+ * Parse the tagged prompt into section objects
214
+ * @returns {Array<Object>} Array of section objects with name, attributes, and content
215
+ */
216
+ function parseSections() {
217
+ const sectionRegex = /<section\s+name="([^"]+)"([^>]*)>([\s\S]*?)<\/section>/g;
218
+ const parsed = [];
219
+ let match;
220
+
221
+ while ((match = sectionRegex.exec(taggedPrompt)) !== null) {
222
+ const [, name, attrs, content] = match;
223
+ const section = {
224
+ name,
225
+ content: content.trim(),
226
+ locked: attrs.includes('locked="true"'),
227
+ required: attrs.includes('required="true"'),
228
+ optional: attrs.includes('optional="true"')
229
+ };
230
+
231
+ // Extract tier attribute if present
232
+ const tierMatch = attrs.match(/tier="([^"]+)"/);
233
+ if (tierMatch) {
234
+ section.tier = tierMatch[1].split(',').map(t => t.trim());
235
+ }
236
+
237
+ parsed.push(section);
238
+ }
239
+
240
+ return parsed;
241
+ }
242
+
243
+ module.exports = {
244
+ taggedPrompt,
245
+ sections,
246
+ defaultOrder,
247
+ parseSections
248
+ };
@@ -0,0 +1,201 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ /**
3
+ * Level 2 Fast Prompt - File Context Analysis (Quick Review)
4
+ *
5
+ * This is the fast tier variant of Level 2 analysis. It is optimized for speed
6
+ * with shorter, more directive prompts and simplified instructions.
7
+ *
8
+ * Tier-specific optimizations applied:
9
+ * - Removed: file-level-guidance section (tier="balanced,thorough")
10
+ * - Simplified: focus-areas to essential checks only
11
+ * - Simplified: guidelines to core requirements
12
+ * - Shortened: available-commands to essentials
13
+ * - Shortened: analysis-process to key steps only
14
+ *
15
+ * Section categories:
16
+ * - locked: Cannot be modified by variants (data integrity)
17
+ * - required: Must be present, content can be rephrased
18
+ * - optional: Can be removed entirely if unhelpful
19
+ */
20
+
21
+ /**
22
+ * Tagged prompt template for Level 2 Fast analysis
23
+ *
24
+ * Placeholders:
25
+ * - {{reviewIntro}} - Review introduction line
26
+ * - {{prContext}} - PR context section
27
+ * - {{customInstructions}} - Custom instructions section (optional)
28
+ * - {{lineNumberGuidance}} - Line number guidance section
29
+ * - {{generatedFiles}} - Generated files exclusion section (optional)
30
+ * - {{validFiles}} - List of valid files for suggestions
31
+ */
32
+ const taggedPrompt = `<section name="role" required="true" tier="fast">
33
+ {{reviewIntro}}
34
+ </section>
35
+
36
+ <section name="pr-context" locked="true">
37
+ {{prContext}}
38
+ </section>
39
+
40
+ <section name="custom-instructions" optional="true" tier="fast,balanced,thorough">
41
+ {{customInstructions}}
42
+ </section>
43
+
44
+ <section name="level-header" required="true" tier="fast">
45
+ # Level 2 Review - Quick File Context Analysis
46
+ </section>
47
+
48
+ <section name="line-number-guidance" required="true" tier="fast">
49
+ {{lineNumberGuidance}}
50
+ </section>
51
+
52
+ <section name="generated-files" optional="true" tier="fast,balanced,thorough">
53
+ {{generatedFiles}}
54
+ </section>
55
+
56
+ <section name="valid-files" locked="true">
57
+ ## Valid Files
58
+ ONLY suggest for files in this list:
59
+ {{validFiles}}
60
+ </section>
61
+
62
+ <section name="analysis-process" required="true" tier="fast">
63
+ ## Steps
64
+ 1. Run annotated diff tool for changes with line numbers
65
+ 2. Read full file when context needed
66
+ 3. Anchor comments to specific lines
67
+ </section>
68
+
69
+ <section name="focus-areas" required="true" tier="fast">
70
+ ## Find
71
+ - File inconsistencies (naming, patterns, error handling)
72
+ - Missing related changes
73
+ - Security issues
74
+ - Style violations
75
+ - Good practices (praise)
76
+ </section>
77
+
78
+ <section name="available-commands" required="true" tier="fast">
79
+ ## Commands (READ-ONLY)
80
+ Annotated diff tool (preferred), \`cat -n <file>\`, ls, find, grep. Do NOT modify files.
81
+ </section>
82
+
83
+ <section name="output-schema" locked="true">
84
+ ## Output Format
85
+
86
+ **>>> CRITICAL: Output ONLY valid JSON. No markdown, no \`\`\`json blocks. Start with { end with }. <<<**
87
+
88
+ {
89
+ "level": 2,
90
+ "suggestions": [{
91
+ "file": "path/to/file",
92
+ "line": 42,
93
+ "old_or_new": "NEW",
94
+ "type": "bug|improvement|praise|suggestion|design|performance|security|code-style",
95
+ "title": "Brief title",
96
+ "description": "Why file context was needed",
97
+ "suggestion": "How to fix (omit for praise)",
98
+ "confidence": 0.0-1.0
99
+ }],
100
+ "fileLevelSuggestions": [{
101
+ "file": "path/to/file",
102
+ "type": "bug|improvement|praise|suggestion|design|performance|security|code-style",
103
+ "title": "File-level concern",
104
+ "description": "File-level observation",
105
+ "suggestion": "How to address (omit for praise)",
106
+ "confidence": 0.0-1.0
107
+ }],
108
+ "summary": "Brief summary"
109
+ }
110
+ </section>
111
+
112
+ <section name="diff-instructions" required="true" tier="fast">
113
+ ## Line Numbers
114
+ "NEW" (default): added [+] and context lines. "OLD": only deleted [-] lines.
115
+ </section>
116
+
117
+ <section name="guidelines" required="true" tier="fast">
118
+ ## Guidelines
119
+ - Anchor file-context issues to specific lines when possible
120
+ - Omit suggestion field for praise; include for all other types
121
+ - Only include confident suggestions
122
+ - Skip files with no issues to report
123
+ </section>`;
124
+
125
+ /**
126
+ * Section definitions with metadata
127
+ * Used for parsing and validation
128
+ */
129
+ const sections = [
130
+ { name: 'role', required: true, tier: ['fast'] },
131
+ { name: 'pr-context', locked: true },
132
+ { name: 'custom-instructions', optional: true, tier: ['fast', 'balanced', 'thorough'] },
133
+ { name: 'level-header', required: true, tier: ['fast'] },
134
+ { name: 'line-number-guidance', required: true, tier: ['fast'] },
135
+ { name: 'generated-files', optional: true, tier: ['fast', 'balanced', 'thorough'] },
136
+ { name: 'valid-files', locked: true },
137
+ { name: 'analysis-process', required: true, tier: ['fast'] },
138
+ { name: 'focus-areas', required: true, tier: ['fast'] },
139
+ { name: 'available-commands', required: true, tier: ['fast'] },
140
+ { name: 'output-schema', locked: true },
141
+ { name: 'diff-instructions', required: true, tier: ['fast'] },
142
+ { name: 'guidelines', required: true, tier: ['fast'] }
143
+ ];
144
+
145
+ /**
146
+ * Default section order for Level 2 Fast
147
+ * Note: Removed file-level-guidance section (tier="balanced,thorough")
148
+ */
149
+ const defaultOrder = [
150
+ 'role',
151
+ 'pr-context',
152
+ 'custom-instructions',
153
+ 'level-header',
154
+ 'line-number-guidance',
155
+ 'generated-files',
156
+ 'valid-files',
157
+ 'analysis-process',
158
+ 'focus-areas',
159
+ 'available-commands',
160
+ 'output-schema',
161
+ 'diff-instructions',
162
+ 'guidelines'
163
+ ];
164
+
165
+ /**
166
+ * Parse the tagged prompt into section objects
167
+ * @returns {Array<Object>} Array of section objects with name, attributes, and content
168
+ */
169
+ function parseSections() {
170
+ const sectionRegex = /<section\s+name="([^"]+)"([^>]*)>([\s\S]*?)<\/section>/g;
171
+ const parsed = [];
172
+ let match;
173
+
174
+ while ((match = sectionRegex.exec(taggedPrompt)) !== null) {
175
+ const [, name, attrs, content] = match;
176
+ const section = {
177
+ name,
178
+ content: content.trim(),
179
+ locked: attrs.includes('locked="true"'),
180
+ required: attrs.includes('required="true"'),
181
+ optional: attrs.includes('optional="true"')
182
+ };
183
+
184
+ // Extract tier attribute if present
185
+ const tierMatch = attrs.match(/tier="([^"]+)"/);
186
+ if (tierMatch) {
187
+ section.tier = tierMatch[1].split(',').map(t => t.trim());
188
+ }
189
+
190
+ parsed.push(section);
191
+ }
192
+
193
+ return parsed;
194
+ }
195
+
196
+ module.exports = {
197
+ taggedPrompt,
198
+ sections,
199
+ defaultOrder,
200
+ parseSections
201
+ };