Recover verified runs from empty scaffold and MCP budget
ober
cf8a509e5a76673a86b55da9a1ad9f5df8edd476
--- a/src/jcode/core/verified-run.ss +++ b/src/jcode/core/verified-run.ss @@ -673,10 +673,10 @@ (params (or (hash-get fn "parameters") (make-hash-table)))) (make-tool-def (make-tool-spec name desc params) - (lambda (args) + (lambda (args) (or (rejected-draft-hard-recovery-message cwd name) (let ((msg (pre-edit-mcp-block-message name))) - (and msg (error 'mcp msg))) + (and msg (raise-recoverable-tool-error msg name))) (let ((msg (post-failed-verify-mcp-block-message name))) (and msg (error 'mcp @@ -3528,8 +3528,9 @@ (template-kind (normal-script-kind kind))) (cond ((not path) - (error 'create_verified_jerboa_script - "missing path arg; use {\"path\":\"main.ss\",\"kind\":\"minimal-pass\"}")) + (raise-recoverable-tool-error + "create_verified_jerboa_script requires a path. Do not retry empty create_verified_jerboa_script(). For this task use edit(path=\"life.ss\", content=<complete implementation>) rather than a generic scaffold, or call create_verified_jerboa_script(path=\"life.ss\", kind=\"minimal-pass\") only for a trivial starter." + 'create_verified_jerboa_script)) ((not (source-ss-path? path)) (error 'create_verified_jerboa_script (format "path must end in .ss for a Jerboa script: ~a" path))) --- a/test/run.ss +++ b/test/run.ss @@ -2467,6 +2467,42 @@ (safe-delete-test-file! target-path)) (let* ([vr-dir "/tmp"] + [target "jcode-verified-empty-scaffold-recovery.txt"] + [target-path (string-append vr-dir "/" target)] + [tool-results '()] + [wf (coding-workflow (string-append "grep -q ok " target) vr-dir)] + [resp (scripted-responder + (list + (list (make-wtool-call "create_verified_jerboa_script" '() #f)) + (list (make-wtool-call "edit" (list (cons "path" target) + (cons "content" "ok\n")) #f)) + (list (make-wtool-call "verify" '() #f)) + (list (make-wtool-call "done" '(("summary" . "empty-scaffold-recovered")) #f))))]) + (safe-delete-test-file! target-path) + (let ([result (run-workflow wf "recover from empty scaffold call" resp + (list (cons 'max-iterations 6) + (cons 'max-tool-errors 0) + (cons 'on-message + (lambda (m) + (when (equal? (message-role m) "tool") + (set! tool-results + (cons (message-content m) tool-results)))))))]) + (check! "verified-run: empty scaffold call recovers with zero hard errors" + result "empty-scaffold-recovered") + (check-pred! "verified-run: empty scaffold call gives recoverable path guidance" + (reverse tool-results) + (lambda (xs) + (let loop ([ys xs]) + (cond + [(null? ys) #f] + [(and (str-contains? (car ys) "[ToolRecoverableError]") + (str-contains? (car ys) "create_verified_jerboa_script requires a path") + (str-contains? (car ys) "edit(path=\"life.ss\"")) + #t] + [else (loop (cdr ys))]))))) + (safe-delete-test-file! target-path)) + +(let* ([vr-dir "/tmp"] [fixture "jcode-verified-run-budget-fixture.txt"] [fixture-path (string-append vr-dir "/" fixture)] [target "jcode-verified-run-budget-out.txt"] @@ -2766,6 +2802,7 @@ (cond [(null? ys) #f] [(and (str-contains? (car ys) "pre-edit MCP discovery limit reached") + (str-contains? (car ys) "[ToolRecoverableError]") (str-contains? (car ys) "edit/write with the first complete draft")) #t] [else (loop (cdr ys))]))))))