cc-reviewer 2.0.0 → 3.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.
package/dist/handoff.js CHANGED
@@ -154,10 +154,11 @@ export function selectRole(focusAreas) {
154
154
  return CHANGE_FOCUSED_REVIEWER;
155
155
  }
156
156
  /**
157
- * Build the review prompt using minimal, targeted context
157
+ * Build the review prompt using minimal, targeted context.
158
+ * No output format constraints — reviewer responds naturally, CC interprets.
158
159
  */
159
160
  export function buildHandoffPrompt(options) {
160
- const { handoff, outputFormat } = options;
161
+ const { handoff } = options;
161
162
  const role = options.role || selectRole(handoff.focusAreas);
162
163
  const sections = [];
163
164
  // SECTION 1: ROLE
@@ -197,38 +198,6 @@ ${handoff.decisions.map((d, i) => `${i + 1}. **${d.decision}**
197
198
  if (handoff.priorityFiles && handoff.priorityFiles.length > 0) {
198
199
  sections.push(`## PRIORITY FILES\n\n${handoff.priorityFiles.map(f => `- \`${f}\``).join('\n')}`);
199
200
  }
200
- // SECTION 7: OUTPUT FORMAT
201
- if (outputFormat === 'schema-enforced') {
202
- sections.push(`## OUTPUT FORMAT
203
- Respond with valid JSON matching the schema. Confidence reflects YOUR certainty.`);
204
- }
205
- else if (outputFormat === 'json') {
206
- sections.push(`## OUTPUT FORMAT
207
- Respond with valid JSON:
208
- \`\`\`json
209
- {
210
- "findings": [{
211
- "id": "string",
212
- "category": "security|performance|correctness|architecture|other",
213
- "severity": "critical|high|medium|low|info",
214
- "confidence": 0.0-1.0,
215
- "title": "string",
216
- "description": "string",
217
- "location": { "file": "string", "line_start": 0 },
218
- "evidence": "code snippet",
219
- "suggestion": "string"
220
- }],
221
- "uncertainty_responses": [{"uncertainty_index": 0, "verified": true, "finding": "string", "recommendation": "string"}],
222
- "question_answers": [{"question_index": 0, "answer": "string", "confidence": 0.0-1.0}],
223
- "agreements": ["string"],
224
- "risk_assessment": { "level": "critical|high|medium|low|minimal", "summary": "string" }
225
- }
226
- \`\`\``);
227
- }
228
- else {
229
- sections.push(`## OUTPUT FORMAT
230
- Structure: ## Findings, ## Uncertainty Responses, ## Question Answers, ## Agreements, ## Risk Assessment.`);
231
- }
232
201
  return sections.join('\n\n');
233
202
  }
234
203
  // =============================================================================
@@ -258,56 +227,3 @@ export function enhanceHandoff(handoff, uncertainties, questions, decisions) {
258
227
  decisions: decisions || handoff.decisions,
259
228
  };
260
229
  }
