fix: build patches from complete target context

This commit is contained in:
thanhnv
2026-07-18 13:44:20 +07:00
parent 850be145d7
commit c0a6dbc25f
2 changed files with 120 additions and 15 deletions
@@ -43,6 +43,43 @@ class GoalPatchWorkflowTests(unittest.TestCase):
with self.assertRaisesRegex(ValueError, "goal_patch_check_failed"):
ORCHESTRATOR.validate_write_output(truncated)
def test_hunk_counts_and_blank_context_are_repaired_deterministically(self):
corrupt = (
"diff --git a/apps/okr/frontend/a.ts b/apps/okr/frontend/a.ts\n"
"--- a/apps/okr/frontend/a.ts\n+++ b/apps/okr/frontend/a.ts\n"
"@@ -10,8 +10,9 @@\n context\n-old\n+new\n\n tail\n"
)
normalized = ORCHESTRATOR.normalize_unified_diff(corrupt)
self.assertIn("@@ -10,4 +10,4 @@", normalized)
self.assertIn("\n \n tail\n", normalized)
def test_write_validation_uses_normalized_patch_after_corrupt_error(self):
corrupt = "diff --git a/a b/a\n--- a/a\n+++ b/a\n@@ -1,9 +1,9 @@\n-old\n+new\n"
with patch.object(ORCHESTRATOR, "validate_patch_check", side_effect=[ValueError("goal_patch_check_failed:error: corrupt patch at line 7"), None]) as check:
normalized = ORCHESTRATOR.validate_write_output(corrupt)
self.assertIn("@@ -1,1 +1,1 @@", normalized)
self.assertEqual(check.call_count, 2)
def test_truncated_replacement_is_not_reinterpreted_as_deletion(self):
truncated = "diff --git a/a b/a\n--- a/a\n+++ b/a\n@@ -1,1 +1,1 @@\n-old\n"
self.assertEqual(ORCHESTRATOR.normalize_unified_diff(truncated), truncated)
def test_write_context_keeps_the_most_relevant_target_file_complete(self):
raw = "export function KeyResultDetail() {\n" + (" return null;\n" * 180) + "}\n"
candidates = [
(20, "apps/okr/frontend/src/pages/KeyResultDetail.tsx", raw),
(5, "docs/technical_architecture.md", "architecture" * 400),
]
project = {"domain": "OKR", "domain_root": "apps/okr", "roots": []}
with tempfile.TemporaryDirectory() as directory, \
patch.object(ORCHESTRATOR, "registered_project", return_value=project), \
patch.object(ORCHESTRATOR, "context_candidates", return_value=candidates), \
patch.object(ORCHESTRATOR, "scan", side_effect=lambda text, mode: (True, text)):
bundle, manifest, _ = ORCHESTRATOR.build_context(os.path.join(directory, "goal.json"), "okr", "KeyResultDetail", True)
self.assertIn(raw.strip(), bundle)
self.assertEqual(manifest["files"][0]["characters"], len(raw.strip()))
self.assertFalse(manifest["files"][0]["truncated"])
def test_invalid_write_output_gets_one_bounded_repair_attempt(self):
repaired = "```diff\ndiff --git a/apps/okr/frontend/a.ts b/apps/okr/frontend/a.ts\n--- a/apps/okr/frontend/a.ts\n+++ b/apps/okr/frontend/a.ts\n@@ -1 +1 @@\n-a\n+b\n```"
with patch.dict(os.environ, {"CASAN_GOAL_PATCH_REPAIR_ATTEMPTS": "1"}, clear=False), \