Compare commits

...

5 commits

Author SHA1 Message Date
YEJI KIM
58d99ab564
Merge 725a26ba88 into bf5da9a9fb 2025-12-11 16:29:25 +08:00
Hussam.lawen
bf5da9a9fb
docs: add configuration options for ticket analysis review in compliance tool
Some checks failed
Build-and-test / build-and-test (push) Has been cancelled
docs-ci / deploy (push) Has been cancelled
2025-12-10 10:48:55 +02:00
isExample
725a26ba88 docs: add inline comments explaining diff marker normalization logic 2025-10-11 02:05:55 +09:00
isExample
1a4df62f89 fix: normalize nested diff markers before YAML parsing 2025-10-11 01:31:31 +09:00
isExample
6561d0478e test: add regression test for diff markers in suggestion blocks 2025-10-11 01:31:06 +09:00
4 changed files with 107 additions and 5 deletions

View file

@ -54,17 +54,17 @@ A `PR Code Verified` label indicates the PR code meets ticket requirements, but
#### Configuration options #### Configuration options
- -
By default, the tool will automatically validate if the PR complies with the referenced ticket. By default, the `review` tool will automatically validate if the PR complies with the referenced ticket.
If you want to disable this feedback, add the following line to your configuration file: If you want to disable this feedback, add the following line to your configuration file:
```toml ```toml
[pr_reviewer] [pr_reviewer]
require_ticket_analysis_review=false require_ticket_analysis_review=false
``` ```
- -
If you set: If you set:
```toml ```toml
@ -72,9 +72,36 @@ A `PR Code Verified` label indicates the PR code meets ticket requirements, but
check_pr_additional_content=true check_pr_additional_content=true
``` ```
(default: `false`) (default: `false`)
the `review` tool will also validate that the PR code doesn't contain any additional content that is not related to the ticket. If it does, the PR will be labeled at best as `PR Code Verified`, and the `review` tool will provide a comment with the additional unrelated content found in the PR code. the `review` tool will also validate that the PR code doesn't contain any additional content that is not related to the ticket. If it does, the PR will be labeled at best as `PR Code Verified`, and the `review` tool will provide a comment with the additional unrelated content found in the PR code.
### Compliance tool
The `compliance` tool also uses ticket context to validate that PR changes fulfill the requirements specified in linked tickets.
#### Configuration options
-
By default, the `compliance` tool will automatically validate if the PR complies with the referenced ticket.
If you want to disable ticket compliance checking in the compliance tool, add the following line to your configuration file:
```toml
[pr_compliance]
require_ticket_analysis_review=false
```
-
If you set:
```toml
[pr_compliance]
check_pr_additional_content=true
```
(default: `false`)
the `compliance` tool will also validate that the PR code doesn't contain any additional content that is not related to the ticket.
## GitHub/Gitlab Issues Integration ## GitHub/Gitlab Issues Integration
Qodo Merge will automatically recognize GitHub/Gitlab issues mentioned in the PR description and fetch the issue content. Qodo Merge will automatically recognize GitHub/Gitlab issues mentioned in the PR description and fetch the issue content.

View file

@ -329,6 +329,10 @@ enable_global_pr_compliance = true
???+ example "Ticket compliance options" ???+ example "Ticket compliance options"
<table> <table>
<tr>
<td><b>require_ticket_analysis_review</b></td>
<td>If set to true, the tool will fetch and analyze ticket context for compliance validation. Default is true.</td>
</tr>
<tr> <tr>
<td><b>enable_ticket_labels</b></td> <td><b>enable_ticket_labels</b></td>
<td>If set to true, the tool will add ticket compliance labels to the PR. Default is false.</td> <td>If set to true, the tool will add ticket compliance labels to the PR. Default is false.</td>

View file

@ -868,6 +868,44 @@ def try_fix_yaml(response_text: str,
except: except:
pass pass
# 5.5 fallback - try to normalize diff-style removal markers ('-') within list items
response_text_lines_copy = response_text_lines.copy()
modified = False
for i, line in enumerate(response_text_lines_copy):
if line.startswith('+'):
response_text_lines_copy[i] = ' ' + line[1:]
modified = True
# normalize lines starting with '-'. Distinguish real YAML list items from diff deletions.
for i, line in enumerate(response_text_lines_copy):
if not line.startswith('-'):
continue
remainder = line[1:]
if line.startswith('- '):
second_char = remainder[1] if len(remainder) > 1 else ''
if second_char and second_char not in (' ', '\t', '+', '-'):
continue # real list item → keep as-is
# treat it as a diff "removed" marker inside block content
cleaned = remainder
while cleaned and cleaned[0] in ('+', '-'):
cleaned = cleaned[1:]
if cleaned and cleaned[0] not in (' ', '\t'):
cleaned = ' ' + cleaned
if cleaned != line:
response_text_lines_copy[i] = cleaned
modified = True
if modified:
try:
data = yaml.safe_load('\n'.join(response_text_lines_copy))
get_logger().info("Successfully parsed AI prediction after normalizing diff removal markers")
return data
except:
pass
# sixth fallback - replace tabs with spaces # sixth fallback - replace tabs with spaces
if '\t' in response_text: if '\t' in response_text:
response_text_copy = copy.deepcopy(response_text) response_text_copy = copy.deepcopy(response_text)

View file

@ -244,3 +244,36 @@ int sub(int a, int b) {
''' '''
expected_output = {'code_suggestions': [{'relevant_file': 'a.c\n', 'existing_code': ' int sum(int a, int b) {\n return a + b;\n }\n\n int sub(int a, int b) {\n return a - b;\n }\n'}]} expected_output = {'code_suggestions': [{'relevant_file': 'a.c\n', 'existing_code': ' int sum(int a, int b) {\n return a + b;\n }\n\n int sub(int a, int b) {\n return a - b;\n }\n'}]}
assert try_fix_yaml(review_text, first_key='code_suggestions', last_key='existing_code') == expected_output assert try_fix_yaml(review_text, first_key='code_suggestions', last_key='existing_code') == expected_output
def test_diff_markers_removed_within_list_item(self):
"""
Ensures diff-style '-' markers nested inside list items are normalised so the YAML parses
into the expected structure.
"""
review_text = '''\
code_suggestions:
- relevant_file: |
example.rb
existing_code: |
+ puts 'hello'
+ puts 'world'
- relevant_file: |
- example.py
- existing_code: |
-+ print('hello')
-+ print('world')
'''
expected_output = {
'code_suggestions': [
{
'relevant_file': 'example.rb\n',
'existing_code': "puts 'hello'\nputs 'world'\n"
},
{
'relevant_file': 'example.py\n',
'existing_code': "print('hello')\nprint('world')\n"
}
]
}
assert try_fix_yaml(review_text, first_key='code_suggestions', last_key='existing_code') == expected_output