Files
ocp/lib
dtzp555-maxGitHubtaodengClaude <claude-opus-4-8> <noreply@anthropic.com>
45c5717aea fix(structured): crash-safe validation façade — deep model reply → refusal not 500 (closes #181) (#184)
* fix(structured): crash-safe validation façade — deep model reply → refusal, not a 500 (closes #181)

#153's cyclic-$ref guard caps the REF-chain depth but not the DATA depth:
validateJsonSchema recurses on the value's nesting (properties/items/additionalProps),
so a model reply nested ~2000+ levels overflowed the stack with a RangeError, which
handleChatCompletions caught as a generic HTTP 500 instead of the spec-correct refusal.
(Found in the #153 final review, filed as #181; ≤1 spawn, no crash, no client-only
trigger — the value always comes from the model reply.)

New exported validateJsonSchemaSafe() wraps the validator: ANY throw (the deep-data
RangeError, or any future recursion hazard) becomes a single validation error, so the
structured-output retry loop treats a pathological reply as "did not validate" →
refusal. A well-formed reply is byte-identical (passes the inner errors through).
runStructuredCompletion calls the safe façade.

Chose the wrapper over threading a data-depth counter through six recursive call
sites: it protects every internal path at once (impossible to miss one) and stays
deterministically testable — a 6000-deep fixture reliably overflows on any platform.

Tests: +2, mutation-proven (revert the wrapper to a bare call → the deep test throws
RED). Suite 431/0. Rule 2: OCP-internal validation, no wire change, no cli.js citation.

Closes #181

Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>

* fix(structured): narrow validateJsonSchemaSafe to RangeError-only + drop unused import (review fold-in)

Reviewer of #184: the catch-all would silently mask a future genuine bug (e.g. a
TypeError from a malformed schema) as a validation miss. Narrowed to
`if (e instanceof RangeError) return [...]; throw e;` so only the #181 deep-nesting
overflow becomes a refusal; any other throw surfaces at error level as before. +1
test proving a non-RangeError (required:42 → TypeError) re-throws. Dropped the now-
unused raw `validateJsonSchema` import from server.mjs. Merged current main (incl.
#183) so CI runs the true post-merge tree. Suite 433/0.

Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com>

---------

Co-authored-by: dtzp555 <dtzp555@gmail.com>
Co-authored-by: Claude <claude-opus-4-8> <noreply@anthropic.com>
2026-07-21 20:05:50 +10:00
..