Skip to content

Let an incomplete entity be saved and report what it still needs - #219

Merged
sorenwacker merged 1 commit into
mainfrom
required-non-blocking
Aug 4, 2026
Merged

Let an incomplete entity be saved and report what it still needs#219
sorenwacker merged 1 commit into
mainfrom
required-non-blocking

Conversation

@sorenwacker

Copy link
Copy Markdown
Owner

required described what a valid entity carries, but it was enforced when one was built. An agent reading a source document was therefore refused an entity whose title it had not reached yet, and lost the fields it did have. Metadata is gathered a piece at a time; the point of required is to guide an incomplete record towards a correct one, not to prevent the incomplete record existing.

The rule now

  • A missing value is allowed and reported by validation.
  • A wrong value is still refused at construction (a unique_id that breaks its pattern raises, as before).
  • The published JSON Schema still declares the profile's required fields, so a consumer decides for itself what to enforce.

Three things this surfaced

The description had gone silent. With nothing Pydantic-required, the generated JSON Schema listed no required fields at all, a description contradicting the profile. EntityBaseModel.model_json_schema now restores the list from spec_required_fields() and unwraps the "or null" for those fields, so the type reads as the profile declares it.

The UI stopped warning. The incomplete-draft warning was produced by catching the rejection. With nothing rejected, an incomplete entity saved silently, the opposite of guiding the user. Both the create and update paths now look for missing required fields via missing_required_fields instead of catching them, so the "Saved draft ... (incomplete)" warning still appears.

String to entity coercion. _coerce_string_to_entity counted Pydantic-required fields to decide whether a bare string should become an entity. With none required that count is always 0, which would have made it coerce far more widely. It now reads the spec's list via __spec_required__.

Tests

Eight tests encoded the old blocking contract and were rewritten to the new one, including test_no_parent_still_requires_the_reference: a parent-child edge is carried by the tree, so a Study created on its own saves and validation reports the missing back-reference if the profile asks for one. Full suite: 2685 passed.

Docs

docs/specification/system-specification.md gains a "Required fields" section stating the rule and the three obligations it places on implementations; two passages claiming requiredness is enforced at model construction were corrected. docs/api/schema-specs.md gains the same with a worked example. Docstrings updated on FieldSpec.required, get_required_fields, RequiredFieldsRule, and the agent's get_required_fields tool.

Compatibility

An entity that used to be refused now saves. Pre-1.0, so this ships as a minor bump.

A required field described what a valid entity carries, but was enforced when
one was built, so an agent reading a source document was refused an entity
whose title it had not reached yet and lost the fields it had. Required now
guides rather than blocks: absence is allowed and reported, a value that breaks
the profile's rules is still refused, and the published JSON Schema keeps
declaring the required fields so a consumer can enforce what it likes.
@sorenwacker
sorenwacker merged commit 1e4d980 into main Aug 4, 2026
4 checks passed
@sorenwacker
sorenwacker deleted the required-non-blocking branch August 4, 2026 07:59
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.

1 participant