@@ -801,7 +801,7 @@ class ToolBatchRunner: |
| 801 | 801 | project_root=self.context.project_root, |
| 802 | 802 | missing_artifact=missing_artifact, |
| 803 | 803 | ) |
| 804 | | - has_artifact_progress = _has_confirmed_artifact_progress( |
| 804 | + has_file_artifact_progress = _has_confirmed_file_artifact_progress( |
| 805 | 805 | dod, |
| 806 | 806 | project_root=self.context.project_root, |
| 807 | 807 | ) |
@@ -813,7 +813,7 @@ class ToolBatchRunner: |
| 813 | 813 | missing_artifact=missing_artifact, |
| 814 | 814 | project_root=self.context.project_root, |
| 815 | 815 | ): |
| 816 | | - if not has_artifact_progress: |
| 816 | + if not has_file_artifact_progress: |
| 817 | 817 | compact_handoff = _compact_missing_artifact_handoff( |
| 818 | 818 | missing_artifact, |
| 819 | 819 | project_root=self.context.project_root, |
@@ -929,10 +929,27 @@ class ToolBatchRunner: |
| 929 | 929 | ) |
| 930 | 930 | |
| 931 | 931 | current_label = _current_mutation_label(tool_call) |
| 932 | + has_file_artifact_progress = _has_confirmed_file_artifact_progress( |
| 933 | + dod, |
| 934 | + project_root=self.context.project_root, |
| 935 | + ) |
| 932 | 936 | todo_refresh = _todo_refresh_guidance( |
| 933 | 937 | dod, |
| 934 | 938 | project_root=self.context.project_root, |
| 935 | 939 | ) |
| 940 | + if not has_file_artifact_progress: |
| 941 | + compact_handoff = _compact_missing_artifact_handoff( |
| 942 | + missing_artifact, |
| 943 | + project_root=self.context.project_root, |
| 944 | + messages=list(getattr(self.context.session, "messages", []) or []), |
| 945 | + ) |
| 946 | + if compact_handoff: |
| 947 | + self.context.queue_steering_message( |
| 948 | + f"Confirmed progress: {current_label} is now recorded. " |
| 949 | + + compact_handoff |
| 950 | + + " Do not reread reference material or spend the next turn on bookkeeping." |
| 951 | + ) |
| 952 | + return |
| 936 | 953 | if _late_stage_missing_artifact_build( |
| 937 | 954 | dod, |
| 938 | 955 | project_root=self.context.project_root, |
@@ -1327,6 +1344,32 @@ def _has_confirmed_artifact_progress( |
| 1327 | 1344 | return bool(dod.touched_files) |
| 1328 | 1345 | |
| 1329 | 1346 | |
| 1347 | +def _has_confirmed_file_artifact_progress( |
| 1348 | + dod: DefinitionOfDone, |
| 1349 | + *, |
| 1350 | + project_root: Path, |
| 1351 | +) -> bool: |
| 1352 | + for target, expect_directory in collect_planned_artifact_targets( |
| 1353 | + dod, |
| 1354 | + project_root=project_root, |
| 1355 | + max_paths=12, |
| 1356 | + ): |
| 1357 | + if expect_directory: |
| 1358 | + continue |
| 1359 | + if planned_artifact_target_satisfied( |
| 1360 | + dod, |
| 1361 | + target=target, |
| 1362 | + expect_directory=False, |
| 1363 | + project_root=project_root, |
| 1364 | + ): |
| 1365 | + return True |
| 1366 | + return any( |
| 1367 | + Path(path).expanduser().resolve(strict=False).suffix |
| 1368 | + for path in dod.touched_files |
| 1369 | + if str(path).strip() |
| 1370 | + ) |
| 1371 | + |
| 1372 | + |
| 1330 | 1373 | def _missing_artifact_resume_suffix( |
| 1331 | 1374 | missing_artifact: tuple[Path, bool] | None, |
| 1332 | 1375 | *, |
@@ -1429,8 +1472,8 @@ def _compact_missing_artifact_handoff( |
| 1429 | 1472 | f"for `{target}` now." |
| 1430 | 1473 | ) |
| 1431 | 1474 | guidance = ( |
| 1432 | | - f"Next step: create `{next_output_file.name}`. Prefer one `write` call for " |
| 1433 | | - f"`{next_output_file}` now." |
| 1475 | + f"Next step: create `{next_output_file.name}`. Prefer one " |
| 1476 | + f"`write(file_path=..., content=...)` call for `{next_output_file}` now." |
| 1434 | 1477 | ) |
| 1435 | 1478 | if not next_output_file.parent.exists(): |
| 1436 | 1479 | guidance += ( |
@@ -1440,7 +1483,8 @@ def _compact_missing_artifact_handoff( |
| 1440 | 1483 | return guidance |
| 1441 | 1484 | |
| 1442 | 1485 | guidance = ( |
| 1443 | | - f"Next step: create `{label}`. Prefer one `write` call for `{target}` now." |
| 1486 | + f"Next step: create `{label}`. Prefer one " |
| 1487 | + f"`write(file_path=..., content=...)` call for `{target}` now." |
| 1444 | 1488 | ) |
| 1445 | 1489 | if not target.parent.exists(): |
| 1446 | 1490 | guidance += ( |