Schema-constrained JSON omits a required action field

For a tested mixed properties/oneOf schema, complete disjoint alternatives restored required action fields without weakening the original application validator.

Retained qualification evidence · October 15, 2026

Tested by the author and rerun by a separate agent on the same Mac. These are bounded task results, not a second-machine or human reproduction. This release reuses those runs; no new model inference was performed.

Download evidence ZIP

321,818 bytes

SHA-256: 3f06c7949d2fe45dcccefb55629a9c0e81a1d86a69bdc120c68e8750247f9dfe

The unchanged report below describes the original pilot. Statements that production was unchanged refer to that pilot, before this publication. Files mentioned in the report are inside the ZIP.

Repair 004: JSON schema permits a missing required action

Kingy reproduced a schema-constrained generation failure on llama.cpp 0.6.0, build 11429, commit d81235049384534c167caea52b85a694f6103d14, with Qwen3-4B-Q4_K_M.gguf. The tested correction changes only the decoder's json_schema representation. The original schema remains the application validator, with no weakened requirements.

Failing example and working correction

For the unchanged prompt Represent a single trip to the mall as JSON with an actions array and location field. Return only JSON., the original mixed properties/oneOf schema yielded HTTP200 and completed JSON:

{"actions":[{"location":"mall"}]}

This is invalid: action is required. With normalized-schema.json supplied instead, the same prompt yielded:

{"actions":[{"action":"go_to","location":"mall"}]}

The correction moves the common object/action requirements into each complete, disjoint oneOf alternative. It removes only the unreachable lay_down branch, whose value the original global enum already prohibits, and explicitly permits additional properties because that is the original Draft7 default. Empty action arrays, extra fields, and unconstrained fields from unselected branches remain valid. See SEMANTICS.md for the two-way argument and semantic-check.py for 7,934 matching validator/contract cases. Do not copy the later four-action upstream example: it widens the original first schema.

This is a schema normalization workaround for this contract and converter, not a runtime patch or a general-purpose normalizer. Use original-schema.json for application validation and reject failures; constrained JSON does not replace validation.

Evidence

The author completed six baseline failures, six exact corrected successes and two reverted failures across two fixed prompts. Each prompt received three baseline, three corrected and one reverted attempt. All were HTTP200, complete JSON, end-of-generation rather than token-cap stops, zero cached tokens, with unchanged prompt, seed, temperature, output cap and context. The second prompt deliberately supplies an incomplete example; it is a constraint stress test. The neutral trip is the ordinary task case.

The six exploratory responses are retained separately. The three-action control already worked with both schemas, showing prompt dependence. No failure frequency or universal reliability is inferred from these deterministic repeats. Actual GBNF from the server is retained in every response: baseline action keys are optional and the impossible lay_down branch remains; corrected alternatives require action and exclude that branch.

A separate agent reran the frozen ZIP from a fresh extraction on the same physical Mac, using fresh server processes and port 18093. It independently repeated all fourteen phase expectations: six baseline failures, six corrected successes and two reverted failures. The author used port 18092. This establishes same-host agent reproduction; no second-machine or human reproduction is claimed. Independent semantic and raw-receipt audits are recorded in INDEPENDENT-VERIFICATION.md and evidence/independent-audit-results.json.

Exact environment and limits

macOS 26.3 build 25D125, arm64 Mac16,7, 24 GiB unified memory. CPU-only two generation/batch threads, one slot, ctx 2048, n_predict 256, temperature 0, seed 42, reasoning off, no prompt cache, UI or context shift. Python 3.14.0 and Node.js v24.16.0. The same rendered prompt is submitted through native /completion with json_schema in all arms. No claim is made about other API envelopes.

Server binary SHA256: 51afbf4ea6485b9ada19e99af97181f12baca42ef704b1e291c26a9ac0644eae.

Model: Qwen/Qwen3-4B-GGUF, revision bc640142c66e1fdd12af0bd68f40445458f3869b, Q4_K_M, 2,497,280,256 bytes. SHA256: 7485fe6f11af29433bc51cab58009521f205840f5b4ae3a32fa7f92e8534fdf5.

The historical lead issue 7703 used an older Windows/Llama3 environment; this is an identified local analogue. The pinned runtime grammar guide documents the mixed-keyword limitation and its different additionalProperties default. Source snapshots and hashes are included. No exhaustive grammar-language equivalence, second-machine testing, model-quality benchmark or complete Draft7 decoder support is claimed.

Run README.md's commands against the frozen input package. The distribution includes the existing MIT jsonschema 1.5.0 validator, schemas, semantic proof, fixed fixtures, runner, original qualification inputs, raw responses, generated grammars, logs, versions, hashes and independent receipts. Weights and executables are excluded. No spending, installation, model download, action execution or Kingy.ai publication occurred.

Read the repair steps in Fix Finder →