Avoid assistant prose for forced edit retry

ober

236e9b7033a6c6a75f7fa3b61548089c0522bda9

diff --git a/src/jcode/core/verified-run.ss b/src/jcode/core/verified-run.ss
index 3890bbf..1cde819 100644
--- a/src/jcode/core/verified-run.ss
+++ b/src/jcode/core/verified-run.ss
@@ -398,8 +398,7 @@
                                   '("edit" "write"))))
                 #t)
                (else (loop (cdr xs))))))
-    (make-text-response
-      "Forced first-edit turn rejected: the model called a hidden inspection or non-edit tool. Do not call read, list, balance, verify, or any other tool on this turn. Call exactly edit(path=<scoped target file>, content=<complete minimal acceptance-complete file body>) or write(path=<scoped target file>, content=<complete minimal acceptance-complete file body>) now.")
+    (make-text-response "JCODE_INTERNAL_FORCE_FIRST_EDIT_RETRY")
     response))
 
 (def (specified-tool-choice-supported? provider)
diff --git a/src/jcode/core/workflow-runner.ss b/src/jcode/core/workflow-runner.ss
index 58622c0..92a5938 100644
--- a/src/jcode/core/workflow-runner.ss
+++ b/src/jcode/core/workflow-runner.ss
@@ -360,6 +360,22 @@
        (message-content (car rev)))
       (else (loop (cdr rev))))))
 
+(def forced-first-edit-retry-marker
+  "JCODE_INTERNAL_FORCE_FIRST_EDIT_RETRY")
+
+(def (forced-first-edit-retry? content)
+  (and (string? content)
+       (string-prefix? forced-first-edit-retry-marker content)))
+
+(def (forced-first-edit-retry-message)
+  (string-append
+    "VERIFIED WORKFLOW REQUIRES A STRUCTURED TOOL CALL NOW. "
+    "The previous turn attempted a hidden inspection while only edit/write "
+    "were available. Do not explain, summarize, ask questions, read, list, "
+    "balance, verify, or call any other tool. Next response must be exactly "
+    "one structured edit(path=<scoped target file>, content=<complete file>) "
+    "or write(path=<scoped target file>, content=<complete file>) tool call."))
+
 (def (verified-text-retry-message workflow enforcer messages raw retry-count)
   (let* ((completed (step-enforcer-completed enforcer))
          (pending (step-enforcer-pending enforcer))
@@ -521,8 +537,11 @@
              (cond
                ;; Intentional text response — emit and consume an iteration.
 	               ((text-response? response)
-	                (let ((content (text-response-content response)))
-	                  (emit! (make-assistant-message content))
+	                (let* ((content (text-response-content response))
+                         (forced-first-edit-retry
+                           (forced-first-edit-retry? content)))
+	                  (unless forced-first-edit-retry
+                      (emit! (make-assistant-message content)))
 	                  (let ((tool-calls
 	                          (and text-response-tool-calls
 	                               (text-response-tool-calls content))))
@@ -543,10 +562,12 @@
 	                          "Model failed to produce a valid tool call after text-response retries."
 	                          content))
 	                      (emit! (make-user-message
-	                               (text-retry-message
+	                               (if forced-first-edit-retry
+                                     (forced-first-edit-retry-message)
+	                                 (text-retry-message
 	                                   workflow enforcer messages content
                                    (error-tracker-consecutive-retries
-                                     error-tracker))))
+                                       error-tracker)))))
 	                      (loop (+ iteration 1)))
 	                    (loop (+ iteration 1)))))))
 	               (else
diff --git a/test/run.ss b/test/run.ss
index ad4842a..270cd19 100644
--- a/test/run.ss
+++ b/test/run.ss
@@ -5865,6 +5865,7 @@
          [readme-path (string-append vr-dir "/" readme)]
          [forced-spec-names '()]
          [tool-results '()]
+         [seen-messages '()]
          [calls 0]
          [read-call
            (lambda (line)
@@ -5906,6 +5907,7 @@
                 (cons 'max-iterations 20)
                 (cons 'on-message
                   (lambda (m)
+                    (set! seen-messages (cons m seen-messages))
                     (when (equal? (message-role m) "tool")
                       (set! tool-results
                         (cons (message-content m) tool-results)))))))])
@@ -5925,7 +5927,32 @@
       (check! "verified-run: hidden remote read was not executed"
               (length (filter (lambda (s) (str-contains? s "context-"))
                               (reverse tool-results)))
-              10))
+              10)
+      (check! "verified-run: forced first-edit marker is not assistant prose"
+              (let loop ([xs seen-messages])
+                (cond
+                  [(null? xs) #f]
+                  [(and (equal? (message-role (car xs)) "assistant")
+                        (str-contains? (message-content (car xs))
+                                       "JCODE_INTERNAL_FORCE_FIRST_EDIT_RETRY"))
+                   #t]
+                  [else (loop (cdr xs))]))
+              #f)
+      (check-pred! "verified-run: forced first-edit retry recommends edit only"
+        seen-messages
+        (lambda (xs)
+          (let loop ([ys xs])
+            (cond
+              [(null? ys) #f]
+              [(and (equal? (message-role (car ys)) "user")
+                    (str-contains? (message-content (car ys))
+                                   "only edit/write")
+                    (str-contains? (message-content (car ys))
+                                   "one structured edit")
+                    (not (str-contains? (message-content (car ys))
+                                        "Invalid previous text excerpt")))
+               #t]
+              [else (loop (cdr ys))])))))
     (safe-delete-test-file! target-path)
     (safe-delete-test-file! readme-path))