on master help sign in
Recover prepared tuple initializers in reports

Defer source-owned literals in direct tuples during a bounded prepared-prelude transaction, then replay their fits against a later exact result context. Restrict the hook to partial reports for import-free ordinary libraries without main; do not publish recovered interfaces or enable list and import recovery. Cover tuple-only recovery, wrong fields, unrelated tags, mold and prepared-inventory mismatches, missing casts, and no-prelude publication controls under eval and on the ship.

commitaa277c92cb62dd91cae47bc0dbffeb382a563f5e authoriko <mail@iko.soy> dateSat 31 Oct 2026, 22:38 (3 hours ago) parentab6fdc1
21 files changed+412−15
README.md+1−1 docs/compiler.md+4−2 docs/development.md+3−1 docs/status.md+7−3 jibb-dev/lib/jibb.hoon+121−8 tests/lib/jibb-deferred-prepared.hoon+114 tests/type-deferred-prepared/expected-control.txt+7 tests/type-deferred-prepared/expected-tuple-only.txt+4 tests/type-deferred-prepared/expected.txt+8 tests/type-deferred-prepared/good.txt+9 tests/type-deferred-prepared/imported.txt+11 tests/type-deferred-prepared/main.txt+10 tests/type-deferred-prepared/mold-collision.txt+9 tests/type-deferred-prepared/no-final-cast.txt+8 tests/type-deferred-prepared/no-prelude.txt+9 tests/type-deferred-prepared/tuple-only.txt+3 tests/type-deferred-prepared/unrelated-tag.txt+11 tests/type-deferred-prepared/wrong-draft.txt+9 tests/type-deferred-prepared/wrong-unit.txt+9 tools/testdata/ship-selftest+6 tools/type-deferred-prepared-test+49
README.md+1−1
@@ -42,7 +42,7 @@ tools/hoon '(golden /a/b/jibb (crip "++ main view"))'
4242tools/hoon --raw --cord src=tests/golden/foo/source.jibb 'tree:(golden /a/b/jibb src)'
4343```
4444
45−`tools/testdata/selftest` tests both tools against a stub library, and `tools/doc-blocks` against Markdown it writes. `tools/importer-test` compares the partial Hoon importer's fixture projections against their golden file. `tools/type-import-test`, `tools/type-import-overlap-test`, `tools/type-import-structural-test`, `tools/type-union-source-test`, `tools/type-union-alias-overlap-test`, `tools/type-full-overlap-test`, `tools/type-generic-recursion-test`, `tools/type-generic-construction-test`, `tools/type-generic-pattern-test`, `tools/type-deferred-test`, `tools/type-deferred-resolver-test`, `tools/type-deferred-context-test`, `tools/type-empty-test`, `tools/type-cell-branch-test`, `tools/type-tlon-test`, `tools/type-mark-test`, `tools/type-poke-test` and `tools/type-api-paths-test` check importer/checker, prelude and partial API path analysis boundaries under eval; the ship suite runs the same fixtures.
45+`tools/testdata/selftest` tests both tools against a stub library, and `tools/doc-blocks` against Markdown it writes. `tools/importer-test` compares the partial Hoon importer's fixture projections against their golden file. `tools/type-import-test`, `tools/type-import-overlap-test`, `tools/type-import-structural-test`, `tools/type-union-source-test`, `tools/type-union-alias-overlap-test`, `tools/type-full-overlap-test`, `tools/type-generic-recursion-test`, `tools/type-generic-construction-test`, `tools/type-generic-pattern-test`, `tools/type-deferred-test`, `tools/type-deferred-prepared-test`, `tools/type-deferred-resolver-test`, `tools/type-deferred-context-test`, `tools/type-empty-test`, `tools/type-cell-branch-test`, `tools/type-tlon-test`, `tools/type-mark-test`, `tools/type-poke-test` and `tools/type-api-paths-test` check importer/checker, prelude and partial API path analysis boundaries under eval; the ship suite runs the same fixtures.
4646
4747### The doc's examples
4848
docs/compiler.md+4−2
@@ -190,7 +190,7 @@ Note 4 has examples of each.
190190
191191Starting `urbit eval` and building the library takes about 8 s. A 2,000-line module of 400 definitions then parses in about a second. Loops over definitions, arms, lines and items are tail calls, so a long module grows no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (note 3).
192192
193−The experimental deferred constructor path can close a small import-free library transaction when ordinary resolution stalls. It retries definitions whose earlier attempts failed from their original states, retaining only successful attempts. A transaction with at most 64 definitions makes at most 4,096 attempts; it stops after a pass with no progress. This bounds the new attempt count, not each attempt's parsing, type walks or ordinary inference. Deferred definitions are restricted to simple one-component wings, literals, static strings, gates, transparent groups and empty bodies, calls, casts and a restricted boolean branch. Each successful call or cast fit must have exactly equal normalized operands so later substitutions cannot invalidate a face check. A multi-argument call also needs closed argument, sample and product types because positional face checks depend on slot boundaries and whether the result can be a cell. Other fits fail closed. A 512-node screen bounds visited expression nodes and a separate 512-node scan bounds each stability check; neither bounds mold shapes, string-piece checks, parsing, normalization, lookup, or total repeated inference. It accepts only a direct constructor callback with a closed input, records its pending fit under the source-owned inference state, and generalizes each definition against the live environment and pending constraints. Before publication it discharges and replays every edge, rejects unresolved tags or changed replay state, and checks that all molds and values are complete. The reporter reads the committed schemes for definitions added by the transaction. API and store paths, `main`, prepared preludes, imports, recursive groups, unresolved holes or written capitals, and new projection actions remain outside this path. `%grec` in the constraint or freshness scan is conservatively unsupported. This is not an island-kind, runtime, or watchability check.
193+The experimental deferred constructor path can close a small import-free library transaction when ordinary resolution stalls. It retries definitions whose earlier attempts failed from their original states, retaining only successful attempts. A transaction with at most 64 definitions makes at most 4,096 attempts; it stops after a pass with no progress. This bounds the new attempt count, not each attempt's parsing, type walks or ordinary inference. Deferred definitions are restricted to simple one-component wings, literals, static strings, gates, transparent groups and empty bodies, calls, casts and a restricted boolean branch. Each successful call or cast fit must have exactly equal normalized operands so later substitutions cannot invalidate a face check. A multi-argument call also needs closed argument, sample and product types because positional face checks depend on slot boundaries and whether the result can be a cell. Other fits fail closed. A 512-node screen bounds visited expression nodes and a separate 512-node scan bounds each stability check; neither bounds mold shapes, string-piece checks, parsing, normalization, lookup, or total repeated inference. It accepts only a direct constructor callback with a closed input, records its pending fit under the source-owned inference state, and generalizes each definition against the live environment and pending constraints. Before publication it discharges and replays every edge, rejects unresolved tags or changed replay state, and checks that all molds and values are complete. The reporter reads the committed schemes for definitions added by the transaction. API and store paths, `main`, prepared-prelude recovery, imports, recursive groups, unresolved holes or written capitals, and new projection actions remain outside this full-module path. `%grec` in the constraint or freshness scan is conservatively unsupported. This is not an island-kind, runtime, or watchability check.
194194
195195An expected cell type can supply context to both arms of a loobean branch. This slice first retains any ordinary inference that already fits. Otherwise it retries from the original state only when a syntax screen excludes nested branches, casts, gates and local bodies, and a substitution screen excludes structural bindings. Both arms must fit, their normalized results and the expected type must be closed, their result types must match, and both fits must replay without changing the final substitution or fresh-ID counter. A successful retry retains the original arm type and its written faces; a failed retry returns the original inference result. The source and substitution screens each visit at most 512 entries. This permits at most one extra attempt for an eligible branch; the screens do not bound preexisting inference, type walks, list construction, or work across separate analyses.
196196
@@ -198,6 +198,8 @@ In an isolated diagnostic with the real todo API and reader inputs, this cell co
198198
199199A deferred boolean branch must use both distinct literal loobean patterns. Its subject is unified with `?`; the arms are inferred in source order without contextual retry. Equal normalized arm types are retained directly. When both written arms are direct literals that each created their own unbound pending tag, the checker can instead retain two source-owned fit obligations to a shared, monomorphic result variable. A later definition may close that variable; replay uses the ordinary literal fit, requires a closed atomic target or a union of direct constant/cell cases, and rejects faced targets and faced union cases. It replays all edges under the final substitution without adding bindings or fresh IDs. This does not support deferred list literals, union-pattern reachability, arbitrary branch expressions or prepared-prelude/imported modules. It does not establish request watchability.
200200
201−Before a fallback, the checker screens the already parsed source for a direct single-constructor call beneath groups, gates, casts or bodies without local definitions. The screen visits at most 64 AST nodes per definition and rejects sources with more than 64 definitions or 65,536 bytes. A transaction is attempted at most once per resolver or report invocation and holds at most 64 pending edges. These limits do not bound the initial parsing, ordinary resolution, normalization, or total work across separate analyses. On the pre-recursive-index snapshot, startup-inclusive synthetic 1,000-gate comparisons had baseline/candidate user times of 25.97/29.30 seconds and 26.30/27.46 seconds in reverse order. These are limited shared-load measurements, not production benchmarks. The trimmed source-backed and direct-guard fixture passed in 28.13 seconds wall and 27.53 seconds user on one run after screening; its cases include parse-success checks in the same transaction source pass. The outer resolver and reporter each parse independently, and a fallback currently parses the source again.
201+With the caller's unchanged prepared prelude, the partial report can also recover a narrow import-free, non-main ordinary library initializer. A direct tuple literal may retain one source-owned fit obligation for each newly created pending literal until a later exact result cast closes them. A separate bounded candidate screen admits a direct tuple even without a constructor call. The prepared transaction requires exact agreement among the supplied interface, value inventory and reserved molds, and retains the API, store, import and `main` exclusions. It only adds recovered entries to the partial report: the ordinary full-module resolver does not publish them. Wrong unit or draft fields, unrelated pending tags and mold-name collisions fail closed; without the later final cast, the initializer remains not checked. This does not add list-literal deferral or import-aware recovery.
202+
203+Before the no-prepared-prelude fallback, the checker screens the already parsed source for a direct single-constructor call beneath groups, gates, casts or bodies without local definitions. The screen visits at most 64 AST nodes per definition and rejects sources with more than 64 definitions or 65,536 bytes. A transaction is attempted at most once per resolver or report invocation and holds at most 64 pending edges. These limits do not bound the initial parsing, ordinary resolution, normalization, or total work across separate analyses. On the pre-recursive-index snapshot, startup-inclusive synthetic 1,000-gate comparisons had baseline/candidate user times of 25.97/29.30 seconds and 26.30/27.46 seconds in reverse order. These are limited shared-load measurements, not production benchmarks. The trimmed source-backed and direct-guard fixture passed in 28.13 seconds wall and 27.53 seconds user on one run after screening; its cases include parse-success checks in the same transaction source pass. The outer resolver and reporter each parse independently, and a fallback currently parses the source again.
202204
203205A single sequential, startup-inclusive comparison against checkpoint `c96597d` measured user CPU for an unrelated stalled library at 25.04 seconds baseline and 26.32 seconds with the screened fallback; an incompatible constructor took 25.72 and 27.16 seconds; a direct constructor that the baseline declined and the candidate resolved took 24.46 and 26.79 seconds. These are small shared-load measurements, not a production benchmark. The screen was separately checked with a trapping fallback: the unrelated source skipped it, while the eligible conflicting source reached it.
docs/development.md+3−1
@@ -83,6 +83,7 @@ git clone https://github.com/urbit/tools /root/src/tools
8383| `tools/type-deferred-test` | Checks the bounded source-owned deferred inference transaction under eval and on the ship |
8484| `tools/type-deferred-resolver-test` | Checks deferred resolution, report consistency and atomic failure under eval and on the ship |
8585| `tools/type-deferred-context-test` | Checks deferred source order and literal branch contexts under eval and on the ship |
86+| `tools/type-deferred-prepared-test` | Checks prepared-prelude tuple initializer recovery, exact partial reports and fail-closed guards under eval and on the ship |
8687| `tools/type-cell-branch-test` | Checks closed-cell branch context, rollback and bounded retry screens under eval and on the ship |
8788| `tools/type-generic-alias-test` | Runs public/private generic union alias and provenance guards under eval and on the ship |
8889| `tools/type-positional-face-guards-test` | Runs positional-call and nested-face guards under eval and on the ship |
@@ -144,6 +145,7 @@ tools/type-generic-pattern-test # source-backed recursive patterns and boun
144145tools/type-deferred-test # source-owned deferred inference guards
145146tools/type-deferred-resolver-test # resolver consistency and failure guards
146147tools/type-deferred-context-test # deferred source-order and branch guards
148+tools/type-deferred-prepared-test # prepared initializer reports and failure guards
147149tools/type-cell-branch-test # contextual branch rollback and bounds
148150tools/type-closed-gate-guards-test # closed gate fit guards pass
149151tools/type-constructor-fit-guards-test # constructor fit guards pass
@@ -214,4 +216,4 @@ Write `source.jibb` and `about.txt` by hand, run `tools/golden --update --case <
214216
215217A short subject in the imperative, then a body that says what changed and why, wrapped at 72 columns, as in `git log`. Each commit leaves every check passing.
216218
217−`tools/type-deferred-test` exercises the bounded, source-owned constructor transaction and low-level freshness/replay guards. `tools/type-deferred-resolver-test` checks the experimental import-free library resolver, report consistency, atomic failure, and that both source orders of a late face constraint decline. These checks do not establish island-kind or watchability support.
219+`tools/type-deferred-test` exercises the bounded, source-owned constructor transaction and low-level freshness/replay guards. `tools/type-deferred-resolver-test` checks the experimental import-free library resolver, report consistency, atomic failure, and that both source orders of a late face constraint decline. `tools/type-deferred-prepared-test` checks the separate partial-report-only prepared-prelude route, direct tuple-literal obligations, exact report types and its wrong-field, unrelated-tag, mold-collision and no-final-cast controls. These checks do not establish island-kind or watchability support.
docs/status.md+7−3
@@ -31,6 +31,8 @@ A bounded local source proof recognizes a narrow class of generic-alias union ca
3131
3232The checker can experimentally discharge a narrowly scoped direct-constructor constraint while resolving an import-free library without a prepared prelude. It preserves independent generalized schemes and publishes only after all source molds, values, and recorded constraints close. API/store paths, `main`, imports, prepared preludes, recursive groups, open constraints, projection actions, and `%grec` in the constraint graph remain unsupported by this route. The fallback also declines source shapes outside its bounded direct-call screen. It does not yet typecheck the unchanged todo island or establish watchability.
3333
34+A prepared-prelude partial report can recover a narrow import-free, non-main ordinary library initializer by deferring source-owned literals in a direct tuple until a later exact result cast. The prepared interface and declared-name inventories must agree exactly. API/store paths, `main` and imports remain excluded, and the ordinary full-module resolver does not publish the recovered interface. Wrong field types, unrelated tags and mold collisions fail closed; a no-final-cast control remains unchecked. `tools/type-deferred-prepared-test` checks the exact recovered types and unchanged `partial inference; module not checked` disclaimer under eval and on the ship. List-literal deferral and import-aware recovery remain unsupported.
35+
3436Closed cell context can now flow through a bounded loobean branch while preserving the inferred value faces and original failed-inference behavior. Open or structurally uncertain substitutions and nested retry shapes remain unsupported. This does not by itself provide the missing text and UI prelude definitions, cross-definition context, island-kind checks, or watchability evidence needed by the unchanged todo island.
3537
3638The internal prelude defines a transparent generic `ask` with pure, agent and store cases, re-exported alongside the Jibb-written `pure` gate. The partial checker infers supported constructors and exhaustive matches. Agent and store receivers operate on raw nouns; their fields do not prove schema validity or watchability. The public prelude now defines the documented source-backed `sub` union; supported `%watch` payloads retain the public `(ask M)` type. Constructing a `sub` does not prove that its request is watchable. Request lowering, checked decoding, runtime validation and island watch checking remain unimplemented.
@@ -61,7 +63,7 @@ The prelude has Jibb-written curried `lead` and `late` pair constructors, inferr
6163
6264The prelude also has a Jibb-written `zing` that concatenates homogeneous lists via `weld`. Its focused golden infers empty, nested text, ship, generic and gate-element lists and reports a non-list error; the same golden passes on the ship. A Hoon translation agrees with Hoon `zing` on selected finite inputs, not on Jibb execution. Hoon’s raw helper additionally accepts heterogeneous noun lists, which the Jibb signature does not express. Backend lowering and jet recognition remain unverified.
6365
64−The experimental deferred constructor transaction conservatively declines tuples, most branches, field reads, nonidentical successful call/cast fits, and multi-argument calls with open argument, sample or result types. This prevents a later substitution from invalidating an earlier face-propagation check; cases requiring deferred structural fits remain unsupported. It can retry source definitions after later dependencies become available, and a two-arm boolean branch can retain separately owned literal-result obligations until a later closed context resolves them. Faced targets or union cases, list literals and general union-pattern branches remain unsupported.
66+The experimental deferred constructor transaction conservatively declines general structural tuple fits, most branches, field reads, nonidentical successful call/cast fits, and multi-argument calls with open argument, sample or result types. This prevents a later substitution from invalidating an earlier face-propagation check; cases requiring deferred structural fits remain unsupported. It can retry source definitions after later dependencies become available, and a two-arm boolean branch can retain separately owned literal-result obligations until a later closed context resolves them. Faced targets or union cases, list literals and general union-pattern branches remain unsupported.
6567
6668The checked inference slice now represents `!!`, proves empty cell positions and filters proven-empty union cases. List and unit payload arms whose elements are empty are rejected as unreachable; fixed opaque cases fail closed when reachability is unknown. The new shared guard covers checked interfaces, partial diagnostics and proof budgets. Its shared guard runs under eval and on the ship.
6769
@@ -92,7 +94,7 @@ What the plan asks for, and where it is:
9294Besides the plan's list:
9395
9496- 659 golden cases: 439 that parse and 220 that fail, each failure at a stated line and column. One failing case has an unclear expectation (corpus question 3). The newer type-output cases exercise only the partial inference fragment. Each case's `about.txt` quotes the doc's words it tests.
95−- The 659-case corpus passed under `urbit eval` in 103.2 s while other checks were running. The fake ship passed all 705 tests, including the source-overlap, structural-overlap, generic-union source and alias-overlap, full-module overlap, deferred-context, generic-recursion, generic-construction, generic-pattern, deferred-inference, empty-mold and cell-branch fixtures, importer, importer/checker and mark/checker bridges, module scope, unification, hole, qath, ask, default-wrapper importer, projection, arithmetic, generic-alias, positional-face, API-evidence, request, closed-gate, todo API, constructor, sub, nested-union, gate-free and direct-gate guards and the unchanged todo report. Desk sync took 99.8 s while other checks were running. The importer golden compares 221 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
97+- The 659-case corpus passed under `urbit eval` in 98.7 s while other checks were running. The fake ship passed all 706 tests, including the source-overlap, structural-overlap, generic-union source and alias-overlap, full-module overlap, deferred-context, generic-recursion, generic-construction, generic-pattern, deferred-inference, empty-mold and cell-branch fixtures, importer, importer/checker and mark/checker bridges, module scope, unification, hole, qath, ask, default-wrapper importer, projection, arithmetic, generic-alias, positional-face, API-evidence, request, closed-gate, todo API, constructor, sub, nested-union, gate-free and direct-gate guards and the unchanged todo report. Desk sync took 94.2 s while other checks were running. The importer golden compares 221 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
9698- `tools/testdata/selftest` (22 checks), `tools/testdata/ship-selftest` and `tools/testdata/clay-fixtures-selftest` test the tools themselves; the last checks temporary Clay fixture cleanup and signal handling without a ship.
9799- Two independent audits before 7c739b7, one of which compared the library with a reference parser written in Python from the doc over about 19,000 generated programs. Before ab797a9, a second Python parser, written from the decisions, agreed with the library on 8,000 generated programs and 900 hand-written probes.
98100- Speed: starting `urbit eval` and building the library takes about 8 s. After that, a 2,000-line module of 400 definitions parses in about a second. Loops over definitions, arms, lines and items grow no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (library section 3).
@@ -205,7 +207,8 @@ Besides the plan's list:
205207| b93a94b | 2026-10-31 | Prove local generic-alias union tags and add successor |
206208| 2826c93 | 2026-10-31 | Report generic-alias overlaps and retain deferred branch contexts |
207209| b5cdc80 | 2026-10-31 | Preserve full-module overlap source evidence |
208−| This change | 2026-10-31 | Add source-backed text conversion wrappers |
210+| ab6fdc1 | 2026-10-31 | Add source-backed text conversion wrappers |
211+| This change | 2026-10-31 | Recover prepared tuple initializers in partial reports |
209212
210213## Checking it
211214
@@ -235,6 +238,7 @@ tools/type-generic-pattern-test # source-proven recursive pattern guards
235238tools/type-deferred-test # source-owned deferred inference guards
236239tools/type-deferred-resolver-test # resolver consistency and failure guards
237240tools/type-deferred-context-test # deferred source-order and branch guards
241+tools/type-deferred-prepared-test # prepared initializer reports and failure guards
238242tools/type-empty-test # empty molds and coverage guards
239243tools/type-cell-branch-test # branch context and rollback guards
240244tools/type-positional-face-guards-test # positional sample face guards
jibb-dev/lib/jibb.hoon+121−8
@@ -8435,7 +8435,10 @@
84358435 =/ traced=iresult $(e val.e)
84368436 ?: ?=(%| -.traced) traced
84378437 $(e then.e, state state.p.traced)
8438− %tuple (infer-simple-items items.e env state)
8438+ %tuple
8439+ ?: &(?=(^ defer.state) ?=(^ prelude.state))
8440+ (dg-infer-tuple-items items.e env state)
8441+ (infer-simple-items items.e env state)
84398442 %body
84408443 ?~ defs.e $(e final.e)
84418444 =/ local-names=(list term) (global-value-names defs.e)
@@ -9241,6 +9244,8 @@
92419244 |= [e=expr expected=itype env=ienv state=istate context=span]
92429245 ^- iresult
92439246 ?: &(?=(^ defer.state) ?=(%branch -.e)) (infer-fragment e env state)
9247+ ?: &(?=(^ defer.state) ?=(^ prelude.state) ?=(%tuple -.e))
9248+ (infer-fragment e env state)
92449249 ?: ?=(%pair -.e) $(e (pair-as-cell e))
92459250 ?: ?=(%group -.e) $(e inner.e)
92469251 ?: &(?=(%body -.e) ?=(~ defs.e)) $(e final.e)
@@ -12658,7 +12663,7 @@
1265812663 ?: ?=(%| -.js) (of-wain:format ~['partial inference; module not checked' p.js])
1265912664 =/ scope-values=(list term)
1266012665 (weld prelude-values (weld (collect-sur-imports imports.p.parsed) (collect-mark-imports imports.p.parsed)))
12661− (golden-types-in-context file src externals mark-externals resolved.p.js scope-values prelude-molds iface)
12666+ (golden-types-in-context-core file src externals mark-externals resolved.p.js scope-values prelude-molds iface prepared)
1266212667::
1266312668:: +golden-types-with-marks: supply declared mark types separately from /sur
1266412669:: entries, as [mark result] with the result from +read-mark:jibb-import.
@@ -12689,6 +12694,10 @@
1268912694++ golden-types-in-context
1269012695 |= [file=path src=@t externals=iexternals mark-externals=imark-externals jimports=ijimports prelude-values=(list term) reserved-molds=(list term) prelude=(unit ifile)]
1269112696 ^- @t
12697+ (golden-types-in-context-core file src externals mark-externals jimports prelude-values reserved-molds prelude ~)
12698+++ golden-types-in-context-core
12699+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals jimports=ijimports prelude-values=(list term) reserved-molds=(list term) prelude=(unit ifile) prepared=(unit iprelude)]
12700+ ^- @t
1269212701 =. reserved-molds (weld reserved-molds (turn jimports |=(j=[face=term interface=ifile] face.j)))
1269312702 =/ parsed (parse file src)
1269412703 ?: ?=(%| -.parsed) (show-error src p.parsed)
@@ -12708,19 +12717,27 @@
1270812717 =/ eligible=?
1270912718 ?& ?=(~ imports.p.parsed)
1271012719 ?=(~ jimports)
12711− ?=(~ prelude)
12712− ?=(~ prelude-values)
12713− ?=(~ reserved-molds)
1271412720 !?=([%ui %api *] file)
1271512721 !?=([%ui %stores *] file)
1271612722 !(lien (global-value-names ds) |=(n=term =(n %main)))
12717− (module-scope-valid p.parsed ~ ~)
1271812723 !(module-values-complete ds env)
1271912724 (lte (met 3 src) 65.536)
1272012725 (lte (lent ds) 64)
12721− (dg-source-candidate ds 64)
12726+ ?| &(?=(~ prepared) ?=(~ prelude) ?=(~ prelude-values) ?=(~ reserved-molds) (module-scope-valid p.parsed ~ ~) (dg-source-candidate ds 64))
12727+ ?& ?=(^ prepared)
12728+ ?=(^ prelude)
12729+ =(u.prelude iface.u.prepared)
12730+ =(prelude-values values.u.prepared)
12731+ =(reserved-molds molds.u.prepared)
12732+ (module-scope-valid p.parsed values.u.prepared molds.u.prepared)
12733+ (dg-prepared-candidate ds 64)
12734+ ==
12735+ ==
1272212736 ==
12723− =/ transaction=(unit dgcommit) ?:(eligible (dg-root-source file src) ~)
12737+ =/ transaction=(unit dgcommit)
12738+ ?. eligible ~
12739+ ?~ prepared (dg-root-source file src)
12740+ (dg-root-prepared file src u.prepared)
1272412741 =. recovered
1272512742 ?~ transaction ~
1272612743 ?. &((module-values-complete ds env.u.transaction) (dg-interface-safe env.u.transaction)) ~
@@ -13006,6 +13023,31 @@
1300613023 [%& result st(next +(next.st), obligations [ex ey obligations.st])]
1300713024 [%& typ.p.left state.p.right]
1300813025::
13026+:: A direct tuple literal may wait for a later exact result context.
13027+:: Each pending literal retains its source tag and its own fit obligation.
13028+++ dg-infer-tuple-items
13029+ |= [items=(list item) env=ienv state=istate]
13030+ ^- iresult
13031+ ?~ items [%| ["empty cell is not supported by partial inference" ~]]
13032+ =/ head=iresult (infer-fragment val.i.items env state)
13033+ ?: ?=(%| -.head) head
13034+ =/ typ=itype typ.p.head
13035+ =/ st=istate state.p.head
13036+ =/ adjusted=(unit [typ=itype state=istate])
13037+ ?. (dg-owned-arm-literal val.i.items typ tags.st sub.st next.state) `[typ st]
13038+ ?: (gth (lent obligations.st) 63) ~
13039+ =/ pending=itype [%var next.st]
13040+ =/ edge=dgo [typ pending (span-of val.i.items) at.i.items]
13041+ `[pending st(next +(next.st), obligations [edge obligations.st])]
13042+ ?~ adjusted [%| ["deferred tuple context needs unsupported inference" ~]]
13043+ =. typ typ.u.adjusted
13044+ =. st state.u.adjusted
13045+ =. typ ?~(face.i.items typ [%face u.face.i.items typ])
13046+ ?~ t.items [%& typ st]
13047+ =/ tail=iresult $(items t.items, state st)
13048+ ?: ?=(%| -.tail) tail
13049+ [%& [%cell typ typ.p.tail] state.p.tail]
13050+::
1300913051:: Deferred inference uses only source forms whose successful fit sites are
1301013052:: guarded below; a shared source-node budget bounds this screen.
1301113053++ dg-safe-expressions
@@ -13015,6 +13057,13 @@
1301513057 =/ first=(unit @ud) (dg-safe-expression i.todo fuel)
1301613058 ?~ first ~
1301713059 $(todo t.todo, fuel u.first)
13060+++ dg-safe-items
13061+ |= [items=(list item) fuel=@ud]
13062+ ^- (unit @ud)
13063+ ?~ items `fuel
13064+ =/ first=(unit @ud) (dg-safe-expression val.i.items fuel)
13065+ ?~ first ~
13066+ $(items t.items, fuel u.first)
1301813067++ dg-safe-expression
1301913068 |= [e=expr fuel=@ud]
1302013069 ^- (unit @ud)
@@ -13032,6 +13081,7 @@
1303213081 $(e final.e, fuel fuel)
1303313082 %gate $(e body.e, fuel fuel)
1303413083 %gate-wide $(e body.e, fuel fuel)
13084+ %tuple (dg-safe-items items.e fuel)
1303513085 %branch
1303613086 ?. (dg-boolean-patterns e) ~
1303713087 ?> ?=(^ arms.e)
@@ -13171,6 +13221,28 @@
1317113221 ?: (dg-direct-source val.i.ds 64) &
1317213222 $(ds t.ds, fuel (dec fuel))
1317313223::
13224+++ dg-prepared-source
13225+ |= [e=expr fuel=@ud]
13226+ ^- ?
13227+ ?: (dg-direct-source e fuel) &
13228+ ?: =(0 fuel) |
13229+ ?+ -.e |
13230+ %group $(e inner.e, fuel (dec fuel))
13231+ %gate $(e body.e, fuel (dec fuel))
13232+ %gate-wide $(e body.e, fuel (dec fuel))
13233+ %cast $(e val.e, fuel (dec fuel))
13234+ %body ?~(defs.e $(e final.e, fuel (dec fuel)) |)
13235+ %tuple &
13236+ ==
13237+++ dg-prepared-candidate
13238+ |= [ds=(list def) fuel=@ud]
13239+ ^- ?
13240+ ?~ ds |
13241+ ?: =(0 fuel) |
13242+ ?. ?=(%value -.i.ds) $(ds t.ds, fuel (dec fuel))
13243+ ?: (dg-prepared-source val.i.ds 64) &
13244+ $(ds t.ds, fuel (dec fuel))
13245+::
1317413246++ dg-interface-safe
1317513247 |= [env=ienv]
1317613248 ^- ?
@@ -13216,6 +13288,47 @@
1321613288 (dg-stage defs base base st ~ 64)
1321713289 ::
1321813290 [& (transact)]
13291+:: The caller supplies the trusted prepared prelude. This transaction is
13292+:: only report evidence; the ordinary module resolver does not publish it.
13293+++ dg-root-prepared
13294+ |= [at=path src=@t prepared=iprelude]
13295+ ^- (unit dgcommit)
13296+ ?: ?=([%ui %api *] at) ~
13297+ ?: ?=([%ui %stores *] at) ~
13298+ ?: (gth (met 3 src) 65.536) ~
13299+ =/ parsed (parse at src)
13300+ ?: ?=(%| -.parsed) ~
13301+ ?^ imports.p.parsed ~
13302+ ?. (module-scope-valid p.parsed values.prepared molds.prepared) ~
13303+ ?^ (duplicate-defs defs.p.parsed) ~
13304+ =/ defs=(list def) defs.p.parsed
13305+ ?: (gth (lent defs) 64) ~
13306+ ?: (lien (global-value-names defs) |=(n=term =(n %main))) ~
13307+ ?. (dg-prepared-candidate defs 64) ~
13308+ =/ local-molds=imolds (collect-simple-molds defs)
13309+ =/ globals=(list term) (weld values.prepared (global-value-names defs))
13310+ =/ iface=ifile iface.prepared
13311+ =/ prelude=(unit ifile) `iface
13312+ =/ resolution=iresolved
13313+ (resolve-groups defs local-molds globals ~ ~ ~ ~ ~ molds.prepared at prelude)
13314+ ?^ grouped.resolution ~
13315+ ?^ artifacts.resolution ~
13316+ =/ base=ienv env.resolution
13317+ =/ templates=ienv
13318+ (turn molds.iface |=(x=[name=term template=ischeme] [name.x template.x]))
13319+ =/ all-env=ienv (weld base (weld values.iface templates))
13320+ =/ free=(unit dgscan) (dg-env all-env ~ 32.768 ~)
13321+ ?~ free ~
13322+ ?^ ids.u.free ~
13323+ =/ all=(unit dgscan) (dg-all-env-ids all-env 32.768 ~)
13324+ ?~ all ~
13325+ =/ fresh=@ud (dg-next-id ids.u.all 0)
13326+ =/ st=istate *istate
13327+ =. st st(next fresh, defer `~, molds local-molds, globals globals, at at, reserved-molds molds.prepared, prelude prelude, top-molds (turn local-molds |=(m=[name=term body=shape] name.m)), in-mold |, jrec-fuel 256)
13328+ =/ checked-molds=(each imold-types @t) (module-mold-types local-molds st)
13329+ ?: ?=(%| -.checked-molds) ~
13330+ (dg-stage defs base base st ~ 64)
13331+::
1321913332++ dg-all-env-ids
1322013333 |= [env=ienv fuel=@ud ids=(list @ud)]
1322113334 ^- (unit dgscan)
tests/lib/jibb-deferred-prepared.hoonnew file+114
@@ -0,0 +1,114 @@
1+:: Prepared-prelude initializer recovery remains a partial report only.
2+/+ jibb
3+/* prelude %jibb /lib/jibb/prelude/jibb
4+/* internal %jibb /lib/jibb/internal/jibb
5+/* good %txt /tests/type-deferred-prepared/good/txt
6+/* tuple-only %txt /tests/type-deferred-prepared/tuple-only/txt
7+/* wrong-unit %txt /tests/type-deferred-prepared/wrong-unit/txt
8+/* wrong-draft %txt /tests/type-deferred-prepared/wrong-draft/txt
9+/* unrelated-tag %txt /tests/type-deferred-prepared/unrelated-tag/txt
10+/* mold-collision %txt /tests/type-deferred-prepared/mold-collision/txt
11+/* no-final-cast %txt /tests/type-deferred-prepared/no-final-cast/txt
12+/* no-prelude %txt /tests/type-deferred-prepared/no-prelude/txt
13+/* main-source %txt /tests/type-deferred-prepared/main/txt
14+/* imported %txt /tests/type-deferred-prepared/imported/txt
15+/* expected %txt /tests/type-deferred-prepared/expected/txt
16+/* expected-control %txt /tests/type-deferred-prepared/expected-control/txt
17+/* expected-tuple-only %txt /tests/type-deferred-prepared/expected-tuple-only/txt
18+|%
19+++ text
20+ |= lines=wain
21+ ^- @t
22+ (rap 3 (turn lines |=(line=@t (cat 3 line '\0a'))))
23+++ check-prepared
24+ |= [where=path source=wain valid=?]
25+ ^- tang
26+ ?~ source ~[leaf+"source fixture missing"]
27+ =/ src=@t (text source)
28+ =/ parsed (parse:jibb where src)
29+ ?: ?=(%| -.parsed) ~[leaf+"source does not parse"]
30+ =/ prepared=(unit iprelude:jibb) (prepare-prelude-with-internal:jibb prelude internal)
31+ ?~ prepared ~[leaf+"prelude unavailable"]
32+ =/ recovered=? ?=(^ (dg-root-prepared:jibb where src u.prepared))
33+ ?. =(valid recovered) ~[leaf+"prepared initializer transaction result changed"]
34+ ~
35+++ check-no-prelude
36+ ^- tang
37+ =/ at=path /ui/prepared/jibb
38+ =/ src=@t (text no-prelude)
39+ ?: ?=(^ (dg-root-source:jibb at src))
40+ ~[leaf+"no-prelude source transaction recovered tuple initializer"]
41+ =/ legacy=jfile-result:jibb
42+ (infer-jibb-file:jibb at src ~ ~ ~ ~[at] ~ ~ ~ ~)
43+ ?: ?=(%& -.legacy) ~[leaf+"no-prelude resolver published recovered tuple initializer"]
44+ ~
45+++ check-ordinary
46+ ^- tang
47+ =/ prepared=(unit iprelude:jibb) (prepare-prelude-with-internal:jibb prelude internal)
48+ ?~ prepared ~[leaf+"prelude unavailable"]
49+ =/ at=path /ui/prepared/jibb
50+ =/ ordinary=jfile-result:jibb
51+ (infer-jibb-file:jibb at (text good) ~ ~ ~ ~[at] values.u.prepared molds.u.prepared ~ `iface.u.prepared)
52+ ?: ?=(%& -.ordinary) ~[leaf+"ordinary full-module path published recovered initializer"]
53+ ~
54+++ check-report
55+ |= [source=wain wanted=wain]
56+ ^- tang
57+ ?~ source ~[leaf+"report source fixture missing"]
58+ ?~ wanted ~[leaf+"expected report fixture missing"]
59+ =/ prepared=(unit iprelude:jibb) (prepare-prelude-with-internal:jibb prelude internal)
60+ ?~ prepared ~[leaf+"prelude unavailable"]
61+ =/ report=@t (golden-types-with-prepared-prelude:jibb /ui/prepared/jibb (text source) ~ ~ ~ prepared)
62+ =/ report-lines=wain (to-wain:format (cat 3 report '\0a'))
63+ ?~ report-lines ~[leaf+"prepared report is empty"]
64+ ?. =('partial inference; module not checked' i.report-lines)
65+ ~[leaf+"partial disclaimer changed"]
66+ ?. =(report-lines wanted) ~[leaf+"prepared report differs from exact recovered types"]
67+ ~
68+++ check-prepared-binding
69+ ^- tang
70+ =/ prepared=(unit iprelude:jibb) (prepare-prelude-with-internal:jibb prelude internal)
71+ ?~ prepared ~[leaf+"prelude unavailable"]
72+ =/ at=path /ui/prepared/jibb
73+ =/ src=@t (text good)
74+ =/ pre=(unit ifile:jibb) `iface.u.prepared
75+ =/ report
76+ |= [vals=(list term) ms=(list term) p=(unit ifile:jibb) prep=(unit iprelude:jibb)]
77+ ^- @t
78+ (golden-types-in-context-core:jibb at src ~ ~ ~ vals ms p prep)
79+ =/ vals=(list term) values.u.prepared
80+ =/ ms=(list term) molds.u.prepared
81+ ?: =((report vals ms pre prepared) (report vals ms pre ~))
82+ ~[leaf+"exact prepared binding did not recover the initializer"]
83+ ?. =((report ~ ms pre prepared) (report ~ ms pre ~))
84+ ~[leaf+"mismatched value inventory reached prepared recovery"]
85+ ?. =((report vals ~ pre prepared) (report vals ~ pre ~))
86+ ~[leaf+"mismatched mold inventory reached prepared recovery"]
87+ ?. =((report vals ms ~ prepared) (report vals ms ~ ~))
88+ ~[leaf+"mismatched prelude interface reached prepared recovery"]
89+ ~
90+++ test-prepared
91+ ^- tang
92+ =/ at=path /ui/prepared/jibb
93+ =/ checks=(list tang)
94+ :~ (check-prepared at good &)
95+ (check-prepared at tuple-only &)
96+ (check-prepared at no-prelude &)
97+ (check-prepared at wrong-unit |)
98+ (check-prepared at wrong-draft |)
99+ (check-prepared at unrelated-tag |)
100+ (check-prepared at mold-collision |)
101+ (check-prepared at no-final-cast |)
102+ (check-prepared at main-source |)
103+ (check-prepared at imported |)
104+ (check-prepared /ui/api/prepared/jibb good |)
105+ (check-prepared /ui/stores/prepared/jibb good |)
106+ check-no-prelude
107+ check-ordinary
108+ check-prepared-binding
109+ (check-report good expected)
110+ (check-report tuple-only expected-tuple-only)
111+ (check-report no-final-cast expected-control)
112+ ==
113+ (zing checks)
114+--
tests/type-deferred-prepared/expected-control.txtnew file+7
@@ -0,0 +1,7 @@
1+partial inference; module not checked
2++$ model: not checked
3++$ message: cases proven disjoint; mold not checked
4+++ initial: `~` needs context in partial inference
5+++ send: $-($-(@t A) $-(@t A))
6+++ first: call constraint is not supported by partial inference
7+++ fixed: name is not available to partial inference
tests/type-deferred-prepared/expected-tuple-only.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2++$ model: not checked
3+++ final: $-((list @t) [(list @t) [@t (unit @t)]])
4+++ initial: $-((list @t) [(list @t) [@t (unit @t)]])
tests/type-deferred-prepared/expected.txtnew file+8
@@ -0,0 +1,8 @@
1+partial inference; module not checked
2++$ model: not checked
3++$ message: cases proven disjoint; mold not checked
4+++ final: $-((list @t) [(list @t) [@t (unit @t)]])
5+++ initial: $-((list @t) [(list @t) [@t (unit @t)]])
6+++ send: $-($-(@t A) $-(@t A))
7+++ first: $-(@t message)
8+++ fixed: $-(@t message)
tests/type-deferred-prepared/good.txtnew file+9
@@ -0,0 +1,9 @@
1++$ model [xs=(list @t) draft=@t error=(unit @t)]
2++$ message
3+ [%got value=@t]
4+ [%other value=@p]
5+++ final ^- $-((list @t) [(list @t) @t (unit @t)]) initial
6+++ initial |= xs=(list @t) [xs "" ~]
7+++ send |= f=$-(@t A) f
8+++ first (send |=%got)
9+++ fixed ^- $-(@t message) first
tests/type-deferred-prepared/imported.txtnew file+11
@@ -0,0 +1,11 @@
1+/= other /ui/other
2+
3++$ model [xs=(list @t) draft=@t error=(unit @t)]
4++$ message
5+ [%got value=@t]
6+ [%other value=@p]
7+++ final ^- $-((list @t) [(list @t) @t (unit @t)]) initial
8+++ initial |= xs=(list @t) [xs "" ~]
9+++ send |= f=$-(@t A) f
10+++ first (send |=%got)
11+++ fixed ^- $-(@t message) first
tests/type-deferred-prepared/main.txtnew file+10
@@ -0,0 +1,10 @@
1++$ model [xs=(list @t) draft=@t error=(unit @t)]
2++$ message
3+ [%got value=@t]
4+ [%other value=@p]
5+++ final ^- $-((list @t) [(list @t) @t (unit @t)]) initial
6+++ initial |= xs=(list @t) [xs "" ~]
7+++ send |= f=$-(@t A) f
8+++ first (send |=%got)
9+++ fixed ^- $-(@t message) first
10+++ main initial
tests/type-deferred-prepared/mold-collision.txtnew file+9
@@ -0,0 +1,9 @@
1++$ list [xs=(list @t) draft=@t error=(unit @t)]
2++$ message
3+ [%got value=@t]
4+ [%other value=@p]
5+++ final ^- $-((list @t) [(list @t) @t (unit @t)]) initial
6+++ initial |= xs=(list @t) [xs "" ~]
7+++ send |= f=$-(@t A) f
8+++ first (send |=%got)
9+++ fixed ^- $-(@t message) first
tests/type-deferred-prepared/no-final-cast.txtnew file+8
@@ -0,0 +1,8 @@
1++$ model [xs=(list @t) draft=@t error=(unit @t)]
2++$ message
3+ [%got value=@t]
4+ [%other value=@p]
5+++ initial |= xs=(list @t) [xs "" ~]
6+++ send |= f=$-(@t A) f
7+++ first (send |=%got)
8+++ fixed ^- $-(@t message) first
tests/type-deferred-prepared/no-prelude.txtnew file+9
@@ -0,0 +1,9 @@
1++$ maybe
2+ %none
3+ [%some value=@t]
4++$ model [draft=@t error=maybe]
5+++ final ^- $-(@t [@t maybe]) initial
6+++ initial |= draft=@t [draft %none]
7+++ send |= f=$-(@t A) f
8+++ first (send |=%some)
9+++ fixed ^- $-(@t maybe) first
tests/type-deferred-prepared/tuple-only.txtnew file+3
@@ -0,0 +1,3 @@
1++$ model [xs=(list @t) draft=@t error=(unit @t)]
2+++ final ^- $-((list @t) [(list @t) @t (unit @t)]) initial
3+++ initial |= xs=(list @t) [xs "" ~]
tests/type-deferred-prepared/unrelated-tag.txtnew file+11
@@ -0,0 +1,11 @@
1++$ model [xs=(list @t) draft=@t error=(unit @t)]
2++$ message
3+ [%got value=@t]
4+ [%other value=@p]
5+++ final ^- $-((list @t) [(list @t) @t (unit @t)]) initial
6+++ initial |= xs=(list @t) [xs "" ~]
7+++ send |= f=$-(@t A) f
8+++ first (send |=%got)
9+++ fixed ^- $-(@t message) first
10+
11+++ unresolved |= x=@t %dangling
tests/type-deferred-prepared/wrong-draft.txtnew file+9
@@ -0,0 +1,9 @@
1++$ model [xs=(list @t) draft=@t error=(unit @t)]
2++$ message
3+ [%got value=@t]
4+ [%other value=@p]
5+++ final ^- $-((list @t) [(list @t) @t (unit @t)]) initial
6+++ initial |= xs=(list @t) [xs ~zod ~]
7+++ send |= f=$-(@t A) f
8+++ first (send |=%got)
9+++ fixed ^- $-(@t message) first
tests/type-deferred-prepared/wrong-unit.txtnew file+9
@@ -0,0 +1,9 @@
1++$ model [xs=(list @t) draft=@t error=(unit @t)]
2++$ message
3+ [%got value=@t]
4+ [%other value=@p]
5+++ final ^- $-((list @t) [(list @t) @t (unit @t)]) initial
6+++ initial |= xs=(list @t) [xs "" %absent]
7+++ send |= f=$-(@t A) f
8+++ first (send |=%got)
9+++ fixed ^- $-(@t message) first
tools/testdata/ship-selftest+6
@@ -334,6 +334,7 @@ def generator_checks(tmp):
334334 'tests/lib/jibb-deferred.hoon',
335335 'tests/lib/jibb-deferred-resolver.hoon',
336336 'tests/lib/jibb-deferred-context.hoon',
337+ 'tests/lib/jibb-deferred-prepared.hoon',
337338 'tests/lib/jibb-cell-branch.hoon'}
338339 <= normal_tests, sorted(normal_tests))
339340 check('generic recursion source and golden are assembled',
@@ -383,6 +384,11 @@ def generator_checks(tmp):
383384 {f'tests/type-deferred-context/{name}.txt' for name in (
384385 'rich', 'plain', 'simple', 'missing', 'wrong', 'duplicate',
385386 'dangling', 'collision-early', 'collision-late', 'report')} <= set(normal.files))
387+ check('prepared initializer sources and exact reports are assembled',
388+ {f'tests/type-deferred-prepared/{name}.txt' for name in (
389+ 'good', 'tuple-only', 'wrong-unit', 'wrong-draft', 'unrelated-tag',
390+ 'mold-collision', 'no-final-cast', 'no-prelude', 'main',
391+ 'imported', 'expected', 'expected-control', 'expected-tuple-only')} <= set(normal.files))
386392 check('cell branch sources are assembled',
387393 {'tests/type-cell-branch/good.txt', 'tests/type-cell-branch/bad.txt'}
388394 <= set(normal.files))
tools/type-deferred-prepared-testnew file+49
@@ -0,0 +1,49 @@
1+#!/usr/bin/env python3
2+"""Evaluate prepared-prelude initializer recovery and report guards."""
3+from pathlib import Path
4+import argparse, subprocess, sys, tempfile
5+root = Path(__file__).resolve().parent.parent
6+p = argparse.ArgumentParser(description=__doc__)
7+p.add_argument('--lib', default=str(root/'jibb-dev/lib/jibb.hoon'))
8+p.add_argument('--hoon', default=str(root/'tools/hoon'))
9+a = p.parse_args()
10+core = (root / 'tests/lib/jibb-deferred-prepared.hoon').read_text()
11+core = core[core.index('\n|%\n') + 1:]
12+names = ['good', 'tuple-only', 'wrong-unit', 'wrong-draft', 'unrelated-tag', 'mold-collision',
13+ 'no-final-cast', 'no-prelude', 'main', 'imported', 'expected', 'expected-control',
14+ 'expected-tuple-only']
15+bindings = ''.join('=/ '+('main-source' if n == 'main' else n)+'=wain (to-wain:format '+n+'-text)\n' for n in names)
16+at = '/ui/prepared/jibb'
17+checks = ['(check-prepared:suite %s %s %s)' % (where, source, valid)
18+ for where, source, valid in (
19+ (at, 'good', '&'), (at, 'tuple-only', '&'), (at, 'no-prelude', '&'),
20+ (at, 'wrong-unit', '|'), (at, 'wrong-draft', '|'),
21+ (at, 'unrelated-tag', '|'), (at, 'mold-collision', '|'),
22+ (at, 'no-final-cast', '|'), (at, 'main-source', '|'),
23+ (at, 'imported', '|'),
24+ ('/ui/api/prepared/jibb', 'good', '|'),
25+ ('/ui/stores/prepared/jibb', 'good', '|'))]
26+checks += ['check-no-prelude:suite', 'check-ordinary:suite', 'check-prepared-binding:suite',
27+ '(check-report:suite good expected)', '(check-report:suite tuple-only expected-tuple-only)',
28+ '(check-report:suite no-final-cast expected-control)']
29+with tempfile.TemporaryDirectory(prefix='jibb-deferred-prepared-') as d:
30+ f = Path(d) / 'report.hoon'
31+ for check in checks:
32+ program = ('=/ jibb .\n' + bindings + '=/ suite\n' + core +
33+ "\n^- @t\n=/ checked=tang " + check + "\n?~ checked 'prepared deferred inference guards passed'\n(crip \"{<checked>}\")\n")
34+ f.write_text(program)
35+ cmd = [a.hoon, '--lib', a.lib, '--raw', '-f', str(f),
36+ '--cord', 'prelude='+str(root/'jibb-dev/lib/jibb/prelude.jibb'),
37+ '--cord', 'internal='+str(root/'jibb-dev/lib/jibb/internal.jibb')]
38+ for n in names:
39+ fixture = root/'tests/type-deferred-prepared'/(n+'.txt')
40+ if not fixture.is_file() or fixture.stat().st_size == 0:
41+ sys.exit('missing or empty fixture: '+str(fixture))
42+ cmd.extend(['--cord', n+'-text='+str(fixture)])
43+ got = subprocess.run(cmd, stdout=subprocess.PIPE)
44+ if got.returncode:
45+ sys.exit(got.returncode)
46+ if got.stdout != b'prepared deferred inference guards passed\n':
47+ sys.stderr.write(got.stdout.decode(errors='replace'))
48+ sys.exit(1)
49+print('prepared deferred inference guards passed')