Skip to content

feat: contract-declared required props reach the grammar as required#43

Merged
ryandmonk merged 2 commits into
mainfrom
feat/required-props-grammar
Jul 21, 2026
Merged

feat: contract-declared required props reach the grammar as required#43
ryandmonk merged 2 commits into
mainfrom
feat/required-props-grammar

Conversation

@ryandmonk

Copy link
Copy Markdown
Contributor

What

A contract prop descriptor may now declare required: true. componentProps() lists flagged props in the props schema's required, and the node branch then requires props itself — an inner requirement never binds when the grammar can drop props wholesale. Contracts without flags produce byte-identical schemas.

Why

Grammar-constrained decoders skip optional heavy branches. Measured in dspack-studio's record-collection scenario work (2026-07-21): across ~20 live generations on gpt-oss:latest and qwen3-coder:30b, the table's nested data rows were never emitted while optional scalar props were — and bounded repair could not recover, exhausting every run against "Required prop 'data' is not present". The grammar never demanded the prop, so the sampler never planned it.

Direct Ollama structured-output test: with data marked required in the schema, the same model fills correct rows first try.

With this fix (linked into dspack-studio) the same prompts produce: a clean first-pass five-row triage table, and a repair run where a prose-list violation is caught by the intent rule and repaired into a filled table — the recordings now shipping in dspack-studio #17, which is draft until this publishes as 0.1.2.

Fail-first evidence

Three new grammar-alignment assertions against the previous implementation:

× required-flagged props land in the props schema's required list
× the node branch requires `props` itself, or the inner requirement never binds
× a data-less table no longer validates; a data-filled one does
Tests  3 failed | 9 passed (12)

Full suite after: 105 passed (105); tsc clean. The fourth new assertion (unflagged components keep the fully optional shape) is the no-regression guard.

CHANGELOG entry added under Unreleased.

🤖 Generated with Claude Code

Grammar-constrained decoders skip optional heavy branches. Measured in
dspack-studio's record-collection scenario work (2026-07-21): across
~20 live generations on gpt-oss:latest and qwen3-coder:30b, the table's
nested `data` rows were NEVER emitted while optional scalar props were,
and bounded repair could not recover — the grammar never demanded the
prop, so every run exhausted its repairs against "Required prop 'data'
is not present". Direct Ollama structured-output test: with `data`
required in the schema, the same model fills correct rows first try.

A prop descriptor may now declare `required: true`. componentProps()
lists flagged props in the props schema's `required`, and the node
branch requires `props` itself (an inner requirement never binds when
the grammar can drop `props` wholesale). Contracts without flags
produce byte-identical schemas.

Fail-first: the three new grammar-alignment assertions fail on the
previous implementation (props.required undefined; node required
["component"]; a data-less table validates). Full suite: 105 passed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 20:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for contract-authored “required” component props by ensuring those requirements are represented in the generated JSON Schema in a way that grammar-constrained decoders can’t bypass (by omitting props entirely).

Changes:

  • Extend ContractProp to allow required: true to be declared in contracts.
  • Update generation-schema construction to (1) add required prop names to the props object’s JSON Schema required list, and (2) require props at the node level when any required props exist.
  • Add grammar-alignment tests that fail on the previous behavior and assert both schema shape and validation outcomes.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/core/grammar-alignment.test.ts Adds regression tests proving required props are enforced by the generation schema (including requiring props itself).
src/core/generation-schema.ts Propagates contract required: true into JSON Schema required and makes node-level props required when needed.
src/core/contract.ts Documents and types the new required?: boolean flag on contract prop descriptors.
CHANGELOG.md Documents the new Unreleased behavior and rationale.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ryandmonk
ryandmonk merged commit c5bfd6d into main Jul 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants