tenseleyflow/loader / 2a6f142

Browse files

Quiet setup handoffs

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
2a6f1423728d9d7b24edebe0ea6055e34950ef6c
Parents
4a458e4
Tree
222c875

2 changed files

StatusFile+-
M src/loader/runtime/tool_batches.py 21 0
M tests/test_tool_batches.py 2 11
src/loader/runtime/tool_batches.pymodified
@@ -2,6 +2,7 @@
22
 
33
 from __future__ import annotations
44
 
5
+import shlex
56
 from collections.abc import Awaitable, Callable
67
 from dataclasses import dataclass, field
78
 from pathlib import Path
@@ -1106,6 +1107,11 @@ class ToolBatchRunner:
11061107
             dod,
11071108
             project_root=self.context.project_root,
11081109
         )
1110
+        if (
1111
+            not has_file_artifact_progress
1112
+            and _is_pure_directory_creation_tool_call(tool_call)
1113
+        ):
1114
+            return
11091115
         resume_target = _preferred_resume_target_path(
11101116
             dod,
11111117
             next_pending=next_pending,
@@ -2112,6 +2118,21 @@ def _current_mutation_label(tool_call: ToolCall) -> str:
21122118
     return f"the successful `{tool_call.name}` result"
21132119
 
21142120
 
2121
+def _is_pure_directory_creation_tool_call(tool_call: ToolCall) -> bool:
2122
+    if tool_call.name != "bash":
2123
+        return False
2124
+    command = str(tool_call.arguments.get("command", "")).strip()
2125
+    if not command or any(
2126
+        operator in command for operator in ("&&", "||", ";", "|", "$(", ">", "<")
2127
+    ):
2128
+        return False
2129
+    try:
2130
+        parts = shlex.split(command)
2131
+    except ValueError:
2132
+        return False
2133
+    return bool(parts) and parts[0] == "mkdir"
2134
+
2135
+
21152136
 def _tool_call_label(tool_call: ToolCall) -> str:
21162137
     """Human-readable label for one tool call."""
21172138
     name = tool_call.name
tests/test_tool_batches.pymodified
@@ -2024,7 +2024,7 @@ async def test_tool_batch_runner_discovery_completion_handoff_stays_persistent(
20242024
 
20252025
 
20262026
 @pytest.mark.asyncio
2027
-async def test_tool_batch_runner_missing_artifact_nudge_prefers_pending_index_after_mkdir(
2027
+async def test_tool_batch_runner_missing_artifact_nudge_stays_quiet_after_setup_mkdir(
20282028
     temp_dir: Path,
20292029
 ) -> None:
20302030
     async def assess_confidence(
@@ -2119,16 +2119,7 @@ async def test_tool_batch_runner_missing_artifact_nudge_prefers_pending_index_af
21192119
         consecutive_errors=0,
21202120
     )
21212121
 
2122
-    assert persistent_messages
2123
-    message = persistent_messages[-1]
2124
-    assert "Next step: create `index.html`." in message
2125
-    assert (
2126
-        f"Prefer one `write(file_path=..., content=...)` call for `{(nginx_root / 'index.html').resolve(strict=False)}` now."
2127
-        in message
2128
-    )
2129
-    assert "One declared output artifact is still missing." not in message
2130
-    assert "Do not reread reference material or spend the next turn on bookkeeping." in message
2131
-    assert "Resume by creating the next output file under `chapters/` now." not in message
2122
+    assert persistent_messages == []
21322123
     assert ephemeral_messages == []
21332124
 
21342125