Make check_source work on unbound rule templates#66
Merged
Conversation
check_source (shipped in PR #65) passed run()'s symbol table straight to check_agreement, so any referenced-but-unbound evidence field raised UnencodableConstruct and every unbound rule template — every Translate draft, and every shipped agreement template in liminate-dev's app/agreement_templates.py — reported encodable=False (Halverson dry run, PR #89, finding 1). Adds a type-inference pre-pass inside check_source only: for each referenced-but-unbound field, infer a scalar type from a literal comparison or a defined predicate's own body, and synthesize a type-only placeholder SymbolEntry (value=None) for it. A real remember/define binding always wins. A field typed by neither path stays unresolved and still correctly reports encodable=False — invariant 8 unchanged. check_agreement, the encoder, and the seven checks are untouched. Ported from case-studies/halverson/check-output/check_harness.py in liminate-dev, the working prototype this stage productionizes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
check_source, as shipped in PR #65, callsrun(source, enter_phase2=False, auto_confirm_amber=True)and passescontract_result.symbol_tablestraight tocheck_agreement. A contract source is very often an unbound rule template by design — it references evidence fields (amount,manager-approval, ...) that norememberbinds.run()returns a symbol table with no entry for them,_build_constantsallocates nothing, andencode_fieldraisesUnencodableConstructthe first time a condition touches the field. Net effect:check_sourcereturnedencodable=Falsefor every unbound template — every Translate draft, and every one of the six shipped templates in liminate-dev'sapp/agreement_templates.py.This was verified against the real shipped
vendor_invoice_reviewtemplate, not just a synthetic case — it failed identically before this change. See Halverson dry run (PR #89), finding 1.Changes
_condition_leaves,_literal_type,_predicate_subject_types,_infer_field_types— a type-inference pre-pass that synthesizes type-only placeholderSymbolEntryobjects (value=None) for referenced-but-unbound fields, inferred from a literal comparison or a defined predicate's own body.check_sourcenow widensrun()'s symbol table with these placeholders before callingcheck_agreement— a realremember/definebinding always wins (only fills gaps, never overwrites).encodable=False— invariant 8 unchanged.check_agreement, the encoder, and the seven checks are untouched.Ported from
case-studies/halverson/check-output/check_harness.pyin liminate-dev — credit to that harness as the working prototype this stage productionizes.Test plan
check_sourceon an unbound template with a numeric threshold returnsencodable=Trueand finds the expected violation (regression test for the whole stage)check_sourceon the real shippedvendor_invoice_reviewtemplate (copied verbatim into the fixture) returnsencodable=Truerememberis not overwritten by inference<subject> is <defined-name>) resolves correctlyencodable=Falsewith askipped_reason, never raisespytest tests/ -q→ 1787 passed (1782 prior + 5 new)🤖 Generated with Claude Code