Skip to content

refactor: replace analysis field with issue/message pair#53

Open
hurshore wants to merge 3 commits intomainfrom
refactor/output-format
Open

refactor: replace analysis field with issue/message pair#53
hurshore wants to merge 3 commits intomainfrom
refactor/output-format

Conversation

@hurshore
Copy link
Collaborator

@hurshore hurshore commented Jan 13, 2026

Summary

Refines the analysis output format by replacing the single analysis field with a structured issue + message pair. This enables scope-aware formatting, where the message can intelligently include or exclude the quoted text based on the issue scope (word, sentence, section, or document).

Changes

Prompt Improvements (src/prompts/directive.ts)

  • Added scope-aware message formatting examples (WORD, SENTENCE, SECTION level)
  • Added critical rule: if quoted_text is longer than 4 words, do NOT include it in the message
  • Added rule requiring section names when comparing/contrasting sections

Schema Updates (src/prompts/schema.ts)

  • Replaced analysis with issue and message fields in both subjective and semi-objective schemas
  • Updated all corresponding TypeScript types

CLI (src/schemas/cli-schemas.ts)

  • Added suggest boolean option for showing suggestions

Scoring (src/scoring/scorer.ts)

  • Updated violation mapping to use new issue/message fields
  • Changed deduplication logic to use message instead of analysis

Tests

  • Updated test fixtures to include pack property and new field structure

Summary by CodeRabbit

  • New Features

    • Added a --suggest CLI option to generate and include improvement suggestions.
    • Suggestions are included in JSON output and optionally in line output when requested.
  • Other Changes

    • Violation records now use separate "issue" and "message" fields for clearer reporting.
    • Built-in directive guidance refined for word/sentence/section reporting.
    • Deduplication now uses message content to determine uniqueness.

✏️ Tip: You can customize this high-level summary in your review settings.

- Rename `analysis` field to `issue` and add `message` field
- Add `--suggest` CLI flag to cli-schemas
- Update subjective and semi-objective LLM schemas
- Add prompt guidance for scope-aware message formatting
- Update scoring logic to use new fields for deduplication
- Add rule for naming sections in comparisons
@hurshore hurshore requested a review from ayo6706 January 13, 2026 07:49
@coderabbitai
Copy link

coderabbitai bot commented Jan 13, 2026

📝 Walkthrough

Walkthrough

Refactors violation data to replace analysis with issue and message, updates deduplication to use message, and adds a --suggest CLI option propagated through evaluation and reporting to conditionally include suggestions.

Changes

Cohort / File(s) Summary
Data shape & deduplication
src/chunking/merger.ts, src/scoring/scorer.ts, src/prompts/schema.ts, tests/scoring-types.test.ts
Replace analysis with issue and message across schemas, types, scoring, and tests. Update deduplication composite key to use v.message instead of v.analysis.
CLI option & wiring
src/cli/commands.ts, src/cli/orchestrator.ts, src/cli/types.ts, src/schemas/cli-schemas.ts
Add --suggest CLI option and suggest?: boolean in types/schemas. Thread suggest through orchestrator/evaluation/reporting signatures and conditionally include suggestions in line and JSON outputs.
Directive text & examples
src/prompts/directive-loader.ts
Update built-in directive text to replace analysis/suggestion with issue/message, add MESSAGE_EXAMPLES and adjust CRITICAL reporting rules.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI
  participant Orchestrator
  participant Evaluator
  participant Reporter

  User->>CLI: run command (with or without --suggest)
  CLI->>Orchestrator: evaluateFile(params..., suggest)
  Orchestrator->>Evaluator: process file -> produce violations (issue, message, suggestion)
  Evaluator-->>Orchestrator: return results + token usage
  Orchestrator->>Reporter: route results + suggest flag
  Reporter-->>User: emit line output (include suggestions only if suggest true)
  Reporter-->>User: emit JSON output (include suggestions)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • ayo6706
  • oshorefueled

Poem

🐇
I nibbled fields and split a thought,
"analysis" swapped for things well-wrought.
A tiny flag, "suggest" in tow,
Now outputs whisper what they know.
Carrots for code that helps us grow.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main refactoring change: replacing the analysis field with an issue/message pair across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8351624 and 9d7abf3.

