Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .clinerules
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ CodeCritique is an AI-powered code review tool that:
- Validate all user inputs
- Log errors with meaningful context

### Logging

- Use `verboseLog(options, ...)` from `src/utils/logging.js` for progress and informational diagnostics gated by verbose mode
- Use `debug(...)` only for developer-focused tracing gated by `DEBUG`
- Keep `console.warn(...)` and `console.error(...)` for warnings and errors that should always be shown
- Avoid raw `console.log(...)` in normal code paths
- Document logging-related options such as `verbose` in JSDoc and pass them through to downstream helpers

### Key Commands

```bash
Expand Down
8 changes: 8 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ CodeCritique is an AI-powered code review tool that:
- Validate all user inputs
- Log errors with meaningful context

### Logging

- Use `verboseLog(options, ...)` from `src/utils/logging.js` for progress and informational diagnostics gated by verbose mode
- Use `debug(...)` only for developer-focused tracing gated by `DEBUG`
- Keep `console.warn(...)` and `console.error(...)` for warnings and errors that should always be shown
- Avoid raw `console.log(...)` in normal code paths
- Document logging-related options such as `verbose` in JSDoc and pass them through to downstream helpers

### Key Commands

```bash
Expand Down
8 changes: 8 additions & 0 deletions .roo/rules/01-project-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ For comprehensive guidelines, see **AGENTS.md** in the project root.
- Validate all user inputs
- Log errors with meaningful context

### Logging

- Use `verboseLog(options, ...)` from `src/utils/logging.js` for progress and informational diagnostics gated by verbose mode
- Use `debug(...)` only for developer-focused tracing gated by `DEBUG`
- Keep `console.warn(...)` and `console.error(...)` for warnings and errors that should always be shown
- Avoid raw `console.log(...)` in normal code paths
- Document logging-related options such as `verbose` in JSDoc and pass them through to downstream helpers

### Key Commands

```bash
Expand Down
8 changes: 8 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,14 @@ import { Internal } from './internal.js';
- Handle errors gracefully with meaningful messages
- Log errors with context

### Logging

- Use `verboseLog(options, ...)` from `src/utils/logging.js` for progress and informational diagnostics that should only appear in verbose mode
- Use `debug(...)` only for developer-focused tracing that should require `DEBUG`
- Use `console.warn(...)` and `console.error(...)` for warnings and errors that should always be surfaced
- Avoid raw `console.log(...)` in normal code paths
- When a function accepts logging-related options such as `verbose`, document them in JSDoc and pass them through to downstream helpers

### Async/Await

- Prefer async/await over raw promises
Expand Down
8 changes: 8 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ CodeCritique is an AI-powered code review tool that:
- Validate all user inputs
- Log errors with meaningful context

### Logging

- Use `verboseLog(options, ...)` from `src/utils/logging.js` for progress and informational diagnostics gated by verbose mode
- Use `debug(...)` only for developer-focused tracing gated by `DEBUG`
- Keep `console.warn(...)` and `console.error(...)` for warnings and errors that should always be shown
- Avoid raw `console.log(...)` in normal code paths
- Document logging-related options such as `verbose` in JSDoc and pass them through to downstream helpers

### Key Commands

```bash
Expand Down
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ src/
- Handle errors gracefully with meaningful messages
- Write self-documenting code with clear variable names

### Logging

- Use `verboseLog(options, ...)` from `src/utils/logging.js` for progress and informational diagnostics gated by verbose mode
- Use `debug(...)` only for developer-focused tracing gated by `DEBUG`
- Keep `console.warn(...)` and `console.error(...)` for warnings and errors that should always be shown
- Avoid raw `console.log(...)` in normal code paths
- Document logging-related options such as `verbose` in JSDoc and pass them through to downstream helpers

---

## Commit Conventions
Expand Down
36 changes: 20 additions & 16 deletions src/content-retrieval.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { calculateCosineSimilarity, calculatePathSimilarity } from './embeddings
import { inferContextFromDocumentContent } from './utils/context-inference.js';
import { isGenericDocument, getGenericDocumentContext } from './utils/document-detection.js';
import { isDocumentationFile } from './utils/file-validation.js';
import { debug } from './utils/logging.js';
import { debug, verboseLog } from './utils/logging.js';

const FILE_EMBEDDINGS_TABLE = TABLE_NAMES.FILE_EMBEDDINGS;
const DOCUMENT_CHUNK_TABLE = TABLE_NAMES.DOCUMENT_CHUNK;
Expand Down Expand Up @@ -79,7 +79,8 @@ export class ContentRetriever {
return [];
}

