tenseleyflow/loader / 5a69d33

Browse files

Force verify after post-build blocks

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
5a69d33642b1626c967de0bb8c2094a78317d6bc
Parents
85c1cee
Tree
9e2019c

2 changed files

StatusFile+-
M src/loader/runtime/tool_batches.py 18 1
M tests/test_tool_batches.py 73 0
src/loader/runtime/tool_batches.pymodified
@@ -792,7 +792,11 @@ class ToolBatchRunner:
792792
     ) -> None:
793793
         """Keep post-build review anchored to the generated artifact set."""
794794
 
795
-        if "[Blocked - completed artifact set scope:" not in event_content:
795
+        blocked_completed_scope = (
796
+            "[Blocked - completed artifact set scope:" in event_content
797
+        )
798
+        blocked_post_build_audit = "[Blocked - post-build audit loop:" in event_content
799
+        if not blocked_completed_scope and not blocked_post_build_audit:
796800
             return
797801
 
798802
         planned_roots: list[str] = []
@@ -811,6 +815,14 @@ class ToolBatchRunner:
811815
             dod,
812816
             project_root=self.context.project_root,
813817
         )
818
+        verification_commands = dod.verification_commands or derive_verification_commands(
819
+            dod,
820
+            project_root=self.context.project_root,
821
+            task_statement=getattr(self.context.session, "current_task", "") or "",
822
+            supplement_existing=True,
823
+        )
824
+        if verification_commands:
825
+            self.context.set_workflow_mode("verify")
814826
         roots_preview = ", ".join(f"`{root}`" for root in planned_roots[:2])
815827
         if len(planned_roots) > 2:
816828
             roots_preview += ", ..."
@@ -820,6 +832,11 @@ class ToolBatchRunner:
820832
                 f"Stay within the current output roots under {roots_preview} and continue "
821833
                 f"with `{next_pending}` using the generated files as the source of truth. "
822834
                 "Do not reopen earlier reference materials."
835
+                + (
836
+                    " Verification should run next using those generated files."
837
+                    if verification_commands
838
+                    else ""
839
+                )
823840
             )
824841
             return
825842
 
tests/test_tool_batches.pymodified
@@ -6132,9 +6132,82 @@ def test_tool_batch_runner_blocked_completed_artifact_scope_nudge_prefers_verifi
61326132
     )
61336133
 
61346134
     assert queued
6135
+    assert context.workflow_mode == "verify"
61356136
     assert "All explicitly planned artifacts already exist." in queued[0]
61366137
     assert "Verify all guide files are linked and complete" in queued[0]
61376138
     assert "Do not reopen earlier reference materials." in queued[0]
6139
+    assert "Verification should run next" in queued[0]
6140
+
6141
+
6142
+def test_tool_batch_runner_blocked_post_build_audit_nudge_switches_to_verify(
6143
+    temp_dir: Path,
6144
+) -> None:
6145
+    async def assess_confidence(
6146
+        tool_name: str,
6147
+        tool_args: dict,
6148
+        context: str,
6149
+    ) -> ConfidenceAssessment:
6150
+        raise AssertionError("Confidence scoring should be disabled in this scenario")
6151
+
6152
+    async def verify_action(
6153
+        tool_name: str,
6154
+        tool_args: dict,
6155
+        result: str,
6156
+        expected: str = "",
6157
+    ) -> ActionVerification:
6158
+        raise AssertionError("Verification should not run in this scenario")
6159
+
6160
+    guide_root = temp_dir / "guide"
6161
+    chapters = guide_root / "chapters"
6162
+    guide_root.mkdir(parents=True)
6163
+    chapters.mkdir()
6164
+    index_path = guide_root / "index.html"
6165
+    chapter_one = chapters / "01-getting-started.html"
6166
+    chapter_two = chapters / "02-installation.html"
6167
+    index_path.write_text("index")
6168
+    chapter_one.write_text("one")
6169
+    chapter_two.write_text("two")
6170
+
6171
+    implementation_plan = temp_dir / "implementation.md"
6172
+    implementation_plan.write_text(
6173
+        "\n".join(
6174
+            [
6175
+                "# Implementation Plan",
6176
+                "",
6177
+                "## File Changes",
6178
+                f"- `{guide_root}`",
6179
+                f"- `{chapters}`",
6180
+                f"- `{index_path}`",
6181
+                f"- `{chapter_one}`",
6182
+                f"- `{chapter_two}`",
6183
+                "",
6184
+            ]
6185
+        )
6186
+    )
6187
+
6188
+    context = build_context(
6189
+        temp_dir=temp_dir,
6190
+        messages=[],
6191
+        safeguards=FakeSafeguards(),
6192
+        assess_confidence=assess_confidence,
6193
+        verify_action=verify_action,
6194
+    )
6195
+    queued: list[str] = []
6196
+    context.queue_steering_message_callback = queued.append
6197
+    runner = ToolBatchRunner(context, DefinitionOfDoneStore(temp_dir))
6198
+    dod = create_definition_of_done("Create a multi-file guide from a reference")
6199
+    dod.implementation_plan = str(implementation_plan)
6200
+    dod.verification_commands = [f"ls -la {guide_root}"]
6201
+
6202
+    runner._queue_blocked_completed_artifact_scope_nudge(
6203
+        "[Blocked - post-build audit loop: all explicitly planned artifacts already exist.]",
6204
+        dod=dod,
6205
+    )
6206
+
6207
+    assert queued
6208
+    assert context.workflow_mode == "verify"
6209
+    assert "All explicitly planned artifacts already exist." in queued[0]
6210
+    assert "move to verification or final confirmation" in queued[0]
61386211
 
61396212
 
61406213
 def test_tool_batch_runner_blocked_html_declared_target_nudge_uses_closest_declared_target(