📒 Files selected for processing (2)
  • src/prompts/directive-loader.ts
  • src/prompts/schema.ts
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Use TypeScript ESM with explicit imports and narrow types
Use 2-space indentation; avoid trailing whitespace
Maintain strict TypeScript with no any; use unknown + schema validation for external data
Use custom error types with proper inheritance; catch blocks use unknown type

Files:

  • src/prompts/directive-loader.ts
  • src/prompts/schema.ts
🔇 Additional comments (7)
src/prompts/schema.ts (3)

26-51: Schema changes look correct.

The issue and message fields are properly added to the violations schema with correct types. The required array is updated appropriately. Note that line remains optional (not in required), which appears intentional for cases where line numbers cannot be determined.


68-91: Semi-objective schema correctly updated.

The schema properly adds issue and message as required fields while retaining description for this evaluation type. The field structure is consistent with the TypeScript type definition below.


152-180: Processed result types correctly updated.

The SemiObjectiveItem and SemiObjectiveResult types properly include issue and message fields. The optional markers on suggestion, quoted_text, context_before, and context_after are appropriate for these processed/downstream types.

src/prompts/directive-loader.ts (4)

24-28: Clear guidance for issue/message distinction.

The directive clearly explains the new issue and message fields with scope-based formatting rules. The examples demonstrate the expected format for WORD-level vs SENTENCE/SECTION/DOCUMENT-level messages.


31-44: Well-structured examples with clear scope distinctions.

The MESSAGE EXAMPLES section provides concrete illustrations for each scope level (WORD, SENTENCE, SECTION). The critical rule about the 4-word threshold is prominently highlighted.


47-54: Critical rules properly updated.

Rule 6 (line number matching) and Rule 7 (naming sections when comparing) are important additions that improve output quality and consistency with the new schema structure.


56-68: loadDirective function unchanged and correct.

The function properly handles the precedence chain (project override → built-in) with appropriate error handling. The empty catch block is acceptable here since the intent is to gracefully fall back to the built-in directive.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @src/prompts/directive-loader.ts:
- Around line 33-44: The documentation has inconsistent thresholds: the line
containing "SENTENCE-level (quoted_text is >5 words)" conflicts with the
CRITICAL rule "If quoted_text is longer than 4 words"; update the SENTENCE-level
wording to "SENTENCE-level (quoted_text is >4 words)" so it matches the CRITICAL
rule and any other references; locate the two strings "SENTENCE-level
(quoted_text is >5 words)" and "If quoted_text is longer than 4 words" in
directive-loader.ts and make the first one use ">4" to ensure the threshold is
consistent.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37dcff8 and 86f159e.

📒 Files selected for processing (9)
  • src/chunking/merger.ts
  • src/cli/commands.ts
  • src/cli/orchestrator.ts
  • src/cli/types.ts
  • src/prompts/directive-loader.ts
  • src/prompts/schema.ts
  • src/schemas/cli-schemas.ts
  • src/scoring/scorer.ts
  • tests/scoring-types.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Use TypeScript ESM with explicit imports and narrow types
Use 2-space indentation; avoid trailing whitespace
Maintain strict TypeScript with no any; use unknown + schema validation for external data
Use custom error types with proper inheritance; catch blocks use unknown type

Files:

  • src/chunking/merger.ts
  • src/cli/commands.ts
  • src/prompts/schema.ts
  • src/scoring/scorer.ts
  • src/schemas/cli-schemas.ts
  • src/cli/types.ts
  • src/prompts/directive-loader.ts
  • src/cli/orchestrator.ts
tests/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.test.ts: Write tests using Vitest framework with focus on config parsing, file discovery, schema/structured output, and locator
Use dependency injection in tests: mock providers; do not hit network in unit tests

Files:

  • tests/scoring-types.test.ts
🧠 Learnings (8)
📚 Learning: 2025-12-28T19:43:51.189Z
Learnt from: CR
Repo: TRocket-Labs/vectorlint PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T19:43:51.189Z
Learning: Applies to src/output/**/*.ts : IDs should be shown as `PromptId.CriterionId` in output

Applied to files:

  • tests/scoring-types.test.ts
  • src/cli/types.ts
  • src/cli/orchestrator.ts
