docs(tools): name the boundary that rejects a padded integer, and what the flavor-guard test actually reads

pyScalar's docstring attributed the rejection of a String-spelled
beyond-safe-range integer to "the Python runtime". No published backend
makes that call on this base. The fact that does not depend on one: the
padded digits name an integer no double holds, and passing it back would
have to cross the argument boundary as a JSON number. Say that, and say
why String rounds at all -- Number::toString is shortest round-trip, so
2 ** 60 emits the 16 digits that re-read to the same double and pads.
Mirror both in the test comment.

The note's Decision sentence said a test covers the flavor guard through
ctx.tools.schemas(). The test reads the definition's getter directly,
under a language absent from both tables; schemas() reaches the same
getter but has no assertion. Name what is read, and record that a
renderer-without-flavor language is drift this guards against rather
than an existing input -- the two key sets are identical today.
This commit is contained in:
Chinesezjc
2026-08-05 19:44:05 +08:00
parent 015bef2f5f
commit ba634896e0
5 changed files with 19 additions and 12 deletions

View File

@@ -259,11 +259,14 @@ function childClassName(base: string, segment: string): string {
* `String`: Python integers are arbitrary-precision, so the emitted digits ARE
* the value the model programs against, and `String` gives a different integer
* than the double holds (`2 ** 60` prints the rounded `...847000`, not the
* exact `...846976`) or no integer literal at all (`1e21` prints `1e+21`). The
* Python runtime then rejects the advertised literal as not exactly
* representable as a JavaScript number, so the SDK would document a value no
* program can pass. The TS flavor needs no counterpart: its literal is re-read
* by a JS parser back into the same double.
* exact `...846976`) or no integer literal at all (`1e21` prints `1e+21`).
* `String`'s rounding is not a bug in it: `Number::toString` is shortest
* round-trip, so it emits the 16 digits that re-read to the same double and
* pads with zeros, and those padded digits name an integer no double holds.
* Passing one back would have to cross the argument boundary as a JSON number
* — a double again — so the SDK would document a value no program can pass.
* The TS flavor needs no counterpart: its literal is re-read by a JS parser
* back into the same double.
*
* `JSON.stringify` is also what keeps this path's output parseable, and it is
* the only thing that does. It covers both classes of hazard: the two kinds of

View File

@@ -71,9 +71,13 @@ describe('jsonSchemaToPy', () => {
// Python integers are arbitrary-precision, so the emitted digits ARE the
// value the model programs against. `String(2 ** 60)` prints the rounded
// ...847000, which is a DIFFERENT integer from the double's exact
// ...846976 — the Python runtime would reject the advertised literal as
// not exactly representable as a JavaScript number, so the SDK would
// document a value no program can pass.
// ...846976: `Number::toString` is shortest round-trip, so it emits the 16
// digits that re-read to the same double and pads with zeros, and those
// padded digits name an integer no double holds. Passing one back would
// have to cross the argument boundary as a JSON number, so the SDK would
// document a value no program can pass. This assertion is what separates
// the two spellings; the 1e21 case below separates them again on the other
// failure mode, where `String` gives no integer literal at all.
expect(jsonSchemaToPy({ type: 'integer', const: 2 ** 60 })).toBe('Literal[1152921504606846976]')
expect(jsonSchemaToPy({ type: 'integer', enum: [2 ** 60, -(2 ** 60)] }))
.toBe('Literal[1152921504606846976, -1152921504606846976]')