diff --git a/CHANGELOG.md b/CHANGELOG.md index d42fc52a..2b775f76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ - `evaluations run` opens the database read-only outside the population phase, so an embedder identity differing from the stored one warns instead of aborting the run. - `docs/installation.md` documents the `jina`, `s3` and `ingester` extras, names the extras the full package actually pulls, drops the removed MixedBread AI reranker, and no longer lists Anthropic as a built-in provider. - `docs/tuning.md` no longer points at the removed `claim_timeout_s` setting. -- `analysis.code_timeout` is checked before each document read; code that reads in a loop no longer overruns it by the duration of the outstanding reads. +- `analysis.code_timeout` is enforced before each document read, bounding a call that reads in a loop. - `metadata.json` in the document VFS rejects writes, matching `content.txt`, `items.jsonl` and `toc.json`. ### Removed diff --git a/haiku_rag_slim/haiku/rag/sandbox/sandbox.py b/haiku_rag_slim/haiku/rag/sandbox/sandbox.py index f808ccf9..0812e250 100644 --- a/haiku_rag_slim/haiku/rag/sandbox/sandbox.py +++ b/haiku_rag_slim/haiku/rag/sandbox/sandbox.py @@ -415,8 +415,8 @@ class Sandbox: ensure_ascii=False, ) - # A MemoryFile accepts writes, so mount metadata.json through the - # same read and deny pair as the rest. The content is already built. + # MemoryFile has no write hook, so metadata.json goes through the + # same read and deny pair as the rest. Its content is already built. files.append( CallbackFile( f"{doc_dir}/metadata.json", @@ -472,9 +472,9 @@ class Sandbox: Monty spends ``max_duration_secs`` across the session's whole life, and the session is reused so variables persist between calls. Budget it for the run rather than for one call, or the first slow call starves every - later one. ``code_timeout`` is enforced per call by the read deadline in - ``_run_on_loop``. This is the backstop for code that computes without - reading, and one such call can spend all of it. + later one. ``code_timeout`` is enforced per call elsewhere: the read + deadline in ``_run_on_loop`` bounds a call that reads, and the pool's + ``request_timeout`` bounds one that computes. """ analysis = self._config.analysis return {"max_duration_secs": analysis.code_timeout * analysis.max_executions} diff --git a/tests/sandbox/test_sandbox.py b/tests/sandbox/test_sandbox.py index 21d148a6..90423a5a 100644 --- a/tests/sandbox/test_sandbox.py +++ b/tests/sandbox/test_sandbox.py @@ -894,7 +894,7 @@ class TestSandboxWorkerCrash: assert crashed.success is False assert "restarted" in crashed.stderr - # Without the discard this raises RuntimeError out of execute(). + # Without the discard every later call fails on the dead session. recovered = await sb.execute("print(3)") assert recovered.success, recovered.stderr assert "3" in recovered.stdout