routes: Re-classify Z576/evaluator_wasi_limit as 422 at orchestrator edge

Z576/evaluator_wasi_limit ("could not acquire a WASI runner in time") is the only resource-exhaustion error the orchestrator can emit that the shared function-schemata HTTP table maps to a 5xx (504/GATEWAY_TIMEOUT). Production has surfaced user-submitted Z7s that fan out enough parallel evaluator calls to saturate the runner pool, returning Z576 — and the user sees 504, suggesting "backend is down, retry" when shrinking the call is what's actually needed.

Diagnosed call shape (one example): Z23082(Q144, Z1002) composes down through Z23615 -> Z23604 -> Z23605 to "first element of (filter is_plural over (lexeme forms for Q144 in en))". The list of forms is large for a common item, the filter predicate Z22490 is a code implementation, and WFList realization issues those calls in parallel via Promise.all. The orchestrator's recursion guard checks call depth, not call width, so it doesn't catch this — fan-out hits the evaluator's runner pool first.

Fix at the orchestrator's response edge only: a small getOrchestratorHttpStatusCode() helper in src/utils.js that delegates to the shared getHttpStatusCode() but overrides Z576 to 422/UNPROCESSABLE_ENTITY (matching evaluator_recursion_limit/Z573). propagateResult() in routes/evaluate-transpiled.js calls it instead of the bare shared mapping. The Rust evaluator's own HTTP edge keeps the 504, where it's correct (capacity failure from the evaluator's perspective).

This is a targeted symptom fix. The underlying cause — a single Z7 being allowed to fan out enough parallel evaluator calls to saturate the pool — still wastes evaluator capacity per occurrence. A per-request concurrent-evaluator-call limit is the planned follow-up; designing it properly is its own piece of work.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

Bug: T423383
Bug: T282922

Edited by Jforrester

Merge request reports

Loading