tenseleyflow/loader / d37b2b4

Browse files

Advance blank child retries

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
d37b2b4e8478de96ad2e51de5ed6357dd614eb4f
Parents
d647e20
Tree
341a6d2

2 changed files

StatusFile+-
M src/loader/runtime/repair.py 2 2
M tests/test_repair.py 90 2
src/loader/runtime/repair.pymodified
@@ -383,7 +383,7 @@ class ResponseRepairer:
383383
         retry_number: int,
384384
         max_empty_retries: int,
385385
     ) -> str | None:
386
-        if retry_number < 3:
386
+        if retry_number < 2:
387387
             return None
388388
         if not self._has_confirmed_output_file_progress(dod):
389389
             return None
@@ -1588,7 +1588,7 @@ class ResponseRepairer:
15881588
         retry_number: int,
15891589
         outline_label: str | None,
15901590
     ) -> str | None:
1591
-        if not require_first_substantive_output or retry_number < 4:
1591
+        if not require_first_substantive_output or retry_number < 2:
15921592
             return None
15931593
         if target.suffix.lower() not in {".html", ".htm"}:
15941594
             return None
tests/test_repair.pymodified
@@ -1360,6 +1360,91 @@ def test_compact_first_substantive_retry_reuses_known_reference_structure(
13601360
         "of `<h2>` sections with short body text, and a back link to `../index.html`."
13611361
         in decision.retry_message
13621362
     )
1363
+    assert (
1364
+        "If blanking continues, use this minimal HTML starter as the `content` value "
1365
+        "and adapt it:"
1366
+        in decision.retry_message
1367
+    )
1368
+
1369
+
1370
+def test_first_substantive_retry_activates_on_second_empty_turn(
1371
+    temp_dir: Path,
1372
+) -> None:
1373
+    context = build_context(
1374
+        temp_dir=temp_dir,
1375
+        use_react=False,
1376
+    )
1377
+    repairer = ResponseRepairer(context)
1378
+
1379
+    guide_root = temp_dir / "guides" / "nginx"
1380
+    chapters = guide_root / "chapters"
1381
+    chapters.mkdir(parents=True)
1382
+    index_path = guide_root / "index.html"
1383
+    reference_chapter = temp_dir / "guides" / "fortran" / "chapters" / "01-introduction.html"
1384
+    reference_chapter.parent.mkdir(parents=True)
1385
+    reference_chapter.write_text("<h1>Chapter 1: Introduction to Fortran</h1>\n")
1386
+    index_path.write_text(
1387
+        "\n".join(
1388
+            [
1389
+                "<html>",
1390
+                '<a href="chapters/01-introduction.html">Chapter 1: Introduction to Nginx</a>',
1391
+                "</html>",
1392
+            ]
1393
+        )
1394
+        + "\n"
1395
+    )
1396
+    context.session.append(
1397
+        Message(
1398
+            role=Role.ASSISTANT,
1399
+            content="",
1400
+            tool_calls=[
1401
+                ToolCall(
1402
+                    id="call_ref",
1403
+                    name="read",
1404
+                    arguments={"file_path": str(reference_chapter)},
1405
+                )
1406
+            ],
1407
+        )
1408
+    )
1409
+
1410
+    implementation_plan = temp_dir / "implementation.md"
1411
+    implementation_plan.write_text(
1412
+        "\n".join(
1413
+            [
1414
+                "# Implementation Plan",
1415
+                "",
1416
+                "## File Changes",
1417
+                f"- `{guide_root}/`",
1418
+                f"- `{chapters}/`",
1419
+                f"- `{index_path}`",
1420
+                "",
1421
+            ]
1422
+        )
1423
+    )
1424
+
1425
+    dod = create_definition_of_done("Create a multi-file nginx guide.")
1426
+    dod.implementation_plan = str(implementation_plan)
1427
+    dod.touched_files.append(str(index_path))
1428
+    dod.completed_items.append("Develop the main index.html file with proper structure")
1429
+    dod.pending_items.append("Create the nginx chapters content")
1430
+
1431
+    decision = repairer.handle_empty_response(
1432
+        task="Create a multi-file nginx guide.",
1433
+        original_task=None,
1434
+        empty_retry_count=2,
1435
+        max_empty_retries=4,
1436
+        dod=dod,
1437
+    )
1438
+
1439
+    assert decision.should_continue is True
1440
+    assert decision.retry_message is not None
1441
+    assert "Emit this tool shape now" in decision.retry_message
1442
+    assert "01-introduction.html" in decision.retry_message
1443
+    assert (
1444
+        "If blanking continues, use this minimal HTML starter as the `content` value "
1445
+        "and adapt it:"
1446
+        in decision.retry_message
1447
+    )
13631448
 
13641449
 
13651450
 def test_late_first_substantive_retry_trims_context_to_core_write_cues(
@@ -1512,8 +1597,11 @@ def test_empty_response_retry_prefers_output_index_over_reference_index_with_sam
15121597
     assert decision.should_continue is True
15131598
     assert decision.retry_message is not None
15141599
     assert (
1515
-        "Prefer one `write(content=...)` call for "
1516
-        f"`{display_runtime_path(output_index)}` before more research."
1600
+        f"Continue `Develop the nginx index.html file` by creating `{output_index.name}`."
1601
+        in decision.retry_message
1602
+    )
1603
+    assert (
1604
+        f'Emit this tool shape now: `write(file_path="{display_runtime_path(output_index)}", content="...")`.'
15171605
         in decision.retry_message
15181606
     )
15191607
     assert str(reference_index) not in decision.retry_message