Save fable pass discoveries

ober

ea9b19e10c42ffb9308060d1fa817a808a004fbd

diff --git a/data/cookbooks.sexp b/data/cookbooks.sexp
index b06594f..6439645 100644
--- a/data/cookbooks.sexp
+++ b/data/cookbooks.sexp
@@ -6202,4 +6202,17 @@
      "blob" "load-shared-object")
    ("title"
      .
-     "Finalize SQLite native statements and reread oversized columns")))
+     "Finalize SQLite native statements and reread oversized columns"))
+ (("code"
+    .
+    "(import (jerboa prelude))\n(import (chezscheme))\n\n(def (delete-file-if-exists path)\n  (when (file-exists? path)\n    (delete-file path)))\n\n(def (atomic-write-string path contents)\n  ;; Keep the temp file in the same directory so rename-file is atomic.\n  (let ([tmp (string-append path \".tmp.\" (number->string (get-process-id)))])\n    (dynamic-wind\n      (lambda () (void))\n      (lambda ()\n        (delete-file-if-exists tmp)\n        (write-file-string tmp contents)\n        (rename-file tmp path))\n      (lambda ()\n        (when (file-exists? tmp)\n          (delete-file tmp))))))")
+   ("id" . "atomic-write-string-rename-file")
+   ("imports" "(jerboa prelude)" "(chezscheme)")
+   ("notes"
+     .
+     "Create the temp file next to the destination; cross-directory renames are not guaranteed atomic. Chez/Jerboa `rename-file` replaces the existing target on the tested platforms, so a fully-written temp file can be moved into place without exposing partial contents. Use `dynamic-wind` cleanup so failed writes, failed renames, or exceptions remove the temp file.")
+   ("tags" "file-io" "atomic-write" "rename-file" "dynamic-wind"
+     "cleanup" "temp-file")
+   ("title"
+     .
+     "Atomically replace a text file with rename-file cleanup")))
diff --git a/data/features.sexp b/data/features.sexp
index 0975466..1f5ea94 100644
--- a/data/features.sexp
+++ b/data/features.sexp
@@ -2244,7 +2244,7 @@
    ("use_case"
      .
      "Validate Jerboa snippets through MCP without rewriting examples to avoid #f sentinels or false-valued consequents.")
-   ("votes" . 0))
+   ("votes" . 1))
  (("description"
     .
     "FFI-heavy Jerboa projects often need environment variables such as JERBOA_QT_LIB, JERBOA_QT_SHIM_DIR, DYLD_LIBRARY_PATH, LD_LIBRARY_PATH, or QT_QPA_PLATFORM before importing a module. jerboa_verify currently runs in a fixed environment, so Qt modules can fail during import with a shared-library load error even when the project builds and tests correctly under Makefile-provided env vars.")
@@ -2761,4 +2761,23 @@
    ("use_case"
      .
      "Verifying tests or scripts that import native-backed modules before running Makefile targets.")
+   ("votes" . 0))
+ (("description"
+    .
+    "Long-running Jerboa MCP calls can fail at the outer `tools/call` timeout boundary with only `timed out awaiting tools/call`, even when the underlying tool was doing useful work. Tools such as the compact dispatcher, jerboa_howto, jerboa_verify, and jerboa_check_balance should either emit phase progress before the outer timeout or return a structured timeout result that names the phase, file, elapsed time, and suggested fallback.")
+   ("estimated_token_reduction"
+     .
+     "~500-1500 tokens per timeout by avoiding repeated retries and manual fallback explanation.")
+   ("example_scenario"
+     .
+     "During a robustness pass, dispatcher search timed out after 120s, then jerboa_verify/check_balance timed out on larger files such as mcp/server.ss and support/data-check.ss. Direct make/data-check gates had to be used, but the MCP result did not say which phase hung or whether any partial diagnostics existed.")
+   ("id" . "mcp-tool-timeout-phase-progress")
+   ("impact" . "medium")
+   ("tags" "mcp" "timeout" "verify" "diagnostics" "progress")
+   ("title"
+     .
+     "Return phase progress when MCP tool calls time out")
+   ("use_case"
+     .
+     "When mandatory Jerboa MCP verification tools run longer than the client timeout, callers need actionable fallback guidance instead of a generic transport timeout.")
    ("votes" . 0)))