261
- /**
262
- * Build a prompt for general-purpose peer assistance (not review).
263
- * The peer acts as a collaborative coworker, not a critic.
264
- */
265
- export function buildPeerPrompt(options) {
266
- const { workingDir, prompt, taskType, relevantFiles, context, focusAreas, customInstructions, outputFormat } = options;
267
- const role = selectRole(focusAreas);
268
- const sections = [];
269
- // SECTION 1: ROLE
270
- sections.push(`# ROLE: ${role.name} — Peer Engineer
271
-
272
- ${role.systemPrompt}
273
- Be direct and actionable.`);
274
- // SECTION 2: TASK
275
- const taskLabel = taskType ? ` [${taskType.toUpperCase()}]` : '';
276
- sections.push(`## YOUR TASK${taskLabel}
277
-
278
- **Request:** ${prompt}${context ? `\n**Context:** ${context}` : ''}`);
279
- // SECTION 3: RELEVANT FILES
280
- if (relevantFiles && relevantFiles.length > 0) {
281
- sections.push(`## RELEVANT FILES\n${relevantFiles.map(f => `- \`${f}\``).join('\n')}`);
282
- }
283
- // SECTION 4: FOCUS AREAS
284
- if (focusAreas && focusAreas.length > 0) {
285
- sections.push(`## FOCUS AREAS\n\n${focusAreas.join(', ')}`);
286
- }
287
- // SECTION 5: CUSTOM INSTRUCTIONS
288
- if (customInstructions) {
289
- sections.push(`## ADDITIONAL INSTRUCTIONS\n\n${customInstructions}`);
290
- }
291
- // SECTION 6: OUTPUT FORMAT
292
- if (outputFormat === 'schema-enforced') {
293
- sections.push(`## OUTPUT FORMAT
294
- Respond with valid JSON matching the schema. Confidence reflects YOUR certainty.`);
295
- }
296
- else {
297
- sections.push(`## OUTPUT FORMAT
298
- Respond with valid JSON:
299
- \`\`\`json
300
- {
301
- "responder": "string",
302
- "answer": "markdown",
303
- "confidence": 0.0-1.0,
304
- "key_points": ["string"],
305
- "suggested_actions": [{ "action": "string", "priority": "high|medium|low", "file": "string", "rationale": "string" }],
306
- "file_references": [{ "path": "string", "lines": "string", "relevance": "string" }],
307
- "alternatives": [{ "topic": "string", "current_approach": "string", "alternative": "string", "tradeoffs": { "pros": [], "cons": [] }, "recommendation": "string" }],
308
- "execution_notes": "string"
309
- }
310
- \`\`\``);
311
- }
312
- return sections.join('\n\n');
313
- }
package/dist/index.d.ts CHANGED
@@ -13,6 +13,6 @@
13
13
  *
14
14
  * Usage:
15
15
  * - npx cc-reviewer # Run MCP server (normal usage)
16
- * - npx cc-reviewer --setup # Install slash commands only
16
+ * - npx cc-reviewer update # Install/update slash commands
17
17
  */
18
18
  import './adapters/index.js';
package/dist/index.js CHANGED
@@ -13,21 +13,31 @@
13
13
  *
14
14
  * Usage:
15
15
  * - npx cc-reviewer # Run MCP server (normal usage)
16
- * - npx cc-reviewer --setup # Install slash commands only
16
+ * - npx cc-reviewer update # Install/update slash commands
17
17
  */
18
18
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
19
19
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
20
20
  import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
21
21
  import { handleCodexReview, handleGeminiReview, handleMultiReview, ReviewInputSchema, TOOL_DEFINITIONS } from './tools/feedback.js';
22
- import { handleAskCodex, handleAskGemini, handleAskMulti, PEER_TOOL_DEFINITIONS, } from './tools/peer.js';
23
- import { PeerInputSchema } from './schema.js';
24
22
  import { logCliStatus } from './cli/check.js';
25
23
  import { installCommands } from './commands.js';