console.log(
verboseLog(
options,
chalk.cyan(`Native hybrid documentation search - limit: ${limit}, threshold: ${similarityThreshold}, reranking: ${useReranking}`)
);

Expand All @@ -91,7 +92,7 @@ export class ContentRetriever {
return [];
}

console.log(chalk.cyan('Performing native hybrid search for documentation...'));
verboseLog(options, chalk.cyan('Performing native hybrid search for documentation...'));
let query = table.search(queryText).nearestToText(queryText);

const resolvedProjectPath = path.resolve(projectPath);
Expand All @@ -106,7 +107,7 @@ export class ContentRetriever {
}

const results = await query.limit(Math.max(limit * 3, 20)).toArray();
console.log(chalk.green(`Native hybrid search returned ${results.length} documentation results`));
verboseLog(options, chalk.green(`Native hybrid search returned ${results.length} documentation results`));

// OPTIMIZATION: Enhanced batch file existence checks with parallel processing
const docsToCheck = [];
Expand Down Expand Up @@ -168,7 +169,7 @@ export class ContentRetriever {
// Filter results based on project match using the map
const projectFilteredResults = results.filter((result, index) => docProjectMatchMap.get(index) === true);

console.log(chalk.blue(`Filtered to ${projectFilteredResults.length} documentation results from current project`));
verboseLog(options, chalk.blue(`Filtered to ${projectFilteredResults.length} documentation results from current project`));
let finalResults = projectFilteredResults.map((result) => {
let similarity;
if (result._distance !== undefined) {
Expand Down Expand Up @@ -197,7 +198,7 @@ export class ContentRetriever {

let queryEmbedding = null;
if (useReranking && queryContextForReranking && finalResults.length >= 3) {
console.log(chalk.cyan('Applying sophisticated contextual reranking to documentation...'));
verboseLog(options, chalk.cyan('Applying sophisticated contextual reranking to documentation...'));
const WEIGHT_INITIAL_SIM = 0.3;
const WEIGHT_H1_CHUNK_RERANK = 0.15;
const HEAVY_BOOST_SAME_AREA = 0.4;
Expand Down Expand Up @@ -416,7 +417,7 @@ export class ContentRetriever {
finalResults = finalResults.slice(0, limit);
}

console.log(chalk.green(`Returning ${finalResults.length} documentation results`));
verboseLog(options, chalk.green(`Returning ${finalResults.length} documentation results`));

return finalResults;
} catch (error) {
Expand All @@ -443,7 +444,10 @@ export class ContentRetriever {
precomputedQueryEmbedding = null,
} = options;

console.log(chalk.cyan(`Native hybrid code search - limit: ${limit}, threshold: ${similarityThreshold}, isTestFile: ${isTestFile}`));
verboseLog(
options,
chalk.cyan(`Native hybrid code search - limit: ${limit}, threshold: ${similarityThreshold}, isTestFile: ${isTestFile}`)
);

try {
if (!queryText?.trim()) {
Expand All @@ -460,7 +464,7 @@ export class ContentRetriever {
}

// Native hybrid search with automatic vector + FTS + RRF
console.log(chalk.cyan('Performing native hybrid search for code...'));
verboseLog(options, chalk.cyan('Performing native hybrid search for code...'));
let query = table.search(queryText).nearestToText(queryText);

// Add filtering conditions
Expand All @@ -472,13 +476,13 @@ export class ContentRetriever {
if (isTestFile) {
// Only include test files
conditions.push(`(path LIKE '%.test.%' OR path LIKE '%.spec.%' OR path LIKE '%_test.py' OR path LIKE 'test_%.py')`);
console.log(chalk.blue(`Filtering to include only test files.`));
verboseLog(options, chalk.blue(`Filtering to include only test files.`));
} else {
// Exclude test files
conditions.push(
`(path NOT LIKE '%.test.%' AND path NOT LIKE '%.spec.%' AND path NOT LIKE '%_test.py' AND path NOT LIKE 'test_%.py')`
);
console.log(chalk.blue(`Filtering to exclude test files.`));
verboseLog(options, chalk.blue(`Filtering to exclude test files.`));
}
}

Expand Down Expand Up @@ -526,7 +530,7 @@ export class ContentRetriever {

const results = await query.limit(Math.max(limit * 3, 20)).toArray();

console.log(chalk.green(`Native hybrid search returned ${results.length} results`));
verboseLog(options, chalk.green(`Native hybrid search returned ${results.length} results`));

// OPTIMIZATION: Batch file existence checks for better performance
const resultsToCheck = [];
Expand Down Expand Up @@ -595,7 +599,7 @@ export class ContentRetriever {
// Filter results based on project match using the map
const projectFilteredResults = results.filter((result, index) => projectMatchMap.get(index) === true);

console.log(chalk.blue(`Filtered to ${projectFilteredResults.length} results from current project`));
verboseLog(options, chalk.blue(`Filtered to ${projectFilteredResults.length} results from current project`));

// Map results to expected format
let finalResults = projectFilteredResults.map((result) => {
Expand Down Expand Up @@ -683,7 +687,7 @@ export class ContentRetriever {
finalResults = finalResults.slice(0, limit);
}

console.log(chalk.green(`Returning ${finalResults.length} optimized hybrid search results`));
verboseLog(options, chalk.green(`Returning ${finalResults.length} optimized hybrid search results`));
return finalResults;
} catch (error) {
console.error(chalk.red(`Error in optimized findSimilarCode: ${error.message}`), error);
Expand Down Expand Up @@ -712,7 +716,7 @@ export class ContentRetriever {
this.h1EmbeddingCache.clear();
this.documentContextCache.clear();
this.documentContextPromiseCache.clear();
console.log(chalk.green('ContentRetriever caches cleared'));
verboseLog({}, chalk.green('ContentRetriever caches cleared'));
}

/**
Expand All @@ -739,7 +743,7 @@ export class ContentRetriever {
parallelRerankingTime: 0,
};

console.log(chalk.green('ContentRetriever cleanup complete'));
verboseLog({}, chalk.green('ContentRetriever cleanup complete'));
} finally {
this.cleaningUp = false;
}
Expand Down
34 changes: 17 additions & 17 deletions src/custom-documents.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { CacheManager } from './embeddings/cache-manager.js';
import { EmbeddingError, ValidationError } from './embeddings/errors.js';
import { ModelManager } from './embeddings/model-manager.js';
import { calculateCosineSimilarity, calculatePathSimilarity } from './embeddings/similarity-calculator.js';
import { debug } from './utils/logging.js';
import { debug, verboseLog } from './utils/logging.js';
import { slugify } from './utils/string-utils.js';

/**
Expand Down Expand Up @@ -140,7 +140,7 @@ export class CustomDocumentProcessor {
this.performanceMetrics.averageChunkSize = chunks.reduce((sum, chunk) => sum + chunk.content.length, 0) / chunks.length;
this.performanceMetrics.processingTime += Date.now() - startTime;

console.log(chalk.gray(` Chunked document "${documentTitle}" into ${chunks.length} chunks`));
verboseLog({}, chalk.gray(` Chunked document "${documentTitle}" into ${chunks.length} chunks`));
return chunks;
} catch (error) {
console.error(chalk.red(`Error chunking document: ${error.message}`));
Expand All @@ -159,18 +159,18 @@ export class CustomDocumentProcessor {

try {
if (!customDocs || customDocs.length === 0) {
console.log(chalk.gray('No custom documents to process'));
verboseLog({}, chalk.gray('No custom documents to process'));
return [];
}

console.log(chalk.cyan(`Processing ${customDocs.length} custom documents into chunks...`));
verboseLog({}, chalk.cyan(`Processing ${customDocs.length} custom documents into chunks...`));

const allChunks = [];
let totalBatchAttempts = 0;
let successfulBatches = 0;

for (const doc of customDocs) {
console.log(chalk.gray(` Processing document: ${doc.title}`));
verboseLog({}, chalk.gray(` Processing document: ${doc.title}`));

// Chunk the document
const chunks = this.chunkDocument(doc);
Expand Down Expand Up @@ -205,12 +205,12 @@ export class CustomDocumentProcessor {
const validChunks = chunksWithEmbeddings.filter((chunk) => chunk !== null);
allChunks.push(...validChunks);

console.log(chalk.gray(` Generated embeddings for ${validChunks.length}/${chunks.length} chunks`));
verboseLog({}, chalk.gray(` Generated embeddings for ${validChunks.length}/${chunks.length} chunks`));
this.performanceMetrics.embeddingsCalculated += validChunks.length;
} catch (error) {
console.error(chalk.red(`Error in batch embedding generation for document ${doc.title}: ${error.message}`));
// Fallback to individual processing for this document
console.log(chalk.yellow(` Falling back to individual processing for ${doc.title}`));
verboseLog({}, chalk.yellow(` Falling back to individual processing for ${doc.title}`));

const chunksWithEmbeddings = await Promise.all(
chunks.map(async (chunk) => {
Expand All @@ -235,7 +235,7 @@ export class CustomDocumentProcessor {
const validChunks = chunksWithEmbeddings.filter((chunk) => chunk !== null);
allChunks.push(...validChunks);

console.log(chalk.gray(` Generated embeddings for ${validChunks.length}/${chunks.length} chunks (fallback)`));
verboseLog({}, chalk.gray(` Generated embeddings for ${validChunks.length}/${chunks.length} chunks (fallback)`));
}
}

Expand All @@ -252,7 +252,7 @@ export class CustomDocumentProcessor {
this.performanceMetrics.documentsProcessed += customDocs.length;
this.performanceMetrics.processingTime += Date.now() - startTime;

console.log(chalk.green(`Successfully processed ${allChunks.length} custom document chunks (${Date.now() - startTime}ms)`));
verboseLog({}, chalk.green(`Successfully processed ${allChunks.length} custom document chunks (${Date.now() - startTime}ms)`));
return allChunks;
} catch (error) {
console.error(chalk.red(`Error processing custom documents: ${error.message}`));
Expand Down Expand Up @@ -285,11 +285,11 @@ export class CustomDocumentProcessor {
}

if (!chunks || chunks.length === 0) {
console.log(chalk.gray('No custom document chunks available for search'));
verboseLog({}, chalk.gray('No custom document chunks available for search'));
return [];
}

console.log(chalk.cyan(`Searching ${chunks.length} custom document chunks...`));
verboseLog({}, chalk.cyan(`Searching ${chunks.length} custom document chunks...`));

// OPTIMIZATION: Use pre-computed query embedding if available
let queryEmbedding = precomputedQueryEmbedding;
Expand Down Expand Up @@ -319,7 +319,7 @@ export class CustomDocumentProcessor {
filteredResults = filteredResults.slice(0, limit);
}

console.log(chalk.green(`Found ${filteredResults.length} relevant custom document chunks (${Date.now() - startTime}ms)`));
verboseLog({}, chalk.green(`Found ${filteredResults.length} relevant custom document chunks (${Date.now() - startTime}ms)`));

// Log top results for debugging
if (filteredResults.length > 0) {
Expand Down Expand Up @@ -371,7 +371,7 @@ export class CustomDocumentProcessor {
* @private
*/
async _applyParallelReranking(filteredResults, queryText, queryContextForReranking, queryFilePath, queryEmbedding) {
console.log(chalk.cyan('Applying optimized parallel contextual reranking to custom document chunks...'));
verboseLog({}, chalk.cyan('Applying optimized parallel contextual reranking to custom document chunks...'));

const WEIGHT_INITIAL_SIM = 0.4;
const WEIGHT_DOCUMENT_TITLE_MATCH = 0.2;
Expand Down Expand Up @@ -466,7 +466,7 @@ export class CustomDocumentProcessor {
// Wait for all reranking calculations to complete in parallel
await Promise.all(rerankingPromises);

console.log(chalk.cyan(`Parallel reranking completed for ${filteredResults.length} chunks`));
verboseLog({}, chalk.cyan(`Parallel reranking completed for ${filteredResults.length} chunks`));

// Log debug info for first few results
for (let i = 0; i < Math.min(3, filteredResults.length); i++) {
Expand Down Expand Up @@ -521,7 +521,7 @@ export class CustomDocumentProcessor {
const resolvedProjectPath = path.resolve(projectPath);
this.customDocumentChunks.delete(resolvedProjectPath);
this.cacheManager.customDocumentChunks.delete(resolvedProjectPath);
console.log(chalk.green(`Cleared custom document chunks for project: ${resolvedProjectPath}`));
verboseLog({}, chalk.green(`Cleared custom document chunks for project: ${resolvedProjectPath}`));
} catch (error) {
console.error(chalk.red(`Error clearing project chunks: ${error.message}`));
}
Expand Down Expand Up @@ -561,7 +561,7 @@ export class CustomDocumentProcessor {
clearCaches() {
this.h1EmbeddingCache.clear();
this.customDocumentChunks.clear();
console.log(chalk.green('CustomDocumentProcessor caches cleared'));
verboseLog({}, chalk.green('CustomDocumentProcessor caches cleared'));
}

/**
Expand Down Expand Up @@ -589,7 +589,7 @@ export class CustomDocumentProcessor {
processingTime: 0,
};

console.log(chalk.green('CustomDocumentProcessor cleanup complete'));
verboseLog({}, chalk.green('CustomDocumentProcessor cleanup complete'));
} finally {
this.cleaningUp = false;
}
Expand Down
Loading