tenseleyflow/loader / 65ebf4a

Browse files

Compact setup handoffs

Authored by espadonne
SHA
65ebf4ac53fe2b7e9583b475f9fbbf64568765cd
Parents
39d15a6
Tree
5bbcfdd

2 changed files

StatusFile+-
M src/loader/runtime/tool_batches.py 49 5
M tests/test_tool_batches.py 7 1
src/loader/runtime/tool_batches.pymodified
@@ -801,7 +801,7 @@ class ToolBatchRunner:
801801
             project_root=self.context.project_root,
802802
             missing_artifact=missing_artifact,
803803
         )
804
-        has_artifact_progress = _has_confirmed_artifact_progress(
804
+        has_file_artifact_progress = _has_confirmed_file_artifact_progress(
805805
             dod,
806806
             project_root=self.context.project_root,
807807
         )
@@ -813,7 +813,7 @@ class ToolBatchRunner:
813813
             missing_artifact=missing_artifact,
814814
             project_root=self.context.project_root,
815815
         ):
816
-            if not has_artifact_progress:
816
+            if not has_file_artifact_progress:
817817
                 compact_handoff = _compact_missing_artifact_handoff(
818818
                     missing_artifact,
819819
                     project_root=self.context.project_root,
@@ -929,10 +929,27 @@ class ToolBatchRunner:
929929
         )
930930
 
931931
         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
+        )
932936
         todo_refresh = _todo_refresh_guidance(
933937
             dod,
934938
             project_root=self.context.project_root,
935939
         )
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
936953
         if _late_stage_missing_artifact_build(
937954
             dod,
938955
             project_root=self.context.project_root,
@@ -1327,6 +1344,32 @@ def _has_confirmed_artifact_progress(
13271344
     return bool(dod.touched_files)
13281345
 
13291346
 
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
+
13301373
 def _missing_artifact_resume_suffix(
13311374
     missing_artifact: tuple[Path, bool] | None,
13321375
     *,
@@ -1429,8 +1472,8 @@ def _compact_missing_artifact_handoff(
14291472
                 f"for `{target}` now."
14301473
             )
14311474
         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."
14341477
         )
14351478
         if not next_output_file.parent.exists():
14361479
             guidance += (
@@ -1440,7 +1483,8 @@ def _compact_missing_artifact_handoff(
14401483
         return guidance
14411484
 
14421485
     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."
14441488
     )
14451489
     if not target.parent.exists():
14461490
         guidance += (
tests/test_tool_batches.pymodified
@@ -1966,7 +1966,13 @@ async def test_tool_batch_runner_missing_artifact_nudge_prefers_pending_index_af
19661966
 
19671967
     assert queued_messages
19681968
     message = queued_messages[-1]
1969
-    assert "Resume by creating `index.html` now." in message
1969
+    assert "Next step: create `index.html`." in message
1970
+    assert (
1971
+        f"Prefer one `write(file_path=..., content=...)` call for `{(nginx_root / 'index.html').resolve(strict=False)}` now."
1972
+        in message
1973
+    )
1974
+    assert "One declared output artifact is still missing." not in message
1975
+    assert "Do not reread reference material or spend the next turn on bookkeeping." in message
19701976
     assert "Resume by creating the next output file under `chapters/` now." not in message
19711977
 
19721978