📚 Learning: 2025-12-28T19:43:51.189Z
Learnt from: CR
Repo: TRocket-Labs/vectorlint PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T19:43:51.189Z
Learning: Applies to tests/**/*.test.ts : Write tests using Vitest framework with focus on config parsing, file discovery, schema/structured output, and locator

Applied to files:

  • tests/scoring-types.test.ts
📚 Learning: 2025-12-28T19:43:51.189Z
Learnt from: CR
Repo: TRocket-Labs/vectorlint PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T19:43:51.189Z
Learning: Keep directories cohesive; maintain acyclic dependencies (CLI → prompts/providers/output); optimize for discoverability

Applied to files:

  • src/cli/commands.ts
📚 Learning: 2025-12-28T19:43:51.189Z
Learnt from: CR
Repo: TRocket-Labs/vectorlint PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T19:43:51.189Z
Learning: Applies to src/providers/**/*.ts : Depend on `LLMProvider` and `SearchProvider` interfaces; keep providers thin (transport only)

Applied to files:

  • src/cli/commands.ts
📚 Learning: 2025-12-28T19:43:51.189Z
Learnt from: CR
Repo: TRocket-Labs/vectorlint PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T19:43:51.189Z
Learning: Applies to src/boundaries/env-parser.ts : All environment variables must be validated via Zod schemas in `src/boundaries/env-parser.ts`

Applied to files:

  • src/cli/commands.ts
  • src/schemas/cli-schemas.ts
📚 Learning: 2025-12-28T19:43:51.189Z
Learnt from: CR
Repo: TRocket-Labs/vectorlint PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T19:43:51.189Z
Learning: Recursively load all `.md` files from within each rule pack; multiple packs can be used simultaneously

Applied to files:

  • src/cli/commands.ts
📚 Learning: 2025-12-28T19:43:51.189Z
Learnt from: CR
Repo: TRocket-Labs/vectorlint PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T19:43:51.189Z
Learning: Organize rules into subdirectories (packs) within RulesPath; use company names (e.g., Acme, TechCorp, Stripe) to indicate which style guide the rules implement

Applied to files:

  • src/cli/commands.ts
📚 Learning: 2025-12-28T19:43:51.189Z
Learnt from: CR
Repo: TRocket-Labs/vectorlint PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-28T19:43:51.189Z
Learning: Applies to src/boundaries/**/*.ts : Use Zod schemas for boundary validation of all external data (files, CLI, env, APIs) at system boundaries

Applied to files:

  • src/schemas/cli-schemas.ts
🧬 Code graph analysis (2)
src/cli/commands.ts (5)
src/config/constants.ts (1)
  • DEFAULT_CONFIG_FILENAME (12-12)
src/errors/index.ts (1)
  • handleUnknownError (46-51)
src/config/preset-loader.ts (1)
  • PresetLoader (5-52)
src/boundaries/rule-pack-loader.ts (1)
  • RulePackLoader (12-95)
src/providers/perplexity-provider.ts (1)
  • PerplexitySearchProvider (11-54)
src/cli/orchestrator.ts (1)
src/providers/token-usage.ts (1)
  • calculateCost (21-30)
🔇 Additional comments (23)
src/chunking/merger.ts (1)

8-14: LGTM!

The deduplication key update correctly replaces analysis with message, maintaining consistency with the new violation schema. The composite key construction and normalization logic remain sound.

src/scoring/scorer.ts (4)

56-64: LGTM!

The violation mapping correctly adopts the new issue and message fields while preserving the optional field handling pattern.


178-185: LGTM!

The type definition for aggregated violations correctly includes the new issue and message fields.


214-224: LGTM!

Violation collection correctly extracts issue and message with appropriate fallbacks for missing values.


254-264: LGTM!

The deduplication key correctly uses message instead of analysis. The two-component key (quoted_text + message) is appropriate here since violations are already grouped by criterion name within criteriaMap.

tests/scoring-types.test.ts (3)

32-32: LGTM!

The pack property addition aligns with the updated PromptFile type.


100-118: LGTM!

The mock violation data correctly includes both issue and message fields, reflecting the updated schema structure. The test assertions remain valid for verifying scoring behavior.


188-188: LGTM!

Consistent pack property addition for technical accuracy test data.

src/schemas/cli-schemas.ts (1)

8-9: LGTM!