26
- // Handle --setup flag: install commands and exit
27
- if (process.argv.includes('--setup') || process.argv.includes('--commands')) {
24
+ // Read version from package.json
25
+ import { readFileSync } from 'fs';
26
+ import { join, dirname } from 'path';
27
+ import { fileURLToPath } from 'url';
28
+ const __pkgPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json');
29
+ const __pkg = JSON.parse(readFileSync(__pkgPath, 'utf-8'));
30
+ const VERSION = __pkg.version;
31
+ // Handle subcommands
32
+ const subcommand = process.argv[2];
33
+ if (subcommand === 'update' || subcommand === '--setup' || subcommand === '--commands') {
28
34
  const result = installCommands();
29
35
  if (result.success) {
30
- console.log(`✓ Installed ${result.installed.length} slash commands: ${result.installed.join(', ')}`);
36
+ console.log(`cc-reviewer v${VERSION}`);
37
+ if (result.removed.length > 0) {
38
+ console.log(`✓ Removed ${result.removed.length} deprecated commands: ${result.removed.map(c => `/${c}`).join(', ')}`);
39
+ }
40
+ console.log(`✓ Installed ${result.installed.length} slash commands: ${result.installed.map(c => `/${c}`).join(', ')}`);
31
41
  process.exit(0);
32
42
  }
33
43
  else {
@@ -40,7 +50,7 @@ import './adapters/index.js';
40
50
  // Create the MCP server
41
51
  const server = new Server({
42
52
  name: 'ai-reviewer',
43
- version: '2.0.0',
53
+ version: VERSION,
44
54
  }, {
45
55
  capabilities: {
46
56
  tools: {},
@@ -53,9 +63,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
53
63
  TOOL_DEFINITIONS.codex_review,
54
64
  TOOL_DEFINITIONS.gemini_review,
55
65
  TOOL_DEFINITIONS.multi_review,
56
- PEER_TOOL_DEFINITIONS.ask_codex,
57
- PEER_TOOL_DEFINITIONS.ask_gemini,
58
- PEER_TOOL_DEFINITIONS.ask_multi,
59
66
  ],
60
67
  };
61
68
  });
@@ -76,18 +83,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
76
83
  const input = ReviewInputSchema.parse(args);
77
84
  return await handleMultiReview(input);
78
85
  }
79
- case 'ask_codex': {
80
- const input = PeerInputSchema.parse(args);
81
- return await handleAskCodex(input);
82
- }
83
- case 'ask_gemini': {
84
- const input = PeerInputSchema.parse(args);
85
- return await handleAskGemini(input);
86
- }
87
- case 'ask_multi': {
88
- const input = PeerInputSchema.parse(args);
89
- return await handleAskMulti(input);
90
- }
91
86
  default:
92
87
  return {
93
88
  content: [{
package/dist/schema.d.ts CHANGED
@@ -76,8 +76,8 @@ export declare const ReviewFinding: z.ZodObject<{
76
76
  column_start?: number | undefined;
77
77
  column_end?: number | undefined;
78
78
  } | undefined;
79
- evidence?: string | undefined;
80
79
  suggestion?: string | undefined;
80
+ evidence?: string | undefined;
81
81
  cwe_id?: string | undefined;
82
82
  owasp_category?: string | undefined;
83
83
  tags?: string[] | undefined;
@@ -95,8 +95,8 @@ export declare const ReviewFinding: z.ZodObject<{
95
95
  column_start?: number | undefined;
96
96
  column_end?: number | undefined;
97
97
  } | undefined;
98
- evidence?: string | undefined;
99
98
  suggestion?: string | undefined;
99
+ evidence?: string | undefined;
100
100
  cwe_id?: string | undefined;
101
101
  owasp_category?: string | undefined;
102
102
  tags?: string[] | undefined;
@@ -279,8 +279,8 @@ export declare const ReviewOutput: z.ZodObject<{
279
279
  column_start?: number | undefined;
280
280
  column_end?: number | undefined;
281
281
  } | undefined;
282
- evidence?: string | undefined;
283
282
  suggestion?: string | undefined;
283
+ evidence?: string | undefined;
284
284
  cwe_id?: string | undefined;
285
285
  owasp_category?: string | undefined;
286
286
  tags?: string[] | undefined;
@@ -298,8 +298,8 @@ export declare const ReviewOutput: z.ZodObject<{
298
298
  column_start?: number | undefined;
299
299
  column_end?: number | undefined;
300
300
  } | undefined;
301
- evidence?: string | undefined;
302
301
  suggestion?: string | undefined;
302
+ evidence?: string | undefined;
303
303
  cwe_id?: string | undefined;
304
304
  owasp_category?: string | undefined;
305
305
  tags?: string[] | undefined;
@@ -444,8 +444,8 @@ export declare const ReviewOutput: z.ZodObject<{
444
444
  column_start?: number | undefined;
445
445
  column_end?: number | undefined;
446
446
  } | undefined;
447
- evidence?: string | undefined;
448
447
  suggestion?: string | undefined;
448
+ evidence?: string | undefined;
449
449
  cwe_id?: string | undefined;
450
450
  owasp_category?: string | undefined;
451
451
  tags?: string[] | undefined;
@@ -512,8 +512,8 @@ export declare const ReviewOutput: z.ZodObject<{
512
512
  column_start?: number | undefined;
513
513
  column_end?: number | undefined;
514
514
  } | undefined;
515
- evidence?: string | undefined;
516
515
  suggestion?: string | undefined;
516
+ evidence?: string | undefined;
517
517
  cwe_id?: string | undefined;
518
518
  owasp_category?: string | undefined;
519
519
  tags?: string[] | undefined;
@@ -649,192 +649,3 @@ export declare function isSubstantiveReview(output: ReviewOutput): boolean;
649
649
  * This provides backwards compatibility during transition.
650
650
  */
651
651
  export declare function parseLegacyMarkdownOutput(markdown: string, reviewer: string): ReviewOutput | null;
652
- export declare const SuggestedAction: z.ZodObject<{
653
- action: z.ZodString;
654
- priority: z.ZodEnum<["high", "medium", "low"]>;
655
- file: z.ZodOptional<z.ZodNullable<z.ZodString>>;
656
- rationale: z.ZodString;
657
- }, "strip", z.ZodTypeAny, {
658
- rationale: string;
659
- action: string;
660
- priority: "high" | "medium" | "low";
661
- file?: string | null | undefined;
662
- }, {
663
- rationale: string;
664
- action: string;
665
- priority: "high" | "medium" | "low";
666
- file?: string | null | undefined;
667
- }>;
668
- export type SuggestedAction = z.infer<typeof SuggestedAction>;
669
- export declare const FileReference: z.ZodObject<{
670
- path: z.ZodString;
671
- lines: z.ZodOptional<z.ZodNullable<z.ZodString>>;
672
- relevance: z.ZodString;
673
- }, "strip", z.ZodTypeAny, {
674
- path: string;
675
- relevance: string;
676
- lines?: string | null | undefined;
677
- }, {
678
- path: string;
679
- relevance: string;
680
- lines?: string | null | undefined;
681
- }>;
682
- export type FileReference = z.infer<typeof FileReference>;
683
- export declare const PeerOutput: z.ZodObject<{
684
- responder: z.ZodString;
685
- timestamp: z.ZodOptional<z.ZodNullable<z.ZodString>>;
686
- answer: z.ZodString;
687
- confidence: z.ZodNumber;
688
- key_points: z.ZodArray<z.ZodString, "many">;
689
- suggested_actions: z.ZodArray<z.ZodObject<{
690
- action: z.ZodString;
691
- priority: z.ZodEnum<["high", "medium", "low"]>;
692
- file: z.ZodOptional<z.ZodNullable<z.ZodString>>;
693
- rationale: z.ZodString;
694
- }, "strip", z.ZodTypeAny, {
695
- rationale: string;
696
- action: string;
697
- priority: "high" | "medium" | "low";
698
- file?: string | null | undefined;
699
- }, {
700
- rationale: string;
701
- action: string;
702
- priority: "high" | "medium" | "low";
703
- file?: string | null | undefined;
704
- }>, "many">;
705
- file_references: z.ZodArray<z.ZodObject<{
706
- path: z.ZodString;
707
- lines: z.ZodOptional<z.ZodNullable<z.ZodString>>;
708
- relevance: z.ZodString;
709
- }, "strip", z.ZodTypeAny, {
710
- path: string;
711
- relevance: string;
712
- lines?: string | null | undefined;
713
- }, {
714
- path: string;
715
- relevance: string;
716
- lines?: string | null | undefined;
717
- }>, "many">;
718
- alternatives: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
719
- topic: z.ZodString;
720
- current_approach: z.ZodString;
721
- alternative: z.ZodString;
722
- tradeoffs: z.ZodObject<{
723
- pros: z.ZodArray<z.ZodString, "many">;
724
- cons: z.ZodArray<z.ZodString, "many">;
725
- }, "strip", z.ZodTypeAny, {
726
- pros: string[];
727
- cons: string[];
728
- }, {
729
- pros: string[];
730
- cons: string[];
731
- }>;
732
- recommendation: z.ZodEnum<["strongly_prefer", "consider", "situational", "informational"]>;
733
- }, "strip", z.ZodTypeAny, {
734
- topic: string;
735
- tradeoffs: {
736
- pros: string[];
737
- cons: string[];
738
- };
739
- current_approach: string;
740
- alternative: string;
741
- recommendation: "strongly_prefer" | "consider" | "situational" | "informational";
742
- }, {
743
- topic: string;
744
- tradeoffs: {
745
- pros: string[];
746
- cons: string[];
747
- };
748
- current_approach: string;
749
- alternative: string;
750
- recommendation: "strongly_prefer" | "consider" | "situational" | "informational";
751
- }>, "many">>>;
752
- execution_notes: z.ZodOptional<z.ZodNullable<z.ZodString>>;
753
- }, "strip", z.ZodTypeAny, {
754
- confidence: number;
755
- answer: string;
756
- responder: string;
757
- key_points: string[];
758
- suggested_actions: {
759
- rationale: string;
760
- action: string;
761
- priority: "high" | "medium" | "low";
762
- file?: string | null | undefined;
763
- }[];
764
- file_references: {
765
- path: string;
766
- relevance: string;
767
- lines?: string | null | undefined;
768
- }[];
769
- alternatives?: {
770
- topic: string;
771
- tradeoffs: {
772
- pros: string[];
773
- cons: string[];
774
- };
775
- current_approach: string;
776
- alternative: string;
777
- recommendation: "strongly_prefer" | "consider" | "situational" | "informational";
778
- }[] | null | undefined;
779
- timestamp?: string | null | undefined;
780
- execution_notes?: string | null | undefined;
781
- }, {
782
- confidence: number;
783
- answer: string;
784
- responder: string;
785
- key_points: string[];
786
- suggested_actions: {
787
- rationale: string;
788
- action: string;
789
- priority: "high" | "medium" | "low";
790
- file?: string | null | undefined;
791
- }[];
792
- file_references: {
793
- path: string;
794
- relevance: string;
795
- lines?: string | null | undefined;
796
- }[];
797
- alternatives?: {
798
- topic: string;
799
- tradeoffs: {
800
- pros: string[];
801
- cons: string[];
802
- };
803
- current_approach: string;
804
- alternative: string;
805
- recommendation: "strongly_prefer" | "consider" | "situational" | "informational";
806
- }[] | null | undefined;
807
- timestamp?: string | null | undefined;
808
- execution_notes?: string | null | undefined;
809
- }>;
810
- export type PeerOutput = z.infer<typeof PeerOutput>;
811
- export declare const TaskType: z.ZodEnum<["plan", "debug", "explain", "question", "fix", "explore", "general"]>;
812
- export type TaskType = z.infer<typeof TaskType>;
813
- export declare const PeerInputSchema: z.ZodObject<{
814
- workingDir: z.ZodString;
815
- prompt: z.ZodString;
816
- taskType: z.ZodOptional<z.ZodEnum<["plan", "debug", "explain", "question", "fix", "explore", "general"]>>;
817
- relevantFiles: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
818
- context: z.ZodOptional<z.ZodString>;
819
- focusAreas: z.ZodOptional<z.ZodArray<z.ZodEnum<["security", "performance", "architecture", "correctness", "maintainability", "scalability", "testing", "documentation"]>, "many">>;
820
- customPrompt: z.ZodOptional<z.ZodString>;
821
- }, "strip", z.ZodTypeAny, {
822
- workingDir: string;
823
- prompt: string;
824
- taskType?: "question" | "plan" | "debug" | "explain" | "fix" | "explore" | "general" | undefined;
825
- context?: string | undefined;
826
- relevantFiles?: string[] | undefined;
827
- focusAreas?: ("performance" | "security" | "testing" | "architecture" | "correctness" | "maintainability" | "scalability" | "documentation")[] | undefined;
828
- customPrompt?: string | undefined;
829
- }, {
830
- workingDir: string;
831
- prompt: string;
832
- taskType?: "question" | "plan" | "debug" | "explain" | "fix" | "explore" | "general" | undefined;
833
- context?: string | undefined;
834
- relevantFiles?: string[] | undefined;
835
- focusAreas?: ("performance" | "security" | "testing" | "architecture" | "correctness" | "maintainability" | "scalability" | "documentation")[] | undefined;
836
- customPrompt?: string | undefined;
837
- }>;
838
- export type PeerInput = z.infer<typeof PeerInputSchema>;
839
- export declare function getPeerOutputJsonSchema(): object;
840
- export declare function parsePeerOutput(rawOutput: string): PeerOutput | null;
package/dist/schema.js CHANGED
@@ -154,7 +154,7 @@ export function getReviewOutputJsonSchema() {
154
154
  return {
155
155
  type: 'object',
156
156
  additionalProperties: false,
157
- required: ['reviewer', 'findings', 'risk_assessment'],
157
+ required: ['reviewer', 'findings', 'agreements', 'disagreements', 'alternatives', 'risk_assessment', 'uncertainty_responses', 'question_answers'],
158
158
  properties: {
159
159
  reviewer: { type: 'string' },
160
160
  findings: {
@@ -499,192 +499,3 @@ export function parseLegacyMarkdownOutput(markdown, reviewer) {
499
499
  return null;
500
500
  }
501
501
  }
502
- // =============================================================================
503
- // PEER OUTPUT SCHEMA (General-purpose coworker responses)
504
- // =============================================================================
505
- export const SuggestedAction = z.object({
506
- action: z.string().describe('What to do'),
507
- priority: z.enum(['high', 'medium', 'low']),
508
- file: z.string().nullable().optional().describe('Relevant file path'),
509
- rationale: z.string().describe('Why this action is recommended'),
510
- });
511
- export const FileReference = z.object({
512
- path: z.string().describe('Relative file path'),
513
- lines: z.string().nullable().optional().describe('Line range, e.g. "10-25"'),
514
- relevance: z.string().describe('Why this file matters'),
515
- });
516
- export const PeerOutput = z.object({
517
- responder: z.string().describe('"codex" or "gemini"'),
518
- timestamp: z.string().nullable().optional(),
519
- // Core response
520
- answer: z.string().describe('Main response text (markdown)'),
521
- confidence: ConfidenceScore.describe('Confidence in the response (0-1)'),
522
- // Structured breakdown
523
- key_points: z.array(z.string()).describe('Bullet summary of main points'),
524
- // Actionable items
525
- suggested_actions: z.array(SuggestedAction).describe('Recommended actions'),
526
- // File references
527
- file_references: z.array(FileReference).describe('Files examined by the peer'),
528
- // Optional — nullable because OpenAI strict mode sends null instead of omitting
529
- alternatives: z.array(Alternative).nullable().optional().describe('Alternative approaches'),
530
- execution_notes: z.string().nullable().optional().describe('Notes about the process'),
531
- });
532
- // =============================================================================
533
- // PEER INPUT SCHEMA
534
- // =============================================================================
535
- export const TaskType = z.enum(['plan', 'debug', 'explain', 'question', 'fix', 'explore', 'general']);
536
- export const PeerInputSchema = z.object({
537
- workingDir: z.string().describe('Working directory for filesystem access'),
538
- prompt: z.string().describe('The question or request from CC'),
539
- taskType: TaskType.optional().describe('Hint about the type of task'),
540
- relevantFiles: z.array(z.string()).optional().describe('Files the peer should focus on'),
541
- context: z.string().optional().describe('Additional context (error messages, prior analysis)'),
542
- focusAreas: z.array(z.enum([
543
- 'security', 'performance', 'architecture', 'correctness',
544
- 'maintainability', 'scalability', 'testing', 'documentation'
545
- ])).optional().describe('Areas to focus on'),
546
- customPrompt: z.string().optional().describe('Additional instructions for the peer'),
547
- });
548
- // =============================================================================
549
- // PEER OUTPUT JSON SCHEMA (for embedding in prompts)
550
- // =============================================================================
551
- export function getPeerOutputJsonSchema() {
552
- return {
553
- type: 'object',
554
- additionalProperties: false,
555
- required: ['responder', 'answer', 'confidence', 'key_points', 'suggested_actions', 'file_references', 'timestamp', 'alternatives', 'execution_notes'],
556
- properties: {
557
- responder: { type: 'string' },
558
- timestamp: { anyOf: [{ type: 'string' }, { type: 'null' }] },
559
- answer: { type: 'string' },
560
- confidence: { type: 'number', minimum: 0, maximum: 1 },
561
- key_points: {
562
- type: 'array',
563
- items: { type: 'string' },
564
- },
565
- suggested_actions: {
566
- type: 'array',
567
- items: {
568
- type: 'object',
569
- additionalProperties: false,
570
- required: ['action', 'priority', 'rationale', 'file'],
571
- properties: {
572
- action: { type: 'string' },
573
- priority: { type: 'string', enum: ['high', 'medium', 'low'] },
574
- file: { anyOf: [{ type: 'string' }, { type: 'null' }] },
575
- rationale: { type: 'string' },
576
- },
577
- },
578
- },
579
- file_references: {
580
- type: 'array',
581
- items: {
582
- type: 'object',
583
- additionalProperties: false,
584
- required: ['path', 'relevance', 'lines'],
585
- properties: {
586
- path: { type: 'string' },
587
- lines: { anyOf: [{ type: 'string' }, { type: 'null' }] },
588
- relevance: { type: 'string' },
589
- },
590
- },
591
- },
592
- alternatives: {
593
- anyOf: [
594
- {
595
- type: 'array',
596
- items: {
597
- type: 'object',
598
- additionalProperties: false,
599
- required: ['topic', 'current_approach', 'alternative', 'tradeoffs', 'recommendation'],
600
- properties: {
601
- topic: { type: 'string' },
602
- current_approach: { type: 'string' },
603
- alternative: { type: 'string' },
604
- tradeoffs: {
605
- type: 'object',
606
- additionalProperties: false,
607
- required: ['pros', 'cons'],
608
- properties: {
609
- pros: { type: 'array', items: { type: 'string' } },
610
- cons: { type: 'array', items: { type: 'string' } },
611
- },
612
- },
613
- recommendation: { type: 'string', enum: ['strongly_prefer', 'consider', 'situational', 'informational'] },
614
- },
615
- },
616
- },
617
- { type: 'null' },
618
- ],
619
- },
620
- execution_notes: { anyOf: [{ type: 'string' }, { type: 'null' }] },
621
- },
622
- };
623
- }
624
- // =============================================================================
625
- // PEER OUTPUT PARSING
626
- // =============================================================================
627
- function normalizePeerOutput(parsed) {
628
- const normalized = { ...parsed };
629
- if (!normalized.responder) {
630
- normalized.responder = 'external';
631
- }
632
- normalized.key_points = normalized.key_points ?? [];
633
- normalized.suggested_actions = normalized.suggested_actions ?? [];
634
- normalized.file_references = normalized.file_references ?? [];
635
- if (normalized.confidence === undefined) {
636
- normalized.confidence = 0.5;
637
- }
638
- if (!normalized.answer && typeof normalized.response === 'string') {
639
- normalized.answer = normalized.response;
640
- }
641
- return normalized;
642
- }
643
- export function parsePeerOutput(rawOutput) {
644
- try {
645
- let jsonStr = rawOutput;
646
- // Unwrap Gemini envelope
647
- try {
648
- const envelope = JSON.parse(rawOutput);
649
- if (envelope && typeof envelope.session_id === 'string' && typeof envelope.response === 'string') {
650
- jsonStr = envelope.response;
651
- }
652
- }
653
- catch {
654
- // Not an envelope
655
- }
656
- // Extract from ```json ... ``` blocks
657
- const jsonBlockMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)```/);
658
- if (jsonBlockMatch) {
659
- jsonStr = jsonBlockMatch[1].trim();
660
- }
661
- // Find JSON object boundaries
662
- const jsonStart = jsonStr.indexOf('{');
663
- const jsonEnd = jsonStr.lastIndexOf('}');
664
- if (jsonStart !== -1 && jsonEnd !== -1 && jsonEnd > jsonStart) {
665
- jsonStr = jsonStr.slice(jsonStart, jsonEnd + 1);
666
- }
667
- const parsed = JSON.parse(jsonStr);
668
- // Try direct parse
669
- const result = PeerOutput.safeParse(parsed);
670
- if (result.success) {
671
- return result.data;
672
- }
673
- // Normalize and retry
674
- const recognizedFields = ['responder', 'answer', 'response', 'key_points', 'suggested_actions', 'file_references', 'confidence'];
675
- const hasRecognizedField = typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) &&
676
- recognizedFields.some(f => f in parsed);
677
- if (!hasRecognizedField) {
678
- return null;
679
- }
680
- const normalized = normalizePeerOutput(parsed);
681
- const retryResult = PeerOutput.safeParse(normalized);
682
- if (retryResult.success) {
683
- return retryResult.data;
684
- }
685
- return null;
686
- }
687
- catch {
688
- return null;
689
- }
690
- }
@@ -1,9 +1,8 @@
1
1
  /**
2
- * MCP Tool Implementations
2
+ * MCP Tool Implementations — Review Tools
3
3
  *
4
- * Provides two levels of review:
5
- * 1. Single model review (codex_review, gemini_review)
6
- * 2. Multi-model parallel review (multi_review)
4
+ * Returns raw reviewer text to CC. No JSON parsing, no reformatting.
5
+ * CC handles interpretation and synthesis.
7
6
  */
8
7
  import { z } from 'zod';
9
8
  export declare const ReviewInputSchema: z.ZodObject<{
@@ -20,8 +19,8 @@ export declare const ReviewInputSchema: z.ZodObject<{
20
19
  ccOutput: string;
21
20
  outputType: "findings" | "analysis" | "plan" | "proposal";
22
21
  focusAreas?: ("performance" | "security" | "testing" | "architecture" | "correctness" | "maintainability" | "scalability" | "documentation")[] | undefined;
23
- customPrompt?: string | undefined;
24
22
  analyzedFiles?: string[] | undefined;
23
+ customPrompt?: string | undefined;
25
24
  reasoningEffort?: "high" | "xhigh" | undefined;
26
25
  serviceTier?: "default" | "fast" | "flex" | undefined;
27
26
  }, {
@@ -29,8 +28,8 @@ export declare const ReviewInputSchema: z.ZodObject<{
29
28
  ccOutput: string;
30
29
  outputType: "findings" | "analysis" | "plan" | "proposal";
31
30
  focusAreas?: ("performance" | "security" | "testing" | "architecture" | "correctness" | "maintainability" | "scalability" | "documentation")[] | undefined;
32
- customPrompt?: string | undefined;
33
31
  analyzedFiles?: string[] | undefined;
32
+ customPrompt?: string | undefined;
34
33
  reasoningEffort?: "high" | "xhigh" | undefined;
35
34
  serviceTier?: "default" | "fast" | "flex" | undefined;
36
35
  }>;