The suggest option follows the established pattern for boolean CLI options with a false default. The Zod schema provides proper boundary validation as per coding guidelines.

src/cli/commands.ts (3)

40-40: LGTM!

The --suggest option is correctly registered with Commander, following the established pattern for boolean flags.


208-223: LGTM!

The suggest parameter is correctly threaded through to the evaluateFiles orchestrator call, enabling conditional suggestion output based on the CLI flag.


100-103: LGTM!

Useful verbose logging addition for debugging directive-related issues.

src/prompts/directive-loader.ts (1)

24-28: Clear separation of issue and message with scope-aware guidance.

The new structure clearly defines:

  • issue: Problem description without quoted_text (5-12 words)
  • message: User-facing output with scope-dependent formatting

This aligns well with the PR objective of enabling scope-aware message formatting.

src/cli/types.ts (2)

37-37: New suggest flag properly propagated through options.

The optional suggest boolean is correctly added to EvaluationOptions, enabling CLI control over suggestion visibility.


81-94: Violation structure updated to use issue/message pair.

The ProcessViolationsParams.violations type now includes issue?: string and message?: string, replacing the previous analysis field. All fields remain optional to handle partial data gracefully.

src/prompts/schema.ts (3)

36-46: Subjective schema correctly updated with required issue and message fields.

The schema now requires both issue and message for violations, replacing the previous analysis field. The TypeScript type SubjectiveLLMResult (lines 110-111) aligns with this schema.


79-91: Semi-objective schema updated consistently.

Both issue and message are added to the schema and marked as required (lines 88-89), with corresponding type updates in SemiObjectiveLLMResult (lines 120-121).


152-160: SemiObjectiveItem type correctly reflects the new structure.

The type replaces analysis with issue and message fields, maintaining consistency with the schema definition.

src/cli/orchestrator.ts (5)

245-248: Suggestion visibility logic is well-documented and correct.

The includeSuggestion logic properly gates suggestions:

  • Line output: Only when --suggest flag is used
  • JSON formats: Always included for machine consumption

The inline comments clearly explain this behavior.


429-442: Violation type and suggest flag correctly propagated in subjective path.

The type cast at lines 424-432 properly includes issue? and message? fields. The suggest flag is coerced with !! for consistent boolean handling.


599-609: Improved type annotation for violation grouping.

The explicit generic type Map<string | undefined, typeof result.violations> enhances type safety for the criterion-grouped violations map.


1019-1025: Formatting improvement for readability.

The multi-line formatting of the calculateCost call improves readability without changing behavior.


193-196: The violation schema defines message and issue as distinct fields with separate purposes. Both are required in the LLM response schema and handled independently throughout the codebase (see src/prompts/schema.ts and scorer.ts). Using message for the displayed summary is the intended design. The defensive fallback to an empty string is safe and prevents crashes; there is no evidence that issue should be used as a fallback for message.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/prompts/schema.ts (1)

117-127: Schema-type mismatch: suggestion is required in schema but optional in type.

The buildSemiObjectiveLLMSchema marks suggestion as required (line 90), but SemiObjectiveLLMResult declares it as optional (suggestion?: string). This inconsistency could cause runtime validation failures when the LLM omits the suggestion field.

Either make suggestion required in the type or remove it from the required array in the schema for consistency.

Proposed fix (Option A - make type required)
 export type SemiObjectiveLLMResult = {
   violations: Array<{
     description: string;
     issue: string;
     message: string;
-    suggestion?: string;
+    suggestion: string;
     quoted_text?: string;
     context_before?: string;
     context_after?: string;
   }>;
 };
Proposed fix (Option B - make schema optional)
             required: [
               "quoted_text",
               "context_before",
               "context_after",
               "description",
               "issue",
               "message",
-              "suggestion",
             ],
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86f159e and 8351624.

📒 Files selected for processing (4)
  • src/cli/commands.ts
  • src/prompts/schema.ts
  • src/scoring/scorer.ts
  • tests/scoring-types.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/scoring-types.test.ts
  • src/cli/commands.ts
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Use TypeScript ESM with explicit imports and narrow types
Use 2-space indentation; avoid trailing whitespace
Maintain strict TypeScript with no any; use unknown + schema validation for external data
Use custom error types with proper inheritance; catch blocks use unknown type

Files:

  • src/scoring/scorer.ts
  • src/prompts/schema.ts
🔇 Additional comments (8)
src/prompts/schema.ts (4)

36-46: LGTM on the issue/message field additions.

The schema correctly defines both issue and message as required properties with proper string types. The structure aligns with the PR objectives for scope-aware message formatting.


79-91: LGTM on the semi-objective schema changes.

The issue and message fields are properly added to both the properties and required arrays, maintaining consistency with the subjective schema structure.


152-160: LGTM on the SemiObjectiveItem type update.

The type correctly reflects the new issue and message fields while maintaining optional fields for suggestion, quoted_text, and context fields.


170-178: LGTM on the SemiObjectiveResult violations type.

The violations array properly includes the new issue and message fields as required, with appropriate optional fields.

src/scoring/scorer.ts (4)

56-64: LGTM on the violation mapping.

The mapping correctly extracts issue and message from SemiObjectiveItem and properly uses conditional spreads for optional fields.


171-188: LGTM on the type definition update.

The violations array type correctly reflects the new issue and message fields, maintaining consistency with the schema types defined in schema.ts.


214-222: LGTM on violation collection.

The fallback to empty strings (v.issue || "", v.message || "") provides safe defaults, consistent with how other fields are handled.


254-263: LGTM on the deduplication key update.

Using message for the deduplication key is a sensible choice since it represents the unique user-facing description of each violation. The composite key combining quoted_text and message provides good uniqueness guarantees.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/prompts/schema.ts (1)

117-127: Type/schema mismatch for optional fields.

The SemiObjectiveLLMResult type marks quoted_text, context_before, and context_after as optional (lines 123-125), but the JSON schema in buildSemiObjectiveLLMSchema (lines 83-86) lists them as required. This inconsistency can cause type-safety issues when parsing LLM responses.

Either update the type to make these fields required, or remove them from the schema's required array.

Option 1: Make type fields required to match schema
 export type SemiObjectiveLLMResult = {
   violations: Array<{
     description: string;
     issue: string;
     message: string;
     suggestion: string;
-    quoted_text?: string;
-    context_before?: string;
-    context_after?: string;
+    quoted_text: string;
+    context_before: string;
+    context_after: string;
   }>;
 };
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8351624 and 9d7abf3.

📒 Files selected for processing (2)
  • src/prompts/directive-loader.ts
  • src/prompts/schema.ts
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Use TypeScript ESM with explicit imports and narrow types
Use 2-space indentation; avoid trailing whitespace
Maintain strict TypeScript with no any; use unknown + schema validation for external data
Use custom error types with proper inheritance; catch blocks use unknown type

Files:

  • src/prompts/directive-loader.ts
  • src/prompts/schema.ts
🔇 Additional comments (7)
src/prompts/schema.ts (3)

26-51: Schema changes look correct.

The issue and message fields are properly added to the violations schema with correct types. The required array is updated appropriately. Note that line remains optional (not in required), which appears intentional for cases where line numbers cannot be determined.


68-91: Semi-objective schema correctly updated.

The schema properly adds issue and message as required fields while retaining description for this evaluation type. The field structure is consistent with the TypeScript type definition below.


152-180: Processed result types correctly updated.

The SemiObjectiveItem and SemiObjectiveResult types properly include issue and message fields. The optional markers on suggestion, quoted_text, context_before, and context_after are appropriate for these processed/downstream types.

src/prompts/directive-loader.ts (4)

24-28: Clear guidance for issue/message distinction.

The directive clearly explains the new issue and message fields with scope-based formatting rules. The examples demonstrate the expected format for WORD-level vs SENTENCE/SECTION/DOCUMENT-level messages.


31-44: Well-structured examples with clear scope distinctions.

The MESSAGE EXAMPLES section provides concrete illustrations for each scope level (WORD, SENTENCE, SECTION). The critical rule about the 4-word threshold is prominently highlighted.


47-54: Critical rules properly updated.

Rule 6 (line number matching) and Rule 7 (naming sections when comparing) are important additions that improve output quality and consistency with the new schema structure.


56-68: loadDirective function unchanged and correct.

The function properly handles the precedence chain (project override → built-in) with appropriate error handling. The empty catch block is acceptable here since the intent is to gracefully fall back to the built-in directive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments