on master help sign in
525 files changed+17322−1647
since splitsnapshots
unifiedsplit
.github/workflows/check.yml−22 README.md+2−3 docs/README.md+6−1 docs/compiler.md+11−3 docs/development.md+5−3 docs/open-questions.md+2−2 docs/prompts/milestone-2-finish.md+97 docs/prompts/repo-review-finish.md+149 docs/prompts/syntax-review-follow-up.md+80 docs/reviews/2026-11-02-questions.md+2 docs/reviews/2026-11-02-syntax-review.md+14 docs/reviews/2026-11-03-checker-map.md+587 docs/reviews/2026-11-03-milestone-2-probes/README.md+23 docs/reviews/2026-11-03-milestone-2-probes/app-check.hoon+67 docs/reviews/2026-11-03-milestone-2-probes/check.hoon+37 docs/reviews/2026-11-03-milestone-2-probes/errors/import-check.hoon+101 docs/reviews/2026-11-03-milestone-2-probes/errors/import-check.out+82 docs/reviews/2026-11-03-milestone-2-probes/errors/p1.jibb+155 docs/reviews/2026-11-03-milestone-2-probes/errors/p1.out+133 docs/reviews/2026-11-03-milestone-2-probes/errors/p2.jibb+106 docs/reviews/2026-11-03-milestone-2-probes/errors/p2.out+38 docs/reviews/2026-11-03-milestone-2-probes/errors/p3.jibb+68 docs/reviews/2026-11-03-milestone-2-probes/errors/p3.out+16 docs/reviews/2026-11-03-milestone-2-probes/errors/p4.jibb+30 docs/reviews/2026-11-03-milestone-2-probes/errors/p4.out+22 docs/reviews/2026-11-03-milestone-2-probes/errors/p5.jibb+45 docs/reviews/2026-11-03-milestone-2-probes/run+46 docs/reviews/2026-11-03-milestone-2-probes/variants/p1.jibb+194 docs/reviews/2026-11-03-milestone-2-probes/variants/p10.jibb+324 docs/reviews/2026-11-03-milestone-2-probes/variants/p10.out+33 docs/reviews/2026-11-03-milestone-2-probes/variants/p2.jibb+919 docs/reviews/2026-11-03-milestone-2-probes/variants/p2.out+185 docs/reviews/2026-11-03-milestone-2-probes/variants/p3.jibb+712 docs/reviews/2026-11-03-milestone-2-probes/variants/p3.out+262 docs/reviews/2026-11-03-milestone-2-probes/variants/p4.jibb+196 docs/reviews/2026-11-03-milestone-2-probes/variants/p4.out+113 docs/reviews/2026-11-03-milestone-2-probes/variants/p5.jibb+130 docs/reviews/2026-11-03-milestone-2-probes/variants/p5.out+127 docs/reviews/2026-11-03-milestone-2-probes/variants/p6.jibb+498 docs/reviews/2026-11-03-milestone-2-probes/variants/p6.out+66 docs/reviews/2026-11-03-milestone-2-probes/variants/p7.jibb+389 docs/reviews/2026-11-03-milestone-2-probes/variants/p7.out+85 docs/reviews/2026-11-03-milestone-2-probes/variants/p8.jibb+342 docs/reviews/2026-11-03-milestone-2-probes/variants/p8.out+57 docs/reviews/2026-11-03-milestone-2-probes/variants/p9.jibb+311 docs/reviews/2026-11-03-milestone-2-probes/variants/p9.out+33 docs/reviews/2026-11-03-milestone-2-review.md+115 docs/spec/core-language.md+10−9 docs/spec/decisions.md+11−8 docs/spec/grammar.md+55−34 docs/spec/overview.md+9−9 docs/status.md+269−289 jibb-dev/lib/jibb.hoon+1226−254 jibb-dev/lib/jibb/prelude.jibb+183−190 my-app/ui/basket.jibb+6−6 my-app/ui/stores/cart.jibb+3−3 my-app/ui/todo-list.jibb+9−9 tests/golden/doc-core-02-update/about.txt+1−1 tests/golden/doc-core-02-update/source.jibb+8−8 tests/golden/doc-core-02-update/tokens.txt+120−122 tests/golden/doc-core-02-update/tree.txt+64−64 tests/golden/doc-grammar-02-buttons/types.txt+1−1 tests/golden/doc-grammar-04-step/about.txt+1−1 tests/golden/doc-grammar-04-step/source.jibb+5−5 tests/golden/doc-grammar-04-step/tokens.txt+36−37 tests/golden/doc-grammar-04-step/tree.txt+13−13 tests/golden/doc-grammar-06-cart-store/about.txt+1−1 tests/golden/doc-grammar-06-cart-store/tokens.txt+34−31 tests/golden/doc-grammar-06-cart-store/tree.txt+14−12 tests/golden/doc-grammar-07-basket/about.txt+1−1 tests/golden/doc-grammar-07-basket/tokens.txt+85−78 tests/golden/doc-grammar-07-basket/tree.txt+38−35 tests/golden/doc-overview-10-todo-list/about.txt+1−1 tests/golden/doc-overview-10-todo-list/tokens.txt+128−124 tests/golden/doc-overview-10-todo-list/tree.txt+68−65 tests/golden/inline-cell-wing-face-bad/about.txt+3 tests/golden/inline-cell-wing-face-bad/source.jibb+1 tests/golden/inline-cell-wing-face-bad/tokens.txt+8 tests/golden/inline-cell-wing-face-bad/tree.txt+3 tests/golden/inline-change-wing/about.txt+3 tests/golden/inline-change-wing/source.jibb+2 tests/golden/inline-change-wing/tokens.txt+18 tests/golden/inline-change-wing/tree.txt+9 tests/golden/inline-decimal-aura-bad/about.txt+4 tests/golden/inline-decimal-aura-bad/source.jibb+10 tests/golden/inline-decimal-aura-bad/tokens.txt+60 tests/golden/inline-decimal-aura-bad/tree.txt+21 tests/golden/inline-decimal-aura-bad/types.txt+41 tests/golden/inline-decimal-fits/about.txt+4 tests/golden/inline-decimal-fits/modules.txt+1 tests/golden/inline-decimal-fits/source.jibb+9 tests/golden/inline-decimal-fits/tokens.txt+64 tests/golden/inline-decimal-fits/tree.txt+23 tests/golden/inline-decimal-fits/types.txt+10 tests/golden/inline-decimal-generic/about.txt+4 tests/golden/inline-decimal-generic/modules.txt+1 tests/golden/inline-decimal-generic/source.jibb+5 tests/golden/inline-decimal-generic/tokens.txt+40 tests/golden/inline-decimal-generic/tree.txt+18 tests/golden/inline-decimal-generic/types.txt+6 tests/golden/inline-decimal-patterns/about.txt+4 tests/golden/inline-decimal-patterns/source.jibb+30 tests/golden/inline-decimal-patterns/tokens.txt+181 tests/golden/inline-decimal-patterns/tree.txt+82 tests/golden/inline-decimal-patterns/types.txt+28 tests/golden/inline-decimal-sites/about.txt+4 tests/golden/inline-decimal-sites/modules.txt+1 tests/golden/inline-decimal-sites/source.jibb+24 tests/golden/inline-decimal-sites/tokens.txt+258 tests/golden/inline-decimal-sites/tree.txt+103 tests/golden/inline-decimal-sites/types.txt+69 tests/golden/inline-decimal/about.txt+1−1 tests/golden/inline-pattern-nested/about.txt+3 tests/golden/inline-pattern-nested/source.jibb+9 tests/golden/inline-pattern-nested/tokens.txt+71 tests/golden/inline-pattern-nested/tree.txt+31 tests/golden/inline-pattern-tag-name-any-arm/about.txt+4 tests/golden/inline-pattern-tag-name-any-arm/modules.txt+1 tests/golden/inline-pattern-tag-name-any-arm/source.jibb+30 tests/golden/inline-pattern-tag-name-any-arm/tokens.txt+160 tests/golden/inline-pattern-tag-name-any-arm/tree.txt+69 tests/golden/inline-pattern-tag-name-any-arm/types.txt+32 tests/golden/inline-pattern-tag-name-generic/about.txt+4 tests/golden/inline-pattern-tag-name-generic/modules.txt+1 tests/golden/inline-pattern-tag-name-generic/source.jibb+30 tests/golden/inline-pattern-tag-name-generic/tokens.txt+158 tests/golden/inline-pattern-tag-name-generic/tree.txt+71 tests/golden/inline-pattern-tag-name-generic/types.txt+21 tests/golden/inline-pattern-tag-name-last/about.txt+4 tests/golden/inline-pattern-tag-name-last/modules.txt+1 tests/golden/inline-pattern-tag-name-last/source.jibb+14 tests/golden/inline-pattern-tag-name-last/tokens.txt+85 tests/golden/inline-pattern-tag-name-last/tree.txt+38 tests/golden/inline-pattern-tag-name-last/types.txt+9 tests/golden/inline-pattern-tag-name-nested/about.txt+4 tests/golden/inline-pattern-tag-name-nested/modules.txt+1 tests/golden/inline-pattern-tag-name-nested/source.jibb+27 tests/golden/inline-pattern-tag-name-nested/tokens.txt+132 tests/golden/inline-pattern-tag-name-nested/tree.txt+59 tests/golden/inline-pattern-tag-name-nested/types.txt+25 tests/golden/inline-pattern-tag-name-ok/about.txt+4 tests/golden/inline-pattern-tag-name-ok/modules.txt+1 tests/golden/inline-pattern-tag-name-ok/source.jibb+53 tests/golden/inline-pattern-tag-name-ok/tokens.txt+303 tests/golden/inline-pattern-tag-name-ok/tree.txt+133 tests/golden/inline-pattern-tag-name-ok/types.txt+13 tests/golden/inline-pattern-tag-name-one-case/about.txt+4 tests/golden/inline-pattern-tag-name-one-case/modules.txt+1 tests/golden/inline-pattern-tag-name-one-case/source.jibb+11 tests/golden/inline-pattern-tag-name-one-case/tokens.txt+64 tests/golden/inline-pattern-tag-name-one-case/tree.txt+31 tests/golden/inline-pattern-tag-name-one-case/types.txt+18 tests/golden/inline-unface-arity-bad/about.txt+4 tests/golden/inline-unface-arity-bad/modules.txt+1 tests/golden/inline-unface-arity-bad/source.jibb+3 tests/golden/inline-unface-arity-bad/tokens.txt+31 tests/golden/inline-unface-arity-bad/tree.txt+13 tests/golden/inline-unface-arity-bad/types.txt+10 tests/golden/inline-unface-deep/about.txt+4 tests/golden/inline-unface-deep/modules.txt+1 tests/golden/inline-unface-deep/source.jibb+10 tests/golden/inline-unface-deep/tokens.txt+129 tests/golden/inline-unface-deep/tree.txt+55 tests/golden/inline-unface-deep/types.txt+11 tests/golden/inline-unface-gates/about.txt+4 tests/golden/inline-unface-gates/modules.txt+1 tests/golden/inline-unface-gates/source.jibb+11 tests/golden/inline-unface-gates/tokens.txt+160 tests/golden/inline-unface-gates/tree.txt+78 tests/golden/inline-unface-gates/types.txt+30 tests/golden/inline-unface-import/about.txt+4 tests/golden/inline-unface-import/module-trees.txt+43 tests/golden/inline-unface-import/modules.txt+1 tests/golden/inline-unface-import/modules/ui/lib.jibb+9 tests/golden/inline-unface-import/source.jibb+5 tests/golden/inline-unface-import/tokens.txt+38 tests/golden/inline-unface-import/tree.txt+17 tests/golden/inline-unface-import/types.txt+5 tests/golden/inline-unface-labelled-slot/about.txt+4 tests/golden/inline-unface-labelled-slot/modules.txt+1 tests/golden/inline-unface-labelled-slot/source.jibb+5 tests/golden/inline-unface-labelled-slot/tokens.txt+76 tests/golden/inline-unface-labelled-slot/tree.txt+37 tests/golden/inline-unface-labelled-slot/types.txt+12 tests/golden/inline-unface-lambda/about.txt+4 tests/golden/inline-unface-lambda/modules.txt+1 tests/golden/inline-unface-lambda/source.jibb+3 tests/golden/inline-unface-lambda/tokens.txt+52 tests/golden/inline-unface-lambda/tree.txt+28 tests/golden/inline-unface-lambda/types.txt+10 tests/golden/inline-unface-named-union/about.txt+4 tests/golden/inline-unface-named-union/modules.txt+1 tests/golden/inline-unface-named-union/source.jibb+9 tests/golden/inline-unface-named-union/tokens.txt+89 tests/golden/inline-unface-named-union/tree.txt+46 tests/golden/inline-unface-named-union/types.txt+8 tests/golden/inline-unface-records/about.txt+4 tests/golden/inline-unface-records/modules.txt+1 tests/golden/inline-unface-records/source.jibb+8 tests/golden/inline-unface-records/tokens.txt+94 tests/golden/inline-unface-records/tree.txt+44 tests/golden/inline-unface-records/types.txt+21 tests/golden/inline-unface-recursive/about.txt+4 tests/golden/inline-unface-recursive/modules.txt+1 tests/golden/inline-unface-recursive/source.jibb+23 tests/golden/inline-unface-recursive/tokens.txt+182 tests/golden/inline-unface-recursive/tree.txt+98 tests/golden/inline-unface-recursive/types.txt+6 tests/golden/inline-unface-reserved-import/about.txt+4 tests/golden/inline-unface-reserved-import/module-trees.txt+6 tests/golden/inline-unface-reserved-import/modules.txt+1 tests/golden/inline-unface-reserved-import/modules/ui/lib.jibb+1 tests/golden/inline-unface-reserved-import/source.jibb+2 tests/golden/inline-unface-reserved-import/tokens.txt+11 tests/golden/inline-unface-reserved-import/tree.txt+3 tests/golden/inline-unface-reserved-import/types.txt+2 tests/golden/inline-unface-reserved-local/about.txt+4 tests/golden/inline-unface-reserved-local/modules.txt+1 tests/golden/inline-unface-reserved-local/source.jibb+3 tests/golden/inline-unface-reserved-local/tokens.txt+14 tests/golden/inline-unface-reserved-local/tree.txt+8 tests/golden/inline-unface-reserved-local/types.txt+2 tests/golden/inline-unface-reserved-mold/about.txt+4 tests/golden/inline-unface-reserved-mold/modules.txt+1 tests/golden/inline-unface-reserved-mold/source.jibb+2 tests/golden/inline-unface-reserved-mold/tokens.txt+8 tests/golden/inline-unface-reserved-mold/tree.txt+3 tests/golden/inline-unface-reserved-mold/types.txt+2 tests/golden/inline-unface-reserved-no-prelude/about.txt+4 tests/golden/inline-unface-reserved-no-prelude/source.jibb+2 tests/golden/inline-unface-reserved-no-prelude/tokens.txt+8 tests/golden/inline-unface-reserved-no-prelude/tree.txt+3 tests/golden/inline-unface-reserved-no-prelude/types.txt+1 tests/golden/inline-unface-reserved-pattern/about.txt+4 tests/golden/inline-unface-reserved-pattern/modules.txt+1 tests/golden/inline-unface-reserved-pattern/source.jibb+3 tests/golden/inline-unface-reserved-pattern/tokens.txt+21 tests/golden/inline-unface-reserved-pattern/tree.txt+11 tests/golden/inline-unface-reserved-pattern/types.txt+2 tests/golden/inline-unface-reserved-positive/about.txt+4 tests/golden/inline-unface-reserved-positive/modules.txt+1 tests/golden/inline-unface-reserved-positive/source.jibb+6 tests/golden/inline-unface-reserved-positive/tokens.txt+36 tests/golden/inline-unface-reserved-positive/tree.txt+15 tests/golden/inline-unface-reserved-positive/types.txt+5 tests/golden/inline-unface-reserved-sample/about.txt+4 tests/golden/inline-unface-reserved-sample/modules.txt+1 tests/golden/inline-unface-reserved-sample/source.jibb+1 tests/golden/inline-unface-reserved-sample/tokens.txt+13 tests/golden/inline-unface-reserved-sample/tree.txt+7 tests/golden/inline-unface-reserved-sample/types.txt+2 tests/golden/inline-unface-reserved-value/about.txt+4 tests/golden/inline-unface-reserved-value/modules.txt+1 tests/golden/inline-unface-reserved-value/source.jibb+2 tests/golden/inline-unface-reserved-value/tokens.txt+12 tests/golden/inline-unface-reserved-value/tree.txt+6 tests/golden/inline-unface-reserved-value/types.txt+2 tests/golden/inline-unface-unknown/about.txt+4 tests/golden/inline-unface-unknown/modules.txt+1 tests/golden/inline-unface-unknown/source.jibb+3 tests/golden/inline-unface-unknown/tokens.txt+36 tests/golden/inline-unface-unknown/tree.txt+18 tests/golden/inline-unface-unknown/types.txt+4 tests/golden/inline-unface-value-bad/about.txt+4 tests/golden/inline-unface-value-bad/modules.txt+1 tests/golden/inline-unface-value-bad/source.jibb+6 tests/golden/inline-unface-value-bad/tokens.txt+75 tests/golden/inline-unface-value-bad/tree.txt+37 tests/golden/inline-unface-value-bad/types.txt+13 tests/golden/lex-body-rest-bad-1/about.txt+3 tests/golden/lex-body-rest-bad-1/source.jibb+4 tests/golden/lex-body-rest-bad-1/tokens.txt+26 tests/golden/lex-body-rest-bad-1/tree.txt+3 tests/golden/lex-body-rest-bad-10/about.txt+3 tests/golden/lex-body-rest-bad-10/source.jibb+5 tests/golden/lex-body-rest-bad-10/tokens.txt+21 tests/golden/lex-body-rest-bad-10/tree.txt+3 tests/golden/lex-body-rest-bad-11/about.txt+3 tests/golden/lex-body-rest-bad-11/source.jibb+4 tests/golden/lex-body-rest-bad-11/tokens.txt+18 tests/golden/lex-body-rest-bad-11/tree.txt+3 tests/golden/lex-body-rest-bad-12/about.txt+3 tests/golden/lex-body-rest-bad-12/source.jibb+5 tests/golden/lex-body-rest-bad-12/tokens.txt+21 tests/golden/lex-body-rest-bad-12/tree.txt+3 tests/golden/lex-body-rest-bad-13/about.txt+3 tests/golden/lex-body-rest-bad-13/source.jibb+5 tests/golden/lex-body-rest-bad-13/tokens.txt+20 tests/golden/lex-body-rest-bad-13/tree.txt+3 tests/golden/lex-body-rest-bad-14/about.txt+3 tests/golden/lex-body-rest-bad-14/source.jibb+5 tests/golden/lex-body-rest-bad-14/tokens.txt+20 tests/golden/lex-body-rest-bad-14/tree.txt+3 tests/golden/lex-body-rest-bad-15/about.txt+3 tests/golden/lex-body-rest-bad-15/source.jibb+5 tests/golden/lex-body-rest-bad-15/tokens.txt+3 tests/golden/lex-body-rest-bad-15/tree.txt+3 tests/golden/lex-body-rest-bad-16/about.txt+3 tests/golden/lex-body-rest-bad-16/source.jibb+3 tests/golden/lex-body-rest-bad-16/tokens.txt+15 tests/golden/lex-body-rest-bad-16/tree.txt+3 tests/golden/lex-body-rest-bad-2/about.txt+3 tests/golden/lex-body-rest-bad-2/source.jibb+5 tests/golden/lex-body-rest-bad-2/tokens.txt+27 tests/golden/lex-body-rest-bad-2/tree.txt+3 tests/golden/lex-body-rest-bad-3/about.txt+3 tests/golden/lex-body-rest-bad-3/source.jibb+4 tests/golden/lex-body-rest-bad-3/tokens.txt+19 tests/golden/lex-body-rest-bad-3/tree.txt+3 tests/golden/lex-body-rest-bad-4/about.txt+3 tests/golden/lex-body-rest-bad-4/source.jibb+5 tests/golden/lex-body-rest-bad-4/tokens.txt+21 tests/golden/lex-body-rest-bad-4/tree.txt+3 tests/golden/lex-body-rest-bad-5/about.txt+3 tests/golden/lex-body-rest-bad-5/source.jibb+5 tests/golden/lex-body-rest-bad-5/tokens.txt+20 tests/golden/lex-body-rest-bad-5/tree.txt+3 tests/golden/lex-body-rest-bad-6/about.txt+3 tests/golden/lex-body-rest-bad-6/source.jibb+4 tests/golden/lex-body-rest-bad-6/tokens.txt+16 tests/golden/lex-body-rest-bad-6/tree.txt+3 tests/golden/lex-body-rest-bad-7/about.txt+3 tests/golden/lex-body-rest-bad-7/source.jibb+5 tests/golden/lex-body-rest-bad-7/tokens.txt+22 tests/golden/lex-body-rest-bad-7/tree.txt+3 tests/golden/lex-body-rest-bad-8/about.txt+3 tests/golden/lex-body-rest-bad-8/source.jibb+4 tests/golden/lex-body-rest-bad-8/tokens.txt+16 tests/golden/lex-body-rest-bad-8/tree.txt+3 tests/golden/lex-body-rest-bad-9/about.txt+3 tests/golden/lex-body-rest-bad-9/source.jibb+2 tests/golden/lex-body-rest-bad-9/tokens.txt+7 tests/golden/lex-body-rest-bad-9/tree.txt+3 tests/golden/lex-body-rest-ok-1/about.txt+4 tests/golden/lex-body-rest-ok-1/module-trees.txt+4 tests/golden/lex-body-rest-ok-1/modules.txt+1 tests/golden/lex-body-rest-ok-1/modules/ui/lib.jibb+1 tests/golden/lex-body-rest-ok-1/source.jibb+11 tests/golden/lex-body-rest-ok-1/tokens.txt+62 tests/golden/lex-body-rest-ok-1/tree.txt+30 tests/golden/lex-body-rest-ok-1/types.txt+4 tests/golden/lex-body-rest-ok-2/about.txt+4 tests/golden/lex-body-rest-ok-2/module-trees.txt+4 tests/golden/lex-body-rest-ok-2/modules.txt+1 tests/golden/lex-body-rest-ok-2/modules/ui/lib.jibb+1 tests/golden/lex-body-rest-ok-2/source.jibb+12 tests/golden/lex-body-rest-ok-2/tokens.txt+67 tests/golden/lex-body-rest-ok-2/tree.txt+36 tests/golden/lex-body-rest-ok-2/types.txt+4 tests/golden/lex-body-rest-ok-3/about.txt+3 tests/golden/lex-body-rest-ok-3/source.jibb+6 tests/golden/lex-body-rest-ok-3/tokens.txt+35 tests/golden/lex-body-rest-ok-3/tree.txt+18 tests/golden/lex-body-rest-ok-4/about.txt+4 tests/golden/lex-body-rest-ok-4/source.jibb+13 tests/golden/lex-body-rest-ok-4/tokens.txt+46 tests/golden/lex-body-rest-ok-4/tree.txt+23 tests/golden/lex-body-rest-ok-4/types.txt+4 tests/golden/lex-body-rest-ok-5/about.txt+3 tests/golden/lex-body-rest-ok-5/source.jibb+7 tests/golden/lex-body-rest-ok-5/tokens.txt+25 tests/golden/lex-body-rest-ok-5/tree.txt+15 tests/golden/lex-body-rest-ok-6/about.txt+3 tests/golden/lex-body-rest-ok-6/source.jibb+7 tests/golden/lex-body-rest-ok-6/tokens.txt+35 tests/golden/lex-body-rest-ok-6/tree.txt+18 tests/golden/lex-body-rest-ok-7/about.txt+4 tests/golden/lex-body-rest-ok-7/module-trees.txt+4 tests/golden/lex-body-rest-ok-7/modules.txt+1 tests/golden/lex-body-rest-ok-7/modules/ui/lib.jibb+1 tests/golden/lex-body-rest-ok-7/source.jibb+10 tests/golden/lex-body-rest-ok-7/tokens.txt+51 tests/golden/lex-body-rest-ok-7/tree.txt+26 tests/golden/lex-body-rest-ok-7/types.txt+3 tests/golden/lex-body-rest-ok-8/about.txt+4 tests/golden/lex-body-rest-ok-8/module-trees.txt+4 tests/golden/lex-body-rest-ok-8/modules.txt+1 tests/golden/lex-body-rest-ok-8/modules/ui/lib.jibb+1 tests/golden/lex-body-rest-ok-8/source.jibb+14 tests/golden/lex-body-rest-ok-8/tokens.txt+63 tests/golden/lex-body-rest-ok-8/tree.txt+32 tests/golden/lex-body-rest-ok-8/types.txt+3 tests/golden/lex-call-open-bad-1/about.txt → tests/golden/lex-call-open-ok-3/about.txt tests/golden/lex-call-open-bad-1/source.jibb → tests/golden/lex-call-open-ok-3/source.jibb tests/golden/lex-call-open-bad-1/tokens.txt → tests/golden/lex-call-open-ok-3/tokens.txt tests/golden/lex-call-open-bad-1/tree.txt → tests/golden/lex-call-open-ok-3/tree.txt tests/golden/lex-layout-bad-4/about.txt+1−1 tests/golden/lex-layout-bad-4/tree.txt+1−1 tests/golden/lex-name-bad-5/tokens.txt+4−3 tests/golden/lex-name-bad-5/tree.txt+1−1 tests/golden/lex-rune-layout-bad-3/about.txt−3 tests/golden/lex-rune-layout-bad-3/tree.txt−3 tests/golden/lex-rune-layout-ok-3/about.txt+3 tests/golden/lex-rune-layout-bad-3/source.jibb → tests/golden/lex-rune-layout-ok-3/source.jibb tests/golden/lex-rune-layout-bad-3/tokens.txt → tests/golden/lex-rune-layout-ok-3/tokens.txt tests/golden/lex-rune-layout-ok-3/tree.txt+6 tests/golden/lex-tight-change-bad-10/about.txt+3 tests/golden/lex-tight-change-bad-10/source.jibb+1 tests/golden/lex-tight-change-bad-10/tokens.txt+7 tests/golden/lex-tight-change-bad-10/tree.txt+3 tests/golden/lex-tight-change-bad-11/about.txt+3 tests/golden/lex-tight-change-bad-11/source.jibb+2 tests/golden/lex-tight-change-bad-11/tokens.txt+9 tests/golden/lex-tight-change-bad-11/tree.txt+3 tests/golden/lex-tight-change-bad-5/about.txt+3−3 tests/golden/lex-tight-change-bad-5/source.jibb+1−1 tests/golden/lex-tight-change-bad-5/tokens.txt+1−2 tests/golden/lex-tight-change-bad-5/tree.txt+3−3 tests/golden/lex-tight-change-ok-2/about.txt+3 tests/golden/lex-tight-change-ok-2/source.jibb+7 tests/golden/lex-tight-change-ok-2/tokens.txt+55 tests/golden/lex-tight-change-ok-2/tree.txt+20 tests/golden/lex-typevar-bad-1/about.txt+3 tests/golden/lex-typevar-bad-1/source.jibb+1 tests/golden/lex-typevar-bad-1/tokens.txt+3 tests/golden/lex-typevar-bad-1/tree.txt+3 tests/golden/lex-typevar-bad-2/about.txt+3 tests/golden/lex-typevar-bad-2/source.jibb+1 tests/golden/lex-typevar-bad-2/tokens.txt+3 tests/golden/lex-typevar-bad-2/tree.txt+3 tests/golden/lex-typevar-bad-3/about.txt+3 tests/golden/lex-typevar-bad-3/source.jibb+1 tests/golden/lex-typevar-bad-3/tokens.txt+3 tests/golden/lex-typevar-bad-3/tree.txt+3 tests/golden/lex-typevar-bad-4/about.txt+3 tests/golden/lex-typevar-bad-4/source.jibb+1 tests/golden/lex-typevar-bad-4/tokens.txt+3 tests/golden/lex-typevar-bad-4/tree.txt+3 tests/golden/lex-typevar-ok-1/about.txt+4 tests/golden/lex-typevar-ok-1/source.jibb+3 tests/golden/lex-typevar-ok-1/tokens.txt+39 tests/golden/lex-typevar-ok-1/tree.txt+15 tests/golden/lex-typevar-ok-1/types.txt+4 tests/golden/module-import-api-scope-conflict/types.txt+7−1 tests/golden/module-import-prelude-value-shadow/types.txt+7−1 tests/golden/prelude-unit-list-transforms/types.txt+1−1 tests/golden/types-change-overlap-lines/about.txt+4 tests/golden/types-change-overlap-lines/modules.txt+1 tests/golden/types-change-overlap-lines/source.jibb+7 tests/golden/types-change-overlap-lines/tokens.txt+49 tests/golden/types-change-overlap-lines/tree.txt+18 tests/golden/types-change-overlap-lines/types.txt+8 tests/golden/types-change-overlap/about.txt+4 tests/golden/types-change-overlap/modules.txt+1 tests/golden/types-change-overlap/source.jibb+4 tests/golden/types-change-overlap/tokens.txt+57 tests/golden/types-change-overlap/tree.txt+22 tests/golden/types-change-overlap/types.txt+8 tests/golden/types-change-repeated-wing/about.txt+4 tests/golden/types-change-repeated-wing/modules.txt+1 tests/golden/types-change-repeated-wing/source.jibb+3 tests/golden/types-change-repeated-wing/tokens.txt+41 tests/golden/types-change-repeated-wing/tree.txt+16 tests/golden/types-change-repeated-wing/types.txt+8 tests/golden/types-change-repeated/about.txt+4 tests/golden/types-change-repeated/modules.txt+1 tests/golden/types-change-repeated/source.jibb+2 tests/golden/types-change-repeated/tokens.txt+39 tests/golden/types-change-repeated/tree.txt+15 tests/golden/types-change-repeated/types.txt+8 tests/golden/types-change-wing/about.txt+4 tests/golden/types-change-wing/modules.txt+1 tests/golden/types-change-wing/source.jibb+24 tests/golden/types-change-wing/tokens.txt+289 tests/golden/types-change-wing/tree.txt+111 tests/golden/types-change-wing/types.txt+46 tests/golden/types-constructor-context/types.txt+2−2 tests/golden/types-generic-union-alias-face/types.txt+1−1 tests/golden/types-generic-union-alias/types.txt+1−1 tests/golden/types-generic-union-local/types.txt+1−1 tests/golden/types-list-open-constraints/about.txt+1−1 tests/golden/types-list-open-constraints/types.txt+4−1 tests/golden/types-local-error-order/about.txt+1−1 tests/golden/types-local-error-order/source.jibb+3−3 tests/golden/types-local-error-order/tokens.txt+3−3 tests/golden/types-local-error-order/tree.txt+3−3 tests/golden/types-partial-aura-generalization/source.jibb+1−1 tests/golden/types-partial-aura-generalization/tokens.txt+8−8 tests/golden/types-partial-aura-generalization/tree.txt+5−5 tests/golden/types-partial-aura-generalization/types.txt+1−1 tests/golden/types-partial-aura/source.jibb+1−1 tests/golden/types-partial-aura/tokens.txt+2−2 tests/golden/types-partial-aura/tree.txt+1−1 tests/golden/types-partial-aura/types.txt+1−1 tests/golden/types-prelude-generic-alias/types.txt+1−1 tests/golden/types-prelude-lead-late/types.txt+1−1 tests/golden/types-prelude-like/source.jibb+1−1 tests/golden/types-prelude-like/tokens.txt+7−7 tests/golden/types-prelude-like/tree.txt+2−1 tests/golden/types-prelude-list-functions/types.txt+1−1 tests/golden/types-prelude-ui/types.txt+21−21 tests/golden/types-proj-explicit-context/types.txt+2−2 tests/golden/types-proj-nested-no-implicit/types.txt+3−3 tests/golden/types-proj-reserved-imported-definition/types.txt+4−1 tests/golden/types-record-change-generic/about.txt+1−1 tests/golden/types-record-change-generic/source.jibb−1 tests/golden/types-record-change-generic/tokens.txt+35−59 tests/golden/types-record-change-generic/tree.txt+15−24 tests/golden/types-record-change-generic/types.txt−1 tests/golden/types-recursion-scc-groups/types.txt+1−1 tests/golden/types-typevar-names/about.txt+4 tests/golden/types-typevar-names/modules.txt+1 tests/golden/types-typevar-names/source.jibb+14 tests/golden/types-typevar-names/tokens.txt+162 tests/golden/types-typevar-names/tree.txt+67 tests/golden/types-typevar-names/types.txt+27 tests/golden/types-typevar-print/about.txt+4 tests/golden/types-typevar-print/source.jibb+11 tests/golden/types-typevar-print/tokens.txt+108 tests/golden/types-typevar-print/tree.txt+43 tests/golden/types-typevar-print/types.txt+10 tests/lib/jibb-arithmetic-guards.hoon+4−3 tests/lib/jibb-doc-examples.hoon+1−1 tests/lib/jibb-full-diagnostics.hoon+45 tests/lib/jibb-full-scope.hoon+37 tests/lib/jibb-page-main.hoon+2 tests/lib/jibb-store.hoon+4−1 tests/type-buttons/expected.txt+1−1 tests/type-deferred-context/report.txt+1−1 tests/type-deferred-resolver/expected.txt+2−2 tests/type-direct-gate/expected.txt+2−2 tests/type-page-main/hand-built-load.txt+2−2 tools/check+1 tools/doc-fragments+61 tools/testdata/stub.hoon+4−1
.github/workflows/check.ymldeleted−22
@@ -1,22 +0,0 @@
1−# The eval checks on every push to master and every pull request:
2−# the flake builds the desks and runs `tools/check --group eval` in the
3−# Nix sandbox (see flake.nix). The ship checks need a fake ~zod and run
4−# before pushing, as docs/development.md says.
5−name: check
6−
7−on:
8− push:
9− branches: [master]
10− pull_request:
11− workflow_dispatch:
12−
13−jobs:
14− eval:
15− name: desks and eval checks
16− runs-on: ubuntu-latest
17− timeout-minutes: 120
18− steps:
19− - uses: actions/checkout@v4
20− - uses: cachix/install-nix-action@v31
21− - name: Build the desks and run the eval checks
22− run: nix build --print-build-logs .#checks.x86_64-linux.desks .#checks.x86_64-linux.eval
README.md+2−3
@@ -77,16 +77,15 @@ It matches each labelled block to the case whose `source.jibb` is the block's te
7777Each `tests/lib/<suite>.hoon` file is a test suite: a core whose `test-` arms return a `tang`, empty when the arm passes. `tools/ship test` runs every suite on the fake ship with the `-test` thread. `tools/test-arms` runs the same arms under `urbit eval`, without a ship, for every suite but the generated `jibb.hoon`, whose golden cases `tools/golden` runs. It gives each suite the subject Ford would give it on the `jibb-dev` desk: its `/+` libraries and its `/*` files, which must be `%txt` or `%jibb` files, from where `tools/ship assemble` puts them. Like `tools/golden`, it needs `urbit` on PATH and Python 3.
7878
7979```
80−tools/test-arms # the my-app copies, then every suite
80+tools/test-arms # every suite
8181tools/test-arms jibb-store 'jibb-program-*' # suites by name or glob
8282tools/test-arms --shard 2/4 # the second of four shards, balanced by measured cost
8383tools/test-arms --list # the suites and their arms; ", report" marks a golden report
8484tools/test-arms --report jibb-import # print a golden-report suite's report
8585tools/test-arms --update jibb-import # write it to the suite's expected file
86−tools/test-arms --copies # only the my-app copies
8786```
8887
89−Many suites share one eval, so the library is built once per eval, not once per suite. Each arm runs under `mule` and prints OK, FAILED or CRASHED, as `-test` does, with what it returned or, for a crash, its trace mapped to lines of the suite and the library. When an eval fails, it is run again one suite at a time, and each suite that doesn't build is reported as `FAILED <suite> (build)`, with its error placed in the suite file. An eval that runs past `--timeout`, 1800 s by default, fails each of its suites as `(timeout)`. The exit status is 0 when every arm passes, 1 when an arm, a golden file or a `my-app` copy fails, and 2 when the suites can't run, for example on a usage error or a suite header it can't read. `tools/check` runs the suites in four shards, `arms-1` to `arms-4`.
88+Many suites share one eval, so the library is built once per eval, not once per suite. Each arm runs under `mule` and prints OK, FAILED or CRASHED, as `-test` does, with what it returned or, for a crash, its trace mapped to lines of the suite and the library. When an eval fails, it is run again one suite at a time, and each suite that doesn't build is reported as `FAILED <suite> (build)`, with its error placed in the suite file. An eval that runs past `--timeout`, 1800 s by default, fails each of its suites as `(timeout)`. The exit status is 0 when every arm passes, 1 when an arm or a golden file fails, and 2 when the suites can't run, for example on a usage error or a suite header it can't read. `tools/check` runs the suites in four shards, `arms-1` to `arms-4`.
9089
9190A golden-report suite has a `report` arm and a `/*` file bound to the face `expected`; when one of its arms fails, the runner prints a diff between that file and the report. Before any eval, the runner checks the golden files of the suites it runs, the `%txt` files bound to a face containing `expected`: each must end in exactly one newline, which an arm can't see in the file's wain, and hold no line that starts `BAD ` or ends `: BAD`. `--update` won't write a report that breaks either rule.
9291
docs/README.md+6−1
@@ -7,16 +7,21 @@ The current full-module checker also has a narrow static/data-page slice, docume
77| File | What it holds |
88| --- | --- |
99| [spec/](spec/) | The doc's tabs, as Markdown, with decisions the doc doesn't have yet; until the doc is synced, this copy is the spec |
10−| [status.md](status.md) | The eight milestones, what milestone 1 built, and how to check it |
10+| [status.md](status.md) | The eight milestones, what Jibb does now with the test that proves each part, and the known gaps |
1111| [open-questions.md](open-questions.md) | Questions still open: the plan's, the grammar's, and those milestone 2 raises |
1212| [development.md](development.md) | Setting up a machine, the ground rules, the checks to run before pushing |
1313| [compiler.md](compiler.md) | A map of `jibb-dev/lib/jibb.hoon`: its API, data, errors and printed formats |
1414| [prelude-inventory.md](prelude-inventory.md) | Working source audit for the prelude's exported inventory |
1515| [prompts/milestone-2.md](prompts/milestone-2.md) | A brief for the developer who builds milestone 2, types and prelude |
1616| [prompts/drop-union-rune.md](prompts/drop-union-rune.md) | The completed brief for dropping `$?`, as decided on 2026-10-30, before milestone 2 |
17+| [prompts/syntax-review-follow-up.md](prompts/syntax-review-follow-up.md) | A brief for finishing the syntax changes Montelot decided on 2026-11-03: open gaps, unfinished reviews, work that waits on the checker core, and questions to ask |
1718| [reviews/2026-11-02-repo-review.md](reviews/2026-11-02-repo-review.md) | A review of the whole repository on 2026-11-02: bugs, gaps and simplifications, each checked by a second reviewer |
1819| [reviews/2026-11-02-questions.md](reviews/2026-11-02-questions.md) | The 45 decisions that review raises, with options and recommendations |
1920| [reviews/2026-11-02-syntax-review.md](reviews/2026-11-02-syntax-review.md) | A review of Jibb's syntax on 2026-11-02: 15 verified proposals with before and after examples, what to keep, and questions for @iko |
21+| [reviews/2026-11-03-milestone-2-review.md](reviews/2026-11-03-milestone-2-review.md) | A review of milestone 2 against the plan on 2026-11-03: the done-criteria, the errors the spec describes, findings M1 to M17, with its [probes](reviews/2026-11-03-milestone-2-probes/) |
22+| [prompts/milestone-2-finish.md](prompts/milestone-2-finish.md) | A brief for finishing milestone 2: the general checker core, diagnostics, patterns, kinds, imports, tests and docs that the milestone 2 review found missing |
23+| [prompts/repo-review-finish.md](prompts/repo-review-finish.md) | A brief for finishing the 2026-11-02 repository review: the open findings no other brief covers, the rulings waiting for @iko, and the review's advice for the checker core |
24+| [reviews/2026-11-03-checker-map.md](reviews/2026-11-03-checker-map.md) | A map of the type checker on 2026-11-03 for whoever builds the general core: its families, recovery slices, hazards, and what the core replaces and keeps |
2025
2126## The spec
2227
docs/compiler.md+11−3
@@ -74,18 +74,22 @@ A single-arm cell pattern can bind two or more positions, with its last binder c
7474
7575String interpolation infers its pieces in order and preserves substitutions and pending constraints. A piece with a known atom aura, unrestricted `@`, or a tape `(list @tD)` is accepted; an isolated decimal literal takes its normal `@ud` default. A known cell reports that it needs a printer, and an explicitly generic atom asks for an aura at its use site. Loobeans, term singletons, non-tape collections, open types and a type fixed only later remain unsupported in this fragment.
7676
77+A bare decimal is a `@ud` (S4): its variable binds only `@ud` or `@u`, and it fits `@` and `*`. A `++` generic over the decimal's aura generalizes it to an atom variable, so there it takes any aura. When a fit fails, `+decimal-misfit` refits with each decimal widened to any aura, so that a generic gate's capital learns its aura from the other arguments, then walks the value's syntax beside the expected type through groups, faces, tuples, term-headed pairs, the union case a head tag picks, units and lists. The first decimal at an atom of another aura gets an error naming it and the expected aura's literal, as "`30` is a @ud, not a @dr; write ~s30"; otherwise the site's own error stands. Casts, call arguments, change fields, list items and tails, unit payloads, branch joins and contextual branch arms use it, and a `?-` over a known union or an atom checks its number patterns against the subject's type the same way.
78+
7779The Hoon bridge translates imported `(unit T)` to the canonical public `unit` union when the prepared template validates as the standard mold. Without that template it retains the older opaque collection behavior. Conversion recurses through imported unions and collection arguments, and API path/diff/poke analysis uses the same prepared reader. The fixtures prove identity, `fall`, `need`, casts, union- and list-nested `need`, canonical unit-typed API full/diff marks, and a canonical direct-poke export while leaving no-prelude output unchanged.
7880
7981The Hoon bridge translates imported `*` as the any-noun type, directly or within supported nonrecursive cells. The reader may still decline a disjoint tagged union with a noun payload, and recursive imports containing `*` remain unsupported. It accepts an exact fork of the two loobean singletons as `?`, and each singleton separately as `%.y` or `%.n`, including inside supported faced cells. Contextual loobean literals specialize against a matching singleton by noun, including a proven singleton in a direct union; named loobean singletons do not silently widen to a distinct aura. Open `%f`, other values, and other forks containing loobean singletons remain unsupported; recursive Hoon molds containing flags can also fail closed.
8082
8183A bare tag that provably matches no case of a known union reports the union and tag sites. This covers casts, single-argument calls, contextual unit payloads, list items and supported branch arms, including unnamed imported unions. For syntactic tuples, ordered fit replay can identify a missing tag in a nested position; an earlier mismatch or uncertainty stops the replay instead of guessing. Existing tags whose shape or payload does not fit retain the ordinary mismatch; unresolved tags stay pending.
8284
83−A change can replace uniquely named fields on a fully known, faced record spine, including through a nested wing. Replacements receive the field type as context, substitutions and pending constraints are retained, and the resulting type remains the original record. Missing fields, empty changes and definite replacement mismatches report sites; the expected-type site is the edit, since the original field declaration location is not retained. Unknown or partly unfaced spines, ambiguous fields and repeated edits remain unsupported. A cast to a known record also supplies field context to a tuple or record initializer, including nested list and union fields. The expected-type site is the cast mold; the original field declaration location is not retained. Isolated cart-style `init` and `update` expressions infer in this fragment. The complete cart-store source fails closed because store kind and declaration scope are not yet checked.
85+A change can replace uniquely named fields on a fully known, faced record spine, including through a nested wing. An item named by a wing, as `m(open.cart=x)`, reads its field through such spines, outermost first. Replacements receive the field type as context, substitutions and pending constraints are retained, and the resulting type remains the original record. Missing fields, empty changes and definite replacement mismatches report sites; the expected-type site is the edit, since the original field declaration location is not retained. A missing field in an item's wing is reported at that name, and a wing through a field that is surely no record, such as a list, an atom or a unit, at the field it goes through. Unknown or partly unfaced spines, wings through tuples and type variables, and ambiguous fields remain unsupported. Two items that set the same field, or one a field inside the other's, are a module error at both items, as a repeated record field is. A cast to a known record also supplies field context to a tuple or record initializer, including nested list and union fields. The expected-type site is the cast mold; the original field declaration location is not retained. Isolated cart-style `init` and `update` expressions infer in this fragment. The complete cart-store source fails closed because store kind and declaration scope are not yet checked.
8486
8587Nested labels of the three public re-exports are normalized recursively to `ask`, `qath` and `raw-poke`, so prepared records and instantiated types do not expose their private `.internal` suffixes. Other private names remain private.
8688
8789For supported closed unions, the type printer keeps the union’s origin separate from its displayed name. It prints an in-scope name such as `msg` or `msg.lib`, including in records and gates; an accessible imported nongeneric alias may name a transitive union. A nongeneric body-local union that escapes its scope, or an origin without an accessible name, prints its cases separated by spaces, parenthesized when nested. That case-list form is print-only. A supported generic union prints its name and all arguments, including unused arguments; when its name is unavailable, the partial printer reports that limitation instead of dropping its arguments. Two faces for the same imported origin remain compatible; compatibility between distinct union origins, including in gate types, remains unsupported. Some comparisons of generic union arguments also remain unsupported rather than deciding equality or mismatch. The Hoon bridge also translates some imported unnamed unions into this representation; unsupported cases remain errors.
8890
91+The type printer shows a type variable by the name it was written with. A variable's ID holds that name above a 64-bit count (`+named-var`), so the name travels through substitution, generalization and instantiation, and `+ienv-fresh-id` counts without it. When a definition is generalized, `+cap-names` names each quantified variable after a capital written in the definition that resolves to it, or else after the earliest made of the named variables joined with it; a call note does the same without the capitals. `+canonical-itype` keeps the names and numbers the other variables as the letters (`+show-var`) that no name in the same type spells.
92+
8993Multi-argument calls form one right-nested sample: `f a b c` supplies `[a [b c]]`, with the last argument able to be a cell itself. The fragment fits the complete sample, preserving known faces and shared variables. Known sample positions can provide list or union context to arguments; unknown sample shapes use ordinary inference and some contextual forms remain unsupported. For a definite mismatch, the diagnostic points to a specific argument when it can establish which one failed; otherwise it reports the combined sample.
9094
9195A list literal can be inferred when a cast or known gate sample supplies a list type and the supplied prelude has the validated standard list definition. Empty, nonempty and nested literals work, including contextual union tags in elements; mismatched elements report the item and expected type. Imported Hoon lists share this representation. Under the same known context, `~` and zero-valued term literals fit an empty list, and a two-item unfaced cell `[head tail]` is a cons; cons cells and list literals can be nested. Mismatched heads or tails report both sites. A known list result also supplies context through complete loobean, unit-shaped and list-shaped branches, including recursive and nested branches. Known loobean result context can propagate through supported complete branches and binder-only cell arms, with a final directional fit; a binder-only arm over a union subject remains unsupported. A known gate with an unresolved result variable can also receive an enclosing result type before its argument is inferred, for example allowing `^- (list @t) (id ~)`; unknown callees and unresolved targets retain the conservative path. A known gate sample supplies context to corresponding positions of a single tuple or record argument, including nested cells; a zero literal can therefore fit a list position. A bound zero constant still remains unsupported rather than a definite mismatch, and an unknown callee does not supply context. Uncontextualized list literals also infer with a fresh element variable, including empty and nested lists; the resulting variable can generalize. Unresolved item tags and uncertain widening remain unsupported. Faced or longer cons cells, and a missing or altered prelude list remain unsupported. For a known standard list with a supported element type, it also infers a complete two-arm branch using `~` and `[item rest]`, in either order. The binders have the element and list types and cannot shadow or duplicate names. Unknown subjects, unsupported element types, other patterns and incomplete arms remain unsupported.
@@ -100,6 +104,8 @@ The checked inference fragment represents the empty mold `!!` explicitly. A cell
100104
101105A known closed union with two or more arms can be matched when each arm provably covers or excludes each remaining case. The checker first tries whole cases; when a pattern splits a case, it can expand known `?` positions into their two noun values, up to 64 alternatives across the union. Binders retain the original case type, and one arm may bind several refinements of that case. It reports missing alternatives and arms already covered, checks tags by noun value, and supports imported and generic union cases. Other partial patterns, expansions above the limit, binders spanning distinct cases, differing arm result types and some complex two-arm subjects remain unsupported. When a cast or known call sample supplies a result type, a known union subject accessed by a wing, a grouped wing or a supported shallow call can propagate that context through whole-case arms and supported finite loobean refinements, including nested cell and list positions. Other partial-pattern contexts and subject forms remain unsupported. The Grammar’s `step` block infers in this fragment, but its module is not yet checked.
102106
107+Before any branch path runs, `+branch-tag-name` rejects a pattern name that spells one of the subject's tags at its position, as `stop` for `%stop` (Grammar, Patterns). It infers the subject on its own and walks each arm's pattern through faces, cells and union cases, skipping the cases a cell pattern can't match. It stops at atoms, `*`, variables, collections, recursive molds and a generic union's argument positions, so every path that checks a `?-` reports the same error. A subject whose inference fails, or whose type isn't known yet, is left to the path.
108+
103109A known closed union can also provide context to each arm of a complete loobean or unit-shaped branch in a cast or a call with a known union sample. Nested branches and transparent groups work; a mismatch reports the expected union and the offending arm. General patterns and context through bodies with local definitions remain unsupported, and unrelated unresolved tags stay pending.
104110
105111The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, nested map, set, queue, list, unit, jar and jug arguments, direct ordered maps, and direct `$^` unions whose source branches can be proved disjoint. It also recognizes a direct ordered-map call with two simple named mold operands, as in Tlon `notes.log`, after validating provenance and operand source; revisiting the same map hold fails closed. It also reads ordered map fields in records when the map arguments are syntactically fixed atom molds and other fields are fixed atom molds or standard collections of static atom molds. Collection names must not be shadowed. The reader can also import a mark door sample, removing its outer sample face and validating its build subject. For a mark whose sample is exactly a named arm of its single Ford-imported `/sur` core, it can recover a source-proved nonrecursive union, including source-location wrappers around fields; recursive or unverified fallback results remain unsupported. The reader checks explicit Hoon `$%`, `$?` and `$^` unions against the Grammar’s disjointness rule, as @iko confirmed on 2026-10-30. For an explicit `$%` with distinct literal head tags, it can also prove restricted local named payload dependencies, including bare `~` fields, re-evaluate and validate each source branch, and recover the union before Hoon collapses it. The real Tlon `notes.u-note` exercises its `[%deleted ~]` case. A bounded fallback also recovers one level of local named tagged unions inside such a union, including Tlon `notes.u-notebook` and `notes.u-notes`. Source-proved tagged unions can also be wrapped in Hoon `$~` defaults, including a downstream union using Tlon `epic.saga`; the selected source and projected branches still undergo the same provenance and disjointness checks. The tagged-source helper peels up to four consecutive default wrappers, while default wrappers encountered inside dependency proofs consume the existing semantic-node budget. A source-proved nested self-recursive union retains its named owner, including Tlon `notes.import-node`; deeper, mutually recursive or unproven cases stay unsupported. The nested source proof has a 256-visit semantic-node budget, and source-location wrapper peeling is limited to four per node; Hoon evaluation and source scans are not metered. It rejects recursive or computed dependencies, inherited same-name collisions, unsupported nested unions and proofs exceeding a shared 4,096-node budget. It re-evaluates statically recognizable source branches before Hoon can collapse them, checks materialized fork cases, and rejects shapes it cannot prove disjoint. Static records may also have verified standard-collection and `path` siblings. One direct explicit union argument in a standard list, set, map or unit is accepted when its call wrapper and collection provenance are verified and its static cases are pairwise disjoint. A synthetic regression checks that forged wrapper subjects, samples and tails are rejected. Other collection-union forms, nested ordered maps, general source-level disjointness and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms, valid term singletons, Hoon's `%n` zero singleton as Jibb `~`, nested faced or unfaced cells, unions of supported, pairwise-disjoint cases, and opaque standard collections with supported arguments from caller-supplied reader results for declared `/-` imports; `+golden-types-with-marks` accepts the same shapes for declared marks. The caller must pass unchanged results from the source-aware reader: the bridge validates the supplied graph but cannot detect source cases Hoon collapsed before that graph was built. The opaque collection types retain their names and arguments for identity, unification and printing. The validated standard prelude `list` mold shares the imported list representation; other Jibb-written collection molds and most prelude collection operations remain unsupported. Other forms remain unsupported. Its disjointness proof is conservative and can reject a valid union it cannot prove disjoint. Collection recognition requires the originating `/sur` core. The reader validates direct zuse subjects and Ford subjects consisting of faced imported cores and a validated tail, checking imported cores transitively; it rejects shadowed names, inconsistent core subjects and other subject shapes. For a recursive reference, the reader matches the exact Hoon hold against named arms in validated cores, including transitive Ford imports; it rejects missing, unlabelled or ambiguous origins. Its fixtures include three real Tlon files; the `tests/lib/jibb-import.hoon` suite, which holds the probes, compares the internal projection with its golden output and checks the structured values behind it, under eval (`tools/test-arms jibb-import`) and on the ship. `tests/lib/jibb-bridge.hoon` and `tests/lib/jibb-mark-bridge.hoon` compare bridge reports under eval and on the ship. `tests/lib/jibb-tlon-bridge.hoon` exercises four real Tlon presence unions and a field read through the source-aware reader and partial checker, under eval and on the ship. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
@@ -126,7 +132,7 @@ For a unique supported declaration, `+api-request-parts` retains that evidence w
126132
127133`+api-support-analysis-source` additionally infers supported ordinary API molds and values, resolves every declared mark, and retains their source, dependency and path evidence. Unsupported helpers or marks fail closed. An unused `/-` core is not independently validated, ordinary definitions that need derived gates remain unsupported, and this result is not a checked API interface or an exported request.
128134
129−The ordinary import resolver can infer derived request-gate types for multiple supported API paths. A case may take one typed path parameter before its reply gate, or one diff fold after the reply; a case with both, multiple parameters or diffs, or a separate scry path remains unsupported. Each reply maps the full mark type to a fresh `M` and the request result is `(ask M)`. Checked ordinary API values and molds, declared mark molds and a supported generic poke command helper are exported too. Every selected `/sur` core must have a directly used, successfully read mold; unselected core bindings are not independently validated, and Jibb module imports remain unsupported in this API fragment. An API module outside the fragment fails with the reason its check gave: without `+$ paths`, the poke-only check's, such as `API poke mark %todo-action has no reader result`; otherwise its request constructor's, such as `request paths need unsupported inference`. A failing Jibb import reports its own error, as it does for other modules. A derived `poke` or request name that clashes with a definition, an import face, a prelude value or another derived name is a definite error showing where the name is derived and what it clashes with; `+api-path-analysis-source` and the path evidence entries report it the same way. Only names that surely exist are checked: `poke` when the module declares `+$ poke`, and the case names of a `+$ paths` that reads as path cases. Two cases with the same name do not read as path cases, so that clash stays unsupported, as does a case named `proj`, a reserved name. A name conflict among an API's imports and ordinary definitions reports `module has conflicting names`, as in other modules; a `/%` mark names a mold, so it conflicts only with another mark or mold, and a mark beside a value of the same name, such as a request, is not a conflict. The unchanged todo API fits this fragment.
135+The ordinary import resolver can infer derived request-gate types for multiple supported API paths. A case may take one typed path parameter before its reply gate, or one diff fold after the reply; a case with both, multiple parameters or diffs, or a separate scry path remains unsupported. Each reply maps the full mark type to a fresh `M` and the request result is `(ask M)`. Checked ordinary API values and molds, declared mark molds and a supported generic poke command helper are exported too. Every selected `/sur` core must have a directly used, successfully read mold; unselected core bindings are not independently validated, and Jibb module imports remain unsupported in this API fragment. An API module outside the fragment fails with the reason its check gave: without `+$ paths`, the poke-only check's, such as `API poke mark %todo-action has no reader result`; otherwise its request constructor's, such as `request paths need unsupported inference`. A failing Jibb import reports its own error, as it does for other modules. A derived `poke` or request name that clashes with a definition, an import face, a prelude value or another derived name is a definite error showing where the name is derived and what it clashes with; `+api-path-analysis-source` and the path evidence entries report it the same way. Only names that surely exist are checked: `poke` when the module declares `+$ poke`, and the case names of a `+$ paths` that reads as path cases. Two cases with the same name do not read as path cases, so that clash stays unsupported, as does a case named `proj` or `unface`, a reserved name. A name conflict among an API's imports and ordinary definitions reports `module has conflicting names`, as in other modules; a `/%` mark names a mold, so it conflicts only with another mark or mold, and a mark beside a value of the same name, such as a request, is not a conflict. The unchanged todo API fits this fragment.
130136
131137A call whose direct result is a known named generic union can receive a matching same-origin, same-arity result context before its arguments are inferred. This retains the ordered generic arguments and existing capital checks; pending tags, recursive or variable-bound origins and unrestricted atom cases remain conservative. Constructor fitting reports unsupported when an unresolved or opaque case could contain the requested tagged head. It keeps definite missing-case errors for proven nonmatching cases, including an explicitly atom-only faced head. The real todo callback `|=%got` can infer when an `(ask msg)` result context fixes its message union; the uncontextualized call remains unsupported.
132138
@@ -181,7 +187,9 @@ The internal prelude defines transparent `(ask M)` cases for pure, agent and sto
181187
182188Public identity aliases of private generic unions retain their public name when the origin, arity and argument order match exactly, including through imported values. Fixed, reordered, repeated and phantom generic aliases remain unsupported where a safe public name cannot be recovered; a fixed nongeneric alias is not printed as though it accepted type arguments.
183189
184−The partial checker reserves `proj` in module, local, sample, pattern and import bindings, including bindings inside unsupported source; a field, tag or path segment may still have that spelling. With a known expected record type, it checks selected explicit `(proj record)` calls over closed, uniquely faced records, preserving the source expression, its type, the result type and field axes in the checked interface. Imported and private-prelude dependencies retain the source needed to lower those plans. The checker does not yet lower or execute them. It supports selecting one or more fields in their original order; a single selected field keeps its face and uses one source axis. Reordered fields, unknown or open record spines, some nested contexts and recursive groups with projections remain unsupported. A directional fit of a wider faced record fails closed instead of inserting a projection, including within supported list, unit and record positions. To limit repeated work, record-spine proofs are reused along the same closed spine and stop at 1,024 fields; field boundaries and the special handling of positional calls reset the appropriate proof. Prepared interfaces and their source remain trusted host inputs.
190+The partial checker reserves `proj` and `unface`, one set checked by `+reserved-name`, in module, local, sample, pattern and import bindings, including bindings inside unsupported source; a field, tag or path segment may still have that spelling. With a known expected record type, it checks selected explicit `(proj record)` calls over closed, uniquely faced records, preserving the source expression, its type, the result type and field axes in the checked interface. Imported and private-prelude dependencies retain the source needed to lower those plans. The checker does not yet lower or execute them. It supports selecting one or more fields in their original order; a single selected field keeps its face and uses one source axis. Reordered fields, unknown or open record spines, some nested contexts and recursive groups with projections remain unsupported. A directional fit of a wider faced record fails closed instead of inserting a projection, including within supported list, unit and record positions. To limit repeated work, record-spine proofs are reused along the same closed spine and stop at 1,024 fields; field boundaries and the special handling of positional calls reset the appropriate proof. Prepared interfaces and their source remain trusted host inputs.
191+
192+An explicit `(unface e)` has e's type with every face removed (`+itype-unface`): through cells, a gate's sample and product, collection arguments and the prelude unit's payload, whose own `u=` stays. Other unions and recursive molds go by name or exact cases, so they are kept whole, and an unbound variable stays, keeping any faces it is bound to later. When e's type is still a bare variable the checker reports `unface on a type not yet known is not supported by partial inference`, as it does field access; the deferred transaction declines `unface`. `unface` written as a value, or with other than one argument, is a definite error. A `++` whose body is `(unface |= …)` counts as a gate for self-recursion, recursive groups and the report, with the unfaced type, while direct-call layout evidence, which reads sample faces, leaves it out. Nothing is lowered yet; the core language's row lowers it to its argument.
185193
186194## The tree
187195
docs/development.md+5−3
@@ -72,7 +72,7 @@ git clone https://github.com/urbit/tools /root/src/tools
7272| --- | --- |
7373| `tools/check` | Runs every check in this table, or a group (`--group eval` or `ship`), or some by name: see [Before pushing](#before-pushing) |
7474| `tools/golden` | Runs the golden cases under `urbit eval`: every case, or those matching `--case`; `--update` rewrites the expected outputs; `--show` prints them |
75−| `tools/test-arms` | Runs the `test-` arms of the `tests/lib` suites under `urbit eval`, each with the subject Ford would give it on the `jibb-dev` desk: every suite, or those named or matched by a glob, as `tools/test-arms jibb-store 'jibb-program-*'`; `--shard I/N` runs the I-th of N balanced shards; `--list` prints the suites and their arms; `--report` and `--update` print or rewrite a golden-report suite's report; `--copies` checks only the `my-app` copies. See [The test suites](#the-test-suites) |
75+| `tools/test-arms` | Runs the `test-` arms of the `tests/lib` suites under `urbit eval`, each with the subject Ford would give it on the `jibb-dev` desk: every suite, or those named or matched by a glob, as `tools/test-arms jibb-store 'jibb-program-*'`; `--shard I/N` runs the I-th of N balanced shards; `--list` prints the suites and their arms; `--report` and `--update` print or rewrite a golden-report suite's report. See [The test suites](#the-test-suites) |
7676| `tools/clay-fixtures` | Syncs `my-app` and `jibb-fixtures`, builds their example `/sur` files and marks through Clay, checks selected mold and mark projections and the partial checker, and records Ford and mark subject shapes on the fake ship |
7777| `tools/hoon` | Evaluates Hoon with the library in scope, as `tools/hoon '(golden /a/b/jibb (crip "++ main view"))'`; `--cord name=file` binds a file's text, `-f` reads the expression from a file; `--no-debug` leaves out `!:`, which gives errors their positions but makes the checker 2.2 to 2.6 times slower than on a ship, for timings |
7878| `tools/doc-blocks` | Checks the doc's `jibb` blocks against the `doc-*` golden cases: `tools/doc-blocks docs/spec` |
@@ -88,6 +88,8 @@ Each file in `tests/lib` is a suite: a core of `test-` arms, with the libraries
8888
8989A golden-report suite has a `report` arm and a golden file bound to the face `expected`; its test arm compares the report with that file, and `tools/test-arms --list` marks it `, report`. `tools/test-arms --report <suite>` prints the report, and `tools/test-arms --update <suite>` writes it to the file; with no suite named, `--update` writes every golden-report suite's. When such a suite's arm fails, `tools/test-arms` prints a unified diff between the file and the report. `jibb-buttons` and `jibb-deferred-prepared` have golden files too, but compare them inside helpers over several cases and have no `report` arm. Every golden file, a `/*` `%txt` file bound to a face containing `expected`, must end in exactly one newline (a suite compares `wain`s, which can't show a missing one) and hold no line that starts `BAD ` or ends `: BAD`; `tools/test-arms` checks that before any eval, and `--update` won't write a report that breaks it.
9090
91+`tools/doc-fragments` guards the examples checked in a larger context: the Core language's `update` must match the todo island's definition, and the valid buttons fixture must match the Grammar's buttons block with `add-button` removed. It runs as part of `tools/check` alongside `tools/doc-blocks`.
92+
9193The `jibb-dev` desk holds `my-app`'s `ui/`, `sur/` and `mar/` under `/my-app` (review question 31), so the suites that check `my-app` files bind them there, as `/* sur %txt /my-app/sur/todo/hoon`, and keep no copies. A mark's `/-` line is Ford's, which `ride` can't parse, so the suites that ride a mark drop it with their `+mark-text` arm. Where the table below calls a `my-app` file byte-identical or unchanged, the suite reads that file itself. Files that only the importer's tests need are kept off `my-app` (review question 34): the Clay fixtures' `/sur` with a Ford import, their mark and the real Tlon notes `/sur` are in `tests/clay-fixtures/desk/`, which the `jibb-fixtures` desk adds to `my-app` and the `jibb-dev` desk leaves out, and the golden cases and `tests/type-poke/mark.txt` that use the mark link to `tests/clay-fixtures/desk/mar/label.hoon`.
9294
9395| Suite | What it checks | Golden files |
@@ -157,13 +159,13 @@ The `jibb-dev` desk holds `my-app`'s `ui/`, `sur/` and `mar/` under `/my-app` (r
157159
158160```
159161tools/check # every check; it exits 0 only when all pass
160−tools/check --group eval # only the checks that need no ship, as CI runs them
162+tools/check --group eval # only the checks that need no ship
161163nix flake check # the same checks in the Nix sandbox, on a fresh fake ~zod
162164```
163165
164166`tools/check` runs every check the repo has. Their one list is `CHECKS` in the script, so a new check goes there, as well as in the table above; `tools/check --list` prints it with each check's command. A new suite in `tests/lib` needs no new check: `arms-1` to `arms-4` run every suite's arms, in shards of about equal time, and a slow suite's cost belongs in `COSTS` in `tools/test-arms`, which balances them. The eval group, the 7 checks that need only `urbit` and Python, runs several at a time (`-j`, by default one per CPU), the slowest first. The ship group, `ship-selftest`, `ship-test`, `check-commit` and `clay-fixtures`, then runs one check at a time on the ship `tools/ship` talks to; `tools/check` starts it if it isn't running and stops it again afterwards. Name checks, or globs, to run only those: `tools/check golden 'arms-*'`. To run one suite under eval, use `tools/test-arms <suite>`, as `tools/test-arms jibb-todo-full`. A failing check's output follows its FAIL line; `-v` prints every check's output, and `--logs DIR` keeps it all.
165167
166−CI, [.github/workflows/check.yml](../.github/workflows/check.yml), builds the desks and runs the eval group through the flake on every push to `master` and every pull request. It doesn't run the ship group, so run that before pushing.
168+There is no CI, so nothing runs these checks for you: run `tools/check` or `nix flake check` before every push. `nix flake check` needs nothing but Nix, since it builds the desks and runs both groups in the Nix sandbox, the ship group (Linux only) on a fake ~zod it boots itself; see the [README](../README.md#building-and-checking-with-nix).
167169
168170`ship-selftest` matters most when `tools/ship` changed, and `check-commit` when the mark or the desks changed, but `tools/check` runs both every time. The self-test leaves fixture files on the `jibb-dev` desk, and `ship-test`, which runs after it, puts the real ones back.
169171
docs/open-questions.md+2−2
@@ -50,14 +50,14 @@ In milestone 1 the parser met about thirty places where the doc could be read mo
5050| 1 | `knot` may be empty, so the EBNF admits `//`, `/a//b` and a trailing `/`. Which are paths? | A segment has at least one character, as in Hoon. `/` alone is the empty path, in expressions and molds; `%/` alone is the root application path. `//` fails at the second `/`, and a trailing `/` just past it. `inline-mold-paths` has `/` alone as a mold |
5151| 2 | Is `/` alone a valid path for a `/=` import? | No: `/=` names a module's file, so its path has a segment. `/= card /` fails just past the `/` (`inline-import-root-bad`) |
5252| 3 | The EBNF's `line = [ name "=" ] expr` lets every open bracket's lines take `name=`. What would it mean on a line of an open `(` or `~[`? | An error: `name=` lines belong to tuples and changes. "expected a space between items, found `=`; `name=value` goes in a cell, as [a=1], or a change, as m(a=1)" |
53−| 4 | Does "items named" make every item of a change need `name=`? | Yes: `m(x)` fails just past `x`, "a change's items are named, as in m(done=%.y)" (`lex-tight-change-bad-3` to `-7`; `-8` and `-9` test what follows a name there). The parser still accepts `m()`, though question 6 settled it as an error |
53+| 4 | Does "items named" make every item of a change need `name=`? | Settled on 2026-11-03 (syntax review S6): yes, `name=value` or `wing=value`, as `m(open.cart=x)`. `m(x)` still fails just past `x`, "a change's items are named, as in m(done=%.y)" (`lex-tight-change-bad-3` to `-7`, where `-5` is a wing with no `=`; `-8` and `-9` test what follows a name there) |
5454| 5 | `term` includes `%0`, `%&` and `%\|`, which no mark is called. What does `/%` take? | `%` and a name only: `/% %0` is "expected a mark's term, as `%todo-action`, found `%0`" |
5555| 6 | What does an indented first line mean? | An error: "the first line is indented: top-level lines start at column 1" (`lex-indent-bad-3`) |
5656| 7 | With levels open at columns 1 and 5, what does a line at column 3 mean? | An error naming the open columns: "this line's indentation matches no enclosing line: indent it to column 1 or 5". `lex-indent-bad-2`, with levels at 1, 5 and 7, gives "column 1, 5 or 7" |
5757| 8 | Tabs, carriage returns, other control characters, and non-ASCII text outside strings and comments? | Errors everywhere, strings and comments included, except that UTF-8 is allowed in strings and comments; a tab in a string is written `\09`. `lex-indent-bad-1` and `lex-spacing-bad-2` test tabs |
5858| 9 | Must a file be valid UTF-8? | Not checked yet: any byte from 128 up passes in strings and comments, and columns assume UTF-8. The proposed reading makes a byte that can't continue a UTF-8 sequence an error. An escape such as `\ff` still writes any byte, as in Hoon |
5959| 10 | Inside `{…}`, may `::` start a comment, which would swallow the `}` and the `"`? Is a lone `}` in a string text? May a comment follow code with no space, as in `5::note`? | A `:` inside `{…}` is "a comment can't start inside `{…}`". A lone `}` is text, as in Hoon. `5::note` is `5` and a comment |
60−| 11 | Is a type variable exactly one capital letter, as `typevar = upper` says? | Yes: `Msg` is "a type variable is one capital letter" |
60+| 11 | Is a type variable exactly one capital letter, as `typevar = upper` says? | Settled on 2026-11-03 (syntax review S7): no, a capital then lowercase letters and digits, as `Msg`; `AB` is an error |
6161| 12 | Hoon has more runes of the left-out kinds than the list names: `?~ ?= ?. ?@ ?^`, `:- :+ :^ :_`, `%- %+ %^ %~`, `=+ =? =.`, `;:` and `~&(…)`. Are they all left out? | Yes, with the list's reasons, as "`:-` is left out: indentation covers it; write a cell as [a b]". Naming them in the doc, or saying "Hoon's other runes", would make the messages the doc's words (`inline-leftout-*`) |
6262| 13 | `@s…` and `@r…` auras are "errors wherever used". Is that the parser's error in Jibb source, or the checker's? | An error before the checker. Where a mold goes, the layout pass's, at the `s` or `r`: "signed and floating-point auras are left out of Jibb". Where an expression goes, the parser's, at the `@`: "expected an expression, found `@`; signed and floating-point auras are left out of Jibb". Imported ones are milestone 2's importer's. The case `inline-leftout-signed-float-auras` still says "expect: unclear" |
6363
docs/prompts/milestone-2-finish.mdnew file+97
@@ -0,0 +1,97 @@
1+# Finishing milestone 2
2+
3+A brief for the developer who finishes milestone 2 of Jibb, types and prelude. Paste it as the first message of a session, or hand it to a person; it assumes the repo `iko-soy/jibb`. Written 2026-11-03, at commit `f84a29e`, from the [milestone 2 review](../reviews/2026-11-03-milestone-2-review.md) of the same day. That review was still running in seven of its nine areas when this was written; where a section below depends on them it says so, and both files will be updated when they finish.
4+
5+---
6+
7+You are finishing milestone 2 of Jibb, a UI language for Urbit: a Hoon dialect with an indentation layout, whose compiler is a Hoon library, `jibb-dev/lib/jibb.hoon`. Milestone 1 built the layout pass and the parser. Milestone 2 has built a large partial type checker, a Hoon type importer and most of the prelude; every check passes, under `urbit eval` and on a fake ship, and the doc's 14 `jibb` blocks check as written. What is missing is a checker that is general rather than fitted to those examples, and that tells the user what is wrong.
8+
9+## Read first
10+
11+1. [docs/reviews/2026-11-03-milestone-2-review.md](../reviews/2026-11-03-milestone-2-review.md): the verdict, findings M1 to M17, and the table of the 33 errors the spec describes. This brief is its to-do list.
12+2. [docs/prompts/milestone-2.md](milestone-2.md): the original brief. Its "What the doc asks of the checker", "Suggested design" and "Tests" sections still hold, and this brief doesn't repeat them.
13+3. [docs/spec/implementation-plan.md](../spec/implementation-plan.md), milestone 2, and the spec tabs it points at, closely Grammar's Tag resolution, Literals by context, Patterns, Modules and Imports.
14+4. [docs/reviews/2026-11-02-questions.md](../reviews/2026-11-02-questions.md): the owner's answers, marked *(chosen)*. Q5 and Q6 set the direction below. Q16 to Q28 are proposals waiting for @iko, not spec.
15+5. [docs/development.md](../development.md): setting up (`nix develop`), the tools, the test suites, and the checks before pushing (`tools/check` or `nix flake check`).
16+6. `git log origin/master`: @iko works in `jibb.hoon` in parallel, and another thread is implementing syntax-review proposals S1, S2, S4 to S7, S11 to S13 and S15 ([syntax review](../reviews/2026-11-02-syntax-review.md)). Rebase often and keep your changes out of theirs where you can. The thread that fixes the 2026-11-02 review's findings planned this same core on 2026-11-03, in stages that keep every check green; ask in the project chat who is building it before you start step 2.
17+
18+## Ground rules
19+
20+The original brief's rules hold: the spec wins, language questions go to @iko and are recorded in Decisions first, no built-ins, everything is a golden test that passes under eval and on the fake ship, push straight to `master` in commits that each leave every check passing, and keep `docs/` current. Two more:
21+
22+- **Fail closed, but say why.** A program the checker can't yet handle must be rejected, never accepted, and its message must name the construct and its site. "module definitions need unsupported inference: <path>: ++ x" is not an acceptable message for an error the spec describes.
23+- **Delete what the core replaces.** When the general core covers a recovery path or a "source-proven" slice, delete the slice and keep its tests. The milestone is done when the slices are gone, not when they are joined by a core.
24+
25+## What is left
26+
27+In order. Steps 1 and 2 can start at once; the rest build on step 2.
28+
29+### 1. Keep the diagnostics the checker already finds (M1, M12, M17)
30+
31+The full checker, `infer-jibb-file-detailed`, drops every per-definition reason in `add-supported-result` (`jibb.hoon` 10670-10689), so almost every error reaches the user as the generic message. The partial report already computes most of them. Thread a diagnostic, an `idiag` with its sites, through `add-supported-defs-core` for each unresolved definition, mold and kind check, and render the first in dependency order where the generic text is built today (14820-14857). Keep the generic text only for real checker limits, and make those name the construct. Make `module-scope-valid` return the shadowed name and both sites, with its own wording for `proj`. This plumbing carries over to the core of step 2.
32+
33+### 2. The general checker core (Q5)
34+
35+The owner chose this on 2026-11-02: union-find bindings with levels, a queue of deferred constraints, and a usefulness check for matches, built before more recovery paths. It is a long piece of work, so first write its design as a new section of the library's design notes, and share it in the project chat for @iko before replacing code. Start from [the checker map](../reviews/2026-11-03-checker-map.md), which says what each part of today's checker does, which tests pin it, what the core replaces and keeps, and the hazards; [repo-review-finish.md](repo-review-finish.md) step 6 has the review's advice for staging it.
36+
37+- **Unification**: union-find over type variables, with levels for generalization instead of environment scans; an occurs check; aura variables and the "is an atom" and "contains no gates" constraints carried on the variable, as `0858191` already does for gate-freedom.
38+- **Deferred constraints**: tags, `~`, numbers and cells, wing access, changes and `?-` on a type not yet known each wait in one queue, retried as variables are bound, as the Grammar's Tag resolution says. A tag-constrained variable does not generalize and stays open until something in the module fixes it. At the end of the module, each still-open constraint is an error at its source: "nothing fixes the union of %add; add a `^-`".
39+- **Order**: infer `++`s by the strongly connected components `839f6b0` already computes, a group of mutually recursive gates together; reject a non-gate value that depends on itself, naming the cycle.
40+- **Kinds by type**: check `main` as an ordinary expression. `(program init update view subs)`, `(page load view)` and `(store init update)` are calls whose unification fixes their components' types, messages included, so a tag in `view` is resolved by `main`. Then read the kind from `main`'s type, as the Grammar says, and run each kind's own checks after inference: gate-free island data and models, naming the field; for islands, a walk of the `(list (sub M))` that asks for a watchability proof only for `%watch`; for pages, a load that is any gate to `(ask D)`, `pure` and typed paths included.
41+- **Rulings it must build in**, chosen by Montelot on 2026-11-03 from the syntax review: a capital that meets a faced position binds only the type under the face, never the face, so `[A A]` fits `[x=@ y=@]`, `(hunt lt-a `1 `2)` checks, and `(roll ~[1 2] 0 add-f)` checks with `++ add-f |= [a=@ud b=@ud] (add a b)`; a join keeps a face once a position takes one, so reordering a list's items never changes whether it checks; and, as the syntax thread lands them, the explicit `unface` (S1), bare decimals fitting only `@ud`, `@u`, `@` and `*` (S4), and a bare-name pattern that spells a union tag being an error (S5). Take their final wording from `decisions.md`, and add each ruling's examples as golden cases in the stage that builds it.
42+- **Then delete** the program, page and store recovery chain, the deferred transactions, the prepared-tuple route and the other example-shaped slices as the core covers their tests (the earlier review counts about 1,180 lines of program recovery alone).
43+
44+When this is done, M2 to M5 are gone: every valid variant in the review's [probe corpus](../reviews/2026-11-03-milestone-2-probes/) checks, and each error in an island is reported where it is, as `button "Add" %submitt` giving "msg has no case `%submitt`" at the tag, with the union's site.
45+
46+### 3. Patterns by a usefulness check (M10)
47+
48+Replace the per-case coverage loops with Maranget's usefulness check over nouns: constants and cells, a loobean as its two constants, lists and units as their unions, nested patterns, literal patterns, `*` and bare names. It gives the missing-case error with a witness, at the `?-` and its subject, and the dead-arm error naming the arm that covers it, for the Grammar's `[%move * *]` example too. Keep the matrix reusable: milestone 3 lowers `?-` with it.
49+
50+### 4. One types pipeline (Q6, M14, M15)
51+
52+Render `types.txt` from the full checker: each definition's type, the module's kind, or the error with its excerpts. Retire the partial report, or make it a view of the full result. Give every `doc-*` case a `types.txt`, with the buttons error for `doc-grammar-02-buttons`.
53+
54+### 5. Every error the spec describes (done-criterion 2)
55+
56+Work down the review's [error table](../reviews/2026-11-03-milestone-2-review.md#appendix-the-errors-the-spec-describes) until every row says Met: a golden case with the spec's message, from the full checker, naming both conflicting sites with excerpts. The rows with no message anywhere today: a capital made `@ud` or a list, `~[text "hi"]` with its suggestion, `(facts …)` outside an API's `paths`, a gate in island data or a model with the field named, `[]`, a generic aura in `{…}` or a path's `(…)`, an imported vase or repeated record face, and a repeated attribute in a literal list, which today is accepted (M9).
57+
58+### 6. Kinds, APIs and the prelude in general (M4, M7, M9)
59+
60+- Pages: the overview's route-parameter page, `(post.api slug same)`, and its catch-all page, `(pure p)`, check.
61+- Islands: `|=(m ~)` for no subscriptions, several watches, `%every`, and a watch with a fold, `(changes.todo |=%got apply)`, check.
62+- Stores: a `poke` with several cases checks.
63+- APIs: an API other than the todo one checks as a module, with typed segments, several parameters, `scry=` paths and folds; `(facts …)` outside `paths` is an error.
64+- `element` can't be built by hand: `^- (element !!) [%island 5]` is rejected, so island data is always checked against `init`.
65+- The prelude: every name in the overview's Prelude and Layout tables is usable with its signature, or listed as deliberately left out. `max` is missing today, so the Grammar's `clamp` example fails. The inventory and its gaps are still being reviewed.
66+- The inline Grammar examples in M7 check: `|=(p title.p)`, `"{(add 1 2)}"`, path and unit literals, and every row of the Patterns table.
67+
68+### 7. The Hoon import table (done-criterion 3)
69+
70+A test `/sur` file with `$%`, `$@`, a map and a recursive mold, imported, printed in Jibb's notation and used from a Jibb module through the full checker, under eval and on the ship. Each row of the overview's import table works or gives the table's error where used. Known gaps from the earlier review: only `%tas` head tags (`%&`, `%|`, `%0` and `(each a b)` fail, A50) and no bare `@` or `@uw` (A14). The review's import area is still running and will add to this list.
71+
72+### 8. Tests (M6, M8, M16)
73+
74+- A ship check of the `my-app` desk as the original brief asks: build each `/sur` and mark through Clay, run the full checker over every `/ui/**.jibb` in dependency order, expect exactly one failure, `buttons.jibb` at 3:16, and record the time in `status.md`.
75+- Turn the spec-valid negatives (two `each` sites, a mapper alias, a page alias, an indirect or `pure` load, a store alias, a hand-built main) into positive cases. Fix `tests/type-page-main/hand-built-load.txt`, which doesn't parse. Make every negative assert its message and place, not only "rejected".
76+- Turn the review's [probe corpus](../reviews/2026-11-03-milestone-2-probes/) into a regression suite: its about 90 valid one-edit variants of the doc modules check, and its wrong variants and error probes fail with their own error at their own site.
77+- Guard the copies: the Core language block as a slice of `todo-list.jibb`, and `tests/type-buttons/valid.txt` as the buttons block without `add-button`.
78+
79+### 9. Speed
80+
81+The original brief asks that "a 2,000-line module should check in seconds, not minutes". Measure the full check of generated modules, written bottom-up and top-down, and of the `my-app` desk, with `tools/hoon --no-debug`, and record the numbers in `status.md`. The review's speed area is still running and will add its measurements here.
82+
83+### 10. Docs
84+
85+`status.md` becomes the capability table that Q41 asked for, then shows milestone 2 done with counts and timings. `compiler.md` and the library's header stop saying milestone 1, and describe the core. `open-questions.md` lists what is still open, and `decisions.md` records any new decision.
86+
87+## Out of scope
88+
89+As in the original brief: lowering and the backends (milestone 3), routes, static files, the theme's contrast check and the host (milestone 4), `load`'s per-request behaviour (milestone 5), the JavaScript runtime (milestone 6) and the formatter (milestone 7). Also the syntax-review changes another thread is making.
90+
91+## When you're done
92+
93+- The plan's three "Done when" items hold, but for the route check: the doc's examples and the review's valid variants check; every row of the error table is Met; the `/sur` import test passes.
94+- Every check passes, under eval and on the ship (`nix flake check`), and the `my-app` desk checks on the ship with its types read through Clay.
95+- The recovery paths and slices the core replaced are deleted.
96+- `docs/status.md` shows milestone 2 done, with counts and timings, and the other docs describe the checker as it is.
97+- Everything is pushed to `master`, and a few lines go to @iko in the project chat: what changed, the counts and timings, the decisions needed, and what is still open.
docs/prompts/repo-review-finish.mdnew file+149
@@ -0,0 +1,149 @@
1+# Finishing the 2026-11-02 repository review
2+
3+A brief for the developer who finishes what the [2026-11-02 repository review](../reviews/2026-11-02-repo-review.md) started. Paste it as the first message of a session, or hand it to a person; it assumes the repo `iko-soy/jibb`. Written 2026-11-03, at commit `e208bcb`, by the thread that fixed the review's findings, from a check of every question and finding against `master` that day.
4+
5+---
6+
7+You are finishing the follow-up to a review of the whole Jibb repository. Jibb is a UI language for Urbit, a Hoon dialect with an indentation layout; its compiler is a Hoon library, `jibb-dev/lib/jibb.hoon`, with a Hoon type importer in `jibb-dev/lib/jibb-import.hoon`. The review, at commit `4bf477e`, found 137 problems (A1 to A137) and raised 45 questions, which Montelot, the project's owner, answered: each answer is marked *(chosen)* in [the questions](../reviews/2026-11-02-questions.md). Most answers have landed. What is left is small fixes, simplifications and docs that no other brief covers, twelve language rulings and one more question (A62) that wait for @iko, and the review's advice for the checker core, which milestone-2-finish.md builds.
8+
9+Three briefs share the remaining work. Don't do one brief's work under another:
10+
11+- **[milestone-2-finish.md](milestone-2-finish.md)** owns the general checker core (review question 5), the diagnostics the full checker still drops (its step 1), the usefulness check for `?-`, one types pipeline (question 6), kinds, APIs, the import table, tests and speed. Its import table step lists two known gaps from this review, A14 and A50; they are fixed here, in step 1 and under question 26.
12+- **[syntax-review-follow-up.md](syntax-review-follow-up.md)** owns the syntax changes S1 to S15, including `unface` and the gaps in S2, S4 to S7.
13+- **This brief** owns the rest of the repository review: the open findings below, the rulings for @iko, and the review's input to the core.
14+
15+## What landed
16+
17+| Questions | What | Commits |
18+| --- | --- | --- |
19+| 1 to 4 | The review on `master`, fixes as commits straight to `master`, a fake ship in cloud containers | `c7cd17d`, `f583172` |
20+| 7 to 15 and the eight "fix first" bugs | Ordinary inference before recovery, the narrow initializer recovery deleted, imported `(unit T)` as the prelude's unit, `ask` and `qath` printed without `.internal`, one branch-join rule, dependency-order resolution, kept diagnostics, no 26-variable gate, a fresh-ID high-water mark, lexer, `tools/ship` and `tools/golden` fixes | `a211c34`, `38c711c` and `ec7c6d4` (@iko), `93d6b23`, `839f6b0`, `f0411ad`, `ce69a3b`, `447a592`, `2b9666c`, `96d1784`, `c0a0b85`, `941c486`, `452f64c`, `68d9b76` |
21+| 25 | `eq` and the gate-free constraint | `0858191` (@iko) |
22+| 29 to 35 | `tools/test-arms` instead of 52 scripts, `tools/check`, `my-app` read on the test desk, the generated `tests/lib/jibb.hoon` no longer committed, importer fixtures in their suite, a `jibb-fixtures` desk, span and Hoon-reference checks as test arms | `d74b5e2`, `0a86d7c`, `8125287`, `ba67080`, `933bc83`, `d43c99b`, `32f4b78` |
23+| 30 (CI) | A GitHub Actions job ran the eval checks; Montelot had it removed on 2026-11-03. There is no CI; don't add one back without asking | `84b8527`, `f84a29e` |
24+| 36, 37, 39, 43 | Decided to keep things as they are | `bf65f8f` |
25+| 40 to 42, 44, 45 | `tools/hoon --no-debug`, `status.md` as a capability table, the repository spec wins until synced, `open-questions.md` only open questions, the MIT licence | `cdf53c8`, `e97aebe`, `7bc7d54`, `116178b` |
26+
27+## Read first
28+
29+1. [The review](../reviews/2026-11-02-repo-review.md): its summary, and the appendix rows for the findings below. Its line numbers are pinned to `4bf477e` and have drifted; find code by arm name.
30+2. [The questions](../reviews/2026-11-02-questions.md), and in [open-questions.md](../open-questions.md) the section "Review rulings waiting for @iko".
31+3. The two other briefs, so you know what they own.
32+4. [The checker map](../reviews/2026-11-03-checker-map.md), before you touch the type checker: what each family of arms does, which tests pin it, the 22 recovery slices, the five copies of definition finalization, and 22 hazards for anyone changing the checker.
33+5. [development.md](../development.md): setting up (`nix develop`), the tools, the test suites, and the checks to run before pushing (`tools/check`, or `nix flake check`).
34+6. `git log origin/master`. @iko and other threads work in `jibb.hoon` in parallel; rebase often.
35+
36+Then run `tools/check`. Every check should pass before you change anything.
37+
38+## Ground rules
39+
40+- **Push straight to `master`**, rebased on `origin/master`, in commits that each leave every check passing, the ship group included. Never force-push. Before a change to `tools/ship`, the desks or the `%jibb` mark, run the ship checks on a fake ship.
41+- **Every fix is a golden case or a test arm.** A finding that changes behaviour gets a case that fails before the fix.
42+- **Don't decide the language.** Questions 16 to 24 and 26 to 28 are Montelot's proposals, and each waits for @iko to confirm it before it goes in `decisions.md` and the code changes. Ask @iko in the project chat; don't build them on the proposal alone.
43+- **Don't patch what the core replaces.** The findings listed at the end of step 6 are fixed by building the core, not by repairing the old code. Before you change `+itype-unify`, `+itype-fit`, branch joins, `?-` coverage, the program, page and store recovery, or the `dg-*` transaction, ask in the project chat who is building the core and what has landed.
44+- **Keep docs current.** `status.md` is a table of capabilities: change the row a fix affects, don't add history. `compiler.md` follows the code.
45+
46+## Step 1: fixes that don't wait for anything
47+
48+A19 and the inhabitation half of A13 touch `+itype-fit-inner` and `+itype-inhabited-proof`, which the core replaces, so follow the ground rule: ask in the project chat first, and leave them to the core if it has replaced that code. A13's `+gate-free-type` half and A14's bridge are code the core keeps (the checker map, 4.2), so they don't wait.
49+
50+Checker and importer:
51+
52+- **A19.** `+width-scan` counts each faced entry on a spine, so a flat faced tuple has more entries than a record whose last field is a faced nested record. The flat tuple is then refused, as unknown by the `too-wide` guard in `+itype-fit-inner`, and as "record width constraint needs unsupported inference" by `+width-shape` in the cast and call checks. When the target's last field is a faced cell, match the source against it structurally instead of by count, and check the `lth` guards in `+width-proj-shape` and `+width-infer-literal` with the same case.
53+- **A13.** `+itype-inhabited-proof` and `+gate-free-type` know only the list and unit collections. Treat set, map, qeu, mop, jar and jug as inhabited by `~`, and check gate-freedom over all their arguments. Add a union match on a case that holds an imported map.
54+- **A14.** One whitelist of auras, `?(%u %ud %ux %uv %t %ta %tas %p %da %dr)`, is copied in `+rec-pattern`, `+import-to-itype-standard` and the API parameter check, and rejects bare `@` and other unsigned auras. Write one predicate for `@` and every unsigned, non-float aura and use it at all three; teach `+rec-pattern` `*` and `?` fields. Add bridge cases. Milestone-2-finish step 7 lists this gap for its import test; fix it here, and that test then covers it.
55+- **A56.** The importer's `+overlap-source-witness` proves a definite overlap only for a top-level `$?` of tagged cells. Accept `$%` bodies and `?(...)` leaves, so duplicate `$%` tags and `?(%a %a)` give the definite overlap, with cases in `tests/importer/tree.txt`.
56+- **A43.** Without a prelude the partial report says a bare "module has a reserved proj or unface name", with no "partial inference; module not checked" header, while the prepared path says "module has conflicting names". Give both paths one message under the header: the prepared path's, or, if milestone-2-finish step 1 has given `proj` its own wording by then, that wording. `inline-unface-reserved-no-prelude` already covers the no-prelude branch for a mold named `unface`; add a case for `++ proj 1`, and update that case's output.
57+- **A22.** The comment on the noun fit says a bare tag is "fixed as a constant", but the code binds it to the expected type. Fix the comment.
58+
59+Lexer and parser:
60+
61+- **A4.** `+read-string` calls `+doomed` for "the `}` of an interpolation", a case that never happens. Delete the call, fall through to `+bad`, and drop the clause from the notes and `+doomed`'s comment.
62+- **A5.** In the lexer's glyph dispatch, the second-character messages ("`|` begins `|=`…", "`^` begins `^-`") win over the 2.2 character errors, so a tab or control character after a glyph gets the wrong message, and only some left-out runes get the doc's reason. Run `+bad-char` first and give every left-out rune of the doc's kinds its reason. The syntax review's S9 (undecided) would rewrite nearby messages; keep to the review's fix.
63+- **A3, what is left.** About a dozen lexer hints have no golden case, among them "this `}` closes no `{`", "`|` begins …", "`^` begins `^-`", a comment inside `{…}`, interpolation outside a string, a wing's `.`, the `@u` and `@t` literal errors, the date bounds, "Jibb writes no such literal" and "Jibb can't read this literal". Several parser hints have none either, as "`+` begins `++` or `+$`", "patterns take no units: write [~ x]", "`?` alone is the loobean mold" and "the wide gate's body is one operand". Add a `lex-*-bad-*` case for each lexical one and an `inline-*` case for each parser one.
64+
65+## Step 2: tools and tests
66+
67+- **A68.** `tools/golden` splices `jibb-import.hoon` into the "(harness)" segment, so its compile errors and crash frames are blamed on the harness. Add the reader as its own segment, so spots map to `jibb-import.hoon` lines.
68+- **A69.** `tools/ship test`, `sync` and `gen-tests` accept a `--golden` folder that doesn't exist and pass with no tests. Fail when the folder is missing or a named folder has no cases, as `tools/golden` does.
69+- **A70, A84.** `tools/testdata/ship-selftest` hard-codes 45 `tests/lib` names, which miss 14 of the 58 suites, and dozens of fixture names in the checks after them. Replace them with one check: every file under `tests/` except `golden/` and `clay-fixtures/desk/` is in `assemble('jibb-dev')`, and so is the generated `tests/lib/jibb.hoon`. Keep the `--lib` and `--golden` isolation checks. That list is the last place a new suite must be registered by hand, so this also closes A84.
70+- **A74.** An `about.txt` that isn't UTF-8 crashes `tools/golden` and `tools/ship gen-tests` with a traceback, because `wants_types` in `tools/golden_case.py` is called outside the `except ValueError` handlers. Have it raise a `ValueError` that names the file, as `source_path` does, and move its calls inside the handlers: in `Case.__init__` in `tools/golden`, and in `generate_tests`' per-case loop and types-helper test in `tools/ship`. Both then exit 2 with a report.
71+- **A75.** `tools/golden` fills the harness's `{…}` placeholders after splicing in the cases' sources, the reader and the preludes, so any of them that contains a placeholder is rewritten. Substitute every placeholder in one pass.
72+- **A76.** The ship's plain `+check-types` isn't under `mule`, unlike `+check-import-types` and its other siblings, so a crash in it shows only as CRASHED, without the case's tokens and tree results or the label its siblings give. Wrap it. The eval and ship runners also keep separate copies of their Hoon helpers and their walk over a case's metadata; share them.
73+- **A72, A77, A73, A79.** Smaller tool copies: `tools/golden` renders the two preludes twice and repeats its read-to-`rap` code three times; `tools/ship` keeps its own `KNOT`/`TERM`, noun decoding and cord escaping beside `golden_case.py`, `noun.py` and `urbit_eval.py`; `delete_batches` keeps an empty-list case only a selftest uses; `tools/ship`'s `find_urbit` ignores `$URBIT`.
74+- **A71.** `check_fixture_crash_isolated` in `tools/testdata/selftest` runs the real compiler and pins checker output, though the file says the selftest runs against the stub. Give it a stub fixture, or say so.
75+- **Test-only code in the shipped library (A93, A127).** Move `+itype-unify-test` and `+check-spans-test` from `jibb.hoon` into the `jibb-typecheck` and `jibb-check-spans` suites, and have `test-unification` return the unifier's failures as its tang, so the one-line `tests/checker/unification.txt` can go (A85).
76+- **A86.** 38 suites repeat a lines-to-cord helper. Put one in a shared test library bound with `/+`.
77+- **A87, A88.** `development.md`'s golden naming table lists only `lex-`, `inline-` and `doc-`; add `types-`, `module-`, `prelude-`, `parser-` and `fixture-`, fix the ten `about.txt` files that lack a required line, and have `tools/golden` or the selftest reject them. Say in the suites section which `tests/type-*` folder belongs to which suite, or rename the folders after their suites.
78+- **A89.** The importer's fixtures are bound one by one in `tests/lib/jibb-import.hoon`; bind them as one list and derive the report and the missing-file checks from it. `tools/clay-fixtures` prints hand-written counts, "7 passed" and "4 projections passed"; compute them from the expected files.
79+- **A90, A102.** Nothing tests the claims that 100,000 nested brackets and a 20,000-line module parse. Add a suite or selftest step that generates them; milestone-2-finish step 9 then records the timings. Then re-measure design note 3's figures with `tools/hoon --no-debug` and say which mode they use: its "8 s" for starting urbit and building the library is now about 27 s.
80+- **A114.** The Clay fixture `tests/clay-fixtures/desk/sur/import-fixture.hoon` writes `$^(@ud [a=@ud b=@t])`, which accepts only atom-headed cells. Write the intended `$@(@ud [a=@ud b=@t])` and update the `ford-nested-union` expected files.
81+- **A111, A117.** `tools/ship`'s `DESKS` skips a `jibb-dev/tests` folder that doesn't exist, for `my-app` and `jibb-fixtures`; drop the skip and the README's "without tests/", and make the README's desk table match `DESKS`: add the `jibb-fixtures` row, and on `jibb-dev` name `my-app` under `/my-app` and the skipped `tests/clay-fixtures/desk`. Make `tools/ship assemble` fail when `my-app/sys.kelvin` and `jibb/sys.kelvin` differ.
82+- **A118.** `vendor/SOURCES.txt` records the machine-local path `/root/src/urbit` it was copied from, and credits the docket files to urbit/urbit's legacy `pkg/landscape`. Drop the local path, and say where the docket files are maintained now.
83+- **A110.** The Clay fixtures build `my-app`'s marks only as Hoon cores. Add a `%cb` build and a `vale` of one sample noun for each, with milestone-2-finish step 8's `my-app` ship check if that lands first.
84+
85+## Step 3: simplifications in code the core keeps
86+
87+Most are in the parser, the importer, and the module and API code, which the core keeps. A few are dead lines in checker arms that the core replaces, as the fuel of `+itype-closed-sample-match` and the last unify of `+itype-closed-gates-match`; deleting them changes nothing, so they don't wait for the core. Each must leave every golden output unchanged.
88+
89+- **Dead code (A26, A31, A42, A44, A130, A18, part of A45).** Delete `+width-has-projections`, `+infer-width-elaboration` and its type `+$ iwidth-elaboration`, `+direct-find-gate`, `+resolve-supported-defs`, the newly dead `+import-to-itypes`, `+one-request-interface-source` and `+golden-types-with-modules` (and its sentence in `compiler.md`), and the orphan comments above unrelated arms. Drop the narrow API branch, `+one-request-interface-graph`, so every API with `+$ paths` goes through `+multi-request-interface-graph`, after checking that `blog.jibb`'s interface and the `type-api` outputs don't change. Remove the never-decremented fuel of `+itype-closed-sample-match`, the always-true unify at the end of `+itype-closed-gates-match`, `+width-scan`'s unused `sub`, and two dead lines in `+find-imported-mold-prelude`. Of A45, fix only what is outside the recovery and `dg-*` arms: the double negation and the `?~ index` branch in the module driver, and the fake `ifile`s in the store code.
90+- **The `?(` check (A7).** `+hoon-union` walks back over tokens at twelve call sites to report a tight `?(`. Have the lexer's `?` branch report it, with the same column and message, and delete `+hoon-union`.
91+- **Names that shadow the standard library (A8).** Rename `+in`, move the `+fail*` helpers into `+parser` so `file` is in scope, and delete the `file` forwarders and the sixteen `in:..zuse` workarounds. Then drop the Code conventions bullet in `development.md` that says `+in` and `+fail` shadow the standard library, and move the `+fail*` helpers from the `%parser-helpers` row of `compiler.md`'s chapter table to the `%parser` row.
92+- **Copies in the parser (A9).** The path-segment loops of `+read-pathlit`, `+read-qath` and `+read-pathmold`, the open-mold-line loops, and the item and line name branches are near copies. Merge them where the result is clearly simpler; the review found some merges are not.
93+- **`%gate` and `%gate-wide` (A34, A123).** The two nodes carry the same fields, and 39 lines in the checker chapters test both or repeat an identical body for each (A34). Make one `%gate` node with a `wide=?` flag that only the printers read. That merges the checker's copies too and changes note 3's tree forms, but no golden output. Ask first if the core is being built; if its builder wants the old node kept for now, use `?(%gate %gate-wide)` in the parser, the printers and the syntax walkers only, and leave A34 to the core.
94+- **Syntax walkers (A32, A129).** The `scope-*`, `dependency-*`, `duplicate-*`, `*-has-hole` and reserved-name walker families each repeat the per-node dispatch. Add one enumeration of an expression's children and a fold, and rewrite these families on it. The type walkers (A21, A35) wait for the core.
95+- **API and module copies (A27, A29, A31).** `+request-graph-merge` should reuse `+request-graph-inputs-match` and `+request-graph-bounded`, drop its fuel arguments, and make the bound agree with its comment. `+prepare-prelude` and `+prepare-prelude-with-internal`, and `+module-mold-types` and its `-detail` form, should each share one core. `+api-path-evidence-source` and `+api-support-analysis-source` should call their `-graph` forms.
96+- **Importer copies (A57, A58, A59).** A provenance-error helper for the repeated preamble, `+local-arm-source` in `+tagged-union-fallback`, one list of standard collections, one unwrap gate parameterised by the wrapper's tag, one case lister for `$%` and `$?` with the budget as a parameter. A59, a reader that walks once for both the plain and diagnostic results, is low priority.
97+- **Budgets (A124).** The checker's literal budgets (256, 64, 4,096 and others) are scattered. Name the ones in code the core keeps in one arm; the `dg-*` ones go with the core.
98+
99+## Step 4: docs
100+
101+- **The library's header and `compiler.md` (A2, A60, A101, A131).** `jibb.hoon`'s first line says milestone 1, and its API list lacks `infer-jibb-file`, `infer-jibb-file-detailed` and the `golden-types-with-*` entry points. Its API list also lacks `+layout-error`, `+golden-types-imports`, `+prepare-prelude` and `+prepare-prelude-with-internal`, which hosts and `tools/golden` call. Add them all, make `compiler.md`'s API table list the same arms, fix its `%api` row, and add `%union-analysis` to its chapter table with an accurate `%type-inference` row; that chapter also holds the module checker, the API code and the recovery, so say so or split it. The header also still says the doc wins, where question 42 made the copy in `docs/spec/` win, and its Status paragraph calls the checker a partial inference fragment; fix both, as `development.md` words the first, and fix `compiler.md`'s first paragraph, which says "as milestone 1 left it". Milestone-2-finish step 10 rewrites these again for the core; this fix is for the code as it is now.
102+- **Design notes 2.6, 3 and 4.2 (A2).** They don't mention the `_` type hole (its token, where a mold may be `_`, its tree form) or the `?(` hint ("a union is a `+$` with its cases below"). Add them, writing the hint where A7 leaves the check: once the lexer reports it, in note 2.6's table of left-out forms, beside `$?` and `$%`.
103+- **The recovery chain (A41).** Neither `compiler.md` nor `status.md` mentions the plain-view recovery, `+program-plain-view-context`, which runs only when the keyed-view proof declines. Add it to `compiler.md`'s recovery paragraph and to `status.md`'s component-local recovery row, or leave it if the core has deleted it by then.
104+- **The importer's header (A53).** It opens with `+read-mold`, which only tests use; the callers use `+read-named` and `+read-mark` and their `-diagnostic` forms. Rewrite the header's API paragraph around them, and fix the two `jibb.hoon` comments that name `+read-mold`.
105+- **The prelude docs (A54, A105, A63, A99).** `prelude-inventory.md` lists the nine 3g shapes as future work though all exist, and its 2a rows contradict the paragraph above them. `decisions.md`'s Core language row still says three rules in its tab are proposed, but `core-language.md` marks none, and the review found each decided in its own row; drop the clause and set the row's Synced column to No, and ask @iko only about a rule that has no decided row. `internal.jibb` should say in a comment that the compiler adds the public prelude's validated list and unit to `core`, to avoid an import cycle, and `tuba-text` should take `values=(list @tD)`.
106+- **Question 38 (A112).** Montelot chose to keep `my-app`'s deliberately failing buttons example and the theme's static font, and to list them as a milestone 4 question. Add it to `open-questions.md` under "Questions milestone 2 raises", or in the plan's table with "review question 38" in the row, so the table doesn't credit the plan with it.
107+- **A106.** A paragraph about the tools sits under `development.md`'s ground rules, and `docs/README.md` carries status prose. Move the first into "The test suites". Delete the second, after adding to a `status.md` row anything it says that no row does.
108+- **A103, what is left.** `open-questions.md` still lists grammar questions 4 and 11, which the syntax review settled (S6, S7). `decisions.md`'s Syntax and Type variables rows already record the answers, so delete the two rows, keep the other rows' numbers, and update the page's "as of" date.
109+- **A115, A116.** `my-app/mar/todo-action.hoon` says it is "not supplied by the design doc", but it is the overview's `todo-action` block; fix the line. Say in the README's desk table that `my-app`'s `desk.bill` is `~` until fixture agents arrive. List the missing `%todo` and `%blog` fixture agents, and a page that embeds the basket, as gaps in `status.md` for milestones 5 and 6, and ask @iko before adding them to `implementation-plan.md`, which is @iko's tab.
110+
111+## Step 5: the rulings, when @iko confirms them
112+
113+Ask @iko about each in the project chat, with the proposal from `open-questions.md`. When one is confirmed, record it in `decisions.md`, move it out of `open-questions.md`, then change the code with golden cases. Until then, change nothing.
114+
115+| Question | Proposal | Then |
116+| --- | --- | --- |
117+| 16, 17 (A20) | A term literal fits its own aura family, `%1.000` a `@ud` and `%&` a `?`; a name term also fits `@t` | Change the two term-literal branches of `+itype-fit-inner`, the `%atom` row of `+tag-presence`, and the sentence in `grammar.md`'s Tag resolution that lists `@tas`, `@ta`, `@` and `*`; the syntax review's S4 already did this for bare decimals |
118+| 18 (A23) | A gate may fit `*` | No code change; say in `core-language.md` that `*` may hold gates |
119+| 19 (A6, A100) | `[]` and `m()` are rejected in the parser, at the closer | Parser errors at the closer, with golden cases; make the EBNF's `tuple` rule take at least one item; delete the three "empty cell is not supported by partial inference" strings, and the checker's "a change takes at least one field" once the parser reports `m()` |
120+| 20 (A30) | `[a=@ud [a=@t b=?]]` is one record, so the duplicate `a` is an error | `+duplicate-fields` carries seen fields through unfaced tails; fix the comment above `+$ written-fields` in `jibb.hoon`, which says each written record has its own scope |
121+| 21 (A25) | `/% %foo` and `++ foo 1` may share a name | `+module-scope-valid` checks marks only against marks and molds, as the API scope check has done since `ce69a3b`; add golden cases for `/% %foo` beside `++ foo 1` and beside a prelude value in an ordinary module. Tell @iko that API modules already allow it |
122+| 22 (A15) | A `?-` arm that matches no remaining case is a definite error, "arm matches no case" | The core's usefulness check gives it; until then it reads "union pattern is not supported" |
123+| 23 (A55), 24 (A64), 27 (A61) | Match Hoon: no comparator in `(mop K V)`; keep both `each`s; the mark keeps dropping the final newline | No code change; record each in `decisions.md` |
124+| 26 (A50) | The importer reads `$%` with `%&`, `%\|` and `%0` tags, then `each` and `json` | `jibb-import.hoon`'s tag checks, then catalogue entries, with importer fixtures |
125+| 28 (A136) | The printer flattens `[a [b c]]` and prints named molds by name | `+show-itype`, and the missing-tag message, which lists an imported union's cases (`union %no %yes has no case %other` in `types-missing-tag-imported`) instead of naming it, `choice.fixture`; many `types.txt` change, so do it with or after the core's one pipeline |
126+
127+One more was never asked: **A62**, whether the prelude's `+$ attr` should spell `pad` and `gap` with a `+$ space %s0 %s1 %s2 %s3` instead of eight constant cases. It adds a public prelude name, which is @iko's call. Ask with the others.
128+
129+Milestone-2-finish step 7 lists the same import gaps (A50, and A14 from step 1). Build A50 here once @iko confirms question 26, and say in the project chat when it lands, so that brief's builder doesn't build it again.
130+
131+## Step 6: the checker core
132+
133+[milestone-2-finish.md](milestone-2-finish.md), steps 2 to 4, describes the core and owns it. Whoever builds it should start from [the checker map](../reviews/2026-11-03-checker-map.md). The review's own advice for staging it:
134+
135+- Give `istate` a constructor first (A28, A125): it has 27 positional fields, built as literals at 10 places in `jibb.hoon`, so every field the core adds touches all of them. The 13 suites that use it bunt `*istate:jibb` and set fields by name, so they don't need to change.
136+- The partial report re-infers each definition on its own, so a new core can sit behind the report one definition at a time, before the full check changes (map, section 4.4).
137+- The program, page and store recovery arms run only for definitions still missing after ordinary resolution, so when the core resolves one ordinarily, its recovery arm stops firing and can be deleted with its tests kept.
138+- Keep `+itype-fit`'s three answers while old callers remain: `%unknown` should still mean "would need a deferred constraint".
139+- Budget the golden changes: question 6 moves every `types.txt` once, 347 on `master` today (283 when the review counted). Do that in one commit, with every changed output read.
140+
141+These findings close when the core lands, and nobody should patch them before: A11 (same-origin unions compared by their raw cases), A15 with question 22, A16 (variable kinds kept by self-bindings in six copied `+itype-walk` arms), A17 (three union-coverage loops), A21 and A35 (the type walkers and variable-kind disjunctions), A33 (`+infer-recursive-gate` retried after every failure), A36 (the call-argument copies in the check-mode dispatcher), A46 (the report's own resolver), A47 (the `dg-*` transaction), A48 (the program recovery arms), A49 (the generic tree proof), A132 (the prelude parsed again for each direct gate-layout proof), the rest of A42 and A130 (the report's entry chain, which parses and duplicate-checks the source again in `+golden-types-in-context` and repeats its eligibility guards, and the ten `+golden-types*` wrappers, which the one pipeline should reduce to the entry points hosts need), the rest of A45, and A121 and A122, the review's direction items on example-fitted slices and two pipelines.
142+
143+## When you're done
144+
145+- Every finding in steps 1 to 4 is fixed, each with its case, or written up in `open-questions.md` with the reason it was left.
146+- Every ruling @iko has confirmed is in `decisions.md` and built; the rest are still listed as waiting.
147+- Every check passes, under eval and on the ship.
148+- `status.md`, `compiler.md` and `open-questions.md` describe the code as it is.
149+- Everything is pushed to `master`, and a few lines go to Montelot in the project chat: what landed, what was left and why, and what waits on @iko or the core.
docs/prompts/syntax-review-follow-up.mdnew file+80
@@ -0,0 +1,80 @@
1+# Finish the 2026-11-02 syntax review's changes
2+
3+A brief for the developer who finishes what the [2026-11-02 syntax review](../reviews/2026-11-02-syntax-review.md) started. Paste it as the first message of a session, or hand it to a person; it assumes a fresh start in the repo `iko-soy/jibb`. Written 2026-11-03, when S1, S2, S4 to S7, S11 to S13 and S15 landed on `master`.
4+
5+---
6+
7+You are finishing a set of syntax changes to Jibb, a UI language for Urbit: a Hoon dialect with an indentation layout. Its spec is in `docs/spec/`; the parser, checker and printer are `jibb-dev/lib/jibb.hoon`; the prelude is `jibb-dev/lib/jibb/prelude.jibb`. On 2026-11-03 Montelot decided ten of the review's fifteen proposals, and they were built the same day, each on its own branch with its own golden cases, then merged. What is left is the gaps those builds reported, four adversarial reviews that didn't finish, and work that waits on the new checker core.
8+
9+## What landed
10+
11+Each proposal is a section of the review, numbered S1 to S15, and a row of `docs/spec/decisions.md` dated 2026-11-03.
12+
13+| # | What it does now | Where to look |
14+| --- | --- | --- |
15+| S1 | `(unface e)` removes every face from `e`'s type, through cells, a gate's sample and product, containers' arguments and the unit's payload; unions and recursive molds go by name and are kept whole. It is reserved with `proj`, is not a value, and `++ f (unface \|= …)` is still a gate | grammar.md "Unface", `+itype-unface`, `+reserved-name`, `inline-unface-*` |
16+| S1 step 1 | Decided, not built: a capital that meets a faced position binds only the type under the face | decisions.md Inference row, `inline-unface-labelled-slot` |
17+| S2 | A body's final line hands the lines after it at its depth to a tall `\|=`, `^-` or `~&` that ends it; a `?-` that begins a body's final line may take its arms at its own depth | grammar.md "The rest of a body", `lex-body-rest-*` |
18+| S4 | A bare decimal is a `@ud`: it fits `@u`, `@` and `*`, and no other aura, unless its `++` is generic over its aura | grammar.md Literals, `inline-decimal-*` |
19+| S5 | A bare pattern name is an error where a case the pattern can match has a tag there that the name spells | grammar.md Patterns, `inline-pattern-tag-name-*` |
20+| S6 | A change's item may name a wing through record fields, `m(open.cart=x)`; overlapping items are an error | grammar.md Expressions, `inline-change-wing`, `types-change-*` |
21+| S7 | Type variables may be words, `Msg`, `T2`, and print by their written names; `program` is `\|$ [Data Model Msg]` | grammar.md Type variables and Printed types, `lex-typevar-*`, `types-typevar-*` |
22+| S11, S12, S15 | Spec wording for deeper lines and nested patterns; the examples build their models with faced cells | grammar.md Lexical rules and Patterns |
23+| S13 | A cast whose expression takes the deeper lines ends its owner line; the prelude, my-app and the spec's examples use the canonical layout, with flat `?-` arms | grammar.md Spacing, prelude.jibb |
24+
25+## Read first
26+
27+1. `docs/README.md` and `docs/development.md`: the ground rules, the checks, and how golden cases work.
28+2. The review's sections for S1, S2, S4, S5, S6, S7 and S12, and decisions.md's rows dated 2026-11-03.
29+3. `docs/status.md`, the rows that name S1 to S7: each says what is partial.
30+
31+Then run `tools/check`. Everything should pass before you change anything.
32+
33+## Ground rules
34+
35+- **The spec wins**, and a language question is Montelot's to decide, as the 2026-11-03 rows were. Where this brief would decide more of the language, it says so, and you ask instead.
36+- **Another thread is building the checker core** that review question 5 asks for: union-find with levels, deferred constraints and a usefulness check for `?-`. It will replace `+itype-unify`, branch joins, `?-` exhaustiveness and pattern binding. Don't patch those for S1 step 1 or face joins; that thread owns them. Ask in the project chat what has landed before you touch the checker.
37+- **Every change is a golden case or a test arm**, and every check passes, the ship group included (`nix flake check` runs it on a fresh fake ship, or see `docs/development.md`).
38+- **Push straight to `master`**, rebased, in commits that each leave every check passing.
39+- **Keep docs current**: the status.md row for each capability, decisions.md when something is settled.
40+
41+## Step 1: finish the adversarial reviews
42+
43+The reviews of S2, S4, S6 and S7 didn't finish before the merge. For each, try to break it: probe edge cases the golden cases don't cover, check that the spec says exactly what the code does, and check every golden output the change touched. Fix what you find, with a golden case for each fix. The probe recipe is at the end of the review.
44+
45+Known already:
46+
47+- **S2.** A body of 40,000 same-depth `~& x` lines runs out of memory under eval, where 40,000 nested parentheses don't: each rest is a level of recursion in the parser. Make the rest loop iterative, if that stays small. Some new ok cases have no `types.txt` because the partial checker can't type them (`lex-body-rest-ok-3`, `-5` and `-6`).
48+- **S4.** Number patterns are checked against the subject only on known-union and atom subjects. The unit, list, loobean, single-case and deferred `?-` paths don't check them, so `[~ 0]` against a `(unit @dr)` falls through to older messages. A constructor applied directly, `(|=%wait 30)`, and a call whose head is still a variable keep the generic "call's sample and argument types do not unify".
49+- **S6.** A wing through a union field's site note reads just "field `data`", with no type. The inference-level "repeated change fields" check is now unreachable from the module entry points, because the duplicate pass reports overlaps first; keep it as a safety net or remove it.
50+- **S7.** A few messages still say "capital", as "use the same capital for a shared type". Names live in the bits of a variable's ID (`+named-var`, `+var-name`), so any test that compares a prelude scheme's IDs exactly must use the named IDs.
51+
52+## Step 2: close S1's and S5's gaps
53+
54+- `unface` on an argument whose type isn't known yet, as `|= f (unface f)` or `|=(g (unface g))` passed where the call fixes `g`, says "not supported by partial inference". The spec says it waits, as wing access does. Make it wait when the deferred path can, and fail closed otherwise. The check also looks only at the top of the type: a faced variable passes and a bare one is refused.
55+- Islands, pages and stores that find `init`, `update`, `load` or `view` by a literal `|=` (around the program, page and store recognisers) don't see through `unface`. `++ update (unface |= …)` should be a gate there, as it is for recursion (`+unfaced-gate`).
56+- Golden cases for `unface` over a set, a map and a jug, which the code handles but no case shows. `inline-unface-unknown`'s about.txt cites the wrong spec sentence. `(unface)` gets a different error in a `++` body and as a call argument; make it one.
57+- S5's exemption for a union's generic arguments works by type equality, so a concretely typed position whose type happens to equal an argument is skipped. Make it follow where the mold puts the type variable. The full module check reports an S5 error only as "module definitions need unsupported inference"; give it the partial report's message and sites.
58+
59+## Step 3: after the checker core lands
60+
61+These wait on the core from review question 5. Coordinate with that thread first.
62+
63+1. **S1 step 1** is the core's job, with a golden case each for `(hunt lt-a `1 `2)`, `(roll ~[1 2] 0 add-f)` and `[A A]` against `[x=@ y=@]`. The same thread makes joins keep a face once a position has taken one, so `~[lt-u lt-a lt-c]` and `~[lt-a lt-u lt-c]` are errors alike (today the first checks and the second doesn't). Update `inline-unface-labelled-slot` and `inline-unface-lambda` when it lands.
64+2. **The prelude's `args=` gates.** Thirty prelude gates take an unfaced `args=[…]` and open a one-arm `?-` to name its parts, only so that they fit slots with any labels. With step 1, write them with labelled samples, `++ weld |= [xs=(list A) ys=(list A)] ^- (list A)`. Use `(unface |=(…))` only for small gates mostly passed as values, as `lth`, `gte` and `lte`. Each rewrite must keep the gate's type report.
65+3. **S12, later part.** Flatten the eight prelude gates that nest a `?-` inside another's arm to look at two values (`both`, `clap`, `hunt`, `mate`, `clef`, `join`, `snip`, `rear`) into nested cell patterns, as the review shows for `hunt`. The partial checker says "branch is not supported" for those today, so wait until the core types nested patterns.
66+
67+## Step 4: lowering, at milestone 3
68+
69+When the lowering to the core language is built, `(unface e)` lowers to `e`, a `++` whose body is `(unface |= …)` joins its group's `rec` as a gate, and a wing item in a change lowers to an edit at the wing's axis (core-language.md says how).
70+
71+## Questions to ask, not decide
72+
73+Put these to Montelot in the project chat, each with a recommendation, and record the answers in decisions.md:
74+
75+1. **What faces does a cast's result keep?** `^- $-([@ud @ud] ?) lt-a` drops the gate's labels today (the fall-through at the end of `+itype-merge-faces`), while `^- [@t @ud] r` keeps a record's. The critique recommends that a cast never removes faces, so `unface` is the one place labels go.
76+2. **May a flat arm's bare-name pattern hide a prelude name?** With flat arms, Hoon's habit of writing `?:`'s else branch back at the rune's column, as `dec a`, parses as a catch-all arm binding `dec`. Today "pattern binder shadows a name" catches it. If S3 ever lands, it wouldn't.
77+3. **Is a `|=` or `~&` that ends a body's final line written flat or with a deeper body by the formatter?** The prelude keeps deeper bodies for `flit` and `bond`.
78+4. **When named type variables merge, which name prints?** Today a capital written in the `++` wins, otherwise the one made first, so `(cork fk fv)` prints `cork`'s `A`, not `fk`'s `Key`.
79+
80+The review's other proposals (S3, S8, S9, S10 and S14) weren't decided. Leave them unless Montelot asks.
docs/reviews/2026-11-02-questions.md+2
@@ -234,6 +234,8 @@ Montelot's answers to 16 to 28 are proposals. They are listed in [open-questions
234234
235235**Answer:** a *(chosen)*
236236
237+On 2026-11-03 Montelot had the GitHub Actions job removed. The checks run before each push instead, with `tools/check` or `nix flake check`.
238+
237239**31. How should the 28 copies of `my-app` files under `tests/` be handled?** (A108, A109)
238240
239241- a) Map `my-app` into the `jibb-dev` desk outside `/tests` and read it directly, removing the copies.
docs/reviews/2026-11-02-syntax-review.md+14
@@ -6,6 +6,20 @@ How it was done: five reviewers each read the spec, the prelude, the example des
66
77This review does not restate the language rulings that [the repository review](2026-11-02-questions.md) raised (questions 16 to 28, now listed in [open-questions.md](../open-questions.md) under "Review rulings waiting for @iko"). Where a proposal extends one of them, it says so. Proposals here are numbered S1 to S15 so they don't collide with those numbers. "Review question N" means a question in that file, and "open question N" means item N of [open-questions.md](../open-questions.md).
88
9+## Outcome, 2026-11-03
10+
11+Montelot decided ten of the proposals on 2026-11-03, and they were built the same day. [decisions.md](../spec/decisions.md) has a row for each, dated 2026-11-03, and [prompts/syntax-review-follow-up.md](../prompts/syntax-review-follow-up.md) lists what is left.
12+
13+| # | Decision | Built |
14+| --- | --- | --- |
15+| S1 | Not as proposed: an explicit `unface` that strips every face from a type, reserved like `proj`, instead of ignoring sample names when gates unify. Step 1 too: a capital binds only the type under a face | `unface` yes; step 1 waits for the checker core of review question 5 |
16+| S2 | Yes, and a `?-` that begins a body's final line may also take its arms at its own depth, without indenting them | Yes |
17+| S4, S5, S6, S7 | Yes | Yes, with gaps listed in the follow-up prompt |
18+| S11, S12, S13, S15 | Yes; S12's prelude rewrite waits for a checker that types nested patterns | Yes |
19+| S3, S8, S9, S10, S14 | Not decided | No |
20+
21+The sections below are the review as written on 2026-11-02, before these decisions.
22+
923## Summary
1024
1125- **The syntax is in good shape.** Open brackets without closers, tightness as the one disambiguator, one exhaustive `?-`, named unions, `|=%tag` constructors and named changes all read well, and nearly every slip the reviewers tried gets an error at the right character. The [keep list](#what-to-keep) says what not to change.
docs/reviews/2026-11-03-checker-map.mdnew file+587
@@ -0,0 +1,587 @@
1+# The checker on 2026-11-03, and what a general core replaces
2+
3+A map of the type checker in `jibb-dev/lib/jibb.hoon`, written for whoever builds the general checker core that [review question 5](2026-11-02-questions.md) chose. It was written by the thread that fixed the [2026-11-02 review](2026-11-02-repo-review.md)'s findings, by reading the code; nothing in it was run. Claims about which tests would fail come from the tests' fixtures, their direct `name:jibb` references, and the code paths.
4+
5+Line numbers without a file are `jibb-dev/lib/jibb.hoon` at commit [`f84a29e`](https://github.com/iko-soy/jibb/blob/f84a29e/jibb-dev/lib/jibb.hoon) (15,838 lines). The syntax changes of 2026-11-03 (`d4aed71` to `706e9ca`: `unface`, S2, S4 to S7) moved them by up to about 800 lines. They added `+itype-unface`, `+infer-unface`, `+unfaced-gate`, the `+decimal-*` arms, `+tag-name-pattern`, `+change-wing-field`, `+wing-overlap` and named type variables kept in the bits of a variable's ID (`+named-var`, `+var-name`, `+show-var`), and renamed `+module-has-reserved-proj` and `+reserved-proj-*` to `+module-has-reserved` and `+reserved-*`. This map doesn't cover them, and its rows in 6.2 for S1, S4, S5, S7 and S12 predate Montelot's decisions of that day; read `decisions.md`'s rows dated 2026-11-03 instead. Find an arm by its name, not its number. Review finding numbers (A1 to A137) come from [the review](2026-11-02-repo-review.md), whose own line numbers are pinned to `4bf477e`.
6+
7+Review Q5 (`docs/reviews/2026-11-02-questions.md:43-49`) was answered (a): *"Build the general core
8+first: union-find bindings with levels, a deferred-constraint queue and Maranget's usefulness check,
9+with `main = (program …)` checked as an ordinary application."* Q6 (l.51-56, one golden pipeline),
10+Q11 (l.88, one branch-join rule) and Q12 (l.95, dependency-order pass) were also chosen.
11+
12+## 0. Numbers
13+
14+| Thing | Value |
15+| --- | --- |
16+| `%type-inference` chapter | 4601-10901 (325 arms) |
17+| `%union-analysis` chapter | 10902-15838 (224 arms). Despite its name it holds union analysis (10902-11302), the module checker, API derivation, program/store recovery, the report and the dg-* transaction (A131) |
18+| Arms and types from 4601 on | 549 `++` arms, 91 `+$` types |
19+| `itype` | 22 cases (4663-4686), six of them variable kinds plus `%tag` |
20+| `istate` | 27 positional fields (5996); built as a positional literal at 10 sites (10699, 10752, 11986, 12001, 12057, 12735, 12769, 14759, 14924, 15107) and bunted at 5 (14497, 14550, 14566, 15610, 15652) |
21+| Program/store/page/static recovery and kind code | 13146-14648 (1,503 lines) |
22+| dg-* deferred transaction | 15147-15719 (573 lines) |
23+| Direct gate-layout evidence | 9002-9228 (227 lines) |
24+| Lines saying "unsupported" or "not supported" | 283 |
25+| Golden cases | 690 in `tests/golden`; 304 have `types.txt`, every one of which starts `partial inference; module not checked`; 177 of those also have `modules.txt` (module-check mode, prepared prelude); 127 of the 304 contain an "unsupported"/"not supported" line |
26+| Suites | 58 files in `tests/lib` (the 57 checker-related suites of the brief plus `jibb-check-spans`/`jibb-hoon-reference`, which are not checker tests); they reference 125 distinct `jibb.hoon` arms and 55 types by `name:jibb` |
27+| Call sites | `itype-fit` 59 (22 in 13311-14648), `itype-unify` 43, `itype-normalize` 95 (20 in program/store, 7 in dg), `instantiate-scheme` 17 (12 in program/store), `itype-merge-faces` 13 (12 in program/store), `direct-invariant` 19 (16 in program/store), `template-apply` 22 (15 in program/store), `add-supported-result` 7 (6 in program/store) |
28+
29+## 1. The checker as it is
30+
31+### 1.1 Data types
32+
33+| Type | Line | Shape | Role and quirks |
34+| --- | --- | --- | --- |
35+| `itype` | 4663 | `%var %fvar %avar %rvar %nvar %rnvar` (one id space), `%atom aura`, `%any-atom` (bare `@`), `%flag`, `%noun`, `%empty`, `%tag [id literal constructor=?]`, `%const literal`, `%collection [name args]`, `%recursive [module name label]`, `%jrec [at name label head aura tail]`, `%grec [at name label proof=shape args]`, `%union [cases origin label args]`, `%face [name body]`, `%fn [sample product]`, `%cell [hed tal]` | The whole type language. `%var` unconstrained; `%fvar` gate-free; `%avar` any atom incl. `?` and `@`; `%rvar` atom other than `?` (arithmetic); `%nvar` decimal literal, defaults to `@ud`; `%rnvar` both. `%tag` is a pending literal resolved by binding its id. Faces and display labels live inside the type, so relabelling changes equality (A11). `%collection` is opaque except list/unit (A13). Three recursive representations (`%recursive` imported, `%jrec` qath-shaped, `%grec` test tree) |
36+| `ibinding`, `isub` | 4687-4688 | `(list [id val])` | Substitution as an association list; first entry wins; entries only prepended; no path compression. Kind refinement is encoded as a self-binding (`[n -> %fvar n]`, `[n -> %rvar n]`, `[n -> %rnvar n]`) |
37+| `ipending` | 4689 | `[id literal at]` | One per `%term`/`%null` literal or `%ctor` tag (created 8780, 8781, 8848) in `istate.tags` |
38+| `igf-form(s)` | 4942-4943 | `[typ sub left]` | Gate-free conversion result with fuel |
39+| `ifit` | 5019 | `%ok [sub next]` / `%bad` / `%unknown` | Three-valued directional fit. `%unknown` is the universal fail-closed answer |
40+| `ischeme`, `ienv`, `imold-types` | 5804-5806 | `[typ vars=(list @ud)]`; `(list [name scheme])`; `(list [name template])` | Schemes with raw (not canonical) quantified ids; environment is newest-first, linear `ienv-lookup` (6001) |
41+| `iderived`, `iwidth-definition`, `iwidth-dependency` | 5807-5809 | | Derived poke constructors; `proj` elaboration evidence (carries the raw `sub`, 10687) |
42+| `irequest-evidence`, `istore-request-evidence`, `irequest-graph` | 5812, 5816, 5820 | | Source-bound API/store request certificates and the trusted closure inputs |
43+| `ifile` | 5822 | `[values molds at derived elaborations dependencies source graph]` | Checked module interface; `graph ~` = detached legacy/prelude file |
44+| `ijimports`, `icap(s)`, `iparams`, `imolds`, `iexternals`, `imark-externals`, `ihole` | 5823-5834 | | Imports in scope; written capitals with their var ids; generic params; local mold shapes; raw importer nouns; type holes (created 7103) |
45+| `iwfield(s)`, `iwstep`, `iwidth-result`, `iwprojection` | 5839-5843 | | Record-spine scan and `proj` plan |
46+| `igf-segment`, `igate-free` | 5931, 5938 | `[verdict=?(%yes %no %unknown) inhabited left path]` | Gate-free proof with witness path |
47+| `igate-prelude-evidence` | 5994 | `[iface gates=(map term def)]` | Re-parsed prelude gate defs for direct-gate recovery |
48+| `dgo` | 5995 | `[left right at context]` | Deferred fit obligation (dg-* only) |
49+| `istate` | 5996 | `next sub caps binders molds globals externals surs mark-externals marks jimports reserved-molds params active tags in-mold at top-molds prelude holes jrec-fuel projections gate-defs head-evidence grec-index defer obligations` | Threaded functional state. `next` restarts at 0 per top-level definition. Recovery-only fields: `jrec-fuel`, `gate-defs`, `head-evidence`, `grec-index`, `defer`, `obligations` |
50+| `idiag`, `iresult`, `isample-result` | 5997-5999 | `[msg sites]`; `(each [typ state] idiag)`; `(each [typ env state] tape)` | A diag with no sites is "unsupported"/retryable (`definite-diag` 7521) |
51+| `irec-pattern` | 6416 | `[pat=upat has=?]` | Imported recursive fork proof |
52+| `ilocal-result` | 7306 | `(each [env state] idiag)` | Locals and groups |
53+| `icap-site` | 7377 | `[name at]` | Written capital occurrence |
54+| `imatch`, `ifinite` | 8106, 8170 | `?(%full %none %unknown)`; `[origin base part]` | Pattern-vs-case classifier; finite loobean refinement row |
55+| `itag-presence` | 8661 | `?(%yes %no %maybe)` | Missing-tag diagnosis |
56+| `iwidth-elaboration` | 8994 | | Dead (only the dead `infer-width-elaboration`) |
57+| `igate-entry`, `igate-seeds` | 10433-10434 | | Recursive-group seeds |
58+| `iresolved` | 10552 | `[env grouped artifacts]` | Resolver output threaded by the recovery chain |
59+| `iadj ivisited iwork iwresult icresult icomponents` | 10553-10558 | | Kosaraju state |
60+| `iadded-definition` | 10668 | `[env checked artifacts]` | `add-supported-result` output |
61+| `icyclesite`, `icycle` | 10788-10789 | | Value-cycle proof |
62+| `upat`, `urelation`, `upair` | 10909, 10919, 10920 | `%unknown %all %empty [%atom (unit @)] %flag [%cell] [%or]`; `?(%disjoint %overlap %unknown)`; `[first second relation]` | Noun-shape projection for disjointness/overlap (also used by the importer at 6463, 6645) |
63+| `uow-case` | 11191 | | Source overlap witness case |
64+| `jsource jbundle jcache jfile-result jfile-overlap jfile-failure jfile-detailed-result jimports(-detailed)-result` | 11507-11518 | | Module sources, per-invocation cache, results with structured overlap evidence |
65+| `written-fields` | 11521 | `(map term span)` | Duplicate-field scope |
66+| `imold-failure` | 11777 | `[message overlap=(unit [name upair])]` | First failing mold |
67+| `iprelude` | 12090 | `[iface values molds]` | Prepared prelude; values/molds reserve every declared name |
68+| `iapi-*` | 12328-12706 | | API path/request/support evidence |
69+| `ione-request-interface`, `imulti-request-gates` | 12780, 13043 | | API constructors |
70+| `istore-declaration` | 13242 | `[action=term defs]` | Store declaration (action always `%poke`) |
71+| `iview-site` | 13608 | `[xs mapper]` | Keyed `each (turn xs mapper)` site |
72+| `igate-free-mold` | 14885 | | `gate-free-mold-source` result |
73+| `dgscan`, `dgcommit`, `dg-step`, `dgparse` | 15149, 15243, 15444, 15581 | | dg-* transaction |
74+| `grec-collected` | 15782 | `[molds proofs]` | grec index input |
75+
76+### 1.2 Pipelines
77+
78+#### (a) The partial golden-types report (all 304 typed goldens)
79+
80+Entry chain:
81+- No prelude (127 typed goldens): `golden-types` 11486 → `golden-types-imports` 11497 → `golden-types-with-marks` 15016 → `golden-types-in-context` 15021 → `golden-types-in-context-core` 15025. `tools/golden:248-253` picks the arm by whether the case has `/sur` or mark fixtures.
82+- Module-check mode (177 typed goldens with `modules.txt`): `tools/golden:254-260` calls `golden-types-with-prepared-prelude` 14975 with a prelude prepared once under `mule` by `prepare-prelude-with-internal` 12103 (`tools/golden:291`), falling back to `golden-types-with-prelude-and-internal` 14969. 14975 parses, runs `duplicate-defs`, `module-scope-valid` 14986, and **resolves Jibb imports with the full checker** (`resolve-jibb-imports` 14989 → `infer-jibb-file-detailed` per imported module), then calls the core.
83+
84+`golden-types-in-context-core` 15025-15146:
85+1. Parse (15029), `duplicate-defs` 15031 (→ `duplicate-fields-report`), reserved `proj` 15033 (bare `'module has reserved proj name'`, no header, A43).
86+2. `resolve-groups` 15040: the same resolver as the full check (10662 → `resolve-groups-core` 10736) but **with no grec index**, so `%grec` never arises here; no program/store recovery, no kind checks.
87+3. `definite-value-cycles` 15041.
88+4. dg-* transaction if eligible (15044-15075): import-free, not API/store, no `main`, incomplete, ≤65,536 bytes, ≤64 defs, and either no prelude + `dg-source-candidate`, or the exact prepared prelude + `dg-prepared-candidate`. Names it adds are "recovered" only if the transaction env is complete and `dg-interface-safe`.
89+5. Per definition in source order (15079-15146): molds → `show-partial-mold` 11431 (never infers the mold; hole report, union disjointness verdict or `not checked`); duplicate name → `name already in scope`; cycle → `non-gate value depends on itself through a cycle`; recovered/grouped → print the scheme from env; otherwise **re-infer the definition afresh** (state literal 15107, `gate-defs`/`head-evidence` 15108-15109, `reserve-def-caps` 15110; gates through `infer-recursive-gate` 15113, others `infer-fragment` 15114) and finalize with its own copy of the finalization (15117-15143, table in 2.8), then `canonical-itype` 15144 + `show-itype` + `show-atom-constraint`.
90+
91+So a report line is not the scheme the resolver published; it is a second inference against the resolved env. The report never runs recovery, kind checks or grec; its messages are the raw per-definition failures.
92+
93+#### (b) The full module check
94+
95+`infer-jibb-file` 14650 (text adapter) → `infer-jibb-file-detailed` 14658-14879:
96+1. Parse 14661 (`module source does not parse: /p`), `duplicate-defs` 14664, API module with `main` rejected 14666.
97+2. `/ui/api/...` branch 14668-14725: `api-poke-interface-result` 12979 first; else `api-derived-clash` 14678, scope with mark rules 14684-14698, prelude required 14699, `resolve-jibb-imports-detailed` 14705, `+$ paths` required 14708, then the "narrow" `one-request-interface-graph` 14711-14721 or `multi-request-interface-graph` 14722-14725. No value inference beyond `api-support-analysis-*` (12708, 12742), which calls `resolve-groups`.
98+3. Other modules: `program-main-def` 14726 and the syntactic recognisers `program-main-parts` 14728, `page-main-parts` 14730, `store-main-parts` 14732; `store-declaration` 14734 (definite clash 14736; `module kind or scope needs unsupported inference` 14740); a `/ui/stores` main that is not a store is rejected 14741.
99+4. `module-scope-valid` 14745, `resolve-jibb-imports-detailed` 14748 (mutual recursion with this arm; cycle check before cache, cache reuse rules 12275).
100+5. Molds: `grec-collect-molds` 15825 only for import-free modules (14750-14752); istate literal 14759; grec index only for import-free prelude-backed modules whose prelude list is exactly `[[%collection %list ~[[%var 0]]] ~[0]]` and that have no local `list` (14762-14772); `module-mold-types-detail` 11799 (first failure aborts; overlap evidence rendered 14774-14780).
101+6. Values: `resolve-groups` or, with an index, `resolve-groups-core` (14781-14784). `resolve-groups-core` 10736-10756: compute names, graph, Kosaraju components, `direct-prelude-evidence` (prelude re-parse) and `dependency-order` 10768 once, then loop: `add-supported-defs-core` 10690 over the ordered defs (fresh positional state per def with `next=0`, `jrec-fuel=256`, `gate-defs` = `direct-checked-gates` of the current env, `head-evidence`; `reserve-def-caps`; `infer-fragment`, then `infer-recursive-gate` if that failed; `add-supported-result` 10670, which **silently drops** any failure or pending tag), then `add-groups` 10645 (cyclic components through `infer-gate-group` 10509), until env stops changing.
102+7. Program recovery chain 14786-14804, only for a direct `(program i u v s)` main: `program-update-context` 13346 → `program-subs-context` 13508 → `program-view-context` 13938 (keyed) → `program-plain-view-context` 13858 (only if keyed declined) → `program-plain-init-context` 14238 → `program-main-context` 14472. Single pass, fixed order, each arm a no-op unless its component (and `main`) is still missing.
103+8. dg fallback 14807-14816: only if incomplete, not a store, no imports **and no prelude** (14809), so it can never affect a prelude-backed check (A47).
104+9. Completeness 14817-14832 (store modules exclude `main`): `module-pending-tag` 10715 (re-infers ≤64 missing defs to find `nothing fixes the union of %x`), then `module-sample-shadow` 12171, then `module definitions need unsupported inference: /p[: ++ name]` with `module-missing-value` 12132 choosing the name.
105+10. `request-graph-merge` 14834; static main swap 14836-14843 (`static-main-specialized` 14487); store main swap 14844-14849 (`store-main-closed` 14599); kind boundary 14850-14857 (`program-main-closed` 14555, `page-main-closed` 14540, store/static results) → `module kind needs unsupported inference: /p`; store-derived exports 14858-14875; `request-graph-bounded` 14876; `ifile` 14878.
106+
107+#### Where the two pipelines differ (A46, A122)
108+
109+| | Report (a) | Full check (b) |
110+| --- | --- | --- |
111+| Resolver | `resolve-groups`, grec index `~` | `resolve-groups-core` with index when import-free |
112+| After resolving | re-infers each definition and prints its own failure | keeps resolver env; failures are silent |
113+| Recovery | none | program chain, static/store main swaps |
114+| Kind checks | none | `program-main-closed`, `page-main-closed`, store, static |
115+| dg-* | eligible with or without prepared prelude (15053-15061) | only without prelude (14809) |
116+| Finalization | 15117-15143 (adds `pending-null`, hidden recursive/generic, merged-capitals messages) | `add-supported-result` 10675-10689 (no `pending-null`, no hidden-name check, merged capitals caught only as `constrained-capitals`) |
117+| Mold check | `show-partial-mold` (projection only) | `module-mold-types-detail` (real templates) |
118+
119+### 1.3 Families, by layer
120+
121+"Category": G general inference, U union analysis, M module and imports, A API and paths, R recovery slice, P reporting/printing, O other. "Tests" lists suites (without the `jibb-` prefix) and goldens; `[call]` marks suites that name the family's arms directly.
122+
123+#### A. Substrate (4601-6400)
124+
125+| Family | Lines | Cat | How it works | Tests |
126+| --- | --- | --- | --- | --- |
127+| Chapter contract, `itype`, `isub` | 4601-4689 | G | Contract comment 4603-4661 (assoc-list sub, occurs check, per-definition generalization, monomorphic binders, capitals shared per definition, `@` one-way, unions keep origin/args; `proj` limits 1,024/4,096; "The unchanged todo API fits this fragment" 4643-4644; closed gate sample may omit one outer face 4653-4655) | every `types-*`; 32 suites build `itype:jibb` |
128+| Lookup, walk, occurs, normalize | 4691-4732, 4817-4843, 6012-6026 | G | Linear `itype-lookup`; `itype-walk` follows chains for the six var kinds and `%tag`, stopping only at a self-binding to `%fvar`/`%rvar`/`%rnvar` (six copied arms, A16); `itype-occurs` (opaque `%recursive`/`%jrec`; same-id `%tag` counts); `itype-normalize` full zonk, leaves `%tag`/`%recursive`/`%jrec` | typecheck, hole-guards [call], arithmetic-guards [call], deferred [call], generic-construction [call]; `types-partial-occurs`, `types-partial-dependency-chain`, `types-partial-shared-tvar` |
129+| Emptiness and inhabitation | 4734-4815 | U | Budgeted; `itype-empty-proof` proves only emptiness; `itype-inhabited-proof` three-valued (`%var` yes only via written capital; only list/unit collections decided, A13; `%grec` via `grec-tree-proof` 4801); `itype-live-cases` drops proven-empty cases, any unknown → `~` | empty [call]; `types-list-patterns`, `types-partial-union-edges`, `types-union-finite-limit`, `types-tuple-context` |
130+| Unification | 4851-4940, 5005-5012 | G | `(unit isub)`, no reason. Walk both, equal → ok; grec by at+name then args; jrec by 5 fields; recursive by module+name; union by origin, then raw `cases` equality when argless (A11) else args; collection by name then args; `%var` binds anything after occurs; `%fvar` via `itype-bind-gate-free`; atom-kind lattice 4884-4925 (nvar~rvar → rnvar with self-binding 4887-4889); const by value; atoms of different aura fail (no widening); face~face same name; fn/cell pointwise | typecheck, arithmetic-guards, gate-free-guards, generic-recursion [call]; `types-arithmetic-*`, `types-partial-atom-*`, `types-union-phantom-generic` |
131+| Gate-free propagation | 4942-5003, 6320-6343 | G | `itype-gate-free-form` (budget; unbound `%var` → self-binding to `%fvar`; fails on fn/noun/tag/recursive/grec); `itype-bind-gate-free` 256 (exhaustion reads as mismatch); `itype-collection-keys` for set/map/mop/jar/jug keys; `itype-var-is-gate-free-fuel` fails open at fuel 0 | gate-free-guards [call], gate-free-source; `types-prelude-unit-helpers` |
132+| Directional fit | 5014-5019, 5451-5711 | G | `itype-fit` = `itype-fit-inner` + empty-source rescue (256). About 45 ordered guards: width (spine ≥1,024 or wider source → unknown); empty/flag-vs-`@f`; `*` accepts anything incl. gates (A23) and binds bare tags to `*` (A22); actual `*` only to a var; grec/jrec/recursive by identity; unions by origin; known union to var by unify; non-var vs union → `itype-fit-cases` (unique %ok wins, two → unknown); tags: ctor only vs fn via `itype-fit-ctor-cases`, term vs `@tas`/`@ta` with no aura check (A20), vs `?` if 0/1, vs `@`; zero vs list → unknown; var vs face unifies with the body (5652); `@` turns a var into a fresh `%avar` (only allocation, 5666); atom by `aura-prefix`; cells head then tail; faces same name; closed gates by `itype-closed-gates-match`; last resort unify, with failures turned to `%unknown` when unions, recursion or related auras are involved. **Gates (fn vs fn) only unify: no variance** | closed-gate-guards, constructor-fit-guards, empty, qath-fuel, generic-construction, arithmetic-guards, generic-recursion, deferred [call]; 32 golden lines `call constraint…`, 37 `cast constraint…` |
133+| Aura families | 5049-5092 | G | `aura-prefix` textual prefix (`@` above all); `itype-family-related` only to turn failures into unknown | `types-partial-aura*`, `types-partial-atom-widening`, `types-partial-branch-widening` |
134+| Branch joins | 5094-5097, 5125-5210 | G | Unify, else `itype-concrete-join` (prefix parent or `@`, never touches sub); n-ary: unify all, else first `@` or common prefix parent present among arms | `types-partial-branch-widening`, `types-list-branch`, `types-union-branch-*`, `types-recursive-branch`, cell-branch, deferred |
135+| Face guards | 5212-5227, 5265-5349 | G | `itype-face-asym` (face on one side vs non-var); `itype-merge-faces` (cast result, 1 + 12 recovery calls); positional rules `itype-positional-face-asym`/`-slot-face-asym` (added with `like`, 640a442); `itype-output-may-be-cell` | positional-face-guards [call], direct-gate-guards [call], deferred [call]; `types-positional-faces`, `types-prelude-like`, `types-generic-face-inference`; 4 golden lines `call result face propagation` |
136+| Closed gate sample matching | 5229-5263 | R | See 3, R12 | closed-gate-guards (via `itype-fit`), todo-api |
137+| Fail-closed structure guards | 5020-5046, 5098-5123, 5372-5449 | G | `itype-has-any-atom/-tag/-union/-recursive/-hidden-generic/-hidden-recursive`; `itype-has-fixed-atom` (5098) is dead | `types-union-unresolved*`, `types-generic-union-escaping`, `types-qath-module-identity` |
138+| Pending tags | 5351-5370 | G | `pending-tags`, `pending-null`, `pending-tag-diagnostic` (`nothing fixes the union of ` + `show-lit`, 5363); checked only at definition end | buttons (`tests/type-buttons/error.txt`), program-init, program-update, deferred [call]; 80 golden lines `tag needs context`, 24 `` `~` needs context `` |
139+| Self-test | 5713-5798 | O | `itype-unify-test`, compared by `jibb-typecheck` with `tests/checker/unification.txt` (the old `tools/hoon` check is gone) | typecheck [call] |
140+| State, env, results | 5800-5806, 5824-5827, 5832-5834, 5995-6006 | G | see 1.1 | 13 suites build `istate:jibb` |
141+| Interface/evidence types | 5807-5823, 5828-5831 | M | see 1.1 | module-*, api-evidence, store, program-watch |
142+| Record width and `proj` | 5835-5923 | O | `width-scan` (closed uniquely faced spine), `width-known-shape`, `width-shape` (wider source → `record width constraint needs unsupported inference`), `width-proj-shape`/`width-project` (source-order planner, 4,096) | proj-guards; `types-proj-*`, `types-partial-projection` |
143+| Gate-free proof with witness | 5925-5992 | O | `gate-free-type` on normalized types; budgeted; list/unit only (A13) | gate-free-guards, gate-free-source, empty, generic-recursion [call]; program-main |
144+| Defaulting, promotion, holes | 6028-6181 | G | `promote-restricted-numbers` (only with written caps), `default-hole-numbers` (only when the type has no gate), `unresolved-hole`, `default-decimals` (`itype-has-gate` treats `%grec` as gate-bearing, ignores union args), `uncertain-hole-msg` | hole-guards [call], generic-recursion [call]; `types-hole-*`, `types-partial-decimal-default` |
145+| Vars, rename, canonical, instantiate | 6183-6318, 6345-6368 | G | `itype-vars` order (fn sample before product, head before tail, union args before cases); `unique-type-vars` O(n²); `itype-rename` single pass, no sub; `canonical-itype` kind precedence rvar > avar (nvar/rnvar → avar) > fvar > var; `instantiate-scheme` pushes fresh fvar/avar/rvar ids onto `binders` | gate-free-guards [call]; `types-partial-generalization`, `types-partial-atom-alias`, `types-many-variables`, `module-import-atom-scheme` |
146+| Local capital and mold lookup | 6370-6395 | M | `icap-lookup`, `find-simple-mold` (unique only), `collect-simple-molds` | 5 suites [call] |
147+
148+#### B. Import bridge and mold elaboration (6397-7253)
149+
150+| Family | Lines | Cat | How it works | Tests |
151+| --- | --- | --- | --- | --- |
152+| Imported Hoon validation and bridge | 6397-6728 | M | `jibb-face-name`, `rec-pattern(s)` (self-recursive disjoint fork → opaque `%recursive`), `imported-faces-valid` (repeated face on a spine fails), `import-to-itype(-standard)` (aura whitelist u ud ux uv t ta tas p da dr tD, duplicated at 6432, 6557, 12666, A14; `%f` pair → `?`; `%unit` → prelude unit union only with the standard template, A10; other forks → originless `%union` after pairwise `union-relate`), `find-imported-mold(-prelude)`, `find-imported-mark(-prelude)`, `collect-sur-imports`, `collect-mark-imports`. 6682-6683 dead (A18). All failures `~` | bridge, api-evidence [call], import*, mark-bridge, tlon-bridge, poke-bridge; `types-import-*`, `module-import-api-*` |
153+| Interface lookup and relabelling | 6730-6841 | M | `find-jibb-interface`, `find-jibb-mold` (~40 callers), `itype-in-import` relabels unions/jrec/grec (display only), `prelude-union-alias`, `identity-union-parameters` | generic-alias, ask-guards, store, page-main, program-watch, todo-full, theme [call]; `module-import-*`, `types-union-print-*` |
154+| Mold elaboration and templates | 6843-6919, 6970-7000, 7099-7253 | G | `infer-simple-shape` (shape→itype; holes allocate a var + `ihole`; unions need `union-pairs` without overlap, else the source slice; local mold expansion guarded by `active`; generic local mold re-elaborated with params bound; generic local unions refused 7216-7217); `template-apply(-sub)` renames scheme vars to args (`template-apply` drops the sub); `infer-mold-template` builds +$ schemes, generalizing exactly the params; `label-direct-union` gives a top-level union its origin | union-source [call], gate-free-guards [call]; `types-generic-*`, `types-hole-*`, `types-union-alias` |
155+| Source-recursive recognisers | 6921-6967 | R | `simple-source-recursive` (`%jrec`), `simple-source-generic-recursive` (`%grec`). See R17, R18 | qath-*, generic-recursion [call] |
156+| Import-invalid replay | 7002-7097 | M | Replays a failed shape to recover the importer's `[%invalid …]` message with site note `invalid imported mold` | import, import-diagnostic, import-overlap, import-structural |
157+| Gate samples | 7255-7300 | G | `infer-sample`: binders fresh `%var`, monomorphic, pushed onto `binders`; shadow → tape `sample shadows a name` | `types-partial-shadow-global`, `module-import-*-shadow` |
158+| Local definitions | 7302-7373, 7514-7702 | G | See 2.7; generalization subtracts `free-env-vars` and `free-cap-vars`; order-independence machinery `shared-types`/`shared-moved`/`closed-local` | `types-local-*`, `types-partial-locals`, `types-local-scc*` |
159+| Capital scope walker | 7375-7512 | G | `scope-*` syntactic walk; `reserve-def-caps` allocates one `%var` per written capital per `++` | `types-local-capitals`, `types-capital-distinct` |
160+| Record field access | 7704-7747 | G | `record-fields-named` on a known faced spine; no deferred has-field constraint | program-init/main/update/watch [call]; `types-record-faces` |
161+
162+#### C. Expression checker (7749-10032)
163+
164+| Family | Lines | Cat | How it works | Tests |
165+| --- | --- | --- | --- | --- |
166+| Contextual branches and list literals | 7749-7921 | G | `infer-union-context` (two loobean arms or unit arms with the same expected type, no join), `infer-list-context` (exact prelude list scheme; cons only under list context), `infer-open-list-items`/`infer-list-items` (drifted copies, A17), each with the `element` fallback hook (R7) | `types-list-*`, `types-flag-branch-context`, `types-union-branch-context`, deferred-context, todo-partial |
167+| Unit and list two-arm branches | 7923-8075 | U | Hand-coded two-arm exhaustiveness (`~` + `[~ x]`, `~` + `[h t]`); unit recognised structurally (no origin check); inhabitation 256 | empty [call]; `types-unit-patterns`, `types-list-patterns` |
168+| String interpolation | 8077-8101 | G | Accepts atoms, `@`, leftover decimals, `(list @tD)`; generic atom from a capital → `a generic atom in interpolation needs an aura`; cell → `a cell in interpolation needs a printer` | `types-string-interpolation` |
169+| Union coverage, three copies | 8103-8390 | U | `union-pattern` %full/%none/%unknown; `infer-known-union-whole` 8208, `-context-whole` 8246, `-finite` 8292 (loobean expansion ≤64 rows); `single-structured-pattern`/`infer-single-case-branch` 8351-8390 | generic-pattern, cell-branch, nested-union-guards, empty; `types-union-patterns*`, `types-union-finite*`, `types-single-case-pattern` |
170+| jrec/grec match views | 8392-8475 | R | R17, R18 | qath-fuel, generic-pattern [call] |
171+| Branch routing | 8477-8549 + 8878-8930 | G | Order in `infer-fragment %branch`: dg → one arm (empty-list, empty-union, grec, structured, cell) → ≥3 arms known-union → two arms: speculative `known-union-subject`, unit, non-literal → known-union, loobeans (unify subject with `?`, infer arms, `itype-branch-join`, failure classified 8921-8929) | `types-union-*`, `types-loobean-*`, `doc-grammar-04-step` |
172+| Empty list / empty union | 8555-8608 | U | `empty-list-null-branch` (exact prelude list; element proven empty), `known-empty-union-wing` | empty [call] |
173+| Record change | 8612-8656 | G | `infer-change-edits` on a known faced spine; `standard-unit-template` 8646 | `types-record-change*` |
174+| Missing-tag diagnostics | 8658-8744 | P | `missing-union-tag` (`{label} has no case %x`), `nested-missing-tag` replay | `types-missing-tag-*`, `types-nested-missing-tag` |
175+| `infer-fragment` | 8749-8980 | G | Synthesis by node kind (literals: `%ud` → `%nvar`, `%loobean` → `%flag`, term/null → `%tag` + `ipending`; ctor → `%tag … &`; `%unit`/`%list`/`%qath` require the exact prelude templates; `%wing` instantiates; `%cast` = shape + check-mode + width check + fit + merge faces; `%gate` monomorphic sample; `%call` → `infer-call-with-head`) | every typed golden; cell-branch, deferred, generic-pattern, qath-source [call] |
176+| Dead code | 8988-9000, 9058-9063, 10780-10783 | O | `width-has-projections`, `infer-width-elaboration`, `direct-find-gate`, `resolve-supported-defs` | none |
177+| Direct gate-layout evidence | 9002-9228 | R | R11 | direct-gate-guards [call] |
178+| Call checking | 9230-9294, 9296-9314 | G | Head first; known `%fn`: context args, width, fit (`itype-fit-inner … skip-width` for multi-arg), else `direct-gate-call-fit`; `%unknown` → `call constraint…` (or a `dgo` in defer mode); `%bad` → missing tag → nested tag → `call's sample and argument types do not unify` (`call-error-site` blame); face-propagation guard 9283-9288. Unknown head: unify with `[%fn arg fresh]` | 116 golden lines `call's sample…` in 53 goldens; positional-face-guards |
179+| Contextual call and singleton/unit/tagged-case | 9316-9562 | R/G | `infer-unit-context` 9321, `infer-contextual-call` 9355 (pre-unify product with expected; `element` exception), `explicit-singleton-in-union` 9480, `contextual-*` 9501-9562 (R15), `grec-direct-context` 9527 | nested-union-guards, constructor-fit-guards [call]; `types-nested-union-context`, `types-unit-context` |
180+| `proj` intrinsic | 9396-9475 | O | `explicit-proj-call`, `infer-proj-context` (check mode only), literal fields by name | proj-guards; `types-proj-*` |
181+| Closed-cell branch retry | 9564-9662 | R | R14 | cell-branch [call]; `types-cell-branch-context` |
182+| Check-mode dispatcher | 9664-9783 | G | `infer-call-context-arg`, ~19 ordered steps (9667-9783): defer → unwrap pair/group/body/trace → peel faces → `proj` → grec ctor → jrec `~`/tuple → call → empty list → structured/cell patterns → loobean singleton → known-union branch → unit → closed-cell → flag/union/list branch → list literal → tagged case → cell tuple → synth. Reads the raw `expected` at 9732, 9743, 9756 to keep provenance (A36). Callers do the final fit | generic-construction, qath-fuel [call] |
183+| Positional items, cell binders | 9785-9928 | G | `infer-call-context-items/-args`, `projection-field-target` (peels one slot face), `infer-simple-items`, `infer-cell-branch` | `types-cell-pattern-*`, `types-multi-call` |
184+| Printers | 9930-10032 | P | `show-itype` (A-Z then T26…; six identical variable arms 9936-9951, A35), `show-itype-cases`, `site-type-note` (bare label for vars, nvar, tags, unions, hidden recursion) | every typed golden; 11 suites [call] |
185+
186+#### D. Definition boundary and module resolver (10034-10900)
187+
188+| Family | Lines | Cat | How it works | Tests |
189+| --- | --- | --- | --- | --- |
190+| Capital and atom-var guards | 10034-10169 | G | `merged-capitals` 10072, `constrained-capitals` 10089 (capital bound to non-var or shared → "explicit capital constraints are not supported"), `atom-var-from-cap`, `atom-var-from-binder`, `unsupported-atom-vars` 10159 (atom vars generalize only from caps or `binders`) | deferred [call]; `types-capital-distinct`, `types-partial-explicit-capital`, `types-partial-aura-*` |
191+| Constraint printing | 10171-10191 | P | `show-atom-constraint`: ` where A is an atom other than ?` / ` is an atom` / ` contains no gates` | all typed goldens with constrained vars |
192+| Names, dependencies | 10193-10214, 10327-10428 | M | `global-value-names`, `unique-value-name`, `dependency-expr` (syntactic, ignores binders, errs closed) | `types-partial-forward`, `types-scope-*` |
193+| Single recursion | 10216-10325 | G | `infer-recursive-gate` 10285: monomorphic `[%fn sam seed-or-fresh]`, body, unify product; `recursive-branch-seed` 10254 (closed base arm of a one-self-call loobean branch); refuses in defer mode; clears `gate-defs` | `types-recursive-*`, `types-local-recursive` |
194+| Mutual recursion groups | 10430-10533 | G | `seed-gate-group`, `infer-gate-group-bodies`, `group-schemes` (short merged-capital text 10495), `infer-gate-group` 10509 (rejects projections, holes, pending tags) | `types-recursion-scc-*`, `types-local-scc*` |
195+| Projection finalization | 10535-10549 | O | `width-finalize` | `types-proj-*` |
196+| Kosaraju SCC | 10552-10643 | M | Work-list DFS; components dependencies-first; duplicates → no components | `types-recursion-scc-order`, `types-value-cycles` |
197+| Resolver fixpoint and finalization | 10645-10778 | M | `add-groups`, `resolve-groups`, `add-supported-result`, `add-supported-defs-core`, `resolve-groups-core`, `dependency-order` (see 1.2(b) step 6, 2.7, 2.8) | all full-check suites; `module-import-*` |
198+| Failure diagnostics, value cycles | 10711-10734, 10785-10900 | P | `module-pending-tag` 10715; `definite-value-cycles` 10885 (report only) | buttons, program-init, program-update; `types-value-cycle*` |
199+
200+#### E. Union analysis and module checker (10902-12600)
201+
202+| Family | Lines | Cat | How it works | Tests |
203+| --- | --- | --- | --- | --- |
204+| Union projection and relation | 10904-11022, 11275-11286 | U | `project-union-mold` (local refs only, `seen` list), `union-relate` (`?` = {0,1}), `union-pairs` O(n²) in (i, j) order | full-overlap-*, import-overlap; 73 goldens print `cases proven disjoint`, 12 `overlapping cases` |
205+| Source disjointness slice + state screen | 11024-11187 | R | R19 | union-source [call] |
206+| Overlap witness | 11189-11273, 11288-11302 | U | `mold-overlap-witness` 11296: first projected overlap, else (only if some pair unknown) `union-source-overlap` 256 | union-alias-overlap, full-overlap-basic [call] |
207+| Hole detection | 11304-11430 | G | `simple-mold-hole` (unit unit span), syntactic `*-has-hole` | hole-guards [call]; `types-hole-*` |
208+| Report printers and entry wrappers | 11431-11500 | P | `show-partial-mold`, `show-inference-diagnostic`, `show-duplicate-fields`, `duplicate-fields-report`, `golden-types`, `golden-types-imports` | all typed goldens |
209+| Duplicate fields | 11520-11693 | O | Pre-inference syntax pass; nested cell opens a new scope (A30); message `record field `x` is repeated` | `types-record-field-*` |
210+| Scope validity, reserved `proj` | 11694-11773 | M | `import-binding-names` (includes `/%` marks, A25), `reserved-proj-*`, `module-scope-valid` | proj-guards, deferred-resolver [call]; `types-proj-reserved-*` |
211+| Module mold elaboration | 11775-11824 | G | `module-mold-types(-detail)`: each mold from the same base state (ids may repeat across templates); first failure aborts; overlap evidence for a union | full-overlap-basic [call]; `module-cache-incomplete` |
212+| Prelude bootstrap | 11826-12024 | R | R21 | `prelude-*`, `types-prelude-*` |
213+| Partial prelude interface | 11913-11926, 12026-12112 | M | `partial-prelude-molds` drops failing molds silently; `prepare-prelude(-with-internal)` re-parse | 33 suites call `prepare-prelude-with-internal`; `tools/golden:291` |
214+| Completeness and failure naming | 12114-12188 | P | `module-values-complete`, `module-missing-value`, `module-sample-shadow` | `module-missing-value-*` |
215+| Import resolver and cache | 12190-12200, 12219-12228, 12275-12324 | M | Cycle check before cache; legacy entries rebuilt; reuse needs identical inputs | `module-import-*`, `module-cache-*`; full-overlap-graph, request-guards |
216+| Request-graph merge | 12202-12218, 12229-12274 | A | Set union of paths; dedup requests/stores; 256/256 bound (A27) | store [call], request-guards |
217+| API path extraction, derived names, typing | 12326-12615 | A | `+$ paths`/`+$ poke` declarations, `api-derived-clash`, `api-path-analysis(-source)`, `api-path-evidence-source` | api-paths, api-evidence, hole-guards, proj-guards [call]; `module-import-api-*` |
218+
219+#### F. API interfaces (12596-13144)
220+
221+| Family | Lines | Cat | How it works | Tests |
222+| --- | --- | --- | --- | --- |
223+| Path evidence | 12596-12652 | A | `api-path-evidence-source/-graph` (copies, A31), `api-path-watchability` | api-evidence [call] |
224+| Request components | 12654-12698 | A | `api-request-parameter-types`, `api-request-fold-type`, `api-request-parts` (argument order not fixed) | api-evidence [call], todo-api |
225+| Supporting definitions | 12700-12774 | A | `api-support-analysis-source/-graph` (copies): ordinary `resolve-groups` with a positional state | api-evidence [call] |
226+| Prelude shape certificates | 12776-12845 | A | `compatible-raw-poke`, `request-compatible-ask`: structural `=` on hard-coded itype nouns | store [call], ask-guards, sub-guards |
227+| Request interface constructors | 12847-12956, 13020-13075, 13099-13144 | A | `one-request-interface-source` (dead) and `-graph` (narrow branch, A44), `api-sur-covered`, `api-request-gates` (fuel 256), `multi-request-interface-graph`; hand-built `∀0` schemes | request-guards, todo-api, page-main, todo-full; `types-request-normal`, `module-import-api-request-reason` |
228+| Poke-only interface | 12958-13018, 13077-13097 | A | `api-poke-interface(-result)`, `api-poke-from-checked`, `api-mark-exports` | hole-guards, api-paths, proj-guards [call]; `module-import-api-poke-*` |
229+
230+#### G. Kind recognition and program/store recovery (13146-14648)
231+
232+| Family | Lines | Cat | How it works | Tests |
233+| --- | --- | --- | --- | --- |
234+| Main-call recognisers | 13146-13240 | M | `program-main-def`, `program-main-wing`, `program-main-args/-parts`, `page-main-parts`, `store-main-parts`: syntax, heads matched by name (four copies of one walk, A48) | program-main, program-watch, store, page-main [call] |
235+| Store declaration, derived-name clash | 13242-13309 | M/P | `store-declaration`, `derived-name-clash` (precedence: definition, import face, another derived name, prelude name) | store; `module-import-store-*`, `module-import-api-*-clash` |
236+| Transparency helpers | 13311-13340 | R | `program-empty-null`, `program-subs-empty`, `program-transparent` | program-main, page-main |
237+| Update, subs recovery | 13342-13606 | R | R1, R2 | via `infer-jibb-file(-detailed)` |
238+| Slot and relation helpers | 13452-13503 | R | `program-inferred-slot`, `program-two-slot-names`, `program-update-relation` | via recovery |
239+| Keyed view-site walker | 13608-13749 | R | R3 | todo-full |
240+| Element message fits | 13751-13853 | R | R7 | todo-full, store, buttons; `types-prelude-ui` |
241+| View recovery | 13855-14155 | R | R3, R4 | todo-full, store |
242+| Initializer | 14157-14312 | R | R5 | program-init |
243+| Derived request/store evidence | 14314-14470 | A | `derived-poke-command-scheme`, `store-derived-schemes`, `program-subs-watch` 14367, `derived-request-member` 14405-14441, `derived-store-request-member` 14443-14470: provenance certificates compared by `=` | store [call], program-watch, page-main |
244+| Program main completion, kind boundary | 14472-14582 | R/M | `program-main-context` (R6), `static-main-specialized` (R9), `page-load-derived`, `page-main-closed` (R10), `program-main-closed` (R6) | program-main, program-watch, store, page-main [call] |
245+| Store kind | 14584-14648 | R | R8 | store |
246+
247+#### H. Driver, report, dg, fresh ids, grec (14650-15838)
248+
249+| Family | Lines | Cat | How it works | Tests |
250+| --- | --- | --- | --- | --- |
251+| Module driver | 14650-14879 | M | 1.2(b) | 23 suites call `infer-jibb-file`, 12 `infer-jibb-file-detailed` |
252+| Mold analysis entry | 14881-14933 | O | `gate-free-mold-source` | gate-free-source [call] |
253+| Report adapters | 14935-15024 | P | `golden-types-with-modules` (dead, A42), `-with-prelude`, `-with-prelude-and-internal`, `-with-prepared-prelude`, `reader-result-for-checker`, `-with-reader-diagnostics`, `-with-marks`, `-in-context` | tools/golden, tools/ship; 24 suites |
254+| Report core | 15025-15146 | P | 1.2(a) | all 304 typed goldens; deferred-prepared [call] |
255+| dg-* | 15147-15656, 15704-15719 | R/G | R20 | deferred, deferred-context, deferred-prepared, deferred-resolver [call] |
256+| Fresh ids | 15658-15702 | G | `ienv-fresh-id` = one above the max id in env (declines on a pending `%tag`); stands in for a global fresh supply | deferred [call]; program recovery suites |
257+| grec trees | 15721-15835 | R | R18 | generic-*, union-source [call] |
258+
259+## 2. Inference today
260+
261+### 2.1 Unification and type comparison: one unifier, one fit, many special comparators
262+
263+| # | Comparator | Lines | Direction | What differs |
264+| --- | --- | --- | --- | --- |
265+| 1 | `itype-unify` | 4851-4940 | symmetric | The only structural unifier. Returns `(unit isub)` with no reason. Nominal rules: grec/jrec/recursive identity; union by origin then (argless) raw case equality or args; face names must match. Atom-kind lattice by pairwise cases 4884-4925. Never widens |
266+| 2 | `itype-fit` / `itype-fit-inner` | 5516-5711 | actual → expected | Widening (aura prefix, `@`, `*`, empty source), tag binding, ctor case selection; three-valued; calls unify for vars and as last resort. Gate types are compared by unify (invariant) except `itype-closed-gates-match` |
267+| 3 | `itype-fit-cases`, `itype-fit-ctor-cases` | 5451-5514 | actual → union cases | Each case tried from the original sub; unique `%ok` wins, two → `%unknown` |
268+| 4 | `itype-closed-gates-match` | 5229-5263 | symmetric, closed only | Gate equality modulo one omitted outer sample-slot face; all unifies from empty sub |
269+| 5 | `direct-invariant` | 9097 | both ways | Fit forward and backward plus a face-asymmetry test; 19 call sites, 16 in program/store recovery |
270+| 6 | `direct-function-fit`, `direct-positional-fit` | 9107, 9142 | both ways per slot | Two-slot gate samples matched with binder-face stripping, then replay must leave `sub`/`next` unchanged |
271+| 7 | `program-union-tag-case`, `program-single-case-fit`, `program-single-generic-fit`, `program-keyed-product-fit` | 13751-13853 | element messages | Select the one literal-tagged case, fit head and tail; element covariance only for a single case |
272+| 8 | `contextual-tagged-case` | 9545 | expected union | Unique const-headed case by head noun |
273+| 9 | Structural `=` on itype | 12782, 12805, 14314-14349, 14408-14470, 14599-14648; `infer-closed-cell-branch` 9616; `dg-stable-fit` 15427; `dg-stage-one` 22-field state equality 15458-15479; `program-init-model` replay 14163-14213 | exact | Prelude certificates and "stability" checks substitute for constraint solving |
274+| 10 | `union-relate` | 10994 | pattern overlap | Not a type relation; noun-shape projection used for disjointness |
275+
276+### 2.2 Substitution
277+
278+- Representation: `isub` assoc list (4688), prepended, never compressed; `itype-lookup` 4691 linear.
279+- Head walk: `itype-walk` 4698-4732, six identical arms (`%var|%fvar`, `%avar`, `%rvar`, `%nvar`, `%rnvar`, `%tag`) that stop at a self-binding to `%fvar`/`%rvar`/`%rnvar` (A16). Self-bindings are created at 4887-4889 (nvar~rvar), 4962 (gate-free form) and in `promote-restricted-numbers` (6119-6131). Any other self-binding loops forever (no fuel).
280+- Second walker: `dg-scan` 15150-15178 follows the sub with fuel; recognises only `%rvar`/`%rnvar` self-bindings, so an `%fvar` self-binding burns fuel and declines.
281+- Full application: `itype-normalize` 6012 (95 call sites); leaves `%tag`, `%recursive`, `%jrec` unexpanded.
282+- Whole-sub scans used as provenance screens: `contextual-simple-sub` 9519 (unbounded), `closed-cell-sub-safe` 9592 (512), `grec-direct-context` 9527 (4,096), `union-state-sub-budget` 11147 (256). Each declines if *any* entry binds a structural type, so behaviour depends on inference order.
283+- Mold-level substitutions (not the type substitution): `bind-params` 6873 (param name → arg type, by re-elaboration), `template-apply-sub` 6882 (rename scheme vars to args), `union-overlap-case` 11206 (tvar → arg pattern).
284+- Rollback is implicit: speculative attempts drop their returned state (`known-union-subject` 8541, closed-cell retry, tagged-case retry 9768-9774, direct-gate replay, `infer-recursive-gate` retry, failed locals).
285+
286+### 2.3 Generalization: six sites, four rules
287+
288+| Site | Lines | Rule |
289+| --- | --- | --- |
290+| Top level (`add-supported-result`) | 10682 | Quantify **every** variable of the normalized type. Sound only because each definition starts at `next=0` (10699) and the env holds closed schemes |
291+| Report (`golden-types-in-context-core`) | 15141 | Same, copied |
292+| Locals (`infer-local-defs`) | 7677-7681 | Type vars minus `free-env-vars(env)` (7307: normalizes every non-quantified var of every env scheme) minus `free-cap-vars(enclosing caps)` (7320) |
293+| Groups (`group-schemes`) | 10502-10504 | Same rule with the outer state's caps |
294+| dg (`dg-generalize`) | 15222 (called 15482) | Vars of the normalized type minus "blocked" = env-free (`dg-env` 15187, whole env scan) + obligation vars + tag-reachable vars (`dg-tags` 15209) + captured; bounded scan 32,768; ≤64 edges |
295+| Molds (`infer-mold-template`) | 6970-7000 | Exactly the fresh param ids; a nongeneric mold must be closed |
296+| Hand-built schemes | 12889, 12943, 13068, 14349, `store-derived-schemes` 14351 | `[… ~[0]]` literals |
297+| Recovery publication | via `add-supported-result` in 13444, 13600, 13927, 14107, 14149, 14306 | Then require `vars ~` and no `itype-vars` (closed-only) |
298+
299+Instantiation is one arm, `instantiate-scheme` 6355 (fresh ids from `next`, kind precedence, fresh atom/gate-free ids pushed onto `binders`, which is what lets `types-partial-atom-alias` re-generalize), plus `template-apply(-sub)` for molds and `itype-rename` 6219. Fresh ids for env-mixing code come from `ienv-fresh-id` 15666 (program recovery 13381, 13543, 13894, 14008, 14271; dg roots 15607, 15649).
300+
301+### 2.4 Branch joins: one join, several non-joins
302+
303+- Join rule (Q11, A133 fixed in 38c711c): `itype-branch-join` 5138 (two arms) and `itype-branch-join-list` 5202 (n arms), falling back to `itype-concrete-join` 5125. Callers: 8029 (list), 8073 (unit), 8226 and 8314 (union folds), 8919 (loobean; failures classified into five messages 8921-8929), 15333 (dg boolean).
304+- Checking-mode branches do not join; each arm is fitted to the expected type and the result is `expected`: `infer-union-context` 7763, `infer-known-union-context-whole` 8246, `infer-known-union-finite` with expected 8292, `infer-single-case-branch` 8361, `infer-cell-branch` 9894, `infer-unit-branch`/`infer-list-branch` with expected (A133 note).
305+- Other "joins": open list literal items are fitted to one element var (`infer-open-list-items` 7879, messages `list item widening is not supported` / `list items do not have compatible types`); `infer-closed-cell-branch` 9616 requires the two arm results to be equal and closed; `dg-boolean-branch` 15316 falls back to a fresh result var with two `dgo` edges.
306+
307+### 2.5 Pending constraints (no queue)
308+
309+| Constraint | Where held | Created | Checked | Outcome when unresolved |
310+| --- | --- | --- | --- | --- |
311+| Tag/`~` literal, ctor | `istate.tags` (`ipending`) + `%tag` pseudo-var | 8780, 8781, 8848 | end of each definition: `pending-tags`/`pending-null` 5351-5370 | locals wait (7673); top level dropped (10680); report prints `tag needs context` / `` `~` needs context `` (15131-15134); groups fail (10529); dg fails (15503); full check explains with `module-pending-tag` 10715 |
312+| Type hole | `istate.holes` (`ihole`) | 7103 | `default-hole-numbers` 6133, `unresolved-hole` 6168 | error (locals, report) or drop (top level); groups reject any new hole (10527) |
313+| Decimal literal | `%nvar`/`%rnvar` | 8773 | `default-decimals` 6062 at top level (10679), report (15130), `width-finalize` | locals do **not** default before generalizing; groups/dg reject `%nvar` (10499, 15481) |
314+| Atom-kind var | `%avar`/`%rvar` + `binders` | 5666, 4887, `instantiate-scheme` | `unsupported-atom-vars` 10159 | locals wait; top level drop; report `unresolved aura-variable inference` |
315+| Written capitals | `istate.caps` | `reserve-def-caps` 7509 | `merged-capitals` 10072, `constrained-capitals` 10089 | definite error (locals, report) or drop |
316+| `proj` | `istate.projections` | 9461 | `width-finalize` 10535 | drop / report message; groups reject |
317+| Call/cast fit `%unknown` | nowhere |: | immediately | `call/cast constraint is not supported…`; in defer mode a `dgo` |
318+| Deferred fit edges | `istate.obligations` (`dgo`) | 9262-9265, 15316, 15355 | `dg-replay-edges` 15252 at transaction close | whole transaction declines; outside dg any obligation is an error (7661) |
319+
320+Nothing carries a constraint from one definition to the next except the dg transaction. A later definition (e.g. `main`) can never fix an earlier definition's tag; that is why the program recovery arms exist.
321+
322+### 2.6 Order of solving
323+
324+Synthesis is left-to-right and eager: every fit is decided when it is met, with `%unknown` meaning "give up". Expected types flow only through `infer-call-context-arg` 9664 and its ~19-step ladder; casts and known call samples are the only sources of context.
325+
326+### 2.7 Fixpoints and retries
327+
328+| Loop | Lines | Bound | Notes |
329+| --- | --- | --- | --- |
330+| Module resolver | 10749-10756 | env stops changing | One productive pass in dependency order (839f6b0) plus a confirming pass; fixpoint kept as fallback (A135) |
331+| `add-supported-defs-core` | 10690-10709 | one pass | Retries `infer-recursive-gate` after every failed `infer-fragment` (10705), gate or not (A33) |
332+| `add-groups` | 10645-10660 | one pass per resolver iteration | Errors discarded |
333+| Locals | 7624-7639 | progress | Pass loop; then `graph-components` + `try-local-group` 7686; then the order-independence rules decide definite vs `local definitions need unsupported inference` (7637) |
334+| dg-stage | 15496-15522 | ≤64 defs, fuel² = 4,096 attempts | Retry `(flop waiting)`; close: replay edges twice and require unchanged `sub`/`next` (15501-15510) |
335+| Program recovery | 14786-14804 | single pass | No fixpoint; order matters |
336+| Report | 15079-15146 | one pass | Re-infers every non-group definition after resolution |
337+| `module-pending-tag` | 10715-10734 | fuel 64 | Failure-path re-inference only |
338+| Replay "stability" checks | 9142/9191 (direct gate), 9616 (closed cell), 14163-14213 (init model), 15501-15510 (dg) |: | Stand-ins for "the constraints are solved" |
339+
340+### 2.8 Definition finalization: five copies
341+
342+| Step | `add-supported-result` 10670 | report 15117 | locals 7659 | groups 10488/10509 | `dg-stage-one` 15445 |
343+| --- | --- | --- | --- | --- | --- |
344+| obligations unchanged |: |: | 7661 | refuses defer 10512 | collects them |
345+| `promote-restricted-numbers` | 10675 | 15117 | 7662 |: |: |
346+| `default-hole-numbers` | 10676 | 15118 | 7663 | holes must not change 10527 | holes unchanged 15477 |
347+| `unresolved-hole` | 10677 drop | 15119 message | 7664 fail |: |: |
348+| `merged-capitals` |: (only via constrained) | 15122 long text | 7666-7669 long text | 10493-10495 short text | any written capital declines 15452 |
349+| `constrained-capitals` | 10678 | 15128 | 7670 | 10496 |: |
350+| `default-decimals` | 10679 | 15130 | **none** | nvar → fail 10499 | nvar → decline 15481 |
351+| `pending-null` |: | 15131 |: |: |: |
352+| pending tags / tag in type | 10680 drop | 15133 | 7673 wait | 10529, 10500 | blocks generalization; 15503 at close |
353+| hidden recursive/generic name |: | 15135-15138 |: | 10500 | `dg-interface-safe` 15573 at publish |
354+| `unsupported-atom-vars` | 10681 drop | 15139 | 7675 wait | 10500 | 15480 |
355+| quantify | all vars 10682 | all vars 15141 | minus env/caps 7677-7680 | minus env/outer caps 10502-10504 | `dg-generalize` 15482 |
356+| `width-finalize` | 10683 | 15142 | (left to the enclosing definition) | projections must not change 10525 | projections unchanged 15479 |
357+
358+## 3. Recovery slices
359+
360+"Would fail if removed today": `[call]` suites name the slice's arms and stop compiling if the arms go; `[out]` suites or goldens whose expected output depends on the path (from fixtures; not executed). **No typed golden reaches R1-R10, R18 or the full-check side of R20**, because the report (15025) runs no recovery, no kind check and no grec index, and the only goldens whose case-local modules have a `main` (`module-import-api-import-error`, `module-import-store-derived-clash`, `module-import-store-face-clash`, all importing a cart store) stop at the derived-name clash before inference. Those slices are pinned only by `tests/lib`.
361+
362+### 3.1 Example-fitted slices
363+
364+| # | Slice | Lines | Serves | Does instead of ordinary inference | Would fail if removed |
365+| --- | --- | --- | --- | --- | --- |
366+| R1 | Update recovery `program-update-context` | 13342-13450 | Todo island `update` (`my-app/ui/todo-list.jibb:16-25`) and basket `update`: bodies end in `[m ~]` and `\|=%acked`, whose tags have no context inside the definition, so `add-supported-result` drops them (10680) | Reads message/model from the written two-slot sample (binder faces stripped), builds `[model (list (cmd message))]` from prelude templates, proves it against program's instantiated slot with `direct-invariant`, checks the body in context, casts, merges faces, publishes only a closed scheme | [out] program-update (all `tests/type-program-update/*`), todo-full, store (basket), page-main (`index.jibb` imports `todo-list`), program-init (needs the update relation) |
367+| R2 | Subs recovery `program-subs-context` | 13505-13606 | Todo `subs ~[[%watch (todos.todo \|=%got)]]`, basket `(state.cart \|=%got)` | Same pattern with `(list (sub message))` and program slot 4 | [out] todo-full, store, page-main, program-init (`initializer-subs`) |
368+| R3 | Keyed view recovery `program-view-context` + view-site walker | 13608-13749, 13938-14155 | Todo `view` with exactly one `each (turn todos.m row-of)` and the mapper `row-of` | Finds the site syntactically, instantiates `each`/`turn`, infers the mapper and the view against hand-built `element message` types, publishes both mapper and view | [out] todo-full (`expected`, `alias`, `ambiguous-mapper`, `open-key`, `non-gate-view`, `wrong-*`), page-main, program-init (`initializer-open-view`) |
369+| R4 | Plain view `program-plain-view-context` | 13855-13936 | Basket `view` (no keyed site, 4bf477e) | Checks the body against `(element message)`; does not check program slot 3 (A48 drift) | [out] store (basket) |
370+| R5 | Initializer `program-init-model`, `program-init-ordinary`, `program-plain-init-context` | 14157-14312 | Todo `init \|= ts=(list item.todo) [ts "" ~]` (`~` needs context), basket `init \|= ~` | Model from the update relation or from a tentative positional fit of main's args (`direct-positional-fit` + replay stability), then context check of the body; ordinary fallback in a separate state | [out] program-init (17 `initializer*` fixtures), todo-full (`cast-init` guards ordering), store, page-main |
371+| R6 | Main completion and program kind check `program-main-context`, `program-main-closed`, `program-subs-watch`, `program-subs-empty` | 13311-13340, 14367-14403, 14472-14482, 14555-14582 | Any direct `(program i u v s)` main | Re-infers `main` after recovery (only agreement check); kind check instantiates program from `*istate`, requires closed invariant main, gate-free init data and model (256 shared budget), and one syntactic watch shape | [call] program-main, program-watch, store (`program-main-closed`); [out] program-main, program-watch, todo-full, store, page-main, program-update/init |
372+| R7 | Element message fits and the list-item hook | 7887-7891, 7909-7913, 9355-9394 (element exception in `infer-contextual-call`), 13751-13853 | Todo union controls (`button "Add" %submit`, `field … \|=%typed`), raw constructors (docs/compiler.md:153) | When an ordinary list-item fit to a prelude `element` union fails, prove the message argument invariantly or pick the single literal case; pre-unify recursive `element` results | [out] todo-full, store, buttons; goldens `types-prelude-ui` (`bad-child` and element lines), probably `doc-grammar-02-buttons` (`labelled`) |
373+| R8 | Store kind and main recovery `store-update-unfaced`, `store-main-closed` | 14584-14648, swap 14844-14849, completeness exception 14817-14819 | Cart store `my-app/ui/stores/cart.jibb` ("The builder erases the action from main", 14597) | Checks prelude `store` value and mold by `=`, checks init/update against local `state`/`poke` invariantly, publishes `[canonical ~]` as `main` even if `main` never inferred | [out] store (cart, basket); compiler.md:143 |
374+| R9 | Static main `static-main-specialized` | 14484-14508, swap 14836-14843 | `about.jibb` `++ main view` | Instantiates main from `*istate`, fits into `(element !!)`, publishes the canonical closed scheme | [out] page-main (about, `wrong-static`) |
375+| R10 | Page kind `page-load-derived`, `page-main-closed` | 14510-14553 | `index.jibb`, `blog/index.jibb` | One syntactic load shape `case.face reply`, provenance via `derived-request-member` | [call] page-main |
376+| R11 | Direct gate-layout evidence `direct-*`, `istate.gate-defs/head-evidence` | 9002-9228; set at 10701-10702, 15108-15109, recovery arms | `(program init update view subs)` with a faced `update \|= [=msg m=model]` against prelude `update=$-([M X] …)` (`prelude.jibb:534`) | After an ordinary call fit is not `%ok`, re-parse the prelude (A132), match written gate samples slot by slot, both ways, then replay | [call] direct-gate-guards; [out] direct-gate-source (`tests/type-direct-gate`), program-main, program-update, todo-full; golden probably `types-prelude-ui` `++ concrete-program` (line 72 of its source) since the report sets `gate-defs` |
377+| R12 | Closed gate sample matching | 5229-5263 (called 5701, 5316) | Todo API named closed fold gates (a1c5f35; contract 4643-4644, 4653-4655) | Gate equality ignoring one outer slot face | [out] closed-gate-guards (through `itype-fit`), todo-api, todo-full, program-watch, page-main |
378+| R13 | Positional face rule | 5313-5349, 9285 | `like` result mapping (640a442) | Ignore one sample-slot face per written argument | [call] positional-face-guards, direct-gate-guards; goldens `types-positional-faces`, `types-prelude-like` |
379+| R14 | Closed-cell branch retry | 9564-9662, dispatch 9743 | Todo `update` inner `?- (gth …)` returning `[m(...) ~]` (22f3788) | Re-check a two-loobean branch against a cell target from the original state; results must be equal, closed, tag-free; replay | [call] cell-branch; golden `types-cell-branch-context`; [out] todo-full |
380+| R15 | Contextual tagged case | 9477-9562 (`contextual-tagged-case` 9545), dispatch 9753-9780 | Todo `subs` body `~[[%watch (todos.todo \|=%got)]]` (72acdb3) | Try ordinary inference; else select the union case by literal head and check the payload in context | [call] nested-union-guards; goldens `types-nested-union-context`, `types-nested-shallow-preserve`; [out] todo-full |
381+| R16 | `infer-contextual-call` element exception | 9355-9394 | Todo controls, `\|=%got` callbacks | Pre-unify a same-origin generic union result with the expected type; recursive only for prelude `element` | goldens `types-generic-result-context`, `types-prelude-ui` (likely); [out] todo-full |
382+| R17 | `%jrec` / qath | 4680, 6925-6952, 8392-8420, 8757-8763, 8807-8821, 9699-9714 | Internal prelude `qath` (`internal.jibb:15-17`, 0ea700d); theme `font=` qath literal; `image`/`link` | Recognise `~ / [h=@aura t=self]`, unfold one layer per fuel (256 per definition) for matching, construction and static path literals | [call] qath-fuel; qath-source, theme; goldens `types-qath-*`, `types-arithmetic-proj-qath`, `types-prelude-ui` (`image-scheme`, `link-scheme` print `qath`) |
383+| R18 | `%grec` generic tree | 4681, 6954-6968, 8422-8475, 9527-9539, 9684-9698, 15721-15835, 4801 | Test-only node tree (`tests/type-generic-recursion`, c96597d) | Fixed two-case shape proof; one-layer view for patterns/construction; index only for import-free prelude-backed modules (14762-14772) | [call] generic-recursion, generic-construction, generic-pattern, union-source; golden `types-generic-recursive-union` only as an unsupported control |
384+| R19 | Union source disjointness, state screen, source overlap witness | 11024-11187, 11189-11273 | One-hop local generic alias with a literal head (b93a94b) | Bounded syntactic proof of distinct heads / positive overlap when projection is unknown | [call] union-source, union-alias-overlap, full-overlap-basic; goldens `types-union-source-alias`, `types-prelude-succ` |
385+| R20 | dg-* deferred transaction | 15147-15656, 15704-15719; hooks 8854, 8879, 8951, 9261-9265, 9281, 9667-9669, 10288, 10512 | Import-free modules without a prelude (full check, 14807-14816); prepared-prelude reports whose fixture is the todo initializer `[xs "" ~]` closed by a later cast (`tests/type-deferred-prepared/good.txt`) | Re-infer definitions with obligation edges for literal branch arms, tuple items and ctor args, retry to a fixpoint, replay edges twice | [call] deferred, deferred-context, deferred-prepared, deferred-resolver; goldens `types-constructor-context`, `types-union-singleton` reach the screens but the transaction declines (report unchanged) |
386+| R21 | Prelude bootstrap | 11826-12024 | `prelude.jibb`, `internal.jibb` | `standard-prelude-list` pattern-matches `\|$ [A] $@(~ [i=A t=(list A)])` and publishes `%collection`; six hard-coded primitive schemes (11930); `infer-private-internal` proof retry; `prelude-label*` | all module-check goldens and 33 suites that prepare the prelude |
387+| R22 | API narrow branch `one-request-interface-graph` | 12904-12956, 14711-14721 | Blog API (one mark import, non-union paths) | Hand-built one-request interface; redundant with multi-request (A44); `one-request-interface-source` 12850 is dead | [out] page-main (blog API), request-guards |
388+
389+### 3.2 Ad hoc slices of general inference (not fitted to one example, but replaced by the core)
390+
391+| Slice | Lines | Replaced by |
392+| --- | --- | --- |
393+| Two-arm unit/list branches | 7923-8075 | usefulness over `~`/cell constructors |
394+| Three coverage loops + 64-row loobean expansion | 8103-8350 | usefulness |
395+| One-arm structured / cell-binder / empty-list / empty-union | 8351-8390, 8555-8608, 9852-9928 | one-row usefulness, empty types have no constructors |
396+| Speculative subject screens | 8477-8549 | infer subject once |
397+| `recursive-branch-seed`, blanket `infer-recursive-gate` retry | 10216-10325, 10705, 10729, 7646 | SCC let-rec with levels |
398+| `known-union-subject` double inference | 8541 |: |
399+| Loobean join failure classification | 8920-8929 | one join + deferred widen |
400+| Import-invalid replay | 7002-7097 | elaboration returning reasons |
401+| `module-pending-tag`, `module-missing-value`, `module-sample-shadow` | 10715, 12132, 12171 | per-definition errors from the core |
402+| Order-independence rules for locals | 7521-7584, 7633-7637 | SCC order + deferral |
403+
404+## 4. What the core replaces, what it must keep, and the hazards
405+
406+### 4.1 Replaced
407+
408+| Core piece | Replaces |
409+| --- | --- |
410+| Union-find store over a map, path compression, one global fresh counter | `isub`/`ibinding` 4687-4688, `itype-lookup` 4691, `itype-walk` 4698-4732, `dg-scan` 15150, `ienv-fresh-id` 15666-15702, per-definition `next=0` (10699, 10752, 14759, 15107) |
411+| Kind on the root (any ⊐ gate-free ⊐ atom ⊐ atom-other-than-? / defaultable number) | `%fvar %avar %rvar %nvar %rnvar` (4666-4670), the pairwise lattice 4884-4925, self-binding refinement (4887-4889, 4962, 6119-6131), `itype-bind-gate-free` 4998 and its 256 budget, `itype-var-is-*` 6267-6343, `binders` bookkeeping for `unsupported-atom-vars` 10159 |
412+| Levels | `free-env-vars` 7307, `free-cap-vars` 7320, `shared-types`/`shared-moved`/`closed-local` 7534-7584, `dg-env` 15187, `dg-generalize` 15222, all-var quantification 10682/15141 |
413+| Deferred-constraint queue (woken on binding, reported at module end) | `%tag` + `ipending` + `pending-tags`/`pending-null` 5351-5370 + drop at 10680 + `module-pending-tag` 10715; holes 6133-6181 (as level-exit obligations); decimal defaulting 6062 and promotion 6119 (as level-exit defaulting); fit `%unknown` (5527-5711) as "enqueue"; `itype-fit-ctor-cases` 5474; field access 7720, change 8622, interpolation 8081, `proj` 9461, cell/cons literals 7834; the whole dg-* transaction 15147-15719 and its hooks |
414+| Bidirectional check mode (synthesize then unify/subsume with expected; push expected into arms and items) | most of `infer-call-context-arg` 9664-9783: contextual branches 7749-7921, unit context 9321, singleton 9480, tagged case 9477-9562, closed-cell retry 9564-9662, `infer-contextual-call` pre-unify 9355 |
415+| Maranget usefulness over a constructor signature taken from the subject type | 7923-8075, 8103-8390, 8395, 8425-8475, 8477-8608, 9852-9928, `dg-boolean-patterns` 15292; branch routing 8878-8930 |
416+| One nominal recursive mold `(module, name, args)` unfolded on demand | `%recursive`/`%jrec`/`%grec` 4679-4681, `simple-source-recursive` 6925, `simple-source-generic-recursive` 6954, `jrec-match-view`, `qath-static-fuel`, grec 15721-15835, `jrec-fuel` |
417+| SCC driver, one pass, scheme-or-error per definition | `resolve-groups-core` fixpoint 10736-10756, `add-supported-defs-core` retries, `add-groups`, locals' pass loop 7611-7681, `try-local-group` 7686, `dg-stage` 15487 |
418+| `main` as an ordinary application, sample-slot faces as labels | program chain 13342-14482, `direct-*` 9002-9228, `itype-closed-gates-match` 5229-5263, positional face rules 5313-5349, element fits 13751-13853 and hooks 7887-7891/7909-7913, `static-main-specialized` 14487, store component recovery 14599-14648 |
419+| One pipeline (Q6) | report re-inference 15079-15146; its separate finalization 15117-15143 |
420+| Five finalization copies (2.8) | one generalization step at level exit |
421+
422+### 4.2 Kept (retargeted to the new representation, behaviour preserved)
423+
424+- **Printers**: `show-itype` 9930-9995 (A-Z then T26…, `(label args)`, space-separated unnamed unions, parenthesised in context), `site-type-note` 10024, `show-atom-constraint` 10171, `canonical-itype` 6345 with `itype-vars` order 6183 (fn sample before product, head before tail, union args before cases) and kind precedence rvar > avar > fvar > var, `show-partial-mold` 11431 (until Q6 changes the report), `show-inference-diagnostic` 11458, `show-duplicate-fields` 11470, `prelude-label*` 11870-11911, `itype-in-import` labels 6806 (display separate from identity).
425+- **Error wording and site notes** (golden-pinned; full list in 4.3).
426+- **API path analysis and derived interfaces**: 12326-13144 and 14314-14470, `derived-name-clash` 13289, request-graph 12202-12274, watchability; they synthesize schemes into interfaces before consumers are checked. The hand-built schemes should become instantiations of declared templates.
427+- **Hoon importer bridge**: 6397-6728 plus `jibb-dev/lib/jibb-import.hoon`; the import-invalid wording (`invalid imported mold` + importer message).
428+- **Overlap witness and disjointness**: `upat`/`union-relate`/`union-pairs` 10904-11022/11275, `mold-overlap-witness` 11296, `module-mold-overlap` 11786, `jfile-overlap` 11513 evidence. `union-relate` is also the importer's disjointness relation (6477, 6665), so either keep `upat` as the importer projection or give itype a pattern view.
429+- **Pre-inference passes**: duplicate fields 11520-11693, scope and reserved `proj` 11694-11773, dependency extraction 10327-10428, Kosaraju 10552-10643, value-cycle diagnosis 10785-10900 (wording), module graph and cache 12190-12324.
430+- **Elaboration**: `infer-simple-shape` 7099 / `infer-mold-template` 6970 / `label-direct-union` 6843 (mold → type, origin assignment), `proj` planning 5835-5923, 9396-9475, `width-finalize` 10535 (artifacts), `gate-free-type` 5925-5992 as a post-solve check with witness path.
431+- **Kind boundary** as post-solve matching of `main`'s closed type against prelude molds; watch/load provenance checks; store-derived exports.
432+
433+### 4.3 Hazards
434+
435+1. **Golden output moves.** All 304 `types.txt` come from the report path. Pinned fail-closed lines: 80 `tag needs context in partial inference`, 24 `` `~` needs context ``, 32 `call constraint is not supported…`, 37 `cast constraint…`, 5 `record width constraint…`, 5 `proj constraint…`, 6 `type hole needs unsupported inference`, 6 `unresolved aura-variable inference`, 4 `call result face propagation`, 31 `local definitions need unsupported inference`, 47 `name is not available to partial inference`; 127 goldens contain some unsupported text. Mold lines: 171 `+$ X: not checked`, 171 `cases proven disjoint; mold not checked`, 6 `case disjointness unresolved`, 22 `overlapping cases`. A stronger core changes these; each stage must either keep the exact `%unknown` sites or budget a deliberate golden update (Q6 predicts ~283 outputs change once).
436+2. **Definite wording to keep byte-exact**: `call's sample and argument types do not unify` + `called gate`/`argument` (116 golden lines, 53 goldens); `branch arms have incompatible types` + `first arm`/`second arm`; `cast mold and expression type do not unify` + `cast mold`/`expression`; `{label} has no case `%x`` + `expected union`/`tag` (8706); `record has no field `x`` + `unknown field`; `change field and replacement do not unify`; `a change takes at least one field` + `empty change`; `missing union case X` (no sites, first remaining case); `branch arm is covered by earlier arms` + `covered arm`; `branch does not cover both loobeans`; `nothing fixes the union of %x` (5363; `tests/type-buttons/error.txt`, program-init, program-update; not in any golden); `non-gate value depends on itself through a cycle` + `value in cycle`/`dependency in cycle`; the long capitals message (7669, 15126) vs the short one (10495); `type hole needs a determined type` + `unresolved type hole`; `a generic atom in interpolation needs an aura`, `a cell in interpolation needs a printer`; `record field `x` is repeated` + `first field`/`repeated field`; derived-name clash texts; module/API texts in 1.2(b).
437+3. **Sites decide definiteness.** `definite-diag` 7521 treats site-less diags as retryable; several definite-sounding errors have no sites (`missing union case`, `pattern binder shadows a name`, `unit present pattern is unreachable`, `sample shadows a name`). Adding sites changes local-definition outcomes (they stop ending as `local definitions need unsupported inference`).
438+4. **Message precedence is order-dependent**: report checks 15117-15143 in fixed order; loobean join classification 8921-8929; missing tag → nested tag → generic after every `%bad`; union coverage checks `%unknown` before coverage and `covered` before `not supported` (A15); locals report the earliest failing local (`rear sure`, 7636); finite expansion prints `%.n` rows before `%.y`; the full check reports pending tag, then shadowing sample, then missing value (14821-14832); API precedence poke-only → clash → scope → import error → constructor reason.
439+5. **Unification semantics goldens rely on**: unequal atoms never unify; argful named unions unify by args only, argless by raw case equality (A11); `%var` binds faces, unions, tags; a `%tag` vs non-var fails in unify; faces must match by name; fit is invariant for gates; `*` accepts gates (A23, pending Q18) and binds bare tags (A22); term literal fits `@tas`/`@ta` with no aura check (A20); `?` vs `@f` is unknown; zero vs list unknown; only `@` allocates in fit.
440+6. **Self-binding invariant**: any self-binding other than `%fvar`/`%rvar`/`%rnvar` loops `itype-walk`. A staged migration that keeps `isub` alongside a union-find store must keep this invariant or convert at the boundary.
441+7. **Ids**: ids restart at 0 per top-level definition, `itype-rename` is single-pass, so scheme ids may coincide with fresh ids by design (6008-6010); `module-mold-types` reuses one base state per mold, so template ids repeat. A union-find store must never assume scheme ids are globally unique; instantiate always.
442+8. **Rollback**: speculative attempts drop state; tests assert that failed retries return the original result and replays leave `sub`/`next` byte-identical (cell-branch, direct-gate-guards, deferred). A mutable store needs a trail/snapshot or a persistent map.
443+9. **Provenance screens**: grec, tagged-case and closed-cell screens decline if any substitution entry is structural; `infer-call-context-arg` reads raw `expected` at 9732, 9743, 9756. Behaviour of these slices depends on inference order; a new store changes when they fire.
444+10. **Budgets pinned by tests**: `jrec-fuel` 256 (qath-fuel uses 0/1/2); grec arms 128; closed-cell screens 512 (cell-branch tests the limits); `union-source-distinct-tags` 18 ok / 17 declines; `union-source-overlap` 20/19; `module-mold-params-valid` 256/257; `union-source-state-safe` 256/257 caps; `dg-direct-source` 63/64 wrappers, `dg-source-candidate` 64/65 defs; `ienv-fresh-id` results `2.000.002`, `1`, `10`; `dg-generalize` results `~[43]`, `~[81]`, `~[722]`, `~[713]`. Other literals: empty proof 256 in fit, live cases 4,096, inhabitation 256, finite 64, width 1,024/4,096, gate-free 256, obligations 62/63/64, `module-pending-tag` 64, request graph 256/256, `api-request-gates` 256.
445+11. **`istate` shape**: 27 positional fields at 10 literal sites, 5 bunts, `dg-stage-one` compares 22 fields (15458-15479), 13 suites use `istate:jibb`, all by bunting `*istate:jibb` and setting fields by name. Adding union-find, level or queue fields touches the 10 literal sites; a constructor arm (A28/A125) should come first.
446+12. **Interfaces are hashed nouns**: `iwidth-definition` carries the raw `sub` (10687) into `ifile.elaborations`; cache reuse compares inputs by equality (12219, 12275). Changing the representation changes interface nouns, cache keys and anything comparing `ifile`s (`request-graph-merge` dedup, `derived-request-member` evidence equality).
447+13. **Structural `=` certificates**: `compatible-raw-poke`, `request-compatible-ask`, `derived-poke-command-scheme` (five `cmd` cases in order `poke go wait now who`, label `raw-poke`), `store-main-closed`, `derived-request-member` (`∀m. $-($-(full m) (ask m))`), `derived-store-request-member`. A new var representation must keep these equal or replace them with template comparisons; any edit to `prelude.jibb`/`internal.jibb` silently disables them.
448+14. **Printer stability**: variable letters depend on `itype-vars` order and kind precedence; `site-type-note` suppression rules; nvar/rnvar print as atom constraints; `(unit qath)` and other public labels rely on `prelude-label-nested` (A134; jibb-theme).
449+15. **Prelude identity checks**: exact list scheme compared at 7844, 7996, 8572, 8800, 14767 (and built at 11920, 11979, 12013, 12064); unit via `standard-unit-template` 8646; `element` by origin `[at.prelude %element]`; qath must be `%jrec` at `/lib/jibb/internal/jibb` (8816). The core must expose the same identities or these paths all fail closed.
450+16. **Two pipelines**: changing the resolver or finalization in one pipeline without the other moves goldens or suites (A46, A122). The golden report also runs the full check on imported case-local modules (14989), so module-check goldens see both.
451+17. **Recovery adapters**: until R1-R10 are retired, they call `itype-fit` (22×), `itype-merge-faces` (12×), `instantiate-scheme` (12×), `direct-invariant` (16×), `template-apply` (15×), `infer-sample`, `reserve-def-caps`, `record-fields-named`, `itype-in-import`, `add-supported-result` (6×), `infer-call-context-arg` (6×), `ienv-fresh-id`; and they mix substitutions on purpose (body inferred from the sample's own sub with the gate-fit's `next`, 13418-13421; mapper from `initial`). A core that threads one store changes their edge behaviour.
452+18. **Negative fixtures that encode recovery limits, not spec errors**: `tests/type-todo-full/ambiguous-mapper.txt`, `alias.txt`, probably `open-key.txt`; generic strings `module definitions need unsupported inference: /p: ++ name` and `module kind needs unsupported inference: /p` asserted by program-update/init/main. An ordinary-application core will accept or reject these differently; decide per fixture.
453+19. **`program-single-generic-fit` is in ordinary inference** (7890, 7912) for any prelude `element` target, so removing the program recovery does not remove it; `types-prelude-ui` and `doc-grammar-02-buttons` depend on the path that reaches it.
454+20. **Performance**: assoc-list lookups and 95 `itype-normalize` calls; `unique-type-vars` O(n²); `free-env-vars`/`dg-env` rescans per generalization; `itype-fit-cases` re-fits every case; subjects inferred twice; whole-to-finite re-inference; prelude re-parsed per `direct-prelude-evidence` call (A132); report re-infers every definition; compiler.md:67-69 reports 38-72 s CPU for 2,000 gates. Brief l.141 asks for seconds.
455+21. **Deviations from the spec the core should not copy unknowingly**: gates fit `*` (Q18 pending), tag fits `@tas`/`@ta` without aura check (Q16/Q17), faces handled by asymmetric guards instead of "unnamed acquires the face" (S1 pending), argless union identity by raw cases (A11), only list/unit in inhabitation/gate-free (A13), arms matching no case reported as unsupported (Q22), decimal defaulting skipped in locals and gate types (compiler.md:59 notes defaulting in gate types is incomplete).
456+22. **Dead code not to port**: `itype-has-fixed-atom` 5098, `width-has-projections` 8988, `infer-width-elaboration` 8995 and `iwidth-elaboration` 8994, `direct-find-gate` 9058, `resolve-supported-defs` 10780, `golden-types-with-modules` 14939, `one-request-interface-source` 12850, unreachable `!!` at 14258 and 14525, the last `[%& …]` of `dg-boolean-branch` (15351), the always-`~` `captured` argument of `dg-generalize`, misplaced headers (5014-5018, 6008-6010, 6320-6321, 6397-6403, 5835-5837), the stale comment at 11502-11505.
457+
458+### 4.4 Seams a staged plan can use (observations, not a plan)
459+
460+- `golden-types-in-context-core` re-infers each definition independently (15107-15114), so a new core can be swapped in per definition behind the same printer and finalization, leaving `resolve-groups` in place, before the full check changes.
461+- The full check's recovery chain only runs for components still missing after `resolve-groups-core` (`?^ (ienv-lookup …) ~` at the top of each arm). A core that resolves a component ordinarily turns its recovery arm into a no-op without deleting it; the `cast-init` regression already guards that ordering.
462+- `itype-fit`'s three-valued API can be preserved over a new store as long as `%unknown` stays the answer for "would need a queued constraint" in the old callers; R1-R10 are its heaviest users.
463+- The dg-* transaction is reachable from the full check only without a prelude (14809) and from the report only on eligible sources; its tests are self-contained (four suites), so it can be retired as a unit once the queue exists.
464+
465+## 5. Entry points that must stay stable during a staged migration
466+
467+### 5.1 Tools (signatures are checked)
468+
469+| Arm | Line | Caller |
470+| --- | --- | --- |
471+| `golden` | (%api chapter) | `tools/golden` (parser outputs), module trees |
472+| `golden-types` `[file=path src=@t] -> @t` | 11486 | `tools/golden:251-253` (signature enforced at `tools/golden:407-408`), `tools/ship:1234` |
473+| `golden-types-imports` | 11497 | `tools/golden:252`, `tools/ship:1257` |
474+| `golden-types-with-marks` | 15016 | `tools/golden:248`, `tools/ship:1288` |
475+| `golden-types-with-prelude-and-internal` | 14969 | `tools/golden:259`, `tools/ship:1345` |
476+| `golden-types-with-prepared-prelude` | 14975 | `tools/golden:260`, `tools/ship:1346` |
477+| `prepare-prelude-with-internal` | 12103 | `tools/golden:291` (under `mule`), `tools/ship:1222` |
478+
479+### 5.2 Module-check API (suites, and itself recursively)
480+
481+`infer-jibb-file` 14650 (23 suites; also builds the internal prelude, 11956), `infer-jibb-file-detailed` 14658 (12 suites; `resolve-jibb-imports-detailed` 12316/12320), `resolve-jibb-imports` 12286 (deferred-resolver, generic-recursion), `prepare-prelude` 12092 (api-evidence, poke-bridge), `prepare-prelude-with-internal` (33 suites), `golden-types-with-prelude` 14955 (bridge, list-alias-guards, module-scope), `golden-types-with-reader-diagnostics` 15007 (bridge, import-*), `golden-types-in-context` 15021 (empty, union-alias-overlap, union-source), `golden-types-in-context-core` 15025 (deferred-prepared), `gate-free-mold-source` 14887, the API evidence arms (`api-path-analysis(-source)`, `api-path-evidence-source`, `api-path-parameters`, `api-path-watchability`, `api-request-parts`, `api-support-analysis-source`, `api-poke-interface`), `find-jibb-cache`, `request-graph-bounded`, `request-graph-reusable`, `module-scope-valid`, `module-mold-params-valid`, `program-main-def`, `program-main-parts`, `page-main-parts`, `parse`, `show-error`, `show-itype` (11 suites), `canonical-itype` (buttons, deferred-resolver, doc-examples), `record-fields-named` (program-init/main/update/watch), `itype-in-import` (5 suites), `itype-vars` (page-main, program-watch, store, theme), `ienv-lookup` (17 suites), `find-jibb-mold` (13 suites), `find-jibb-interface`, `find-simple-mold`, `collect-simple-molds`, `find-imported-mold`, `find-imported-mark`, `import-to-itype`, `template-apply`, `identity-union-parameters`, `prelude-union-alias`, `compatible-raw-poke`, `request-compatible-ask`, `derived-poke-command-scheme`.
482+
483+### 5.3 Substrate arms called by suites (keep or migrate the suites in the same stage)
484+
485+`itype-fit` (8 suites: arithmetic-guards, closed-gate-guards, constructor-fit-guards, deferred, empty, generic-construction, generic-recursion, qath-fuel), `itype-unify` (arithmetic-guards, gate-free-guards, generic-recursion), `itype-unify-test` (typecheck), `itype-walk` (arithmetic-guards, deferred), `itype-lookup` (hole-guards), `itype-normalize` (deferred, generic-construction), `itype-empty-proof`/`itype-inhabited-proof`/`itype-live-cases`/`empty-list-null-branch` (empty), `itype-gate-free-form`/`itype-collection-keys`/`itype-var-is-gate-free`/`instantiate-scheme`/`template-apply-sub` (gate-free-guards), `gate-free-type` (empty, gate-free-guards, generic-recursion), `itype-has-face` (deferred, empty), `itype-face-asym`/`itype-output-may-be-cell`/`pending-tags`/`unsupported-atom-vars` (deferred), `itype-positional-face-asym` (positional-face-guards), `itype-positional-slot-face-asym` (direct-gate-guards), `itype-fit-ctor-cases` (constructor-fit-guards), `itype-has-gate`/`default-decimals` (generic-recursion), `default-hole-numbers`/`simple-mold-hole` (hole-guards), `infer-fragment` (cell-branch, deferred, generic-pattern, qath-source), `infer-call-context-arg` (generic-construction, qath-fuel), `infer-simple-shape` (union-source).
486+
487+### 5.4 Recovery and dg arms called by suites (retire with their suites)
488+
489+direct-gate-guards: `direct-checked-gates`, `direct-gate-call-fit`, `direct-gate-sample`, `direct-positional-fit`, `direct-prelude-evidence`. cell-branch: `closed-cell-branch-eligible`, `closed-cell-retry-safe`, `closed-cell-sub-safe`, `infer-closed-cell-branch`. nested-union-guards: `contextual-direct-union`, `contextual-simple-sub`, `contextual-tagged-case`. constructor-fit-guards: `explicit-singleton-in-union`. qath-fuel: `jrec-match-view`, `qath-static-fuel`. generic-*: `simple-source-generic-recursive`, `grec-direct-context`, `grec-match-view`, `grec-patterns-eligible`, `grec-single-wing-subject`, `grec-unfold-view`. union-source: `grec-collect-molds`, `union-source-distinct-tags`, `union-source-state-safe`. union-alias-overlap and full-overlap-basic: `union-source-overlap`. program-main/-watch/store: `program-main-closed`; page-main: `page-main-closed`. deferred*: `dg-close-env`, `dg-direct-source`, `dg-generalize`, `dg-obligations`, `dg-replay-edges`, `dg-root-detail`, `dg-root-prepared`, `dg-root-source`, `dg-scan`, `dg-source-candidate`, `dg-stable-call-fit`, `dg-stage`, `ienv-fresh-id`.
490+
491+### 5.5 Types constructed by suites
492+
493+`itype` (32 suites), `iprelude` (32), `ifile` (25), `ischeme` (24), `istate` (13: cell-branch, deferred-context, deferred, direct-gate-guards, empty, gate-free-guards, generic-construction, generic-pattern, generic-recursion, hole-guards, qath-fuel, qath-source, union-source), `ienv` (11), `isub` (10), `iresult` (6), `ifit` (6), `upair` (3), `irequest-graph`/`irequest-evidence` (3), `dgo`/`ipending`/`igate-free`/`iwprojection`/`iwidth-definition` (2), `istore-request-evidence`, `igate-prelude-evidence`, `igf-form`, `igf-segment`, `ibinding`, `dgscan`, `dgparse`, `dgcommit`, `grec-collected` (1 each). Q37 decided tests keep calling internal arms (A126) until the core lands; a facade or same-stage suite edits are required for every renamed arm or reshaped type.
494+
495+## 6. Spec rules the core must meet, and open rulings
496+
497+Repository spec wins over the design doc (review Q42); several type-system rows in `decisions.md` are still marked unsynced.
498+
499+### 6.1 Rules
500+
501+| Topic | Rule (short) | Where | Core requirement | Today |
502+| --- | --- | --- | --- | --- |
503+| Inference basis | HM with aura variables; principal types; no general subtyping except listed one-way widenings and explicit `proj` | grammar.md l.121; decisions.md l.35; implementation-plan.md l.15; milestone-2.md l.39, l.62, l.141 | Union-find + levels; widening as directional constraints outside unify | assoc list, env scans, fit mixes widening and unification |
504+| Atoms and auras | `@` any atom per occurrence; specific auras distinct; aura fits `@` and Hoon-family ancestor; reverse needs a check | grammar.md l.124; decisions.md l.59, l.35, Q15 l.134, Q19 l.142 | `fit(actual, expected)` constraint that waits while actual is unbound; unify never widens | `aura-prefix` 5052, fit 5663-5680, `itype-concrete-join` 5125 |
505+| Noun | `*` is the noun type, top of fit only; arbitrary noun does not fit narrower | grammar.md l.121, l.132; decisions.md l.49, Q9 l.122 | unify(`*`, T) fails unless T is `*` | 5549-5557 accepts gates (Q18) |
506+| Empty and crash | `!!` expression has any type; mold `!!` empty; empty-position cells empty, disjoint from all | grammar.md l.62, l.127, l.132; decisions.md l.48, Q17 l.138 | crash = fresh var; usefulness drops uninhabited constructors | `%empty`, 4744, 5521-5525 |
507+| Loobeans | `?` = {0,1}; disjoint from cells, overlaps 0 and 1; arithmetic rejects, comparison accepts | grammar.md l.124, l.127, l.59; decisions.md l.52, l.60, Q16, Q28 | finite constructor set; "atom other than ?" kind | `?` vs `@f` unresolved (5546-5548) |
508+| Constants | singletons compared by noun (`%$` = `%.y` = `~` = 0) | grammar.md l.29-31, l.125, l.144; decisions.md l.29, Q34 | key singletons by noun in unify, fit, ctor, patterns, disjointness | `%const` by value 4926, 5617 |
509+| Literals | decimal `@ud` or any aura by context; prefixed numbers, ships, dates, knots, cords; `` `x ``, `~[…]`, `a+b`, paths, qath read as Hoon | grammar.md l.19-39; decisions.md l.14, l.58 | literal → type or var + literal constraint; prelude unit/list/path/qath templates available | 8770-8821 |
510+| Faces | faces are part of types; unnamed position unifies with faced and takes its face; different faces don't unify; duplicate fields error (also imported); `[a]` is `a`; `[]` error; theme `dark=[tones=…]` must check | grammar.md l.126, l.33; decisions.md l.15, l.42, l.35, Q5, Q8, Q21, Q27 | label slot that may be unknown, bound by unification | `%face` wrapper + asymmetry guards 5212-5349 |
511+| `proj` | explicit, type-directed; expected type selects fields; evaluated once; never inserted implicitly; reserved name | grammar.md l.126; decisions.md l.43; core-language.md l.85; Q32 | deferred `proj(S) : T` with recorded axes | 5835-5923, 9461, 10535, 11706-11760 |
512+| Capitals | generalized per `++`; local `++` shares an enclosing capital it also uses; cannot force two capitals equal; cannot become more specific | grammar.md l.129; decisions.md l.50, Q4, Q23; milestone-2.md l.66 | rigid (skolem) vars scoped before inference; violations name both sites | `merged-capitals` 10072; forcing concrete is "unsupported" (10089) |
513+| Atom/arith constraints | atom constraint and "atom other than ?" retained through generalization and instantiation; printed as where-clauses separated by commas | grammar.md l.124, l.137; decisions.md l.31, l.60, Q28, Q29 | kind lattice on roots | six var kinds, A16 |
514+| Gate-free | `eq` args and map/set keys contain no gates; inferred and generalized; printed `where A contains no gates` | grammar.md l.137; decisions.md l.33, l.106; core-language.md l.39 | gate-free kind, structural propagation, binding a gate fails with sites | `%fvar`, 4998, 5951 |
515+| Holes | `_` wherever a mold may; resolves to a concrete type or written capital; unconstrained is an error; a definition determines its own holes | grammar.md l.123, l.130; decisions.md l.51, Q30, Q31 | hole var with span checked at its level exit | 6133-6181 |
516+| Order, recursion, value cycles | any order; gates self/mutually recursive; non-gate value depending on itself is an error; infer in dependency order, groups together | grammar.md l.56, l.101; decisions.md l.23; core-language.md l.145; milestone-2.md l.66, l.141 | one SCC pass; value cycles reported from the graph | fixpoint fallback 10749-10756; cycle proof needs a cast |
517+| Locals | `++` at the start of any body; mutually visible; generalize locally, captured outer vars shared | grammar.md l.56; decisions.md l.22; milestone-2.md l.97 | levels + same SCC machinery | 7611-7681 |
518+| No shadowing | samples, locals, pattern binders, imports, prelude | grammar.md l.101; decisions.md l.13; core-language.md l.37; milestone-2.md l.95 | scope pass with sites | several site-less messages (8018, 8240…) |
519+| Namespaces | molds and values separate, by position | grammar.md l.102; overview.md l.305 | two tables per scope/interface | `ifile` 5822 |
520+| Tag resolution | tag/`~` = fresh var + pending constraint; non-union = one-case union; checked by shape and shared tag positions, field positions against fields; `@tas`/`@ta`/`@`/`*` make it that constant; no match → `msg has no case %submitt` | grammar.md l.141-143; decisions.md l.29; milestone-2.md l.77 | the deferred queue, woken on binding | `%tag` 4676, 5451, 8693, 8711 |
521+| Non-generalization, module end | tag-constrained vars (and what they mention) do not generalize; an island's `main` fixes its messages; open at module end → error asking for `^-`, never guess | grammar.md l.145-146, l.150-158; milestone-2.md l.79 | keep such vars at module level; module-end pass reports `nothing fixes the union of %add` | dropped at 10680; recovery R1-R5; `module-pending-tag` |
522+| `\|=%tag` | case constructor typed by the expected gate; any case whose head noun equals the tag; no such case is an error | grammar.md l.48, l.141, l.144; decisions.md l.47, Q34; milestone-2.md l.78, l.124 | deferred ctor constraint on the product's root | 5474 |
523+| Numbers by context | wait for context; default `@ud` at the `++` only if unfixed and not generic over it | grammar.md l.162-167; decisions.md l.35; milestone-2.md l.81 | defaultable kind, defaulted at level exit unless linked to a quantified/rigid var | 6062, 6119; incomplete in gate types (compiler.md:59) |
524+| Cell literals | tuple, record or cons (under list); default tuple | grammar.md l.33, l.168, l.172 | deferred cell constraint | cons only under known list context (7834) |
525+| Null | `~` is the `~` case of any union that has one | grammar.md l.31, l.141 | same queue keyed on noun 0 | 5365, 5613-5616 |
526+| Waiting | wing access, changes and `?-` on unknown types wait; patterns don't; `m()` error | grammar.md l.147-148, l.45, l.47; decisions.md l.13, Q6 | deferred has-field / edit / match constraints | 7720, 8622 need a known spine |
527+| Samples, inline gates | every bare name in a sample binds; `\|=(p title.p)` works when the call fixes the type | grammar.md l.48, l.58; decisions.md l.21, l.47; milestone-2.md l.69 | relies on deferred wing access |: |
528+| Calls | right-nested sample; parentheses only group | grammar.md l.43; core-language.md l.29, l.88 | apply = unify/fit with `$-(sample result)` | several call paths |
529+| Named unions | every Jibb union is named; imports may be unnamed; identity = origin + args, display separate | grammar.md l.57, l.127; decisions.md l.29; overview.md l.77 | nominal identity | raw-case equality (A11) |
530+| Disjointness | cases must differ as nouns (for all generic args); `*`, vars and `(list A)` overlap; `!!` disjoint; imported `$% $? $^` too; unverifiable imports fail closed; error suggests leaving `[` open | grammar.md l.127, l.94; decisions.md l.29, l.41, Q16, Q17, Q22; overview.md l.66-68; milestone-2.md l.86, l.125; jibb.hoon 4620 | noun-shape signature shared with usefulness; overlap witness naming both sites | 10909-11302 |
531+| Generic molds | `\|$ [V E]` right after `+$` name; prelude `cmd`/`sub` use `\|$ [M]` | grammar.md l.64, l.131; milestone-2.md l.70 | templates instantiated at exact arity; unions keep origin/args | 6970, 6355; recursive generics only via grec |
532+| Recursive molds | allowed; identity by name and module; imported (e.g. `json`) matched by name | grammar.md l.57, l.135; decisions.md l.56; overview.md l.74 | one nominal recursive type unfolded on demand | three forms |
533+| Containers | list, unit, set, map, mop, qeu, jar, jug; imported maps/sets checked with `apt`; keys gate-free | grammar.md l.128; overview.md l.70-71, l.88, l.102 | inhabitation and gate-free over all containers | list/unit only (A13) |
534+| `?-` | exhaustive, ordered; missing case error naming it; covered arm error; nested patterns allowed; last position binds the rest | grammar.md l.59, l.184-219, l.276-277; decisions.md l.32, l.57; milestone-2.md l.89-92, l.142 | Maranget usefulness with witnesses; one matrix also for milestone-3 lowering | three loops + slices; nested mostly unsupported |
535+| Pattern typing | patterns checked against the subject; binders take position types | grammar.md l.148, l.184; core-language.md l.92-93 | binder types from specialized matrix columns | `union-pattern-bind` 8156 |
536+| Branch join | unify, else widen only to an explicitly present parent aura or `@`; with an expected type each arm fits it | questions.md Q11; A133; grammar.md l.121 | unify + deferred widen; check mode with expected | 5138, 5202 |
537+| Interpolation | atoms print by aura (`@` as `@ud`); text auras and tapes splice; other cells error; generic aura error here and in qath segments; `~&` printer from type | grammar.md l.49, l.170-171; decisions.md l.58; core-language.md l.79, l.95; milestone-2.md l.82 | deferred printable constraint decided at level exit; record the printer | 8081 rejects late-known types |
538+| Paths | constant, empty, typed by aura (`_` allowed); qath with printable segments; route check is milestone 4 | grammar.md l.130, l.36-37, l.173; overview.md l.337 | path mold kind; same printable constraint | jrec qath |
539+| Imports, module values | `/-`, `/%` (no face), `/=` under a face; records read with `.`; module as a value is a cell of definitions in name order; APIs re-export `/%` types; import cycles are errors | grammar.md l.86-94, l.104, l.47; core-language.md l.146; overview.md l.305; milestone-2.md l.98-99 | interface noun; faces as record access with per-use instantiation | `ifile`, 12293, cycle 12304 |
540+| Hoon import table | `$% $? $^` unions if disjoint; `$@`; `$~` dropped; containers by name; tags `%0 %& %\|`; recursive by name; errors where used for duplicates, cores, gates, vases, signed/float auras | overview.md l.60-77; grammar.md l.94; decisions.md l.41, Q21, Q22; milestone-2.md l.102-104, l.134-140, l.153 | imported molds become the same core types; unsupported molds poisoned at use | 6527-6728; whitelist triplicated (A14) |
541+| Module kinds | main's type decides: `(element !!)` page, `(page R D)`, `(program D X M)`, `(store S)`, none = library; built by builders; stages never inferred | grammar.md l.103, l.107-117; overview.md l.106-115; decisions.md l.55, l.66, Q11; milestone-2.md l.100, l.107 | post-solve match of main's closed type; main ordinary (Q5) | syntactic recognisers 13146-13240 |
542+| Islands | `main` record of exactly init/update/view/subs; `island` checks data against init's sample; update/subs/init types from the prelude | overview.md l.112, l.115-121, l.155, l.166; grammar.md l.293-343; decisions.md l.70-71 | follows from prelude types once tags defer across `++` | R1-R6 |
543+| Gate-free island data/model | no gates in data and models; name the field | overview.md l.121; decisions.md l.73; core-language.md l.39; milestone-2.md l.109, l.124 | post-solve gate-free check with witness path | `program-main-closed` 14555 + 5951 (256) |
544+| Effects | `cmd`/`sub` prelude unions with `\|$ [M]`; `raw-poke`, `ask`, `qath` transparent internal types re-exported | overview.md l.140-160; grammar.md l.133-134; decisions.md l.36-37, Q24, Q25 | generic unions with gate payloads; public names in printing | `prelude-label-nested` 11878 |
545+| Stores | `state`, local `+$ poke`, `++ main (store init update)`; builder `\|= [init=S update=$-([A S] S)] ^- (store S)`; kind check verifies A against poke; derived poke helper and state request; one store per page | overview.md l.168-169; grammar.md l.105, l.293-306, l.343; decisions.md l.77-78, Q11 | record A's instantiation at main's application, or check update against `$-([poke state] state)` | R8 |
546+| APIs | `/ui/api/<agent>.jibb` declares `+$ poke` and `+$ paths` (declarations); `(facts full diff …)` with fold `$-([[%mark diff] full] full)`; optional `scry=`; derived poke helper and one request per case; clashes are errors | overview.md l.283-307, l.157-158; grammar.md l.105, l.134; decisions.md l.38-40; milestone-2.md l.111-114 | declaration elaboration into interface schemes | 12329-13148 |
547+| Watchability | islands read agents only by watching; first fact full state; a `scry=` case cannot be watched; unproven watchability is a type error; store state is watchable | overview.md l.159; grammar.md l.105; decisions.md l.38, l.79, Q33 | type-level marker or provenance analysis over the elaborated tree | one syntactic watch shape (14367) |
548+| Pages with data | `load` maps route parameters to one `ask`/`pure`; `view` takes D, returns `(element !!)` | overview.md l.125-130, l.334; grammar.md l.103; decisions.md l.67; milestone-2.md l.161 | ordinary application of `page` | one load shape (14512) |
549+| Elements, attributes | elements are ordinary gates; duplicate attribute in a literal list is an error; `~[text "hi"]` gets a suggestion | overview.md l.174-204; grammar.md l.44; milestone-2.md l.121, l.124 | type-directed post-solve checks | absent |
550+| Theme | `++ theme ^- theme`, backtick units | overview.md l.211-222; decisions.md l.83, Q5 | plain record check | works (uses R17 for the qath font) |
551+| Prelude | Hoon stdlib regrouped in Jibb with a complete inventory; private internal module | overview.md l.81-102; decisions.md l.87-88; open-questions Q3; milestone-2.md l.116-121 | prelude checked by the same core and exported as an interface | partial interface (compiler.md:159) |
552+| No built-ins | type-directed rules only if listed in the Grammar; special cases for one gate are language changes | decisions.md l.34; milestone-2.md l.28 | `program`, `page`, `store`, `each`, `turn`, `element` as ordinary gates | R3, R7 are gate-specific |
553+| Printing | Jibb mold syntax; unnamed unions as space-separated cases; where-clauses; no private names | grammar.md l.137; overview.md l.77; decisions.md l.30-31; milestone-2.md l.143, l.148 | keep origin/name through solving; canonical names past 26 | 9930, 6345, 10171 |
554+| Errors | each error names both sites with excerpts; messages are golden tests; catalogue (aura mismatch, faces, missing case, open constraint, ctor, overlap, missing `?-` case, covered arm, self-dependent value, shadowing, interpolation, capitals, `~[text "hi"]`, clashing derived names, import cycle, `(facts …)` misuse, gate in island data, repeated attribute) | implementation-plan.md Risks; milestone-2.md l.48, l.123-127 | every constraint carries spans; union-find keeps a reason per binding | `idiag` 5997; 283 unsupported lines |
555+| Elaborated output | types/faces/casts leave nothing; lowering needs field axes, edits, decision tree, `proj` plans, printers, path validators | core-language.md l.74-98, l.33-41 | apply the final substitution to a typed tree | only width artifacts (5808) |
556+| Checker as function | caller passes Clay inputs; interface is its own noun; cache with interface and body hashed separately; modules one at a time in dependency order | milestone-2.md l.133; implementation-plan.md (pipeline, cache row); compiler.md:19 | interfaces store generalized schemes with constraints and mold templates | `ifile`, `prepare-prelude` |
557+| Speed | a 2,000-line module checks in seconds | milestone-2.md l.141, l.155; implementation-plan.md Risks | near-constant find, level generalization, one SCC pass | 38-72 s CPU for 2,000 gates (compiler.md:67-69) |
558+| Golden types | third golden output: each definition's type and the module kind, or the rendered error | milestone-2.md l.148; questions.md Q6 | one pipeline returning scheme-or-error per definition | all 304 from the report path (A122) |
559+
560+### 6.2 Open rulings that affect the core
561+
562+| Ruling | State | Effect on the core |
563+| --- | --- | --- |
564+| open-questions.md Q3 (prelude inventory and signatures) | open | Fixes the environment the core checks against; the prepared prelude is partial today |
565+| open-questions.md Q32 (`proj` reordering) | partly settled | How `proj` constraints discharge (jibb.hoon 4625 treats reordering as a doc question) |
566+| Review Q16 (A20): follow Hoon, `%1.000` is `@ud`, `%&` is `?` | proposed, awaiting @iko | How tag constraints discharge against atoms (today 5617-5626, 5636-5648) |
567+| Review Q17 (A20): a name term fits `@t` | proposed | Same discharge rule |
568+| Review Q18 (A23): `*` may hold gates | proposed "yes" | Fit to `*`, gate-free proofs, element's child erasure to `*` (prelude.jibb l.447-466), core-language.md l.33 |
569+| Review Q19 (A6, A100): reject `[]` and `m()` in the parser | proposed | Otherwise the core must reject them |
570+| Review Q20 (A30): `[a=@ud [a=@t b=?]]` is one record, duplicate `a` is an error | proposed | Record and field-access semantics (today nested tails get their own scope, 11556) |
571+| Review Q21 (A25): `/% %foo` beside `++ foo` | proposed | Scope check (11760) |
572+| Review Q22 (A15): an arm matching no remaining case is definite (`arm matches no case`) | proposed | Usefulness reports a useless row; today `union pattern is not supported` (8236, 8273, 8324) |
573+| Review Q23 (A55): `(mop K V)` without comparator | proposed | No comparator in the type |
574+| Review Q24 (A64): Hoon's `each` mold beside the `each` gate | proposed | Relies on separate namespaces |
575+| Review Q26 (A50): importer learns `$%` with `%& %\| %0` tags, then `each` and `json` | proposed | Which imported unions reach the core |
576+| Review Q28 (A136): printer flattens `[a [b c]]`, prints named molds by name | proposed | Core must keep mold names through solving |
577+| Review Q6 (A122): render the report from the full checker | decided, not done | ~283 `types.txt` change once |
578+| Review Q37 (A126): tests keep calling ~137 internal arms | decided; revisit after the core | Keep arms or move suites behind a facade per stage |
579+| Syntax review S1: capitals bind only the type under a face; gate sample names ignored when gate types unify | question for @iko | Decides the face rules; reopens decisions.md l.33 and settled Q8; directly decides whether R11-R13 become unnecessary |
580+| Syntax review S3: samples/binders/locals may reuse prelude value names | question for @iko | Shadowing pass; todo-list's `[%typed text]` fails today |
581+| Syntax review S4: bare decimal fits only `@ud @u @ *` | question for @iko | Number-literal constraint (grammar.md l.21 says any aura) |
582+| Syntax review S5: a pattern name spelling a case tag at a union position is an error | question for @iko | Usefulness-time check |
583+| Syntax review S7: multi-letter type variables | question for @iko | Printer and capital scoping |
584+| Syntax review S12: nested cell patterns shown in the spec | question for @iko | The EBNF allows them; the prelude uses nested `?-` because the checker lacks them, so the core must handle nesting |
585+| Derived request argument order | unresolved in code (`api-request-parts` 12683) | Overview's `(post.api slug same)` suggests segments first |
586+| Application paths vs routes | milestone 4 | Core types `%/…` as qath with printable segments only |
587+| Spec sync | repository copy wins (Q42) | Unsynced decisions.md rows (Unions, Printed type constraints, Partial type annotations, Record fields, Record projection, Store builder, Agent APIs, Effects) may still differ from the design doc |
docs/reviews/2026-11-03-milestone-2-probes/README.mdnew file+23
@@ -0,0 +1,23 @@
1+# Probes for the milestone 2 review
2+
3+The Jibb sources the [milestone 2 review](../2026-11-03-milestone-2-review.md) ran through the full module checker, `infer-jibb-file-detailed`, at `f84a29e`, with what the checker printed then. They are evidence for the review and a ready regression corpus for [finishing milestone 2](../../prompts/milestone-2-finish.md). No check runs them: they are not tests, and several outputs record what is wrong today.
4+
5+Each `.jibb` file holds sections, each starting with a line `#### <label>`; each section is checked as a module on its own. A `.out` file is the output of its `.jibb`: per section, `CHECKED` and the exported molds and values with their types, or `REJECTED:` and the message.
6+
7+| Files | What they hold | Run with |
8+| --- | --- | --- |
9+| `variants/p1.jibb` to `p10.jibb` | The `my-app` modules and the doc blocks as written (`p1`), then about 90 spec-valid one-edit variants of them (`p2` to `p8`: reordered, renamed, extra helpers, a second watch, `\|=(m ~)` subscriptions, aliases, typed and `pure` loads) and wrong variants that must fail with their own error (`p9`, `p10`, labels starting `BAD-`). A label is the module's path, then a name | `run app` |
10+| `errors/p1.jibb` to `p5.jibb` | One or more probes for each error the spec describes, labelled as in the review's error table (`E01` an aura mismatch, `S2` the Grammar's `[%move * *]`, `C1` `%submitt` in an island, `W1` to `W4` island initializers) | `run plain` |
11+| `errors/import-check.hoon` | Invalid Hoon imports (`I1` to `I9`), module-graph errors (`M1` to `M5`) and the raw reader results | `run imports` |
12+
13+`variants/p1.jibb` has no saved output; every section in it checks, except `buttons`, which fails with "nothing fixes the union of %add".
14+
15+From the repo root, with `urbit` on `PATH` (`nix develop`):
16+
17+```
18+docs/reviews/2026-11-03-milestone-2-probes/run app docs/reviews/2026-11-03-milestone-2-probes/variants/p9.jibb
19+docs/reviews/2026-11-03-milestone-2-probes/run plain docs/reviews/2026-11-03-milestone-2-probes/errors/p1.jibb
20+docs/reviews/2026-11-03-milestone-2-probes/run imports
21+```
22+
23+`run plain` checks each section as `/ui/probe/jibb` against the real prelude (`check.hoon`). `run app` checks each section at the path its label names, with `my-app`'s todo and blog `/sur` files and marks compiled by `ride` (marks without their `/-` lines, as the `tests/lib` suites do) and a bundle of `api/todo`, `todo-list`, `api/blog`, `card` and `cart`, the section's own path left out (`app-check.hoon`). A label of the form `<path> module <name>` adds that section to the bundle instead. Each run takes 30 to 80 s, most of it building the libraries.
docs/reviews/2026-11-03-milestone-2-probes/app-check.hoonnew file+67
@@ -0,0 +1,67 @@
1+=/ prepared=iprelude (need (prepare-prelude-with-internal prelude internal))
2+=/ todo=type -:(ride -:!>(..zuse) sur)
3+=/ subject=type [%cell [%face %todo todo] -:!>(..zuse)]
4+=/ ma=* (read-mark:imp %todo-action -:(ride subject action))
5+=/ mt=* (read-mark:imp %todos -:(ride subject todos))
6+=/ mu=* (read-mark:imp %todo-update -:(ride subject update))
7+=/ mi=* (read-mark:imp %todo-item -:(ride subject item))
8+=/ blog=type -:(ride -:!>(..zuse) blogsur)
9+=/ blog-subject=type [%cell [%face %blog blog] -:!>(..zuse)]
10+=/ mp=* (read-mark:imp %posts -:(ride blog-subject posts))
11+=/ item-input=* (read-named:imp %todo %item todo)
12+=/ post-input=* (read-named:imp %blog %post blog)
13+=/ marks=imark-externals ~[[%todo-action ma] [%todos mt] [%todo-update mu] [%todo-item mi] [%posts mp]]
14+=/ externals=iexternals ~[[%todo %item item-input] [%blog %post post-input]]
15+=/ all-modules=jbundle
16+ :~ [/ui/api/todo/jibb todoapi]
17+ [/ui/todo-list/jibb todolist]
18+ [/ui/api/blog/jibb blogapi]
19+ [/ui/components/card/jibb card]
20+ [/ui/stores/cart/jibb cart]
21+ ==
22+=/ lines=wain (to-wain:format src)
23+=| out=(list [label=@t body=wain])
24+=| cur=(unit [label=@t body=wain])
25+=/ sections=(list [label=@t body=wain])
26+ |-
27+ ?~ lines
28+ (flop ?~(cur out [[label.u.cur (flop body.u.cur)] out]))
29+ ?: =('#### ' (end [3 5] i.lines))
30+ =? out ?=(^ cur) [[label.u.cur (flop body.u.cur)] out]
31+ $(lines t.lines, cur `[(rsh [3 5] i.lines) ~])
32+ ?~ cur $(lines t.lines)
33+ $(lines t.lines, body.u.cur [i.lines body.u.cur])
34+=/ extra=jbundle
35+ %+ murn sections
36+ |= [label=@t body=wain]
37+ ^- (unit jsource)
38+ =/ words=(list tape) (rash label (more ace (star ;~(less ace next))))
39+ ?. (gte (lent words) 3) ~
40+ ?. =('module' (crip (snag 1 words))) ~
41+ `[(stab (crip (snag 0 words))) (of-wain:format body)]
42+=/ base=jbundle
43+ %+ weld extra
44+ (skip all-modules |=(j=jsource (lien extra |=(e=jsource =(at.e at.j)))))
45+^- tape
46+%- zing
47+%+ turn sections
48+|= [label=@t body=wain]
49+^- tape
50+=/ words=(list tape) (rash label (more ace (star ;~(less ace next))))
51+=/ at=path (stab (crip (snag 0 words)))
52+=/ text=@t (of-wain:format body)
53+=/ modules=jbundle (skip base |=(j=jsource =(at.j at)))
54+=/ r=jfile-detailed-result
55+ (infer-jibb-file-detailed at text externals marks modules ~[at] values.prepared molds.prepared ~ `iface.prepared)
56+=/ head=tape "#### {(trip label)}\0a"
57+?: ?=(%| -.r) `tape`(zing `(list tape)`~[head "REJECTED: " (trip message.p.r) "\0a"])
58+=/ ms=(list tape)
59+ %+ turn molds.iface.p.r
60+ |= [name=term s=ischeme]
61+ "+$ {(trip name)}: {(show-itype (canonical-itype typ.s vars.s) ~)}\0a"
62+=/ vals=(list tape)
63+ %+ turn values.iface.p.r
64+ |= [name=term s=ischeme]
65+ =/ c=itype (canonical-itype typ.s vars.s)
66+ "++ {(trip name)}: {(show-itype c ~)}{(show-atom-constraint c)}\0a"
67+`tape`(zing `(list tape)`~[head "CHECKED\0a" `tape`(zing ms) `tape`(zing vals)])
docs/reviews/2026-11-03-milestone-2-probes/check.hoonnew file+37
@@ -0,0 +1,37 @@
1+:: Full-module check of several sources in one eval. Bind `src` to a
2+:: file whose sections each start with a line "#### <label>"; each
3+:: section is checked on its own as /ui/probe/jibb against the real
4+:: prelude. Bind: prelude, internal, src.
5+=/ prepared=iprelude (need (prepare-prelude-with-internal prelude internal))
6+=/ at=path /ui/probe/jibb
7+=/ lines=wain (to-wain:format src)
8+=| out=(list [label=@t body=wain])
9+=| cur=(unit [label=@t body=wain])
10+=/ sections=(list [label=@t body=wain])
11+ |-
12+ ?~ lines
13+ (flop ?~(cur out [[label.u.cur (flop body.u.cur)] out]))
14+ ?: =('#### ' (end [3 5] i.lines))
15+ =? out ?=(^ cur) [[label.u.cur (flop body.u.cur)] out]
16+ $(lines t.lines, cur `[(rsh [3 5] i.lines) ~])
17+ ?~ cur $(lines t.lines)
18+ $(lines t.lines, body.u.cur [i.lines body.u.cur])
19+^- tape
20+%- zing
21+%+ turn sections
22+|= [label=@t body=wain]
23+^- tape
24+=/ text=@t (of-wain:format body)
25+=/ r=jfile-detailed-result
26+ (infer-jibb-file-detailed at text ~ ~ ~ ~[at] values.prepared molds.prepared ~ `iface.prepared)
27+=/ head=tape "#### {(trip label)}\0a"
28+?: ?=(%| -.r) `tape`(zing `(list tape)`~[head "REJECTED: " (trip message.p.r) "\0a"])
29+=/ ms=(list tape)
30+ %+ turn molds.iface.p.r
31+ |= [name=term s=ischeme]
32+ "+$ {(trip name)}: {(show-itype (canonical-itype typ.s vars.s) ~)}\0a"
33+=/ vals=(list tape)
34+ %+ turn values.iface.p.r
35+ |= [name=term s=ischeme]
36+ "++ {(trip name)}: {(show-itype (canonical-itype typ.s vars.s) ~)}\0a"
37+`tape`(zing `(list tape)`~[head "CHECKED\0a" `tape`(zing ms) `tape`(zing vals)])
docs/reviews/2026-11-03-milestone-2-probes/errors/import-check.hoonnew file+101
@@ -0,0 +1,101 @@
1+=> [lib=jibb-lib reader=reader prelude=prelude internal=internal ..zuse]
2+=/ prepared=iprelude:lib (need (prepare-prelude-with-internal:lib prelude internal))
3+=/ sur=@t
4+ '''
5+ |%
6+ +$ signed @sd
7+ +$ flt @rd
8+ +$ gat $-(@t @t)
9+ +$ vas vase
10+ +$ dup [a=@ud a=@t]
11+ +$ ovl $%([%a @t] [%a @ud])
12+ +$ ovl2 $?(@t @ud)
13+ +$ cel $^([@t @t] [@ud @ud])
14+ +$ good @t
15+ +$ cor _^|(|=(a=@ a))
16+ --
17+ '''
18+=/ cor=type -:(ride -:!>(..zuse) sur)
19+=/ conv
20+ |= d=import-diagnostic:reader
21+ ^- *
22+ ?- -.d
23+ %ok [%& value.d]
24+ %invalid d
25+ %unsupported [%| message.d]
26+ ==
27+=/ names=(list term) ~[%signed %flt %gat %vas %dup %ovl %ovl2 %cel %good %cor]
28+=/ ext=(list [module=term name=term result=*])
29+ %+ turn names
30+ |= n=term
31+ =/ r (mule |.((read-named-diagnostic:reader %fix n cor)))
32+ ?: ?=(%| -.r) [%fix n [%| 'reader crashed']]
33+ [%fix n (conv p.r)]
34+=/ raw=(list [term *])
35+ %+ turn names
36+ |= n=term
37+ =/ r (mule |.((read-named-diagnostic:reader %fix n cor)))
38+ ?: ?=(%| -.r) [n %crash]
39+ [n p.r]
40+=/ mark-src=@t
41+ '''
42+ |_ a=@t
43+ ++ grab |% ++ noun @t --
44+ ++ grow |% ++ noun a --
45+ ++ grad %noun
46+ --
47+ '''
48+=/ mcor=type -:(ride -:!>(..zuse) mark-src)
49+=/ full-mark=* (read-mark:reader %full mcor)
50+=/ marks=(list [mark=term result=*]) ~[[%full full-mark]]
51+=/ probes=(list [label=@t at=path src=@t mods=jbundle:lib])
52+ :~ ['I1-signed' /ui/probe/jibb '/- fix\0a++ a |= x=signed.fix x\0a' ~]
53+ ['I2-float' /ui/probe/jibb '/- fix\0a++ a |= x=flt.fix x\0a' ~]
54+ ['I3-gate' /ui/probe/jibb '/- fix\0a++ a |= x=gat.fix x\0a' ~]
55+ ['I3b-core' /ui/probe/jibb '/- fix\0a++ a |= x=cor.fix x\0a' ~]
56+ ['I4-vase' /ui/probe/jibb '/- fix\0a++ a |= x=vas.fix x\0a' ~]
57+ ['I5-dupfields' /ui/probe/jibb '/- fix\0a++ a |= x=dup.fix x\0a' ~]
58+ ['I6-overlap-cen' /ui/probe/jibb '/- fix\0a++ a |= x=ovl.fix x\0a' ~]
59+ ['I7-overlap-wut' /ui/probe/jibb '/- fix\0a++ a |= x=ovl2.fix x\0a' ~]
60+ ['I8-overlap-ket' /ui/probe/jibb '/- fix\0a++ a |= x=cel.fix x\0a' ~]
61+ ['I9-good-unused-bad' /ui/probe/jibb '/- fix\0a++ a |= x=good.fix x\0a' ~]
62+ ['M1-cycle' /ui/probe/jibb '/= a /ui/a\0a++ v (identity.a "hi")\0a' ~[[/ui/a/jibb '/= b /ui/b\0a++ identity |=(x (identity.b x))\0a'] [/ui/b/jibb '/= a /ui/a\0a++ identity |=(x (identity.a x))\0a']]]
63+ ['M1b-root-cycle' /ui/probe/jibb '/= a /ui/a\0a++ v 1\0a' ~[[/ui/a/jibb '/= p /ui/probe\0a++ w 2\0a']]]
64+ ['M2-derived-clash' /ui/probe/jibb '/= api /ui/api/demo\0a++ x 1\0a' ~[[/ui/api/demo/jibb '/% %full\0a+$ paths\0a [%plain /plain full]\0a [%other /other full]\0a++ plain 5\0a']]]
65+ ['M2b-derived-clash-root' /ui/api/demo/jibb '/% %full\0a+$ paths\0a [%plain /plain full]\0a [%other /other full]\0a++ plain 5\0a' ~]
66+ ['M2c-derived-face-clash' /ui/api/demo/jibb '/% %full\0a/- plain\0a+$ paths\0a [%plain /plain full]\0a' ~]
67+ ['M2d-poke-clash' /ui/api/demo/jibb '/% %full\0a+$ poke full\0a++ poke "bad"\0a' ~]
68+ ['M3-facts-in-library' /ui/probe/jibb '/% %full\0a+$ x (facts full full)\0a' ~]
69+ ['M3b-facts-in-api-other-mold' /ui/api/demo/jibb '/% %full\0a+$ paths\0a [%plain /plain full]\0a+$ x (facts full full)\0a' ~]
70+ ['M4-shadow-import-face' /ui/probe/jibb '/= lib /ui/lib\0a++ f |= lib=@t lib\0a' ~[[/ui/lib/jibb '++ identity |=(x x)\0a']]]
71+ ['M4b-shadow-import-value' /ui/probe/jibb '/= lib /ui/lib\0a++ lib 1\0a' ~[[/ui/lib/jibb '++ identity |=(x x)\0a']]]
72+ ['M5-api-ok' /ui/api/demo/jibb '/% %full\0a+$ paths\0a [%plain /plain full]\0a' ~]
73+ ==
74+=/ out=(list tape)
75+ %+ turn probes
76+ |= [label=@t at=path src=@t mods=jbundle:lib]
77+ ^- tape
78+ =/ r (mule |.((infer-jibb-file-detailed:lib at src ext marks mods ~[at] values.prepared molds.prepared ~ `iface.prepared)))
79+ =/ head=tape "#### {(trip label)}\0a"
80+ ?: ?=(%| -.r) `tape`(weld head "CRASH\0a")
81+ =/ res p.r
82+ ?: ?=(%| -.res) `tape`(zing `(list tape)`~[head "REJECTED: " (trip message.p.res) "\0a"])
83+ =/ vals=(list tape)
84+ %+ turn values.iface.p.res
85+ |= [name=term s=ischeme:lib]
86+ ^- tape
87+ "++ {(trip name)}: {(show-itype:lib (canonical-itype:lib typ.s vars.s) ~)}\0a"
88+ `tape`(zing `(list tape)`~[head "CHECKED\0a" `tape`(zing vals)])
89+=/ rawt=tape
90+ %- zing
91+ %+ turn raw
92+ |= [n=term v=*]
93+ ^- tape
94+ =/ desc=tape
95+ ?@ v "atom"
96+ ?: ?=([%invalid @ @] v) "invalid {(trip ;;(@t +<.v))}: {(trip ;;(@t +>.v))}"
97+ ?: ?=([%unsupported @] v) "unsupported: {(trip ;;(@t +.v))}"
98+ ?: ?=([%ok *] v) "ok"
99+ "other"
100+ "{(trip n)}: {desc}\0a"
101+^- tape (zing `(list tape)`~[`tape`(zing out) "#### RAW\0a" rawt])
docs/reviews/2026-11-03-milestone-2-probes/errors/import-check.outnew file+82
@@ -0,0 +1,82 @@
1+#### I1-signed
2+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
3+#### I2-float
4+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
5+#### I3-gate
6+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
7+#### I3b-core
8+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
9+#### I4-vase
10+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
11+#### I5-dupfields
12+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
13+#### I6-overlap-cen
14+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
15+#### I7-overlap-wut
16+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
17+#### I8-overlap-ket
18+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ a
19+#### I9-good-unused-bad
20+CHECKED
21+++ a: $-(@t @t)
22+#### M1-cycle
23+REJECTED: import cycle at /ui/a/jibb
24+#### M1b-root-cycle
25+REJECTED: import cycle at /ui/probe/jibb
26+#### M2-derived-clash
27+REJECTED: API derived name `plain` clashes with a definition
28+/ui/api/demo.jibb:3:3: `plain` is derived from this path case
29+ [%plain /plain full]
30+ ^
31+/ui/api/demo.jibb:5:1: clashing definition
32+++ plain 5
33+^
34+#### M2b-derived-clash-root
35+REJECTED: API derived name `plain` clashes with a definition
36+/ui/api/demo.jibb:3:3: `plain` is derived from this path case
37+ [%plain /plain full]
38+ ^
39+/ui/api/demo.jibb:5:1: clashing definition
40+++ plain 5
41+^
42+#### M2c-derived-face-clash
43+REJECTED: API derived name `plain` clashes with an import face
44+/ui/api/demo.jibb:4:3: `plain` is derived from this path case
45+ [%plain /plain full]
46+ ^
47+/ui/api/demo.jibb:2:1: clashing import face
48+/- plain
49+^
50+#### M2d-poke-clash
51+REJECTED: API derived name `poke` clashes with a definition
52+/ui/api/demo.jibb:2:1: `poke` is derived from this mold
53++$ poke full
54+^
55+/ui/api/demo.jibb:3:1: clashing definition
56+++ poke "bad"
57+^
58+#### M3-facts-in-library
59+REJECTED: module mold needs unsupported inference: /ui/probe/jibb
60+#### M3b-facts-in-api-other-mold
61+REJECTED: API module needs unsupported inference: /ui/api/demo/jibb: module mold needs unsupported inference
62+#### M4-shadow-import-face
63+REJECTED: /ui/probe.jibb:2:9: sample `lib` shadows a name already in scope
64+++ f |= lib=@t lib
65+ ^
66+#### M4b-shadow-import-value
67+REJECTED: module has conflicting names: /ui/probe/jibb
68+#### M5-api-ok
69+CHECKED
70+++ plain: $-($-(@t A) (ask A))
71+#### RAW
72+signed: invalid aura: signed and float auras cannot be imported
73+flt: invalid aura: signed and float auras cannot be imported
74+gat: invalid core: cores and gates cannot be imported
75+vas: unsupported: vases cannot be imported
76+dup: ok
77+ovl: unsupported: Hoon union disjointness could not be verified
78+ovl2: unsupported: Hoon union disjointness could not be verified
79+cel: unsupported: Hoon $^ union disjointness could not be verified
80+good: ok
81+cor: invalid core: cores and gates cannot be imported
82+
docs/reviews/2026-11-03-milestone-2-probes/errors/p1.jibbnew file+155
@@ -0,0 +1,155 @@
1+#### ok-control
2+++ inc |= n=@ud (add n 1)
3+#### E01-aura-call
4+++ inc |= n=@ud (add n 1)
5+++ x (inc "hi")
6+#### E01b-aura-cast
7+++ x ^- @ud "hi"
8+#### E01c-aura-sample-only
9+++ f |= x=@t ^- @ud x
10+#### E01d-at-to-ud
11+++ f |= x=@ ^- @ud x
12+#### E02-faces-call
13+++ f |= p=[a=@ud b=@ud] a.p
14+++ g |= q=[x=@ud y=@ud] (f q)
15+#### E02b-faces-cast
16++$ ab [a=@ud b=@ud]
17++$ xy [x=@ud y=@ud]
18+++ v ^- ab [1 2]
19+++ w ^- xy v
20+#### E03-submitt-cast
21++$ msg
22+ [%typed text=@t]
23+ %submit
24+++ bad ^- msg %submitt
25+#### E03b-submitt-call
26++$ msg
27+ [%typed text=@t]
28+ %submit
29+++ take |= m=msg "ok"
30+++ call (take %submitt)
31+#### E04-unresolved-tag
32+++ absent %submitt
33+#### E04b-add-button
34+++ add-button |= label=@t
35+ button label %add
36+#### E05-open-null
37+++ loose ~
38+#### E06-ctor-no-case
39++$ msg
40+ [%typed text=@t]
41+ %submit
42+++ f ^- $-(@t msg) |=%other
43+#### E07-overlap
44++$ overlap
45+ @t
46+ @ud
47+++ identity |=(x x)
48+#### E07b-overlap-records
49++$ pt
50+ [a=@ud b=@ud]
51+ [x=@ud y=@ud]
52+#### E08-missing-case
53++$ choice
54+ [%a value=@t]
55+ %b
56+ %c
57+++ missing |= v=choice
58+ ?- v
59+ [%a payload] payload
60+ %b "b"
61+#### E08b-missing-loobean
62+++ f |= b=?
63+ ?- b
64+ %.y "yes"
65+#### E09-covered-arm
66++$ choice
67+ [%a value=@t]
68+ %b
69+ %c
70+++ duplicate |= v=choice
71+ ?- v
72+ [%a payload] payload
73+ %b "b"
74+ %b "again"
75+ %c "c"
76+#### E09b-covered-after-wild
77++$ choice
78+ %b
79+ %c
80+++ covered |= v=choice
81+ ?- v
82+ * "all"
83+ %c "never"
84+#### E10-self-ref-doc
85+++ title (trim title)
86+#### E10b-self-ref-cast
87+++ title ^- @t title
88+#### E10c-through-gate
89+++ maker |= x=@t value
90+++ value ^- @t (maker "hi")
91+#### E11-shadow-prelude-sample
92+++ f |= add=@ud add
93+#### E11b-shadow-global-sample
94+++ x 1
95+++ f |= x=@ud x
96+#### E11c-shadow-local
97+++ y 1
98+++ f |= z=@ud
99+ ++ y 2
100+ z
101+#### E11d-shadow-pattern
102++$ choice
103+ [%a value=@t]
104+ %b
105+++ complete "c"
106+++ shadow |= v=choice
107+ ?- v
108+ [%a complete] complete
109+ %b "b"
110+#### E11e-shadow-prelude-top
111+++ add 1
112+#### E11f-shadow-prelude-mold
113++$ list @ud
114+#### E12-cell-printer
115+++ record |= x=[@t @ud] "{x}"
116+#### E13-generic-aura-interp
117+++ show |= n=A "{(add n 1)}"
118+#### E13b-generic-aura-path
119+++ link-to |= n=A %/blog/(add n 1)
120+#### E14-capital-ud
121+++ concrete |= x=A ^- @t x
122+#### E14b-capital-ud-arith
123+++ c |= x=A ^- @ud (add x 1)
124+#### E14c-capital-list
125+++ l |= x=A (lent x)
126+#### E15-text-hi
127+++ v ^- (list (element !!)) ~[text "hi"]
128+#### E16-empty-change
129+++ f |= m=[a=@ud b=@ud] m()
130+#### E17-dup-fields-mold
131++$ r [a=@ud a=@t]
132+++ v ^- r [1 "x"]
133+#### E17b-dup-fields-expr
134+++ v [a=1 a=2]
135+#### E18-proj-defined
136+++ proj 1
137+#### E19-loobean-arith
138+++ v (add %.y %.n)
139+#### E20-capitals-forced
140+++ repeat |= p=[A A] p
141+++ bad |= p=[A B] (repeat p)
142+#### E21-hole-unconstrained
143+++ id |= x=_ x
144+#### E21b-hole-mold
145++$ box [item=_]
146+#### E22-eq-gate
147+++ f |= g=$-(@ud @ud) (eq g g)
148+#### E22b-map-key-gate
149+++ m |= [g=$-(@ud @ud) mp=(map $-(@ud @ud) @ud)] (put.by mp g 1)
150+#### E23-facts-outside
151++$ x (facts @t @t)
152+#### E24-repeat-attr
153+++ v (el ~[pad+%s1 pad+%s2] (text "x"))
154+#### E25-empty-cell
155+++ v []
docs/reviews/2026-11-03-milestone-2-probes/errors/p1.outnew file+133
@@ -0,0 +1,133 @@
1+#### ok-control
2+CHECKED
3+++ inc: $-(@ud @ud)
4+#### E01-aura-call
5+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ x
6+#### E01b-aura-cast
7+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ x
8+#### E01c-aura-sample-only
9+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
10+#### E01d-at-to-ud
11+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
12+#### E02-faces-call
13+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ g
14+#### E02b-faces-cast
15+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ w
16+#### E03-submitt-cast
17+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ bad
18+#### E03b-submitt-call
19+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ call
20+#### E04-unresolved-tag
21+REJECTED: /ui/probe.jibb:1:11: nothing fixes the union of %submitt
22+++ absent %submitt
23+ ^
24+#### E04b-add-button
25+REJECTED: /ui/probe.jibb:2:16: nothing fixes the union of %add
26+ button label %add
27+ ^
28+#### E05-open-null
29+REJECTED: /ui/probe.jibb:1:10: nothing fixes the union of ~
30+++ loose ~
31+ ^
32+#### E06-ctor-no-case
33+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
34+#### E07-overlap
35+REJECTED: module mold overlap has overlapping cases
36+/ui/probe.jibb:2:3: first union case
37+ @t
38+ ^
39+/ui/probe.jibb:3:3: overlapping case
40+ @ud
41+ ^
42+#### E07b-overlap-records
43+REJECTED: module mold pt has overlapping cases
44+/ui/probe.jibb:2:3: first union case
45+ [a=@ud b=@ud]
46+ ^
47+/ui/probe.jibb:3:3: overlapping case
48+ [x=@ud y=@ud]
49+ ^
50+#### E08-missing-case
51+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ missing
52+#### E08b-missing-loobean
53+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
54+#### E09-covered-arm
55+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ duplicate
56+#### E09b-covered-after-wild
57+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ covered
58+#### E10-self-ref-doc
59+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ title
60+#### E10b-self-ref-cast
61+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ title
62+#### E10c-through-gate
63+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ maker
64+#### E11-shadow-prelude-sample
65+REJECTED: /ui/probe.jibb:1:9: sample `add` shadows a name already in scope
66+++ f |= add=@ud add
67+ ^
68+#### E11b-shadow-global-sample
69+REJECTED: /ui/probe.jibb:2:9: sample `x` shadows a name already in scope
70+++ f |= x=@ud x
71+ ^
72+#### E11c-shadow-local
73+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
74+#### E11d-shadow-pattern
75+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ shadow
76+#### E11e-shadow-prelude-top
77+REJECTED: module has conflicting names: /ui/probe/jibb
78+#### E11f-shadow-prelude-mold
79+REJECTED: module has conflicting names: /ui/probe/jibb
80+#### E12-cell-printer
81+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ record
82+#### E13-generic-aura-interp
83+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ show
84+#### E13b-generic-aura-path
85+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ link-to
86+#### E14-capital-ud
87+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ concrete
88+#### E14b-capital-ud-arith
89+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ c
90+#### E14c-capital-list
91+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ l
92+#### E15-text-hi
93+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ v
94+#### E16-empty-change
95+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
96+#### E17-dup-fields-mold
97+REJECTED: record field `a` is repeated
98+/ui/probe.jibb:1:7: first field
99++$ r [a=@ud a=@t]
100+ ^
101+/ui/probe.jibb:1:13: repeated field
102++$ r [a=@ud a=@t]
103+ ^
104+#### E17b-dup-fields-expr
105+REJECTED: record field `a` is repeated
106+/ui/probe.jibb:1:7: first field
107+++ v [a=1 a=2]
108+ ^
109+/ui/probe.jibb:1:11: repeated field
110+++ v [a=1 a=2]
111+ ^
112+#### E18-proj-defined
113+REJECTED: module has conflicting names: /ui/probe/jibb
114+#### E19-loobean-arith
115+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ v
116+#### E20-capitals-forced
117+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ bad
118+#### E21-hole-unconstrained
119+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ id
120+#### E21b-hole-mold
121+REJECTED: module mold needs unsupported inference: /ui/probe/jibb
122+#### E22-eq-gate
123+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
124+#### E22b-map-key-gate
125+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ m
126+#### E23-facts-outside
127+REJECTED: module mold needs unsupported inference: /ui/probe/jibb
128+#### E24-repeat-attr
129+CHECKED
130+++ v: (element A)
131+#### E25-empty-cell
132+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ v
133+
docs/reviews/2026-11-03-milestone-2-probes/errors/p2.jibbnew file+106
@@ -0,0 +1,106 @@
1+#### G1-gate-model
2++$ message
3+ %start
4+ %stop
5++$ model [count=@ud callback=$-(@t @t)]
6+++ main (program init update view subs)
7+++ init |= input=@t ^- model [count=0 callback=echo]
8+++ update |= [msg=message state=model]
9+ ^- [model (list (cmd message))] [state ~]
10+++ view |= state=model ^- (element message) (text "view")
11+++ subs |= state=model ^- (list (sub message)) ~
12+++ echo |= input=@t input
13+#### G2-gate-data
14++$ message
15+ %start
16+ %stop
17++$ model [count=@ud]
18+++ main (program init update view subs)
19+++ init |= input=$-(@t @t) ^- model [count=0]
20+++ update |= [msg=message state=model]
21+ ^- [model (list (cmd message))] [state ~]
22+++ view |= state=model ^- (element message) (text "view")
23+++ subs |= state=model ^- (list (sub message)) ~
24+#### G3-gate-model-nested
25++$ message
26+ %start
27+ %stop
28++$ model [count=@ud inner=[cb=(list $-(@t @t))]]
29+++ main (program init update view subs)
30+++ init |= input=@t ^- model [count=0 inner=[cb=~]]
31+++ update |= [msg=message state=model]
32+ ^- [model (list (cmd message))] [state ~]
33+++ view |= state=model ^- (element message) (text "view")
34+++ subs |= state=model ^- (list (sub message)) ~
35+#### S1-step-missing-stop
36++$ step
37+ [%move %left n=@ud]
38+ [%move %right n=@ud]
39+ [text=@t %draft]
40+ [text=@t %sent at=@da]
41+ %stop
42+++ describe |= s=step
43+ ?- s
44+ [%move %left n] "left {n}"
45+ [%move %right n] "right {n}"
46+ [t %draft] t
47+ [t %sent sent-at] t
48+#### S2-move-any-covered
49++$ step
50+ [%move dir=@tas n=@ud]
51+ %stop
52+++ describe |= s=step
53+ ?- s
54+ [%move * *] "move"
55+ [%move %left n] "left"
56+ %stop "stop"
57+#### S3-loobean-repeated
58+++ f |= flag=? ^- ?
59+ ?- flag
60+ %.y %.y
61+ %.y %.n
62+#### S4-list-missing
63+++ f |= xs=(list @t) ^- ?
64+ ?- xs
65+ ~ %.y
66+#### S5-pattern-no-case
67++$ choice
68+ %a
69+ %b
70+++ f |= v=choice
71+ ?- v
72+ %a "a"
73+ %b "b"
74+ %c "c"
75+#### T1-local-aura
76+++ inc |= n=@ud n
77+++ f |= x=@t
78+ ++ bad (inc %.y)
79+ x
80+#### T2-change-bad-tag
81++$ actions
82+ %start
83+ %stop
84++$ model [mode=actions data=(unit @t)]
85+++ bad-tag |= m=model m(mode=%missing)
86+#### T3-hole-path
87+++ p /todo/[id=_]
88+#### T4-unit-inner
89+++ v ^- (unit @ud) `"x"
90+#### T5-list-item
91+++ v ^- (list @ud) ~[1 "x"]
92+#### T6-repeat-attr-column
93+++ v (column ~[gap+%s1 gap+%s2] ~[(text "x")])
94+#### T7-msg-mismatch-element
95++$ msg
96+ %a
97+ %b
98+++ v ^- (element msg) (button "x" %c)
99+#### T8-generic-aura-path-sample
100+++ link-to |= n=A
101+ ++ m (add n 1)
102+ %/blog/(m)
103+#### T9-wing-unknown-field
104+++ f |= p=[a=@ud b=@ud] c.p
105+#### T10-unknown-name
106+++ f missing
docs/reviews/2026-11-03-milestone-2-probes/errors/p2.outnew file+38
@@ -0,0 +1,38 @@
1+#### G1-gate-model
2+REJECTED: module kind needs unsupported inference: /ui/probe/jibb
3+#### G2-gate-data
4+REJECTED: module kind needs unsupported inference: /ui/probe/jibb
5+#### G3-gate-model-nested
6+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ init
7+#### S1-step-missing-stop
8+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ describe
9+#### S2-move-any-covered
10+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ describe
11+#### S3-loobean-repeated
12+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
13+#### S4-list-missing
14+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
15+#### S5-pattern-no-case
16+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
17+#### T1-local-aura
18+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
19+#### T2-change-bad-tag
20+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ bad-tag
21+#### T3-hole-path
22+REJECTED: module source does not parse: /ui/probe/jibb
23+#### T4-unit-inner
24+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ v
25+#### T5-list-item
26+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ v
27+#### T6-repeat-attr-column
28+CHECKED
29+++ v: (element A)
30+#### T7-msg-mismatch-element
31+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ v
32+#### T8-generic-aura-path-sample
33+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ link-to
34+#### T9-wing-unknown-field
35+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
36+#### T10-unknown-name
37+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ f
38+
docs/reviews/2026-11-03-milestone-2-probes/errors/p3.jibbnew file+68
@@ -0,0 +1,68 @@
1+#### C0-island-ok
2++$ msg
3+ [%typed text=@t]
4+ %submit
5++$ model [draft=@t]
6+++ main (program init update view subs)
7+++ init |= input=@t ^- model [draft=input]
8+++ update |= [=msg m=model]
9+ ^- [model (list (cmd msg))]
10+ ?- msg
11+ [%typed t] [m(draft=t) ~]
12+ %submit [m(draft="") ~]
13+++ view |= m=model ^- (element msg)
14+ row ~[gap+%s1] ~[
15+ (field "New todo" draft.m |=%typed)
16+ button "Add" %submit
17+++ subs |= m=model ^- (list (sub msg)) ~
18+#### C1-island-submitt-view
19++$ msg
20+ [%typed text=@t]
21+ %submit
22++$ model [draft=@t]
23+++ main (program init update view subs)
24+++ init |= input=@t ^- model [draft=input]
25+++ update |= [=msg m=model]
26+ ^- [model (list (cmd msg))]
27+ ?- msg
28+ [%typed t] [m(draft=t) ~]
29+ %submit [m(draft="") ~]
30+++ view |= m=model ^- (element msg)
31+ row ~[gap+%s1] ~[
32+ (field "New todo" draft.m |=%typed)
33+ button "Add" %submitt
34+++ subs |= m=model ^- (list (sub msg)) ~
35+#### C2-island-submitt-noview-cast
36++$ msg
37+ [%typed text=@t]
38+ %submit
39++$ model [draft=@t]
40+++ main (program init update view subs)
41+++ init |= input=@t ^- model [draft=input]
42+++ update |= [=msg m=model]
43+ ^- [model (list (cmd msg))]
44+ ?- msg
45+ [%typed t] [m(draft=t) ~]
46+ %submit [m(draft="") ~]
47+++ view |= m=model
48+ row ~[gap+%s1] ~[
49+ (field "New todo" draft.m |=%typed)
50+ button "Add" %submitt
51+++ subs |= m=model ^- (list (sub msg)) ~
52+#### C3-island-ctor-typo
53++$ msg
54+ [%typed text=@t]
55+ %submit
56++$ model [draft=@t]
57+++ main (program init update view subs)
58+++ init |= input=@t ^- model [draft=input]
59+++ update |= [=msg m=model]
60+ ^- [model (list (cmd msg))]
61+ ?- msg
62+ [%typed t] [m(draft=t) ~]
63+ %submit [m(draft="") ~]
64+++ view |= m=model ^- (element msg)
65+ row ~[gap+%s1] ~[
66+ (field "New todo" draft.m |=%typd)
67+ button "Add" %submit
68+++ subs |= m=model ^- (list (sub msg)) ~
docs/reviews/2026-11-03-milestone-2-probes/errors/p3.outnew file+16
@@ -0,0 +1,16 @@
1+#### C0-island-ok
2+CHECKED
3++$ msg: msg
4++$ model: [draft=@t]
5+++ main: [init=$-(@t [draft=@t]) [update=$-([msg draft=@t] [draft=@t (list (cmd msg))]) [view=$-([draft=@t] (element msg)) subs=$-([draft=@t] (list (sub msg)))]]]
6+++ subs: $-([draft=@t] (list (sub msg)))
7+++ view: $-([draft=@t] (element msg))
8+++ update: $-([msg=msg m=[draft=@t]] [draft=@t (list (cmd msg))])
9+++ init: $-(@t [draft=@t])
10+#### C1-island-submitt-view
11+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ view
12+#### C2-island-submitt-noview-cast
13+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ view
14+#### C3-island-ctor-typo
15+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ view
16+
docs/reviews/2026-11-03-milestone-2-probes/errors/p4.jibbnew file+30
@@ -0,0 +1,30 @@
1+#### X1-multiarg-site
2+++ v (add 1 "x")
3+#### X2-pt-valid
4++$ pt
5+ @t
6+ [@ud @ud]
7+++ a ^- pt "x"
8+#### X3-pt-faced-cases
9++$ pt
10+ x=@ud
11+ y=@ud
12+#### X4-pt-tuple-meant
13++$ pt
14+ @ud
15+ @ud
16+#### X5-step-doc-missing-stop
17++$ step
18+ [%move %left n=@ud]
19+ [%move %right n=@ud]
20+ [text=@t %draft]
21+ [text=@t %sent at=@da]
22+ %stop
23+++ describe |= s=step
24+ ?- s
25+ [%move %left n] "left {n}"
26+ [%move %right n] "right {n}"
27+ [t %draft] t
28+ [t %sent sent-at] t
29+#### X6-title-trim-annotated
30+++ title ^- @t (trim title)
docs/reviews/2026-11-03-milestone-2-probes/errors/p4.outnew file+22
@@ -0,0 +1,22 @@
1+#### X1-multiarg-site
2+CHECKED
3+++ v: @t
4+#### X2-pt-valid
5+CHECKED
6++$ pt: pt
7+++ a: pt
8+#### X3-pt-faced-cases
9+REJECTED: module source does not parse: /ui/probe/jibb
10+#### X4-pt-tuple-meant
11+REJECTED: module mold pt has overlapping cases
12+/ui/probe.jibb:2:3: first union case
13+ @ud
14+ ^
15+/ui/probe.jibb:3:3: overlapping case
16+ @ud
17+ ^
18+#### X5-step-doc-missing-stop
19+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ describe
20+#### X6-title-trim-annotated
21+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ title
22+
docs/reviews/2026-11-03-milestone-2-probes/errors/p5.jibbnew file+45
@@ -0,0 +1,45 @@
1+#### W1-initializer-error
2++$ model [xs=(list @t) draft=@t error=@t]
3++$ message
4+ %start
5+ %stop
6+++ main (program init update view subs)
7+++ init |= ts=(list @t) [ts "" ~]
8+++ update |= [msg=message state=model]
9+ ^- [model (list (cmd message))] [state ~]
10+++ view |= state=model ^- (element message) (text "view")
11+++ subs |= state=model ^- (list (sub message)) ~
12+#### W2-initializer-earlier
13++$ model [xs=(list @t) draft=@t error=(unit @t)]
14++$ message
15+ %start
16+ %stop
17+++ main (program init update view subs)
18+++ init |= ts=(list @t) [ts ~zod ~]
19+++ update |= [msg=message state=model]
20+ ^- [model (list (cmd message))] [state ~]
21+++ view |= state=model ^- (element message) (text "view")
22+++ subs |= state=model ^- (list (sub message)) ~
23+#### W3-initializer-model
24++$ model [xs=(list @t) draft=@t error=(unit @t)]
25++$ other [xs=(list @t) draft=@t error=(unit @t) extra=@ud]
26++$ message
27+ %start
28+ %stop
29+++ main (program init update view subs)
30+++ init |= ts=(list @t) [ts "" ~]
31+++ update |= [msg=message state=other]
32+ ^- [other (list (cmd message))] [state ~]
33+++ view |= state=model ^- (element message) (text "view")
34+++ subs |= state=model ^- (list (sub message)) ~
35+#### W4-earlier-annotated
36++$ model [xs=(list @t) draft=@t error=(unit @t)]
37++$ message
38+ %start
39+ %stop
40+++ main (program init update view subs)
41+++ init |= ts=(list @t) ^- model [ts ~zod ~]
42+++ update |= [msg=message state=model]
43+ ^- [model (list (cmd message))] [state ~]
44+++ view |= state=model ^- (element message) (text "view")
45+++ subs |= state=model ^- (list (sub message)) ~
docs/reviews/2026-11-03-milestone-2-probes/runnew file+46
@@ -0,0 +1,46 @@
1+#!/bin/sh
2+# Rerun the milestone 2 review's probes through the full module checker,
3+# infer-jibb-file-detailed, from the repo root:
4+#
5+# docs/reviews/2026-11-03-milestone-2-probes/run plain FILE one module per section
6+# docs/reviews/2026-11-03-milestone-2-probes/run app FILE sections at my-app paths, with its imports
7+# docs/reviews/2026-11-03-milestone-2-probes/run imports the Hoon import errors
8+#
9+# FILE holds sections, each starting with a line "#### <label>"; see README.md.
10+set -e
11+HERE=$(cd "$(dirname "$0")" && pwd)
12+ROOT=$(cd "$HERE/../../.." && pwd)
13+cd "$ROOT"
14+TMP=$(mktemp -d)
15+trap 'rm -rf "$TMP"' EXIT
16+PRELUDE="--cord prelude=jibb-dev/lib/jibb/prelude.jibb --cord internal=jibb-dev/lib/jibb/internal.jibb"
17+case "$1" in
18+ plain)
19+ tools/hoon --raw $PRELUDE --cord src="$2" -f "$HERE/check.hoon"
20+ ;;
21+ app)
22+ # Marks without their /- lines, which ride can't parse; the check binds
23+ # the /sur face by hand, as the tests/lib suites do.
24+ for m in todo-action todos todo-update todo-item posts; do
25+ grep -v '^/-' "my-app/mar/$m.hoon" > "$TMP/$m.hoon"
26+ done
27+ { printf '=/ imp\n => ..zuse\n'; cat jibb-dev/lib/jibb-import.hoon; cat "$HERE/app-check.hoon"; } > "$TMP/check.hoon"
28+ tools/hoon --raw $PRELUDE \
29+ --cord sur=my-app/sur/todo.hoon --cord blogsur=my-app/sur/blog.hoon \
30+ --cord action="$TMP/todo-action.hoon" --cord todos="$TMP/todos.hoon" \
31+ --cord update="$TMP/todo-update.hoon" --cord item="$TMP/todo-item.hoon" \
32+ --cord posts="$TMP/posts.hoon" \
33+ --cord todoapi=my-app/ui/api/todo.jibb --cord todolist=my-app/ui/todo-list.jibb \
34+ --cord blogapi=my-app/ui/api/blog.jibb --cord card=my-app/ui/components/card.jibb \
35+ --cord cart=my-app/ui/stores/cart.jibb \
36+ --cord src="$2" -f "$TMP/check.hoon"
37+ ;;
38+ imports)
39+ { printf '=/ jibb-lib .\n=/ reader\n'; cat jibb-dev/lib/jibb-import.hoon; printf '\n'; cat "$HERE/errors/import-check.hoon"; } > "$TMP/check.hoon"
40+ tools/hoon --raw $PRELUDE -f "$TMP/check.hoon"
41+ ;;
42+ *)
43+ sed -n '2,10p' "$0"
44+ exit 2
45+ ;;
46+esac
docs/reviews/2026-11-03-milestone-2-probes/variants/p1.jibbnew file+194
@@ -0,0 +1,194 @@
1+#### /ui/api/todo/jibb api-todo
2+:: /ui/api/todo.jibb
3+/- todo
4+/% %todo-action
5+/% %todos
6+/% %todo-update
7+/% %todo-item
8+
9++$ item item.todo
10++$ poke todo-action
11++$ paths
12+ [%todos /todos todos]
13+ [%changes /changes (facts todos todo-update)]
14+ [%todo-by-id /todo/[id=@ud] todo-item]
15+#### /ui/api/blog/jibb api-blog
16+:: Fixture for the documented examples; not supplied by the design doc.
17+/% %posts
18+
19++$ paths
20+ [%posts /posts posts]
21+#### /ui/components/card/jibb card
22+:: Fixture for the documented examples; not supplied by the design doc.
23+/- blog
24+
25+++ card |= p=post.blog
26+ text title.p
27+#### /ui/components/buttons/jibb buttons
28+:: /ui/components/buttons.jibb, a library with no main
29+++ add-button |= label=@t
30+ button label %add :: error: nothing fixes the union of %add
31+++ labelled |= [label=@t msg=M]
32+ button label msg :: fine: the caller's union
33+++ wide ^- (list attr)
34+ ~[width+[%fill 1] pad+%s2] :: fine: the cast fixes the tags
35+#### /ui/theme/jibb theme
36+++ theme ^- theme
37+ [ space=[s1="4px" s2="8px" s3="16px"]
38+ tones=[normal="#222" background="#fff" accent="#17734f" danger="#b3261e" muted="#5f5f5f"]
39+ wide="60rem"
40+ lang="en"
41+ zone="UTC"
42+ font=`%/static/fonts/inter.woff2
43+ dark=`[tones=[normal="#eee" background="#111" accent="#4c9" danger="#f28b82" muted="#aaa"]]
44+#### /ui/stores/cart/jibb cart
45+:: /ui/stores/cart.jibb
46++$ state [items=(list @t) open=?]
47++$ poke
48+ [%add item=@t]
49+ %toggle
50+
51+++ main (store init update)
52+++ init ^- state [items=~ open=%.n]
53+++ update |= [a=poke s=state]
54+ ?- a
55+ [%add item] s(items=[item items.s])
56+ %toggle s(open=(not open.s))
57+#### /ui/basket/jibb basket
58+:: /ui/basket.jibb
59+/= cart /ui/stores/cart
60+
61+++ main (program init update view subs)
62+
63++$ model [cart=state.cart note=@t]
64++$ msg
65+ [%noted text=@t]
66+ %add
67+ %toggle
68+ [%got cart=state.cart]
69+ [%acked err=(unit @t)]
70+
71+++ init |= ~
72+ [cart=[items=~ open=%.n] note=""]
73+
74+++ update |= [=msg m=model]
75+ ?- msg
76+ [%noted t] [m(note=t) ~]
77+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
78+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
79+ [%got c] [m(cart=c) ~]
80+ [%acked err] [m ~]
81+
82+++ subs |= m=model
83+ ~[[%watch (state.cart |=%got)]]
84+
85+++ view |= m=model
86+ column ~[gap+%s1] ~[
87+ (text "{(lent items.cart.m)} items")
88+ field "Item" note.m |=%noted
89+ button "Add" %add
90+#### /ui/todo-list/jibb todo-list
91+/= todo /ui/api/todo
92+
93+++ main (program init update view subs)
94+
95++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
96++$ msg
97+ [%typed text=@t]
98+ %submit
99+ [%toggled id=@ud]
100+ [%got todos=(list item.todo)]
101+ [%acked err=(unit @t)]
102+
103+++ init |= ts=(list item.todo)
104+ [todos=ts draft="" error=~]
105+
106+++ update |= [=msg m=model]
107+ ?- msg
108+ [%typed t]
109+ ?- (gth (lent (tuba (trip t))) 80)
110+ %.y [m(draft=t error=`"Too long") ~]
111+ %.n [m(draft=t error=~) ~]
112+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
113+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
114+ [%got ts] [m(todos=ts) ~]
115+ [%acked err] [m(error=err) ~]
116+
117+++ subs |= m=model
118+ ~[[%watch (todos.todo |=%got)]]
119+
120+++ view |= m=model
121+ column ~[gap+%s2] ~[
122+ heading 2 "Todos"
123+ each (turn todos.m row-of)
124+ row ~[gap+%s1] ~[
125+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
126+ button "Add" %submit
127+ el ~[tone+%danger] (text (fall error.m ""))
128+
129+++ row-of |= t=item.todo
130+ [id.t (toggle done.t text.t [%toggled id.t])]
131+#### /ui/index/jibb index
132+/= todo /ui/api/todo
133+/= todo-list /ui/todo-list
134+
135+++ main (page load view)
136+++ load |=(~ (todos.todo same))
137+
138+++ view |= ts=(list item.todo)
139+ column ~[pad+%s3] ~[
140+ heading 1 "My ship"
141+ island main.todo-list ts
142+#### /ui/about/jibb about
143+++ main view
144+
145+++ view
146+ column ~[width+[%fill 1] pad+%s3 gap+%s2] ~[
147+ heading 1 "About this ship"
148+ para ~[(text "Hosted on Urbit. This page ships no JavaScript.")]
149+ el ~[tone+%accent] (link %/blog "Read the blog")
150+#### /ui/blog/index/jibb blog-index
151+/- blog
152+/= api /ui/api/blog
153+/= card /ui/components/card
154+
155+++ main (page load view)
156+++ load |=(~ (posts.api same))
157+
158+++ view |= ps=(list post.blog)
159+ column ~[gap+%s2] (turn ps card.card)
160+#### /ui/imports/jibb imports
161+/- todo :: the molds from /sur/todo.hoon this module uses
162+/% %todo-action :: a mark's type, named todo-action
163+/= card /ui/components/card :: a Jibb module
164+#### /ui/view-day/jibb view-day
165+++ view |= [day=@da n=@ud]
166+ column ~[gap+%s1] ~[
167+ (text "Updated {day}") :: day printed as a date
168+ (text "{n} items") :: n printed as @ud
169+#### /ui/step/jibb step
170++$ step
171+ [%move %left n=@ud]
172+ [%move %right n=@ud]
173+ [text=@t %draft]
174+ [text=@t %sent at=@da]
175+ %stop
176+
177+++ describe |= s=step
178+ ?- s
179+ [%move %left n] "left {n}"
180+ [%move %right n] "right {n}"
181+ [t %draft] t
182+ [t %sent sent-at] t
183+ %stop "stop"
184+#### /ui/update/jibb core-update-alone
185+++ update |= [=msg m=model]
186+ ?- msg
187+ [%typed t]
188+ ?- (gth (lent (tuba (trip t))) 80)
189+ %.y [m(draft=t error=`"Too long") ~]
190+ %.n [m(draft=t error=~) ~]
191+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
192+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
193+ [%got ts] [m(todos=ts) ~]
194+ [%acked err] [m(error=err) ~]
docs/reviews/2026-11-03-milestone-2-probes/variants/p10.jibbnew file+324
@@ -0,0 +1,324 @@
1+#### /ui/index/jibb BAD-island-data-atom
2+/= todo /ui/api/todo
3+/= todo-list /ui/todo-list
4+
5+++ main (page load view)
6+++ load |=(~ (todos.todo same))
7+
8+++ view |= ts=(list item.todo)
9+ column ~[pad+%s3] ~[
10+ heading 1 "My ship"
11+ island main.todo-list 5
12+#### /ui/index/jibb BAD-view-sample
13+/= todo /ui/api/todo
14+/= todo-list /ui/todo-list
15+
16+++ main (page load view)
17+++ load |=(~ (todos.todo same))
18+
19+++ view |= ts=(list @t)
20+ column ~[pad+%s3] ~[
21+ heading 1 "My ship"
22+ text "x"
23+#### /ui/todo-list/jibb BAD-cmd-bare-tag
24+/= todo /ui/api/todo
25+
26+++ main (program init update view subs)
27+
28++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
29++$ msg
30+ [%typed text=@t]
31+ %submit
32+ [%toggled id=@ud]
33+ [%got todos=(list item.todo)]
34+ [%acked err=(unit @t)]
35+
36+++ init |= ts=(list item.todo)
37+ [todos=ts draft="" error=~]
38+
39+++ update |= [=msg m=model]
40+ ?- msg
41+ [%typed t]
42+ ?- (gth (lent (tuba (trip t))) 80)
43+ %.y [m(draft=t error=`"Too long") ~]
44+ %.n [m(draft=t error=~) ~]
45+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
46+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
47+ [%got ts] [m(todos=ts) ~[%submit]]
48+ [%acked err] [m(error=err) ~]
49+
50+++ subs |= m=model
51+ ~[[%watch (todos.todo |=%got)]]
52+
53+++ view |= m=model
54+ column ~[gap+%s2] ~[
55+ heading 2 "Todos"
56+ each (turn todos.m row-of)
57+ row ~[gap+%s1] ~[
58+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
59+ button "Add" %submit
60+ el ~[tone+%danger] (text (fall error.m ""))
61+
62+++ row-of |= t=item.todo
63+ [id.t (toggle done.t text.t [%toggled id.t])]
64+#### /ui/basket/jibb BAD-cart-poke-case
65+:: /ui/basket.jibb
66+/= cart /ui/stores/cart
67+
68+++ main (program init update view subs)
69+
70++$ model [cart=state.cart note=@t]
71++$ msg
72+ [%noted text=@t]
73+ %add
74+ %toggle
75+ [%got cart=state.cart]
76+ [%acked err=(unit @t)]
77+
78+++ init |= ~
79+ [cart=[items=~ open=%.n] note=""]
80+
81+++ update |= [=msg m=model]
82+ ?- msg
83+ [%noted t] [m(note=t) ~]
84+ %add [m(note="") ~[(poke.cart [%remove note.m] |=%acked)]]
85+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
86+ [%got c] [m(cart=c) ~]
87+ [%acked err] [m ~]
88+
89+++ subs |= m=model
90+ ~[[%watch (state.cart |=%got)]]
91+
92+++ view |= m=model
93+ column ~[gap+%s1] ~[
94+ (text "{(lent items.cart.m)} items")
95+ field "Item" note.m |=%noted
96+ button "Add" %add
97+#### /ui/todo-list/jibb BAD-watch-reply
98+/= todo /ui/api/todo
99+
100+++ main (program init update view subs)
101+
102++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
103++$ msg
104+ [%typed text=@t]
105+ %submit
106+ [%toggled id=@ud]
107+ [%got todos=(list item.todo)]
108+ [%acked err=(unit @t)]
109+
110+++ init |= ts=(list item.todo)
111+ [todos=ts draft="" error=~]
112+
113+++ update |= [=msg m=model]
114+ ?- msg
115+ [%typed t]
116+ ?- (gth (lent (tuba (trip t))) 80)
117+ %.y [m(draft=t error=`"Too long") ~]
118+ %.n [m(draft=t error=~) ~]
119+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
120+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
121+ [%got ts] [m(todos=ts) ~]
122+ [%acked err] [m(error=err) ~]
123+
124+++ subs |= m=model
125+ ~[[%watch (todos.todo |=%acked)]]
126+
127+++ view |= m=model
128+ column ~[gap+%s2] ~[
129+ heading 2 "Todos"
130+ each (turn todos.m row-of)
131+ row ~[gap+%s1] ~[
132+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
133+ button "Add" %submit
134+ el ~[tone+%danger] (text (fall error.m ""))
135+
136+++ row-of |= t=item.todo
137+ [id.t (toggle done.t text.t [%toggled id.t])]
138+#### /ui/stores/cart/jibb BAD-cart-open-num
139+:: /ui/stores/cart.jibb
140++$ state [items=(list @t) open=?]
141++$ poke
142+ [%add item=@t]
143+ %toggle
144+
145+++ main (store init update)
146+++ init ^- state [items=~ open=%.n]
147+++ update |= [a=poke s=state]
148+ ?- a
149+ [%add item] s(items=[item items.s])
150+ %toggle s(open=5)
151+#### /ui/todo-list/jibb BAD-init-error-cord
152+/= todo /ui/api/todo
153+
154+++ main (program init update view subs)
155+
156++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
157++$ msg
158+ [%typed text=@t]
159+ %submit
160+ [%toggled id=@ud]
161+ [%got todos=(list item.todo)]
162+ [%acked err=(unit @t)]
163+
164+++ init |= ts=(list item.todo)
165+ [todos=ts draft="" error="x"]
166+
167+++ update |= [=msg m=model]
168+ ?- msg
169+ [%typed t]
170+ ?- (gth (lent (tuba (trip t))) 80)
171+ %.y [m(draft=t error=`"Too long") ~]
172+ %.n [m(draft=t error=~) ~]
173+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
174+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
175+ [%got ts] [m(todos=ts) ~]
176+ [%acked err] [m(error=err) ~]
177+
178+++ subs |= m=model
179+ ~[[%watch (todos.todo |=%got)]]
180+
181+++ view |= m=model
182+ column ~[gap+%s2] ~[
183+ heading 2 "Todos"
184+ each (turn todos.m row-of)
185+ row ~[gap+%s1] ~[
186+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
187+ button "Add" %submit
188+ el ~[tone+%danger] (text (fall error.m ""))
189+
190+++ row-of |= t=item.todo
191+ [id.t (toggle done.t text.t [%toggled id.t])]
192+#### /ui/todo-list/jibb BAD-model-gate
193+/= todo /ui/api/todo
194+
195+++ main (program init update view subs)
196+
197++$ model [todos=(list item.todo) draft=@t error=(unit @t) f=$-(@t @t)]
198++$ msg
199+ [%typed text=@t]
200+ %submit
201+ [%toggled id=@ud]
202+ [%got todos=(list item.todo)]
203+ [%acked err=(unit @t)]
204+
205+++ init |= ts=(list item.todo)
206+ [todos=ts draft="" error=~ f=same]
207+
208+++ update |= [=msg m=model]
209+ ?- msg
210+ [%typed t]
211+ ?- (gth (lent (tuba (trip t))) 80)
212+ %.y [m(draft=t error=`"Too long") ~]
213+ %.n [m(draft=t error=~) ~]
214+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
215+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
216+ [%got ts] [m(todos=ts) ~]
217+ [%acked err] [m(error=err) ~]
218+
219+++ subs |= m=model
220+ ~[[%watch (todos.todo |=%got)]]
221+
222+++ view |= m=model
223+ column ~[gap+%s2] ~[
224+ heading 2 "Todos"
225+ each (turn todos.m row-of)
226+ row ~[gap+%s1] ~[
227+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
228+ button "Add" %submit
229+ el ~[tone+%danger] (text (fall error.m ""))
230+
231+++ row-of |= t=item.todo
232+ [id.t (toggle done.t text.t [%toggled id.t])]
233+#### /ui/blog/index/jibb BAD-card-wrong
234+/- blog
235+/= api /ui/api/blog
236+/= card /ui/components/card
237+
238+++ main (page load view)
239+++ load |=(~ (posts.api same))
240+
241+++ view |= ps=(list post.blog)
242+ column ~[gap+%s2] (turn ps |=(p=post.blog p))
243+#### /ui/todo-list/jibb BAD-poke-payload
244+/= todo /ui/api/todo
245+
246+++ main (program init update view subs)
247+
248++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
249++$ msg
250+ [%typed text=@t]
251+ %submit
252+ [%toggled id=@ud]
253+ [%got todos=(list item.todo)]
254+ [%acked err=(unit @t)]
255+
256+++ init |= ts=(list item.todo)
257+ [todos=ts draft="" error=~]
258+
259+++ update |= [=msg m=model]
260+ ?- msg
261+ [%typed t]
262+ ?- (gth (lent (tuba (trip t))) 80)
263+ %.y [m(draft=t error=`"Too long") ~]
264+ %.n [m(draft=t error=~) ~]
265+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
266+ [%toggled id] [m ~[(poke.todo [%toggle "x"] |=%acked)]]
267+ [%got ts] [m(todos=ts) ~]
268+ [%acked err] [m(error=err) ~]
269+
270+++ subs |= m=model
271+ ~[[%watch (todos.todo |=%got)]]
272+
273+++ view |= m=model
274+ column ~[gap+%s2] ~[
275+ heading 2 "Todos"
276+ each (turn todos.m row-of)
277+ row ~[gap+%s1] ~[
278+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
279+ button "Add" %submit
280+ el ~[tone+%danger] (text (fall error.m ""))
281+
282+++ row-of |= t=item.todo
283+ [id.t (toggle done.t text.t [%toggled id.t])]
284+#### /ui/todo-list/jibb BAD-row-key-gate
285+/= todo /ui/api/todo
286+
287+++ main (program init update view subs)
288+
289++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
290++$ msg
291+ [%typed text=@t]
292+ %submit
293+ [%toggled id=@ud]
294+ [%got todos=(list item.todo)]
295+ [%acked err=(unit @t)]
296+
297+++ init |= ts=(list item.todo)
298+ [todos=ts draft="" error=~]
299+
300+++ update |= [=msg m=model]
301+ ?- msg
302+ [%typed t]
303+ ?- (gth (lent (tuba (trip t))) 80)
304+ %.y [m(draft=t error=`"Too long") ~]
305+ %.n [m(draft=t error=~) ~]
306+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
307+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
308+ [%got ts] [m(todos=ts) ~]
309+ [%acked err] [m(error=err) ~]
310+
311+++ subs |= m=model
312+ ~[[%watch (todos.todo |=%got)]]
313+
314+++ view |= m=model
315+ column ~[gap+%s2] ~[
316+ heading 2 "Todos"
317+ each (turn todos.m row-of)
318+ row ~[gap+%s1] ~[
319+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
320+ button "Add" %submit
321+ el ~[tone+%danger] (text (fall error.m ""))
322+
323+++ row-of |= t=item.todo
324+ [same (toggle done.t text.t [%toggled id.t])]
docs/reviews/2026-11-03-milestone-2-probes/variants/p10.outnew file+33
@@ -0,0 +1,33 @@
1+#### /ui/index/jibb BAD-island-data-atom
2+REJECTED: module definitions need unsupported inference: /ui/index/jibb: ++ view
3+#### /ui/index/jibb BAD-view-sample
4+REJECTED: module definitions need unsupported inference: /ui/index/jibb: ++ main
5+#### /ui/todo-list/jibb BAD-cmd-bare-tag
6+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
7+ [todos=ts draft="" error=~]
8+ ^
9+#### /ui/basket/jibb BAD-cart-poke-case
10+REJECTED: /ui/basket.jibb:15:16: nothing fixes the union of ~
11+ [cart=[items=~ open=%.n] note=""]
12+ ^
13+#### /ui/todo-list/jibb BAD-watch-reply
14+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
15+ [todos=ts draft="" error=~]
16+ ^
17+#### /ui/stores/cart/jibb BAD-cart-open-num
18+REJECTED: module definitions need unsupported inference: /ui/stores/cart/jibb: ++ update
19+#### /ui/todo-list/jibb BAD-init-error-cord
20+REJECTED: module definitions need unsupported inference: /ui/todo-list/jibb: ++ main
21+#### /ui/todo-list/jibb BAD-model-gate
22+REJECTED: module kind needs unsupported inference: /ui/todo-list/jibb
23+#### /ui/blog/index/jibb BAD-card-wrong
24+REJECTED: module definitions need unsupported inference: /ui/blog/index/jibb: ++ view
25+#### /ui/todo-list/jibb BAD-poke-payload
26+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
27+ [todos=ts draft="" error=~]
28+ ^
29+#### /ui/todo-list/jibb BAD-row-key-gate
30+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
31+ [todos=ts draft="" error=~]
32+ ^
33+
docs/reviews/2026-11-03-milestone-2-probes/variants/p2.jibbnew file+919
@@ -0,0 +1,919 @@
1+#### /ui/todo-list/jibb control
2+/= todo /ui/api/todo
3+
4+++ main (program init update view subs)
5+
6++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
7++$ msg
8+ [%typed text=@t]
9+ %submit
10+ [%toggled id=@ud]
11+ [%got todos=(list item.todo)]
12+ [%acked err=(unit @t)]
13+
14+++ init |= ts=(list item.todo)
15+ [todos=ts draft="" error=~]
16+
17+++ update |= [=msg m=model]
18+ ?- msg
19+ [%typed t]
20+ ?- (gth (lent (tuba (trip t))) 80)
21+ %.y [m(draft=t error=`"Too long") ~]
22+ %.n [m(draft=t error=~) ~]
23+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
24+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
25+ [%got ts] [m(todos=ts) ~]
26+ [%acked err] [m(error=err) ~]
27+
28+++ subs |= m=model
29+ ~[[%watch (todos.todo |=%got)]]
30+
31+++ view |= m=model
32+ column ~[gap+%s2] ~[
33+ heading 2 "Todos"
34+ each (turn todos.m row-of)
35+ row ~[gap+%s1] ~[
36+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
37+ button "Add" %submit
38+ el ~[tone+%danger] (text (fall error.m ""))
39+
40+++ row-of |= t=item.todo
41+ [id.t (toggle done.t text.t [%toggled id.t])]
42+#### /ui/todo-list/jibb reorder
43+/= todo /ui/api/todo
44+
45+++ row-of |= t=item.todo
46+ [id.t (toggle done.t text.t [%toggled id.t])]
47+
48+++ view |= m=model
49+ column ~[gap+%s2] ~[
50+ heading 2 "Todos"
51+ each (turn todos.m row-of)
52+ row ~[gap+%s1] ~[
53+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
54+ button "Add" %submit
55+ el ~[tone+%danger] (text (fall error.m ""))
56+
57+++ subs |= m=model
58+ ~[[%watch (todos.todo |=%got)]]
59+
60+++ update |= [=msg m=model]
61+ ?- msg
62+ [%typed t]
63+ ?- (gth (lent (tuba (trip t))) 80)
64+ %.y [m(draft=t error=`"Too long") ~]
65+ %.n [m(draft=t error=~) ~]
66+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
67+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
68+ [%got ts] [m(todos=ts) ~]
69+ [%acked err] [m(error=err) ~]
70+
71+++ init |= ts=(list item.todo)
72+ [todos=ts draft="" error=~]
73+
74++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
75++$ msg
76+ [%typed text=@t]
77+ %submit
78+ [%toggled id=@ud]
79+ [%got todos=(list item.todo)]
80+ [%acked err=(unit @t)]
81+
82+++ main (program init update view subs)
83+#### /ui/todo-list/jibb rename-view-sample
84+/= todo /ui/api/todo
85+
86+++ main (program init update view subs)
87+
88++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
89++$ msg
90+ [%typed text=@t]
91+ %submit
92+ [%toggled id=@ud]
93+ [%got todos=(list item.todo)]
94+ [%acked err=(unit @t)]
95+
96+++ init |= ts=(list item.todo)
97+ [todos=ts draft="" error=~]
98+
99+++ update |= [=msg m=model]
100+ ?- msg
101+ [%typed t]
102+ ?- (gth (lent (tuba (trip t))) 80)
103+ %.y [m(draft=t error=`"Too long") ~]
104+ %.n [m(draft=t error=~) ~]
105+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
106+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
107+ [%got ts] [m(todos=ts) ~]
108+ [%acked err] [m(error=err) ~]
109+
110+++ subs |= m=model
111+ ~[[%watch (todos.todo |=%got)]]
112+
113+++ view |= mdl=model
114+ column ~[gap+%s2] ~[
115+ heading 2 "Todos"
116+ each (turn todos.mdl row-of)
117+ row ~[gap+%s1] ~[
118+ el ~[width+[%fill 1]] (field "New todo" draft.mdl |=%typed)
119+ button "Add" %submit
120+ el ~[tone+%danger] (text (fall error.mdl ""))
121+
122+++ row-of |= t=item.todo
123+ [id.t (toggle done.t text.t [%toggled id.t])]
124+#### /ui/todo-list/jibb rename-row-sample
125+/= todo /ui/api/todo
126+
127+++ main (program init update view subs)
128+
129++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
130++$ msg
131+ [%typed text=@t]
132+ %submit
133+ [%toggled id=@ud]
134+ [%got todos=(list item.todo)]
135+ [%acked err=(unit @t)]
136+
137+++ init |= ts=(list item.todo)
138+ [todos=ts draft="" error=~]
139+
140+++ update |= [=msg m=model]
141+ ?- msg
142+ [%typed t]
143+ ?- (gth (lent (tuba (trip t))) 80)
144+ %.y [m(draft=t error=`"Too long") ~]
145+ %.n [m(draft=t error=~) ~]
146+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
147+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
148+ [%got ts] [m(todos=ts) ~]
149+ [%acked err] [m(error=err) ~]
150+
151+++ subs |= m=model
152+ ~[[%watch (todos.todo |=%got)]]
153+
154+++ view |= m=model
155+ column ~[gap+%s2] ~[
156+ heading 2 "Todos"
157+ each (turn todos.m row-of)
158+ row ~[gap+%s1] ~[
159+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
160+ button "Add" %submit
161+ el ~[tone+%danger] (text (fall error.m ""))
162+
163+++ row-of |= it=item.todo
164+ [id.it (toggle done.it text.it [%toggled id.it])]
165+#### /ui/todo-list/jibb rename-init-sample
166+/= todo /ui/api/todo
167+
168+++ main (program init update view subs)
169+
170++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
171++$ msg
172+ [%typed text=@t]
173+ %submit
174+ [%toggled id=@ud]
175+ [%got todos=(list item.todo)]
176+ [%acked err=(unit @t)]
177+
178+++ init |= items=(list item.todo)
179+ [todos=items draft="" error=~]
180+
181+++ update |= [=msg m=model]
182+ ?- msg
183+ [%typed t]
184+ ?- (gth (lent (tuba (trip t))) 80)
185+ %.y [m(draft=t error=`"Too long") ~]
186+ %.n [m(draft=t error=~) ~]
187+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
188+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
189+ [%got ts] [m(todos=ts) ~]
190+ [%acked err] [m(error=err) ~]
191+
192+++ subs |= m=model
193+ ~[[%watch (todos.todo |=%got)]]
194+
195+++ view |= m=model
196+ column ~[gap+%s2] ~[
197+ heading 2 "Todos"
198+ each (turn todos.m row-of)
199+ row ~[gap+%s1] ~[
200+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
201+ button "Add" %submit
202+ el ~[tone+%danger] (text (fall error.m ""))
203+
204+++ row-of |= t=item.todo
205+ [id.t (toggle done.t text.t [%toggled id.t])]
206+#### /ui/todo-list/jibb rename-subs-sample
207+/= todo /ui/api/todo
208+
209+++ main (program init update view subs)
210+
211++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
212++$ msg
213+ [%typed text=@t]
214+ %submit
215+ [%toggled id=@ud]
216+ [%got todos=(list item.todo)]
217+ [%acked err=(unit @t)]
218+
219+++ init |= ts=(list item.todo)
220+ [todos=ts draft="" error=~]
221+
222+++ update |= [=msg m=model]
223+ ?- msg
224+ [%typed t]
225+ ?- (gth (lent (tuba (trip t))) 80)
226+ %.y [m(draft=t error=`"Too long") ~]
227+ %.n [m(draft=t error=~) ~]
228+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
229+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
230+ [%got ts] [m(todos=ts) ~]
231+ [%acked err] [m(error=err) ~]
232+
233+++ subs |= mdl=model
234+ ~[[%watch (todos.todo |=%got)]]
235+
236+++ view |= m=model
237+ column ~[gap+%s2] ~[
238+ heading 2 "Todos"
239+ each (turn todos.m row-of)
240+ row ~[gap+%s1] ~[
241+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
242+ button "Add" %submit
243+ el ~[tone+%danger] (text (fall error.m ""))
244+
245+++ row-of |= t=item.todo
246+ [id.t (toggle done.t text.t [%toggled id.t])]
247+#### /ui/todo-list/jibb unused-helper
248+/= todo /ui/api/todo
249+
250+++ main (program init update view subs)
251+
252++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
253++$ msg
254+ [%typed text=@t]
255+ %submit
256+ [%toggled id=@ud]
257+ [%got todos=(list item.todo)]
258+ [%acked err=(unit @t)]
259+
260+++ init |= ts=(list item.todo)
261+ [todos=ts draft="" error=~]
262+
263+++ update |= [=msg m=model]
264+ ?- msg
265+ [%typed t]
266+ ?- (gth (lent (tuba (trip t))) 80)
267+ %.y [m(draft=t error=`"Too long") ~]
268+ %.n [m(draft=t error=~) ~]
269+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
270+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
271+ [%got ts] [m(todos=ts) ~]
272+ [%acked err] [m(error=err) ~]
273+
274+++ subs |= m=model
275+ ~[[%watch (todos.todo |=%got)]]
276+
277+++ view |= m=model
278+ column ~[gap+%s2] ~[
279+ heading 2 "Todos"
280+ each (turn todos.m row-of)
281+ row ~[gap+%s1] ~[
282+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
283+ button "Add" %submit
284+ el ~[tone+%danger] (text (fall error.m ""))
285+
286+++ row-of |= t=item.todo
287+ [id.t (toggle done.t text.t [%toggled id.t])]
288+
289+++ count |= m=model
290+ (lent todos.m)
291+#### /ui/todo-list/jibb unused-helper-mold
292+/= todo /ui/api/todo
293+
294+++ main (program init update view subs)
295+
296++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
297++$ msg
298+ [%typed text=@t]
299+ %submit
300+ [%toggled id=@ud]
301+ [%got todos=(list item.todo)]
302+ [%acked err=(unit @t)]
303+
304+++ init |= ts=(list item.todo)
305+ [todos=ts draft="" error=~]
306+
307+++ update |= [=msg m=model]
308+ ?- msg
309+ [%typed t]
310+ ?- (gth (lent (tuba (trip t))) 80)
311+ %.y [m(draft=t error=`"Too long") ~]
312+ %.n [m(draft=t error=~) ~]
313+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
314+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
315+ [%got ts] [m(todos=ts) ~]
316+ [%acked err] [m(error=err) ~]
317+
318+++ subs |= m=model
319+ ~[[%watch (todos.todo |=%got)]]
320+
321+++ view |= m=model
322+ column ~[gap+%s2] ~[
323+ heading 2 "Todos"
324+ each (turn todos.m row-of)
325+ row ~[gap+%s1] ~[
326+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
327+ button "Add" %submit
328+ el ~[tone+%danger] (text (fall error.m ""))
329+
330+++ row-of |= t=item.todo
331+ [id.t (toggle done.t text.t [%toggled id.t])]
332+
333++$ flag ?
334+#### /ui/todo-list/jibb swap-model-fields
335+/= todo /ui/api/todo
336+
337+++ main (program init update view subs)
338+
339++$ model [draft=@t todos=(list item.todo) error=(unit @t)]
340++$ msg
341+ [%typed text=@t]
342+ %submit
343+ [%toggled id=@ud]
344+ [%got todos=(list item.todo)]
345+ [%acked err=(unit @t)]
346+
347+++ init |= ts=(list item.todo)
348+ [draft="" todos=ts error=~]
349+
350+++ update |= [=msg m=model]
351+ ?- msg
352+ [%typed t]
353+ ?- (gth (lent (tuba (trip t))) 80)
354+ %.y [m(draft=t error=`"Too long") ~]
355+ %.n [m(draft=t error=~) ~]
356+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
357+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
358+ [%got ts] [m(todos=ts) ~]
359+ [%acked err] [m(error=err) ~]
360+
361+++ subs |= m=model
362+ ~[[%watch (todos.todo |=%got)]]
363+
364+++ view |= m=model
365+ column ~[gap+%s2] ~[
366+ heading 2 "Todos"
367+ each (turn todos.m row-of)
368+ row ~[gap+%s1] ~[
369+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
370+ button "Add" %submit
371+ el ~[tone+%danger] (text (fall error.m ""))
372+
373+++ row-of |= t=item.todo
374+ [id.t (toggle done.t text.t [%toggled id.t])]
375+#### /ui/todo-list/jibb init-cast-body
376+/= todo /ui/api/todo
377+
378+++ main (program init update view subs)
379+
380++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
381++$ msg
382+ [%typed text=@t]
383+ %submit
384+ [%toggled id=@ud]
385+ [%got todos=(list item.todo)]
386+ [%acked err=(unit @t)]
387+
388+++ init |= ts=(list item.todo)
389+ ^- model [ts "" ~]
390+
391+++ update |= [=msg m=model]
392+ ?- msg
393+ [%typed t]
394+ ?- (gth (lent (tuba (trip t))) 80)
395+ %.y [m(draft=t error=`"Too long") ~]
396+ %.n [m(draft=t error=~) ~]
397+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
398+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
399+ [%got ts] [m(todos=ts) ~]
400+ [%acked err] [m(error=err) ~]
401+
402+++ subs |= m=model
403+ ~[[%watch (todos.todo |=%got)]]
404+
405+++ view |= m=model
406+ column ~[gap+%s2] ~[
407+ heading 2 "Todos"
408+ each (turn todos.m row-of)
409+ row ~[gap+%s1] ~[
410+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
411+ button "Add" %submit
412+ el ~[tone+%danger] (text (fall error.m ""))
413+
414+++ row-of |= t=item.todo
415+ [id.t (toggle done.t text.t [%toggled id.t])]
416+#### /ui/todo-list/jibb init-positional
417+/= todo /ui/api/todo
418+
419+++ main (program init update view subs)
420+
421++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
422++$ msg
423+ [%typed text=@t]
424+ %submit
425+ [%toggled id=@ud]
426+ [%got todos=(list item.todo)]
427+ [%acked err=(unit @t)]
428+
429+++ init |= ts=(list item.todo)
430+ [ts "" ~]
431+
432+++ update |= [=msg m=model]
433+ ?- msg
434+ [%typed t]
435+ ?- (gth (lent (tuba (trip t))) 80)
436+ %.y [m(draft=t error=`"Too long") ~]
437+ %.n [m(draft=t error=~) ~]
438+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
439+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
440+ [%got ts] [m(todos=ts) ~]
441+ [%acked err] [m(error=err) ~]
442+
443+++ subs |= m=model
444+ ~[[%watch (todos.todo |=%got)]]
445+
446+++ view |= m=model
447+ column ~[gap+%s2] ~[
448+ heading 2 "Todos"
449+ each (turn todos.m row-of)
450+ row ~[gap+%s1] ~[
451+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
452+ button "Add" %submit
453+ el ~[tone+%danger] (text (fall error.m ""))
454+
455+++ row-of |= t=item.todo
456+ [id.t (toggle done.t text.t [%toggled id.t])]
457+#### /ui/todo-list/jibb second-sub-every
458+/= todo /ui/api/todo
459+
460+++ main (program init update view subs)
461+
462++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
463++$ msg
464+ [%typed text=@t]
465+ %submit
466+ [%toggled id=@ud]
467+ [%got todos=(list item.todo)]
468+ [%acked err=(unit @t)]
469+ [%tick at=@da]
470+
471+++ init |= ts=(list item.todo)
472+ [todos=ts draft="" error=~]
473+
474+++ update |= [=msg m=model]
475+ ?- msg
476+ [%typed t]
477+ ?- (gth (lent (tuba (trip t))) 80)
478+ %.y [m(draft=t error=`"Too long") ~]
479+ %.n [m(draft=t error=~) ~]
480+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
481+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
482+ [%got ts] [m(todos=ts) ~]
483+ [%acked err] [m(error=err) ~]
484+ [%tick at] [m ~]
485+
486+++ subs |= m=model
487+ ~[[%watch (todos.todo |=%got)] [%every ~s30 |=%tick]]
488+
489+++ view |= m=model
490+ column ~[gap+%s2] ~[
491+ heading 2 "Todos"
492+ each (turn todos.m row-of)
493+ row ~[gap+%s1] ~[
494+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
495+ button "Add" %submit
496+ el ~[tone+%danger] (text (fall error.m ""))
497+
498+++ row-of |= t=item.todo
499+ [id.t (toggle done.t text.t [%toggled id.t])]
500+#### /ui/todo-list/jibb second-sub-watch
501+/= todo /ui/api/todo
502+
503+++ main (program init update view subs)
504+
505++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
506++$ msg
507+ [%typed text=@t]
508+ %submit
509+ [%toggled id=@ud]
510+ [%got todos=(list item.todo)]
511+ [%acked err=(unit @t)]
512+
513+++ init |= ts=(list item.todo)
514+ [todos=ts draft="" error=~]
515+
516+++ update |= [=msg m=model]
517+ ?- msg
518+ [%typed t]
519+ ?- (gth (lent (tuba (trip t))) 80)
520+ %.y [m(draft=t error=`"Too long") ~]
521+ %.n [m(draft=t error=~) ~]
522+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
523+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
524+ [%got ts] [m(todos=ts) ~]
525+ [%acked err] [m(error=err) ~]
526+
527+++ subs |= m=model
528+ ~[[%watch (todos.todo |=%got)] [%watch (todos.todo |=%got)]]
529+
530+++ view |= m=model
531+ column ~[gap+%s2] ~[
532+ heading 2 "Todos"
533+ each (turn todos.m row-of)
534+ row ~[gap+%s1] ~[
535+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
536+ button "Add" %submit
537+ el ~[tone+%danger] (text (fall error.m ""))
538+
539+++ row-of |= t=item.todo
540+ [id.t (toggle done.t text.t [%toggled id.t])]
541+#### /ui/todo-list/jibb subs-none
542+/= todo /ui/api/todo
543+
544+++ main (program init update view subs)
545+
546++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
547++$ msg
548+ [%typed text=@t]
549+ %submit
550+ [%toggled id=@ud]
551+ [%got todos=(list item.todo)]
552+ [%acked err=(unit @t)]
553+
554+++ init |= ts=(list item.todo)
555+ [todos=ts draft="" error=~]
556+
557+++ update |= [=msg m=model]
558+ ?- msg
559+ [%typed t]
560+ ?- (gth (lent (tuba (trip t))) 80)
561+ %.y [m(draft=t error=`"Too long") ~]
562+ %.n [m(draft=t error=~) ~]
563+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
564+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
565+ [%got ts] [m(todos=ts) ~]
566+ [%acked err] [m(error=err) ~]
567+
568+++ subs |=(m ~)
569+
570+++ view |= m=model
571+ column ~[gap+%s2] ~[
572+ heading 2 "Todos"
573+ each (turn todos.m row-of)
574+ row ~[gap+%s1] ~[
575+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
576+ button "Add" %submit
577+ el ~[tone+%danger] (text (fall error.m ""))
578+
579+++ row-of |= t=item.todo
580+ [id.t (toggle done.t text.t [%toggled id.t])]
581+#### /ui/todo-list/jibb sixth-msg
582+/= todo /ui/api/todo
583+
584+++ main (program init update view subs)
585+
586++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
587++$ msg
588+ [%typed text=@t]
589+ %submit
590+ [%toggled id=@ud]
591+ [%got todos=(list item.todo)]
592+ [%acked err=(unit @t)]
593+ %clear
594+
595+++ init |= ts=(list item.todo)
596+ [todos=ts draft="" error=~]
597+
598+++ update |= [=msg m=model]
599+ ?- msg
600+ [%typed t]
601+ ?- (gth (lent (tuba (trip t))) 80)
602+ %.y [m(draft=t error=`"Too long") ~]
603+ %.n [m(draft=t error=~) ~]
604+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
605+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
606+ [%got ts] [m(todos=ts) ~]
607+ [%acked err] [m(error=err) ~]
608+ %clear [m(todos=~) ~]
609+
610+++ subs |= m=model
611+ ~[[%watch (todos.todo |=%got)]]
612+
613+++ view |= m=model
614+ column ~[gap+%s2] ~[
615+ heading 2 "Todos"
616+ each (turn todos.m row-of)
617+ row ~[gap+%s1] ~[
618+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
619+ button "Add" %submit
620+ el ~[tone+%danger] (text (fall error.m ""))
621+
622+++ row-of |= t=item.todo
623+ [id.t (toggle done.t text.t [%toggled id.t])]
624+#### /ui/todo-list/jibb sixth-msg-button
625+/= todo /ui/api/todo
626+
627+++ main (program init update view subs)
628+
629++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
630++$ msg
631+ [%typed text=@t]
632+ %submit
633+ [%toggled id=@ud]
634+ [%got todos=(list item.todo)]
635+ [%acked err=(unit @t)]
636+ %clear
637+
638+++ init |= ts=(list item.todo)
639+ [todos=ts draft="" error=~]
640+
641+++ update |= [=msg m=model]
642+ ?- msg
643+ [%typed t]
644+ ?- (gth (lent (tuba (trip t))) 80)
645+ %.y [m(draft=t error=`"Too long") ~]
646+ %.n [m(draft=t error=~) ~]
647+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
648+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
649+ [%got ts] [m(todos=ts) ~]
650+ [%acked err] [m(error=err) ~]
651+ %clear [m(todos=~) ~]
652+
653+++ subs |= m=model
654+ ~[[%watch (todos.todo |=%got)]]
655+
656+++ view |= m=model
657+ column ~[gap+%s2] ~[
658+ heading 2 "Todos"
659+ each (turn todos.m row-of)
660+ row ~[gap+%s1] ~[
661+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
662+ button "Add" %submit
663+ button "Clear" %clear
664+ el ~[tone+%danger] (text (fall error.m ""))
665+
666+++ row-of |= t=item.todo
667+ [id.t (toggle done.t text.t [%toggled id.t])]
668+#### /ui/todo-list/jibb view-helper-title
669+/= todo /ui/api/todo
670+
671+++ main (program init update view subs)
672+
673++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
674++$ msg
675+ [%typed text=@t]
676+ %submit
677+ [%toggled id=@ud]
678+ [%got todos=(list item.todo)]
679+ [%acked err=(unit @t)]
680+
681+++ init |= ts=(list item.todo)
682+ [todos=ts draft="" error=~]
683+
684+++ update |= [=msg m=model]
685+ ?- msg
686+ [%typed t]
687+ ?- (gth (lent (tuba (trip t))) 80)
688+ %.y [m(draft=t error=`"Too long") ~]
689+ %.n [m(draft=t error=~) ~]
690+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
691+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
692+ [%got ts] [m(todos=ts) ~]
693+ [%acked err] [m(error=err) ~]
694+
695+++ subs |= m=model
696+ ~[[%watch (todos.todo |=%got)]]
697+
698+++ view |= m=model
699+ column ~[gap+%s2] ~[
700+ (title "Todos")
701+ each (turn todos.m row-of)
702+ row ~[gap+%s1] ~[
703+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
704+ button "Add" %submit
705+ el ~[tone+%danger] (text (fall error.m ""))
706+
707+++ row-of |= t=item.todo
708+ [id.t (toggle done.t text.t [%toggled id.t])]
709+
710+++ title |= words=@t
711+ heading 2 words
712+#### /ui/todo-list/jibb view-helper-error
713+/= todo /ui/api/todo
714+
715+++ main (program init update view subs)
716+
717++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
718++$ msg
719+ [%typed text=@t]
720+ %submit
721+ [%toggled id=@ud]
722+ [%got todos=(list item.todo)]
723+ [%acked err=(unit @t)]
724+
725+++ init |= ts=(list item.todo)
726+ [todos=ts draft="" error=~]
727+
728+++ update |= [=msg m=model]
729+ ?- msg
730+ [%typed t]
731+ ?- (gth (lent (tuba (trip t))) 80)
732+ %.y [m(draft=t error=`"Too long") ~]
733+ %.n [m(draft=t error=~) ~]
734+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
735+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
736+ [%got ts] [m(todos=ts) ~]
737+ [%acked err] [m(error=err) ~]
738+
739+++ subs |= m=model
740+ ~[[%watch (todos.todo |=%got)]]
741+
742+++ view |= m=model
743+ column ~[gap+%s2] ~[
744+ heading 2 "Todos"
745+ each (turn todos.m row-of)
746+ row ~[gap+%s1] ~[
747+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
748+ button "Add" %submit
749+ (error-line m)
750+
751+++ row-of |= t=item.todo
752+ [id.t (toggle done.t text.t [%toggled id.t])]
753+
754+++ error-line |= m=model
755+ el ~[tone+%danger] (text (fall error.m ""))
756+#### /ui/todo-list/jibb inline-row-of
757+/= todo /ui/api/todo
758+
759+++ main (program init update view subs)
760+
761++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
762++$ msg
763+ [%typed text=@t]
764+ %submit
765+ [%toggled id=@ud]
766+ [%got todos=(list item.todo)]
767+ [%acked err=(unit @t)]
768+
769+++ init |= ts=(list item.todo)
770+ [todos=ts draft="" error=~]
771+
772+++ update |= [=msg m=model]
773+ ?- msg
774+ [%typed t]
775+ ?- (gth (lent (tuba (trip t))) 80)
776+ %.y [m(draft=t error=`"Too long") ~]
777+ %.n [m(draft=t error=~) ~]
778+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
779+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
780+ [%got ts] [m(todos=ts) ~]
781+ [%acked err] [m(error=err) ~]
782+
783+++ subs |= m=model
784+ ~[[%watch (todos.todo |=%got)]]
785+
786+++ view |= m=model
787+ column ~[gap+%s2] ~[
788+ heading 2 "Todos"
789+ each (turn todos.m |=(t=item.todo [id.t (toggle done.t text.t [%toggled id.t])]))
790+ row ~[gap+%s1] ~[
791+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
792+ button "Add" %submit
793+ el ~[tone+%danger] (text (fall error.m ""))
794+#### /ui/todo-list/jibb view-local-rows
795+/= todo /ui/api/todo
796+
797+++ main (program init update view subs)
798+
799++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
800++$ msg
801+ [%typed text=@t]
802+ %submit
803+ [%toggled id=@ud]
804+ [%got todos=(list item.todo)]
805+ [%acked err=(unit @t)]
806+
807+++ init |= ts=(list item.todo)
808+ [todos=ts draft="" error=~]
809+
810+++ update |= [=msg m=model]
811+ ?- msg
812+ [%typed t]
813+ ?- (gth (lent (tuba (trip t))) 80)
814+ %.y [m(draft=t error=`"Too long") ~]
815+ %.n [m(draft=t error=~) ~]
816+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
817+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
818+ [%got ts] [m(todos=ts) ~]
819+ [%acked err] [m(error=err) ~]
820+
821+++ subs |= m=model
822+ ~[[%watch (todos.todo |=%got)]]
823+
824+++ view |= m=model
825+ ++ rows (turn todos.m row-of)
826+ column ~[gap+%s2] ~[
827+ heading 2 "Todos"
828+ each rows
829+ row ~[gap+%s1] ~[
830+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
831+ button "Add" %submit
832+ el ~[tone+%danger] (text (fall error.m ""))
833+
834+++ row-of |= t=item.todo
835+ [id.t (toggle done.t text.t [%toggled id.t])]
836+#### /ui/todo-list/jibb drop-each
837+/= todo /ui/api/todo
838+
839+++ main (program init update view subs)
840+
841++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
842++$ msg
843+ [%typed text=@t]
844+ %submit
845+ [%toggled id=@ud]
846+ [%got todos=(list item.todo)]
847+ [%acked err=(unit @t)]
848+
849+++ init |= ts=(list item.todo)
850+ [todos=ts draft="" error=~]
851+
852+++ update |= [=msg m=model]
853+ ?- msg
854+ [%typed t]
855+ ?- (gth (lent (tuba (trip t))) 80)
856+ %.y [m(draft=t error=`"Too long") ~]
857+ %.n [m(draft=t error=~) ~]
858+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
859+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
860+ [%got ts] [m(todos=ts) ~]
861+ [%acked err] [m(error=err) ~]
862+
863+++ subs |= m=model
864+ ~[[%watch (todos.todo |=%got)]]
865+
866+++ view |= m=model
867+ column ~[gap+%s2] ~[
868+ heading 2 "Todos"
869+ row ~[gap+%s1] ~[
870+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
871+ button "Add" %submit
872+ el ~[tone+%danger] (text (fall error.m ""))
873+
874+++ row-of |= t=item.todo
875+ [id.t (toggle done.t text.t [%toggled id.t])]
876+#### /ui/todo-list/jibb update-helper-cmd
877+/= todo /ui/api/todo
878+
879+++ main (program init update view subs)
880+
881++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
882++$ msg
883+ [%typed text=@t]
884+ %submit
885+ [%toggled id=@ud]
886+ [%got todos=(list item.todo)]
887+ [%acked err=(unit @t)]
888+
889+++ init |= ts=(list item.todo)
890+ [todos=ts draft="" error=~]
891+
892+++ update |= [=msg m=model]
893+ ?- msg
894+ [%typed t]
895+ ?- (gth (lent (tuba (trip t))) 80)
896+ %.y [m(draft=t error=`"Too long") ~]
897+ %.n [m(draft=t error=~) ~]
898+ %submit [m(draft="") ~[(add-cmd draft.m)]]
899+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
900+ [%got ts] [m(todos=ts) ~]
901+ [%acked err] [m(error=err) ~]
902+
903+++ subs |= m=model
904+ ~[[%watch (todos.todo |=%got)]]
905+
906+++ view |= m=model
907+ column ~[gap+%s2] ~[
908+ heading 2 "Todos"
909+ each (turn todos.m row-of)
910+ row ~[gap+%s1] ~[
911+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
912+ button "Add" %submit
913+ el ~[tone+%danger] (text (fall error.m ""))
914+
915+++ row-of |= t=item.todo
916+ [id.t (toggle done.t text.t [%toggled id.t])]
917+
918+++ add-cmd |= d=@t
919+ (poke.todo [%add d] |=%acked)
docs/reviews/2026-11-03-milestone-2-probes/variants/p2.outnew file+185
@@ -0,0 +1,185 @@
1+#### /ui/todo-list/jibb control
2+CHECKED
3++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
4++$ msg: msg
5+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
6+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
7+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
8+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
9+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
10+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
11+#### /ui/todo-list/jibb reorder
12+CHECKED
13++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
14++$ msg: msg
15+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
16+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
17+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
18+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
19+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
20+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
21+#### /ui/todo-list/jibb rename-view-sample
22+CHECKED
23++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
24++$ msg: msg
25+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
26+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
27+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
28+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
29+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
30+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
31+#### /ui/todo-list/jibb rename-row-sample
32+CHECKED
33++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
34++$ msg: msg
35+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
36+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
37+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
38+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
39+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
40+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
41+#### /ui/todo-list/jibb rename-init-sample
42+CHECKED
43++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
44++$ msg: msg
45+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
46+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
47+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
48+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
49+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
50+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
51+#### /ui/todo-list/jibb rename-subs-sample
52+CHECKED
53++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
54++$ msg: msg
55+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
56+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
57+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
58+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
59+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
60+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
61+#### /ui/todo-list/jibb unused-helper
62+CHECKED
63++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
64++$ msg: msg
65+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
66+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
67+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
68+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
69+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
70+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
71+++ count: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] @ud)
72+#### /ui/todo-list/jibb unused-helper-mold
73+CHECKED
74++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
75++$ msg: msg
76++$ flag: ?
77+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
78+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
79+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
80+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
81+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
82+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
83+#### /ui/todo-list/jibb swap-model-fields
84+CHECKED
85++$ model: [draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]]
86++$ msg: msg
87+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]]) [update=$-([msg [draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]]] [[draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]] (list (cmd msg))]) [view=$-([draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]] (element msg)) subs=$-([draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]] (list (sub msg)))]]]
88+++ init: $-((list [id=@ud [done=? text=@t]]) [draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]])
89+++ view: $-([draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]] (element msg))
90+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
91+++ subs: $-([draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]] (list (sub msg)))
92+++ update: $-([msg=msg m=[draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]]] [[draft=@t [todos=(list [id=@ud [done=? text=@t]]) error=(unit @t)]] (list (cmd msg))])
93+#### /ui/todo-list/jibb init-cast-body
94+CHECKED
95++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
96++$ msg: msg
97+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
98+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
99+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
100+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
101+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
102+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
103+#### /ui/todo-list/jibb init-positional
104+CHECKED
105++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
106++$ msg: msg
107+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
108+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
109+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
110+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
111+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
112+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
113+#### /ui/todo-list/jibb second-sub-every
114+REJECTED: module kind needs unsupported inference: /ui/todo-list/jibb
115+#### /ui/todo-list/jibb second-sub-watch
116+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
117+ [todos=ts draft="" error=~]
118+ ^
119+#### /ui/todo-list/jibb subs-none
120+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
121+ [todos=ts draft="" error=~]
122+ ^
123+#### /ui/todo-list/jibb sixth-msg
124+CHECKED
125++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
126++$ msg: msg
127+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
128+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
129+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
130+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
131+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
132+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
133+#### /ui/todo-list/jibb sixth-msg-button
134+CHECKED
135++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
136++$ msg: msg
137+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
138+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
139+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
140+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
141+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
142+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
143+#### /ui/todo-list/jibb view-helper-title
144+CHECKED
145++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
146++$ msg: msg
147+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
148+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
149+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
150+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
151+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
152+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
153+++ title: $-(@t (element A))
154+#### /ui/todo-list/jibb view-helper-error
155+CHECKED
156++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
157++$ msg: msg
158+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
159+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
160+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
161+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
162+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
163+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
164+++ error-line: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element A))
165+#### /ui/todo-list/jibb inline-row-of
166+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
167+ [todos=ts draft="" error=~]
168+ ^
169+#### /ui/todo-list/jibb view-local-rows
170+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
171+ [todos=ts draft="" error=~]
172+ ^
173+#### /ui/todo-list/jibb drop-each
174+REJECTED: /ui/todo-list.jibb:39:32: nothing fixes the union of %toggled
175+ [id.t (toggle done.t text.t [%toggled id.t])]
176+ ^
177+#### /ui/todo-list/jibb update-helper-cmd
178+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
179+ [todos=ts draft="" error=~]
180+ ^
181+
182+
183+real 1m14.273s
184+user 1m13.404s
185+sys 0m0.129s
docs/reviews/2026-11-03-milestone-2-probes/variants/p3.jibbnew file+712
@@ -0,0 +1,712 @@
1+#### /ui/stores/cart/jibb cart-reorder
2++$ poke
3+ [%add item=@t]
4+ %toggle
5+++ update |= [a=poke s=state]
6+ ?- a
7+ [%add item] s(items=[item items.s])
8+ %toggle s(open=(not open.s))
9+++ init ^- state [items=~ open=%.n]
10+++ main (store init update)
11++$ state [items=(list @t) open=?]
12+#### /ui/stores/cart/jibb cart-init-uncast
13+:: /ui/stores/cart.jibb
14++$ state [items=(list @t) open=?]
15++$ poke
16+ [%add item=@t]
17+ %toggle
18+
19+++ main (store init update)
20+++ init [items=~ open=%.n]
21+++ update |= [a=poke s=state]
22+ ?- a
23+ [%add item] s(items=[item items.s])
24+ %toggle s(open=(not open.s))
25+#### /ui/stores/cart/jibb cart-rename
26+:: /ui/stores/cart.jibb
27++$ state [items=(list @t) open=?]
28++$ poke
29+ [%add item=@t]
30+ %toggle
31+
32+++ main (store init update)
33+++ init ^- state [items=~ open=%.n]
34+++ update |= [p=poke st=state]
35+ ?- p
36+ [%add item] st(items=[item items.st])
37+ %toggle st(open=(not open.st))
38+#### /ui/stores/cart/jibb cart-third-case
39+:: /ui/stores/cart.jibb
40++$ state [items=(list @t) open=?]
41++$ poke
42+ [%add item=@t]
43+ %toggle
44+ %clear
45+
46+++ main (store init update)
47+++ init ^- state [items=~ open=%.n]
48+++ update |= [a=poke s=state]
49+ ?- a
50+ [%add item] s(items=[item items.s])
51+ %toggle s(open=(not open.s))
52+ %clear s(items=~)
53+#### /ui/stores/cart/jibb cart-unused-helper
54+:: /ui/stores/cart.jibb
55++$ state [items=(list @t) open=?]
56++$ poke
57+ [%add item=@t]
58+ %toggle
59+
60+++ main (store init update)
61+++ init ^- state [items=~ open=%.n]
62+++ update |= [a=poke s=state]
63+ ?- a
64+ [%add item] s(items=[item items.s])
65+ %toggle s(open=(not open.s))
66+++ size |= s=state
67+ (lent items.s)
68+#### /ui/stores/cart/jibb cart-swap-fields
69+:: /ui/stores/cart.jibb
70++$ state [open=? items=(list @t)]
71++$ poke
72+ [%add item=@t]
73+ %toggle
74+
75+++ main (store init update)
76+++ init ^- state [open=%.n items=~]
77+++ update |= [a=poke s=state]
78+ ?- a
79+ [%add item] s(items=[item items.s])
80+ %toggle s(open=(not open.s))
81+#### /ui/stores/cart/jibb cart-update-helper
82+:: /ui/stores/cart.jibb
83++$ state [items=(list @t) open=?]
84++$ poke
85+ [%add item=@t]
86+ %toggle
87+
88+++ main (store init update)
89+++ init ^- state [items=~ open=%.n]
90+++ update |= [a=poke s=state]
91+ ?- a
92+ [%add item] s(items=[item items.s])
93+ %toggle (flip s)
94+++ flip |= s=state
95+ s(open=(not open.s))
96+#### /ui/basket/jibb basket-control
97+:: /ui/basket.jibb
98+/= cart /ui/stores/cart
99+
100+++ main (program init update view subs)
101+
102++$ model [cart=state.cart note=@t]
103++$ msg
104+ [%noted text=@t]
105+ %add
106+ %toggle
107+ [%got cart=state.cart]
108+ [%acked err=(unit @t)]
109+
110+++ init |= ~
111+ [cart=[items=~ open=%.n] note=""]
112+
113+++ update |= [=msg m=model]
114+ ?- msg
115+ [%noted t] [m(note=t) ~]
116+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
117+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
118+ [%got c] [m(cart=c) ~]
119+ [%acked err] [m ~]
120+
121+++ subs |= m=model
122+ ~[[%watch (state.cart |=%got)]]
123+
124+++ view |= m=model
125+ column ~[gap+%s1] ~[
126+ (text "{(lent items.cart.m)} items")
127+ field "Item" note.m |=%noted
128+ button "Add" %add
129+#### /ui/basket/jibb basket-init-cast
130+:: /ui/basket.jibb
131+/= cart /ui/stores/cart
132+
133+++ main (program init update view subs)
134+
135++$ model [cart=state.cart note=@t]
136++$ msg
137+ [%noted text=@t]
138+ %add
139+ %toggle
140+ [%got cart=state.cart]
141+ [%acked err=(unit @t)]
142+
143+++ init |= ~
144+ ^- model [[~ %.n] ""]
145+
146+++ update |= [=msg m=model]
147+ ?- msg
148+ [%noted t] [m(note=t) ~]
149+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
150+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
151+ [%got c] [m(cart=c) ~]
152+ [%acked err] [m ~]
153+
154+++ subs |= m=model
155+ ~[[%watch (state.cart |=%got)]]
156+
157+++ view |= m=model
158+ column ~[gap+%s1] ~[
159+ (text "{(lent items.cart.m)} items")
160+ field "Item" note.m |=%noted
161+ button "Add" %add
162+#### /ui/basket/jibb basket-rename-view
163+:: /ui/basket.jibb
164+/= cart /ui/stores/cart
165+
166+++ main (program init update view subs)
167+
168++$ model [cart=state.cart note=@t]
169++$ msg
170+ [%noted text=@t]
171+ %add
172+ %toggle
173+ [%got cart=state.cart]
174+ [%acked err=(unit @t)]
175+
176+++ init |= ~
177+ [cart=[items=~ open=%.n] note=""]
178+
179+++ update |= [=msg m=model]
180+ ?- msg
181+ [%noted t] [m(note=t) ~]
182+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
183+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
184+ [%got c] [m(cart=c) ~]
185+ [%acked err] [m ~]
186+
187+++ subs |= m=model
188+ ~[[%watch (state.cart |=%got)]]
189+
190+++ view |= mdl=model
191+ column ~[gap+%s1] ~[
192+ (text "{(lent items.cart.mdl)} items")
193+ field "Item" note.mdl |=%noted
194+ button "Add" %add
195+#### /ui/basket/jibb basket-sixth-msg
196+:: /ui/basket.jibb
197+/= cart /ui/stores/cart
198+
199+++ main (program init update view subs)
200+
201++$ model [cart=state.cart note=@t]
202++$ msg
203+ [%noted text=@t]
204+ %add
205+ %toggle
206+ [%got cart=state.cart]
207+ [%acked err=(unit @t)]
208+ %clear
209+
210+++ init |= ~
211+ [cart=[items=~ open=%.n] note=""]
212+
213+++ update |= [=msg m=model]
214+ ?- msg
215+ [%noted t] [m(note=t) ~]
216+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
217+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
218+ [%got c] [m(cart=c) ~]
219+ [%acked err] [m ~]
220+ %clear [m(note="") ~]
221+
222+++ subs |= m=model
223+ ~[[%watch (state.cart |=%got)]]
224+
225+++ view |= m=model
226+ column ~[gap+%s1] ~[
227+ (text "{(lent items.cart.m)} items")
228+ field "Item" note.m |=%noted
229+ button "Add" %add
230+ button "Clear" %clear
231+#### /ui/basket/jibb basket-second-sub
232+:: /ui/basket.jibb
233+/= cart /ui/stores/cart
234+
235+++ main (program init update view subs)
236+
237++$ model [cart=state.cart note=@t]
238++$ msg
239+ [%noted text=@t]
240+ %add
241+ %toggle
242+ [%got cart=state.cart]
243+ [%acked err=(unit @t)]
244+ [%tick at=@da]
245+
246+++ init |= ~
247+ [cart=[items=~ open=%.n] note=""]
248+
249+++ update |= [=msg m=model]
250+ ?- msg
251+ [%noted t] [m(note=t) ~]
252+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
253+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
254+ [%got c] [m(cart=c) ~]
255+ [%acked err] [m ~]
256+ [%tick at] [m ~]
257+
258+++ subs |= m=model
259+ ~[[%watch (state.cart |=%got)] [%every ~s30 |=%tick]]
260+
261+++ view |= m=model
262+ column ~[gap+%s1] ~[
263+ (text "{(lent items.cart.m)} items")
264+ field "Item" note.m |=%noted
265+ button "Add" %add
266+#### /ui/basket/jibb basket-view-helper
267+:: /ui/basket.jibb
268+/= cart /ui/stores/cart
269+
270+++ main (program init update view subs)
271+
272++$ model [cart=state.cart note=@t]
273++$ msg
274+ [%noted text=@t]
275+ %add
276+ %toggle
277+ [%got cart=state.cart]
278+ [%acked err=(unit @t)]
279+
280+++ init |= ~
281+ [cart=[items=~ open=%.n] note=""]
282+
283+++ update |= [=msg m=model]
284+ ?- msg
285+ [%noted t] [m(note=t) ~]
286+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
287+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
288+ [%got c] [m(cart=c) ~]
289+ [%acked err] [m ~]
290+
291+++ subs |= m=model
292+ ~[[%watch (state.cart |=%got)]]
293+
294+++ view |= m=model
295+ column ~[gap+%s1] ~[
296+ (count-line m)
297+ field "Item" note.m |=%noted
298+ button "Add" %add
299+
300+++ count-line |= m=model
301+ text "{(lent items.cart.m)} items"
302+#### /ui/basket/jibb basket-swap-fields
303+:: /ui/basket.jibb
304+/= cart /ui/stores/cart
305+
306+++ main (program init update view subs)
307+
308++$ model [note=@t cart=state.cart]
309++$ msg
310+ [%noted text=@t]
311+ %add
312+ %toggle
313+ [%got cart=state.cart]
314+ [%acked err=(unit @t)]
315+
316+++ init |= ~
317+ [note="" cart=[items=~ open=%.n]]
318+
319+++ update |= [=msg m=model]
320+ ?- msg
321+ [%noted t] [m(note=t) ~]
322+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
323+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
324+ [%got c] [m(cart=c) ~]
325+ [%acked err] [m ~]
326+
327+++ subs |= m=model
328+ ~[[%watch (state.cart |=%got)]]
329+
330+++ view |= m=model
331+ column ~[gap+%s1] ~[
332+ (text "{(lent items.cart.m)} items")
333+ field "Item" note.m |=%noted
334+ button "Add" %add
335+#### /ui/basket/jibb basket-unused-helper
336+:: /ui/basket.jibb
337+/= cart /ui/stores/cart
338+
339+++ main (program init update view subs)
340+
341++$ model [cart=state.cart note=@t]
342++$ msg
343+ [%noted text=@t]
344+ %add
345+ %toggle
346+ [%got cart=state.cart]
347+ [%acked err=(unit @t)]
348+
349+++ init |= ~
350+ [cart=[items=~ open=%.n] note=""]
351+
352+++ update |= [=msg m=model]
353+ ?- msg
354+ [%noted t] [m(note=t) ~]
355+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
356+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
357+ [%got c] [m(cart=c) ~]
358+ [%acked err] [m ~]
359+
360+++ subs |= m=model
361+ ~[[%watch (state.cart |=%got)]]
362+
363+++ view |= m=model
364+ column ~[gap+%s1] ~[
365+ (text "{(lent items.cart.m)} items")
366+ field "Item" note.m |=%noted
367+ button "Add" %add
368+
369+++ empty |= m=model
370+ (eq items.cart.m ~)
371+#### /ui/index/jibb index-reorder
372+/= todo /ui/api/todo
373+/= todo-list /ui/todo-list
374+
375+++ view |= ts=(list item.todo)
376+ column ~[pad+%s3] ~[
377+ heading 1 "My ship"
378+ island main.todo-list ts
379+
380+++ load |=(~ (todos.todo same))
381+++ main (page load view)
382+#### /ui/index/jibb index-rename
383+/= todo /ui/api/todo
384+/= todo-list /ui/todo-list
385+
386+++ main (page load view)
387+++ load |=(~ (todos.todo same))
388+
389+++ view |= items=(list item.todo)
390+ column ~[pad+%s3] ~[
391+ heading 1 "My ship"
392+ island main.todo-list items
393+#### /ui/index/jibb index-tall-load
394+/= todo /ui/api/todo
395+/= todo-list /ui/todo-list
396+
397+++ main (page load view)
398+++ load |= ~
399+ (todos.todo same)
400+
401+++ view |= ts=(list item.todo)
402+ column ~[pad+%s3] ~[
403+ heading 1 "My ship"
404+ island main.todo-list ts
405+#### /ui/index/jibb index-cast-load
406+/= todo /ui/api/todo
407+/= todo-list /ui/todo-list
408+
409+++ main (page load view)
410+++ load |= ~
411+ ^- (ask (list item.todo)) (todos.todo same)
412+
413+++ view |= ts=(list item.todo)
414+ column ~[pad+%s3] ~[
415+ heading 1 "My ship"
416+ island main.todo-list ts
417+#### /ui/index/jibb index-view-helper
418+/= todo /ui/api/todo
419+/= todo-list /ui/todo-list
420+
421+++ main (page load view)
422+++ load |=(~ (todos.todo same))
423+
424+++ view |= ts=(list item.todo)
425+ column ~[pad+%s3] ~[
426+ (title "My ship")
427+ island main.todo-list ts
428+
429+++ title |= words=@t
430+ heading 1 words
431+#### /ui/index/jibb index-unused-helper
432+/= todo /ui/api/todo
433+/= todo-list /ui/todo-list
434+
435+++ main (page load view)
436+++ load |=(~ (todos.todo same))
437+
438+++ view |= ts=(list item.todo)
439+ column ~[pad+%s3] ~[
440+ heading 1 "My ship"
441+ island main.todo-list ts
442+
443+++ count |= ts=(list item.todo)
444+ (lent ts)
445+#### /ui/index/jibb index-pure-load
446+/= todo /ui/api/todo
447+/= todo-list /ui/todo-list
448+
449+++ main (page load view)
450+++ load |=(~ (pure ~))
451+
452+++ view |= ts=(list item.todo)
453+ column ~[pad+%s3] ~[
454+ heading 1 "My ship"
455+ island main.todo-list ts
456+#### /ui/index/jibb index-mapped-reply
457+/= todo /ui/api/todo
458+
459+++ main (page load view)
460+++ load |=(~ (todos.todo lent))
461+
462+++ view |= n=@ud
463+ text "{n} todos"
464+#### /ui/index/jibb index-typed-load
465+/= todo /ui/api/todo
466+
467+++ main (page load view)
468+++ load |=(~ (todo-by-id.todo 1 same))
469+
470+++ view |= t=item.todo
471+ text text.t
472+#### /ui/about/jibb about-reorder
473+++ view
474+ column ~[width+[%fill 1] pad+%s3 gap+%s2] ~[
475+ heading 1 "About this ship"
476+ para ~[(text "Hosted on Urbit. This page ships no JavaScript.")]
477+ el ~[tone+%accent] (link %/blog "Read the blog")
478+
479+++ main view
480+#### /ui/about/jibb about-inline
481+++ main
482+ column ~[width+[%fill 1] pad+%s3 gap+%s2] ~[
483+ heading 1 "About this ship"
484+ para ~[(text "Hosted on Urbit. This page ships no JavaScript.")]
485+ el ~[tone+%accent] (link %/blog "Read the blog")
486+#### /ui/about/jibb about-helper
487+++ main view
488+
489+++ view
490+ column ~[width+[%fill 1] pad+%s3 gap+%s2] ~[
491+ heading 1 "About this ship"
492+ intro
493+ el ~[tone+%accent] (link %/blog "Read the blog")
494+
495+++ intro
496+ para ~[(text "Hosted on Urbit. This page ships no JavaScript.")]
497+#### /ui/about/jibb about-rename
498+++ main body
499+
500+++ body
501+ column ~[width+[%fill 1] pad+%s3 gap+%s2] ~[
502+ heading 1 "About this ship"
503+ para ~[(text "Hosted on Urbit. This page ships no JavaScript.")]
504+ el ~[tone+%accent] (link %/blog "Read the blog")
505+#### /ui/blog/index/jibb blog-reorder
506+/- blog
507+/= api /ui/api/blog
508+/= card /ui/components/card
509+
510+++ view |= ps=(list post.blog)
511+ column ~[gap+%s2] (turn ps card.card)
512+
513+++ load |=(~ (posts.api same))
514+++ main (page load view)
515+#### /ui/blog/index/jibb blog-rename
516+/- blog
517+/= api /ui/api/blog
518+/= card /ui/components/card
519+
520+++ main (page load view)
521+++ load |=(~ (posts.api same))
522+
523+++ view |= items=(list post.blog)
524+ column ~[gap+%s2] (turn items card.card)
525+#### /ui/blog/index/jibb blog-inline-card
526+/- blog
527+/= api /ui/api/blog
528+/= card /ui/components/card
529+
530+++ main (page load view)
531+++ load |=(~ (posts.api same))
532+
533+++ view |= ps=(list post.blog)
534+ column ~[gap+%s2] (turn ps |=(p=post.blog (text title.p)))
535+#### /ui/blog/index/jibb blog-inline-card-bare
536+/- blog
537+/= api /ui/api/blog
538+/= card /ui/components/card
539+
540+++ main (page load view)
541+++ load |=(~ (posts.api same))
542+
543+++ view |= ps=(list post.blog)
544+ column ~[gap+%s2] (turn ps |=(p (text title.p)))
545+#### /ui/blog/index/jibb blog-local-helper
546+/- blog
547+/= api /ui/api/blog
548+/= card /ui/components/card
549+
550+++ main (page load view)
551+++ load |=(~ (posts.api same))
552+
553+++ view |= ps=(list post.blog)
554+ column ~[gap+%s2] (turn ps show)
555+
556+++ show |= p=post.blog
557+ (card.card p)
558+#### /ui/theme/jibb theme-no-font
559+++ theme ^- theme
560+ [ space=[s1="4px" s2="8px" s3="16px"]
561+ tones=[normal="#222" background="#fff" accent="#17734f" danger="#b3261e" muted="#5f5f5f"]
562+ wide="60rem"
563+ lang="en"
564+ zone="UTC"
565+ font=~
566+ dark=`[tones=[normal="#eee" background="#111" accent="#4c9" danger="#f28b82" muted="#aaa"]]
567+#### /ui/theme/jibb theme-helper-value
568+++ theme ^- theme
569+ [ space=[s1="4px" s2="8px" s3="16px"]
570+ tones=[normal="#222" background="#fff" accent=accent danger="#b3261e" muted="#5f5f5f"]
571+ wide="60rem"
572+ lang="en"
573+ zone="UTC"
574+ font=`%/static/fonts/inter.woff2
575+ dark=`[tones=[normal="#eee" background="#111" accent="#4c9" danger="#f28b82" muted="#aaa"]]
576+
577+++ accent "#17734f"
578+#### /ui/components/buttons/jibb buttons-reorder
579+++ wide ^- (list attr)
580+ ~[width+[%fill 1] pad+%s2]
581+++ labelled |= [label=@t msg=M]
582+ button label msg
583+++ add-button |= label=@t
584+ button label %add
585+#### /ui/components/buttons/jibb buttons-fixed
586++$ add-msg %add
587+++ add-button |= label=@t
588+ ^- (element add-msg) (button label %add)
589+++ labelled |= [label=@t msg=M]
590+ button label msg
591+++ wide ^- (list attr)
592+ ~[width+[%fill 1] pad+%s2]
593+#### /ui/components/buttons/jibb buttons-labelled-use
594+++ labelled |= [label=@t msg=M]
595+ button label msg
596+++ wide ^- (list attr)
597+ ~[width+[%fill 1] pad+%s2]
598++$ go-msg %go
599+++ go-button ^- (element go-msg) (labelled "Go" %go)
600+#### /ui/step/jibb step-reorder
601+++ describe |= s=step
602+ ?- s
603+ [%move %left n] "left {n}"
604+ [%move %right n] "right {n}"
605+ [t %draft] t
606+ [t %sent sent-at] t
607+ %stop "stop"
608+
609++$ step
610+ [%move %left n=@ud]
611+ [%move %right n=@ud]
612+ [text=@t %draft]
613+ [text=@t %sent at=@da]
614+ %stop
615+#### /ui/step/jibb step-arm-order
616++$ step
617+ [%move %left n=@ud]
618+ [%move %right n=@ud]
619+ [text=@t %draft]
620+ [text=@t %sent at=@da]
621+ %stop
622+
623+++ describe |= s=step
624+ ?- s
625+ [%move %right n] "right {n}"
626+ [t %draft] t
627+ [t %sent sent-at] t
628+ %stop "stop"
629+ [%move %left n] "left {n}"
630+#### /ui/step/jibb step-catch-all
631++$ step
632+ [%move %left n=@ud]
633+ [%move %right n=@ud]
634+ [text=@t %draft]
635+ [text=@t %sent at=@da]
636+ %stop
637+
638+++ describe |= s=step
639+ ?- s
640+ [%move %left n] "left {n}"
641+ [%move %right n] "right {n}"
642+ [t %draft] t
643+ [t %sent sent-at] t
644+ * "other"
645+#### /ui/step/jibb step-rename
646++$ step
647+ [%move %left n=@ud]
648+ [%move %right n=@ud]
649+ [text=@t %draft]
650+ [text=@t %sent at=@da]
651+ %stop
652+
653+++ describe |= x=step
654+ ?- x
655+ [%move %left n] "left {n}"
656+ [%move %right n] "right {n}"
657+ [t %draft] t
658+ [t %sent sent-at] t
659+ %stop "stop"
660+#### /ui/step/jibb step-sent-star
661++$ step
662+ [%move %left n=@ud]
663+ [%move %right n=@ud]
664+ [text=@t %draft]
665+ [text=@t %sent at=@da]
666+ %stop
667+
668+++ describe |= s=step
669+ ?- s
670+ [%move %left n] "left {n}"
671+ [%move %right n] "right {n}"
672+ [t %draft] t
673+ [t %sent *] t
674+ %stop "stop"
675+#### /ui/step/jibb step-stop-crash
676++$ step
677+ [%move %left n=@ud]
678+ [%move %right n=@ud]
679+ [text=@t %draft]
680+ [text=@t %sent at=@da]
681+ %stop
682+
683+++ describe |= s=step
684+ ?- s
685+ [%move %left n] "left {n}"
686+ [%move %right n] "right {n}"
687+ [t %draft] t
688+ [t %sent sent-at] t
689+ %stop !!
690+#### /ui/view-day/jibb viewday-swap
691+++ view |= [n=@ud day=@da]
692+ column ~[gap+%s1] ~[
693+ (text "Updated {day}") :: day printed as a date
694+ (text "{n} items") :: n printed as @ud
695+#### /ui/view-day/jibb viewday-add
696+++ view |= [day=@da n=@ud]
697+ column ~[gap+%s1] ~[
698+ (text "Updated {day}") :: day printed as a date
699+ (text "{n} items")
700+ (text "{(add n 1)} next") :: n printed as @ud
701+#### /ui/view-day/jibb viewday-generic-sum
702+++ total
703+ text "{(add 1 2)}"
704+#### /ui/imports/jibb imports-use
705+/- todo :: the molds from /sur/todo.hoon this module uses
706+/% %todo-action :: a mark's type, named todo-action
707+/= card /ui/components/card :: a Jibb module
708+
709+++ first |= i=item.todo
710+ text.i
711+++ show card.card
712+++ act |= a=todo-action a
docs/reviews/2026-11-03-milestone-2-probes/variants/p3.outnew file+262
@@ -0,0 +1,262 @@
1+#### /ui/stores/cart/jibb cart-reorder
2+CHECKED
3++$ poke: poke
4++$ state: [items=(list @t) open=?]
5+++ state: $-($-([items=(list @t) open=?] A) (ask A))
6+++ poke: $-([poke $-((unit @t) A)] (cmd A))
7+++ main: [init=[items=(list @t) open=?] update=*]
8+++ init: [items=(list @t) open=?]
9+++ update: $-([a=poke s=[items=(list @t) open=?]] [items=(list @t) open=?])
10+#### /ui/stores/cart/jibb cart-init-uncast
11+REJECTED: /ui/stores/cart.jibb:8:16: nothing fixes the union of ~
12+++ init [items=~ open=%.n]
13+ ^
14+#### /ui/stores/cart/jibb cart-rename
15+CHECKED
16++$ state: [items=(list @t) open=?]
17++$ poke: poke
18+++ state: $-($-([items=(list @t) open=?] A) (ask A))
19+++ poke: $-([poke $-((unit @t) A)] (cmd A))
20+++ main: [init=[items=(list @t) open=?] update=*]
21+++ update: $-([p=poke st=[items=(list @t) open=?]] [items=(list @t) open=?])
22+++ init: [items=(list @t) open=?]
23+#### /ui/stores/cart/jibb cart-third-case
24+CHECKED
25++$ state: [items=(list @t) open=?]
26++$ poke: poke
27+++ state: $-($-([items=(list @t) open=?] A) (ask A))
28+++ poke: $-([poke $-((unit @t) A)] (cmd A))
29+++ main: [init=[items=(list @t) open=?] update=*]
30+++ update: $-([a=poke s=[items=(list @t) open=?]] [items=(list @t) open=?])
31+++ init: [items=(list @t) open=?]
32+#### /ui/stores/cart/jibb cart-unused-helper
33+CHECKED
34++$ state: [items=(list @t) open=?]
35++$ poke: poke
36+++ state: $-($-([items=(list @t) open=?] A) (ask A))
37+++ poke: $-([poke $-((unit @t) A)] (cmd A))
38+++ main: [init=[items=(list @t) open=?] update=*]
39+++ size: $-([items=(list @t) open=?] @ud)
40+++ update: $-([a=poke s=[items=(list @t) open=?]] [items=(list @t) open=?])
41+++ init: [items=(list @t) open=?]
42+#### /ui/stores/cart/jibb cart-swap-fields
43+CHECKED
44++$ state: [open=? items=(list @t)]
45++$ poke: poke
46+++ state: $-($-([open=? items=(list @t)] A) (ask A))
47+++ poke: $-([poke $-((unit @t) A)] (cmd A))
48+++ main: [init=[open=? items=(list @t)] update=*]
49+++ update: $-([a=poke s=[open=? items=(list @t)]] [open=? items=(list @t)])
50+++ init: [open=? items=(list @t)]
51+#### /ui/stores/cart/jibb cart-update-helper
52+CHECKED
53++$ state: [items=(list @t) open=?]
54++$ poke: poke
55+++ state: $-($-([items=(list @t) open=?] A) (ask A))
56+++ poke: $-([poke $-((unit @t) A)] (cmd A))
57+++ main: [init=[items=(list @t) open=?] update=*]
58+++ update: $-([a=poke s=[items=(list @t) open=?]] [items=(list @t) open=?])
59+++ flip: $-([items=(list @t) open=?] [items=(list @t) open=?])
60+++ init: [items=(list @t) open=?]
61+#### /ui/basket/jibb basket-control
62+CHECKED
63++$ model: [cart=[items=(list @t) open=?] note=@t]
64++$ msg: msg
65+++ main: [init=$-(~ [cart=[items=(list @t) open=?] note=@t]) [update=$-([msg [cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))]) [view=$-([cart=[items=(list @t) open=?] note=@t] (element msg)) subs=$-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))]]]
66+++ init: $-(~ [cart=[items=(list @t) open=?] note=@t])
67+++ view: $-([cart=[items=(list @t) open=?] note=@t] (element msg))
68+++ subs: $-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))
69+++ update: $-([msg=msg m=[cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))])
70+#### /ui/basket/jibb basket-init-cast
71+CHECKED
72++$ model: [cart=[items=(list @t) open=?] note=@t]
73++$ msg: msg
74+++ main: [init=$-(~ [cart=[items=(list @t) open=?] note=@t]) [update=$-([msg [cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))]) [view=$-([cart=[items=(list @t) open=?] note=@t] (element msg)) subs=$-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))]]]
75+++ view: $-([cart=[items=(list @t) open=?] note=@t] (element msg))
76+++ subs: $-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))
77+++ update: $-([msg=msg m=[cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))])
78+++ init: $-(~ [cart=[items=(list @t) open=?] note=@t])
79+#### /ui/basket/jibb basket-rename-view
80+CHECKED
81++$ model: [cart=[items=(list @t) open=?] note=@t]
82++$ msg: msg
83+++ main: [init=$-(~ [cart=[items=(list @t) open=?] note=@t]) [update=$-([msg [cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))]) [view=$-([cart=[items=(list @t) open=?] note=@t] (element msg)) subs=$-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))]]]
84+++ init: $-(~ [cart=[items=(list @t) open=?] note=@t])
85+++ view: $-([cart=[items=(list @t) open=?] note=@t] (element msg))
86+++ subs: $-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))
87+++ update: $-([msg=msg m=[cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))])
88+#### /ui/basket/jibb basket-sixth-msg
89+CHECKED
90++$ model: [cart=[items=(list @t) open=?] note=@t]
91++$ msg: msg
92+++ main: [init=$-(~ [cart=[items=(list @t) open=?] note=@t]) [update=$-([msg [cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))]) [view=$-([cart=[items=(list @t) open=?] note=@t] (element msg)) subs=$-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))]]]
93+++ init: $-(~ [cart=[items=(list @t) open=?] note=@t])
94+++ view: $-([cart=[items=(list @t) open=?] note=@t] (element msg))
95+++ subs: $-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))
96+++ update: $-([msg=msg m=[cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))])
97+#### /ui/basket/jibb basket-second-sub
98+REJECTED: module kind needs unsupported inference: /ui/basket/jibb
99+#### /ui/basket/jibb basket-view-helper
100+CHECKED
101++$ model: [cart=[items=(list @t) open=?] note=@t]
102++$ msg: msg
103+++ main: [init=$-(~ [cart=[items=(list @t) open=?] note=@t]) [update=$-([msg [cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))]) [view=$-([cart=[items=(list @t) open=?] note=@t] (element msg)) subs=$-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))]]]
104+++ init: $-(~ [cart=[items=(list @t) open=?] note=@t])
105+++ view: $-([cart=[items=(list @t) open=?] note=@t] (element msg))
106+++ subs: $-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))
107+++ update: $-([msg=msg m=[cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))])
108+++ count-line: $-([cart=[items=(list @t) open=?] note=@t] (element A))
109+#### /ui/basket/jibb basket-swap-fields
110+CHECKED
111++$ model: [note=@t cart=[items=(list @t) open=?]]
112++$ msg: msg
113+++ main: [init=$-(~ [note=@t cart=[items=(list @t) open=?]]) [update=$-([msg [note=@t cart=[items=(list @t) open=?]]] [[note=@t cart=[items=(list @t) open=?]] (list (cmd msg))]) [view=$-([note=@t cart=[items=(list @t) open=?]] (element msg)) subs=$-([note=@t cart=[items=(list @t) open=?]] (list (sub msg)))]]]
114+++ init: $-(~ [note=@t cart=[items=(list @t) open=?]])
115+++ view: $-([note=@t cart=[items=(list @t) open=?]] (element msg))
116+++ subs: $-([note=@t cart=[items=(list @t) open=?]] (list (sub msg)))
117+++ update: $-([msg=msg m=[note=@t cart=[items=(list @t) open=?]]] [[note=@t cart=[items=(list @t) open=?]] (list (cmd msg))])
118+#### /ui/basket/jibb basket-unused-helper
119+REJECTED: module definitions need unsupported inference: /ui/basket/jibb: ++ empty
120+#### /ui/index/jibb index-reorder
121+CHECKED
122+++ main: [load=$-(~ (ask (list [id=@ud [done=? text=@t]]))) view=$-((list [id=@ud [done=? text=@t]]) (element !!))]
123+++ load: $-(~ (ask (list [id=@ud [done=? text=@t]])))
124+++ view: $-((list [id=@ud [done=? text=@t]]) (element !!))
125+#### /ui/index/jibb index-rename
126+CHECKED
127+++ main: [load=$-(~ (ask (list [id=@ud [done=? text=@t]]))) view=$-((list [id=@ud [done=? text=@t]]) (element !!))]
128+++ view: $-((list [id=@ud [done=? text=@t]]) (element !!))
129+++ load: $-(~ (ask (list [id=@ud [done=? text=@t]])))
130+#### /ui/index/jibb index-tall-load
131+CHECKED
132+++ main: [load=$-(~ (ask (list [id=@ud [done=? text=@t]]))) view=$-((list [id=@ud [done=? text=@t]]) (element !!))]
133+++ view: $-((list [id=@ud [done=? text=@t]]) (element !!))
134+++ load: $-(~ (ask (list [id=@ud [done=? text=@t]])))
135+#### /ui/index/jibb index-cast-load
136+CHECKED
137+++ main: [load=$-(~ (ask (list [id=@ud [done=? text=@t]]))) view=$-((list [id=@ud [done=? text=@t]]) (element !!))]
138+++ view: $-((list [id=@ud [done=? text=@t]]) (element !!))
139+++ load: $-(~ (ask (list [id=@ud [done=? text=@t]])))
140+#### /ui/index/jibb index-view-helper
141+CHECKED
142+++ main: [load=$-(~ (ask (list [id=@ud [done=? text=@t]]))) view=$-((list [id=@ud [done=? text=@t]]) (element !!))]
143+++ view: $-((list [id=@ud [done=? text=@t]]) (element !!))
144+++ title: $-(@t (element A))
145+++ load: $-(~ (ask (list [id=@ud [done=? text=@t]])))
146+#### /ui/index/jibb index-unused-helper
147+CHECKED
148+++ count: $-((list [id=@ud [done=? text=@t]]) @ud)
149+++ main: [load=$-(~ (ask (list [id=@ud [done=? text=@t]]))) view=$-((list [id=@ud [done=? text=@t]]) (element !!))]
150+++ view: $-((list [id=@ud [done=? text=@t]]) (element !!))
151+++ load: $-(~ (ask (list [id=@ud [done=? text=@t]])))
152+#### /ui/index/jibb index-pure-load
153+REJECTED: /ui/index.jibb:5:20: nothing fixes the union of ~
154+++ load |=(~ (pure ~))
155+ ^
156+#### /ui/index/jibb index-mapped-reply
157+CHECKED
158+++ main: [load=$-(~ (ask @ud)) view=$-(@ud (element !!))]
159+++ view: $-(@ud (element A))
160+++ load: $-(~ (ask @ud))
161+#### /ui/index/jibb index-typed-load
162+REJECTED: module kind needs unsupported inference: /ui/index/jibb
163+#### /ui/about/jibb about-reorder
164+CHECKED
165+++ main: (element !!)
166+++ view: (element A)
167+#### /ui/about/jibb about-inline
168+CHECKED
169+++ main: (element !!)
170+#### /ui/about/jibb about-helper
171+CHECKED
172+++ main: (element !!)
173+++ view: (element A)
174+++ intro: (element A)
175+#### /ui/about/jibb about-rename
176+CHECKED
177+++ main: (element !!)
178+++ body: (element A)
179+#### /ui/blog/index/jibb blog-reorder
180+CHECKED
181+++ main: [load=$-(~ (ask (list [title=@t slug=@ta]))) view=$-((list [title=@t slug=@ta]) (element !!))]
182+++ load: $-(~ (ask (list [title=@t slug=@ta])))
183+++ view: $-((list [title=@t slug=@ta]) (element A))
184+#### /ui/blog/index/jibb blog-rename
185+CHECKED
186+++ main: [load=$-(~ (ask (list [title=@t slug=@ta]))) view=$-((list [title=@t slug=@ta]) (element !!))]
187+++ view: $-((list [title=@t slug=@ta]) (element A))
188+++ load: $-(~ (ask (list [title=@t slug=@ta])))
189+#### /ui/blog/index/jibb blog-inline-card
190+CHECKED
191+++ main: [load=$-(~ (ask (list [title=@t slug=@ta]))) view=$-((list [title=@t slug=@ta]) (element !!))]
192+++ view: $-((list [title=@t slug=@ta]) (element A))
193+++ load: $-(~ (ask (list [title=@t slug=@ta])))
194+#### /ui/blog/index/jibb blog-inline-card-bare
195+REJECTED: module definitions need unsupported inference: /ui/blog/index/jibb: ++ view
196+#### /ui/blog/index/jibb blog-local-helper
197+CHECKED
198+++ main: [load=$-(~ (ask (list [title=@t slug=@ta]))) view=$-((list [title=@t slug=@ta]) (element !!))]
199+++ view: $-((list [title=@t slug=@ta]) (element A))
200+++ show: $-([title=@t slug=@ta] (element A))
201+++ load: $-(~ (ask (list [title=@t slug=@ta])))
202+#### /ui/theme/jibb theme-no-font
203+CHECKED
204+++ theme: [space=[s1=@t [s2=@t s3=@t]] [tones=[normal=@t [background=@t [accent=@t [danger=@t muted=@t]]]] [wide=@t [lang=@t [zone=@t [font=(unit qath) dark=(unit [tones=[normal=@t [background=@t [accent=@t [danger=@t muted=@t]]]]])]]]]]]
205+#### /ui/theme/jibb theme-helper-value
206+CHECKED
207+++ theme: [space=[s1=@t [s2=@t s3=@t]] [tones=[normal=@t [background=@t [accent=@t [danger=@t muted=@t]]]] [wide=@t [lang=@t [zone=@t [font=(unit qath) dark=(unit [tones=[normal=@t [background=@t [accent=@t [danger=@t muted=@t]]]]])]]]]]]
208+++ accent: @t
209+#### /ui/components/buttons/jibb buttons-reorder
210+REJECTED: /ui/components/buttons.jibb:6:16: nothing fixes the union of %add
211+ button label %add
212+ ^
213+#### /ui/components/buttons/jibb buttons-fixed
214+CHECKED
215++$ add-msg: %add
216+++ wide: (list attr)
217+++ labelled: $-([label=@t msg=A] (element A))
218+++ add-button: $-(@t (element %add))
219+#### /ui/components/buttons/jibb buttons-labelled-use
220+CHECKED
221++$ go-msg: %go
222+++ go-button: (element %go)
223+++ wide: (list attr)
224+++ labelled: $-([label=@t msg=A] (element A))
225+#### /ui/step/jibb step-reorder
226+CHECKED
227++$ step: step
228+++ describe: $-(step @t)
229+#### /ui/step/jibb step-arm-order
230+CHECKED
231++$ step: step
232+++ describe: $-(step @t)
233+#### /ui/step/jibb step-catch-all
234+CHECKED
235++$ step: step
236+++ describe: $-(step @t)
237+#### /ui/step/jibb step-rename
238+CHECKED
239++$ step: step
240+++ describe: $-(step @t)
241+#### /ui/step/jibb step-sent-star
242+CHECKED
243++$ step: step
244+++ describe: $-(step @t)
245+#### /ui/step/jibb step-stop-crash
246+CHECKED
247++$ step: step
248+++ describe: $-(step @t)
249+#### /ui/view-day/jibb viewday-swap
250+CHECKED
251+++ view: $-([n=@ud day=@da] (element A))
252+#### /ui/view-day/jibb viewday-add
253+CHECKED
254+++ view: $-([day=@da n=@ud] (element A))
255+#### /ui/view-day/jibb viewday-generic-sum
256+REJECTED: module definitions need unsupported inference: /ui/view-day/jibb: ++ total
257+#### /ui/imports/jibb imports-use
258+CHECKED
259+++ act: $-(([%add text=@t] [%toggle id=@ud]) ([%add text=@t] [%toggle id=@ud]))
260+++ show: $-([title=@t slug=@ta] (element A))
261+++ first: $-([id=@ud [done=? text=@t]] @t)
262+
docs/reviews/2026-11-03-milestone-2-probes/variants/p4.jibbnew file+196
@@ -0,0 +1,196 @@
1+#### /ui/probe/jibb inc-generic
2+++ inc |= n=A (add n 1)
3+#### /ui/probe/jibb inc-ud
4+++ inc |= n=@ud (add n 1)
5+++ two (inc 1)
6+#### /ui/probe/jibb clamp-max
7+++ clamp |= [lo=A hi=A n=A]
8+ ?- (gth n hi)
9+ %.y hi
10+ %.n (max lo n)
11+#### /ui/probe/jibb clamp-no-max
12+++ clamp |= [lo=A hi=A n=A]
13+ ?- (gth n hi)
14+ %.y hi
15+ %.n
16+ ?- (gth lo n)
17+ %.y lo
18+ %.n n
19+++ use (clamp 1 10 5)
20+#### /ui/probe/jibb sum-print
21+++ shown "{(add 1 2)}"
22+#### /ui/probe/jibb literals-atoms
23+++ a 0x1f
24+++ b 0v5.fdf99
25+++ c ~zod
26+++ c2 ~sampel-palnet
27+++ d ~2026.10.23
28+++ d2 ~2026.10.23..14.30.00
29+++ e ~s30
30+++ e2 ~h1.m30
31+++ f ~.my-post
32+++ g "milk"
33+++ h %.y
34+++ i 1.000
35+++ j /posts/~zod
36+++ k %/blog
37+#### /ui/probe/jibb literals-containers
38+++ u `5
39+++ l ~[1 2 3]
40+++ t [1 "a"]
41+++ r [text="milk" done=%.n]
42+++ n ^- (unit @ud) ~
43+++ term ^- @tas %add
44+++ pair ^- attr gap+%s2
45+#### /ui/probe/jibb hole-id
46+++ id |= x=A ^- _ x
47+#### /ui/probe/jibb one-case-union
48++$ go [%go url=@t]
49+++ g ^- go [%go "x"]
50+#### /ui/probe/jibb ctor-one-case
51++$ typed [%typed text=@t]
52+++ mk ^- $-(@t typed) |=%typed
53+#### /ui/probe/jibb proj
54+++ wider ^- [x=@ud y=@ud z=@ud] [1 2 3]
55+++ narrow ^- [x=@ud y=@ud] (proj wider)
56+#### /ui/probe/jibb unnamed-takes-face
57+++ pt ^- [x=@ud y=@ud] [0 0]
58+#### /ui/probe/jibb widen-to-bare-atom
59+++ f |= a=@ a
60+++ g (f 5)
61+#### /ui/probe/jibb widen-aura-family
62+++ f |= a=@u a
63+++ five ^- @ud 5
64+++ g (f five)
65+#### /ui/probe/jibb pattern-unit
66+++ show |= u=(unit @ud)
67+ ?- u
68+ ~ 0
69+ [~ x] x
70+#### /ui/probe/jibb pattern-pair-units
71+++ both |= p=[(unit @ud) (unit @ud)]
72+ ?- p
73+ [[~ a] [~ b]] (add a b)
74+ * 0
75+#### /ui/probe/jibb pattern-list-one
76+++ one |= xs=(list @ud)
77+ ?- xs
78+ [x ~] x
79+ * 0
80+#### /ui/probe/jibb pattern-literals
81+++ lit |= n=@ud
82+ ?- n
83+ 1.000 %.y
84+ * %.n
85+++ who |= s=@p
86+ ?- s
87+ ~zod "zod"
88+ * "other"
89+++ milk |= t=@t
90+ ?- t
91+ "milk" %.y
92+ * %.n
93+#### /ui/probe/jibb pattern-eq
94+++ same-ud |= [a=@ud b=@ud]
95+ ?- (eq a b)
96+ %.y "same"
97+ %.n "different"
98+#### /ui/probe/jibb gate-free-generic
99+++ same-as |= [a=A b=A] (eq a b)
100+#### /ui/probe/jibb cons-where-list
101+++ cons |= xs=(list @ud)
102+ ^- (list @ud) [1 xs]
103+#### /ui/probe/jibb shared-capital
104+++ outer |= x=A
105+ ++ inner |= y=A y
106+ (inner x)
107+#### /ui/probe/jibb bind-any-depth
108+++ f |= [a=@ b]
109+ a
110+++ g (f 1 "x")
111+#### /ui/probe/jibb roll
112+++ total |= xs=(list @ud) (roll xs 0 add)
113+#### /ui/probe/jibb clap
114+++ both (clap `1 `2 add)
115+#### /ui/probe/jibb bare-sample-inline
116+++ titles |= ps=(list [title=@t n=@ud])
117+ (turn ps |=(p title.p))
118+#### /ui/probe/jibb typed-sample-inline
119+++ titles |= ps=(list [title=@t n=@ud])
120+ (turn ps |=(p=[title=@t n=@ud] title.p))
121+#### /ui/probe/jibb image-element
122+++ logo ^- (element !!) (image %/static/img/logo.png "The logo")
123+#### /ui/probe/jibb get-by
124+++ look |= [m=(map @t @ud) k=@t] (get.by m k)
125+#### /ui/probe/jibb items-count
126+++ show |= n=@ud
127+ text "{n} items"
128+#### /ui/probe/jibb add-cmd-helper-lib
129++$ msg
130+ [%acked err=(unit @t)]
131+ %go
132+++ wait-cmd |= gap=@dr
133+ ^- (cmd msg) [%wait gap %go]
134+#### /ui/probe/jibb eq-list-null
135+++ empty |= xs=(list @t) (eq xs ~)
136+#### /ui/probe/jibb fall-literal
137+++ f |= e=(unit @t) (fall e "")
138+#### /ui/probe/jibb lent-tuba-trip
139+++ long |= t=@t (gth (lent (tuba (trip t))) 80)
140+#### /ui/api/journal/jibb module journal-api
141+/% %posts
142+
143++$ paths
144+ [%posts /posts posts]
145+ [%post /post/[slug=@ta] posts]
146+#### /ui/blog/_slug/jibb slug-page
147+/= api /ui/api/journal
148+
149+++ main (page load view)
150+++ load |=([slug=@ta] (post.api slug same))
151+
152+++ view |= ps=posts.api
153+ text "post"
154+#### /ui/settings/__rest/jibb catch-all-page
155+++ main (page load view)
156+++ load |=(p=path (pure p))
157+
158+++ view |= p=path
159+ text "settings"
160+#### /ui/todo-list/jibb island-changes-fold
161+/= todo /ui/api/todo
162+
163+++ main (program init update view subs)
164+
165++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
166++$ msg
167+ [%typed text=@t]
168+ %submit
169+ [%toggled id=@ud]
170+ [%got todos=(list item.todo)]
171+ [%acked err=(unit @t)]
172+
173+++ init |= ts=(list item.todo)
174+ [todos=ts draft="" error=~]
175+
176+++ update |= [=msg m=model]
177+ ?- msg
178+ [%typed t] [m(draft=t) ~]
179+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
180+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
181+ [%got ts] [m(todos=ts) ~]
182+ [%acked err] [m(error=err) ~]
183+
184+++ apply |= [d=[%todo-update todo-update.todo] s=todos.todo]
185+ s
186+
187+++ subs |= m=model
188+ ~[[%watch (changes.todo |=%got apply)]]
189+
190+++ view |= m=model
191+ column ~[gap+%s2] ~[
192+ heading 2 "Todos"
193+ each (turn todos.m row-of)
194+
195+++ row-of |= t=item.todo
196+ [id.t (toggle done.t text.t [%toggled id.t])]
docs/reviews/2026-11-03-milestone-2-probes/variants/p4.outnew file+113
@@ -0,0 +1,113 @@
1+#### /ui/probe/jibb inc-generic
2+CHECKED
3+++ inc: $-(A A)
4+#### /ui/probe/jibb inc-ud
5+CHECKED
6+++ two: @ud
7+++ inc: $-(@ud @ud)
8+#### /ui/probe/jibb clamp-max
9+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ clamp
10+#### /ui/probe/jibb clamp-no-max
11+CHECKED
12+++ use: @ud
13+++ clamp: $-([lo=A [hi=A n=A]] A)
14+#### /ui/probe/jibb sum-print
15+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ shown
16+#### /ui/probe/jibb literals-atoms
17+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ j
18+#### /ui/probe/jibb literals-containers
19+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ u
20+#### /ui/probe/jibb hole-id
21+CHECKED
22+++ id: $-(A A)
23+#### /ui/probe/jibb one-case-union
24+CHECKED
25++$ go: [%go url=@t]
26+++ g: [%go url=@t]
27+#### /ui/probe/jibb ctor-one-case
28+CHECKED
29++$ typed: [%typed text=@t]
30+++ mk: $-(@t [%typed text=@t])
31+#### /ui/probe/jibb proj
32+CHECKED
33+++ narrow: [x=@ud y=@ud]
34+++ wider: [x=@ud [y=@ud z=@ud]]
35+#### /ui/probe/jibb unnamed-takes-face
36+CHECKED
37+++ pt: [x=@ud y=@ud]
38+#### /ui/probe/jibb widen-to-bare-atom
39+CHECKED
40+++ g: @
41+++ f: $-(@ @)
42+#### /ui/probe/jibb widen-aura-family
43+CHECKED
44+++ g: @u
45+++ five: @ud
46+++ f: $-(@u @u)
47+#### /ui/probe/jibb pattern-unit
48+CHECKED
49+++ show: $-((unit @ud) @ud)
50+#### /ui/probe/jibb pattern-pair-units
51+REJECTED: module has conflicting names: /ui/probe/jibb
52+#### /ui/probe/jibb pattern-list-one
53+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ one
54+#### /ui/probe/jibb pattern-literals
55+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ lit
56+#### /ui/probe/jibb pattern-eq
57+CHECKED
58+++ same-ud: $-([a=@ud b=@ud] @t)
59+#### /ui/probe/jibb gate-free-generic
60+CHECKED
61+++ same-as: $-([a=A b=A] ?)
62+#### /ui/probe/jibb cons-where-list
63+CHECKED
64+++ cons: $-((list @ud) (list @ud))
65+#### /ui/probe/jibb shared-capital
66+CHECKED
67+++ outer: $-(A A)
68+#### /ui/probe/jibb bind-any-depth
69+CHECKED
70+++ g: @
71+++ f: $-([a=@ b=A] @)
72+#### /ui/probe/jibb roll
73+CHECKED
74+++ total: $-((list @ud) @ud)
75+#### /ui/probe/jibb clap
76+REJECTED: module has conflicting names: /ui/probe/jibb
77+#### /ui/probe/jibb bare-sample-inline
78+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ titles
79+#### /ui/probe/jibb typed-sample-inline
80+CHECKED
81+++ titles: $-((list [title=@t n=@ud]) (list @t))
82+#### /ui/probe/jibb image-element
83+CHECKED
84+++ logo: (element !!)
85+#### /ui/probe/jibb get-by
86+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ look
87+#### /ui/probe/jibb items-count
88+CHECKED
89+++ show: $-(@ud (element A))
90+#### /ui/probe/jibb add-cmd-helper-lib
91+CHECKED
92++$ msg: msg
93+++ wait-cmd: $-(@dr (cmd msg))
94+#### /ui/probe/jibb eq-list-null
95+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ empty
96+#### /ui/probe/jibb fall-literal
97+CHECKED
98+++ f: $-((unit @t) @t)
99+#### /ui/probe/jibb lent-tuba-trip
100+CHECKED
101+++ long: $-(@t ?)
102+#### /ui/api/journal/jibb module journal-api
103+CHECKED
104++$ posts: (list [title=@t slug=@ta])
105+++ posts: $-($-((list [title=@t slug=@ta]) A) (ask A))
106+++ post: $-([@ta $-((list [title=@t slug=@ta]) A)] (ask A))
107+#### /ui/blog/_slug/jibb slug-page
108+REJECTED: module kind needs unsupported inference: /ui/blog/_slug/jibb
109+#### /ui/settings/__rest/jibb catch-all-page
110+REJECTED: module kind needs unsupported inference: /ui/settings/__rest/jibb
111+#### /ui/todo-list/jibb island-changes-fold
112+REJECTED: module kind needs unsupported inference: /ui/todo-list/jibb
113+
docs/reviews/2026-11-03-milestone-2-probes/variants/p5.jibbnew file+130
@@ -0,0 +1,130 @@
1+#### /ui/probe/jibb lit-hex
2+++ x 0x1f
3+#### /ui/probe/jibb lit-b32
4+++ x 0v5.fdf99
5+#### /ui/probe/jibb lit-ship
6+++ x ~zod
7+#### /ui/probe/jibb lit-ship2
8+++ x ~sampel-palnet
9+#### /ui/probe/jibb lit-date
10+++ x ~2026.10.23
11+#### /ui/probe/jibb lit-date2
12+++ x ~2026.10.23..14.30.00
13+#### /ui/probe/jibb lit-dur
14+++ x ~s30
15+#### /ui/probe/jibb lit-dur2
16+++ x ~h1.m30
17+#### /ui/probe/jibb lit-knot
18+++ x ~.my-post
19+#### /ui/probe/jibb lit-str
20+++ x "milk"
21+#### /ui/probe/jibb lit-loob
22+++ x %.y
23+#### /ui/probe/jibb lit-dec
24+++ x 1.000
25+#### /ui/probe/jibb lit-path
26+++ x /posts/~zod
27+#### /ui/probe/jibb lit-qath
28+++ x %/blog
29+#### /ui/probe/jibb lit-unit
30+++ x `5
31+#### /ui/probe/jibb lit-list
32+++ x ~[1 2 3]
33+#### /ui/probe/jibb lit-tuple
34+++ x [1 "a"]
35+#### /ui/probe/jibb lit-record
36+++ x [text="milk" done=%.n]
37+#### /ui/probe/jibb lit-null-cast
38+++ x ^- (unit @ud) ~
39+#### /ui/probe/jibb lit-term-cast
40+++ x ^- @tas %add
41+#### /ui/probe/jibb lit-pair-cast
42+++ x ^- attr gap+%s2
43+#### /ui/probe/jibb lit-num-term-cast
44+++ x ^- @ %1.000
45+#### /ui/probe/jibb lit-empty-path
46+++ x /
47+#### /ui/probe/jibb lit-unit-cast
48+++ x ^- (unit @ud) `5
49+#### /ui/probe/jibb lit-list-cast
50+++ x ^- (list @ud) ~[1 2 3]
51+#### /ui/probe/jibb lit-path-cast
52+++ x ^- path /posts/~zod
53+#### /ui/probe/jibb lit-interp-day
54+++ x "Since {~2026.10.23}"
55+#### /ui/probe/jibb inc-cell-unsound?
56+++ inc |= n=A (add n 1)
57+++ bad (inc [1 2])
58+#### /ui/probe/jibb inc-loobean
59+++ inc |= n=A (add n 1)
60+++ bad (inc %.y)
61+#### /ui/probe/jibb inc-generic-print
62+++ inc |= n=A (add n 1)
63+#### /ui/probe/jibb eq-gates-unsound?
64+++ same-as |= [a=A b=A] (eq a b)
65+++ bad (same-as same same)
66+#### /ui/probe/jibb eq-generic-print
67+++ same-as |= [a=A b=A] (eq a b)
68+#### /ui/probe/jibb clamp-print
69+++ clamp |= [lo=A hi=A n=A]
70+ ?- (gth n hi)
71+ %.y hi
72+ %.n
73+ ?- (gth lo n)
74+ %.y lo
75+ %.n n
76+#### /ui/probe/jibb unknown-name
77+++ x (nosuch 1)
78+#### /ui/probe/jibb pattern-pair-units
79+++ pair-sum |= p=[(unit @ud) (unit @ud)]
80+ ?- p
81+ [[~ a] [~ b]] (add a b)
82+ * 0
83+#### /ui/probe/jibb clap-units
84+++ summed (clap `1 `2 add)
85+#### /ui/probe/jibb pattern-lit-ud
86+++ lit |= n=@ud
87+ ?- n
88+ 1.000 %.y
89+ * %.n
90+#### /ui/probe/jibb pattern-lit-ship
91+++ who |= s=@p
92+ ?- s
93+ ~zod "zod"
94+ * "other"
95+#### /ui/probe/jibb pattern-lit-cord
96+++ milk |= t=@t
97+ ?- t
98+ "milk" %.y
99+ * %.n
100+#### /ui/probe/jibb pattern-list-cons
101+++ first |= xs=(list @ud)
102+ ?- xs
103+ ~ 0
104+ [x xs2] x
105+#### /ui/probe/jibb pattern-list-one-catch
106+++ one |= xs=(list @ud)
107+ ?- xs
108+ [x ~] x
109+ * 0
110+#### /ui/probe/jibb pattern-trailing-rest
111+++ second |= p=[(unit @ud) (unit @ud)]
112+ ?- p
113+ [~ b] b
114+ * ~
115+#### /ui/probe/jibb print-sum-annotated
116+++ shown ^- @t "{(add 1 2)}"
117+#### /ui/probe/jibb print-ud-var
118+++ shown |= n=@ud "{n} items"
119+#### /ui/probe/jibb print-generic-error
120+++ shown |= n=A
121+ "{(add n 1)}"
122+#### /ui/probe/jibb eq-list-null
123+++ empty |= xs=(list @t) (eq xs ~)
124+#### /ui/probe/jibb eq-list-null-cast
125+++ empty |= xs=(list @t) (eq xs ^-((list @t) ~))
126+#### /ui/probe/jibb self-ref-error
127+++ title (lent title)
128+#### /ui/probe/jibb capital-made-ud
129+++ f |= x=A (add x ^- @ud 1)
130+
docs/reviews/2026-11-03-milestone-2-probes/variants/p5.outnew file+127
@@ -0,0 +1,127 @@
1+#### /ui/probe/jibb lit-hex
2+CHECKED
3+++ x: @ux
4+#### /ui/probe/jibb lit-b32
5+CHECKED
6+++ x: @uv
7+#### /ui/probe/jibb lit-ship
8+CHECKED
9+++ x: @p
10+#### /ui/probe/jibb lit-ship2
11+CHECKED
12+++ x: @p
13+#### /ui/probe/jibb lit-date
14+CHECKED
15+++ x: @da
16+#### /ui/probe/jibb lit-date2
17+CHECKED
18+++ x: @da
19+#### /ui/probe/jibb lit-dur
20+CHECKED
21+++ x: @dr
22+#### /ui/probe/jibb lit-dur2
23+CHECKED
24+++ x: @dr
25+#### /ui/probe/jibb lit-knot
26+CHECKED
27+++ x: @ta
28+#### /ui/probe/jibb lit-str
29+CHECKED
30+++ x: @t
31+#### /ui/probe/jibb lit-loob
32+CHECKED
33+++ x: ?
34+#### /ui/probe/jibb lit-dec
35+CHECKED
36+++ x: @ud
37+#### /ui/probe/jibb lit-path
38+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ x
39+#### /ui/probe/jibb lit-qath
40+CHECKED
41+++ x: qath
42+#### /ui/probe/jibb lit-unit
43+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ x
44+#### /ui/probe/jibb lit-list
45+CHECKED
46+++ x: (list @ud)
47+#### /ui/probe/jibb lit-tuple
48+CHECKED
49+++ x: [@ud @t]
50+#### /ui/probe/jibb lit-record
51+CHECKED
52+++ x: [text=@t done=?]
53+#### /ui/probe/jibb lit-null-cast
54+CHECKED
55+++ x: (unit @ud)
56+#### /ui/probe/jibb lit-term-cast
57+CHECKED
58+++ x: @tas
59+#### /ui/probe/jibb lit-pair-cast
60+CHECKED
61+++ x: attr
62+#### /ui/probe/jibb lit-num-term-cast
63+CHECKED
64+++ x: @
65+#### /ui/probe/jibb lit-empty-path
66+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ x
67+#### /ui/probe/jibb lit-unit-cast
68+CHECKED
69+++ x: (unit @ud)
70+#### /ui/probe/jibb lit-list-cast
71+CHECKED
72+++ x: (list @ud)
73+#### /ui/probe/jibb lit-path-cast
74+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ x
75+#### /ui/probe/jibb lit-interp-day
76+CHECKED
77+++ x: @t
78+#### /ui/probe/jibb inc-cell-unsound?
79+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ bad
80+#### /ui/probe/jibb inc-loobean
81+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ bad
82+#### /ui/probe/jibb inc-generic-print
83+CHECKED
84+++ inc: $-(A A) where A is an atom other than ?
85+#### /ui/probe/jibb eq-gates-unsound?
86+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ bad
87+#### /ui/probe/jibb eq-generic-print
88+CHECKED
89+++ same-as: $-([a=A b=A] ?) where A contains no gates
90+#### /ui/probe/jibb clamp-print
91+CHECKED
92+++ clamp: $-([lo=A [hi=A n=A]] A) where A is an atom
93+#### /ui/probe/jibb unknown-name
94+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ x
95+#### /ui/probe/jibb pattern-pair-units
96+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ pair-sum
97+#### /ui/probe/jibb clap-units
98+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ summed
99+#### /ui/probe/jibb pattern-lit-ud
100+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ lit
101+#### /ui/probe/jibb pattern-lit-ship
102+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ who
103+#### /ui/probe/jibb pattern-lit-cord
104+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ milk
105+#### /ui/probe/jibb pattern-list-cons
106+CHECKED
107+++ first: $-((list @ud) @ud)
108+#### /ui/probe/jibb pattern-list-one-catch
109+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ one
110+#### /ui/probe/jibb pattern-trailing-rest
111+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ second
112+#### /ui/probe/jibb print-sum-annotated
113+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ shown
114+#### /ui/probe/jibb print-ud-var
115+CHECKED
116+++ shown: $-(@ud @t)
117+#### /ui/probe/jibb print-generic-error
118+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ shown
119+#### /ui/probe/jibb eq-list-null
120+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ empty
121+#### /ui/probe/jibb eq-list-null-cast
122+REJECTED: module source does not parse: /ui/probe/jibb
123+#### /ui/probe/jibb self-ref-error
124+REJECTED: module definitions need unsupported inference: /ui/probe/jibb: ++ title
125+#### /ui/probe/jibb capital-made-ud
126+REJECTED: module source does not parse: /ui/probe/jibb
127+
docs/reviews/2026-11-03-milestone-2-probes/variants/p6.jibbnew file+498
@@ -0,0 +1,498 @@
1+#### /ui/todo-list/jibb todo-full-alias
2+/= todo /ui/api/todo
3+
4+++ main (program init update view subs)
5+
6++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
7++$ msg
8+ [%typed text=@t]
9+ %submit
10+ [%toggled id=@ud]
11+ [%got todos=(list item.todo)]
12+ [%acked err=(unit @t)]
13+
14+++ init |= ts=(list item.todo)
15+ [ts "" ~]
16+
17+++ update |= [=msg m=model]
18+ ?- msg
19+ [%typed t]
20+ ?- (gth (lent (tuba (trip t))) 80)
21+ %.y [m(draft=t error=`"Too long") ~]
22+ %.n [m(draft=t error=~) ~]
23+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
24+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
25+ [%got ts] [m(todos=ts) ~]
26+ [%acked err] [m(error=err) ~]
27+
28+++ subs |= m=model
29+ ~[[%watch (todos.todo |=%got)]]
30+
31+++ view |= m=model
32+ column ~[gap+%s2] ~[
33+ heading 2 "Todos"
34+ each (turn todos.m row-alias)
35+ row ~[gap+%s1] ~[
36+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
37+ button "Add" %submit
38+ el ~[tone+%danger] (text (fall error.m ""))
39+
40+++ row-of |= t=item.todo
41+ [id.t (toggle done.t text.t [%toggled id.t])]
42+
43+++ row-alias row-of
44+#### /ui/todo-list/jibb todo-full-ambiguous-mapper
45+/= todo /ui/api/todo
46+
47+++ main (program init update view subs)
48+
49++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
50++$ msg
51+ [%typed text=@t]
52+ %submit
53+ [%toggled id=@ud]
54+ [%got todos=(list item.todo)]
55+ [%acked err=(unit @t)]
56+
57+++ init |= ts=(list item.todo)
58+ [ts "" ~]
59+
60+++ update |= [=msg m=model]
61+ ?- msg
62+ [%typed t]
63+ ?- (gth (lent (tuba (trip t))) 80)
64+ %.y [m(draft=t error=`"Too long") ~]
65+ %.n [m(draft=t error=~) ~]
66+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
67+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
68+ [%got ts] [m(todos=ts) ~]
69+ [%acked err] [m(error=err) ~]
70+
71+++ subs |= m=model
72+ ~[[%watch (todos.todo |=%got)]]
73+
74+++ view |= m=model
75+ column ~[gap+%s2] ~[
76+ heading 2 "Todos"
77+ each (turn todos.m row-of)
78+ each (turn todos.m row-of)
79+ row ~[gap+%s1] ~[
80+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
81+ button "Add" %submit
82+ el ~[tone+%danger] (text (fall error.m ""))
83+
84+++ row-of |= t=item.todo
85+ [id.t (toggle done.t text.t [%toggled id.t])]
86+#### /ui/index/jibb page-main-page-alias
87+/= todo /ui/api/todo
88+/= todo-list /ui/todo-list
89+
90+++ make-page page
91+++ main (make-page load view)
92+++ load |=(~ (todos.todo same))
93+
94+++ view |= ts=(list item.todo)
95+ column ~[pad+%s3] ~[
96+ heading 1 "My ship"
97+ island main.todo-list ts
98+#### /ui/index/jibb page-main-indirect-load
99+/= todo /ui/api/todo
100+/= todo-list /ui/todo-list
101+
102+++ main (page load view)
103+++ request |=(~ (todos.todo same))
104+++ load |=(~ (request ~))
105+
106+++ view |= ts=(list item.todo)
107+ column ~[pad+%s3] ~[
108+ heading 1 "My ship"
109+ island main.todo-list ts
110+#### /ui/index/jibb page-main-pure-load
111+/= todo /ui/api/todo
112+/= todo-list /ui/todo-list
113+
114+++ main (page load view)
115+++ load |=(~ (pure ~))
116+
117+++ view |= ts=(list item.todo)
118+ column ~[pad+%s3] ~[
119+ heading 1 "My ship"
120+ island main.todo-list ts
121+#### /ui/index/jibb page-main-hand-built-load
122+/= todo /ui/api/todo
123+/= todo-list /ui/todo-list
124+
125+++ main (page load view)
126+++ load |=(~
127+ ^- (ask (list item.todo))
128+ [%agent api="/ui/api/todo" case=%todos agent=%todo path=~[%todos] scry=~ receive=receive])
129+++ receive |= input=[mark=@tas state=(unit *) fact=*]
130+ ^- [state=* message=(list item.todo)] [state=0 message=~]
131+
132+++ view |= ts=(list item.todo)
133+ column ~[pad+%s3] ~[
134+ heading 1 "My ship"
135+ island main.todo-list ts
136+#### /ui/index/jibb page-main-typed-load
137+/= todo /ui/api/todo
138+/= todo-list /ui/todo-list
139+
140+++ main (page load view)
141+++ load |=(~ (todo-by-id.todo 1 |=%one))
142+
143+++ view |= item=todo-item.todo
144+ text "One todo"
145+#### /ui/index/jibb page-main-diff-load
146+/= todo /ui/api/todo
147+/= todo-list /ui/todo-list
148+
149+++ main (page load view)
150+++ fold |= [d=[%todo-update todo-update.todo] s=todos.todo] s
151+++ load |=(~ (changes.todo same fold))
152+
153+++ view |= ts=(list item.todo)
154+ column ~[pad+%s3] ~[
155+ heading 1 "My ship"
156+ island main.todo-list ts
157+#### /ui/stores/cart/jibb store-alias-main
158+:: /ui/stores/cart.jibb
159++$ state [items=(list @t) open=?]
160++$ poke
161+ [%add item=@t]
162+ %toggle
163+
164+++ main (build init update)
165+++ init ^- state [items=~ open=%.n]
166+++ update |= [a=poke s=state]
167+ ?- a
168+ [%add item] s(items=[item items.s])
169+ %toggle s(open=(not open.s))
170+++ build store
171+#### /ui/stores/cart/jibb store-hand-main
172+:: /ui/stores/cart.jibb
173++$ state [items=(list @t) open=?]
174++$ poke
175+ [%add item=@t]
176+ %toggle
177+
178+++ main [init update]
179+++ init ^- state [items=~ open=%.n]
180+++ update |= [a=poke s=state]
181+ ?- a
182+ [%add item] s(items=[item items.s])
183+ %toggle s(open=(not open.s))
184+#### /ui/todo-list/jibb castinit-second-watch
185+/= todo /ui/api/todo
186+
187+++ main (program init update view subs)
188+
189++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
190++$ msg
191+ [%typed text=@t]
192+ %submit
193+ [%toggled id=@ud]
194+ [%got todos=(list item.todo)]
195+ [%acked err=(unit @t)]
196+
197+++ init |= ts=(list item.todo)
198+ ^- model [ts "" ~]
199+
200+++ update |= [=msg m=model]
201+ ?- msg
202+ [%typed t]
203+ ?- (gth (lent (tuba (trip t))) 80)
204+ %.y [m(draft=t error=`"Too long") ~]
205+ %.n [m(draft=t error=~) ~]
206+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
207+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
208+ [%got ts] [m(todos=ts) ~]
209+ [%acked err] [m(error=err) ~]
210+
211+++ subs |= m=model
212+ ~[[%watch (todos.todo |=%got)] [%watch (todos.todo |=%got)]]
213+
214+++ view |= m=model
215+ column ~[gap+%s2] ~[
216+ heading 2 "Todos"
217+ each (turn todos.m row-of)
218+ row ~[gap+%s1] ~[
219+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
220+ button "Add" %submit
221+ el ~[tone+%danger] (text (fall error.m ""))
222+
223+++ row-of |= t=item.todo
224+ [id.t (toggle done.t text.t [%toggled id.t])]
225+#### /ui/todo-list/jibb castinit-subs-none
226+/= todo /ui/api/todo
227+
228+++ main (program init update view subs)
229+
230++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
231++$ msg
232+ [%typed text=@t]
233+ %submit
234+ [%toggled id=@ud]
235+ [%got todos=(list item.todo)]
236+ [%acked err=(unit @t)]
237+
238+++ init |= ts=(list item.todo)
239+ ^- model [ts "" ~]
240+
241+++ update |= [=msg m=model]
242+ ?- msg
243+ [%typed t]
244+ ?- (gth (lent (tuba (trip t))) 80)
245+ %.y [m(draft=t error=`"Too long") ~]
246+ %.n [m(draft=t error=~) ~]
247+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
248+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
249+ [%got ts] [m(todos=ts) ~]
250+ [%acked err] [m(error=err) ~]
251+
252+++ subs |=(m ~)
253+
254+++ view |= m=model
255+ column ~[gap+%s2] ~[
256+ heading 2 "Todos"
257+ each (turn todos.m row-of)
258+ row ~[gap+%s1] ~[
259+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
260+ button "Add" %submit
261+ el ~[tone+%danger] (text (fall error.m ""))
262+
263+++ row-of |= t=item.todo
264+ [id.t (toggle done.t text.t [%toggled id.t])]
265+#### /ui/todo-list/jibb castinit-subs-none-typed
266+/= todo /ui/api/todo
267+
268+++ main (program init update view subs)
269+
270++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
271++$ msg
272+ [%typed text=@t]
273+ %submit
274+ [%toggled id=@ud]
275+ [%got todos=(list item.todo)]
276+ [%acked err=(unit @t)]
277+
278+++ init |= ts=(list item.todo)
279+ ^- model [ts "" ~]
280+
281+++ update |= [=msg m=model]
282+ ?- msg
283+ [%typed t]
284+ ?- (gth (lent (tuba (trip t))) 80)
285+ %.y [m(draft=t error=`"Too long") ~]
286+ %.n [m(draft=t error=~) ~]
287+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
288+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
289+ [%got ts] [m(todos=ts) ~]
290+ [%acked err] [m(error=err) ~]
291+
292+++ subs |=(m=model ~)
293+
294+++ view |= m=model
295+ column ~[gap+%s2] ~[
296+ heading 2 "Todos"
297+ each (turn todos.m row-of)
298+ row ~[gap+%s1] ~[
299+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
300+ button "Add" %submit
301+ el ~[tone+%danger] (text (fall error.m ""))
302+
303+++ row-of |= t=item.todo
304+ [id.t (toggle done.t text.t [%toggled id.t])]
305+#### /ui/todo-list/jibb castinit-inline-row
306+/= todo /ui/api/todo
307+
308+++ main (program init update view subs)
309+
310++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
311++$ msg
312+ [%typed text=@t]
313+ %submit
314+ [%toggled id=@ud]
315+ [%got todos=(list item.todo)]
316+ [%acked err=(unit @t)]
317+
318+++ init |= ts=(list item.todo)
319+ ^- model [ts "" ~]
320+
321+++ update |= [=msg m=model]
322+ ?- msg
323+ [%typed t]
324+ ?- (gth (lent (tuba (trip t))) 80)
325+ %.y [m(draft=t error=`"Too long") ~]
326+ %.n [m(draft=t error=~) ~]
327+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
328+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
329+ [%got ts] [m(todos=ts) ~]
330+ [%acked err] [m(error=err) ~]
331+
332+++ subs |= m=model
333+ ~[[%watch (todos.todo |=%got)]]
334+
335+++ view |= m=model
336+ column ~[gap+%s2] ~[
337+ heading 2 "Todos"
338+ each (turn todos.m |=(t=item.todo [id.t (toggle done.t text.t [%toggled id.t])]))
339+ row ~[gap+%s1] ~[
340+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
341+ button "Add" %submit
342+ el ~[tone+%danger] (text (fall error.m ""))
343+#### /ui/todo-list/jibb castinit-update-helper
344+/= todo /ui/api/todo
345+
346+++ main (program init update view subs)
347+
348++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
349++$ msg
350+ [%typed text=@t]
351+ %submit
352+ [%toggled id=@ud]
353+ [%got todos=(list item.todo)]
354+ [%acked err=(unit @t)]
355+
356+++ init |= ts=(list item.todo)
357+ ^- model [ts "" ~]
358+
359+++ update |= [=msg m=model]
360+ ?- msg
361+ [%typed t]
362+ ?- (gth (lent (tuba (trip t))) 80)
363+ %.y [m(draft=t error=`"Too long") ~]
364+ %.n [m(draft=t error=~) ~]
365+ %submit [m(draft="") ~[(add-cmd draft.m)]]
366+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
367+ [%got ts] [m(todos=ts) ~]
368+ [%acked err] [m(error=err) ~]
369+
370+++ subs |= m=model
371+ ~[[%watch (todos.todo |=%got)]]
372+
373+++ view |= m=model
374+ column ~[gap+%s2] ~[
375+ heading 2 "Todos"
376+ each (turn todos.m row-of)
377+ row ~[gap+%s1] ~[
378+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
379+ button "Add" %submit
380+ el ~[tone+%danger] (text (fall error.m ""))
381+
382+++ row-of |= t=item.todo
383+ [id.t (toggle done.t text.t [%toggled id.t])]
384+
385+++ add-cmd |= d=@t
386+ (poke.todo [%add d] |=%acked)
387+#### /ui/todo-list/jibb castinit-second-sub-every
388+/= todo /ui/api/todo
389+
390+++ main (program init update view subs)
391+
392++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
393++$ msg
394+ [%typed text=@t]
395+ %submit
396+ [%toggled id=@ud]
397+ [%got todos=(list item.todo)]
398+ [%acked err=(unit @t)]
399+ [%tick at=@da]
400+
401+++ init |= ts=(list item.todo)
402+ ^- model [ts "" ~]
403+
404+++ update |= [=msg m=model]
405+ ?- msg
406+ [%typed t]
407+ ?- (gth (lent (tuba (trip t))) 80)
408+ %.y [m(draft=t error=`"Too long") ~]
409+ %.n [m(draft=t error=~) ~]
410+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
411+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
412+ [%got ts] [m(todos=ts) ~]
413+ [%acked err] [m(error=err) ~]
414+ [%tick at] [m ~]
415+
416+++ subs |= m=model
417+ ~[[%watch (todos.todo |=%got)] [%every ~s30 |=%tick]]
418+
419+++ view |= m=model
420+ column ~[gap+%s2] ~[
421+ heading 2 "Todos"
422+ each (turn todos.m row-of)
423+ row ~[gap+%s1] ~[
424+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
425+ button "Add" %submit
426+ el ~[tone+%danger] (text (fall error.m ""))
427+
428+++ row-of |= t=item.todo
429+ [id.t (toggle done.t text.t [%toggled id.t])]
430+#### /ui/todo-list/jibb castinit-every-only
431+/= todo /ui/api/todo
432+
433+++ main (program init update view subs)
434+
435++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
436++$ msg
437+ [%typed text=@t]
438+ %submit
439+ [%toggled id=@ud]
440+ [%got todos=(list item.todo)]
441+ [%acked err=(unit @t)]
442+ [%tick at=@da]
443+
444+++ init |= ts=(list item.todo)
445+ ^- model [ts "" ~]
446+
447+++ update |= [=msg m=model]
448+ ?- msg
449+ [%typed t]
450+ ?- (gth (lent (tuba (trip t))) 80)
451+ %.y [m(draft=t error=`"Too long") ~]
452+ %.n [m(draft=t error=~) ~]
453+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
454+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
455+ [%got ts] [m(todos=ts) ~]
456+ [%acked err] [m(error=err) ~]
457+ [%tick at] [m ~]
458+
459+++ subs |= m=model
460+ ~[[%every ~s30 |=%tick]]
461+
462+++ view |= m=model
463+ column ~[gap+%s2] ~[
464+ heading 2 "Todos"
465+ each (turn todos.m row-of)
466+ row ~[gap+%s1] ~[
467+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
468+ button "Add" %submit
469+ el ~[tone+%danger] (text (fall error.m ""))
470+
471+++ row-of |= t=item.todo
472+ [id.t (toggle done.t text.t [%toggled id.t])]
473+#### /ui/stores/cart/jibb cart-init-uncast-tuple
474+:: /ui/stores/cart.jibb
475++$ state [items=(list @t) open=?]
476++$ poke
477+ [%add item=@t]
478+ %toggle
479+
480+++ main (store init update)
481+++ init [~ %.n]
482+++ update |= [a=poke s=state]
483+ ?- a
484+ [%add item] s(items=[item items.s])
485+ %toggle s(open=(not open.s))
486+#### /ui/stores/cart/jibb cart-init-uncast-nonull
487+:: /ui/stores/cart.jibb
488++$ state [count=@ud open=?]
489++$ poke
490+ [%add item=@t]
491+ %toggle
492+
493+++ main (store init update)
494+++ init [count=0 open=%.n]
495+++ update |= [a=poke s=state]
496+ ?- a
497+ [%add item] s(count=(add 1 count.s))
498+ %toggle s(open=(not open.s))
docs/reviews/2026-11-03-milestone-2-probes/variants/p6.outnew file+66
@@ -0,0 +1,66 @@
1+#### /ui/todo-list/jibb todo-full-alias
2+REJECTED: /ui/todo-list.jibb:14:10: nothing fixes the union of ~
3+ [ts "" ~]
4+ ^
5+#### /ui/todo-list/jibb todo-full-ambiguous-mapper
6+REJECTED: /ui/todo-list.jibb:14:10: nothing fixes the union of ~
7+ [ts "" ~]
8+ ^
9+#### /ui/index/jibb page-main-page-alias
10+REJECTED: module kind needs unsupported inference: /ui/index/jibb
11+#### /ui/index/jibb page-main-indirect-load
12+REJECTED: module kind needs unsupported inference: /ui/index/jibb
13+#### /ui/index/jibb page-main-pure-load
14+REJECTED: /ui/index.jibb:5:20: nothing fixes the union of ~
15+++ load |=(~ (pure ~))
16+ ^
17+#### /ui/index/jibb page-main-hand-built-load
18+REJECTED: module source does not parse: /ui/index/jibb
19+#### /ui/index/jibb page-main-typed-load
20+REJECTED: module definitions need unsupported inference: /ui/index/jibb: ++ load
21+#### /ui/index/jibb page-main-diff-load
22+REJECTED: module kind needs unsupported inference: /ui/index/jibb
23+#### /ui/stores/cart/jibb store-alias-main
24+REJECTED: module kind needs unsupported inference: /ui/stores/cart/jibb
25+#### /ui/stores/cart/jibb store-hand-main
26+REJECTED: module kind needs unsupported inference: /ui/stores/cart/jibb
27+#### /ui/todo-list/jibb castinit-second-watch
28+REJECTED: module definitions need unsupported inference: /ui/todo-list/jibb: ++ subs
29+#### /ui/todo-list/jibb castinit-subs-none
30+REJECTED: /ui/todo-list.jibb:27:14: nothing fixes the union of ~
31+++ subs |=(m ~)
32+ ^
33+#### /ui/todo-list/jibb castinit-subs-none-typed
34+CHECKED
35++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
36++$ msg: msg
37+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
38+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
39+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
40+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
41+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
42+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
43+#### /ui/todo-list/jibb castinit-inline-row
44+REJECTED: module definitions need unsupported inference: /ui/todo-list/jibb: ++ view
45+#### /ui/todo-list/jibb castinit-update-helper
46+REJECTED: /ui/todo-list.jibb:40:32: nothing fixes the union of %toggled
47+ [id.t (toggle done.t text.t [%toggled id.t])]
48+ ^
49+#### /ui/todo-list/jibb castinit-second-sub-every
50+REJECTED: module kind needs unsupported inference: /ui/todo-list/jibb
51+#### /ui/todo-list/jibb castinit-every-only
52+REJECTED: module kind needs unsupported inference: /ui/todo-list/jibb
53+#### /ui/stores/cart/jibb cart-init-uncast-tuple
54+REJECTED: /ui/stores/cart.jibb:8:10: nothing fixes the union of ~
55+++ init [~ %.n]
56+ ^
57+#### /ui/stores/cart/jibb cart-init-uncast-nonull
58+CHECKED
59++$ state: [count=@ud open=?]
60++$ poke: poke
61+++ state: $-($-([count=@ud open=?] A) (ask A))
62+++ poke: $-([poke $-((unit @t) A)] (cmd A))
63+++ main: [init=[count=@ud open=?] update=*]
64+++ update: $-([a=poke s=[count=@ud open=?]] [count=@ud open=?])
65+++ init: [count=@ud open=?]
66+
docs/reviews/2026-11-03-milestone-2-probes/variants/p7.jibbnew file+389
@@ -0,0 +1,389 @@
1+#### /ui/todo-list/jibb castinit-two-each
2+/= todo /ui/api/todo
3+
4+++ main (program init update view subs)
5+
6++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
7++$ msg
8+ [%typed text=@t]
9+ %submit
10+ [%toggled id=@ud]
11+ [%got todos=(list item.todo)]
12+ [%acked err=(unit @t)]
13+
14+++ init |= ts=(list item.todo)
15+ ^- model [ts "" ~]
16+
17+++ update |= [=msg m=model]
18+ ?- msg
19+ [%typed t]
20+ ?- (gth (lent (tuba (trip t))) 80)
21+ %.y [m(draft=t error=`"Too long") ~]
22+ %.n [m(draft=t error=~) ~]
23+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
24+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
25+ [%got ts] [m(todos=ts) ~]
26+ [%acked err] [m(error=err) ~]
27+
28+++ subs |= m=model
29+ ~[[%watch (todos.todo |=%got)]]
30+
31+++ view |= m=model
32+ column ~[gap+%s2] ~[
33+ heading 2 "Todos"
34+ each (turn todos.m row-of)
35+ each (turn todos.m row-of)
36+ row ~[gap+%s1] ~[
37+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
38+ button "Add" %submit
39+ el ~[tone+%danger] (text (fall error.m ""))
40+
41+++ row-of |= t=item.todo
42+ [id.t (toggle done.t text.t [%toggled id.t])]
43+#### /ui/todo-list/jibb two-each-orig-init
44+/= todo /ui/api/todo
45+
46+++ main (program init update view subs)
47+
48++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
49++$ msg
50+ [%typed text=@t]
51+ %submit
52+ [%toggled id=@ud]
53+ [%got todos=(list item.todo)]
54+ [%acked err=(unit @t)]
55+
56+++ init |= ts=(list item.todo)
57+ [todos=ts draft="" error=~]
58+
59+++ update |= [=msg m=model]
60+ ?- msg
61+ [%typed t]
62+ ?- (gth (lent (tuba (trip t))) 80)
63+ %.y [m(draft=t error=`"Too long") ~]
64+ %.n [m(draft=t error=~) ~]
65+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
66+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
67+ [%got ts] [m(todos=ts) ~]
68+ [%acked err] [m(error=err) ~]
69+
70+++ subs |= m=model
71+ ~[[%watch (todos.todo |=%got)]]
72+
73+++ view |= m=model
74+ column ~[gap+%s2] ~[
75+ heading 2 "Todos"
76+ each (turn todos.m row-of)
77+ each (turn todos.m row-of)
78+ row ~[gap+%s1] ~[
79+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
80+ button "Add" %submit
81+ el ~[tone+%danger] (text (fall error.m ""))
82+
83+++ row-of |= t=item.todo
84+ [id.t (toggle done.t text.t [%toggled id.t])]
85+#### /ui/todo-list/jibb update-catch-all
86+/= todo /ui/api/todo
87+
88+++ main (program init update view subs)
89+
90++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
91++$ msg
92+ [%typed text=@t]
93+ %submit
94+ [%toggled id=@ud]
95+ [%got todos=(list item.todo)]
96+ [%acked err=(unit @t)]
97+
98+++ init |= ts=(list item.todo)
99+ [todos=ts draft="" error=~]
100+
101+++ update |= [=msg m=model]
102+ ?- msg
103+ [%typed t]
104+ ?- (gth (lent (tuba (trip t))) 80)
105+ %.y [m(draft=t error=`"Too long") ~]
106+ %.n [m(draft=t error=~) ~]
107+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
108+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
109+ [%got ts] [m(todos=ts) ~]
110+ * [m ~]
111+
112+++ subs |= m=model
113+ ~[[%watch (todos.todo |=%got)]]
114+
115+++ view |= m=model
116+ column ~[gap+%s2] ~[
117+ heading 2 "Todos"
118+ each (turn todos.m row-of)
119+ row ~[gap+%s1] ~[
120+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
121+ button "Add" %submit
122+ el ~[tone+%danger] (text (fall error.m ""))
123+
124+++ row-of |= t=item.todo
125+ [id.t (toggle done.t text.t [%toggled id.t])]
126+#### /ui/todo-list/jibb update-arms-reordered
127+/= todo /ui/api/todo
128+
129+++ main (program init update view subs)
130+
131++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
132++$ msg
133+ [%typed text=@t]
134+ %submit
135+ [%toggled id=@ud]
136+ [%got todos=(list item.todo)]
137+ [%acked err=(unit @t)]
138+
139+++ init |= ts=(list item.todo)
140+ [todos=ts draft="" error=~]
141+
142+++ update |= [=msg m=model]
143+ ?- msg
144+ [%typed t]
145+ ?- (gth (lent (tuba (trip t))) 80)
146+ %.y [m(draft=t error=`"Too long") ~]
147+ %.n [m(draft=t error=~) ~]
148+ [%got ts] [m(todos=ts) ~]
149+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
150+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
151+ [%acked err] [m(error=err) ~]
152+
153+++ subs |= m=model
154+ ~[[%watch (todos.todo |=%got)]]
155+
156+++ view |= m=model
157+ column ~[gap+%s2] ~[
158+ heading 2 "Todos"
159+ each (turn todos.m row-of)
160+ row ~[gap+%s1] ~[
161+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
162+ button "Add" %submit
163+ el ~[tone+%danger] (text (fall error.m ""))
164+
165+++ row-of |= t=item.todo
166+ [id.t (toggle done.t text.t [%toggled id.t])]
167+#### /ui/todo-list/jibb model-extra-field
168+/= todo /ui/api/todo
169+
170+++ main (program init update view subs)
171+
172++$ model [todos=(list item.todo) draft=@t error=(unit @t) count=@ud]
173++$ msg
174+ [%typed text=@t]
175+ %submit
176+ [%toggled id=@ud]
177+ [%got todos=(list item.todo)]
178+ [%acked err=(unit @t)]
179+
180+++ init |= ts=(list item.todo)
181+ [todos=ts draft="" error=~ count=0]
182+
183+++ update |= [=msg m=model]
184+ ?- msg
185+ [%typed t]
186+ ?- (gth (lent (tuba (trip t))) 80)
187+ %.y [m(draft=t error=`"Too long") ~]
188+ %.n [m(draft=t error=~) ~]
189+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
190+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
191+ [%got ts] [m(todos=ts) ~]
192+ [%acked err] [m(error=err) ~]
193+
194+++ subs |= m=model
195+ ~[[%watch (todos.todo |=%got)]]
196+
197+++ view |= m=model
198+ column ~[gap+%s2] ~[
199+ heading 2 "Todos"
200+ each (turn todos.m row-of)
201+ row ~[gap+%s1] ~[
202+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
203+ button "Add" %submit
204+ el ~[tone+%danger] (text (fall error.m ""))
205+
206+++ row-of |= t=item.todo
207+ [id.t (toggle done.t text.t [%toggled id.t])]
208+#### /ui/todo-list/jibb main-open-paren
209+/= todo /ui/api/todo
210+
211+++ main (program init update
212+ view
213+ subs
214+
215++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
216++$ msg
217+ [%typed text=@t]
218+ %submit
219+ [%toggled id=@ud]
220+ [%got todos=(list item.todo)]
221+ [%acked err=(unit @t)]
222+
223+++ init |= ts=(list item.todo)
224+ [todos=ts draft="" error=~]
225+
226+++ update |= [=msg m=model]
227+ ?- msg
228+ [%typed t]
229+ ?- (gth (lent (tuba (trip t))) 80)
230+ %.y [m(draft=t error=`"Too long") ~]
231+ %.n [m(draft=t error=~) ~]
232+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
233+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
234+ [%got ts] [m(todos=ts) ~]
235+ [%acked err] [m(error=err) ~]
236+
237+++ subs |= m=model
238+ ~[[%watch (todos.todo |=%got)]]
239+
240+++ view |= m=model
241+ column ~[gap+%s2] ~[
242+ heading 2 "Todos"
243+ each (turn todos.m row-of)
244+ row ~[gap+%s1] ~[
245+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
246+ button "Add" %submit
247+ el ~[tone+%danger] (text (fall error.m ""))
248+
249+++ row-of |= t=item.todo
250+ [id.t (toggle done.t text.t [%toggled id.t])]
251+#### /ui/index/jibb index-two-islands
252+/= todo /ui/api/todo
253+/= todo-list /ui/todo-list
254+
255+++ main (page load view)
256+++ load |=(~ (todos.todo same))
257+
258+++ view |= ts=(list item.todo)
259+ column ~[pad+%s3] ~[
260+ heading 1 "My ship"
261+ island main.todo-list ts
262+ island main.todo-list ts
263+#### /ui/index/jibb index-island-flop
264+/= todo /ui/api/todo
265+/= todo-list /ui/todo-list
266+
267+++ main (page load view)
268+++ load |=(~ (todos.todo same))
269+
270+++ view |= ts=(list item.todo)
271+ column ~[pad+%s3] ~[
272+ heading 1 "My ship"
273+ island main.todo-list (flop ts)
274+#### /ui/index/jibb index-hand-built-tall
275+/= todo /ui/api/todo
276+/= todo-list /ui/todo-list
277+
278+++ main (page load view)
279+++ load |= ~
280+ ^- (ask (list item.todo))
281+ [%pure ~]
282+
283+++ view |= ts=(list item.todo)
284+ column ~[pad+%s3] ~[
285+ heading 1 "My ship"
286+ island main.todo-list ts
287+#### /ui/basket/jibb basket-unused-size
288+:: /ui/basket.jibb
289+/= cart /ui/stores/cart
290+
291+++ main (program init update view subs)
292+
293++$ model [cart=state.cart note=@t]
294++$ msg
295+ [%noted text=@t]
296+ %add
297+ %toggle
298+ [%got cart=state.cart]
299+ [%acked err=(unit @t)]
300+
301+++ init |= ~
302+ [cart=[items=~ open=%.n] note=""]
303+
304+++ update |= [=msg m=model]
305+ ?- msg
306+ [%noted t] [m(note=t) ~]
307+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
308+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
309+ [%got c] [m(cart=c) ~]
310+ [%acked err] [m ~]
311+
312+++ subs |= m=model
313+ ~[[%watch (state.cart |=%got)]]
314+
315+++ view |= m=model
316+ column ~[gap+%s1] ~[
317+ (text "{(lent items.cart.m)} items")
318+ field "Item" note.m |=%noted
319+ button "Add" %add
320+
321+++ size |= m=model
322+ (lent items.cart.m)
323+#### /ui/basket/jibb basket-update-helper
324+:: /ui/basket.jibb
325+/= cart /ui/stores/cart
326+
327+++ main (program init update view subs)
328+
329++$ model [cart=state.cart note=@t]
330++$ msg
331+ [%noted text=@t]
332+ %add
333+ %toggle
334+ [%got cart=state.cart]
335+ [%acked err=(unit @t)]
336+
337+++ init |= ~
338+ [cart=[items=~ open=%.n] note=""]
339+
340+++ update |= [=msg m=model]
341+ ?- msg
342+ [%noted t] [m(note=t) ~]
343+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
344+ %toggle [m ~[flip]]
345+ [%got c] [m(cart=c) ~]
346+ [%acked err] [m ~]
347+
348+++ subs |= m=model
349+ ~[[%watch (state.cart |=%got)]]
350+
351+++ view |= m=model
352+ column ~[gap+%s1] ~[
353+ (text "{(lent items.cart.m)} items")
354+ field "Item" note.m |=%noted
355+ button "Add" %add
356+
357+++ flip ^- (cmd msg) (poke.cart %toggle |=%acked)
358+#### /ui/basket/jibb basket-subs-none
359+:: /ui/basket.jibb
360+/= cart /ui/stores/cart
361+
362+++ main (program init update view subs)
363+
364++$ model [cart=state.cart note=@t]
365++$ msg
366+ [%noted text=@t]
367+ %add
368+ %toggle
369+ [%got cart=state.cart]
370+ [%acked err=(unit @t)]
371+
372+++ init |= ~
373+ [cart=[items=~ open=%.n] note=""]
374+
375+++ update |= [=msg m=model]
376+ ?- msg
377+ [%noted t] [m(note=t) ~]
378+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
379+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
380+ [%got c] [m(cart=c) ~]
381+ [%acked err] [m ~]
382+
383+++ subs |=(m ~)
384+
385+++ view |= m=model
386+ column ~[gap+%s1] ~[
387+ (text "{(lent items.cart.m)} items")
388+ field "Item" note.m |=%noted
389+ button "Add" %add
docs/reviews/2026-11-03-milestone-2-probes/variants/p7.outnew file+85
@@ -0,0 +1,85 @@
1+#### /ui/todo-list/jibb castinit-two-each
2+REJECTED: /ui/todo-list.jibb:41:32: nothing fixes the union of %toggled
3+ [id.t (toggle done.t text.t [%toggled id.t])]
4+ ^
5+#### /ui/todo-list/jibb two-each-orig-init
6+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
7+ [todos=ts draft="" error=~]
8+ ^
9+#### /ui/todo-list/jibb update-catch-all
10+CHECKED
11++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
12++$ msg: msg
13+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
14+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
15+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
16+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
17+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
18+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
19+#### /ui/todo-list/jibb update-arms-reordered
20+CHECKED
21++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
22++$ msg: msg
23+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
24+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
25+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
26+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
27+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
28+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
29+#### /ui/todo-list/jibb model-extra-field
30+CHECKED
31++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]]
32++$ msg: msg
33+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]] (list (sub msg)))]]]
34+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]])
35+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]] (element msg))
36+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
37+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]] (list (sub msg)))
38+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t [error=(unit @t) count=@ud]]] (list (cmd msg))])
39+#### /ui/todo-list/jibb main-open-paren
40+CHECKED
41++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
42++$ msg: msg
43+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
44+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
45+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
46+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
47+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
48+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
49+#### /ui/index/jibb index-two-islands
50+CHECKED
51+++ main: [load=$-(~ (ask (list [id=@ud [done=? text=@t]]))) view=$-((list [id=@ud [done=? text=@t]]) (element !!))]
52+++ view: $-((list [id=@ud [done=? text=@t]]) (element !!))
53+++ load: $-(~ (ask (list [id=@ud [done=? text=@t]])))
54+#### /ui/index/jibb index-island-flop
55+CHECKED
56+++ main: [load=$-(~ (ask (list [id=@ud [done=? text=@t]]))) view=$-((list [id=@ud [done=? text=@t]]) (element !!))]
57+++ view: $-((list [id=@ud [done=? text=@t]]) (element !!))
58+++ load: $-(~ (ask (list [id=@ud [done=? text=@t]])))
59+#### /ui/index/jibb index-hand-built-tall
60+REJECTED: module source does not parse: /ui/index/jibb
61+#### /ui/basket/jibb basket-unused-size
62+CHECKED
63++$ model: [cart=[items=(list @t) open=?] note=@t]
64++$ msg: msg
65+++ main: [init=$-(~ [cart=[items=(list @t) open=?] note=@t]) [update=$-([msg [cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))]) [view=$-([cart=[items=(list @t) open=?] note=@t] (element msg)) subs=$-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))]]]
66+++ init: $-(~ [cart=[items=(list @t) open=?] note=@t])
67+++ view: $-([cart=[items=(list @t) open=?] note=@t] (element msg))
68+++ subs: $-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))
69+++ update: $-([msg=msg m=[cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))])
70+++ size: $-([cart=[items=(list @t) open=?] note=@t] @ud)
71+#### /ui/basket/jibb basket-update-helper
72+CHECKED
73++$ model: [cart=[items=(list @t) open=?] note=@t]
74++$ msg: msg
75+++ main: [init=$-(~ [cart=[items=(list @t) open=?] note=@t]) [update=$-([msg [cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))]) [view=$-([cart=[items=(list @t) open=?] note=@t] (element msg)) subs=$-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))]]]
76+++ init: $-(~ [cart=[items=(list @t) open=?] note=@t])
77+++ view: $-([cart=[items=(list @t) open=?] note=@t] (element msg))
78+++ subs: $-([cart=[items=(list @t) open=?] note=@t] (list (sub msg)))
79+++ update: $-([msg=msg m=[cart=[items=(list @t) open=?] note=@t]] [[cart=[items=(list @t) open=?] note=@t] (list (cmd msg))])
80+++ flip: (cmd msg)
81+#### /ui/basket/jibb basket-subs-none
82+REJECTED: /ui/basket.jibb:15:16: nothing fixes the union of ~
83+ [cart=[items=~ open=%.n] note=""]
84+ ^
85+
docs/reviews/2026-11-03-milestone-2-probes/variants/p8.jibbnew file+342
@@ -0,0 +1,342 @@
1+#### /ui/todo-list/jibb todo-full-wrong-model
2+/= todo /ui/api/todo
3+
4+++ main (program init update view subs)
5+
6++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
7++$ msg
8+ [%typed text=@t]
9+ %submit
10+ [%toggled id=@ud]
11+ [%got todos=(list item.todo)]
12+ [%acked err=(unit @t)]
13+
14+++ init |= ts=(list item.todo)
15+ [ts "" ~]
16+
17+++ update |= [=msg m=model]
18+ ?- msg
19+ [%typed t]
20+ ?- (gth (lent (tuba (trip t))) 80)
21+ %.y [m(draft=t error=`"Too long") ~]
22+ %.n [m(draft=t error=~) ~]
23+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
24+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
25+ [%got ts] [m(todos=ts) ~]
26+ [%acked err] [m(error=err) ~]
27+
28+++ subs |= m=[count=@ud]
29+ ~[[%watch (todos.todo |=%got)]]
30+
31+++ view |= m=model
32+ column ~[gap+%s2] ~[
33+ heading 2 "Todos"
34+ each (turn todos.m row-of)
35+ row ~[gap+%s1] ~[
36+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
37+ button "Add" %submit
38+ el ~[tone+%danger] (text (fall error.m ""))
39+
40+++ row-of |= t=item.todo
41+ [id.t (toggle done.t text.t [%toggled id.t])]
42+#### /ui/todo-list/jibb todo-full-wrong-message
43+/= todo /ui/api/todo
44+
45+++ main (program init update view subs)
46+
47++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
48++$ msg
49+ [%typed text=@t]
50+ %submit
51+ [%toggled id=@ud]
52+ [%got todos=(list item.todo)]
53+ [%acked err=(unit @t)]
54+
55+++ init |= ts=(list item.todo)
56+ [ts "" ~]
57+
58+++ update |= [=msg m=model]
59+ ?- msg
60+ [%typed t]
61+ ?- (gth (lent (tuba (trip t))) 80)
62+ %.y [m(draft=t error=`"Too long") ~]
63+ %.n [m(draft=t error=~) ~]
64+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
65+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
66+ [%got ts] [m(todos=ts) ~]
67+ [%acked err] [m(error=err) ~]
68+
69+++ subs |= m=model
70+ ~[[%watch (todos.todo |=%got)]]
71+
72+++ view |= m=model
73+ column ~[gap+%s2] ~[
74+ heading 2 "Todos"
75+ each (turn todos.m row-of)
76+ row ~[gap+%s1] ~[
77+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
78+ button "Add" %submit
79+ el ~[tone+%danger] (text (fall error.m ""))
80+
81+++ row-of |= t=item.todo
82+ [id.t (toggle done.t text.t [%other])]
83+#### /ui/todo-list/jibb todo-full-wrong-result
84+/= todo /ui/api/todo
85+
86+++ main (program init update view subs)
87+
88++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
89++$ msg
90+ [%typed text=@t]
91+ %submit
92+ [%toggled id=@ud]
93+ [%got todos=(list item.todo)]
94+ [%acked err=(unit @t)]
95+
96+++ init |= ts=(list item.todo)
97+ [ts "" ~]
98+
99+++ update |= [=msg m=model]
100+ ?- msg
101+ [%typed t]
102+ ?- (gth (lent (tuba (trip t))) 80)
103+ %.y [m(draft=t error=`"Too long") ~]
104+ %.n [m(draft=t error=~) ~]
105+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
106+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
107+ [%got ts] [m(todos=ts) ~]
108+ [%acked err] [m(error=err) ~]
109+
110+++ subs |= m=model
111+ ~[[%watch (todos.todo |=%got)]]
112+
113+++ view |= m=model
114+ column ~[gap+%s2] ~[
115+ heading 2 "Todos"
116+ each (turn todos.m row-of)
117+ row ~[gap+%s1] ~[
118+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
119+ button "Add" %submit
120+ el ~[tone+%danger] (text (fall error.m ""))
121+
122+++ row-of |= t=item.todo
123+ text.t
124+#### /ui/todo-list/jibb todo-full-open-key
125+/= todo /ui/api/todo
126+
127+++ main (program init update view subs)
128+
129++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
130++$ msg
131+ [%typed text=@t]
132+ %submit
133+ [%toggled id=@ud]
134+ [%got todos=(list item.todo)]
135+ [%acked err=(unit @t)]
136+
137+++ init |= ts=(list item.todo)
138+ [ts "" ~]
139+
140+++ update |= [=msg m=model]
141+ ?- msg
142+ [%typed t]
143+ ?- (gth (lent (tuba (trip t))) 80)
144+ %.y [m(draft=t error=`"Too long") ~]
145+ %.n [m(draft=t error=~) ~]
146+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
147+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
148+ [%got ts] [m(todos=ts) ~]
149+ [%acked err] [m(error=err) ~]
150+
151+++ subs |= m=model
152+ ~[[%watch (todos.todo |=%got)]]
153+
154+++ view |= m=model
155+ column ~[gap+%s2] ~[
156+ heading 2 "Todos"
157+ each (turn todos.m row-of)
158+ row ~[gap+%s1] ~[
159+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
160+ button "Add" %submit
161+ el ~[tone+%danger] (text (fall error.m ""))
162+
163+++ row-of |= t=item.todo
164+ [!! (toggle done.t text.t [%toggled id.t])]
165+#### /ui/todo-list/jibb todo-full-wrong-watch
166+/= todo /ui/api/todo
167+
168+++ main (program init update view subs)
169+
170++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
171++$ msg
172+ [%typed text=@t]
173+ %submit
174+ [%toggled id=@ud]
175+ [%got todos=(list item.todo)]
176+ [%acked err=(unit @t)]
177+
178+++ init |= ts=(list item.todo)
179+ [ts "" ~]
180+
181+++ update |= [=msg m=model]
182+ ?- msg
183+ [%typed t]
184+ ?- (gth (lent (tuba (trip t))) 80)
185+ %.y [m(draft=t error=`"Too long") ~]
186+ %.n [m(draft=t error=~) ~]
187+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
188+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
189+ [%got ts] [m(todos=ts) ~]
190+ [%acked err] [m(error=err) ~]
191+
192+++ subs |= m=model
193+ ~[[%watch (pure %submit)]]
194+
195+++ view |= m=model
196+ column ~[gap+%s2] ~[
197+ heading 2 "Todos"
198+ each (turn todos.m row-of)
199+ row ~[gap+%s1] ~[
200+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
201+ button "Add" %submit
202+ el ~[tone+%danger] (text (fall error.m ""))
203+
204+++ row-of |= t=item.todo
205+ [id.t (toggle done.t text.t [%toggled id.t])]
206+#### /ui/todo-list/jibb todo-full-non-gate-view
207+/= todo /ui/api/todo
208+
209+++ main (program init update view subs)
210+
211++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
212++$ msg
213+ [%typed text=@t]
214+ %submit
215+ [%toggled id=@ud]
216+ [%got todos=(list item.todo)]
217+ [%acked err=(unit @t)]
218+
219+++ init |= ts=(list item.todo)
220+ [ts "" ~]
221+
222+++ update |= [=msg m=model]
223+ ?- msg
224+ [%typed t]
225+ ?- (gth (lent (tuba (trip t))) 80)
226+ %.y [m(draft=t error=`"Too long") ~]
227+ %.n [m(draft=t error=~) ~]
228+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
229+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
230+ [%got ts] [m(todos=ts) ~]
231+ [%acked err] [m(error=err) ~]
232+
233+++ subs |= m=model
234+ ~[[%watch (todos.todo |=%got)]]
235+
236+++ view init
237+
238+++ row-of |= t=item.todo
239+ [id.t (toggle done.t text.t [%toggled id.t])]
240+#### /ui/todo-list/jibb todo-full-cast-init
241+/= todo /ui/api/todo
242+
243+++ main (program init update view subs)
244+
245++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
246++$ msg
247+ [%typed text=@t]
248+ %submit
249+ [%toggled id=@ud]
250+ [%got todos=(list item.todo)]
251+ [%acked err=(unit @t)]
252+
253+++ make-model |= ts=(list item.todo)
254+ ^- model [ts "" ~]
255+
256+++ init ^- $-((list item.todo) model)
257+ |= ts=(list item.todo) (make-model ts)
258+
259+++ update |= [=msg m=model]
260+ ?- msg
261+ [%typed t]
262+ ?- (gth (lent (tuba (trip t))) 80)
263+ %.y [m(draft=t error=`"Too long") ~]
264+ %.n [m(draft=t error=~) ~]
265+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
266+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
267+ [%got ts] [m(todos=ts) ~]
268+ [%acked err] [m(error=err) ~]
269+
270+++ subs |= m=model
271+ ~[[%watch (todos.todo |=%got)]]
272+
273+++ view |= m=model
274+ column ~[gap+%s2] ~[
275+ heading 2 "Todos"
276+ each (turn todos.m row-of)
277+ row ~[gap+%s1] ~[
278+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
279+ button "Add" %submit
280+ el ~[tone+%danger] (text (fall error.m ""))
281+
282+++ row-of |= t=item.todo
283+ [id.t (toggle done.t text.t [%toggled id.t])]
284+#### /ui/theme/jibb theme-dark-absent
285+++ theme ^- theme
286+ [ space=[s1="4px" s2="8px" s3="16px"]
287+ tones=[normal="#222" background="#fff" accent="#17734f" danger="#b3261e" muted="#5f5f5f"]
288+ wide="60rem"
289+ lang="en"
290+ zone="UTC"
291+ font=`%/static/fonts/inter.woff2
292+ dark=~
293+#### /ui/theme/jibb theme-wrong-nested-aura
294+++ theme ^- theme
295+ [ space=[s1="4px" s2="8px" s3="16px"]
296+ tones=[normal=~zod background="#fff" accent="#17734f" danger="#b3261e" muted="#5f5f5f"]
297+ wide="60rem"
298+ lang="en"
299+ zone="UTC"
300+ font=`%/static/fonts/inter.woff2
301+ dark=[tones=[normal="#eee" background="#111" accent="#4c9" danger="#f28b82" muted="#aaa"]]
302+#### /ui/theme/jibb theme-missing-field
303+++ theme ^- theme
304+ [ space=[s1="4px" s2="8px" s3="16px"]
305+ tones=[normal="#222" background="#fff" accent="#17734f" danger="#b3261e" muted="#5f5f5f"]
306+ wide="60rem"
307+ lang="en"
308+ font=`%/static/fonts/inter.woff2
309+ dark=[tones=[normal="#eee" background="#111" accent="#4c9" danger="#f28b82" muted="#aaa"]]
310+#### /ui/theme/jibb theme-wrong-font
311+++ theme ^- theme
312+ [ space=[s1="4px" s2="8px" s3="16px"]
313+ tones=[normal="#222" background="#fff" accent="#17734f" danger="#b3261e" muted="#5f5f5f"]
314+ wide="60rem"
315+ lang="en"
316+ zone="UTC"
317+ font=`"/static/fonts/inter.woff2"
318+ dark=[tones=[normal="#eee" background="#111" accent="#4c9" danger="#f28b82" muted="#aaa"]]
319+#### /ui/theme/jibb theme-wrong-dark
320+++ theme ^- theme
321+ [ space=[s1="4px" s2="8px" s3="16px"]
322+ tones=[normal="#222" background="#fff" accent="#17734f" danger="#b3261e" muted="#5f5f5f"]
323+ wide="60rem"
324+ lang="en"
325+ zone="UTC"
326+ font=`%/static/fonts/inter.woff2
327+ dark="dark"
328+#### /ui/index/jibb page-main-wrong-static
329+++ main (button "Go" %go)
330+#### /ui/index/jibb page-main-arbitrary-main
331+++ main 42
332+#### /tests/page-main/ctor/jibb page-main-ctor-page
333+/= todo /ui/api/todo
334+
335++$ msg
336+ [%got todos=(list item.todo)]
337+++ main (page load view)
338+++ load |= ~
339+ ^- (ask msg) (todos.todo |=%got)
340+
341+++ view |= m=msg
342+ text "Todos loaded"
docs/reviews/2026-11-03-milestone-2-probes/variants/p8.outnew file+57
@@ -0,0 +1,57 @@
1+#### /ui/todo-list/jibb todo-full-wrong-model
2+REJECTED: /ui/todo-list.jibb:14:10: nothing fixes the union of ~
3+ [ts "" ~]
4+ ^
5+#### /ui/todo-list/jibb todo-full-wrong-message
6+REJECTED: /ui/todo-list.jibb:14:10: nothing fixes the union of ~
7+ [ts "" ~]
8+ ^
9+#### /ui/todo-list/jibb todo-full-wrong-result
10+REJECTED: /ui/todo-list.jibb:14:10: nothing fixes the union of ~
11+ [ts "" ~]
12+ ^
13+#### /ui/todo-list/jibb todo-full-open-key
14+REJECTED: /ui/todo-list.jibb:14:10: nothing fixes the union of ~
15+ [ts "" ~]
16+ ^
17+#### /ui/todo-list/jibb todo-full-wrong-watch
18+REJECTED: module kind needs unsupported inference: /ui/todo-list/jibb
19+#### /ui/todo-list/jibb todo-full-non-gate-view
20+REJECTED: /ui/todo-list.jibb:14:10: nothing fixes the union of ~
21+ [ts "" ~]
22+ ^
23+#### /ui/todo-list/jibb todo-full-cast-init
24+CHECKED
25++$ model: [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]
26++$ msg: msg
27+++ main: [init=$-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]) [update=$-([msg [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))]) [view=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg)) subs=$-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))]]]
28+++ view: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (element msg))
29+++ row-of: $-([id=@ud [done=? text=@t]] [key=@ud el=(element msg)])
30+++ subs: $-([todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (sub msg)))
31+++ update: $-([msg=msg m=[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]]] [[todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]] (list (cmd msg))])
32+++ init: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
33+++ make-model: $-((list [id=@ud [done=? text=@t]]) [todos=(list [id=@ud [done=? text=@t]]) [draft=@t error=(unit @t)]])
34+#### /ui/theme/jibb theme-dark-absent
35+CHECKED
36+++ theme: [space=[s1=@t [s2=@t s3=@t]] [tones=[normal=@t [background=@t [accent=@t [danger=@t muted=@t]]]] [wide=@t [lang=@t [zone=@t [font=(unit qath) dark=(unit [tones=[normal=@t [background=@t [accent=@t [danger=@t muted=@t]]]]])]]]]]]
37+#### /ui/theme/jibb theme-wrong-nested-aura
38+REJECTED: module definitions need unsupported inference: /ui/theme/jibb: ++ theme
39+#### /ui/theme/jibb theme-missing-field
40+REJECTED: module definitions need unsupported inference: /ui/theme/jibb: ++ theme
41+#### /ui/theme/jibb theme-wrong-font
42+REJECTED: module definitions need unsupported inference: /ui/theme/jibb: ++ theme
43+#### /ui/theme/jibb theme-wrong-dark
44+REJECTED: module definitions need unsupported inference: /ui/theme/jibb: ++ theme
45+#### /ui/index/jibb page-main-wrong-static
46+REJECTED: /ui/index.jibb:1:22: nothing fixes the union of %go
47+++ main (button "Go" %go)
48+ ^
49+#### /ui/index/jibb page-main-arbitrary-main
50+REJECTED: module kind needs unsupported inference: /ui/index/jibb
51+#### /tests/page-main/ctor/jibb page-main-ctor-page
52+CHECKED
53++$ msg: [%got todos=(list [id=@ud [done=? text=@t]])]
54+++ main: [load=$-(~ (ask [%got todos=(list [id=@ud [done=? text=@t]])])) view=$-([%got todos=(list [id=@ud [done=? text=@t]])] (element !!))]
55+++ view: $-([%got todos=(list [id=@ud [done=? text=@t]])] (element A))
56+++ load: $-(~ (ask [%got todos=(list [id=@ud [done=? text=@t]])]))
57+
docs/reviews/2026-11-03-milestone-2-probes/variants/p9.jibbnew file+311
@@ -0,0 +1,311 @@
1+#### /ui/todo-list/jibb typo-submitt-view
2+/= todo /ui/api/todo
3+
4+++ main (program init update view subs)
5+
6++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
7++$ msg
8+ [%typed text=@t]
9+ %submit
10+ [%toggled id=@ud]
11+ [%got todos=(list item.todo)]
12+ [%acked err=(unit @t)]
13+
14+++ init |= ts=(list item.todo)
15+ [todos=ts draft="" error=~]
16+
17+++ update |= [=msg m=model]
18+ ?- msg
19+ [%typed t]
20+ ?- (gth (lent (tuba (trip t))) 80)
21+ %.y [m(draft=t error=`"Too long") ~]
22+ %.n [m(draft=t error=~) ~]
23+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
24+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
25+ [%got ts] [m(todos=ts) ~]
26+ [%acked err] [m(error=err) ~]
27+
28+++ subs |= m=model
29+ ~[[%watch (todos.todo |=%got)]]
30+
31+++ view |= m=model
32+ column ~[gap+%s2] ~[
33+ heading 2 "Todos"
34+ each (turn todos.m row-of)
35+ row ~[gap+%s1] ~[
36+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
37+ button "Add" %submitt
38+ el ~[tone+%danger] (text (fall error.m ""))
39+
40+++ row-of |= t=item.todo
41+ [id.t (toggle done.t text.t [%toggled id.t])]
42+#### /ui/todo-list/jibb typo-typd-ctor
43+/= todo /ui/api/todo
44+
45+++ main (program init update view subs)
46+
47++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
48++$ msg
49+ [%typed text=@t]
50+ %submit
51+ [%toggled id=@ud]
52+ [%got todos=(list item.todo)]
53+ [%acked err=(unit @t)]
54+
55+++ init |= ts=(list item.todo)
56+ [todos=ts draft="" error=~]
57+
58+++ update |= [=msg m=model]
59+ ?- msg
60+ [%typed t]
61+ ?- (gth (lent (tuba (trip t))) 80)
62+ %.y [m(draft=t error=`"Too long") ~]
63+ %.n [m(draft=t error=~) ~]
64+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
65+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
66+ [%got ts] [m(todos=ts) ~]
67+ [%acked err] [m(error=err) ~]
68+
69+++ subs |= m=model
70+ ~[[%watch (todos.todo |=%got)]]
71+
72+++ view |= m=model
73+ column ~[gap+%s2] ~[
74+ heading 2 "Todos"
75+ each (turn todos.m row-of)
76+ row ~[gap+%s1] ~[
77+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typd)
78+ button "Add" %submit
79+ el ~[tone+%danger] (text (fall error.m ""))
80+
81+++ row-of |= t=item.todo
82+ [id.t (toggle done.t text.t [%toggled id.t])]
83+#### /ui/todo-list/jibb typo-in-update-pattern
84+/= todo /ui/api/todo
85+
86+++ main (program init update view subs)
87+
88++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
89++$ msg
90+ [%typed text=@t]
91+ %submit
92+ [%toggled id=@ud]
93+ [%got todos=(list item.todo)]
94+ [%acked err=(unit @t)]
95+
96+++ init |= ts=(list item.todo)
97+ [todos=ts draft="" error=~]
98+
99+++ update |= [=msg m=model]
100+ ?- msg
101+ [%typed t]
102+ ?- (gth (lent (tuba (trip t))) 80)
103+ %.y [m(draft=t error=`"Too long") ~]
104+ %.n [m(draft=t error=~) ~]
105+ %submitt [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
106+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
107+ [%got ts] [m(todos=ts) ~]
108+ [%acked err] [m(error=err) ~]
109+
110+++ subs |= m=model
111+ ~[[%watch (todos.todo |=%got)]]
112+
113+++ view |= m=model
114+ column ~[gap+%s2] ~[
115+ heading 2 "Todos"
116+ each (turn todos.m row-of)
117+ row ~[gap+%s1] ~[
118+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
119+ button "Add" %submit
120+ el ~[tone+%danger] (text (fall error.m ""))
121+
122+++ row-of |= t=item.todo
123+ [id.t (toggle done.t text.t [%toggled id.t])]
124+#### /ui/todo-list/jibb missing-case-in-update
125+/= todo /ui/api/todo
126+
127+++ main (program init update view subs)
128+
129++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
130++$ msg
131+ [%typed text=@t]
132+ %submit
133+ [%toggled id=@ud]
134+ [%got todos=(list item.todo)]
135+ [%acked err=(unit @t)]
136+
137+++ init |= ts=(list item.todo)
138+ [todos=ts draft="" error=~]
139+
140+++ update |= [=msg m=model]
141+ ?- msg
142+ [%typed t]
143+ ?- (gth (lent (tuba (trip t))) 80)
144+ %.y [m(draft=t error=`"Too long") ~]
145+ %.n [m(draft=t error=~) ~]
146+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
147+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
148+ [%got ts] [m(todos=ts) ~]
149+
150+++ subs |= m=model
151+ ~[[%watch (todos.todo |=%got)]]
152+
153+++ view |= m=model
154+ column ~[gap+%s2] ~[
155+ heading 2 "Todos"
156+ each (turn todos.m row-of)
157+ row ~[gap+%s1] ~[
158+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
159+ button "Add" %submit
160+ el ~[tone+%danger] (text (fall error.m ""))
161+
162+++ row-of |= t=item.todo
163+ [id.t (toggle done.t text.t [%toggled id.t])]
164+#### /ui/todo-list/jibb aura-mismatch-update
165+/= todo /ui/api/todo
166+
167+++ main (program init update view subs)
168+
169++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
170++$ msg
171+ [%typed text=@t]
172+ %submit
173+ [%toggled id=@ud]
174+ [%got todos=(list item.todo)]
175+ [%acked err=(unit @t)]
176+
177+++ init |= ts=(list item.todo)
178+ [todos=ts draft="" error=~]
179+
180+++ update |= [=msg m=model]
181+ ?- msg
182+ [%typed t]
183+ ?- (gth (lent (tuba (trip t))) 80)
184+ %.y [m(draft=t error=`"Too long") ~]
185+ %.n [m(draft=~zod error=~) ~]
186+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
187+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
188+ [%got ts] [m(todos=ts) ~]
189+ [%acked err] [m(error=err) ~]
190+
191+++ subs |= m=model
192+ ~[[%watch (todos.todo |=%got)]]
193+
194+++ view |= m=model
195+ column ~[gap+%s2] ~[
196+ heading 2 "Todos"
197+ each (turn todos.m row-of)
198+ row ~[gap+%s1] ~[
199+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
200+ button "Add" %submit
201+ el ~[tone+%danger] (text (fall error.m ""))
202+
203+++ row-of |= t=item.todo
204+ [id.t (toggle done.t text.t [%toggled id.t])]
205+#### /ui/todo-list/jibb dead-arm-update
206+/= todo /ui/api/todo
207+
208+++ main (program init update view subs)
209+
210++$ model [todos=(list item.todo) draft=@t error=(unit @t)]
211++$ msg
212+ [%typed text=@t]
213+ %submit
214+ [%toggled id=@ud]
215+ [%got todos=(list item.todo)]
216+ [%acked err=(unit @t)]
217+
218+++ init |= ts=(list item.todo)
219+ [todos=ts draft="" error=~]
220+
221+++ update |= [=msg m=model]
222+ ?- msg
223+ [%typed t]
224+ ?- (gth (lent (tuba (trip t))) 80)
225+ %.y [m(draft=t error=`"Too long") ~]
226+ %.n [m(draft=t error=~) ~]
227+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
228+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
229+ [%got ts] [m(todos=ts) ~]
230+ [%acked err] [m(error=err) ~]
231+ %submit [m ~]
232+
233+++ subs |= m=model
234+ ~[[%watch (todos.todo |=%got)]]
235+
236+++ view |= m=model
237+ column ~[gap+%s2] ~[
238+ heading 2 "Todos"
239+ each (turn todos.m row-of)
240+ row ~[gap+%s1] ~[
241+ el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
242+ button "Add" %submit
243+ el ~[tone+%danger] (text (fall error.m ""))
244+
245+++ row-of |= t=item.todo
246+ [id.t (toggle done.t text.t [%toggled id.t])]
247+#### /ui/basket/jibb basket-typo-addd
248+:: /ui/basket.jibb
249+/= cart /ui/stores/cart
250+
251+++ main (program init update view subs)
252+
253++$ model [cart=state.cart note=@t]
254++$ msg
255+ [%noted text=@t]
256+ %add
257+ %toggle
258+ [%got cart=state.cart]
259+ [%acked err=(unit @t)]
260+
261+++ init |= ~
262+ [cart=[items=~ open=%.n] note=""]
263+
264+++ update |= [=msg m=model]
265+ ?- msg
266+ [%noted t] [m(note=t) ~]
267+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
268+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
269+ [%got c] [m(cart=c) ~]
270+ [%acked err] [m ~]
271+
272+++ subs |= m=model
273+ ~[[%watch (state.cart |=%got)]]
274+
275+++ view |= m=model
276+ column ~[gap+%s1] ~[
277+ (text "{(lent items.cart.m)} items")
278+ field "Item" note.m |=%noted
279+ button "Add" %addd
280+#### /ui/basket/jibb basket-missing-case
281+:: /ui/basket.jibb
282+/= cart /ui/stores/cart
283+
284+++ main (program init update view subs)
285+
286++$ model [cart=state.cart note=@t]
287++$ msg
288+ [%noted text=@t]
289+ %add
290+ %toggle
291+ [%got cart=state.cart]
292+ [%acked err=(unit @t)]
293+
294+++ init |= ~
295+ [cart=[items=~ open=%.n] note=""]
296+
297+++ update |= [=msg m=model]
298+ ?- msg
299+ [%noted t] [m(note=t) ~]
300+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
301+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
302+ [%got c] [m(cart=c) ~]
303+
304+++ subs |= m=model
305+ ~[[%watch (state.cart |=%got)]]
306+
307+++ view |= m=model
308+ column ~[gap+%s1] ~[
309+ (text "{(lent items.cart.m)} items")
310+ field "Item" note.m |=%noted
311+ button "Add" %add
docs/reviews/2026-11-03-milestone-2-probes/variants/p9.outnew file+33
@@ -0,0 +1,33 @@
1+#### /ui/todo-list/jibb typo-submitt-view
2+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
3+ [todos=ts draft="" error=~]
4+ ^
5+#### /ui/todo-list/jibb typo-typd-ctor
6+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
7+ [todos=ts draft="" error=~]
8+ ^
9+#### /ui/todo-list/jibb typo-in-update-pattern
10+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
11+ [todos=ts draft="" error=~]
12+ ^
13+#### /ui/todo-list/jibb missing-case-in-update
14+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
15+ [todos=ts draft="" error=~]
16+ ^
17+#### /ui/todo-list/jibb aura-mismatch-update
18+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
19+ [todos=ts draft="" error=~]
20+ ^
21+#### /ui/todo-list/jibb dead-arm-update
22+REJECTED: /ui/todo-list.jibb:14:28: nothing fixes the union of ~
23+ [todos=ts draft="" error=~]
24+ ^
25+#### /ui/basket/jibb basket-typo-addd
26+REJECTED: /ui/basket.jibb:15:16: nothing fixes the union of ~
27+ [cart=[items=~ open=%.n] note=""]
28+ ^
29+#### /ui/basket/jibb basket-missing-case
30+REJECTED: /ui/basket.jibb:15:16: nothing fixes the union of ~
31+ [cart=[items=~ open=%.n] note=""]
32+ ^
33+
docs/reviews/2026-11-03-milestone-2-review.mdnew file+115
@@ -0,0 +1,115 @@
1+# Milestone 2 review, 2026-11-03
2+
3+A review of milestone 2, "Types and prelude", at [`f84a29e`](https://github.com/iko-soy/jibb/commit/f84a29e1a0af663afdb77e793c933470b59a249b), asked for in the project chat. It judges the combined result of the milestone's commits, from `1dd92a6` ("Start type inference and Hoon imports", 2026-10-30) to `f84a29e`, about 150 of them, against the plan in [implementation-plan.md](../spec/implementation-plan.md) and the brief in [prompts/milestone-2.md](../prompts/milestone-2.md). It builds on the [repository review of 2026-11-02](2026-11-02-repo-review.md) (findings A1 to A137, at `4bf477e`) and does not repeat what that review settled.
4+
5+**This is a first version.** The review runs in nine areas. Two have finished: whether the doc's examples typecheck (done-criterion 1) and whether every error the spec describes has a test with its message (done-criterion 2). The other seven are still running: the Hoon import table (done-criterion 3), inference soundness, unions and `?-`, modules, APIs and the prelude, what became of the earlier review's findings, tests and docs, and architecture and speed. Their results, and a second reviewer's check of every finding, will be added to this file. The findings below had one reviewer each, who reproduced them with probes; the headline ones (M1, M2, M3 and M9) were reproduced again for this write-up.
6+
7+What is left to build is briefed in [prompts/milestone-2-finish.md](../prompts/milestone-2-finish.md). The probe sources behind the findings, with the checker's output for each, are in [2026-11-03-milestone-2-probes/](2026-11-03-milestone-2-probes/), with a script to rerun them.
8+
9+Line numbers are links into `f84a29e`.
10+
11+## Verdict
12+
13+**Milestone 2 is not done by its own "Done when" list.** Every check passes, the 14 `jibb` blocks of the doc check as written, and nothing wrong that the core probes tried was accepted. But the checker that a build will run, the full module checker, reports almost every error in the spec as "module definitions need unsupported inference: <path>: ++ name", with no line, column or excerpt. And the island, page and store checks are fitted to the examples' exact shapes, so small valid edits are rejected, often with a wrong error. `docs/status.md` still says "In progress", which matches; its rewrite as a capability table (`e97aebe`) landed while this review ran.
14+
15+| Plan item | Status | Evidence |
16+| --- | --- | --- |
17+| Done when: the doc's examples typecheck, except those written as errors | **Met as written, fragile** | All 14 blocks check with exact types (`jibb-doc-examples`, `jibb-todo-full`, `jibb-store`, `jibb-page-main`, `jibb-theme`, `jibb-buttons`), and `add-button` fails with "nothing fixes the union of %add". Of about 90 spec-valid one-edit variants of those modules, about 27 are rejected (M2, M4) |
18+| Done when: each error the Grammar tab describes has a test with its message | **Not met** | Of the 33 errors the spec describes, 4 have a test and get their message from the full checker. 28 don't get their message from the full checker, most of them only the generic "needs unsupported inference"; the partial report, which no build runs, has a message for most of those. One, a repeated attribute, is accepted (M1, M3, the [error table](#appendix-the-errors-the-spec-describes)) |
19+| Done when: a `/sur` file with `$%`, `$@`, maps and a recursive mold imports as the table says | Not yet reviewed | Still running. The earlier review's A50 (only `%tas` head tags, no `each` or `json`) and A14 (bare `@`, `@uw`) were open at `4bf477e` |
20+| Each milestone ends with its checks passing on a fake ship | **Met** | `nix flake check`: 11 of 11 checks pass, the ship group on a fresh fake `~zod` ([Check run](#check-run)) |
21+| Brief: on the ship, the `my-app` desk checked with its Hoon types read through Clay, every module but `buttons.jibb` checking | **Not met** | No check walks `my-app/ui`. The suites compile `/sur` and mark text themselves with `ride`; Clay-built types reach only the partial report (M8) |
22+| Builds: exhaustive `?-` with dead-arm errors | Partly | Flat whole-case unions only; the Grammar's own `[%move * *]` example is "not supported" (M10) |
23+| Builds: the prelude's types | Partly | `max`, which the Grammar's `clamp` example calls, is missing; a repeated attribute is accepted; a hand-built element checks (M9). The full inventory review is still running |
24+| Builds: Hindley–Milner inference, deferred constraints, union disjointness, imports, API files | Still running | Early probe results are under [Early results](#early-results-from-the-areas-still-running) |
25+
26+## Check run
27+
28+`nix flake check` at `f84a29e`, on 4 CPUs, took 471 s and passed every check:
29+
30+| Group | Checks | Result | Time |
31+| --- | --- | --- | --- |
32+| eval | `selftest`, `golden`, `arms-1` to `arms-4`, `doc-blocks` | 7 of 7 pass | 225 s |
33+| ship, on a fake `~zod` booted in the sandbox | `ship-selftest`, `ship-test`, `check-commit`, `clay-fixtures` | 4 of 4 pass | 414 s |
34+
35+The corpus has 691 golden cases, 304 of them with a `types.txt`, and 58 suites in `tests/lib` with 62 test arms. All 304 `types.txt` files are partial reports that begin "partial inference; module not checked".
36+
37+## What works
38+
39+- The 14 doc blocks check with exact, closed types, including the todo island, the cart store and basket, the theme, the three pages and the imports example, and the `cmd`/`sub` block as prelude source.
40+- About 64 of 90 valid edits to those modules still check: reordering and renaming, unused helpers, consistent field swaps, an `init` written as a cast, a sixth message, helpers in `view`, two islands on a page.
41+- Overlapping union cases, a repeated field in a Jibb record, and derived-name clashes get good errors from the full checker, with both sites and excerpts. The unresolved-tag error of the Grammar's buttons example is exact, and moves with the code when the block is reordered.
42+- None of the wrong programs probed in this version was accepted, apart from the two in M9.
43+
44+## Findings so far
45+
46+Severity follows the earlier review's scale: high means unsound, or a done-criterion clearly not met, or a false error on common valid code.
47+
48+| # | Finding | Severity | Evidence | Fix | Prior |
49+| --- | --- | --- | --- | --- | --- |
50+| M1 | **The full checker throws away every per-definition diagnostic.** An aura mismatch, mismatched faces, `msg has no case %submitt`, a missing `?-` case, a covered arm, `++ title (trim title)`, a shadowed local, a cell in `{…}`, a capital made `@ud`, `m()`, `[]`, `(add %.y %.n)`, a gate in `eq`, an unknown name and every invalid Hoon import all give only "module definitions need unsupported inference: /ui/probe/jibb: ++ x". The partial report has a definite message with sites for most of them | High | [`add-supported-result`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L10670-L10689) returns `~` on a failed result and on hole, capital, pending-tag and atom-variable failures, dropping the reason. Only the pending-tag and sample-shadow retries rebuild an error ([14820-14832](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L14820-L14832)); mold and kind failures go the same way ([14856-14857](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L14856-L14857)) | Keep the first definite diagnostic per unresolved definition and render it at 14830, in dependency order; keep the generic text for real checker limits. Same for molds and kinds | A40, A12 still open |
51+| M2 | **Valid one-edit variants of the doc's islands are rejected, mostly with a false error at a correct line.** `++ subs \|=(m ~)`, which the overview gives for "no subscriptions", a second watch, an inline or local mapper, two `each` sites, and an update helper that returns a poke command each give "todo-list.jibb:14:28: nothing fixes the union of ~", pointing at `error=~` in a correct `init`. Any `%every` subscription, and a watch with a fold (`(changes.todo \|=%got apply)`, from the overview), give "module kind needs unsupported inference" | High | `main` is not checked as an application: a fixed chain of program recoveries fits each component, and a definition the chain can't resolve falls to the pending-tag retry, which reports whatever tag is still open ([10711-10735](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L10711-L10735)). The Grammar says such a constraint "stays open until something in the module fixes it. An island's `main` fixes its messages" | The general core of Q5: check `main = (program init update view subs)` as an ordinary application whose unification fixes the components, with module-wide deferred tag constraints. Walk the `(list (sub M))` and ask for a watchability proof only for `%watch` | A121, fix-first 1 in a new form |
52+| M3 | **In an island, every error is reported as "nothing fixes the union of ~" at `init`.** The criterion's own example, `button "Add" %submitt` in the todo view, gives "todo-list.jibb:14:28: nothing fixes the union of ~". So do `\|=%typd`, a pattern typo, a missing `[%acked err]` arm, a second `%submit` arm, an aura mismatch in `update`, and a gate as a row key. Outside an island, the partial report puts the caret under `"Add"`, the wrong argument | High | Probes of the unchanged island with one edit each, reproduced for this write-up. The same in the basket: "basket.jibb:15:16: nothing fixes the union of ~". A gate in the model gives "module kind needs unsupported inference" and names no field, though the overview says "the checker names the field" | Report a pending tag only when the definition otherwise checks in its module context. For a call whose sample fit fails, re-fit each argument and report the first failing one, as "msg has no case `%submitt`" when it is a tag | A121 |
53+| M4 | **Page and store kinds are recognised by syntax**, so the overview's route-parameter page (`(post.api slug same)`), its catch-all page (`(pure p)`), a typed-path load, `(pure ~)`, a page or store alias, and the cart's `init` without its cast are rejected | Medium | [`page-main-parts`, `store-main-parts`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L13200-L13240) match the literal `(page w w)` and `(store w w)`; [`page-load-derived`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L14510-L14538) takes only a gate whose body is one derived request. The Grammar says "`main`'s type decides a module's kind" | Decide the kind from `main`'s inferred type. Check a load as a gate to `(ask D)`, `pure` and typed paths included; pages need no watchability | A121 |
54+| M5 | **An island `init` mismatch is blamed on a correct `~`.** In `[ts ~zod ~]` against `draft=@t`, the error is `~zod`, but the checker says "nothing fixes the union of ~" at the last `~`. `jibb-program-init` locks three such messages | Medium | `tests/type-program-main/initializer-earlier.txt` and two siblings; [`jibb-program-init.hoon:129-131`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/tests/lib/jibb-program-init.hoon#L129-L131) | As M3, then update the three expected strings | |
55+| M6 | **Negative tests lock in rejections of valid programs, one fixture doesn't parse, and negatives check only "rejected".** Two `each` sites and a mapper alias (`jibb-todo-full`), a page alias, an indirect and a `pure` load (`jibb-page-main`), an alias and a hand-built main (`jibb-store`) are all spec-valid. `tests/type-page-main/hand-built-load.txt` fails to parse, so its case passes on a parse error. Every `jibb-todo-full` negative, "wrong message" included, fails with the same `~` error and the arm compares only "<label>: rejected" | Medium | [`jibb-todo-full.hoon:121-168`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/tests/lib/jibb-todo-full.hoon#L121-L168), [`jibb-page-main.hoon:164-167`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/tests/lib/jibb-page-main.hoon#L164-L167), [`jibb-store.hoon:261-262`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/tests/lib/jibb-store.hoon#L261-L262). The fixtures also still use the positional `[ts "" ~]` that `44e3324` replaced in the doc | Move the valid cases to positive expectations, marked as known gaps until they pass. Fix the fixture. Make each negative assert its message and place | |
56+| M7 | **Inline Grammar examples meant to check are rejected**: `(turn ps \|=(p title.p))`, `"{(add 1 2)}"`, `/posts/~zod` (even under `^- path`), `` `5 `` without a cast, the Patterns rows `1.000`, `~zod`, `"milk"`, `[x ~]`, `[[~ a] [~ b]]` and `[~ b]`, `(eq xs ~)`, `(clap `1 `2 add)`. `clamp` fails because the prelude has no `max`, and the unknown name is reported as "unsupported", not as unknown | Medium | Probes, one module each. `inline-pattern-literals` and `inline-pattern-nested` have no `types.txt`, so nothing tests them | Add a typed case for each, and support them in the general core | |
57+| M8 | **No check runs the `my-app` desk with its Hoon types read through Clay**, as the brief asks, or asserts that every module but `buttons.jibb` checks. `card.jibb` and `api/blog.jibb` are checked only as imports, with no asserted type. No `my-app` timing is recorded | Medium | The suites read `/sur` and mark text with `/*` and `ride` it after dropping `/-` lines ([`jibb-todo-full.hoon:29-53`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/tests/lib/jibb-todo-full.hoon#L29-L53)). `tools/clay-fixtures` builds types with `.^(vase %ca …)` but feeds only the partial report | A ship check that builds each `/sur` and mark through Clay, runs the full checker over every `/ui/**.jibb` in dependency order and expects exactly one failure, `buttons.jibb` at 3:16, timed | |
58+| M9 | **Two wrong programs are accepted.** A repeated attribute, `(column ~[gap+%s1 gap+%s2] ~[(text "x")])`, checks as `(element A)`, though the overview makes it an error. A hand-built element, `^- (element !!) [%island 5]`, checks as `(element !!)`, bypassing the island's check of its data against `init` | Medium | Both reproduced with the full checker. [status.md](../status.md) lists raw-constructor encapsulation and duplicate-attribute checks as missing; nothing tests either error | Report a repeated head tag in a literal `(list attr)` with both sites. Make `element`'s constructors the only way to build one, or check its payloads | |
59+| M10 | **`?-` exhaustiveness and dead arms cover only flat whole-case unions.** A missing case has no site ("missing union case %c"); a covered arm doesn't name the arm that covers it; the Grammar's `[%move * *]` then `[%move %left n]` is "union pattern is not supported"; a loobean without `%.n` and a list without `[i t]` are "branch pattern is not supported"; a repeated `%.y` says "branch does not cover both loobeans" | Medium | Partial report; the full checker is generic for all (M1). The loop matches arms to whole cases ([8225-8311](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L8225-L8311)) | The usefulness check Q5 chose (Maranget): a missing-case witness at the `?-`, and a dead-arm error naming the covering arm, for loobeans, lists, units and nested cells | A15 still open |
60+| M11 | **Errors in imported Hoon types are generic in the full checker**, and a vase, a record with a repeated face, and most overlapping `$%`, `$?` and `$^` have no definite message in either pipeline | Medium | The reader is definite for signed and float auras and for cores and gates, and the partial report shows them at a use site. A vase is only `%unsupported` ([`jibb-import.hoon:1560`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb-import.hoon#L1560)); `[a=@ud a=@t]` reads as ok and the bridge drops it silently | Reuse the partial path's import diagnostics through M1. Give vases and repeated faces `%invalid` codes. Extend the overlap witness | A56 |
61+| M12 | **Shadowing and `proj` errors name neither the name nor its sites.** `++ add 1`, `+$ list @ud`, `++ proj 1` and a definition named like an import face all give "module has conflicting names: /ui/probe/jibb". A shadowing local or pattern binder is generic in the full checker | Medium | [`module-scope-valid`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L11760-L11773) returns a bare `?`. Only a gate sample gets a definite error | Return a diagnostic naming the binding and what it shadows, with a separate wording for `proj` | A43 partly |
62+| M13 | **Several errors the spec describes have no definite message anywhere**: a capital that a body makes `@ud` or a list, `~[text "hi"]` with its suggestion, `(facts …)` outside an API's `paths`, a gate in island data or a model naming the field, `[]`, and a generic aura in `{…}` or a path's `(…)` | Medium | Each probed in both pipelines: "explicit capital constraints are not supported", "list item constraint is not supported", "module mold needs unsupported inference", "module kind needs unsupported inference". No code suggests `~[(text "hi")]` | One definite diagnostic each, with a golden case | A6, A100 for `[]` |
63+| M14 | **Message tests lock the partial report, which no build produces.** For about 20 of the 33 errors, the only test asserts a message the real checker never gives | Medium | `tools/golden` calls only the `golden-types-*` entry points ([`tools/golden:248-262`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/tools/golden#L248-L262)). The program suites lock the generic strings themselves, as at [`jibb-program-watch.hoon:178`](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/tests/lib/jibb-program-watch.hoon#L178) | Q6: render `types.txt` from the full checker, and add one case per error in the catalogue, with the doc's own examples | A122 still open |
64+| M15 | **The goldens never show a doc example checking.** 11 of the 14 `doc-*` cases have no `types.txt`; the other 3 are partial reports, and `doc-grammar-04-step` says "+$ step: cases proven disjoint; mold not checked" although the full checker accepts it | Low | `grep -L '^partial inference' tests/golden/*/types.txt` finds none | As M14 | A122 |
65+| M16 | **Two fragment checks rest on unguarded copies.** The Core language block is "checked inside the todo island" only because `todo-list.jibb` lines 16-25 equal `tests/golden/doc-core-02-update/source.jibb`, which nothing compares. `tests/type-buttons/valid.txt` is a hand copy of the buttons block | Low | `sed -n 16,25p my-app/ui/todo-list.jibb \| diff - tests/golden/doc-core-02-update/source.jibb` is empty today; no tool references `doc-core-02` | Assert the slice in `tools/doc-blocks` or `jibb-todo-full`; derive `valid.txt` from the doc block | |
66+| M17 | **Message polish**: an import cycle names one path, with no `/=` line or chain; "nothing fixes the union of %add" doesn't ask for a `^-` as the Grammar says; an overlap doesn't suggest an open `[`; some mismatch sites print no types; an imported union is named by its cases | Low | [12303-12304](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L12303-L12304), [5363](https://github.com/iko-soy/jibb/blob/f84a29e1a0af663afdb77e793c933470b59a249b/jibb-dev/lib/jibb.hoon#L5363) | Report the cycle as a chain; append "; add a `^-`"; add the hint; print types at every site | A136 |
67+
68+## Early results from the areas still running
69+
70+These come from probes the inference reviewer had run when this version was written. They have not been through that reviewer's own write-up or a second reviewer, so treat them as leads:
71+
72+- Every wrong program in about 40 soundness probes was rejected, except the two in M9 and a gate passed where `*` is expected (A23, known).
73+- Common valid code is rejected as "unsupported": a sum with `roll`, a pair of mutually recursive top-level gates, list reverse, factorial, a recursive count, a pattern binding the rest of a list, wing access on a union or list, and patterns over atoms with number or string literals.
74+- `~[1 "a"]` checks as `(list @t)`: a bare decimal takes the aura `@t`. The spec allows that today; syntax-review proposal S4 would forbid it.
75+
76+## Appendix: the errors the spec describes
77+
78+From [grammar.md](../spec/grammar.md), [overview.md](../spec/overview.md), [core-language.md](../spec/core-language.md) and [decisions.md](../spec/decisions.md), leaving out milestone 1's parse errors and the route, static-file and contrast checks that the brief leaves to milestone 4. "Full" is what `infer-jibb-file-detailed`, the checker a build runs, reports; "generic" is "module definitions need unsupported inference: <path>: ++ name". "Partial" is the report `types.txt` shows.
79+
80+| Error | Test with its message | Full checker | Status |
81+| --- | --- | --- | --- |
82+| Aura mismatch | Partial only (`types-local-error-call`) | Generic | Partly |
83+| Mismatched faces | Partial only (`types-record-faces`) | Generic | Partly |
84+| `msg has no case %submitt` | Partial only (`types-missing-tag-named`) | Generic; in an island, the `~` error of M3 | Partly |
85+| Unresolved tag, "nothing fixes the union of %add" | `jibb-buttons` | Exact, one site | Met |
86+| `~` still pending at the end of a module | None | Exact, one site | Partly |
87+| `\|=%tag` with no case of an equal head | Partial, as a generic unify failure | Generic | Partly |
88+| Overlapping union cases | `jibb-full-overlap-basic`, `types-union-overlap` | Exact, both sites | Met |
89+| Missing `?-` case, named | Partial, no site | Generic | Partly |
90+| Arm that earlier arms cover | Partial, one site; `[%move * *]` unsupported | Generic | Partly |
91+| Value that depends on itself | Partial, annotated values only | Generic | Partly |
92+| Shadowing, prelude and imports included | Gate samples only | Exact for samples; "module has conflicting names" or generic otherwise | Partly |
93+| Cell in `{…}` with no printer | Partial | Generic | Partly |
94+| Generic aura in `{…}` or a path's `(…)` | Partial, one narrow form | Generic | Partly |
95+| Capital that a body makes `@ud` or a list | None; partial says "not supported" | Generic | Partly |
96+| `~[text "hi"]`, suggesting `~[(text "hi")]` | None | Generic | Partly |
97+| Clashing derived names, import faces included | `module-import-api-derived-clash` and three more | Exact, both sites | Met |
98+| Import cycle | `module-import-cycle`, `module-import-root-cycle` | One path, no site | Partly |
99+| Imported signed or float aura | Partial (`type-import-diagnostic`) | Generic | Partly |
100+| Imported core, gate or vase | Partial for cores and gates; vases "unsupported" | Generic | Partly |
101+| Imported `$%`, `$?`, `$^` whose cases overlap | Partial for one form | Generic | Partly |
102+| Imported record with a repeated field | None; silently dropped | Generic | Partly |
103+| `(facts …)` outside an API's `paths` | None; partial accepts it | "module mold needs unsupported inference" | Partly |
104+| Gate in island data or a model, naming the field | Rejection only | "module kind needs unsupported inference", no field | Partly |
105+| Repeated attribute in a literal list | None | Accepted | Not met |
106+| Repeated field in a Jibb record | `types-record-field-expr-duplicate` and two more | Exact, both sites | Met |
107+| `proj` is reserved | "module has conflicting names" | Same, no name | Partly |
108+| `m()` | Partial | Generic | Partly |
109+| `[]` | None; partial says "not supported" | Generic | Partly |
110+| Loobean operands to arithmetic | Partial | Generic | Partly |
111+| Two distinct capitals forced equal | Partial, both sites | Generic | Partly |
112+| Unconstrained hole, or one fixed only by a later use | Partial | Generic; a mold's hole names neither | Partly |
113+| Gates in `eq` arguments and map or set keys | Partial | Generic | Partly |
114+| Watching an unwatchable request, or one with `scry=` | The generic kind message is the expected value | "module kind needs unsupported inference" | Partly |
115+| Each error names both conflicting sites, with excerpts | | Two sites only for overlaps, repeated fields and derived clashes | Partly |
docs/spec/core-language.md+10−9
@@ -83,8 +83,9 @@ Types, faces and casts leave nothing behind. Everything else lowers by these rul
8383| `/posts/~zod`, `%/blog/(slug)` | A list of knots, typed segments printed by their aura's native; the runtime adds the base path to an application path |
8484| `title.p`, `space.theme.theme` | `slot` at the field's axis, nested for longer wings |
8585| `(proj record)` | Apply a `lam` to the source once; its body constructs the expected record from the required fields using `slot` and `cons`, discarding extra fields |
86+| `(unface e)` | `e`: only its type changes |
8687| `card.card`, an import | The qualified name `components/card:card` |
87−| `m(draft=t error=~)` | One `edit` per item, in order: `(edit 7 (edit 6 m t) ~)` |
88+| `m(draft=t error=~)` | One `edit` per item, in order: `(edit 7 (edit 6 m t) ~)`. A wing's item edits at the wing's axis, so with `cart` at 2 and `open` at 3 inside it, `m(open.cart=x)` is `(edit 5 m x)`. Each value is computed from `m` as it was |
8889| `f a b c` | `(app f (cons a (cons b c)))`: the arguments are the sample |
8990| `\|= [a=@ b=@] body` | `(lam _1 (let a (slot 2 _1) (let b (slot 3 _1) body)))`; a single face, as in `\|= m=model`, names the `lam` itself |
9091| `\|=%got` | `(lam _1 (cons %got _1))` |
@@ -104,14 +105,14 @@ The todo island's `update`, from worked example 3:
104105```jibb
105106++ update |= [=msg m=model]
106107 ?- msg
107− [%typed t]
108− ?- (gth (lent (tuba (trip t))) 80)
109− %.y [m(draft=t error=`"Too long") ~]
110− %.n [m(draft=t error=~) ~]
111− %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
112− [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
113− [%got ts] [m(todos=ts) ~]
114− [%acked err] [m(error=err) ~]
108+ [%typed t]
109+ ?- (gth (lent (tuba (trip t))) 80)
110+ %.y [m(draft=t error=`"Too long") ~]
111+ %.n [m(draft=t error=~) ~]
112+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
113+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
114+ [%got ts] [m(todos=ts) ~]
115+ [%acked err] [m(error=err) ~]
115116```
116117
117118lowers to the program below. The model `[todos draft error]` puts `todos` at axis 2, `draft` at 6 and `error` at 7, and `%submit`, the only atom case, needs no test once `cell?` fails.
docs/spec/decisions.md+11−8
@@ -8,10 +8,12 @@ The choices behind the Language tab, made on 2026-10-23; a later date marks a re
88
99Until the Claude doc is synced with this copy, this copy is the spec (review question 42). Synced says whether the doc's Decisions tab has the row as written here. A row decided by 2026-10-29 or undated was in the doc when `spec/` was copied from it on 2026-10-30, and is unchanged. A row decided on or after 2026-10-31 is only here. A row of 2026-10-30 says Check: the copy had that day's answers to the 12 grammar questions, but other rows of that day were added or edited here afterwards ([docs/README.md](../README.md#the-spec)), and nobody has compared them with the doc yet.
1010
11+Rows dated 2026-11-03 are Montelot's decisions on the [syntax review](../reviews/2026-11-02-syntax-review.md): S1 with its step 1, S2, S4 to S7, S11 to S13 and S15. S1 step 1 is decided but not built yet; the checker core that review question 5 asks for will build it.
12+
1113| Decision | Choice | Status | Synced |
1214| --- | --- | --- | --- |
13−| Syntax | Hoon's runes as keywords, and its literals; wide forms only for `\|=` and `$-`; changes take one or more record items, as `m(draft="x")`, so `m()` is an error; `.` reads fields, imports and prelude groups; no name may shadow another | Decided 2026-10-30 | Check |
14−| Literals | Exactly Hoon's, including `%$` as a term literal and pattern: `1000` is an error, `~2026.2.31` is `~2026.3.3`, and years BC and sub-second groups are dates; `print-date`'s minute form is not a literal | Decided 2026-10-30 | Check |
15+| Syntax | Hoon's runes as keywords, and its literals; wide forms only for `\|=` and `$-`; changes take one or more record items, as `m(draft="x")`, so `m()` is an error; an item may name a wing through record fields, as `m(open.cart=x)`, every value is computed from the original record, and two items that name the same field, or one inside the other, are an error; `.` reads fields, imports and prelude groups; no name may shadow another | Decided 2026-11-03 | No |
16+| Literals | Exactly Hoon's, including `%$` as a term literal and pattern: a bare decimal is a `@ud`, so `^- @dr 30` is an error and a duration is written `~s30`; `1000` is an error, `~2026.2.31` is `~2026.3.3`, and years BC and sub-second groups are dates; `print-date`'s minute form is not a literal | Decided 2026-11-03 | No |
1517| Cells | A single-item cell `[a]` is `a`; an empty `[]` is an error, in expressions and molds | Decided 2026-10-30 | Check |
1618| Numeric terms | `%` and a decimal as Hoon writes it: `%1.000`; `%1000` and `%007` are errors | Decided 2026-10-30 | Check |
1719| Strings | Hoon's escapes: `\\`, `\"`, `\{`, and `\` with two lowercase hex digits; a string and each `{…}` close on the line they open; `::` in a string is text | Decided 2026-10-30 | Check |
@@ -32,7 +34,7 @@ Until the Claude doc is synced with this copy, this copy is the spec (review que
3234| Branching | `?-` only, loobeans included; exhaustive, with explicit catch-alls; covered arms are errors; failures say `!!` | Decided 2026-10-29 | Yes |
3335| Equality and negation | The gates `eq` and `not`, with Hoon's bitwise `not` exposed as `not.bit`; `eq`'s arguments and map and set keys contain no gates, even nested; the checker infers and generalizes that constraint; union matching never inspects a gate to distinguish cases | Decided 2026-10-30 | Check |
3436| Special rules | No built-ins; type-directed rules are welcome, each listed in the Grammar tab | Decided 2026-10-29 | Yes |
35−| Inference | Hindley–Milner with aura variables; `@` is any atom, a specific atom fits `@` and a more specific aura fits an ancestor in its Hoon aura family, but each reverse needs a check, and repeated atom-constrained capitals give the same type; a number takes `@ud` only where its `++` isn't generic over its aura; distinct specific auras remain distinct; faces are part of record types, and an unnamed position can take a face but two different faces don't unify; principal types | Decided 2026-10-30 | Check |
37+| Inference | Hindley–Milner with aura variables; `@` is any atom, a specific atom fits `@` and a more specific aura fits an ancestor in its Hoon aura family, but each reverse needs a check, and repeated atom-constrained capitals give the same type; a decimal is a `@ud`, which fits `@u`, `@` and `*` but no other aura, except where its `++` is generic over its aura; distinct specific auras remain distinct; faces are part of record types, and an unnamed position can take a face but two different faces don't unify; a capital that meets a faced position binds only the type under the face, so `$-([A A] ?)` takes a gate with named parameters (not built yet); principal types | Decided 2026-11-03 | No |
3638| Effects | The library unions `cmd` and `sub`; `raw-poke`, `ask` and `qath` are transparent types defined in the internal prelude and re-exported normally; derived gates and `pure` also construct requests; islands read agents only by watching; replies get full state, and diffs take a fold; timers carry the time; `%who` gives the owner's `@p`; nacks reach replies as text | Decided 2026-11-01 | No |
3739| Poke representation | The source-backed private internal prelude module defines `raw-poke`, and the public prelude re-exports it as an ordinary transparent type. A store's local `poke` action remains an ordinary mold; derived helpers produce the runtime envelope | Decided 2026-11-01 | No |
3840| Agent APIs | `/ui/api/<agent>.jibb` with `+$ poke` and `+$ paths`, over the agent's mark types; a case is a name, a path and a type, with `(facts full diff …)` for diffs, told apart by mark; an optional scry path, for pages; an island may watch a request only when the checker proves it is watchable, so a separate scry path or unknown watchability is an error; typed segments by aura | Decided 2026-10-31 | No |
@@ -40,21 +42,22 @@ Until the Claude doc is synced with this copy, this copy is the spec (review que
4042| Derived gates | API files and stores give a generic `poke` command helper taking an action and reply, and a checked request per path or store state; clashing names are errors, including a derived name that clashes with an import face | Decided 2026-11-01 | No |
4143| Hoon types | A fixed translation table; `map`, `set`, `qeu`, `jar`, `jug` by name; `mop` as `(mop K V)`, read with `on`; imported `$%`, `$?` and `$^` cases must differ as nouns, and records with duplicate field names are errors where used; unused molds skipped | Decided 2026-10-30 | Check |
4244| Record fields | Duplicate field names in a Jibb-written record are an error, as they are in an imported Hoon record | Decided 2026-10-31 | No |
45+| Unface | The explicit type-directed operation `unface` removes every face from its argument's type, through cells, a gate's sample and product, and containers' arguments; unions and recursive molds go by name and are kept whole; like `proj`, it is reserved and not a value; it leaves nothing behind at run time | Decided 2026-11-03 | No |
4346| Record projection | The explicit type-directed operation `proj` takes a record and uses its expected result type to select its fields; no projection is inserted automatically. `proj` is reserved and cannot be defined or imported under that name. The result has exactly the fields declared by its type | Decided 2026-10-31 | No |
44−| Layout | Indentation; juxtaposed calls; a bracket open at line end takes one item per line, with no closer | Decided | Yes |
47+| Layout | Indentation; juxtaposed calls; a bracket open at line end takes one item per line, with no closer; a block of deeper lines belongs to the line above, so a call never continues onto a deeper line; a body's final line may hand the rest of the body, at its depth, to a tall `\|=`, `^-` or `~&` that ends it, and a `?-` that begins it may take its arms at its depth | Decided 2026-11-03 | No |
4548| Elements | Ordinary gates; containers take attribute lists; `stack` switches at `wide`; `el` adds attributes and wins; headings 1 to 6; `form` sends on Enter, the innermost when nested; `image` from an application path, sized from the file, or a sized URL; no focus control for now | Decided 2026-10-29 | Yes |
4649| Long calls | One argument per line inside parentheses | Decided | Yes |
4750| Inline gates | Hoon's wide form; the mold may be inferred; a bare sample name binds; `\|=%got` is a case's constructor, typed by the gate expected; a bare tag is always a value | Decided 2026-10-29 | Yes |
4851| Empty mold | `!!`, with no values; the expression has any type; pages are `(element !!)`, which keeps islands out of islands | Decided 2026-10-29 | Yes |
4952| Noun mold | `*` is the noun type, not a type variable; use a capital for a generic type; a value of a more specific noun type can be used where `*` is expected | Decided 2026-10-30 | Check |
50−| Type variables | Capitals, generalized per `++`; a capital in a local `++` shares the enclosing `++`'s variable of that name if the enclosing `++` also uses it; otherwise it is introduced and generalized locally; a different type takes a different capital; a body cannot force distinct capitals to be equal, so a shared type uses the same capital; one used where an atom is required gains an inferred atom constraint, and cannot be fixed to a more specific type in its body | Decided 2026-10-30 | Check |
53+| Type variables | A capital, then lowercase letters and digits, as `A` or `Msg`, printed by the name they were written with; generalized per `++`; a capital in a local `++` shares the enclosing `++`'s variable of that name if the enclosing `++` also uses it; otherwise it is introduced and generalized locally; a different type takes a different capital; a body cannot force distinct capitals to be equal, so a shared type uses the same capital; one used where an atom is required gains an inferred atom constraint, and cannot be fixed to a more specific type in its body | Decided 2026-11-03 | No |
5154| Partial type annotations | `_` may appear wherever a mold may appear and marks that part of the type for inference; a hole inferred as a named type variable is resolved; an unconstrained hole is an error, and a named mold or value definition must determine its own holes without constraints from later uses | Decided 2026-10-31 | No |
5255| Loobean mold | `?`, switched with `?-` | Decided 2026-10-26 | Yes |
5356| Defaults | None | Decided | Yes |
5457| Modules | Records, not cores | Decided | Yes |
55−| Kinds | The type of `main`: `(element !!)`, `(page R D)`, `(program D X M)` or `(store S)`; other names by file kind, in the Grammar tab | Decided 2026-10-29 | Yes |
58+| Kinds | The type of `main`: `(element !!)`, `(page Params Data)`, `(program Data Model Msg)` or `(store S)`; other names by file kind, in the Grammar tab | Decided 2026-11-03 | No |
5659| Type identity | Recursive molds by name and module | Decided 2026-10-29 | Yes |
57−| Binding patterns | In `?-` arms; the last position binds the rest | Decided 2026-10-29 | Yes |
60+| Binding patterns | In `?-` arms; the last position binds the rest; cells of patterns nest; a bare name is an error where a case the pattern can match has there a tag the name spells, as `stop` for `%stop` | Decided 2026-11-03 | No |
5861| Text | Strings are written only as `"…"` and are always cords; tapes come from `trip`; `{…}` prints by aura, a bare `@` as `@ud`, and an atom whose aura its `++` is generic over is an error; `print-date` prints Urbit-style to the minute in the theme's zone, from jibb-dev's zone table; numbers keep Hoon's form | Decided 2026-10-30 | Check |
5962| Auras | Specific auras stay distinct; `@` is any atom, a more specific aura fits an ancestor in its Hoon aura family one way, with the reverse requiring a check, and shared atom-constrained type variables preserve the same aura | Decided 2026-10-30 | Check |
6063| Loobean arithmetic | Arithmetic rejects loobean operands; comparison may accept them and returns `?` | Decided 2026-10-31 | No |
@@ -96,7 +99,7 @@ Until the Claude doc is synced with this copy, this copy is the spec (review que
9699| Access | Every page is private to the owner; public pages come in a later version | Decided 2026-10-29 | Yes |
97100| Tests | `test-…` arms under `/ui/tests`, run by `-jibb!test`; the JavaScript side and differential tests under Node from jibb-dev | Decided 2026-10-29 | Yes |
98101| Editor support | Tree-sitter grammar | Decided | Yes |
99−| Formatter | One canonical layout | Decided | Yes |
102+| Formatter | One canonical layout: a cast whose expression takes the deeper lines ends the line it belongs to; every `?-` begins its own line, with its arms at its depth where the rest of a body allows that | Decided 2026-11-03 | No |
100103| Name | Jibb | Decided | Yes |
101104
102105## Settled milestone 2 questions
docs/spec/grammar.md+55−34
@@ -6,19 +6,20 @@ The syntax the compiler accepts.
66
77## Lexical rules
88
9−- **Indentation is structure**: a deeper line continues the line above; returning to an earlier indentation closes every block since. Spaces only; blank and comment-only lines don't count.
9+- **Indentation is structure**: a block of deeper lines belongs to the line above it: to the last bracket that line leaves open at its end, to the body of the last rune or `++` on it, to `?-`'s arms, to an arm's body, or to a `+$`'s cases; or, for a rune or `?-` that ends a body's final line, so do the lines after it at the same depth, as The rest of a body says. A deeper line that nothing on the line above takes is an error, so a call never continues onto a deeper line. Returning to an earlier indentation closes every block since. Spaces only; blank and comment-only lines don't count.
1010- **Layout tokens**: a deeper line emits INDENT, the same depth NEWLINE, a shallower one a DEDENT per closed level, then NEWLINE.
11−- **Open brackets**: a bracket open at line end takes one item per deeper line and closes at the first line that isn't deeper, with no closer. Brackets opened and closed on one line work as usual. A mold's `[` and `(` open the same way, with one field or mold per deeper line. A line may leave several brackets open: the deeper lines go to the last one, or to the body of the last rune, and the others close with it, so `(column ~ ~[` above its items needs no `)`.
11+- **Open brackets**: a bracket open at line end takes one item per deeper line and closes at the first line that isn't deeper, with no closer. Brackets opened and closed on one line work as usual. A mold's `[` and `(` open the same way, with one field or mold per deeper line. A line may leave several brackets open: the deeper lines go to the last one, or to the body of the last rune, and the others close with it, so `(column ~ ~[` above its items needs no `)`. On the opener's line, spaces separate items, so `~[text "a"` holds two items. In an expression's open bracket each deeper line is one whole item: `text "a"` there is `(text "a")`, `label=trim " x "` is `label=(trim " x ")`, and under a `(` alone the first deeper line is the head. A mold's open bracket takes exactly one field or mold per deeper line.
1212- **Tight forms**: `a+b`, `a.b`, `` `x ``, `|=%got` and the openers `~[`, `|=(`, `$-(` take no spaces. A `(` right after a wing is a change: `m(note=text)` changes, `m (note text)` calls. `%/` starts an application path, `%/blog/(slug)`.
13−- **Spacing**: one space between items; more for alignment. That is style, which the formatter keeps: the parser takes one or more spaces between items, and allows spaces after an opener, before a closer and at the end of a line. Faces `name=value`, puns `=name` and typed path segments `[id=@ud]` take no spaces, and a rune is followed by one.
13+- **Spacing**: one space between items; more for alignment. That is style, which the formatter keeps: the parser takes one or more spaces between items, and allows spaces after an opener, before a closer and at the end of a line. Faces `name=value`, puns `=name` and typed path segments `[id=@ud]` take no spaces, and a rune is followed by one. The formatter puts a cast whose expression takes the deeper lines at the end of the line it belongs to, the `|=`, `++` or arm line, and a cast whose expression fits on its own line on the line below with it. It starts every `?-` on its own line, below the line it belongs to, with its arms at its depth where the rest of a body allows that, and one level deeper on an open bracket's line.
1414- **Comments**: `::` to the end of the line, outside strings; inside a string, `::` is text.
1515- **Names**: Hoon terms; lowercase letters, digits and hyphens, starting with a letter.
16+- **Type variables**: a capital, then lowercase letters and digits: `A`, `Msg`, `T2`. `AB`, `MSG`, `Msg_x` and `Msg-x` are errors. In a mold, a capitalized name is a type variable and a lowercase name is a mold: the reverse of Elm, where `Msg` is a concrete type and `msg` a type variable.
1617
1718## Literals
1819
1920| Form | Example | Type |
2021| --- | --- | --- |
21−| Decimal | `1.000` | `@ud`, or any aura by context; groups of three, as in Hoon |
22+| Decimal | `1.000` | `@ud`, which also fits `@u`, `@` and `*`; groups of three, as in Hoon |
2223| Hexadecimal | `0x1f` | `@ux` |
2324| Base 32 | `0v5.fdf99` | `@uv` |
2425| Ship | `~zod`, `~sampel-palnet` | `@p` |
@@ -42,27 +43,35 @@ Every literal reads exactly as Hoon reads it: `1000` is an error (write `1.000`)
4243
4344- **Call**: `f a b`; parentheses only group. A call open in parentheses puts its head and first arguments on the first line, then one argument per indented line; a `(` alone at the end of a line puts the head on the first indented line.
4445- **Lists**: `~[a b c]`, or `~[` at line end with one item per line. On one line, whitespace separates items, so calls need parentheses: `~[(text "hi")]`, which the checker suggests for `~[text "hi"]`. On indented lines, each line is an item.
45−- **Faced cells**: `[text="milk" done=%.n]`, or one `name=value` per line of an open bracket. A change takes one or more of the same items, as `m(done=%.y)`; `m()` is an error.
46+- **Faced cells**: `[text="milk" done=%.n]`, or one `name=value` per line of an open bracket. A change takes one or more of the same items, as `m(done=%.y)`; `m()` is an error. A change's item, inline or on a line, may name a wing instead, read through record fields only: `m(open.cart=(not open.cart.m))` sets field `open` of field `cart`, as Hoon's `m(open.cart x)`. Every value is computed from the original record. Two items that set the same field, or one a field inside the other's, as `m(cart=c open.cart=%.y)`, are an error. A cell's items take plain names.
4647- **Pairs and units**: `gap+%s2` and `` `x `` bind tighter than calls, so `pad+%s3 gap+%s2` is two items.
4748- **Wing** `title.p`, also for imports and prelude groups, which are records: `card.card`, `space.theme.theme`, `get.by`. **Change** `m(draft="x" error=~)`.
49+- **Unface**: `(unface e)` is `e` with every face removed from its type, so a gate or record fits where other names are expected. `~[(unface lth2) (unface lte2)]` is a list though `lth2` names its sample `[x=A y=A]` and `lte2` names it `[a=A b=A]`, and `(take-kv (unface pair))` passes a `[p=@t q=@ud]` where `[k=@t v=@ud]` is expected; the fields then match by position alone. Faces go from cells, from a gate's sample and product, and from a container's arguments, as in `(list [p=@t q=@ud])`. A union or recursive mold goes by name, so it is kept whole: a gate over `msg` still takes a `msg`. A type variable inside `e`'s type keeps the faces it is bound to later. Like `proj`, it is an operation the checker handles by type, not a gate: it takes one argument, and `(turn gs unface)` is an error; write `|=(g (unface g))`. A `++` whose body is `(unface |= …)` is still a gate, so it can call itself.
4850- **Inline gate**: `|=(p=post.blog title.p)`, or `|=(p title.p)` when the call fixes the type. A bare name in a sample always binds. `|=%got` is case `%got`'s constructor, typed by the gate expected. A bare name binds at any depth of a sample, so `|= [a=@ b]` binds `a` and `b`.
4951- **Interpolation**: `{…}` holds any expression; `\{` writes a brace and `\"` a quote; no `<…>`. Strings take Hoon's escapes: `\\` writes a backslash, and `\` with two lowercase hex digits writes that byte, as `\0a` a line feed; any other `\` is an error. A string and each `{…}` close on the line they open, and `::` inside a string is text.
5052- **No operators**: `eq a b`, `not x`, `gth a b` are gates.
5153
5254## Runes
5355
54−A rune's first children sit on its line, the last taking the rest of it; the others follow, indented.
56+A rune's first children sit on its line, the last taking the rest of it; the others follow, indented. On a body's final line, the last child may instead take the rest of the body at the same depth, as The rest of a body says.
5557
5658- `++` **luslus**: defines a value, at top level or as local names at the start of any body (a gate's, an arm's, a `^-`'s, a `~&`'s or a `++`'s), visible to each other and the final expression. Gates may call themselves and their siblings; other values can't depend on themselves, even through a gate, so `++ title (trim title)` is an error.
5759- `+$` **lusbuc**: defines a mold, likewise: on its line, or as cases on the lines below, one per line, where several cases make a union and one is just that mold. Molds may be recursive.
5860- `|=` **bartis**: a gate with a faced sample, `m=model`, `=msg` (`msg=msg`) or `[a=@ b=@]`; the body on the same line or below.
59−- `?-` **wuthep**: the only branch, exhaustive; the subject on its line, then arms of a pattern and an expression or body. Conditions switch on `%.y` and `%.n`.
61+- `?-` **wuthep**: the only branch, exhaustive; the subject on its line, then arms of a pattern and an expression or body, one per line, deeper. A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth. Conditions switch on `%.y` and `%.n`.
6062- `^-` **kethep**: a cast; the mold on its line, the expression after it or below.
6163- `~&` **sigpam**: prints the value on its line, then runs the body below; output goes to the ship's log or the browser's console.
6264- `!!` **zapzap**: a crash, an expression of any type; as a mold, the empty mold. It is an operand, so `f !!` and `~[!!]` need no parentheses.
6365- `$-` **buchep**: a gate's mold, `$-(sample product)`.
6466- `|$` **barbuc**: a generic mold, right after a `+$`'s name: `+$ result |$ [V E]`, then the mold on its line or the cases below.
6567
68+**The rest of a body.** A body's final line may hand the rest of the body, the lines after it at the same depth, to the rune that ends the line:
69+
70+- a tall `|=`, `^-` or `~&`, or a chain of them such as `^- @ud ~& x`, when the line ends where the innermost rune's last child goes. That child is the rest, a body of its own: first its local `++` and `+$`, then its expression, whose own final line may do the same;
71+- a `?-` that begins the line and ends it with its subject. Its arms are the rest, one per line, so nothing follows them.
72+
73+A gate's body can then be `~& msg`, then `?- msg`, then its arms, all at one depth, and adding or removing the `~&` line moves no other line. This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression. So `++ inner |= y=@ud` above `(inner x)`, `[a b] ?- a` above `%.y 1`, `^- @ud ?- x` above `%.y 1` and `++ g ?- x` above `%.y 1` stay errors.
74+
6675Only `|=` and `$-` have wide forms: `|=(sample expr)` and `$-(mold mold)`. Their children are operands, so calls inside need parentheses.
6776
6877Left out on purpose:
@@ -98,9 +107,9 @@ An imported Hoon record with duplicate field names is an error where used; impor
98107A file is a module: imports, then definitions.
99108
100109- `+$ name mold` defines a mold; `++ name expr` a value.
101−- Names may refer to each other in any order, and no name may shadow one already in scope, imports and the prelude included.
110+- Names may refer to each other in any order, and no name may shadow one already in scope, imports and the prelude included. `proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold.
102111- Molds and values have separate namespaces, told apart by position: `todo-action.todo` is a mold, `poke.todo` its command helper, and `todos.todo` a mold and a request.
103−- `main`'s type decides the kind: `(element !!)` a page; `(page R D)` a page with data, from parameters `R` to data `D`; `(program D X M)` an island, with data, model and messages; `(store S)` a store with state `S`. They're built by `(page load view)`, `(program init update view subs)` and `(store init update)`. A module without `main` is a library.
112+- `main`'s type decides the kind: `(element !!)` a page; `(page Params Data)` a page with data, from parameters to data; `(program Data Model Msg)` an island, with data, model and messages; `(store S)` a store with state `S`. They're built by `(page load view)`, `(program init update view subs)` and `(store init update)`. A module without `main` is a library.
104113- Everything is exported and read through the import's face, as `card.card`. The prelude keeps private helpers in a separate internal module; it imports them without exposing them.
105114- An API module, `/ui/api/<agent>.jibb`, also exports derived gates: a generic `poke` command helper, adding the agent and mark and taking a reply, and a request per `paths` case, taking a reply over full state, plus a fold for `(facts full diff …)`. An island may watch a request only when the checker proves it is watchable. A request whose case has a separate `scry=` path, or whose watchability cannot be proved, is a type error. A store's local `+$ poke` is its ordinary action mold; a store exports a generic `poke` command helper and a `state` request. Clashing derived names are errors, including a derived name that clashes with an import face.
106115
@@ -121,15 +130,16 @@ Every other name is free.
121130A mold is only a type: never called on a noun, and with no default. Types are inferred, Hindley–Milner with aura variables: every expression has a principal type, and there is no general subtyping. These one-way widenings are allowed: a value of a specific atom type fits `@`, a value of a specific noun type fits `*`, and a more specific aura fits an ancestor in its Hoon aura family; the reverse of each widening needs a check. Records can also be projected explicitly, as described below.
122131
123132- **Partial annotations**: `_` may appear wherever a mold may appear. It marks a part of the type for the checker to infer, so a type annotation can specify only the parts it needs to. A hole inferred to be a named type variable is resolved: in `++ id |= x=A ^- _ x`, the result hole is `A`. An unconstrained hole is an error. A named mold or value definition must determine its own holes: `+$ box [item=_]` and `++ id |= x=_ x` do not determine their holes, and later uses cannot fix them.
124−- **Atoms**: `@` is any atom, regardless of aura; auras such as `@ud`, `@t`, `@p` and `@da` are specific atom types. An `@ud` value fits where `@` is expected, but an `@` value needs a check to fit `@ud`. A more specific aura also fits an ancestor in its Hoon aura family: `@ud` and `@ux` fit `@u`, and `@tD` fits `@t`. The reverse needs a check. Distinct specific auras remain distinct; sharing an ancestor does not make them unify. Each bare `@` independently accepts any atom: it is not an aura variable. Atoms that must share a type take one capital, as `[lo=A hi=A]`, with the atom constraint inferred from the body. `add` takes `[A A]` and returns `A`, with `A` constrained to atoms, so `(add n 1)` with `n=@ud` is a `@ud`. Arithmetic rejects loobean operands: `?` contains only 0 and 1, while an arithmetic result need not. Comparison may take loobeans and returns `?`.
133+- **Atoms**: `@` is any atom, regardless of aura; auras such as `@ud`, `@t`, `@p` and `@da` are specific atom types. An `@ud` value fits where `@` is expected, but an `@` value needs a check to fit `@ud`. A more specific aura also fits an ancestor in its Hoon aura family: `@ud` and `@ux` fit `@u`, and `@tD` fits `@t`. The reverse needs a check. Distinct specific auras remain distinct; sharing an ancestor does not make them unify. Each bare `@` independently accepts any atom: it is not an aura variable. Atoms that must share a type take one type variable, as `[lo=A hi=A]`, with the atom constraint inferred from the body. `add` takes `[A A]` and returns `A`, with `A` constrained to atoms, so `(add n 1)` with `n=@ud` is a `@ud`. Arithmetic rejects loobean operands: `?` contains only 0 and 1, while an arithmetic result need not. Comparison may take loobeans and returns `?`.
125134- **Constants**: `%add`, `~` and the loobeans have one value each.
126135- **Records and tuples**: `[text=@t done=?]`, `[@t ?]`. An empty `[]` is an error. Duplicate field names in a record are an error. Faces are part of the type, so `[a=@ b=@]` and `[x=@ y=@]` don't unify. An unnamed position can unify with a faced position and take its face, so `[0 0]` fits `[x=@ud y=@ud]`; two different faces don't unify. The explicit type-directed operation `(proj record)` selects fields from its argument according to the expected result type: `^- [x=@ud y=@ud] (proj wider)`, or `(f (proj wider))` when `f` expects that record. The source is evaluated once, and the result contains exactly the fields in the expected layout. No projection is inserted for a direct call. `proj` is reserved: a module cannot define or import another name `proj`. A record too long for one line can leave its `[` open, with one field per deeper line, as an expression's bracket does.
127136- **Unions**: a `+$` with several cases below it. Every union written in Jibb has a name, so one used in a field, a sample, a cast, a gate's mold or an argument gets its own `+$`; only imports bring in unions without one. Tags take their union from context, as Tag resolution describes. Cases must differ as nouns: inhabited cases must differ at some position of their right-nested cells, where one is an atom and the other a cell, or both are different constants. `*`, type variables and molds that can be either, such as `(list A)`, can overlap atoms and cells. `?` counts as the two atoms `%.y` and `%.n`: it is disjoint from cells and overlaps the constants 0 and 1. The empty mold `!!` is disjoint from every case; a cell with an empty position at any depth is itself empty and is also disjoint from every case. A union whose cases don't all differ is rejected.
128137- **Containers**: `(list A)`, `(unit A)`, `(set A)`, `(map K V)`, `(mop K V)`, `(qeu A)`, `(jar K V)`, `(jug K V)`.
129−- **Gates**: `$-(A B)`. Type variables are capitals, generalized per `++`. A capital in a local `++` shares the enclosing `++`'s variable of the same name if the enclosing `++` also uses it; otherwise the local `++` introduces and generalizes its own variable. For example, `++ inner |= y=A y` uses the enclosing `A` when its enclosing gate has a sample `x=A`; if the enclosing `++` does not use `A`, `inner` generalizes its own `A`. Use another capital for a different type. A body can't force two distinct capitals to be equal; use the same capital wherever a type must be shared. A type variable used where an atom is required gains an atom constraint, so `++ clamp |= [lo=A hi=A n=A]`, whose body calls `gth` and `max`, works on any one aura. It can become nothing more specific: a body that makes `A` a `@ud` or a list is an error.
138+- **Gates**: `$-(A B)`. Type variables are capitalized names, as `A` or `Msg`, generalized per `++`. A capital in a local `++` shares the enclosing `++`'s variable of the same name if the enclosing `++` also uses it; otherwise the local `++` introduces and generalizes its own variable. For example, `++ inner |= y=A y` uses the enclosing `A` when its enclosing gate has a sample `x=A`; if the enclosing `++` does not use `A`, `inner` generalizes its own `A`. Use another capital for a different type. A body can't force two distinct capitals to be equal; use the same capital wherever a type must be shared. A type variable used where an atom is required gains an atom constraint, so `++ clamp |= [lo=A hi=A n=A]`, whose body calls `gth` and `max`, works on any one aura. It can become nothing more specific: a body that makes `A` a `@ud` or a list is an error.
139+- **Printed types** show a type variable by the name it was written with: `++ id |= x=Msg x` prints `$-(Msg Msg)`. A variable from a gate a `++` uses keeps that gate's name, so `++ make program` keeps `program`'s `Data`, `Model` and `Msg`. When several named variables become one, a capital written in the `++` names it; otherwise the one made first does, and a called gate's variables are made before its arguments', so `(cork same same)` prints `$-(A A)`, from `cork`'s `A`. A variable with no name prints as a letter that no other variable in the same type uses: `++ h |= x=A [x same]` prints `$-(A [A $-(B B)])`.
130140- **Paths**: `/todos` is constant, `/` empty, and `/todo/[id=@ud]` typed by aura. A typed segment may use `_` for an inferred aura; it still must resolve to an aura that the path rules can print and parse. `%/blog/(slug)` is an `qath`, checked against routes and static files.
131141- **Generic molds**: `+$ result |$ [V E]` with cases below; `|$` goes only right after a `+$`'s name.
132−- **Noun**: `*`, not a type variable; use a capital for a generic type. A value already known to have a more specific noun type, such as `@ud`, can be used where `*` is expected. **Empty**: `!!`.
142+- **Noun**: `*`, not a type variable; use a type variable for a generic type. A value already known to have a more specific noun type, such as `@ud`, can be used where `*` is expected. **Empty**: `!!`.
133143- **Pokes**: `raw-poke` is defined in the source-backed private internal prelude module and re-exported by the public prelude as an ordinary transparent type. Ordinary modules can construct and inspect its values; derived `poke` helpers return commands.
134144- **Effect and application-path types**: `raw-poke`, `ask` and `qath` are transparent types, defined in the internal prelude and re-exported normally; callers can construct and inspect their values. Derived gates and `pure` also construct requests, and application-path literals have type `qath`. `(facts full diff …)` appears only in an API file's `paths`.
135145- **Identity**: recursive molds go by name and module.
@@ -144,7 +154,7 @@ A tag literal or `~` gets a fresh type variable and a pending constraint: the va
144154- `|=%typed` is a case's constructor: against `$-(@t M)` it is `|=(t [%typed t])`, requiring `M` to have a case `[%typed @t]`. It works for cases whose head is a literal with the same noun as the tag, regardless of how that literal is written: `|=%$` also constructs a case headed by `%.y` or `~`, since each is the noun 0. A bare tag is always a value.
145155- A variable constrained by tag resolution, and any it mentions, doesn't generalize; it stays open until something in the module fixes it. An island's `main` fixes its messages, so islands resolve their own tags. The inferred gate-free constraint is retained when a type variable is generalized.
146156- A constraint still open when its module is checked is an error asking for a `^-`; the checker never guesses. Library helpers can cast, as in `^- (list attr)`.
147−- Wing access, changes and `?-` on a type not yet known wait the same way.
157+- Wing access, changes, `unface` and `?-` on a type not yet known wait the same way.
148158- Patterns need none of this; they're checked against the subject's type.
149159
150160```jibb
@@ -159,12 +169,12 @@ A tag literal or `~` gets a fresh type variable and a pending constraint: the va
159169
160170## Literals by context
161171
162−Number and cell literals resolve like tags: each waits for its context and takes a default when its `++` is checked. A number takes `@ud` only if nothing fixes its aura and its `++` isn't generic over it, so `++ inc |= n=A (add n 1)` stays generic, while the sum in `"{(add 1 2)}"` is a `@ud`.
172+Number and cell literals resolve like tags: each waits for its context and takes a default when its `++` is checked. A number is a `@ud`, as in Hoon: a context can make it a `@u`, and it fits `@` and `*`, but every other aura takes its own literal, as `~s30` for a `@dr`, `~2026.1.1` for a `@da`, `~zod` for a `@p`, `"5"` for a `@t` and `0x1` for a `@ux`. So `^- @dr 30`, `^- @p 0`, `(add ~s1 1)` and `(text 5)` are errors, each naming the number and the aura it met. A number takes `@ud` only if nothing fixes its aura and its `++` isn't generic over it, so `++ inc |= n=A (add n 1)` stays generic, and `(inc ~s1)` is a `@dr`, while the sum in `"{(add 1 2)}"` is a `@ud`.
163173
164174| Literal | Can become | Default |
165175| --- | --- | --- |
166176| Tag `%a`, or `~` | A union's case or a constant atom | None: an error asking for a `^-` |
167−| Number `5` | Any aura | `@ud` |
177+| Number `5` | `@ud` or `@u`, or any aura its `++` is generic over | `@ud` |
168178| Cell `[x xs]` | A tuple, a record, a cons | A tuple |
169179
170180- In `{…}`, an atom prints by its aura: `@ud` as `1.000`, `@da` as a UTC date with sub-seconds, `@p` as a ship, and a bare `@` as `@ud`. `@t`, `@ta`, `@tas` and tapes splice as text; any other cell is an error asking for a printer. Printers are picked when compiling, so an atom whose aura its `++` is generic over, as `n` in `|= n=A` when `A` is constrained to atoms, is an error asking for an aura, here and in a `(…)` segment of an application path. For readers, `print-date` prints in the theme's zone, Urbit-style, to the minute, as `~2026.10.29..14.30`; numbers keep Hoon's form.
@@ -181,7 +191,7 @@ Number and cell literals resolve like tags: each waits for its context and takes
181191
182192## Patterns
183193
184−Arms are tried in order. Every case needs an arm or a catch-all, `*` or a bare name. An arm that earlier arms cover, such as a second `%add` or anything after `[%move * *]`, is an error, and a case that should fail says `!!`. A name in a pattern always binds anew, so compare values with `?- (eq a b)`. Patterns take terms, numbers, strings without `{…}`, ships, loobeans and `~`, not lists or pairs.
194+Arms are tried in order. Every case needs an arm or a catch-all, `*` or a bare name. An arm that earlier arms cover, such as a second `%add` or anything after `[%move * *]`, is an error, and a case that should fail says `!!`. A name in a pattern always binds anew, so compare values with `?- (eq a b)`. A name is an error where the subject's type at its position is a union, or a one-case mold, and a case that the rest of the pattern can match has there the constant the name spells, so `stop` written for `%stop` below is an error, not a catch-all. Positions typed by an aura, `*`, a type variable, a container's element or a recursive mold are unaffected, so `[t %draft] t` still binds `t`, and `x` is still a catch-all on a `@tas` subject. Patterns take terms, numbers, strings without `{…}`, ships, loobeans and `~`, and cells of patterns, which nest; not `~[…]` lists or `a+b` pairs. A number pattern is a `@ud` too, so `0` can't match a `@p` or a `@dr`: write `~zod`, or compare a duration with `eq`.
185195
186196| Pattern | Matches | Binds |
187197| --- | --- | --- |
@@ -192,11 +202,15 @@ Arms are tried in order. Every case needs an arm or a catch-all, `*` or a bare n
192202| `[%move %left n]` | Tagged `%move`, then `%left` | `n` |
193203| `~` | Null | Nothing |
194204| `[~ x]` | A unit holding a value | `x` |
205+| `[[~ a] [~ b]]` | A pair of units that both hold a value | `a`, `b` |
206+| `[x ~]` | A list of one item | `x` |
195207| `1.000`, `"milk"`, `~zod` | That literal | Nothing |
196208| `[a b]` | Any cell; `b` is the rest | `a`, `b` |
197209| `*` | Anything | Nothing |
198210| `x` | Anything | `x` |
199211
212+Cells nest, so one arm can look into several values, or a list's first cells. A cell pattern matches from the left, and its last pattern takes the rest: over `[(unit A) (unit A)]`, `[~ b]` means "the first is null", with `b` the second unit, not "a unit holding `b`". Keep every position visible, as `[* ~ b]`.
213+
200214Tags can sit anywhere in a case, and a case can carry several:
201215
202216```jibb
@@ -209,11 +223,11 @@ Tags can sit anywhere in a case, and a case can carry several:
209223
210224++ describe |= s=step
211225 ?- s
212− [%move %left n] "left {n}"
213− [%move %right n] "right {n}"
214− [t %draft] t
215− [t %sent sent-at] t
216− %stop "stop"
226+ [%move %left n] "left {n}"
227+ [%move %right n] "right {n}"
228+ [t %draft] t
229+ [t %sent sent-at] t
230+ %stop "stop"
217231```
218232
219233Leaving out `%stop` is an error naming it; to crash instead, write `%stop !!`.
@@ -235,14 +249,21 @@ definition = "+$" name [ generic ] ( mold | cases )
235249generic = "|$" "[" typevar { typevar } "]" ;
236250cases = INDENT mold { NEWLINE mold } DEDENT ; (* one case is that mold; more make a union *)
237251
238−body = INDENT { definition NEWLINE } expr DEDENT ;
252+body = INDENT rest DEDENT ;
253+rest = { definition NEWLINE } last ; (* a body's lines, to its DEDENT *)
254+last = expr
255+ | head NEWLINE rest (* the rest is the innermost rune's last child *)
256+ | "?-" expr NEWLINE arm { NEWLINE arm } ; (* arms at the ?-'s depth *)
257+head = { "|=" field | "^-" mold } ( "|=" field | "^-" mold | "~&" expr ) ; (* on one line *)
239258expr = rune | call ;
240259call = operand { operand } ;
241260operand = literal | qath | ref | change | pair | unit | group | list | tuple
242261 | gate | ctor | pathlit | "!!" ;
243262ref = wing ;
244263wing = name { "." name } ;
245−change = wing "(" item { item } ")" | wing "(" { item } open ; (* no space before "("; items named *)
264+change = wing "(" edit { edit } ")" | wing "(" { edit } elines ; (* no space before "(" *)
265+edit = wing "=" operand ; (* a name, or a wing through record fields *)
266+elines = INDENT wing "=" expr { NEWLINE wing "=" expr } DEDENT ;
246267pair = name "+" operand ; (* [%name operand] *)
247268unit = "`" operand ; (* [~ operand] *)
248269group = "(" expr ")" | "(" { operand } open ;
@@ -274,7 +295,7 @@ pathmold = "/" [ segment { "/" segment } ] ;
274295segment = knot | "[" name "=" ( aura | "_" ) "]" ;
275296
276297pattern = term | number | string | ship | loobean | "~" | "*" | name
277− | "[" pattern { pattern } "]" ;
298+ | "[" pattern { pattern } "]" ; (* a name can't spell a tag the subject has there; see Patterns *)
278299
279300literal = number | string | ship | date | duration | knotlit
280301 | term | loobean | "~" ;
@@ -283,7 +304,7 @@ pathlit = "/" knot { "/" knot } ;
283304term = "%" name | "%" decimal | "%&" | "%|" | "%$" ;
284305loobean = "%.y" | "%.n" ;
285306aura = "@" { lower } [ upper ] ;
286−typevar = upper ;
307+typevar = upper { lower | digit } ;
287308name = lower { lower | digit | "-" } ;
288309knot = { lower | digit | "-" | "." | "~" | "_" } ;
289310```
@@ -298,11 +319,11 @@ knot = { lower | digit | "-" | "." | "~" | "_" } ;
298319 %toggle
299320
300321++ main (store init update)
301−++ init ^- state [~ %.n]
322+++ init ^- state [items=~ open=%.n]
302323++ update |= [a=poke s=state]
303324 ?- a
304− [%add item] s(items=[item items.s])
305− %toggle s(open=(not open.s))
325+ [%add item] s(items=[item items.s])
326+ %toggle s(open=(not open.s))
306327```
307328
308329```jibb
@@ -320,15 +341,15 @@ knot = { lower | digit | "-" | "." | "~" | "_" } ;
320341 [%acked err=(unit @t)]
321342
322343++ init |= ~
323− [[~ %.n] ""]
344+ [cart=[items=~ open=%.n] note=""]
324345
325346++ update |= [=msg m=model]
326347 ?- msg
327− [%noted t] [m(note=t) ~]
328− %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
329− %toggle [m ~[(poke.cart %toggle |=%acked)]]
330− [%got c] [m(cart=c) ~]
331− [%acked err] [m ~]
348+ [%noted t] [m(note=t) ~]
349+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
350+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
351+ [%got c] [m(cart=c) ~]
352+ [%acked err] [m ~]
332353
333354++ subs |= m=model
334355 ~[[%watch (state.cart |=%got)]]
docs/spec/overview.md+9−9
@@ -465,18 +465,18 @@ A `page`: each request scries `%blog` and renders in Nock.
465465 [%acked err=(unit @t)]
466466
467467++ init |= ts=(list item.todo)
468− [ts "" ~]
468+ [todos=ts draft="" error=~]
469469
470470++ update |= [=msg m=model]
471471 ?- msg
472− [%typed t]
473− ?- (gth (lent (tuba (trip t))) 80)
474− %.y [m(draft=t error=`"Too long") ~]
475− %.n [m(draft=t error=~) ~]
476− %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
477− [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
478− [%got ts] [m(todos=ts) ~]
479− [%acked err] [m(error=err) ~]
472+ [%typed t]
473+ ?- (gth (lent (tuba (trip t))) 80)
474+ %.y [m(draft=t error=`"Too long") ~]
475+ %.n [m(draft=t error=~) ~]
476+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
477+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
478+ [%got ts] [m(todos=ts) ~]
479+ [%acked err] [m(error=err) ~]
480480
481481++ subs |= m=model
482482 ~[[%watch (todos.todo |=%got)]]
docs/status.md+269−289
@@ -1,11 +1,13 @@
11# Status
22
3−As of 2026-11-02. The plan is [spec/implementation-plan.md](spec/implementation-plan.md); each milestone ends with its checks passing on a fake ship.
3+As of 2026-11-03. This file lists what Jibb does now, whether each part is done, partial or missing, and the test or check that proves it, then the known gaps. History is in git (`git log --oneline`). The plan is [spec/implementation-plan.md](spec/implementation-plan.md), and each milestone ends with its checks passing on a fake ship.
4+
5+## Milestones
46
57| # | Milestone | Status |
68| --- | --- | --- |
79| 1 | Parser and mark | Done (7c739b7; the doc's grammar decisions of 2026-10-30 in ab797a9) |
8−| 2 | Types and prelude | In progress. [prompts/milestone-2.md](prompts/milestone-2.md) briefs the developer; the checker and importer are partial |
10+| 2 | Types and prelude | In progress: the checker and the Hoon importer are partial. [prompts/milestone-2.md](prompts/milestone-2.md) briefs it. The [milestone 2 review](reviews/2026-11-03-milestone-2-review.md) of 2026-11-03 lists what the done-criteria still need, briefed in [prompts/milestone-2-finish.md](prompts/milestone-2-finish.md) |
911| 3 | Core language | Not started |
1012| 4 | Host and static pages: the first release | Not started |
1113| 5 | Published pages | Not started |
@@ -13,300 +15,278 @@ As of 2026-11-02. The plan is [spec/implementation-plan.md](spec/implementation-
1315| 7 | Tooling | Not started |
1416| 8 | Polish | Not started |
1517
16−The plan sets no dates: "agree them after milestone 1, once it shows how fast the Hoon work goes". They haven't been agreed yet. Milestone 1's commits run from 2026-10-29 18:13 UTC to 2026-10-30 11:50 UTC.
17−
18−On 2026-10-30, @iko decided that Jibb drops `$?`, so a `+$` takes a union's cases on the lines below its name. [prompts/drop-union-rune.md](prompts/drop-union-rune.md) records the change before milestone 2. The repository spec records the decision; the Claude document still needs to be synchronized.
19−
20−## Milestone 2: in progress
21−
22−The parser accepts `_` in mold positions and typed path segments, retaining each hole’s span. The partial checker tracks ordinary annotation holes through inference and requires each value or local definition to resolve its own holes before generalization. A hole can resolve to a concrete type or an explicitly written in-scope type variable; later uses cannot fix an unresolved definition. Independent decimal holes can default, but captured variables are not defaulted prematurely. Structural named molds with an unresolved hole report its site. Complex mold forms, inferred path segments, mutual recursive groups and other unsupported constraints still fail closed, and the fragment does not claim the module is checked. A syntax-tree pass rejects duplicate field names within each written record and reports both sites. The repository spec now records that `ask` and `qath` are transparent; complete request checking remains outstanding.
23−
24−On 2026-10-31, @iko chose explicit, result-directed `(proj record)` to construct a record with exactly the expected fields, and reserved `proj` against definitions and imports. The partial checker handles selected explicit calls with known, closed record types, records field-selection evidence for later lowering, and reserves the name across source bindings. Reordered fields, some nested contexts and several open or recursive cases remain unsupported; lowering and execution are not implemented yet. The field-order question remains open.
25−
26−The internal prelude also defines `qath` as a transparent recursive knot sequence, re-exported by the public prelude. The partial checker recognizes its source identity, supports selected null/cell construction and matching, and types static application-path literals. Construction and matching for other recursive shapes, broader patterns and dynamic application-path segments remain unsupported. A 256-step limit applies per inference attempt, not to parsing or retries; checking routes and static files remains milestone 4.
27−
28−The checker also recognizes a limited source-proven generic recursive tree in an import-free defining module. Its nominal identity retains the defining path, mold name and type arguments, including across supported imports and aliases. With a known expected type it can construct supported tagged cases by checking one source-proven layer at a time. Flat matches with explicit tags or nonbinding catch-alls also work for these source-proven trees, as does a missing-case diagnostic for a supported single-arm match. At most 128 arms are screened per attempt; whole-case binders and nested patterns remain unsupported. Broader pattern matching, general structural fits and gate-free proof remain unsupported; this is not yet the prelude's `element` implementation or island checking. The source index uses fixed-shape checks during mold collection. Each construction or supported pattern attempt has 256 unfolding steps and at most 4,096 face and substitution visits per scan; pattern subject recognition and view validation can each scan separately. Parsing, other inference and retries remain outside those limits. A single startup-inclusive comparison of 1,000 ordinary gates produced identical reports and used 29.12 seconds of user CPU before the shared-resolver refactor and 28.55 seconds after it, with other work running; it is not a general performance bound.
29−
30−A bounded local source proof recognizes a narrow class of generic-alias union cases with different literal heads, then applies the ordinary mold checks. Nested or qualified aliases and several open states remain unsupported, including a valid alias used during the deferred transaction; the partial report states that the mold itself has not been checked. The `jibb-union-source` suite, `tests/lib/jibb-union-source.hoon`, exercises the source and state bounds and failure paths under eval (`tools/test-arms jibb-union-source`) and on the ship (`tools/ship test`). A separate bounded witness now reports proven collisions between supported literal-headed aliases, with both original case sites; unknown payload intersections still decline. The detailed full-module result now carries the first failed mold’s source-bound overlap evidence, including through ordinary Jibb imports; the legacy text result renders both case excerpts. Specialized API and prelude paths remain limited. The shared guards pass under eval and on the ship.
31−
32−The 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.
33−
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. The `jibb-deferred-prepared` suite, `tests/lib/jibb-deferred-prepared.hoon`, 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−
36−Closed 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 remaining cross-definition context or complete island-kind and watchability checks needed by the unchanged todo island.
37−
38−The 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 general island watch checking remain unimplemented; the separate direct-program proof below covers only one narrow static value shape.
39−
40−The public prelude now contains the source-backed UI length/attribute molds, all element constructors, and exact program/page records and builders. The full 19-case generic `element` union is nonrecursive: nested child, keyed-item and table payloads are `*`, while public constructor schemes preserve typed composition and independent key types. `island` returns `(element !!)` with `[program data]` as its erased payload. The focused UI golden checks exact schemes, static and message-bearing composition, concrete programs/pages/islands, malformed inputs and selected mismatches. A child-message mismatch fails closed as an unsupported constraint. Raw-constructor encapsulation, duplicate-attribute checks, rendering, storage, navigation and execution are not claimed.
41−
42−The remaining doc fragments now also have full detailed and legacy checks: the import-only module resolves its real `/sur`, mark and Jibb-module inputs; `view-day` and `step` check with their exact exported schemes; and the `cmd`/`sub` block checks at the prelude path against the canonical printed schemes. Additional consumers use all three imported names, and the shared eval/ship fixture rejects missing `/sur`, mark and Jibb-module inputs.
43−
44−The documented buttons library now fully checks its valid `labelled` and `wide` definitions with their exact generic element and attribute-list schemes. Ordinary positional calls unify a variable argument with the body of an expected faced sample slot without propagating that slot face. When full checking would otherwise reject an incomplete module, a failure-only retry of at most 64 missing definitions can report a still-pending tag at its source; the unchanged buttons module thus reports that nothing fixes the union of `%add`, with the actual excerpt, through both detailed and legacy inference. Successful checks do not run that retry. The shared eval/ship fixture is type checking only and claims no UI runtime.
45−
46−The public prelude now defines the exact documented `theme` record, including required text tokens, an optional `qath` font and optional dark tones. A shared eval/ship fixture fully checks the byte-identical `my-app/ui/theme.jibb`, checks its exact exported type and structural downstream import, and covers absent dark tones plus wrong nested auras, missing fields and wrong font/dark types. On 2026-11-01, @iko chose explicit backtick syntax for present units, and the documented dark record now uses it. No contrast check, rendering, routing or other theme behavior is implemented.
47−
48−Known same-origin generic-union result context can now constrain a call before its arguments are inferred. An unresolved or opaque constructor target stays unsupported rather than producing a definite mismatch; proven missing tags still report errors. A todo request with explicit `(ask msg)` context can infer `|=%got`; its uncontextualized form remains unsupported. A two-item literal-headed tuple can receive payload context from a known union of uniquely headed literal cells when its payload is a shallow wing-headed call with literal, wing or constructor arguments. Existing inference takes precedence when it fits; otherwise the checker tries the contextual path once. It conservatively declines that path when any substitution has a structural root, as well as for duplicate or opaque competitors. The guard scans substitutions per eligible tuple and may add one shallow inference; no global linear-time bound is claimed. This allows an explicitly typed todo subscription body to infer, but does not check the island or prove request watchability.
49−
50−A separate source-backed analysis can prove one named mold gate-free, report a definite gate with a field path, or return unknown. It retains the prepared prelude, source bundle, reader results and resolved imports; the actual todo model proves gate-free, while a callback field reports its path and `*` remains unknown. Its classifier is capped at 256 nodes, not the surrounding parse and import work. API, store and private roots are unsupported, and the artifact does not check a module or island, infer generalized constraints, or prove watchability.
51−
52−The partial checker can also match a directly named, checked root gate against a generic gate sample in a direct, unshadowed source-backed prelude call. It uses the written two-slot sample layouts to preserve nested record faces, then requires the complete call samples to be closed and tag-free and repeats the fit under the final substitution. The proof falls back to existing inference for unavailable or ambiguous source layouts, local or dynamic gates, aliases, recursive placeholders and open generic caller types. It preserves written-capital checks and projection evidence; it does not add `program`, check islands or prove request watchability. Prepared prelude source and interface remain a trusted pair.
53−
54−A narrow full-module path now checks direct four-wing `(program init update view subs)` definitions named `main`. It requires the canonical prepared `program` value and mold, reuses ordinary source-backed program fitting, and publishes only after all ordinary module and request-graph checks. The inferred `main` must be closed and invariantly match the instantiated `program` mold. Initializer data and model must be closed and gate-free with `%yes` verdicts inside a shared 256-node budget. `subs` may syntactically return null through transparent forms, or one direct imported request watch after the request graph merges. The latter is only an unfaced two-item `[%watch (case.face |=%callback)]` singleton: the imported member must have the exact plain derived-request scheme, a unique merged request must match the API path and both case names and occur in the interface's own graph, the API source must be identical, and scry, diffs and parameters must be absent. Pure or hand-built values, helpers, aliases, re-exports, typed paths, folds, multiple watches and unknown or ambiguous evidence remain rejected. Checked interfaces retain source evidence and support ordinary downstream imports; no program execution or runtime watching is claimed. A transactional extension can recover a direct initializer when update, view and subs are already resolved: it infers the initializer against the closed model that update's two-item sample, or else main's own program fit, establishes, then re-infers `main` under all ordinary finalization and kind checks. Any body and closed sample of a direct gate check this way; a body that context inference cannot take is inferred ordinarily as a whole gate. An update sample written as one faced mold, a pun, a named mold or generic in the model, and generic view and subs samples, also check. Non-main libraries, aliased mains or initializers, simultaneously unresolved subscriptions and unrelated pending tags remain rejected.
55−
56−Static and direct data-page `main` checking now completes the unchanged about page, blog index and todo index through the real Hoon readers. Static generic element mains specialize to closed canonical `(element !!)`; direct pages require a closed invariant `page` type and a direct plain derived-request load. Page loads reuse the strict source/member/evidence identity checks used by program watches, rejecting aliases, indirect/hand-built/pure/unknown requests, typed paths, diffs and store paths. The shared eval and ship fixture asserts exact main types and structural downstream imports. Rendering, runtime loading and request execution remain unimplemented.
57−
58−The prelude now has the approved `store` mold and action-checking builder. The runtime envelope is the transparent `raw-poke`; a store's local `+$ poke` remains its ordinary action mold throughout inference. Direct two-wing store mains require closed state and action molds, exact init/state and update relations, and no gate-free-state restriction. Stores export those molds plus derived generic `poke` command and state-request gates. The command helper checks the canonical `raw-poke`, `cmd` and `unit` shapes, takes an action and reply, and returns `(cmd M)` directly. Separate source-bound store certificates prove only the actual imported state member watchable; API evidence checks and page-load rejection remain intact. The unchanged cart and basket pass detailed and legacy checking with exact mains, derived schemes and structural imports, including non-keyed view and null-sample initializer recovery. Multi-action declarations, lowering and runtime execution remain unsupported.
59−
60−Keyed programs no longer skip ordinary component inference: an annotated initializer that checks normally is accepted, with recovery reserved for definitions that still need it. The todo fixture's initializer is a gate cast to its full type, which only ordinary inference accepts, so it fails if the skip returns; it checks through detailed and legacy inference, including on the ship.
61−
62−Imported Hoon `(unit T)` now converts to the validated canonical prelude `unit` when that template is supplied, instead of remaining an incompatible collection. Conversion recurses through imported unions and collections, and API path/diff/poke analysis uses the same prepared reader. The fixtures prove identity, `fall`, `need`, `(unit @t)` casts, union- and list-nested matching, canonical unit-typed API full/diff marks and a canonical direct-poke export while preserving the no-prelude compatibility report and wrong-collection rejection. Nested public re-export labels also remain `ask`, `qath` and `raw-poke` instead of leaking their private `.internal` suffixes into printed types.
63−
64−Uncontextual `?-` result joining now uses one rule for loobean, unit, list and known-union branches: unify and retain substitutions first, then widen only to an explicitly present parent aura or `@`. Multi-arm folds select an explicitly present parent independently of arm order and bind variables to that final parent; deferred boolean branches retain their pending-literal fallback, and sibling auras remain distinct without a present common parent. Valid recursive local branches that were rejected by the old per-kind screens now infer, while pending tags and distinct type variables retain definite diagnostics.
65−
66−The component-local program recovery now covers update, subscriptions, one direct keyed `each`/`turn` mapper and its view, then the existing initializer and ordinary `main` path. Each recovered scheme is closed and freshly allocated; non-gate views decline safely. Canonical `element` recursion and exact singleton-case list fits are narrowly guarded, with successful ordinary fits taking precedence. The byte-identical unchanged todo now passes both detailed and legacy full-module checks with an exact closed `main` type and structural downstream import. Wrong models, messages, results, mappers, keys, aliases, non-gate views and watches fail closed. This is static checking only: no Jibb execution or runtime watching is claimed.
67−
68−The API path analyzer can retain its source, complete prepared prelude, reader results and resolved dependencies as evidence, and classify a unique declaration as watchable, not watchable or unknown. This remains declaration evidence rather than proof about an arbitrary request value. The narrow direct-program check above composes it with final value syntax, resolved imports and merged evidence for one plain request. Prepared artifacts and reader results remain trusted host inputs.
69−
70−For a unique supported path declaration, the request-parts analysis derives ordered typed path parameters, a full-state reply sample and a fold type for one diff mark. Multiple diffs and unsupported or ambiguous evidence fail closed. By itself it does not create request gates or establish watchability of values.
18+The plan sets no dates ("agree them after milestone 1, once it shows how fast the Hoon work goes"), and none have been agreed yet. Milestone 1's commits ran from 2026-10-29 18:13 to 2026-10-30 11:50 UTC.
7119
72−A separate supporting-definition analysis infers supported ordinary API molds and values and resolves all declared marks, retaining their source and dependency evidence. It fails closed on unsupported helpers or marks; unused `/-` cores are not independently validated, and definitions depending on derived gates remain unsupported. This does not check or export the whole API.
20+Decisions the Claude doc does not have yet, such as dropping `$?` ([prompts/drop-union-rune.md](prompts/drop-union-rune.md)), explicit `proj`, the `like` gate and backtick units, are rows of [spec/decisions.md](spec/decisions.md) whose Synced column says No (rows of 2026-10-30 say Check: nobody has compared them yet). The parser already follows the `$?` decision. Until the doc is synced, the repository copy wins.
7321
74−Ordinary imports can infer derived request-gate types for multiple supported API paths. A case may take one typed segment before the reply or one diff fold after it; the unchanged todo API's plain, typed and diff requests infer, including a named closed fold. Checked ordinary API definitions, mark molds and a supported generic poke command helper are exported. Each `/sur` core must have a directly used, successfully read mold; unselected bindings are not independently validated. Jibb module imports, scry paths, multiple parameters or diffs and a parameter together with a fold remain unsupported. Source-qualified request evidence and exact trusted graph inputs survive transitive imports and cached interfaces, while stale or ambiguous evidence fails closed. This is a type-only interface: request execution, schema validation and proof that a request value is watchable remain unimplemented. In one loaded-machine run, the real-todo eval took 195.83 s wall and 67.83 s user CPU; the prior prototype took 111.81 s wall and 64.60 s user. Both include Hoon compilation and reader setup and overlapped other work, so they are not isolated checker benchmarks.
22+## Reading the tables
7523
76−The Hoon reader's tagged-union source proof also handles `$~` default wrappers. A shared eval and ship golden exercises the unmodified Tlon `epic.saga` mold as a named payload in a labeled downstream extension, alongside overlap, recursive, shadow and malformed-wrapper controls. The tagged-source helper peels at most four consecutive defaults; defaults inside dependency proofs spend the existing semantic-node budget. Other unverified nested unions and dependencies remain unsupported.
24+- Done: works as the row says, and the linked test or check proves it. Partial: works for the shapes named, and the words after the colon say what is left out or unproved. Missing: not implemented, or rejected on purpose; the link shows the current failure where a test pins it.
25+- Suite names link to `tests/lib/<suite>.hoon`, and case names to `tests/golden/<case>/`; a name with `*` stands for every case it matches. Every suite runs under `urbit eval` and on the fake ship.
26+- The checker has two entry points, and they can disagree. The full-module check, in its detailed and legacy forms, decides whether a module checks, and "checks" in this file means it. The partial inference report, which all 304 golden `types.txt` files print, starts "partial inference; module not checked" and declines more. For example, its report on the cart store leaves the store's kind and scope unresolved ([doc-grammar-06-cart-store](../tests/golden/doc-grammar-06-cart-store/)) and its report on the Grammar's buttons example says only "tag needs context" ([doc-grammar-02-buttons](../tests/golden/doc-grammar-02-buttons/)), while the full check passes the cart store ([jibb-store](../tests/lib/jibb-store.hoon)) and reports the buttons error exactly ([jibb-buttons](../tests/lib/jibb-buttons.hoon)).
7727
78−The repository spec records the subsequent type-system and prelude decisions, including the chosen `like` result-mapping gate; those changes also need synchronization to the Claude document. An initial inference fragment and a standalone Hoon type reader are being tested. The fragment explicitly reports that it does not check a module; partial bridges pass Hoon `*` in supported nonrecursive molds, selected Hoon atoms, term singletons, the null singleton, the two loobean singletons and their exact fork, nested faced or unfaced cells, supported disjoint unions and opaque standard collections from `/sur` molds and marks into inference. Collections retain their names and supported arguments for printing and unification; nested supported union arguments are retained too. The bridge trusts unchanged results from the source-aware reader; a materialized type graph alone cannot reveal cases Hoon already collapsed. The source-validated standard prelude `list` mold shares this representation with imported lists; other Jibb-written collection molds and most prelude collection operations remain unsupported; malformed names and arities fail closed. Selected self-recursive `/sur` molds, including Tlon `notes.import-node` with list-wrapped self references, cross as opaque module-and-name identities; aliases, foreign references, recursive marks, unfolding and construction remain unsupported. The reader handles mark samples, including a source-proved nonrecursive union from a single Ford-imported `/sur` core, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, including source-validated named operands such as Tlon `notes.log`, certain ordered-map fields, direct `$^` unions whose cases can be proved disjoint, and one verified explicit union argument in a list, set, map or unit. Tagged `$%` cases can additionally use restricted local named payload molds, bare `~` fields and one level of local named tagged unions, as in real Tlon `notes`, with bounded source proof; unsupported or ambiguous dependencies fail closed. Ambiguous recursive origins fail closed; recognizable explicit unions are checked from source before Hoon can collapse their cases, as @iko confirmed for imported `$%`, `$?` and `$^`, while other nested unions, nested ordered maps, general union disjointness and complete import integration remain unfinished. Opt-in structured reader APIs preserve successful graphs and distinguish definite unsupported-aura and core evidence from failures the reader cannot prove; unverified union disjointness and name-only vase recognition remain unsupported. They revalidate and re-walk failed types. An opt-in partial checker entry point consumes unchanged reader results and reports definite aura or core errors at imported mold use sites when their inputs are unique. Ordered replay covers nested cell samples, record and function casts, and non-generic same-module aliases; unsupported prefixes, cycles and shadowing stop it. Union molds, generic applications, transitive modules and unsupported reader outcomes remain generic. Replay repeats inference and may add work. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and a source-derived partial prelude interface, caches completed interfaces per run, detects missing sources and cycles, and resolves nested fields of imported values with independent scheme instantiation. The source-backed internal prelude defines `poke` and the public prelude re-exports it as a transparent type. A dedicated trusted preparation path supplies private comparison and arithmetic schemes to the Jibb-written `gth`, `add` and `dec` wrappers; ordinary imports cannot access them. The public `add` and `dec` wrappers use private arithmetic interfaces; supported inference preserves the shared atom constraint that excludes loobeans. Primitive execution, jet recognition and length remain unfinished. The partial checker resolves its supported source shape and rejects ordinary imports of the private path. An imported API with one mark and a matching direct `+$ poke` declaration can export a constructor and retain agent/mark metadata when the representation has the supported agent case. A separate partial analysis resolves supported API path declarations and their full and diff mark types, including the todo paths; it does not by itself create requests or check an API module. Ordinary imports additionally infer the supported multi-path request-gate types described above. Complete private module checking, other API shapes, request lowering, root API and kind checking, stores, complete `ask` and `pure` checking and runtime effects remain unfinished. A possible store or root API with `+$ poke` reports unsupported kind or scope, while definite duplicates and unrelated shadowing still report conflicts. The prelude includes the doc-exact generic `cmd` union; the prelude inventory is incomplete. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, generalized atom constraints arising from explicit capitals or bare sample binders, acyclic local value definitions with captures, selected single self-recursive top-level and local gates, simple and nonrecursive generic mold aliases, selected faced record casts and field reads, and contextual tags, `~` and constructors for closed disjoint unions, including direct nonrecursive generic unions and propagation through complete loobean and unit-shaped branches in casts and known union-sample calls, including nested branches. Known loobean result context also propagates through supported complete branches and binder-only cell arms; binder-only arms over union subjects remain unsupported. A directly known named union can instantiate an unconstrained generic gate sample with its origin, generic arguments and faces preserved; unnamed, pending, recursive and variable-bound cases remain unsupported. A known gate with an unresolved result variable can receive a known enclosing result type before its arguments are inferred; unknown calls and unresolved targets remain conservative. Multi-argument calls form a right-nested sample, retain known faces and shared type variables, and can use known sample positions to contextualize list and union arguments. A definite mismatch points to the failing argument when the fragment can establish it, otherwise to the combined sample; unsupported contextual forms still fail closed. For a supported recursive gate, the checker infers the sample first and uses its exact type, including field faces, for one monomorphic self reference. It generalizes after the body is checked; subsequent uses instantiate it independently. Incompatible recursive arguments can report the gate and argument sites. For a complete loobean branch with one direct self-call arm, a separately inferred closed base type can seed the recursive result before the whole body is checked. Open or pending base types do not seed it; other branch shapes remain subject to the fragment’s existing limits. A supported single local recursive gate also uses a monomorphic self reference and generalizes variables free of the enclosing environment after checking its body; captured variables remain shared. The checker collects written capitals per `++` before inference, excluding nested definitions: a capital used in an enclosing definition is shared with its locals even when written later, while a capital introduced only in a local definition is generalized there. Sibling locals can introduce independent capitals with the same spelling; generic mold parameters keep their own scope. Top-level groups of syntactic gates are inferred together with monomorphic placeholders and shared substitutions, then generalized only after the whole group checks; downstream uses and library interfaces instantiate those schemes independently. A dependency graph identifies groups with two iterative depth-first passes; its conservative local-reference edges can reject otherwise valid programs. Supported local mutually recursive gate groups also use shared monomorphic placeholders and generalize only after the group checks, preserving captured outer variables. A bounded dependency proof reports certain non-gate cycles through values and gates when an explicit atom or loobean result cast and simple unshadowed expressions establish the cycle. Other mixed gate/value cycles, polymorphic recursion, unresolved literal constraints and unresolved branch joins remain unsupported. Reporting repeats inference for a single recursive gate outside a group; grouped reports use the stored schemes. Its performance cost remains unmeasured. A single-arm cell pattern accepts two or more binders, the last capturing the remaining tail; duplicate and shadowed binders are rejected. A structured single-arm pattern also works for a known non-union cell when coverage is proven, including nested literal and wildcard positions. Intermediate union or collection tails, nested patterns, wildcards and faced records remain unsupported. String interpolation accepts known atom auras, unrestricted `@`, tapes and isolated decimal literals; a known cell asks for a printer, and an explicitly generic atom asks for an aura. Loobeans, term singletons, non-tape collections, open types and a type fixed only later remain unsupported. A known closed union with two or more arms supports patterns that provably cover or exclude each remaining case, including payload binders, imported and generic cases, and binder-free catch-alls. Partial boolean patterns can split known `?` positions into their two noun values, up to 64 alternatives across the union; binders retain their original case type. Missing alternatives and covered arms are reported. Other partial patterns, expansions above the limit, binders spanning distinct cases, differing arm result types and some complex two-arm subjects remain unsupported. A cast or known call sample can supply result context through whole-case arms and supported finite loobean refinements for a known union accessed by a wing, a grouped wing or a supported shallow call, including nested cell and list positions; other partial-pattern contexts and subject forms remain unsupported. The Grammar’s `step` block infers in this fragment, but its module is not yet checked. A bare tag proved absent from a known union reports the union and tag sites in casts, single-argument calls, unit payloads, list items and supported branch arms; imported unnamed unions print their cases. Ordered fit replay can identify a missing tag nested in a syntactic tuple, stopping at an earlier mismatch or uncertainty. Known faced records support uniquely named field changes, including nested wings, with field context passed to replacements and the original record type retained. Missing fields, empty changes and definite mismatches report sites; the expected-type site is the edit because the original field declaration location is not retained. Unknown or partly unfaced spines, ambiguous fields and repeated edits remain unsupported. A known record cast supplies field context to its tuple or record initializer, including nested list and union fields; mismatch diagnostics use the cast mold because the original field declaration location is not retained. Isolated cart-style `init` and `update` expressions infer, while the complete cart-store fails closed because its kind and declaration scope remain unchecked. Uncontextualized list literals infer a fresh element type, including empty and nested lists, with independently generalized uses. Unresolved item tags and uncertain widening remain unsupported. Backtick unit construction uses the validated standard prelude unit template, infers its payload without losing pending constraints, and makes the prelude’s `some` available. Ordinary result annotations also let its `bind`, `biff`, `both`, `clap`, `clef` and `flit` infer. A known unit in a cast, call, list item or record field supplies context to its payload, including nested units and lists; mismatches identify the payload and context. Unrelated union identities, some variable-dependent fits, and missing or altered prelude unit templates remain unsupported. Literal singleton heads compare by runtime noun, so `|=%$` also matches explicit null- and loobean-zero-headed cases. When equal heads have disjoint payloads, the constructor selects a uniquely proven compatible payload; unknown and ambiguous candidates remain unsupported. Unresolved nulls remain pending and are reported separately from tags. A known union of `~` and a null-headed cell supports a complete `~` / `[~ value]` branch in either order, including shadow checks; unknown subjects, missing or duplicate arms, and unresolved branch results remain unsupported. This fragment infers the prelude’s `fall` and `need` signatures. With the validated prelude list and a known cast or gate sample, empty, nonempty and nested list literals infer their element types, including contextual union tags; a mismatched element names both sites. In that context `~` and zero-valued terms fit an empty list, and two-item unfaced cells form cons lists, including nested cons and imported-list contexts; invalid heads or tails name both sites. A known gate sample also supplies context to matching positions in a single tuple or record argument, including nested cells; zero literals can fit list positions. A bound zero constant remains unsupported rather than a definite mismatch, and an unknown callee does not supply context. Faced or longer cells and a missing or altered prelude list fail closed. A known list result also supplies context through complete loobean, unit-shaped and list-shaped branches, including recursive and nested branches. For a known standard list with a supported element type, a complete `~` / `[item rest]` branch infers the element and tail types in either arm order and checks binders for shadowing. Unknown subjects, unsupported element types and other or incomplete list patterns remain unsupported. A value with type variable `A` can fit a field whose type is that same `A`, including in generic union payloads and nested or repeated record fields. Other variable-dependent face merges remain unsupported. Forced equality of distinct written capitals now reports both source sites, following @iko’s decision; forcing one to a concrete type remains unsupported. Imported record spines with repeated faces fail closed where used, but only with a generic unsupported diagnostic. Hoon may erase unfaced nested-cell boundaries, so the check can conservatively reject valid names in distinct erased scopes. Supported closed unions print using an in-scope name or imported alias; an unnamed nongeneric union prints its cases, parenthesized when nested. The latter is print-only. Generic union types retain all arguments in their printed name; if that name is unavailable, the partial printer reports the limitation. Different import faces for the same origin remain compatible; compatibility across distinct union origins and some generic-argument comparisons remain unsupported. Nonrecursive generic aliases can reorder, repeat or omit parameters while retaining a union’s origin, including through local scopes and library interfaces. A generic union declared directly inside a body remains unsupported, as do differing-variable face constraints in a union payload. A transitive generic union whose name is unavailable is reported as unsupported instead of hiding its arguments. Unfixed decimal literals default to `@ud` in gate-free inferred types; recursive molds, general branch tag context, other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; a wrapper regression also rejects forged subjects, samples and tails. Its golden fixtures include three real Tlon files. A Clay test passes a Ford-built nested union through the reader into partial inference. The partial prelude includes `murn`, `join`, `snip`, `rear` and the agreed shared-type `clap`; supported calls infer, while backend validation remains outstanding, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
28+## Parser and mark
7929
80−The prelude now writes `hunt` with the ordering gate first, matching the target Hoon's `(hunt ord a b)`. Its focused golden infers both ordering outcomes and absent units, and reports mismatched unit payloads and ordering-gate samples. Execution and jet recognition remain unverified.
30+These rows cover milestone 1. The plan's three done-when criteria are the rows on the doc examples, the lexical rules and `|commit`.
8131
82−The prelude now also writes `eq` and `mate`. A dedicated constrained variable retains `A contains no gates` through nested unification, canonicalization, instantiation and imports; atom constraints remain stronger. Direct and nested gate arguments fail, while open cell, face, collection and union members receive the constraint with bounded traversal and substitution updates. `set`, `map`, `mop`, `jar` and `jug` constrain only their key positions, leaving map values independent. The shared solver guards cover existing and later gate injection, exact traversal budgets and conservative budget fallback; backend equality and crash behavior remain unverified.
83−
84−The shared prelude interface reserves every name present in the supplied vendored source and makes only supported inferred entries available, including `list`, `unit`, `same`, `fall`, `need`, `bond`, `lure`, `weld`, `snoc`, `turn` and `lent`. The validated standard `list` mold is injected when the prelude’s own gates are inferred; `weld` and `turn` have ordinary explicit result casts. An absent or altered `list` is not injected, and an altered declaration cannot leak through direct or transitive mold aliases. The same validated template is available when prelude mold aliases are prepared, so supported direct and transitive aliases can use it. Unsupported entries such as most list helpers remain reserved but unavailable; backend validation of the helpers remains outstanding. All callers use the same prelude origin, so a library can export a type containing unqualified `(unit A)` to another module. The source-only `+prepare-prelude` rejects empty, malformed, conflicting or import-bearing source; `+prepare-prelude-with-internal` also accepts the supported private internal import. Prepared values are trusted and must come unchanged from the matching preparation arm. When canonical public list or unit templates are missing or altered, independently inferred private molds remain available, while molds that depend on those templates do not. The module-scope fixture compares the prepared and source-taking paths against the real prelude and a two-module golden under eval and on the ship. The source and checker remain incomplete, so this does not establish complete shadowing coverage or a checked module.
85−
86−The prelude has a Jibb-written `succ` gate that increments through `add`; partial inference retains its arithmetic atom constraint. A Hoon translation agrees with Hoon on ten selected inputs. Jibb execution and jet recognition remain unverified.
87−
88−The prelude has Jibb-written curried `lead` and `late` pair constructors, inferred with independent argument types including gate values. Their focused golden passes under eval and on the ship, and a Hoon-reference comparison covers operand order. Jibb backend execution remains unverified.
89−
90−The 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.
91−
92−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.
93−
94−The 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.
95−
96−An eval and ship fixture now reports partial inference for the unchanged todo island with its real API and Hoon readers. It verifies that the source fixtures match `my-app` and exercises missing or duplicate imports; the report does not claim the module or island has been checked. The prelude also has a Jibb-written recursive `lent` whose supported generic calls infer `@ud`. Execution and shape-based jet recognition remain future backend work. Nested union tests check equal runtime nouns, different nested tags, empty fields and unknown inhabitation.
97−
98−The prelude now writes `lth`, `gte` and `lte` in Jibb using `gth` and `not`. Supported generic and concrete calls infer, including loobeans; mismatched explicit auras fail. Execution, jet recognition and complete import checking remain unfinished.
99−
100−The prelude also writes `trip` and `tuba` over private primitives, with inferred cord, tape and UTF-32 list types matching the target ship's Hoon 135 definitions. Their composition with `lent` and invalid argument controls pass under eval and on the ship; primitive lowering, execution and jet recognition remain unfinished. In the unchanged todo report, `update` now reaches its remaining branch-context limitation instead of failing on missing text names.
101−
102−The Hoon reader can prove overlaps among supported original `$?` source cases, including nested cells and unions with more than two cases, and report them at a Jibb use site. It evaluates each case independently and compares runtime noun values. Other overlaps, Hoon case locations and mark-reader overlap diagnostics remain unfinished. The source screen allows at most 128 cases and 4,096 source noun nodes; dependency checking and pairwise witness analysis each have a separate 4,096-node budget. These budgets do not bound chapter lookup, Hoon evaluation or graph walks.
103−
104−Restricted-number promotion now skips an environment scan when a definition has no written capitals. In a single startup-inclusive pair on 2,000 independent gates, output was identical and user CPU fell from 71.67 to 38.26 seconds; wall time was 72.80 versus 51.66 seconds with other checks running. This is a partial-inference measurement, not a complete checker or a bound on dependent modules.
105−
106−## Milestone 1: parser and mark
107−
108−What the plan asks for, and where it is:
109−
110−| The plan | Where |
111−| --- | --- |
112−| The `%jibb` mark as the first tab gives it | `jibb-dev/mar/jibb.hoon`, as the doc writes it |
113−| The layout pass, emitting INDENT, DEDENT and NEWLINE | `+layout` in `jibb-dev/lib/jibb.hoon`, designed in its section 2 |
114−| A parser for the Grammar tab's EBNF that returns a syntax tree with source positions | `+parse` and `+parse-tokens`, section 3. Every node has a span, its start and end, and `+check-spans` tests the spans of every tree the golden tests print |
115−| Errors with file, line, column and an excerpt | `+show-error`, section 4.3. Each error points at the first character where the text stops being the start of any valid module (section 2.0) |
116−| Done when every Jibb code block in the doc parses | The doc labels its 14 Jibb blocks `jibb`. Each is a golden case, `tests/golden/doc-*`, and `tools/doc-blocks docs/spec` checks that they match. All parse; the one block written as an error, the Grammar's buttons example, has a type error for milestone 2 |
117−| Done when each lexical rule has a test input that breaks it | The `lex-*` golden cases: for each lexical rule, inputs that break it (`-bad-`), each with the error's expected place, and inputs that keep it (`-ok-`), except for the forms Jibb leaves out (the closers, blob and `@c` literals) |
118−| Done when `\|commit` stores `.jibb` files on a fake ship | `tools/ship check-commit`: 7 checks, from reading every file back byte for byte to three-way merges |
119−
120−Besides the plan's list:
121−
122−- 689 golden cases: 460 that parse and 229 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.
123−- The 689-case corpus passed under `urbit eval` in 107.0 s while other checks were running. The fake ship passed all 746 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 111.2 s and the ship's `-test` run took 316.7 s. 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.
124−- `tools/testdata/selftest` (23 checks) and `tools/testdata/ship-selftest` test the tools themselves.
125−- 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.
126−- Speed: starting `urbit eval` and building the library takes about 27 s with the dev tools' `!:`, and 24 s without it (`tools/hoon --no-debug`). 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).
127−
128−### History
129−
130−| Commit | Date | What |
32+| Area | Status | Proved by |
33+| --- | --- | --- |
34+| The `%jibb` mark: grab `mime`, `noun` and `txt`, grow `mime`, `txt` and `noun`, grad `%txt` | Done | [jibb-dev/mar/jibb.hoon](../jibb-dev/mar/jibb.hoon), `tools/ship check-commit` |
35+| `\|commit` stores `.jibb` files on a fake ship: 7 checks, from reading every `/ui` file back byte for byte to three-way merges and conflicts | Done | `tools/ship check-commit` |
36+| Layout pass: `+layout` (library section 2) emits INDENT, DEDENT and NEWLINE | Done | `lex-layout-*`, `lex-indent-*`, `lex-rune-layout-*` |
37+| Lexical rules: for each rule, inputs that break it, with the error's expected place, and inputs that keep it | Done: 148 `-bad-` and 57 `-ok-` cases; the left-out closers, blob and `@c` literals have only `-bad-` cases, and so does `lex-char` | `lex-*` |
38+| Parser: `+parse` and `+parse-tokens` (library section 3) turn the Grammar tab's EBNF into a syntax tree | Done | every golden `tree.txt` |
39+| The rest of a body (syntax review S2): a body's final line hands the lines after it at its depth to a tall `\|=`, `^-` or `~&` that ends it, and a `?-` that begins it may take its arms at its depth; arm, bracket, top-level and definition lines keep deeper bodies | Done: a body of 40,000 same-depth rest lines runs out of memory under eval, where 20,000 parse | `lex-body-rest-*`, [lex-rune-layout-ok-3](../tests/golden/lex-rune-layout-ok-3/) |
40+| Type variables longer than one letter (S7): a capital, then lowercase letters and digits; `AB`, `MSG` and `Msg_x` are errors | Done | `lex-typevar-*` |
41+| Unions without `$?`: a `+$` takes its cases on the lines below, and `$?` is an error | Done | [inline-union-wide](../tests/golden/inline-union-wide/), [inline-union-one-case](../tests/golden/inline-union-one-case/), `inline-hoon-union-*` |
42+| Spans: every node keeps its start and end, and `+golden` appends `SPAN ERROR` when `+check-spans` fails | Done | [jibb-check-spans](../tests/lib/jibb-check-spans.hoon), `tools/golden` |
43+| Parse errors: file, line, column, message, excerpt and caret (`+show-error`), at the first character where the text stops being the start of any valid module (library section 2.0) | Done: each failing case's `about.txt` states the position, except the unclear case below | `lex-*-bad-*`, `inline-*-bad` |
44+| Underlining with span ends | Partial: parse errors give a start only, and type errors name both sites with excerpts but mark each with one caret at its start | [jibb-check-spans](../tests/lib/jibb-check-spans.hoon), [types-multi-call](../tests/golden/types-multi-call/) |
45+| Type holes: `_` in mold positions and typed path segments (`[id=_]`), each with its own span; `_` stays a literal knot in `/_` and `%/_` | Done: holes in parameters, patterns and values are rejected | `parser-hole-*`, `types-hole-*` |
46+| Doc examples: the 14 `jibb` blocks in [spec/](spec/) (6 in grammar.md, 7 in overview.md, 1 in core-language.md) are golden cases, and all parse | Done | `doc-*`, `tools/doc-blocks docs/spec` |
47+| Golden corpus: 691 cases, 462 that parse and 229 that fail, each failure pinned to a line and column | Partial: eight `types-*` cases have no `expect:` line in their `about.txt`, which [development.md](development.md#golden-cases) asks for | `tools/golden` |
48+| The expected result of [inline-leftout-signed-float-auras](../tests/golden/inline-leftout-signed-float-auras/) | Partial: its `about.txt` says "expect: unclear" (grammar question 13); the outputs pin the layout pass's error at 1:7 | [inline-leftout-signed-float-auras](../tests/golden/inline-leftout-signed-float-auras/) |
49+| The 13 grammar questions never put to the doc's author | Partial: the parser follows provisional readings, listed in [open-questions.md](open-questions.md#grammar-questions-never-put-to-the-docs-author) | [inline-import-root-bad](../tests/golden/inline-import-root-bad/), [lex-indent-bad-3](../tests/golden/lex-indent-bad-3/) and others |
50+| Forms the parser leaves to the checker: `!! a`, the module kinds and an empty change `m()` | Partial: the partial checker reports an empty change ("a change takes at least one field") | [inline-crash-call](../tests/golden/inline-crash-call/), [inline-kinds](../tests/golden/inline-kinds/), [types-record-change](../tests/golden/types-record-change/) |
51+| `[]` as an error and `[a]` as `a`, as [spec/decisions.md](spec/decisions.md) decides (Cells) | Partial: the checker types `[a]` as `a`, but `[]` parses and the checker calls it unsupported, not an error; no case writes `[]` | [lex-tight-opener-bad-1](../tests/golden/lex-tight-opener-bad-1/) |
52+| Long and deeply nested input | Partial: library section 3 records 100,000 nested brackets and a 20,000-line module parsing, but no case, suite or check exercises them | none |
53+
54+Two independent audits came before 7c739b7: one 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. Neither audit's code nor its results are in the repository.
55+
56+## Types and prelude: full-module checks
57+
58+| Area | Status | Proved by |
59+| --- | --- | --- |
60+| Program `main`: a direct four-wing `(program init update view subs)`, closed and matching the canonical `program` mold invariantly | Done: generic mains, open messages, mismatched models, arbitrary mains, store paths and an aliased `program` are rejected | [jibb-program-main](../tests/lib/jibb-program-main.hoon), [type-program-main/source.txt](../tests/type-program-main/source.txt) |
61+| Initializer data and model: closed and gate-free, with `%yes` verdicts inside one shared 256-node budget | Done: a gate in the model or the data is rejected; no test exhausts the shared budget | [jibb-program-main](../tests/lib/jibb-program-main.hoon), [jibb-gate-free-guards](../tests/lib/jibb-gate-free-guards.hoon) |
62+| Initializer recovery: with update, view and subs resolved, a direct initializer is inferred against the model, then `main` is inferred again | Done: also when update's sample is a faced mold, a pun, a named mold or generic in the model, and with generic view and subs samples; the recovered model must be closed and tag-free | [jibb-program-init](../tests/lib/jibb-program-init.hoon), [type-program-main/initializer-unfaced.txt](../tests/type-program-main/initializer-unfaced.txt) |
63+| Recovery boundaries: non-main sources, init and subs unresolved together, unrelated pending tags, a `program` alias, a main that is not a program | Partial: all rejected in detailed and legacy checks; no fixture tries an aliased initializer (`++ init other`) | [jibb-program-init](../tests/lib/jibb-program-init.hoon), [jibb-program-main](../tests/lib/jibb-program-main.hoon) |
64+| Update recovery: an unannotated two-slot update takes its result type from the program, through a union and a loobean branch | Done: a wrong result, model or message, a malformed or three-slot sample, a non-main source, an unrelated tag, a missing `cmd` or `list`, and API and store paths are rejected | [jibb-program-update](../tests/lib/jibb-program-update.hoon) |
65+| Program `subs`: null, or one unfaced `[%watch (case.face \|=%callback)]` whose request has the exact derived scheme and matches the API's path, case names and source, with no scry, diffs or parameters | Done | [jibb-program-watch](../tests/lib/jibb-program-watch.hoon), [jibb-program-main](../tests/lib/jibb-program-main.hoon) |
66+| Other watches: pure or hand-built requests, helpers, aliases, typed paths, diff folds, several watches, unknown or ambiguous evidence | Missing: all rejected, but only unknown or ambiguous evidence by decision (settled question 33 in [spec/decisions.md](spec/decisions.md)); re-exports have no test | [jibb-program-watch](../tests/lib/jibb-program-watch.hoon) |
67+| Program interfaces keep their source evidence and work in downstream imports | Done | [jibb-program-main](../tests/lib/jibb-program-main.hoon), [jibb-program-watch](../tests/lib/jibb-program-watch.hoon), [jibb-todo-full](../tests/lib/jibb-todo-full.hoon) |
68+| The unchanged todo island: exact closed `main`, a cast-initializer variant and a structural downstream import | Done: wrong model, message, result, mapper, key, alias, watch and non-gate view are rejected | [jibb-todo-full](../tests/lib/jibb-todo-full.hoon), [type-todo-full/cast-init.txt](../tests/type-todo-full/cast-init.txt) |
69+| Component-local recovery of update, subs, one keyed `each`/`turn` mapper and view, before init and `main` | Partial: fresh allocation and the `element` and singleton-list guards are not asserted separately | [jibb-todo-full](../tests/lib/jibb-todo-full.hoon) |
70+| The partial report on the todo island, with its real API and readers | Done: missing or duplicate marks and a missing `/sur` are rejected; the report still declines `main`, init, update, subs, view and row-of | [jibb-todo-partial](../tests/lib/jibb-todo-partial.hoon), [type-todo-partial/expected.txt](../tests/type-todo-partial/expected.txt) |
71+| Pages: the unchanged about page, blog index and index page, with exact `main` types and downstream imports; the about page is `(element !!)` | Done | [jibb-page-main](../tests/lib/jibb-page-main.hoon) |
72+| Page loads, through the same derived-request identity check as program watches | Done: builder aliases, indirect, pure, hand-built and unknown requests, typed paths, diffs and store paths are rejected; no test puts a request alias in a load | [jibb-page-main](../tests/lib/jibb-page-main.hoon) |
73+| Stores: the unchanged cart store and basket, as direct two-wing mains with exact schemes and structural imports | Done: wrong init, action or result, name collisions, aliases and forged evidence are rejected; state holding gates is accepted | [jibb-store](../tests/lib/jibb-store.hoon) |
74+| Store exports: state and action molds, a derived generic `poke` command helper returning `(cmd M)`, and state requests | Done: a noncanonical `cmd`, `unit` or `raw-poke` is rejected | [jibb-store](../tests/lib/jibb-store.hoon) |
75+| Store watchability: source-bound store evidence, merged into the basket's graph | Partial: indirect state requests and a store state used as a page load are rejected | [jibb-store](../tests/lib/jibb-store.hoon), [jibb-api-evidence](../tests/lib/jibb-api-evidence.hoon) |
76+| Store scope: a definite duplicate `+$ poke` or unrelated prelude shadowing | Partial: reported as a conflict; a possible root API's `poke` is left unchecked, and no test asserts the "module kind or scope" message | [jibb-store](../tests/lib/jibb-store.hoon), [types-scope-store-duplicate](../tests/golden/types-scope-store-duplicate/), [types-scope-store-shadow](../tests/golden/types-scope-store-shadow/), [types-scope-root-api](../tests/golden/types-scope-root-api/) |
77+| Theme: the real `my-app/ui/theme.jibb`, with backtick units, against the prelude's `theme` | Done: absent dark tones check; a wrong nested aura, a missing field and a wrong font or dark type are rejected | [jibb-theme](../tests/lib/jibb-theme.hoon), [doc-overview-02-theme](../tests/golden/doc-overview-02-theme/) |
78+| Buttons: `labelled` and `wide` with exact generic schemes, and the unchanged module's "nothing fixes the union of %add" at 3:16 with its excerpt | Done: the retry that finds the tag runs only on an incomplete module, and its fuel of 64 counts every definition visited | [jibb-buttons](../tests/lib/jibb-buttons.hoon), [type-buttons/error.txt](../tests/type-buttons/error.txt) |
79+| Doc fragments: the import-only module (real `/sur`, mark and Jibb module), `view-day`, `step` (`describe: $-(step @t)`) and the `cmd`/`sub` block at the prelude path | Done: missing `/sur`, mark or module inputs are rejected | [jibb-doc-examples](../tests/lib/jibb-doc-examples.hoon) |
80+| Generic-alias unions: a bounded local source proof of cases with different literal heads, then the ordinary mold checks | Done: the full check accepts the module, though its partial report says "mold not checked" | [jibb-union-source](../tests/lib/jibb-union-source.hoon), [type-union-source/good.txt](../tests/type-union-source/good.txt) |
81+| Generic-alias unions through nested or qualified aliases, structured or pending states, recursive-index states or the deferred transaction | Missing: declined | [jibb-union-source](../tests/lib/jibb-union-source.hoon) |
82+| Generic-alias overlaps: a bounded witness reports proven collisions with both case sites, and the module stays rejected | Done: unknown or opaque payload intersections, wrong arity, duplicate and qualified owners and short fuel decline | [jibb-union-alias-overlap](../tests/lib/jibb-union-alias-overlap.hoon), [jibb-full-overlap-basic](../tests/lib/jibb-full-overlap-basic.hoon), [jibb-full-overlap-graph](../tests/lib/jibb-full-overlap-graph.hoon) |
83+| Full-module overlap evidence: the first failing mold's source-bound evidence, through imports, with both excerpts in the legacy text | Partial: not on the specialized API and prelude paths | [jibb-full-overlap-basic](../tests/lib/jibb-full-overlap-basic.hoon), [jibb-full-overlap-graph](../tests/lib/jibb-full-overlap-graph.hoon) |
84+| Complete private module checking, other API shapes, root API and kind checking, complete `ask` and `pure` checking | Missing | none |
85+
86+## Types and prelude: requests and API analysis
87+
88+| Area | Status | Proved by |
89+| --- | --- | --- |
90+| API paths: supported path declarations and their full and diff mark types, including the todo paths | Done: unknown scry parameters, bad marks, a wrong path, a missing prelude, private imports and cycles fail closed; it creates no requests | [jibb-api-paths](../tests/lib/jibb-api-paths.hoon), [type-api-paths/expected.txt](../tests/type-api-paths/expected.txt) |
91+| Path evidence: source, prepared prelude, reader graphs and dependencies; a unique declaration is watchable, not watchable (scry) or unknown | Partial: declaration evidence only, not proof about a request value | [jibb-api-evidence](../tests/lib/jibb-api-evidence.hoon) |
92+| Request parts: ordered typed parameters, a full-state reply sample and a one-diff fold | Done: several diffs, a missing or duplicate case, missing evidence and unknown auras fail closed | [jibb-api-evidence](../tests/lib/jibb-api-evidence.hoon) |
93+| Supporting definitions: ordinary API molds and values, and every declared mark with its source and mark-graph evidence | Partial: unused `/-` cores are not validated, dependence on derived gates is unsupported (noted only in code), and the whole API is neither checked nor exported | [jibb-api-evidence](../tests/lib/jibb-api-evidence.hoon) |
94+| Request gates through ordinary imports: several API paths, one typed segment before the reply or one diff fold after it; the todo's plain, typed and diff requests, including a named closed fold | Done | [jibb-todo-api](../tests/lib/jibb-todo-api.hoon), [jibb-request-guards](../tests/lib/jibb-request-guards.hoon), [types-request-normal](../tests/golden/types-request-normal/) |
95+| Request gates for Jibb module imports in an API, scry paths, two or more parameters or diffs, a parameter with a fold | Missing: only two parameters and two diffs are tested; the rest is rejected in code (`api-request-gates`, `multi-request-interface-graph`) | [module-import-api-request-reason](../tests/golden/module-import-api-request-reason/), [type-todo-api/unsupported.txt](../tests/type-todo-api/unsupported.txt) |
96+| Request evidence through diamond and transitive imports and cached interfaces | Done: changed sources, stale caches and duplicates fail closed or rebuild | [jibb-request-guards](../tests/lib/jibb-request-guards.hoon) |
97+| API exports: the real todo API's checked definitions, mark molds and derived poke and request members, with a request certificate | Partial: unselected `/sur` bindings are not validated | [jibb-todo-api](../tests/lib/jibb-todo-api.hoon), [jibb-poke-bridge](../tests/lib/jibb-poke-bridge.hoon) |
98+| API poke export: one mark and a matching direct `+$ poke` give a `(cmd ...)` constructor with agent and mark metadata | Partial: one mark only; wrong payloads, marks and cases are rejected | [jibb-poke-bridge](../tests/lib/jibb-poke-bridge.hoon), `module-import-api-poke-*` |
99+| The todo's `subs` with an explicit type: `~[[%watch (todos.api \|=%got)]]` infers `(list (sub msg))` | Done | [jibb-todo-api](../tests/lib/jibb-todo-api.hoon), [jibb-todo-full](../tests/lib/jibb-todo-full.hoon) |
100+| A todo request under explicit `(ask msg)` context infers `\|=%got` and reports an absent tag | Partial: without context, the full check accepts it in the todo's `main`, but the partial report does not | [jibb-program-watch](../tests/lib/jibb-program-watch.hoon), [jibb-todo-full](../tests/lib/jibb-todo-full.hoon), [type-todo-partial/expected.txt](../tests/type-todo-partial/expected.txt) |
101+| Gate-free analysis of one named mold: gate-free, a gate with its field path, or unknown | Partial: capped at 256 nodes; API, store and private roots are rejected, and it checks no module or island and proves no watchability | [jibb-gate-free-source](../tests/lib/jibb-gate-free-source.hoon), [jibb-gate-free-guards](../tests/lib/jibb-gate-free-guards.hoon) |
102+| Request lowering, checked decoding, runtime validation, general island watch checking | Missing: only the direct program watch and page loads are proved | none |
103+| `ask` receivers for agents and stores | Missing: they take raw nouns (`state=(unit *)`, `fact=*`), so they prove no schema validity or watchability | [internal.jibb](../jibb-dev/lib/jibb/internal.jibb) |
104+
105+## Types and prelude: checker
106+
107+### Atoms, literals, holes and capitals
108+
109+| Area | Status | Proved by |
110+| --- | --- | --- |
111+| Unification: the library's own `+itype-unify-test` cases | Done | [jibb-typecheck](../tests/lib/jibb-typecheck.hoon) |
112+| Atoms: `@`, one-way widening to aura-family parents, branch widening to a present parent, atom constraints from capitals or bare binders | Partial: generic joins needing a common-type rule are unsupported | [types-partial-atom-widening](../tests/golden/types-partial-atom-widening/), [types-partial-aura-family](../tests/golden/types-partial-aura-family/), [types-partial-branch-widening](../tests/golden/types-partial-branch-widening/), [types-partial-bare-atom](../tests/golden/types-partial-bare-atom/), [types-partial-many-atom-constraints](../tests/golden/types-partial-many-atom-constraints/) |
113+| Decimal defaulting: unfixed decimals become `@ud` in gate-free types, including tuples and polymorphic calls | Partial: gate types still report "unresolved aura-variable inference" | [types-partial-decimal-default](../tests/golden/types-partial-decimal-default/) |
114+| Bare decimals fit only `@ud`, `@u`, `@` and `*` (S4), in casts, calls, fields, lists, branch joins and number patterns, with a hint for the aura's own literal | Partial: number patterns are checked only on known-union and atom subjects; a constructor applied directly, `(\|=%wait 30)`, keeps the generic message | `inline-decimal-*` |
115+| Literal heads: `%$` matches null-, loobean-zero- and term-zero-headed cases, and equal heads with disjoint payloads select a unique case | Partial: overlapping same-noun cases decline | [types-literal-constructor-nouns](../tests/golden/types-literal-constructor-nouns/), [types-equal-head-disjoint](../tests/golden/types-equal-head-disjoint/), [types-loobean-singleton-source](../tests/golden/types-loobean-singleton-source/) |
116+| String interpolation: known auras, `@`, tapes and isolated decimals; a known cell asks for a printer, a generic atom for an aura | Partial: a gate or non-tape list, which the Grammar makes a printer error, pending tags, generic or unknown types and a type fixed only later are unsupported | [types-string-interpolation](../tests/golden/types-string-interpolation/) |
117+| Annotation holes: each value or local definition resolves its own `_` before generalization, and later uses cannot repair it | Done: independent decimal holes default to `@ud`, captured and written-capital variables don't, and structural named molds report the hole's site | `types-hole-*`, [jibb-hole-guards](../tests/lib/jibb-hole-guards.hoon) |
118+| Holes in complex molds (`(list _)`), mutual recursive groups and inferred path segments | Missing: the first two fail closed; path-segment holes are only parsed and have no type test | [types-hole-named-complex](../tests/golden/types-hole-named-complex/), [types-hole-local-boundary](../tests/golden/types-hole-local-boundary/), [types-hole-unbound-mold](../tests/golden/types-hole-unbound-mold/), [parser-hole-path](../tests/golden/parser-hole-path/) |
119+| Written capitals: collected per `++`, shared with locals even when written later, generalized locally otherwise, independent across siblings | Done | [types-local-capitals](../tests/golden/types-local-capitals/), [types-generic-local-parameter](../tests/golden/types-generic-local-parameter/) |
120+| Forcing two distinct written capitals equal, by a call or a cast | Done: both sites are reported; forcing one to a concrete type is unsupported | [types-capital-distinct](../tests/golden/types-capital-distinct/), [types-multi-call](../tests/golden/types-multi-call/) |
121+| Empty types: `!!`, proven-empty cell positions and union cases; empty list or unit payload arms are rejected | Done: opaque reachability and spent budgets decline | [jibb-empty](../tests/lib/jibb-empty.hoon) |
122+
123+### Records, lists and units
124+
125+| Area | Status | Proved by |
126+| --- | --- | --- |
127+| Duplicate field names in a written record, including nested records, samples and expressions | Done: both sites are shown | [types-record-field-nested-mold](../tests/golden/types-record-field-nested-mold/), [types-record-field-expr-duplicate](../tests/golden/types-record-field-expr-duplicate/), [types-record-field-sample-duplicate](../tests/golden/types-record-field-sample-duplicate/) |
128+| Acyclic local definitions with captures, simple and nonrecursive generic mold aliases, faced record casts and field reads | Partial: selected shapes only | `types-local-*`, `types-generic-*`, `types-record-*` |
129+| Record changes: uniquely named fields, wing items through record fields (S6), with same-field and nested overlaps rejected, nested wings, field context for replacements | Done: unknown or partly unfaced spines are unsupported, and mismatches point at the edit, not the field's declaration | [types-record-change](../tests/golden/types-record-change/) |
130+| Record initializers under a known record cast, including nested list and union fields | Partial: mismatches point at the cast mold | [types-record-cast-context](../tests/golden/types-record-cast-context/) |
131+| A value of type variable `A` in a field typed `A`, including union payloads and nested or repeated fields | Partial: faces of differing variables don't merge | [types-generic-face-inference](../tests/golden/types-generic-face-inference/) |
132+| `proj`: explicit `(proj record)` with a known closed record type, keeping field-axis evidence for lowering; `proj` is reserved in definitions, samples, patterns and imports | Partial: same-order fields only; no context, a bare or aliased `proj` and the wrong arity fail closed | [jibb-proj-guards](../tests/lib/jibb-proj-guards.hoon), `types-proj-*` |
133+| `unface` (S1): removes every face from its argument's type, through cells, gate samples and products, containers' arguments and the unit's payload, keeping unions and recursive molds whole; reserved with `proj`; `++ f (unface \|= …)` is a gate for recursion | Partial: an argument of unknown type is unsupported; islands, pages and stores don't see a gate through `unface`; lowering waits for milestone 3 | `inline-unface-*` |
134+| `proj` with reordered fields or in nested unit, list or call contexts; `proj` lowering and execution | Missing: field order is open (question 32 in [open-questions.md](open-questions.md)) | [types-proj-explicit-context](../tests/golden/types-proj-explicit-context/), [types-proj-nested-no-implicit](../tests/golden/types-proj-nested-no-implicit/) |
135+| List literals without context, empty and nested, generalized independently | Partial: unresolved item tags and uncertain widening fail closed | [types-list-open](../tests/golden/types-list-open/), [types-list-open-constraints](../tests/golden/types-list-open-constraints/) |
136+| List literals with the validated prelude list and a known cast or sample: empty, nonempty, nested and cons, contextual tags, imported-list contexts | Done: a bad element, head or tail names both sites | [types-list-context](../tests/golden/types-list-context/), [types-list-cons](../tests/golden/types-list-cons/), [types-list-imported](../tests/golden/types-list-imported/), [types-list-zero-fit](../tests/golden/types-list-zero-fit/) |
137+| Gate sample context for one tuple or record argument, including nested cells and empty lists | Partial: a bound zero constant is unsupported, an unknown callee gives no context, and faced or three-item cons cells fail closed | [types-tuple-context](../tests/golden/types-tuple-context/), [types-list-zero-fit](../tests/golden/types-list-zero-fit/), [types-list-cons](../tests/golden/types-list-cons/) |
138+| List branches: a known list result gives context through complete loobean, unit-shaped and list-shaped branches, and `~` / `[item rest]` infers element and tail in either order | Done: unknown or non-list subjects, sets and incomplete patterns are unsupported | [types-list-branch](../tests/golden/types-list-branch/), [types-list-patterns](../tests/golden/types-list-patterns/), [types-list-pattern-imported](../tests/golden/types-list-pattern-imported/) |
139+| Unit construction with backticks, `some`, and `bind`, `biff`, `both`, `clap`, `clef` and `flit` under result annotations | Done: an unrelated union in unit context, a forced capital and an incompatible `clef` gate are unsupported | [types-unit-construction](../tests/golden/types-unit-construction/), [types-prelude-unit-helpers](../tests/golden/types-prelude-unit-helpers/) |
140+| Unit context: a known unit in a cast, call, list item or record field gives its payload context | Partial: unrelated union identities, some variable-dependent fits and a missing or altered unit template are unsupported | [types-unit-context](../tests/golden/types-unit-context/) |
141+| Nulls stay pending until resolved, and a known `~` / null-headed-cell union takes a complete `~` / `[~ value]` branch in either order | Partial: unknown subjects, missing or duplicate arms and unresolved results are not accepted | `types-null-*`, [types-unit-patterns](../tests/golden/types-unit-patterns/) |
142+| Loobean result context through complete list, unit and binder-only cell branches | Partial: binder-only arms over union subjects are unsupported | [types-flag-branch-context](../tests/golden/types-flag-branch-context/) |
143+
144+### Unions and patterns
145+
146+| Area | Status | Proved by |
147+| --- | --- | --- |
148+| Contextual tags, `~` and constructors for closed disjoint and direct nonrecursive generic unions, through complete and nested loobean branches | Partial: no test carries union context through a unit-shaped `~` / `[~ x]` branch | [types-union-tags](../tests/golden/types-union-tags/), [types-union-context-flow](../tests/golden/types-union-context-flow/), [types-union-branch-context](../tests/golden/types-union-branch-context/), [types-generic-union-local](../tests/golden/types-generic-union-local/), [types-nested-union-context](../tests/golden/types-nested-union-context/) |
149+| Result context: a known result type, including a same-origin generic union, reaches a call before its arguments are inferred | Partial: unknown targets and calls stay unsupported; wrong payloads and proven missing tags report errors | [types-constructor-context](../tests/golden/types-constructor-context/), [types-generic-result-context](../tests/golden/types-generic-result-context/), [jibb-constructor-fit-guards](../tests/lib/jibb-constructor-fit-guards.hoon) |
150+| Tuple payload context: a two-item literal-headed tuple whose payload is a shallow call, from a known union of uniquely headed cells | Partial: inference that already fits wins; the path has no complexity bound | [types-nested-union-context](../tests/golden/types-nested-union-context/), [types-nested-noun-context](../tests/golden/types-nested-noun-context/), [types-nested-shallow-preserve](../tests/golden/types-nested-shallow-preserve/), [types-prelude-sub-nested](../tests/golden/types-prelude-sub-nested/), [jibb-nested-union-guards](../tests/lib/jibb-nested-union-guards.hoon) |
151+| Missing tags: a bare tag absent from a known union reports both sites in casts, calls, unit payloads, list items, branch arms and nested tuples | Done | `types-missing-tag-*`, [types-nested-missing-tag](../tests/golden/types-nested-missing-tag/) |
152+| Union printing: by in-scope name or imported alias; unnamed unions that escape print their cases, and generic unions keep their arguments | Done | `types-union-print-*`, [types-generic-union-escaping](../tests/golden/types-generic-union-escaping/), [types-generic-union-transitive](../tests/golden/types-generic-union-transitive/) |
153+| Different import faces for one union origin are compatible, and distinct origins stay distinct | Partial: compatibility across distinct origins and some generic-argument comparisons are unsupported | [types-union-print-same-origin](../tests/golden/types-union-print-same-origin/), [types-union-print-distinct](../tests/golden/types-union-print-distinct/) |
154+| Generic aliases may reorder, repeat or omit parameters, keeping a union's origin through scopes and library interfaces | Done: generic unions declared in a body and constraints on differing variables' faces are unsupported | [types-generic-union-alias](../tests/golden/types-generic-union-alias/), [types-generic-union-transitive](../tests/golden/types-generic-union-transitive/), [jibb-generic-alias](../tests/lib/jibb-generic-alias.hoon) |
155+| Nested unions compare by runtime noun; an empty field empties a cell, and unknown inhabitation stays unresolved | Done | [types-partial-union-nested-nouns](../tests/golden/types-partial-union-nested-nouns/) |
156+| Union patterns: whole-case arms, payload binders, imported and generic cases and binder-free catch-alls; missing cases and covered arms are reported | Done | [types-union-patterns](../tests/golden/types-union-patterns/), [types-union-patterns-generic](../tests/golden/types-union-patterns-generic/), [types-union-patterns-import](../tests/golden/types-union-patterns-import/) |
157+| A bare pattern name that spells a tag a matching case has at that position is an error (S5), on every checker path that types `?-` | Done: the full module check reports it only as "needs unsupported inference" | `inline-pattern-tag-name-*` |
158+| Partial boolean patterns: `?` positions split into at most 64 alternatives across the union | Done: past the limit the report says "union pattern expansion needs unsupported inference" | [types-union-finite](../tests/golden/types-union-finite/), [types-union-finite-limit](../tests/golden/types-union-finite-limit/), [types-union-finite-generic](../tests/golden/types-union-finite-generic/) |
159+| Other partial patterns, binders spanning cases, some complex two-arm subjects | Missing: fail closed | [types-union-finite-limit](../tests/golden/types-union-finite-limit/), [types-union-patterns-generic](../tests/golden/types-union-patterns-generic/) |
160+| Union pattern result context from a cast or call sample, for a union reached by a wing, grouped wing or shallow call | Partial: other subject forms are unsupported | [types-union-pattern-result-context](../tests/golden/types-union-pattern-result-context/), [types-union-pattern-result-controls](../tests/golden/types-union-pattern-result-controls/), [types-union-finite-context](../tests/golden/types-union-finite-context/) |
161+| Branch result joins: `?-` arms unify, then widen only to a present parent aura or `@`, in any arm order | Done: sibling auras without a parent stay distinct, and distinct variables forced equal get a two-site error | [types-partial-branch-widening](../tests/golden/types-partial-branch-widening/), [types-union-finite](../tests/golden/types-union-finite/), [types-union-finite-generic](../tests/golden/types-union-finite-generic/), [jibb-deferred](../tests/lib/jibb-deferred.hoon) |
162+| Recursive local branches, such as `rec-widen` | Done: arms over a known union whose results are all pending tags still fail closed as unsupported | [types-recursive-branch](../tests/golden/types-recursive-branch/), [types-local-error-order](../tests/golden/types-local-error-order/), [types-recursion-scc-local](../tests/golden/types-recursion-scc-local/), [types-union-patterns-generic](../tests/golden/types-union-patterns-generic/) |
163+| Cell patterns: a single arm with two or more binders, the last taking the tail | Done: duplicate and shadowed binders and definite non-cell subjects fail | `types-cell-pattern-*` |
164+| Structured single-arm patterns on a known non-union cell, with nested sub-patterns, wildcards and literal heads | Partial: intermediate union or collection tails and faced-record patterns are unsupported | [types-cell-pattern-many](../tests/golden/types-cell-pattern-many/), [types-cell-pattern-tail](../tests/golden/types-cell-pattern-tail/), [types-single-case-pattern](../tests/golden/types-single-case-pattern/) |
165+| Closed cell context through a bounded loobean branch, keeping value faces and rolling back on failure | Partial: open or uncertain substitutions and nested retries are unsupported | [jibb-cell-branch](../tests/lib/jibb-cell-branch.hoon), [types-cell-branch-context](../tests/golden/types-cell-branch-context/) |
166+
167+### Gates, recursion and imports
168+
169+| Area | Status | Proved by |
170+| --- | --- | --- |
171+| Multi-argument calls: a right-nested sample keeping faces and shared variables, giving context to list and union arguments | Done: unknown-callee contexts and pending tags are unsupported | [types-multi-call](../tests/golden/types-multi-call/) |
172+| Positional calls unify a variable argument with a faced sample slot without passing the face on | Done: `labelled` checks as `$-([label=@t msg=A] (element A))` | [jibb-buttons](../tests/lib/jibb-buttons.hoon), [jibb-positional-face-guards](../tests/lib/jibb-positional-face-guards.hoon), [jibb-closed-gate-guards](../tests/lib/jibb-closed-gate-guards.hoon), [types-positional-faces](../tests/golden/types-positional-faces/) |
173+| A capital that meets a faced position binds only the type under the face (S1 step 1, decided 2026-11-03) | Missing: `(hunt lt-a `1 `2)` still fails; the checker core of review question 5 builds it | [inline-unface-labelled-slot](../tests/golden/inline-unface-labelled-slot/) |
174+| Printed type variables keep their written names (S7), as `(program Data Model Msg)`; a variable with no name prints as an unused letter | Done: when named variables merge, a capital written in the `++` names the result, otherwise the earliest-made one | [types-typevar-names](../tests/golden/types-typevar-names/), [types-typevar-print](../tests/golden/types-typevar-print/) |
175+| Named unions through unconstrained polymorphic gates, keeping origin, arguments and faces | Partial: different origins, explicit-capital forcing and pending tags are unsupported | [types-union-polymorphic-identity](../tests/golden/types-union-polymorphic-identity/) |
176+| Direct gate sample fit: a directly named, checked root gate against a generic gate sample in a direct prelude call | Partial: other cases fall back to ordinary inference, and it proves no island or watchability | [jibb-direct-gate-guards](../tests/lib/jibb-direct-gate-guards.hoon), [jibb-direct-gate-source](../tests/lib/jibb-direct-gate-source.hoon) |
177+| Single self-recursive gates, top-level and local: a monomorphic self reference, then generalization; bad recursive arguments name both sites | Done: polymorphic recursion, explicit-capital forcing and local name collisions are unsupported | [types-recursive-sample](../tests/golden/types-recursive-sample/), [types-recursive-gate](../tests/golden/types-recursive-gate/), [types-local-recursive](../tests/golden/types-local-recursive/) |
178+| A closed base type seeds the result of a complete loobean branch with one direct self-call arm | Done: open or pending bases don't seed it | [types-recursive-branch](../tests/golden/types-recursive-branch/) |
179+| Top-level mutual recursion: gate groups inferred together, generalized after the group checks, instantiated independently downstream | Partial: conservative dependency edges can reject valid programs | `types-recursion-scc-*` |
180+| Local mutual recursion: shared monomorphic seeds, captured outer variables kept shared | Partial: distinct forced captures, unresolved tags, shadowing and mixed gate/value cycles fail closed | [types-local-scc](../tests/golden/types-local-scc/), [types-local-scc-adversarial](../tests/golden/types-local-scc-adversarial/), [types-recursion-scc-local](../tests/golden/types-recursion-scc-local/) |
181+| Non-gate value cycles, reported with a dependency site when an explicit atom or loobean cast establishes them | Partial: bare aliases, branches and nested-local edges decline | [types-value-cycles](../tests/golden/types-value-cycles/), [types-value-cycle-shadow](../tests/golden/types-value-cycle-shadow/), [types-value-cycle-unsupported](../tests/golden/types-value-cycle-unsupported/) |
182+| Other mixed gate/value cycles, polymorphic recursion, unresolved literal constraints and unresolved branch joins | Missing | [types-recursion-scc-failures](../tests/golden/types-recursion-scc-failures/), [types-value-cycle-unsupported](../tests/golden/types-value-cycle-unsupported/) |
183+| Library imports: supplied Jibb sources in dependency order, a per-run interface cache, missing-source and cycle reports, nested fields of imported values | Partial: a library with a recursive mold yields no interface | `module-import-*`, `module-cache-*`, `types-module-field-*` |
184+
185+### Bounded and experimental routes
186+
187+| Area | Status | Proved by |
188+| --- | --- | --- |
189+| Generic recursive trees: a source-proven tree in an import-free owner module keeps its nominal identity across imports and aliases | Partial: a narrow test tree, not `element`; different origins and unproved casts decline | [jibb-generic-recursion](../tests/lib/jibb-generic-recursion.hoon) |
190+| Tree construction one source-proven layer at a time under a known type | Partial: wrong-owner, wrong-argument and bad-child cases report "list item constraint is not supported", not an error | [jibb-generic-construction](../tests/lib/jibb-generic-construction.hoon) |
191+| Flat tree matches with explicit tags or nonbinding catch-alls, and a missing-case error for a single-arm match | Done: 128 arms are screened and 129 decline | [jibb-generic-pattern](../tests/lib/jibb-generic-pattern.hoon) |
192+| Whole-case binders, nested patterns, general structural fits and gate-free proof for these trees | Missing: declined | [jibb-generic-pattern](../tests/lib/jibb-generic-pattern.hoon), [jibb-generic-recursion](../tests/lib/jibb-generic-recursion.hoon) |
193+| Tree limits: 4,096 face and substitution visits per scan, 128 arms per pattern, unfolding fuel per attempt | Partial: the 4,096 and 128-arm boundaries are tested; the suites test fuel 0 to 4, not the 256-step `jrec-fuel` | [jibb-generic-construction](../tests/lib/jibb-generic-construction.hoon), [jibb-generic-pattern](../tests/lib/jibb-generic-pattern.hoon) |
194+| `qath`: source identity, null and cell construction and matching, static application-path literals, faces and identity across imports | Partial: the suites test fuel 0 to 2, not the 256-step limit | `types-qath-*`, [jibb-qath-fuel](../tests/lib/jibb-qath-fuel.hoon), [jibb-qath-source](../tests/lib/jibb-qath-source.hoon) |
195+| `qath` for other recursive shapes, broader patterns and dynamic path segments; route and static-file checks | Missing: dynamic segments need unsupported inference, and routes wait for milestone 4 | [types-qath-recursive](../tests/golden/types-qath-recursive/) |
196+| Deferred constructor transaction: unsafe shapes decline, so a later substitution cannot undo a face check | Partial: experimental; no test isolates each declined category | [jibb-deferred](../tests/lib/jibb-deferred.hoon) |
197+| Deferred retries once later dependencies exist; a two-arm boolean branch keeps literal obligations until a closed context resolves them | Partial: faced targets, unions with a case that is not a constant or a cell, list literals and general union-pattern branches decline | [jibb-deferred-context](../tests/lib/jibb-deferred-context.hoon), [jibb-deferred](../tests/lib/jibb-deferred.hoon) |
198+| Deferred direct-constructor constraints in an import-free library without a prepared prelude, published only when everything closes | Partial: experimental; stores, preludes, imports, recursive groups, open interfaces and `%grec` scans are rejected | [jibb-deferred](../tests/lib/jibb-deferred.hoon), [jibb-deferred-resolver](../tests/lib/jibb-deferred-resolver.hoon) |
199+| Prepared-prelude initializer recovery: a non-main library tuple initializer deferred to a later exact result cast | Partial: needs exact value, mold and interface inventories, and the report keeps "partial inference; module not checked"; list literals are not deferred | [jibb-deferred-prepared](../tests/lib/jibb-deferred-prepared.hoon) |
200+| Prepared recovery guards: API and store paths, `main` and imports are excluded; wrong fields, unrelated tags and mold collisions fail closed | Done | [jibb-deferred-prepared](../tests/lib/jibb-deferred-prepared.hoon) |
201+
202+## Types and prelude: prelude
203+
204+| Area | Status | Proved by |
205+| --- | --- | --- |
206+| Shared interface: every vendored name reserved, only inferred entries exposed, such as `list`, `unit`, `same`, `fall`, `need`, `bond`, `lure`, `weld`, `snoc`, `turn` and `lent` | Partial: backend validation is outstanding | [jibb-module-scope](../tests/lib/jibb-module-scope.hoon), [jibb-list-alias-guards](../tests/lib/jibb-list-alias-guards.hoon), [types-prelude-interface](../tests/golden/types-prelude-interface/) |
207+| One prelude origin for all callers, so a library can export a type with unqualified `(unit A)` | Done | [types-prelude-interface](../tests/golden/types-prelude-interface/), [jibb-module-scope](../tests/lib/jibb-module-scope.hoon) |
208+| Preparation: `+prepare-prelude` rejects malformed, conflicting and import-bearing source, and `+prepare-prelude-with-internal` takes the private internal import | Done: that prepared values are trusted is a contract, which no test checks | [jibb-poke-bridge](../tests/lib/jibb-poke-bridge.hoon), [jibb-module-scope](../tests/lib/jibb-module-scope.hoon) |
209+| The validated `list` template for the prelude's own gates and mold aliases; an altered, omitted, duplicate or malformed `list` doesn't leak through aliases | Done | [jibb-list-alias-guards](../tests/lib/jibb-list-alias-guards.hoon), [types-prelude-list-alias](../tests/golden/types-prelude-list-alias/), [types-prelude-list-functions](../tests/golden/types-prelude-list-functions/) |
210+| The prelude `list` and imported Hoon lists unify both ways | Partial: other Jibb-written collection molds and most collection operations are unsupported | [types-list-imported](../tests/golden/types-list-imported/), [types-list-pattern-imported](../tests/golden/types-list-pattern-imported/), [jibb-bridge](../tests/lib/jibb-bridge.hoon) |
211+| With `list` or `unit` missing or altered, independent private molds (`qath`) stay available and dependent ones (`ask`) don't | Done | [jibb-qath-source](../tests/lib/jibb-qath-source.hoon), [jibb-ask-guards](../tests/lib/jibb-ask-guards.hoon) |
212+| Module scope: the prepared and source-taking prelude paths compared against the real prelude | Partial: full checks name top-level conflicts and show both sites when sources are available; nested reserved names and API mark conflicts can still be generic | [jibb-full-scope](../tests/lib/jibb-full-scope.hoon), [jibb-module-scope](../tests/lib/jibb-module-scope.hoon), [types-prelude-interface](../tests/golden/types-prelude-interface/) |
213+| Full-check definition diagnostics | Partial: definite inference failures on unresolved definitions retain their sites; mold, kind and context-dependent failures remain incomplete | [jibb-full-diagnostics](../tests/lib/jibb-full-diagnostics.hoon) |
214+| `fall` and `need` | Done | [prelude-list-unit](../tests/golden/prelude-list-unit/), [types-prelude-direct](../tests/golden/types-prelude-direct/) |
215+| `drop`, `skim`, `skip`, `murn`, `join`, `snip`, `rear` and a shared-type `clap` | Partial: no test calls `rear` | [types-prelude-list-helpers](../tests/golden/types-prelude-list-helpers/), [types-prelude-unit-helpers](../tests/golden/types-prelude-unit-helpers/) |
216+| `bond`, `levy`, `lien`, and gate composition and currying | Partial: currying a faced sample is unsupported | [types-prelude-bond](../tests/golden/types-prelude-bond/), [types-prelude-predicates](../tests/golden/types-prelude-predicates/), [types-prelude-functional](../tests/golden/types-prelude-functional/) |
217+| `hunt`, with the ordering gate first | Done: both ordering outcomes and absent units infer; a mismatched payload or ordering-gate sample names both sites | [types-prelude-unit-helpers](../tests/golden/types-prelude-unit-helpers/), [prelude-unit-list-transforms](../tests/golden/prelude-unit-list-transforms/) |
218+| `like`: the value gate maps a `(like A)` result with a gate, and `like` is still a mold | Partial: an incompatible converter is reported as unsupported, not as an error | [types-prelude-like](../tests/golden/types-prelude-like/) |
219+| `eq` and `mate`, with a gate-free variable; `set`, `map`, `mop`, `jar` and `jug` constrain only their keys | Partial: backend equality and crash behavior are unverified | [jibb-gate-free-guards](../tests/lib/jibb-gate-free-guards.hoon), [types-prelude-unit-helpers](../tests/golden/types-prelude-unit-helpers/) |
220+| `lent` | Done | [types-prelude-lent](../tests/golden/types-prelude-lent/) |
221+| `succ` through `add`, keeping its non-loobean atom constraint | Done: a Hoon translation agrees with Hoon's `succ` on ten inputs | [types-prelude-succ](../tests/golden/types-prelude-succ/), [jibb-hoon-reference](../tests/lib/jibb-hoon-reference.hoon) |
222+| `lead` and `late`, curried | Done: a Hoon translation agrees with Hoon's on 25 pairs of five nouns, a gate among them | [types-prelude-lead-late](../tests/golden/types-prelude-lead-late/), [jibb-hoon-reference](../tests/lib/jibb-hoon-reference.hoon) |
223+| `zing` over `weld` | Done: a Hoon translation matches Hoon's `zing` on 4 inputs | [types-prelude-zing](../tests/golden/types-prelude-zing/), [jibb-hoon-reference](../tests/lib/jibb-hoon-reference.hoon) |
224+| `lth`, `gte` and `lte` over `gth` and `not` | Partial: complete import checking is unfinished | [types-prelude-comparison](../tests/golden/types-prelude-comparison/) |
225+| Private `gth`, `add` and `dec` schemes that ordinary imports cannot reach; `add` and `dec` reject loobeans | Done | [types-prelude-arithmetic](../tests/golden/types-prelude-arithmetic/), [types-arithmetic-module](../tests/golden/types-arithmetic-module/), [jibb-arithmetic-guards](../tests/lib/jibb-arithmetic-guards.hoon) |
226+| `trip` and `tuba` over private primitives: `$-(@t (list @tD))` and `$-((list @tD) (list @c))` | Partial: no test compares them with Hoon's definitions | [types-prelude-text](../tests/golden/types-prelude-text/) |
227+| `cmd`, the doc's generic union with five cases | Partial: the prelude inventory is incomplete | [types-prelude-cmd](../tests/golden/types-prelude-cmd/) |
228+| `sub`, with `%watch` payloads of type `(ask M)` | Done: building a `sub` proves no watchability | [types-prelude-sub](../tests/golden/types-prelude-sub/), [types-prelude-sub-nested](../tests/golden/types-prelude-sub-nested/), [jibb-sub-guards](../tests/lib/jibb-sub-guards.hoon) |
229+| `ask`, with pure, agent and store cases, and `pure` | Partial: receiver mismatches and path, `qath` and erased-fact casts are unsupported | [jibb-ask-guards](../tests/lib/jibb-ask-guards.hoon), [types-prelude-ask](../tests/golden/types-prelude-ask/) |
230+| `qath`, `~` or `[i=@ta t=qath]` in the internal prelude, re-exported | Done | [jibb-qath-source](../tests/lib/jibb-qath-source.hoon), [types-qath-module-identity](../tests/golden/types-qath-module-identity/) |
231+| `raw-poke`, defined in the internal prelude and re-exported as a transparent type | Done | [jibb-poke-bridge](../tests/lib/jibb-poke-bridge.hoon) |
232+| Printed types say `ask`, `qath` and `raw-poke`, without `.internal` | Done | [types-prelude-ui](../tests/golden/types-prelude-ui/), [jibb-theme](../tests/lib/jibb-theme.hoon), [types-prelude-cmd](../tests/golden/types-prelude-cmd/) |
233+| `store` mold and builder; a store's local `+$ poke` stays its own action mold | Done: multi-action declarations are unsupported | [jibb-store](../tests/lib/jibb-store.hoon), [jibb-poke-bridge](../tests/lib/jibb-poke-bridge.hoon) |
234+| UI length and attribute molds, the 19 element constructors, and `program` and `page` records and builders, with exact schemes | Done | [types-prelude-ui](../tests/golden/types-prelude-ui/) |
235+| `element`: a nonrecursive 19-case union with `*` children, and `island` giving `(element !!)` | Partial: a child-message mismatch (`bad-child`) is reported as unsupported, not as an error | [types-prelude-ui](../tests/golden/types-prelude-ui/) |
236+| Raw-constructor encapsulation, duplicate-attribute checks, rendering, storage and navigation | Missing: a raw `[%text "raw"]` element infers | [types-prelude-ui](../tests/golden/types-prelude-ui/) |
237+| `theme`: required text tokens, an optional `qath` font and optional dark tones | Done: no theme behavior is implemented | [jibb-theme](../tests/lib/jibb-theme.hoon), [doc-overview-02-theme](../tests/golden/doc-overview-02-theme/) |
238+| Execution and jet recognition of prelude gates and primitives | Missing | none |
239+
240+## Types and prelude: Hoon importer
241+
242+| Area | Status | Proved by |
243+| --- | --- | --- |
244+| The bridge into inference: `*`, selected atoms, singletons, nested cells, disjoint unions and opaque standard collections from `/sur` molds and marks | Partial: supported shapes only, with `*` only in nonrecursive molds; the mark bridge mainly tests that only the declared aura mark resolves | [jibb-bridge](../tests/lib/jibb-bridge.hoon), [jibb-tlon-bridge](../tests/lib/jibb-tlon-bridge.hoon), [type-import/expected.txt](../tests/type-import/expected.txt), [jibb-mark-bridge](../tests/lib/jibb-mark-bridge.hoon) |
245+| Bridged collections keep their names and arguments, including nested union arguments | Partial: the bridge trusts unchanged source-aware reader results, which is documented, not testable | [jibb-bridge](../tests/lib/jibb-bridge.hoon) |
246+| A Hoon `(unit T)` becomes the prelude `unit`, also inside unions and lists, API marks and poke exports | Done | [jibb-bridge](../tests/lib/jibb-bridge.hoon), [jibb-api-paths](../tests/lib/jibb-api-paths.hoon) |
247+| Repeated faces in imported record spines | Partial: fail closed with a generic diagnostic, and may reject valid names in scopes Hoon erased | [jibb-bridge](../tests/lib/jibb-bridge.hoon) |
248+| Reader coverage: mark samples, Ford-verified recursive molds, nested collections, direct ordered maps (Tlon `notes.log`), disjoint direct `$^` unions, one explicit union argument in a collection | Done | [jibb-import](../tests/lib/jibb-import.hoon), [jibb-mark-bridge](../tests/lib/jibb-mark-bridge.hoon), [types-import-tlon-notes](../tests/golden/types-import-tlon-notes/) |
249+| Tagged `$%` cases with local named payload molds, bare `~` fields and one level of nested tagged unions, as in the real Tlon notes | Partial: other nested unions are unfinished | [types-import-tlon-notes](../tests/golden/types-import-tlon-notes/), [jibb-import](../tests/lib/jibb-import.hoon) |
250+| Self-recursive `/sur` molds, including Tlon `notes.import-node`, as opaque module-and-name identities | Partial: aliases, foreign references, recursive marks, unfolding and construction are unsupported | [types-import-tlon-notes](../tests/golden/types-import-tlon-notes/), [jibb-import](../tests/lib/jibb-import.hoon) |
251+| Explicit `$%`, `$?` and `$^` unions checked from source, including cases Hoon would collapse | Partial: ambiguous recursive origins fail closed | [jibb-import](../tests/lib/jibb-import.hoon), [jibb-import-overlap](../tests/lib/jibb-import-overlap.hoon), [jibb-import-structural](../tests/lib/jibb-import-structural.hoon) |
252+| Other nested unions, nested ordered maps, general union disjointness, complete import integration | Missing: reported as disjointness that could not be verified | [jibb-import](../tests/lib/jibb-import.hoon) |
253+| Collection recognition checks the originating core and rejects shadows, missing provenance and forged subjects, samples and tails | Done | [jibb-import](../tests/lib/jibb-import.hoon), the Tlon fixtures [importer/tlon-epic.txt](../tests/importer/tlon-epic.txt), [importer/tlon-presence.txt](../tests/importer/tlon-presence.txt) and [importer/tlon-docs.txt](../tests/importer/tlon-docs.txt) |
254+| `$?` overlaps, proved by comparing each case's runtime noun and reported at the Jibb use site | Partial: Hoon case locations are not reported, and the mark reader reports no overlaps | [jibb-import-overlap](../tests/lib/jibb-import-overlap.hoon), [jibb-import-structural](../tests/lib/jibb-import-structural.hoon) |
255+| Overlap budgets: 128 cases and 4,096 source nodes per union, and 4,096 nodes each for dependencies and the witness | Done: they don't bound chapter lookup, Hoon evaluation or graph walks | [jibb-import-overlap](../tests/lib/jibb-import-overlap.hoon), [jibb-import-structural](../tests/lib/jibb-import-structural.hoon) |
256+| `$~` default wrappers in the tagged-union proof: the Tlon saga mold and a labelled saga envelope | Done: overlap, recursive, shadow and malformed controls are rejected | [jibb-import-default](../tests/lib/jibb-import-default.hoon) |
257+| Consecutive default wrappers | Partial: four are peeled and five rejected; no test shows that defaults in dependency proofs spend the node budget | [jibb-import-default](../tests/lib/jibb-import-default.hoon) |
258+| Structured reader APIs (`read-named-diagnostic`, `read-mark-diagnostic`) keep graphs and tell definite aura and core errors from unprovable ones | Partial: unverified union disjointness and name-only vase recognition are unsupported | [jibb-import-diagnostic](../tests/lib/jibb-import-diagnostic.hoon), [jibb-import](../tests/lib/jibb-import.hoon) |
259+| Reader errors at Jibb use sites, replayed into nested samples, casts and same-module aliases | Partial: imported union molds, generic applications and transitive modules keep the generic message, as do duplicate, missing or clashing inputs | [jibb-import-diagnostic](../tests/lib/jibb-import-diagnostic.hoon), [type-import-diagnostic/nested.txt](../tests/type-import-diagnostic/nested.txt) |
260+| The importer golden: 221 projections | Done | [jibb-import](../tests/lib/jibb-import.hoon), [importer/tree.txt](../tests/importer/tree.txt) |
261+| Clay: the example `/sur` files and marks built through Clay, a recursive Ford import's origin, a Ford-built nested union into partial inference | Done: 14 threads, each with an expected file | `tools/clay-fixtures`, [clay-fixtures/](../tests/clay-fixtures/) |
262+
263+## Desks and tools
264+
265+| Area | Status | Proved by |
131266| --- | --- | --- |
132−| 1cb51df | 2026-10-29 | Foundation: the parser's design, the tools, the desks, the vendored base-dev and landscape files, the golden corpus |
133−| 15a5545 | 2026-10-29 | The layout pass |
134−| 3c5f50a | 2026-10-29 | The parser |
135−| 7c739b7 | 2026-10-30 | Fixes from two independent audits; milestone 1 done |
136−| 5a4aa73 | 2026-10-30 | `tools/doc-blocks`, after the doc labelled its Jibb blocks |
137−| ab797a9 | 2026-10-30 | The 12 grammar decisions of 2026-10-30: four changed the parser, eight confirmed it |
138−| aad6ddb | 2026-10-30 | Drop `$?`; `+$` takes union cases below its name |
139−| 1dd92a6 | 2026-10-30 | Begin type inference and Hoon imports |
140−| 51ce4d9 | 2026-10-30 | Extend partial inference and importer, record type and prelude decisions |
141−| be6d2a5 | 2026-10-30 | Add atom widening, nested collections and case-local Hoon import fixtures |
142−| 26554ac | 2026-10-30 | Infer an atom constraint, extend the prelude and read example molds through Clay |
143−| fbeaa83 | 2026-10-30 | Extend atom constraints and nested ordered-map imports; connect Clay types to partial inference |
144−| 47a1f49 | 2026-10-30 | Read validated Ford imports, widen aura families, and show both sites of selected errors |
145−| bd37989 | 2026-10-30 | Read mark samples and test partial mark imports; reject unproven nested `$^`; preserve atom constraints through aliases |
146−| 2d5deb2 | 2026-10-30 | Default gate-free decimal types, validate named Hoon mold lookup, and isolate fixture failures |
147−| 1b7dbae | 2026-10-30 | Infer acyclic local definitions and parse case-local Jibb module fixtures |
148−| 8b9c9ac | 2026-10-30 | Preserve recursive import origins, infer simple local molds, and supply Jibb module sources to the partial checker |
149−| 529736a | 2026-10-30 | Infer supported library import graphs and guard nested Hoon `$^` in collections |
150−| 8bf1b12 | 2026-10-30 | Infer selected record faces and check nested `$^` in static Hoon records |
151−| d8ac47d | 2026-10-30 | Cache library interfaces, preserve imported Hoon record faces, and check nested tagged unions |
152−| edd9277 | 2026-10-30 | Infer nonrecursive generic mold aliases with lexical parameters |
153−| 4406f6f | 2026-10-30 | Resolve selected contextual tags and check explicit imported unions |
154−| 5c73614 | 2026-10-30 | Print supported named and escaping union types |
155−| 0070584 | 2026-10-30 | Propagate union context through loobean branches, read selected unions in Hoon collections, and add `flit` |
156−| 250564c | 2026-10-30 | Infer selected named generic unions, test Hoon collection wrappers, and add list helpers |
157−| e95ef8f | 2026-10-30 | Bridge selected Hoon unions into partial inference and support generic union aliases |
158−| 56a899f | 2026-10-30 | Infer matching variable types in faced fields and bridge opaque Hoon collections |
159−| 4d45d2f | 2026-10-30 | Resolve selected contextual null literals |
160−| e878edc | 2026-10-30 | Infer complete unit-shaped branches and bridge selected recursive Hoon molds |
161−| 743dfd8 | 2026-10-30 | Propagate union context through unit-shaped branches |
162−| 3f90fa8 | 2026-10-30 | Share a partial prelude interface across module inference |
163−| 29bd39f | 2026-10-30 | Infer contextual list literals and validate prelude parity |
164−| a2a6ef5 | 2026-10-30 | Infer complete list-shaped branches |
165−| 671fe72 | 2026-10-30 | Infer contextual list nulls and cons cells |
166−| 7e69436 | 2026-10-30 | Infer selected self-recursive gates |
167−| 9ab52e8 | 2026-10-30 | Infer recursive branches with closed base types |
168−| d782b45 | 2026-10-30 | Propagate list context and apply settled type decisions |
169−| c7082e0 | 2026-10-30 | Infer multi-argument calls |
170−| 918acbd | 2026-10-30 | Infer recursive gates from their samples first |
171−| 1470d18 | 2026-10-30 | Infer selected prelude list helpers |
172−| 10cbf9c | 2026-10-30 | Infer selected local recursive gates and distinguish reader diagnostics |
173−| 45afb13 | 2026-10-30 | Infer local capital scopes and report direct reader diagnostics |
174−| 054e651 | 2026-10-30 | Report nested reader diagnostics |
175−| 98c19cd | 2026-10-30 | Infer known-aura string interpolation |
176−| ddba633 | 2026-10-30 | Infer top-level mutually recursive gates |
177−| 9f1517e | 2026-10-30 | Infer whole-case union patterns and prelude `turn` |
178−| 9dd35c8 | 2026-10-31 | Match finite boolean refinements of union cases |
179−| 54852d4 | 2026-10-31 | Contextualize tuple calls and infer known record changes |
180−| 0bc5113 | 2026-10-31 | Contextualize record initializers and infer unit construction |
181−| 264a436 | 2026-10-31 | Contextualize unit payloads in casts, calls and nested values |
182−| a140383 | 2026-10-31 | Report missing union tags and infer prelude unit helpers |
183−| d69cc52 | 2026-10-31 | Infer longer cell binder patterns and prelude unit helpers |
184−| ae35005 | 2026-10-31 | Import source-verified tagged Hoon unions |
185−| c8f894a | 2026-10-31 | Report nested missing tags and contextualize union branch results |
186−| ef2ea71 | 2026-10-31 | Import Hoon null singleton cases |
187−| 67f900e | 2026-10-31 | Infer local mutual gates and uncontextualized lists |
188−| 7ff15f1 | 2026-10-31 | Contextualize finite union patterns and record the initial poke decision |
189−| c790a9f | 2026-10-31 | Expose transparent `poke` from the internal prelude |
190−| ef4772a | 2026-10-31 | Bridge imported loobeans and loobean singletons |
191−| ad46655 | 2026-10-31 | Bridge selected imported any-noun molds |
192−| beada10 | 2026-10-31 | Import source-proved Ford mark unions, analyze API paths and infer list helpers |
193−| e28f7be | 2026-10-31 | Diagnose proven non-gate cycles and import Tlon null-payload union cases |
194−| fd2f288 | 2026-10-31 | Infer qualified fields of imported values |
195−| ed9291e | 2026-10-31 | Infer term-headed pairs and function helpers, and import nested named unions |
196−| ad0265e | 2026-10-31 | Infer proven single-case patterns and the prelude command union |
197−| 413b12b | 2026-10-31 | Propagate known result context into generic calls and batch ship deletions |
198−| c690076 | 2026-10-31 | Propagate loobean context, infer predicate helpers, and import named ordered-map operands |
199−| 0bf6178 | 2026-10-31 | Bridge recursive Tlon lists and prepare a private comparison interface |
200−| 4e472b5 | 2026-10-31 | Pass known named unions through polymorphic gates |
201−| e3e184f | 2026-10-31 | Parse type holes, reject duplicate written record fields, and extend partial union inference and imports |
202−| 80e221a | 2026-10-31 | Infer supported annotation holes and prelude list aliases |
203−| ba1fec4 | 2026-10-31 | Add the curried `bond` prelude gate |
204−| 0ea700d | 2026-10-31 | Infer a source-defined recursive `qath` subset and record the explicit `proj` decision |
205−| 75f5952 | 2026-10-31 | Check a subset of explicit `proj` calls and retain their lowering evidence |
206−| cf17925 | 2026-10-31 | Infer supported single-field projections |
207−| 1a891e2 | 2026-10-31 | Infer source-backed addition and decrement without loobean operands; record the watchability decision |
208−| 81af5fd | 2026-10-31 | Preserve public names of identity-generic union aliases and record the `like` decision |
209−| 640a442 | 2026-10-31 | Add the source-backed `like` result mapper and infer supported positional calls |
210−| 445a0a1 | 2026-10-31 | Retain source-backed API path evidence and classify declarations |
211−| f69493d | 2026-10-31 | Derive supported request components from API declarations |
212−| f0f6954 | 2026-10-31 | Analyze supported API helper definitions and declared marks |
213−| 3f55af7 | 2026-10-31 | Define source-backed transparent ask and pure |
214−| ae1ec26 | 2026-10-31 | Prove selected default-wrapped Hoon unions from source |
215−| dde791c | 2026-10-31 | Infer a source-backed request-gate type through ordinary imports |
216−| a1c5f35 | 2026-10-31 | Infer supported multi-path requests and named closed folds |
217−| 911ca0c | 2026-10-31 | Propagate union context, define subscriptions and match literal nouns |
218−| 72acdb3 | 2026-10-31 | Infer selected nested union payloads from context |
219−| 706035c | 2026-10-31 | Analyze gate-free source molds with field witnesses |
220−| 651b8ec | 2026-10-31 | Match source-proven gate samples in direct calls |
221−| cc8e389 | 2026-10-31 | Add source-backed list length and real todo regression |
222−| 4da6891 | 2026-10-31 | Add source-backed comparisons and nested Hoon union controls |
223−| 09db390 | 2026-10-31 | Skip unnecessary inference environment scans |
224−| 179d717 | 2026-10-31 | Diagnose source-proven Hoon union overlaps |
225−| 142f2e2 | 2026-10-31 | Prove structural overlaps across Hoon union cases |
226−| c96597d | 2026-10-31 | Track source-proven generic recursive identities |
227−| 190a9d5 | 2026-10-31 | Add source-backed list flattening |
228−| d9d51e6 | 2026-10-31 | Check source-proven recursive tree construction |
229−| 30b0a9e | 2026-10-31 | Match source-proven recursive tree cases |
230−| 72d85ab | 2026-10-31 | Add bounded deferred inference and expand runtime equality coverage |
231−| 22f3788 | 2026-10-31 | Check empty molds and propagate closed cell context into branches |
232−| 341bcb4 | 2026-10-31 | Keep deferred fits stable under later substitutions |
233−| b93a94b | 2026-10-31 | Prove local generic-alias union tags and add successor |
234−| 2826c93 | 2026-10-31 | Report generic-alias overlaps and retain deferred branch contexts |
235−| b5cdc80 | 2026-10-31 | Preserve full-module overlap source evidence |
236−| ab6fdc1 | 2026-10-31 | Add source-backed text conversion wrappers |
237−| aa277c9 | 2026-10-31 | Recover prepared tuple initializers in partial reports |
238−| b4703e7 | 2026-11-01 | Check narrow closed subscription-free program mains |
239−| 26bf7a7 | 2026-11-01 | Recover narrow direct-program initializer contexts |
240−| 642d2c0 | 2026-11-01 | Prove direct request-value watchability for program subscriptions |
241−| 2e4d582 | 2026-11-01 | Add the source-backed UI, program and page prelude slice |
242−| a163965 | 2026-11-01 | Recover direct-program update result contexts |
243−| 46748b0 | 2026-11-01 | Check the unchanged todo island through component recovery |
244−| 1e17d5f | 2026-11-01 | Check static and direct data-page mains |
245−| 0517053 | 2026-11-01 | Add the theme mold and require explicit unit syntax |
246−| This change | 2026-11-01 | Check the unchanged cart store and basket |
267+| `tools/golden`: the golden corpus under `urbit eval` | Done | `tools/testdata/selftest` |
268+| `tools/test-arms`: the 62 `test-` arms of the 58 `tests/lib` suites under eval, chosen by name, glob or shard, with `--list`, `--report` and `--update` | Done | `tools/testdata/selftest` |
269+| `tools/ship test`: the same arms and one arm per golden case on the fake ship, 753 in all | Done | `tools/testdata/ship-selftest` |
270+| `tools/check`: every check, with the suites in four cost-balanced shards (`arms-1` to `arms-4`) | Done | `nix flake check` runs the same groups ([flake.nix](../flake.nix)); nothing tests the runner itself |
271+| `nix build` and `nix flake check`: the four desks, and every check in the Nix sandbox | Done | [flake.nix](../flake.nix) |
272+| The tools' own tests: `tools/testdata/selftest` (23 checks) and `tools/testdata/ship-selftest` | Done | the two scripts |
273+| `tools/hoon --no-debug` builds the library without `!:`, for timings | Done | `tools/testdata/selftest` |
274+| A UI runtime and the shared host | Missing: the `jibb` desk holds only `desk.bill` and `sys.kelvin` | none |
275+
276+## Gaps
277+
278+- Nothing runs yet: with no lowering, backend, UI runtime or jet recognition, programs, pages, stores, islands and prelude gates are checked statically only ([type-todo-full/about.txt](../tests/type-todo-full/about.txt)).
279+- Requests have no lowering, checked decoding or runtime validation, nothing proves an arbitrary request value watchable, agent and store `ask` receivers take raw nouns, and API request gates don't take Jibb module imports, scry paths, more than one parameter or diff, or a parameter with a fold ([internal.jibb](../jibb-dev/lib/jibb/internal.jibb), [module-import-api-request-reason](../tests/golden/module-import-api-request-reason/)).
280+- Complete private module checking, other API shapes, root API and module kind checking, complete `ask` and `pure` checking and multi-action stores are not implemented (Kinds, Agent APIs and Shared state in [spec/decisions.md](spec/decisions.md)), and the partial report every golden `types.txt` prints declines modules the full check accepts.
281+- The `my-app` modules are checked with Hoon types read by `ride`, not through Clay as [prompts/milestone-2.md](prompts/milestone-2.md) asks; the Clay threads run only the partial checker, on synthetic modules ([clay-fixtures/](../tests/clay-fixtures/)).
282+- The parser still accepts `[]` and `m()`, which the decisions make errors (where to reject them waits for [review ruling 19](open-questions.md#review-rulings-waiting-for-iko)), and the 13 unasked grammar questions follow [provisional readings](open-questions.md#grammar-questions-never-put-to-the-docs-author).
283+- The prelude's inventory and signatures are not specified yet (question 3 in [open-questions.md](open-questions.md)), most collection operations are unsupported, the UI prelude has no raw-constructor encapsulation or duplicate-attribute check, and themes have no contrast check, rendering or font routing ([types-prelude-ui](../tests/golden/types-prelude-ui/), [jibb-theme](../tests/lib/jibb-theme.hoon)).
284+- Inference declines many shapes it should decide, and the Partial and Missing rows name them. The largest are `proj` with reordered fields (question 32 in [open-questions.md](open-questions.md)) or in nested contexts, patterns past 64 boolean alternatives or across cases, polymorphic recursion and other mixed gate/value cycles, holes in complex molds, and dynamic `qath` segments.
285+- Some definite errors come out as "unsupported": a child-message mismatch in UI composition, a gate or non-tape list in interpolation, union branch arms whose results are all pending tags, and wrong-owner tree construction ([types-prelude-ui](../tests/golden/types-prelude-ui/), [types-string-interpolation](../tests/golden/types-string-interpolation/), [types-union-patterns-generic](../tests/golden/types-union-patterns-generic/), [jibb-generic-construction](../tests/lib/jibb-generic-construction.hoon)). Diagnostics are coarse in places: one caret per site, record mismatches at the cast or edit, generic messages for imported union molds and repeated faces, and no Hoon case locations ([types-multi-call](../tests/golden/types-multi-call/), [type-import-diagnostic/about.txt](../tests/type-import-diagnostic/about.txt)).
286+- The Hoon importer leaves other nested unions, nested ordered maps, general disjointness, mark-reader overlap diagnostics, recursive aliases and marks, unfolding and complete import integration unfinished, and peels at most four `$~` wrappers ([compiler.md](compiler.md), [importer/tree.txt](../tests/importer/tree.txt), [jibb-import-default](../tests/lib/jibb-import-default.hoon)).
287+- No test reaches some stated limits: the 256-step `jrec-fuel`, program `main`'s shared 256-node budget, the 64-definition pending-tag retry behind the buttons error, defaults inside `$~` dependency proofs, and the rejection of re-exported watches and of aliased initializers ([jibb-dev/lib/jibb.hoon](../jibb-dev/lib/jibb.hoon)).
288+- No test or check measures performance. The timings in [compiler.md](compiler.md) and the library's notes are single runs, the brief's timings of the corpus and the `my-app` desk ([prompts/milestone-2.md](prompts/milestone-2.md)) are not recorded, and neither the tuple payload context nor reader diagnostic replay has a complexity bound.
247289
248290## Checking it
249291
250−On a machine set up as [development.md](development.md) says:
251−
252−```
253−tools/golden # 660 cases under urbit eval
254−tools/test-arms # the my-app copies, then every tests/lib suite under urbit eval
255−tools/test-arms --list # the suites and their arms; ", report" marks a golden report
256−tools/test-arms --report jibb-import # print a golden-report suite's report
257−tools/test-arms --update jibb-import # write it to the suite's expected file
258−tools/test-arms jibb-import # the Hoon importer fixture projection
259−tools/test-arms jibb-import-default # default-wrapped source proof golden
260−tools/test-arms jibb-bridge # the importer/checker bridge fixture
261−tools/test-arms jibb-import-overlap # source-aware Hoon overlap and provenance fixture
262−tools/test-arms jibb-import-structural # structural overlap and multi-case source fixture
263−tools/test-arms jibb-union-source # local generic-alias union guards
264−tools/test-arms jibb-union-alias-overlap # local generic-alias overlap diagnostics
265−tools/test-arms 'jibb-full-overlap-*' # full-module overlap evidence, in two suites
266−tools/test-arms jibb-tlon-bridge # the real Tlon reader/checker fixture
267−tools/test-arms jibb-mark-bridge # the mark/checker bridge fixture
268−tools/test-arms jibb-poke-bridge # the source-backed poke/API fixture
269−tools/test-arms jibb-api-evidence # API declaration evidence guards
270−tools/test-arms jibb-api-paths # partial API path metadata fixture
271−tools/test-arms jibb-hole-guards # hole defaulting and API interface guards
272−tools/test-arms jibb-list-alias-guards # prelude list-alias guards
273−tools/test-arms jibb-generic-alias # generic union alias guards
274−tools/test-arms jibb-generic-recursion # source-proven generic recursion guards
275−tools/test-arms jibb-generic-construction # source-proven recursive construction guards
276−tools/test-arms jibb-generic-pattern # source-proven recursive pattern guards
277−tools/test-arms jibb-deferred # source-owned deferred inference guards
278−tools/test-arms jibb-deferred-resolver # resolver consistency and failure guards
279−tools/test-arms jibb-deferred-context # deferred source-order and branch guards
280−tools/test-arms jibb-deferred-prepared # prepared initializer reports and failure guards
281−tools/test-arms jibb-empty # empty molds and coverage guards
282−tools/test-arms jibb-cell-branch # branch context and rollback guards
283−tools/test-arms jibb-positional-face-guards # positional sample face guards
284−tools/test-arms 'jibb-qath-*' # qath source and unfolding guards, in two suites
285−tools/test-arms jibb-ask-guards # ask source and bootstrap guards
286−tools/test-arms jibb-proj-guards # projection evidence and scope guards
287−tools/test-arms jibb-buttons # documented buttons schemes and exact pending-tag error
288−tools/test-arms jibb-theme # byte-identical real theme, exact type and rejection guards
289−tools/test-arms jibb-module-scope # module and prelude scope fixture
290−tools/test-arms jibb-program-main # closed program-main interface and rejection guards
291−tools/test-arms jibb-program-init # transactional direct-program initializer context guards
292−tools/test-arms jibb-program-update # transactional direct-program update context guards
293−tools/test-arms jibb-program-watch # direct request-value watchability guards
294−tools/test-arms jibb-todo-full # byte-identical full todo and rejection guards
295−tools/test-arms jibb-check-spans # the span checker catches planted wrong spans
296−tools/test-arms jibb-hoon-reference # Hoon translations of zing, lead, late and succ agree with Hoon's
297−tools/testdata/selftest # the tools themselves
298−tools/doc-blocks docs/spec # the doc's examples are golden cases
299−tools/ship start
300−tools/ship test # the same 660 cases, and every tests/lib suite, as -test arms on the ship
301−tools/testdata/ship-selftest
302−tools/ship check-commit # |commit stores .jibb files
303−tools/clay-fixtures # example /sur files and marks build through Clay
304−```
305−
306−`tools/test-arms` runs the `test-` arms of the `tests/lib` suites under eval, and `tools/ship test` runs the same arms on the ship. [The test suites](development.md#the-test-suites) in development.md says what each suite checks. `tools/check` runs them in four shards balanced by measured cost, `arms-1` to `arms-4`; `tools/check --list` prints its checks, and `tools/test-arms --shard 2/4 --list` the suites in one shard. Where a comment above says byte-identical, the suite reads a copy of the `my-app` file kept under `tests/`. `tools/test-arms --copies`, and `tools/test-arms` with no suite or shard named, check that every copy listed in `tests/my-app-copies.txt` still matches its source; naming a suite skips that check.
307−
308−## What milestone 1 leaves to later milestones
309−
310−- Errors carry a start only. Spans keep each node's end so that milestone 2's type errors can underline both conflicting sites with excerpts (library section 1).
311−- The parser accepts forms for the checker to judge: `[]`, `[a]`, `m()`, `!! a`, and the module kinds. `[]` and `m()` have since been decided to be errors, and `[a]` is `a`; the parser has not changed. The Grammar's buttons example parses, though the doc marks it as a type error.
312−- Grammar questions the doc's author hasn't been asked follow the readings in [open-questions.md](open-questions.md).
292+[Before pushing](development.md#before-pushing) in development.md says how to run every check (`tools/check`; `tools/check --list` prints them), and [The test suites](development.md#the-test-suites) says what each suite checks. The [README](../README.md) gives each tool's commands: the [golden tests](../README.md#golden-tests), the [test suites](../README.md#test-suites), the [fake ship](../README.md#fake-ship) and [Nix](../README.md#building-and-checking-with-nix). `tools/test-arms --shard 2/4 --list` prints the suites of one shard.
jibb-dev/lib/jibb.hoon+1226−254
@@ -206,9 +206,11 @@
206206:: token holds the text after @. An aura starting @s or
207207:: @r is an error at 2nd: "signed and floating-point
208208:: auras are left out of Jibb"
209−:: A-Z type variable: one capital. A letter or digit right
210−:: after it is an error there, "a type variable is one
211−:: capital letter", after the type variable's token
209+:: A-Z type variable [A-Z][a-z0-9]*: a capital, then
210+:: lowercase letters and digits, as M, Msg or T2. Right
211+:: after it, which is emitted first, a capital, _ or -
212+:: is an error there, "a type variable is a capital,
213+:: then lowercase letters and digits"
212214:: a-z name [a-z][a-z0-9-]*, or a wing: two or more names
213215:: joined by dots. Right after the name or wing, which
214216:: is emitted first, a capital or _ is an error there,
@@ -405,6 +407,7 @@
405407:: Why: after the layout pass the grammar is LL(2). Each choice is made by
406408:: the next token, at most with the one after it and whether it is tight:
407409:: name, then = tight a face (items, lines, fields, samples)
410+:: wing, then = tight a change's item or line, wing=value
408411:: name, then + tight a pair
409412:: name or wing, then ( tight a change
410413:: |=, then a term tight a constructor; else, where an
@@ -412,6 +415,9 @@
412415:: ++ or +$ a definition; else a body's final expr
413416:: INDENT a body, an open bracket's lines, arms
414417:: or cases; else the expression goes on
418+:: NEWLINE, after a rune's head the rest of the body, on a body's
419+:: or ?-'s subject final line (The rest of a body);
420+:: else an error
415421:: So the parser never backtracks, its first failure is its furthest, and
416422:: "expected X, found Y" falls out of each arm without tracking failures
417423:: across alternatives. Hoon's combinators read tapes of characters and
@@ -455,7 +461,9 @@
455461:: cases below -> %mold; one case is that mold, several
456462:: are %union. The optional generic wraps either in %generic.
457463:: ++ name expr or body -> %value (a body becomes a %body expr)
458−:: body INDENT { definition NEWLINE } expr DEDENT -> %body
464+:: body INDENT rest DEDENT; rest is { definition NEWLINE } last
465+:: -> %body, and last is expr, or the rest of a body that
466+:: a rune on its final line took (The rest of a body)
459467:: call one operand is that operand; more -> %call head args
460468:: operand literal -> %lit or %str; pathlit -> %path, as a path
461469:: literal is an expression (Decisions); !! -> %crash, as
@@ -472,7 +480,9 @@
472480:: that line, as () is no group. A ( followed by a rune is
473481:: the closed form. Lines of an open group or list take no
474482:: name= (doc question)
475−:: change every item and line has name= (the EBNF's "items named")
483+:: change every item and line has name= or wing=, as open.cart=
484+:: (the EBNF's edit) -> %change of edits, each with its
485+:: names as written; a tuple's item takes no wing=
476486:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch.
477487:: !! is an operand, not a rune (Decisions): alone where an
478488:: expression goes it is a call of one operand, and !! a
@@ -553,7 +563,23 @@
553563:: - Local definitions: at the start of any body, a gate's, an arm's,
554564:: a ^-'s, a ~&'s or a ++'s, as the EBNF's body takes them
555565:: (Decisions); +$ as well as ++, as the Runes prose's "likewise"
556−:: says.
566+:: says. The rest of a body is a body too, so it takes them.
567+:: - The rest of a body (decided 2026-11-03, syntax review S2): a
568+:: body's final line is read with a flag, fin (+read-last), that
569+:: passes down the chain of runes on the line, as ^- @ud ~& x, while
570+:: nothing on the line is left open. A rune whose last child would
571+:: go next, and finds NEWLINE there, takes the lines after it at its
572+:: depth as that child, a body of its own (+read-rest); a ?- that
573+:: begins the line takes them as its arms (+read-branch). The flag
574+:: is off everywhere else: in a bracket, on an arm's line, for a
575+:: definition's own expression, and for a ?- after a rune on the
576+:: line, so ^- @ud ?- x keeps its arms deeper. A line nothing takes
577+:: is an error as before. A rest ends at its body's DEDENT, which
578+:: +read-rest leaves for whatever opened the body, so one DEDENT
579+:: ends every rest nested on that body's lines. Each rest is a level
580+:: of nesting, so the stack grows with them, as with brackets: a
581+:: body of 20.000 ~& x lines at one depth parses, and one of 40.000
582+:: runs out of memory, where 40.000 nested parentheses don't.
557583:: - Where errors point: the doc says only "line, column and an
558584:: excerpt"; 2.0 and Errors below say where.
559585::
@@ -604,11 +630,12 @@
604630:: found the end of the line" (+fail-space). No later line can give
605631:: a tight form its next token. A wing and a ( after a space are no
606632:: error: that is a call; nor is / or %/ alone, a whole path. A
607−:: change's item is name=, so a name there with no = right after it
608−:: fails just past the name, whatever follows: `m(b c)` at the
609−:: space, `m(b)` at the ), `m(a"x)` at the " with the layout pass's
610−:: message after the parser's (+unnamed, +moved). `m(a==1)` has its
611−:: =, and fails at the second, where the layout pass does.
633+:: change's item is name= or wing=, so a name or a wing there with
634+:: no = right after it fails just past it, whatever follows: `m(b c)`
635+:: and `m(a.b 1)` at the space, `m(b)` at the ), `m(a"x)` at the "
636+:: with the layout pass's message after the parser's (+unnamed,
637+:: +moved). `m(a==1)` has its =, and fails at the second, where the
638+:: layout pass does.
612639:: - Where the place needs text on its own line and the line ends,
613640:: whatever line comes next: at the end of that line, just past its
614641:: last token, "found the end of the line" (+fail-line), as no later
@@ -786,7 +813,9 @@
786813:: (value 8:1 init
787814:: (cast 8:9
788815:: (ref 8:12 state)
789−:: (tuple 8:18 (lit 8:19 ~) (lit 8:21 %.n))))
816+:: (tuple 8:18
817+:: (face 8:19 items (lit 8:25 ~))
818+:: (face 8:27 open (lit 8:32 %.n)))))
790819:: (value 9:1 update
791820:: (gate 9:11
792821:: (cell 9:14
@@ -795,17 +824,17 @@
795824:: (body 10:3
796825:: (branch 10:3
797826:: (wing 10:6 a)
798−:: (arm 11:5
799−:: (cell 11:5 (lit 11:6 %add) (bind 11:11 item))
800−:: (change 11:18 s
801−:: (edit 11:20 items
802−:: (tuple 11:26 (wing 11:27 item) (wing 11:32 items.s)))))
803−:: (arm 12:5
804−:: (lit 12:5 %toggle)
805−:: (change 12:18 s
806−:: (edit 12:20 open
807−:: (group 12:25
808−:: (call 12:26 (wing 12:26 not) (wing 12:30 open.s)))))))))))
827+:: (arm 11:3
828+:: (cell 11:3 (lit 11:4 %add) (bind 11:9 item))
829+:: (change 11:16 s
830+:: (edit 11:18 items
831+:: (tuple 11:24 (wing 11:25 item) (wing 11:30 items.s)))))
832+:: (arm 12:3
833+:: (lit 12:3 %toggle)
834+:: (change 12:16 s
835+:: (edit 12:18 open
836+:: (group 12:23
837+:: (call 12:24 (wing 12:24 not) (wing 12:28 open.s)))))))))))
809838::
810839:: 4.3 Errors (+show-error): "<file>:<line>:<col>: <message>", then the
811840:: source line, then a caret under the column (col - 1 spaces, then ^).
@@ -816,9 +845,93 @@
816845:: prints as a space, so the caret stays under its column and golden
817846:: files hold no raw control bytes.
818847::
819−:: /ui/basket.jibb:22:5: msg has no case %submitt
820−:: %submitt [m(note="") ~]
821−:: ^
848+:: /ui/basket.jibb:22:3: msg has no case %submitt
849+:: %submitt [m(note="") ~]
850+:: ^
851+::
852+:: ===================================================================
853+:: 5. General checker core (design; not implemented yet)
854+:: ===================================================================
855+::
856+:: The existing inference and recovery paths are described in
857+:: docs/compiler.md. This section is a plan for replacing them, not a
858+:: claim that the current checker implements these rules. The Grammar and
859+:: Decisions are authoritative if this design needs adjustment.
860+::
861+:: 5.1 State and unification. Give each inference variable an identity and
862+:: a union-find entry: parent or binding, rank, level, source, rigidity,
863+:: and the atom, arithmetic-atom and gate-free obligations it carries.
864+:: Hoon's immutable maps hold the entries; operations return the updated
865+:: state. Find compresses paths in that returned state. Bind only after an
866+:: occurs check, merge obligations at roots, and lower levels throughout
867+:: the bound type to the root's level. A rigid written capital may acquire
868+:: allowed constraints but cannot be forced to a concrete type or a
869+:: different written capital. Keep origins for both sides of each fit so
870+:: a failure can show both excerpts. Recursive named molds retain their
871+:: identity; the occurs check is for inference variables, not a ban on
872+:: declared recursion.
873+::
874+:: A scheme quantifies eligible variables above the enclosing level;
875+:: instantiate with fresh variables and copy their obligations. Written
876+:: capitals respect their lexical scope, including sharing with a local
877+:: definition when the enclosing definition uses the same name. Retain
878+:: aura variables and directional aura fits, rather than turning every
879+:: fit into symmetric equality. At a faced position a capital binds the
880+:: type under the face; joining an unnamed position with a faced one keeps
881+:: the face, independently of the order of the inputs. Different explicit
882+:: faces conflict. No gate may hide inside a gate-free type, including in
883+:: a container; propagate the obligation through its arguments.
884+::
885+:: 5.2 Work queue. A constraint owns its source span, the types and
886+:: expression shape it depends on, and the information needed to report
887+:: failure. Tags and constructors, null, decimal and cell literals,
888+:: wings, changes, unface and unknown match subjects enter the same queue.
889+:: Index waiting constraints by the roots they read. Binding or merging a
890+:: root wakes its dependants; a retry either solves, fails with its sites,
891+:: or registers the roots still needed. Run to a fixed point, without
892+:: losing constraints when a root is redirected. Check patterns once the
893+:: subject is known. Contextual tags inspect case shapes and noun-equal
894+:: heads, retaining the named union and its site in diagnostics.
895+::
896+:: Variables reachable from an open tag constraint remain monomorphic
897+:: across definitions, so a later use, including main, can fix them.
898+:: Other eligible variables can generalize, with their atom and gate-free
899+:: obligations intact. At each definition boundary resolve its holes and
900+:: apply the specified decimal and cell defaults, without defaulting a
901+:: decimal whose definition is generic over its aura. A decimal fits @ud,
902+:: @u, @ and *; other concrete auras need their own literal. At module
903+:: completion retry the queue and report each still-open constraint at its
904+:: source; an unresolved tag asks for a ^-, never a guessed union.
905+::
906+:: 5.3 Definition order and kinds. Use the existing dependency graph's
907+:: strongly connected components in dependency order. Give a recursive
908+:: group of gates monomorphic placeholders, infer all members in one state,
909+:: solve what can be solved, then generalize together. Reject a cycle
910+:: involving a non-gate value, including one through a gate, and show the
911+:: cycle. Check a named definition's holes before later uses can fix them.
912+:: Infer main as an ordinary expression against ordinary prelude schemes;
913+:: only its resulting type determines library, page, island or store.
914+:: Afterwards check kind-specific invariants: recursively find the field
915+:: containing a gate in island data or a model, and inspect subscriptions
916+:: for watchability only at %watch. A page load may be any gate to ask,
917+:: including pure and typed paths. Preserve request provenance needed for
918+:: a watchability proof through ordinary calls and aliases.
919+::
920+:: 5.4 Matches and migration. A reusable usefulness matrix over noun
921+:: constructors, constants, cells and wildcards checks nested patterns;
922+:: loobeans, lists and units expand to their cases. Test an arm against
923+:: previous rows for usefulness, then test a wildcard for exhaustiveness;
924+:: keep a witness for a missing case and the covering arm's site for a
925+:: dead one. Recursive types require memoized specialization and a
926+:: terminating treatment of recursive states. The same matrix can later
927+:: drive lowering. The bare-name/tag spelling rule is checked against the
928+:: subject and the cases the rest of the pattern can match.
929+::
930+:: Migrate in small stages with eval and ship goldens for every change.
931+:: Keep diagnostics and source sites in the single full result; types.txt
932+:: is a rendering of that result. As general inference covers an existing
933+:: recovery or source-proven slice, remove that slice and retain its tests.
934+:: An unsupported construct fails closed at its own site until then.
822935::
823936|%
824937+| %positions
@@ -964,9 +1077,10 @@
9641077::
9651078+$ item $~([*span ~ *expr] [at=span face=(unit term) val=expr])
9661079::
967−:: +edit: a change's item or line, name=value
1080+:: +edit: a change's item or line, name=value or wing=value; names
1081+:: as written, as a %wing's: open.cart is ~[%open %cart]
9681082::
969−+$ edit $~([*span %$ *expr] [at=span name=term val=expr])
1083++$ edit $~([*span ~ *expr] [at=span names=(list term) val=expr])
9701084::
9711085:: +arm: a ?- arm, a pattern and an expression or body
9721086::
@@ -1355,10 +1469,10 @@
13551469 =? n &(?=(^ rest) (is-upper i.rest)) +(n)
13561470 (emit +(n) [%aura (@ta (crip (scag n t.cs)))])
13571471 ?: (is-upper a)
1358− => (emit 1 [%tvar a])
1359− ?. &(?=(^ cs) |((is-lower i.cs) (is-upper i.cs) (is-digit i.cs)))
1360− cor
1361− (err col "a type variable is one capital letter")
1472+ =/ n=@ud (run-len t.cs tvar-mask)
1473+ => (emit +(n) [%tvar (crip [a (scag n t.cs)])])
1474+ ?. &(?=(^ cs) |((is-upper i.cs) =('_' i.cs) =('-' i.cs))) cor
1475+ (err col "a type variable is a capital, then lowercase letters and digits")
13621476 ?: =(':' a)
13631477 ?. =(0 dep) (err col "a comment can't start inside `\{…}`")
13641478 ?: =(':' b) comment
@@ -1662,6 +1776,7 @@
16621776++ digit-mask 0x3ff.0000.0000.0000 :: 0-9
16631777++ hex-mask 0x7e.0000.0000.03ff.0000.0000.0000 :: 0-9 a-f
16641778++ name-mask 0x7ff.fffe.0000.0000.03ff.2000.0000.0000 :: a-z 0-9 -
1779+++ tvar-mask 0x7ff.fffe.0000.0000.03ff.0000.0000.0000 :: a-z 0-9
16651780++ knot-mask 0x47ff.fffe.8000.0000.03ff.6000.0000.0000 :: and . ~ _
16661781++ number-mask 0x7ff.fffe.07ff.fffe.03ff.4000.0000.0000 :: a-z A-Z 0-9 .
16671782++ bad-mask 0x8000.0000.0000.0000.0000.0000.ffff.fbff :: 2.2
@@ -2280,7 +2395,7 @@
22802395++ sexp-edit
22812396 |= e=edit
22822397 ^- sexp
2283− (nod "edit" at.e (trip name.e) ~[(sexp-expr val.e)])
2398+ (nod "edit" at.e (show-names names.e) ~[(sexp-expr val.e)])
22842399::
22852400++ sexp-arm
22862401 |= a=arm
@@ -2689,24 +2804,32 @@
26892804 ?~ t.els i.els
26902805 [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
26912806::
2807+:: +slot: a bracket's item or line as read, before +bracket-node
2808+:: makes it an item or an edit: its name=, or a change's wing=, else ~
2809+::
2810++$ slot [at=span face=(list term) val=expr]
2811+::
26922812:: +bracket-node: a tuple, list or change from its items, ending at fin
26932813::
26942814++ bracket-node
26952815 |= $: kind=?(%tuple %list %change)
26962816 op=token
26972817 target=(unit [t=token names=(list term)])
2698− its=(list item)
2818+ its=(list slot)
26992819 fin=loc
27002820 ==
27012821 ^- expr
27022822 ?- kind
2703− %tuple [%tuple [beg.at.op fin] its]
2704− %list [%list [beg.at.op fin] (turn its |=(i=item val.i))]
2823+ %tuple
2824+ :+ %tuple [beg.at.op fin]
2825+ (turn its |=(i=slot ^-(item [at.i ?~(face.i ~ `i.face.i) val.i])))
2826+ ::
2827+ %list [%list [beg.at.op fin] (turn its |=(i=slot val.i))]
27052828 ::
27062829 %change
27072830 =/ beg=loc ?~(target beg.at.op beg.at.t.u.target)
27082831 :^ %change [beg fin] ?~(target ~ names.u.target)
2709− (turn its |=(i=item ^-(edit [at.i ?~(face.i %$ u.face.i) val.i])))
2832+ (turn its |=(i=slot ^-(edit [at.i face.i val.i])))
27102833 ==
27112834::
27122835+| %parser
@@ -2927,23 +3050,22 @@
29273050 ::
29283051 :: +unnamed: a change's item or line without its name=
29293052 ::
2930− :: A name could still begin one, so the error is just past it, as
2931− :: a tight form's is (+fail-space): `m(b c)` at the space, `m(b)`
2932− :: at the ). So is an error token's text there, unless it begins
2933− :: with the =: `m(a"x)` at the ", with the layout pass's message
2934− :: after the parser's (+moved), but `m(a==1)` at the lexer's error,
2935− :: the second =. So is a wing's first name: `m(a.b=1)` fails at the
2936− :: dot (+fail-in). At an error token whose text can't begin a name,
2937− :: at that text, as `m( @sd` at the @ (+fail-in).
3053+ :: A name or a wing could still begin one, so the error is just
3054+ :: past it, as a tight form's is (+fail-space): `m(b c)` and
3055+ :: `m(a.b 1)` at the space, `m(b)` at the ). So is an error token's
3056+ :: text there, unless it begins with the =: `m(a"x)` at the ", with
3057+ :: the layout pass's message after the parser's (+moved), but
3058+ :: `m(a==1)` at the lexer's error, the second =. At an error token
3059+ :: whose text can't begin a name, at that text, as `m( @sd` at the
3060+ :: @ (+fail-in).
29383061 ::
29393062 ++ unnamed
29403063 |= ts=(list token)
29413064 ^- [%| p=error]
29423065 =/ why=tape "a change's items are named, as in m(done=%.y)"
29433066 ?: ?=([[* * [%error *]] *] ts) (bad-in ts "a named item" lower-mask)
2944− ?: ?=([[* * [%wing *]] *] ts)
2945− (bad-in-why ts "a named item" lower-mask why)
2946− ?. ?=([[* * [%name *]] *] ts) (bad-why ts "a named item" why)
3067+ ?. ?=([[* * ?([%name *] [%wing *])] *] ts)
3068+ (bad-why ts "a named item" why)
29473069 =/ want=tape "`=` right after {(show-found i.ts)}"
29483070 ?: ?& ?=([* [* * [%error *]] *] ts)
29493071 =(end.at.i.ts from.lex.i.t.ts)
@@ -2961,9 +3083,10 @@
29613083 :: closes on its line (2.9). A bracket that needs none of these
29623084 :: closes with the deeper lines instead (+shut). No later line can
29633085 :: give it that, so the error is at the end of the line that took
2964− :: them (section 3, Errors). want is what it needs. Only an error path
2965− :: calls this, and it looks only when after begins with NEWLINE or
2966− :: DEDENT, so it costs nothing on the way to a tree.
3086+ :: them (section 3, Errors). want is what it needs. It looks only when
3087+ :: after begins with NEWLINE or DEDENT, so it costs nothing on the way
3088+ :: to a tree, except where a rune takes the rest of a body (+read-last):
3089+ :: a look at that rune's line.
29673090 ::
29683091 ++ doomed
29693092 |= [ts=(list token) after=(list token) want=tape]
@@ -3120,7 +3243,7 @@
31203243 ?: =(%'++' lex.rune)
31213244 ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
31223245 ;< [e=expr more=(list token)] then
3123− (read-expr-or-body "the name" after)
3246+ (read-expr-or-body | "the name" after)
31243247 [%& [%value [beg.at.rune end:(span-of e)] nam e] more]
31253248 ?: (is-closer rune)
31263249 %^ bad-why ts "a definition"
@@ -3200,20 +3323,36 @@
32003323 [%& p.lex.i.ts t.ts]
32013324 ::
32023325 :: +read-expr-or-body: a space and an expression on the line, or a
3203− :: body on deeper lines; what names what comes before, for errors
3326+ :: body on deeper lines; what names what comes before, for errors.
3327+ :: On a body's final line (fin, +read-last), a line at the same depth
3328+ :: is the rest of the body instead, and the expression on the line
3329+ :: goes on with fin, except a ?-, which keeps its arms deeper
32043330 ::
32053331 ++ read-expr-or-body
3206− |= [what=tape ts=(list token)]
3332+ |= [fin=? what=tape ts=(list token)]
32073333 ^- (pare expr)
32083334 ?: ?=([[* * %indent] *] ts) (read-body t.ts)
3335+ ?: &(fin ?=([[* * %newline] *] ts)) (read-rest t.ts)
32093336 ?: ?=([[* * ?(%newline %dedent)] *] ts)
32103337 (bad ts "an expression, or a body on deeper lines")
32113338 ?: &(?=(^ ts) tight.i.ts) (no-gap ts "a space after {what}")
3212− (read-expr ts)
3339+ (read-last &(fin !?=([[* * %'?-'] *] ts)) ts)
32133340 ::
3214− :: +read-body: after its INDENT, { definition NEWLINE } expr DEDENT
3341+ :: +read-body: after its INDENT, the rest of a body, then its DEDENT
32153342 ::
32163343 ++ read-body
3344+ |= ts=(list token)
3345+ ^- (pare expr)
3346+ ;< [e=expr after=(list token)] then (read-rest ts)
3347+ ?> ?=([[* * %dedent] *] after)
3348+ [%& e t.after]
3349+ ::
3350+ :: +read-rest: { definition NEWLINE } last, up to the DEDENT that ends
3351+ :: a body, which it leaves for whatever opened the body: its INDENT's
3352+ :: reader, or the rune on the final line that took the rest of it
3353+ :: (+read-last)
3354+ ::
3355+ ++ read-rest
32173356 |= ts=(list token)
32183357 ^- (pare expr)
32193358 =| defs=(list def)
@@ -3227,12 +3366,15 @@
32273366 %: bad-in-why ts "a definition or an expression" plus-mask
32283367 "`+` begins `++` or `+$`"
32293368 ==
3230− ;< [e=expr after=(list token)] then (read-expr ts)
3369+ ;< [e=expr after=(list token)] then (read-last & ts)
32313370 ?: ?=([[* * %dedent] *] after)
32323371 =/ ds=(list def) (flop defs)
32333372 =/ beg=loc ?~(ds beg:(span-of e) beg:(span-of i.ds))
3234− [%& [%body [beg end:(span-of e)] ds e] t.after]
3373+ [%& [%body [beg end:(span-of e)] ds e] after]
32353374 ?. ?=([[* * %newline] *] after) (bad-end-in after (tail-can e))
3375+ ?: &(?=(%branch -.e) !?=([* [* * ?(%'++' %'+$')] *] after))
3376+ %^ bad-why after "the end of the body"
3377+ "this `?-`'s arms are on deeper lines, so this one goes there too"
32363378 %^ bad-why after "the end of the body"
32373379 "a body's final expression is its last line"
32383380 ::
@@ -3241,13 +3383,24 @@
32413383 ++ read-expr
32423384 |= ts=(list token)
32433385 ^- (pare expr)
3386+ (read-last | ts)
3387+ ::
3388+ :: +read-last: +read-expr, where fin says the expression is a body's
3389+ :: final line or goes on one, with no bracket open before it: then
3390+ :: the rune that ends the line may take the rest of the body at the
3391+ :: same depth as its last child, and a ?- that begins the line its
3392+ :: arms (section 3, The rest of a body)
3393+ ::
3394+ ++ read-last
3395+ |= [fin=? ts=(list token)]
3396+ ^- (pare expr)
32443397 ?~ ts (bad ts "an expression")
32453398 =* t i.ts
32463399 ?+ lex.t (read-call ts)
3247− %'|=' ?:((is-ctor ts) (read-call ts) (read-gate t t.ts))
3248− %'^-' (read-cast t t.ts)
3249− %'~&' (read-trace t t.ts)
3250− %'?-' (read-branch t t.ts)
3400+ %'|=' ?:((is-ctor ts) (read-call ts) (read-gate fin t t.ts))
3401+ %'^-' (read-cast fin t t.ts)
3402+ %'~&' (read-trace fin t t.ts)
3403+ %'?-' (read-branch fin t t.ts)
32513404 ==
32523405 ::
32533406 :: +read-call: operand { operand }; one operand alone is itself
@@ -3462,9 +3615,9 @@
34623615 (unclosed par ")" after)
34633616 ;< [els=(list expr) after=(list token)] then (read-operands ts)
34643617 ?: ?=([[* * %indent] *] after)
3465− ;< [ls=(list item) more=(list token)] then
3618+ ;< [ls=(list slot) more=(list token)] then
34663619 (read-lines %group t.after)
3467− =/ inner=expr (call-of (weld els (turn ls |=(i=item val.i))))
3620+ =/ inner=expr (call-of (weld els (turn ls |=(i=slot val.i))))
34683621 [%& [%group [beg.at.par end:(span-of inner)] inner] more]
34693622 ?~ els
34703623 ?: ?=([[* * ?(%newline %dedent)] *] after)
@@ -3489,7 +3642,7 @@
34893642 ==
34903643 ^- (pare expr)
34913644 =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
3492− =| its=(list item)
3645+ =| its=(list slot)
34933646 |- ^- (pare expr)
34943647 ?~ ts (bad ts "an item")
34953648 =* t i.ts
@@ -3497,8 +3650,8 @@
34973650 [%& (bracket-node kind op target (flop its) end.at.t) t.ts]
34983651 ?: (is-closer t) (unclosed op (trip close) ts)
34993652 ?: ?=(%indent lex.t)
3500− ;< [ls=(list item) more=(list token)] then (read-lines kind t.ts)
3501− =/ every=(list item) (weld (flop its) ls)
3653+ ;< [ls=(list slot) more=(list token)] then (read-lines kind t.ts)
3654+ =/ every=(list slot) (weld (flop its) ls)
35023655 =/ fin=loc ?~(every end.at.op end.at:(rear every))
35033656 [%& (bracket-node kind op target every fin) more]
35043657 ?: &(?=(^ its) (shut op `at.i.its ts))
@@ -3506,21 +3659,21 @@
35063659 ?: ?=(?(%newline %dedent) lex.t)
35073660 (unclosed-open op (trip close) "an item" ts)
35083661 ?: &(tight.t ?=(^ its)) (no-space ts)
3509− ;< [i=item more=(list token)] then (read-item kind ts)
3662+ ;< [i=slot more=(list token)] then (read-item kind ts)
35103663 $(its [i its], ts more)
35113664 ::
35123665 :: +read-item: [ name= ] operand; a tuple's item may be named, a
3513− :: change's must be, a list's is not
3666+ :: change's must be, by a name or a wing, a list's is not
35143667 ::
35153668 ++ read-item
35163669 |= [kind=?(%tuple %list %change) ts=(list token)]
3517− ^- (pare item)
3518− ?: &(!?=(%list kind) ?=([[* * [%name *]] [* %& %'='] *] ts))
3670+ ^- (pare slot)
3671+ ?: &(?=([* * *] ts) (named-item kind ts))
35193672 =* nam i.ts
35203673 =/ rest=(list token) t.t.ts
35213674 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
35223675 ;< [v=expr after=(list token)] then (read-operand rest)
3523− [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3676+ [%& [[beg.at.nam end:(span-of v)] (names-of lex.nam) v] after]
35243677 ?: ?=(%change kind) (unnamed ts)
35253678 ?: &(?=(^ ts) (is-rune i.ts))
35263679 %: bad-in-why ts "an expression" operand-mask
@@ -3529,15 +3682,25 @@
35293682 ;< [v=expr after=(list token)] then (read-operand ts)
35303683 [%& [(span-of v) ~ v] after]
35313684 ::
3685+ :: +named-item: whether ts begins an item's or a line's name=: a
3686+ :: tuple's or a change's name, or a change's wing, then = tight
3687+ ::
3688+ ++ named-item
3689+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
3690+ ^- ?
3691+ ?. ?=([* [* %& %'='] *] ts) |
3692+ ?: ?=([[* * [%name *]] *] ts) ?=(?(%tuple %change) kind)
3693+ &(?=(%change kind) ?=([[* * [%wing *]] *] ts))
3694+ ::
35323695 :: +read-lines: after an open bracket's INDENT, its lines, an item
35333696 :: each, to its DEDENT
35343697 ::
35353698 ++ read-lines
35363699 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3537− ^- (pare (list item))
3538− =| ls=(list item)
3539− |- ^- (pare (list item))
3540− ;< [l=item after=(list token)] then (read-line kind ts)
3700+ ^- (pare (list slot))
3701+ =| ls=(list slot)
3702+ |- ^- (pare (list slot))
3703+ ;< [l=slot after=(list token)] then (read-line kind ts)
35413704 ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
35423705 ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
35433706 ?. ?=([[* * ?(%')' %']')] *] after) (bad-end-in after (tail-can val.l))
@@ -3564,22 +3727,20 @@
35643727 "its items end at the first line that isn't deeper"
35653728 ::
35663729 :: +read-line: an open bracket's line, [ name= ] expr; a tuple's may
3567− :: be named, a change's must be, a list's and a group's are not
3568− :: (doc question)
3730+ :: be named, a change's must be, by a name or a wing, a list's and a
3731+ :: group's are not (doc question)
35693732 ::
35703733 ++ read-line
35713734 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3572− ^- (pare item)
3735+ ^- (pare slot)
35733736 =/ cf (closer-first ts "an item")
35743737 ?^ cf u.cf
3575− ?: ?& ?=(?(%tuple %change) kind)
3576− ?=([[* * [%name *]] [* %& %'='] *] ts)
3577− ==
3738+ ?: &(?=([* * *] ts) (named-item kind ts))
35783739 =* nam i.ts
35793740 =/ rest=(list token) t.t.ts
35803741 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
35813742 ;< [v=expr after=(list token)] then (read-expr rest)
3582− [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3743+ [%& [[beg.at.nam end:(span-of v)] (names-of lex.nam) v] after]
35833744 ?: ?=(%change kind) (unnamed ts)
35843745 ;< [v=expr after=(list token)] then (read-expr ts)
35853746 [%& [(span-of v) ~ v] after]
@@ -3616,10 +3777,11 @@
36163777 %^ bad-why more (closing op ")")
36173778 "the wide gate's body is one operand, so a call goes in parentheses"
36183779 ::
3619− :: +read-gate: |= sample, then an expression or a body
3780+ :: +read-gate: |= sample, then an expression or a body; fin as for
3781+ :: +read-last
36203782 ::
36213783 ++ read-gate
3622− |= [bar=token ts=(list token)]
3784+ |= [fin=? bar=token ts=(list token)]
36233785 ^- (pare expr)
36243786 ?: &(?=(^ ts) tight.i.ts)
36253787 :: a % could begin a constructor's term, as |=%got
@@ -3631,13 +3793,14 @@
36313793 =/ dm (doomed ts after "an expression, or a body on deeper lines")
36323794 ?^ dm u.dm
36333795 ;< [e=expr more=(list token)] then
3634− (read-expr-or-body "the sample" after)
3796+ (read-expr-or-body fin "the sample" after)
36353797 [%& [%gate [beg.at.bar end:(span-of e)] s e] more]
36363798 ::
3637− :: +read-cast: ^- mold, then an expression or a body
3799+ :: +read-cast: ^- mold, then an expression or a body; fin as for
3800+ :: +read-last
36383801 ::
36393802 ++ read-cast
3640− |= [ket=token ts=(list token)]
3803+ |= [fin=? ket=token ts=(list token)]
36413804 ^- (pare expr)
36423805 ?: &(?=(^ ts) tight.i.ts) (wide-rune "^-" ts)
36433806 ;< [s=shape after=(list token)] then (read-mold ts)
@@ -3646,41 +3809,65 @@
36463809 =/ dm (doomed ts after "an expression, or a body on deeper lines")
36473810 ?^ dm u.dm
36483811 ;< [e=expr more=(list token)] then
3649− (read-expr-or-body "the mold" after)
3812+ (read-expr-or-body fin "the mold" after)
36503813 [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
36513814 ::
3652− :: +read-trace: ~& expr, then its body below
3815+ :: +read-trace: ~& expr, then its body below, or, on a body's final
3816+ :: line (fin, +read-last), the rest of the body
36533817 ::
36543818 ++ read-trace
3655− |= [sig=token ts=(list token)]
3819+ |= [fin=? sig=token ts=(list token)]
36563820 ^- (pare expr)
36573821 ?: &(?=(^ ts) tight.i.ts) (wide-rune "~&" ts)
36583822 ;< [v=expr after=(list token)] then (read-expr ts)
3659− ?. ?=([[* * %indent] *] after)
3660− =/ dm (doomed ts after "`~&`'s body on deeper lines")
3661− ?^ dm u.dm
3823+ =/ dm (doomed ts after "`~&`'s body on deeper lines")
3824+ ?^ dm u.dm
3825+ ;< [b=expr more=(list token)] then
3826+ ?: ?=([[* * %indent] *] after) (read-body t.after)
3827+ ?: &(fin ?=([[* * %newline] *] after)) (read-rest t.after)
36623828 (bad after "`~&`'s body on deeper lines")
3663− ;< [b=expr more=(list token)] then (read-body t.after)
36643829 [%& [%trace [beg.at.sig end:(span-of b)] v b] more]
36653830 ::
3666− :: +read-branch: ?- expr, then its arms below, one per line
3831+ :: +read-branch: ?- expr, then its arms below, one per line; or, when
3832+ :: it begins a body's final line (fin, +read-last), at its own depth
3833+ :: to the end of the body, whose DEDENT it leaves (+read-rest)
36673834 ::
36683835 ++ read-branch
3669− |= [wut=token ts=(list token)]
3836+ |= [fin=? wut=token ts=(list token)]
36703837 ^- (pare expr)
36713838 ?: &(?=(^ ts) tight.i.ts) (wide-rune "?-" ts)
36723839 ;< [s=expr after=(list token)] then (read-expr ts)
3673− ?. ?=([[* * %indent] *] after)
3674− =/ dm (doomed ts after "`?-`'s arms on deeper lines")
3675− ?^ dm u.dm
3840+ =/ dm (doomed ts after "`?-`'s arms on deeper lines")
3841+ ?^ dm u.dm
3842+ ?. ?=([[* * ?(%indent %newline)] *] after)
36763843 (bad after "`?-`'s arms on deeper lines")
3844+ =/ flat=? ?=(%newline lex.i.after)
3845+ ?: &(flat !fin) (bad after "`?-`'s arms on deeper lines")
36773846 =| arms=(list arm)
36783847 =/ rest=(list token) t.after
36793848 |- ^- (pare expr)
3680− ;< [a=arm more=(list token)] then (read-arm rest)
3849+ ;< [a=arm more=(list token)] then
3850+ ?:(flat (read-flat-arm rest) (read-arm rest))
36813851 ?: ?=([[* * %newline] *] more) $(arms [a arms], rest t.more)
36823852 ?. ?=([[* * %dedent] *] more) (bad-end-in more (tail-can val.a))
3683− [%& [%branch [beg.at.wut end.at.a] s (flop [a arms])] t.more]
3853+ =/ at=span [beg.at.wut end.at.a]
3854+ [%& [%branch at s (flop [a arms])] ?:(flat more t.more)]
3855+ ::
3856+ :: +read-flat-arm: +read-arm at its ?-'s depth, where a line that
3857+ :: could begin the body's other lines gets a hint
3858+ ::
3859+ ++ read-flat-arm
3860+ |= ts=(list token)
3861+ ^- (pare arm)
3862+ ?: ?=([[* * ?(%'++' %'+$')] *] ts)
3863+ %: bad-in-why ts "a pattern" pattern-mask
3864+ "a body's local definitions come before its final expression"
3865+ ==
3866+ ?: ?=([[* * ?(%'~&' %'^-')] *] ts)
3867+ %: bad-in-why ts "a pattern" pattern-mask
3868+ "a trace or cast goes in the arm's body"
3869+ ==
3870+ (read-arm ts)
36843871 ::
36853872 :: +read-arm: a pattern, then an expression or a body
36863873 ::
@@ -3695,7 +3882,7 @@
36953882 %^ bad-why after "a space after the pattern"
36963883 "patterns take no `name=`: a bare name binds, as [a b]"
36973884 ;< [e=expr more=(list token)] then
3698− (read-expr-or-body "the pattern" after)
3885+ (read-expr-or-body | "the pattern" after)
36993886 [%& [[beg:(span-of p) end:(span-of e)] p e] more]
37003887 ::
37013888 :: +read-pattern: a term, number, string, ship, loobean, ~, * or name,
@@ -4437,7 +4624,7 @@
44374624++ outline-edit
44384625 |= e=edit
44394626 ^- outline
4440− [%edit at.e ~[%name] %kid ~[(outline-expr val.e)]]
4627+ [%edit at.e ~[%name %wing] %kid ~[(outline-expr val.e)]]
44414628::
44424629++ outline-arm
44434630 |= a=arm
@@ -4614,7 +4801,10 @@
46144801:: Restricted-number promotion considers written capitals only; if there
46154802:: are none, it skips the otherwise unnecessary environment traversal.
46164803:: Bare @ is a separate unrestricted atom type. A directional fit check
4617−:: permits concrete atoms to widen to it, never the reverse. A fit that
4804+:: permits concrete atoms to widen to it, never the reverse. A bare
4805+:: decimal is a @ud: its variable binds only @ud or @u, it fits @ and *,
4806+:: and +decimal-misfit names it where it meets another aura (S4); a
4807+:: ++ generic over its aura generalizes it to any aura. A fit that
46184808:: needs a not-yet-implemented constraint remains unsupported. Named unions
46194809:: retain origin and ordered arguments, including phantom arguments, apart
46204810:: from their display name. Generic cases must be disjoint for all arguments.
@@ -4634,6 +4824,14 @@
46344824:: proofs to fewer than 1,024 cells; the projection planner has a separate
46354825:: 4,096-step bound. These are inference limits, not language limits.
46364826::
4827+:: `unface` is reserved with proj (+reserved-name) and is also handled by
4828+:: type: (unface e) has e's type with every face removed, through cells,
4829+:: gates and collection arguments, keeping unions and recursive molds
4830+:: whole (+itype-unface). It is not a value, it takes one argument, and
4831+:: a bare type variable is unsupported, as field access on one is. A ++
4832+:: whose body is (unface |= …) is a gate for recursion (+unfaced-gate).
4833+:: It lowers to its argument; no lowering is implemented yet.
4834+::
46374835:: Supported API imports derive request-gate types atomically for multiple
46384836:: paths, including one typed segment or one diff fold per case. Their checked
46394837:: ordinary definitions, mark molds and supported poke constructor are also
@@ -4845,7 +5043,8 @@
48455043:: +itype-unify: consistent substitutions, or ~ for a mismatch
48465044::
48475045:: Different concrete auras conflict. A variable may become an atom or
4848−:: a function, but cannot contain itself. Aura-only variables and faces
5046+:: a function, but cannot contain itself. A decimal's variable binds
5047+:: only @ud or @u (+decimal-aura). Aura-only variables and faces
48495048:: require further distinctions before this supports general Jibb.
48505049::
48515050++ itype-unify
@@ -4894,10 +5093,10 @@
48945093 ?: &(?=(%rnvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
48955094 ?: &(?=(%avar -.a) ?=(%rnvar -.b)) `[[id.a b] sub]
48965095 ?: ?=(%rnvar -.a)
4897− ?. |(?=(%rnvar -.b) ?=(%atom -.b)) ~
5096+ ?. |(?=(%rnvar -.b) &(?=(%atom -.b) (decimal-aura aura.b))) ~
48985097 `[[id.a b] sub]
48995098 ?: ?=(%rnvar -.b)
4900− ?. ?=(%atom -.a) ~
5099+ ?. &(?=(%atom -.a) (decimal-aura aura.a)) ~
49015100 `[[id.b a] sub]
49025101 ?: &(?=(%avar -.a) ?=(%rvar -.b)) `[[id.a b] sub]
49035102 ?: &(?=(%rvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
@@ -4908,14 +5107,15 @@
49085107 ?. ?=(%atom -.a) ~
49095108 `[[id.b a] sub]
49105109 :: The narrower decimal constraint survives a match with an atom
4911− :: variable; decimal syntax alone does not make it a loobean.
5110+ :: variable; decimal syntax alone does not make it a loobean. A
5111+ :: concrete aura takes a decimal only if it is @ud or @u.
49125112 ?: &(?=(%nvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
49135113 ?: &(?=(%avar -.a) ?=(%nvar -.b)) `[[id.a b] sub]
49145114 ?: ?=(%nvar -.a)
4915− ?. |(?=(%nvar -.b) ?=(%atom -.b)) ~
5115+ ?. |(?=(%nvar -.b) &(?=(%atom -.b) (decimal-aura aura.b))) ~
49165116 `[[id.a b] sub]
49175117 ?: ?=(%nvar -.b)
4918− ?. ?=(%atom -.a) ~
5118+ ?. &(?=(%atom -.a) (decimal-aura aura.a)) ~
49195119 `[[id.b a] sub]
49205120 ?: ?=(%avar -.a)
49215121 ?. |(?=(%avar -.b) ?=(%atom -.b) ?=(%any-atom -.b) ?=(%flag -.b)) ~
@@ -4939,6 +5139,35 @@
49395139 $(a tal.a, b tal.b, sub u.first)
49405140 ~
49415141::
5142+:: +itype-unface: t with every face removed, for (unface e)
5143+::
5144+:: It strips through cells, through a gate's sample and product and
5145+:: through a built-in collection's arguments, the prelude's unit
5146+:: included, walking bound variables. Other unions and recursive
5147+:: molds are compared by name or by their exact cases, so stripping
5148+:: inside them would stop them from fitting their own name: they are
5149+:: kept whole. An unbound variable stays, so faces it is bound to
5150+:: later are kept. The unit keeps its own u=, as a list keeps i= and
5151+:: t= in its mold.
5152+::
5153+++ itype-unface
5154+ |= [t=itype sub=isub]
5155+ ^- itype
5156+ =. t (itype-walk t sub)
5157+ ?+ -.t t
5158+ %face $(t body.t)
5159+ %cell [%cell $(t hed.t) $(t tal.t)]
5160+ %fn [%fn $(t sample.t) $(t product.t)]
5161+ %collection [%collection name.t (turn args.t |=(a=itype ^$(t a)))]
5162+ %union
5163+ ?. =(origin.t `[/lib/jibb/prelude/jibb %unit]) t
5164+ ?. ?=([* ~] args.t) t
5165+ =/ nil=itype [%const [%null %n 0 '~']]
5166+ ?. =(cases.t ~[nil [%cell nil [%face %u i.args.t]]]) t
5167+ =/ arg=itype $(t i.args.t)
5168+ t(cases ~[nil [%cell nil [%face %u arg]]], args ~[arg])
5169+ ==
5170+::
49425171+$ igf-form [typ=itype sub=isub left=@ud]
49435172+$ igf-forms [types=(list itype) sub=isub left=@ud]
49445173++ itype-gate-free-forms
@@ -5060,6 +5289,16 @@
50605289 ?. =(i.a i.b) |
50615290 $(a t.a, b t.b)
50625291::
5292+:: +decimal-aura: whether a bare decimal fits an atom of this aura
5293+::
5294+:: A decimal is a @ud, so as in Hoon it fits @ud and its ancestors
5295+:: @u and @; every other aura takes its own literal (S4).
5296+::
5297+++ decimal-aura
5298+ |= aura=@ta
5299+ ^- ?
5300+ (aura-prefix aura %ud)
5301+::
50635302:: Related auras in a structural unification need a common-type rule;
50645303:: until that rule is implemented, report an unknown rather than error.
50655304::
@@ -5795,6 +6034,24 @@
57956034 ["canonicalization should retain gate-free variables" problems]
57966035 =? problems !=((show-atom-constraint canonical-free) " where A contains no gates")
57976036 ["the printer should show gate-free constraints" problems]
6037+ =/ decimal=itype [%nvar 50]
6038+ =? problems ?=(~ (itype-unify decimal num ~))
6039+ ["a decimal should unify with @ud" problems]
6040+ =? problems ?=(~ (itype-unify [%atom %u] decimal ~))
6041+ ["a decimal should unify with @u" problems]
6042+ =? problems ?=(^ (itype-unify decimal [%atom %dr] ~))
6043+ ["a decimal should not unify with @dr" problems]
6044+ =? problems ?=(^ (itype-unify [%atom %ux] decimal ~))
6045+ ["a decimal should not unify with @ux" problems]
6046+ =/ restricted=(unit isub) (itype-unify decimal [%rvar 51] ~)
6047+ =? problems |(?=(~ restricted) ?=(^ (itype-unify [%rvar 51] [%atom %p] u.restricted)))
6048+ ["arithmetic should keep a decimal's aura rule" problems]
6049+ =/ decimal-any=ifit (itype-fit decimal [%any-atom ~] ~ 52)
6050+ =? problems !?=(%ok -.decimal-any)
6051+ ["a decimal should fit @" problems]
6052+ =/ decimal-noun=ifit (itype-fit decimal [%noun ~] ~ 52)
6053+ =? problems !?=(%ok -.decimal-noun)
6054+ ["a decimal should fit a noun" problems]
57986055 problems
57996056::
58006057:: The expression inference below is deliberately a fragment: bindings,
@@ -6342,15 +6599,67 @@
63426599 ^- ?
63436600 (itype-var-is-gate-free-fuel n t 256)
63446601::
6602+:: +named-var: the ID of the nth type variable, written as name
6603+::
6604+:: An ID counts in its low 64 bits. The name a variable was written
6605+:: with, as Msg, sits above them, or 0 for none, so the name travels
6606+:: with the variable through substitution, generalization and
6607+:: instantiation, and the printer can show it (+show-var). No two
6608+:: IDs share a count, so a name never makes two variables one.
6609+::
6610+++ named-var
6611+ |= [name=@t n=@ud]
6612+ ^- @ud
6613+ (add (lsh 6 name) (end 6 n))
6614+::
6615+:: +var-name: the name in a type variable's ID, or 0 for none
6616+::
6617+++ var-name
6618+ |= id=@ud
6619+ ^- @t
6620+ (rsh 6 id)
6621+::
6622+:: +var-count: a type variable's ID without its name
6623+::
6624+++ var-count
6625+ |= id=@ud
6626+ ^- @ud
6627+ (end 6 id)
6628+::
6629+:: +canonical-itype: t with the variables in vars renumbered to print
6630+::
6631+:: A variable keeps its name unless one before it in vars has the same
6632+:: name. The others take numbers from 0, skipping any whose letter
6633+:: (+show-var) is a name in vars, so a printed type never shows one
6634+:: name for two variables.
6635+::
63456636++ canonical-itype
63466637 |= [t=itype vars=(list @ud)]
63476638 ^- itype
6639+ =/ names=(list @t) (turn vars var-name)
6640+ =/ used=(list @t) ~
63486641 =/ ren=isub ~
63496642 =/ n=@ud 0
63506643 |-
63516644 ?~ vars (itype-rename t ren)
6352− =/ replacement=itype ?:((itype-var-is-restricted i.vars t) [%rvar n] ?:((itype-var-is-atom i.vars t) [%avar n] ?:((itype-var-is-gate-free i.vars t) [%fvar n] [%var n])))
6353− $(vars t.vars, ren [[i.vars replacement] ren], n +(n))
6645+ =/ name=@t (var-name i.vars)
6646+ =/ own=? &(!=(0 name) !(lien used |=(u=@t =(u name))))
6647+ =? n !own (letter-free n names)
6648+ =/ id=@ud ?:(own (named-var name 0) n)
6649+ =/ replacement=itype ?:((itype-var-is-restricted i.vars t) [%rvar id] ?:((itype-var-is-atom i.vars t) [%avar id] ?:((itype-var-is-gate-free i.vars t) [%fvar id] [%var id])))
6650+ $(vars t.vars, ren [[i.vars replacement] ren], n ?:(own n +(n)), used ?:(own [name used] used))
6651+::
6652+:: +letter-free: the first number from n whose letter is none of names
6653+::
6654+++ letter-free
6655+ |= [n=@ud names=(list @t)]
6656+ ^- @ud
6657+ ?. (lien names |=(m=@t =(m (crip (show-var n))))) n
6658+ $(n +(n))
6659+::
6660+:: +instantiate-scheme: a scheme's type with fresh quantified variables
6661+::
6662+:: Each fresh variable keeps the name of the one it replaces.
63546663::
63556664++ instantiate-scheme
63566665 |= [scheme=ischeme state=istate]
@@ -6359,12 +6668,13 @@
63596668 =/ vars=(list @ud) vars.scheme
63606669 |-
63616670 ?~ vars [(itype-rename typ.scheme ren) state]
6671+ =/ fresh=@ud (named-var (var-name i.vars) next.state)
63626672 =/ replacement=itype
6363− ?:((itype-var-is-restricted i.vars typ.scheme) [%rvar next.state] ?:((itype-var-is-atom i.vars typ.scheme) [%avar next.state] ?:((itype-var-is-gate-free i.vars typ.scheme) [%fvar next.state] [%var next.state])))
6673+ ?:((itype-var-is-restricted i.vars typ.scheme) [%rvar fresh] ?:((itype-var-is-atom i.vars typ.scheme) [%avar fresh] ?:((itype-var-is-gate-free i.vars typ.scheme) [%fvar fresh] [%var fresh])))
63646674 :: A generalized atom variable is a valid origin for re-generalizing
63656675 :: an alias, just as a sample binder is.
63666676 =/ st=istate state(next +(next.state))
6367− =? binders.st |(?=(%fvar -.replacement) ?=(%avar -.replacement) ?=(%rvar -.replacement)) [next.state binders.state]
6677+ =? binders.st |(?=(%fvar -.replacement) ?=(%avar -.replacement) ?=(%rvar -.replacement)) [fresh binders.state]
63686678 $(vars t.vars, ren [[i.vars replacement] ren], state st)
63696679::
63706680++ icap-lookup
@@ -7224,7 +7534,8 @@
72247534 ?: in-mold.state ~
72257535 =/ n=(unit @ud) (icap-lookup name.sh caps.state)
72267536 ?^ n `[[%var u.n] state]
7227− `[[%var next.state] state(next +(next.state), caps [[name.sh next.state at.sh] caps.state])]
7537+ =/ id=@ud (named-var name.sh next.state)
7538+ `[[%var id] state(next +(next.state), caps [[name.sh id at.sh] caps.state])]
72287539 * ~
72297540 ==
72307541::
@@ -7257,12 +7568,12 @@
72577568 ^- isample-result
72587569 ?- -.s
72597570 %bind
7260− ?: |(=(name.s %proj) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
7571+ ?: |((reserved-name name.s) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
72617572 [%| "sample shadows a name"]
72627573 =/ t=itype [%var next.state]
72637574 [%& t [[name.s [t ~]] env] state(next +(next.state), binders [next.state binders.state])]
72647575 %face
7265− ?: |(=(name.s %proj) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
7576+ ?: |((reserved-name name.s) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
72667577 [%| "sample shadows a name"]
72677578 =/ t=(unit [typ=itype state=istate]) (infer-simple-shape shape.s state)
72687579 ?~ t [%| "sample mold is not supported by partial inference"]
@@ -7330,7 +7641,7 @@
73307641 |-
73317642 ?~ ds &
73327643 ?: ?=(%mold -.i.ds) $(ds t.ds)
7333− ?: =(name.i.ds %proj) |
7644+ ?: (reserved-name name.i.ds) |
73347645 ?. (unique-value-name name.i.ds names) |
73357646 ?: ?=(^ (ienv-lookup name.i.ds env)) |
73367647 ?: (lien globals.state |=(n=term =(n name.i.ds))) |
@@ -7354,7 +7665,7 @@
73547665 |-
73557666 ?~ locals &
73567667 =/ n=term name.i.locals
7357− ?: =(n %proj) |
7668+ ?: (reserved-name n) |
73587669 ?. (unique-value-name n names) |
73597670 ?: (lien molds.state |=(m=[name=term body=shape] =(n name.m))) |
73607671 ?: (lien marks.state |=(m=term =(n m))) |
@@ -7504,7 +7815,8 @@
75047815 ^- istate
75057816 ?~ sites state
75067817 ?: ?=(^ (icap-lookup name.i.sites caps.state)) $(sites t.sites)
7507− $(sites t.sites, state state(next +(next.state), caps [[name.i.sites next.state at.i.sites] caps.state]))
7818+ =/ id=@ud (named-var name.i.sites next.state)
7819+ $(sites t.sites, state state(next +(next.state), caps [[name.i.sites id at.i.sites] caps.state]))
75087820::
75097821++ reserve-def-caps
75107822 |= [e=expr state=istate]
@@ -7678,7 +7990,8 @@
76787990 (weld (free-env-vars env sub.state.p.inferred) (free-cap-vars caps.state sub.state.p.inferred))
76797991 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
76807992 =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
7681− $(ds t.ds, env [[name.d [typ vars]] env], state state.p.inferred(caps caps.state, holes holes.state), progressed &)
7993+ =/ named=[typ=itype vars=(list @ud)] (cap-names typ vars caps.state.p.inferred sub.state.p.inferred)
7994+ $(ds t.ds, env [[name.d named] env], state state.p.inferred(caps caps.state, holes holes.state), progressed &)
76827995::
76837996:: Try complete cyclic local groups after individual definitions stall.
76847997:: Components with non-gates or unresolved constraints stay unavailable.
@@ -7768,6 +8081,8 @@
77688081 ?: &(?=(%collection -.expected) =(%list name.expected) (context-list-expression e))
77698082 (infer-list-context e expected env state context)
77708083 ?: ?=(%branch -.e)
8084+ =/ named=(unit idiag) (branch-tag-name e env state)
8085+ ?^ named [%| u.named]
77718086 =/ empty-list=(unit iresult) (empty-list-null-branch e env state `[expected context])
77728087 ?^ empty-list u.empty-list
77738088 ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
@@ -7808,6 +8123,8 @@
78088123 ?^ missing [%| u.missing]
78098124 =/ nested=(unit idiag) (nested-missing-tag e typ.p.value expected sub.state.p.value next.state.p.value context)
78108125 ?^ nested [%| u.nested]
8126+ =/ decimal=(unit idiag) (decimal-misfit e typ.p.value expected sub.state.p.value next.state.p.value)
8127+ ?^ decimal [%| u.decimal]
78118128 ?: &(?=(%collection -.expected) =(%list name.expected))
78128129 [%| ["branch arm does not fit its expected list" ~[[context "expected list"] [(span-of e) "branch arm"]]]]
78138130 ?: ?=(%flag -.expected)
@@ -7873,11 +8190,15 @@
78738190 =/ fit=ifit (itype-fit typ.p.tail target sub.state.p.tail next.state.p.tail)
78748191 ?: ?=(%unknown -.fit) [%| ["list tail constraint is not supported by partial inference" ~]]
78758192 ?: ?=(%bad -.fit)
8193+ =/ decimal=(unit idiag) (decimal-misfit val.i.t.items.e typ.p.tail target sub.state.p.tail next.state.p.tail)
8194+ ?^ decimal [%| u.decimal]
78768195 [%| ["list tail does not fit its expected type" ~[[context (site-type-note "expected list" target sub.state.p.tail)] [(span-of val.i.t.items.e) (site-type-note "list tail" typ.p.tail sub.state.p.tail)]]]]
78778196 [%& target state.p.tail(sub sub.fit, next next.fit)]
78788197::
8198+:: done holds the items already checked, the last first, so that a
8199+:: decimal among them can be blamed when a later item fixes its aura.
78798200++ infer-open-list-items
7880− |= [items=(list expr) expected=itype env=ienv state=istate context=span]
8201+ |= [items=(list expr) expected=itype env=ienv state=istate context=span done=(list expr)]
78818202 ^- iresult
78828203 ?~ items [%& expected state]
78838204 =/ target=itype (itype-walk expected sub.state)
@@ -7893,10 +8214,18 @@
78938214 ?: ?=(%bad -.fit)
78948215 ?: |((itype-family-related typ.p.value target sub.state.p.value) (itype-has-any-atom typ.p.value sub.state.p.value) (itype-has-any-atom target sub.state.p.value))
78958216 [%| ["list item widening is not supported by partial inference" ~]]
8217+ =/ decimal=(unit idiag) (decimal-misfit i.items typ.p.value target sub.state.p.value next.state.p.value)
8218+ ?^ decimal [%| u.decimal]
8219+ =/ earlier=(list expr) (flop done)
8220+ |- ^- iresult
8221+ ?^ earlier
8222+ =/ found=(unit idiag) (decimal-misfit-at i.earlier typ.p.value sub.state.p.value)
8223+ ?^ found [%| u.found]
8224+ $(earlier t.earlier)
78968225 [%| ["list items do not have compatible types" ~[[context (site-type-note "expected item" target sub.state.p.value)] [(span-of i.items) (site-type-note "list item" typ.p.value sub.state.p.value)]]]]
78978226 ?: (itype-has-tag (itype-normalize expected sub.fit))
78988227 [%| ["list item needs context in partial inference" ~]]
7899− $(items t.items, state state.p.value(sub sub.fit, next next.fit))
8228+ $(items t.items, state state.p.value(sub sub.fit, next next.fit), done [i.items done])
79008229::
79018230++ infer-list-items
79028231 |= [items=(list expr) expected=itype env=ienv state=istate context=span]
@@ -7917,6 +8246,8 @@
79178246 ?^ missing [%| u.missing]
79188247 =/ nested=(unit idiag) (nested-missing-tag i.items typ.p.value target sub.state.p.value next.state.p.value context)
79198248 ?^ nested [%| u.nested]
8249+ =/ decimal=(unit idiag) (decimal-misfit i.items typ.p.value target sub.state.p.value next.state.p.value)
8250+ ?^ decimal [%| u.decimal]
79208251 [%| ["list item does not fit its expected type" ~[[context (site-type-note "expected item" target sub.state.p.value)] [(span-of i.items) (site-type-note "list item" typ.p.value sub.state.p.value)]]]]
79218252 $(items t.items, state state.p.value(sub sub.fit, next next.fit))
79228253::
@@ -8014,7 +8345,7 @@
80148345 [%| ["list branch pattern is not supported by partial inference" ~]]
80158346 =/ binder=(unit [head=term tail=term]) ?:(first-empty second-name first-name)
80168347 ?~ binder [%| ["list branch pattern is not supported by partial inference" ~]]
8017− ?: |(=(head.u.binder %proj) =(tail.u.binder %proj) =(head.u.binder tail.u.binder) ?=(^ (ienv-lookup head.u.binder env)) ?=(^ (ienv-lookup tail.u.binder env)) (lien globals.state |=(n=term |(=(n head.u.binder) =(n tail.u.binder)))))
8348+ ?: |((reserved-name head.u.binder) (reserved-name tail.u.binder) =(head.u.binder tail.u.binder) ?=(^ (ienv-lookup head.u.binder env)) ?=(^ (ienv-lookup tail.u.binder env)) (lien globals.state |=(n=term |(=(n head.u.binder) =(n tail.u.binder)))))
80188349 [%| ["pattern binder shadows a name" ~]]
80198350 =/ extended=ienv [[head.u.binder [i.args.typ ~]] [tail.u.binder [typ ~]] env]
80208351 =/ left=iresult
@@ -8051,7 +8382,7 @@
80518382 [%| ["unit branch pattern is not supported by partial inference" ~]]
80528383 =/ binder=(unit term) ?:(first-empty second-name first-name)
80538384 ?~ binder [%| ["unit branch pattern is not supported by partial inference" ~]]
8054− ?: |(=(u.binder %proj) ?=(^ (ienv-lookup u.binder env)) (lien globals.state |=(n=term =(n u.binder))))
8385+ ?: |((reserved-name u.binder) ?=(^ (ienv-lookup u.binder env)) (lien globals.state |=(n=term =(n u.binder))))
80558386 [%| ["pattern binder shadows a name" ~]]
80568387 =/ payload=(unit itype) (unit-union-payload typ)
80578388 ?~ payload [%| ["unit branch subject is not supported by partial inference" ~]]
@@ -8158,11 +8489,83 @@
81588489 ^- (unit ienv)
81598490 =. t ?:(?=(%face -.t) body.t t)
81608491 ?: ?=(%bind -.p)
8161− ?: |(=(name.p %proj) ?=(^ (ienv-lookup name.p env)) (lien globals |=(n=term =(n name.p)))) ~
8492+ ?: |((reserved-name name.p) ?=(^ (ienv-lookup name.p env)) (lien globals |=(n=term =(n name.p)))) ~
81628493 `[[name.p [t ~]] env]
81638494 ?: ?=(%cell -.p) (union-pattern-bind-items items.p t env globals)
81648495 `env
81658496::
8497+:: +branch-tag-name: a ?- pattern name that spells one of the subject's tags
8498+::
8499+:: A name in a pattern binds, so `stop` written for `%stop` would
8500+:: catch every case left. Where the subject's type at a name's
8501+:: position is a union, or a one-case mold, with a case whose constant
8502+:: there is the term the name spells, the name is an error (Grammar,
8503+:: Patterns). Every path that checks a ?- asks this first, so they
8504+:: agree; it infers the subject apart and drops the state it leaves.
8505+:: A subject that fails, or whose type isn't known yet, is left to the
8506+:: path. Samples aren't patterns: every sample name binds.
8507+++ branch-tag-name
8508+ |= [e=expr env=ienv state=istate]
8509+ ^- (unit idiag)
8510+ ?. ?=(%branch -.e) ~
8511+ ?. (lien arms.e |=(a=arm (union-pattern-has-bind pat.a))) ~
8512+ =/ subject=iresult (infer-fragment subject.e env state)
8513+ ?: ?=(%| -.subject) ~
8514+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8515+ =/ arms=(list arm) arms.e
8516+ |-
8517+ ?~ arms ~
8518+ =/ found=(unit [at=span name=term]) (tag-name-pattern pat.i.arms typ ~)
8519+ ?~ found $(arms t.arms)
8520+ =/ name=tape (trip name.u.found)
8521+ :- ~
8522+ :- "`{name}` binds a name, but the subject's type has `%{name}` here; write %{name}, or * for a catch-all"
8523+ ~[[(span-of subject.e) "subject"] [at.u.found "pattern name"]]
8524+::
8525+:: +tag-name-pattern: the first name in p that t types by a tag
8526+::
8527+:: The walk enters faces, cells and unions, and of a union only the
8528+:: cases a cell pattern can match, so `[t %draft]` reads t at @t. It
8529+:: stops at atoms, `*`, variables, collections and recursive molds,
8530+:: and at a generic union's argument positions, which a type variable
8531+:: types in its mold, as u in `[~ u=A]`.
8532+++ tag-name-pattern
8533+ |= [p=pattern t=itype args=(list itype)]
8534+ ^- (unit [at=span name=term])
8535+ ?. ?=(?(%bind %cell) -.p) ~
8536+ ?: ?=(%face -.t) $(t body.t)
8537+ ?: (lien args |=(a=itype =(a t))) ~
8538+ ?: ?=(%union -.t)
8539+ =/ inner=(list itype) (weld args.t args)
8540+ =/ cases=(list itype) cases.t
8541+ |-
8542+ ?~ cases ~
8543+ ?: &(?=(%cell -.p) =(%none (union-pattern p i.cases))) $(cases t.cases)
8544+ =/ found=(unit [at=span name=term]) (tag-name-pattern p i.cases inner)
8545+ ?^ found found
8546+ $(cases t.cases)
8547+ ?: ?=(%cell -.p) (tag-name-items items.p t args)
8548+ ?. ?=(%const -.t) ~
8549+ ?. &(=(%term form.literal.t) =(%tas aura.literal.t) =(name.p val.literal.t)) ~
8550+ `[at.p name.p]
8551+::
8552+:: +tag-name-items: +tag-name-pattern along a cell pattern's items
8553+::
8554+:: As in +union-pattern-items, the last item takes the rest of the
8555+:: spine. A union mid-spine is read as the rest of the pattern.
8556+++ tag-name-items
8557+ |= [ps=(list pattern) t=itype args=(list itype)]
8558+ ^- (unit [at=span name=term])
8559+ ?~ ps ~
8560+ ?~ t.ps (tag-name-pattern i.ps t args)
8561+ ?: ?=(%face -.t) $(t body.t)
8562+ ?: (lien args |=(a=itype =(a t))) ~
8563+ ?: ?=(%union -.t) (tag-name-pattern [%cell at.i.ps ps] t args)
8564+ ?. ?=(%cell -.t) ~
8565+ =/ head=(unit [at=span name=term]) (tag-name-pattern i.ps hed.t args)
8566+ ?^ head head
8567+ $(ps t.ps, t tal.t)
8568+::
81668569:: Split loobean fields into finite refinements for partial patterns.
81678570:: Keep original cases for binder types and preserve whole-case matching
81688571:: before trying refinements. Cap products at 64; unknown, empty or opaque
@@ -8210,6 +8613,8 @@
82108613 ^- (unit iresult)
82118614 ?> ?=(%branch -.e)
82128615 ?: ?=(%| -.subject) `subject
8616+ =/ decimal=(unit idiag) (decimal-arms-misfit arms.e typ.p.subject sub.state.p.subject)
8617+ ?^ decimal `[%| u.decimal]
82138618 =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
82148619 ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
82158620 =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
@@ -8248,6 +8653,8 @@
82488653 ^- (unit iresult)
82498654 ?> ?=(%branch -.e)
82508655 ?: ?=(%| -.subject) `subject
8656+ =/ decimal=(unit idiag) (decimal-arms-misfit arms.e typ.p.subject sub.state.p.subject)
8657+ ?^ decimal `[%| u.decimal]
82518658 =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
82528659 ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
82538660 =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
@@ -8608,7 +9015,9 @@
86089015 `subject
86099016::
86109017:: Infer changes only against a fully known record spine. Retain the
8611−:: target type; unknown spines and repeated edits remain unsupported.
9018+:: target type; unknown spines and overlapping edits remain unsupported.
9019+:: An edit's wing, as open.cart, reads through record fields only,
9020+:: outermost first, and its value fits the field it names.
86129021++ change-spine-known
86139022 |= [t=itype sub=isub]
86149023 ^- ?
@@ -8620,26 +9029,87 @@
86209029 $(t tal.t)
86219030::
86229031++ infer-change-edits
8623− |= [edits=(list edit) target=itype env=ienv state=istate seen=(list term)]
9032+ |= [edits=(list edit) target=itype env=ienv state=istate seen=(list (list term))]
86249033 ^- iresult
86259034 ?~ edits [%& target state]
86269035 =/ entry=edit i.edits
8627− ?: (lien seen |=(name=term =(name name.entry)))
9036+ =/ outer=(list term) (flop names.entry)
9037+ ?: (lien seen |=(prior=(list term) (wing-overlap prior outer)))
86289038 [%| ["repeated change fields are not supported by partial inference" ~]]
86299039 ?. (change-spine-known target sub.state)
86309040 [%| ["change target needs a known record in partial inference" ~]]
8631− =/ found=(list itype) (record-fields-named name.entry target sub.state)
8632− ?~ found
8633− [%| ["record has no field `{(trip name.entry)}`" ~[[at.entry "unknown field"]]]]
8634− ?^ t.found [%| ["change field is ambiguous in partial inference" ~]]
8635− =/ expected=itype i.found
9041+ =/ field=(each itype idiag) (change-wing-field entry target sub.state)
9042+ ?: ?=(%| -.field) [%| p.field]
9043+ =/ expected=itype p.field
86369044 =/ value=iresult (infer-call-context-arg val.entry expected env state at.entry)
86379045 ?: ?=(%| -.value) value
86389046 =/ fit=ifit (itype-fit typ.p.value expected sub.state.p.value next.state.p.value)
86399047 ?: ?=(%unknown -.fit) [%| ["change field constraint is not supported by partial inference" ~]]
86409048 ?: ?=(%bad -.fit)
9049+ =/ decimal=(unit idiag) (decimal-misfit val.entry typ.p.value expected sub.state.p.value next.state.p.value)
9050+ ?^ decimal [%| u.decimal]
86419051 [%| ["change field and replacement do not unify" ~[[at.entry (site-type-note "expected replacement" expected sub.state.p.value)] [(span-of val.entry) (site-type-note "replacement" typ.p.value sub.state.p.value)]]]]
8642− $(edits t.edits, state state.p.value(sub sub.fit, next next.fit), seen [name.entry seen])
9052+ $(edits t.edits, state state.p.value(sub sub.fit, next next.fit), seen [outer seen])
9053+::
9054+:: +change-wing-field: the type of the field an edit's wing names in
9055+:: a known record target, read through record fields, outermost first
9056+::
9057+++ change-wing-field
9058+ |= [entry=edit target=itype sub=isub]
9059+ ^- (each itype idiag)
9060+ =/ outer=(list term) (flop names.entry)
9061+ =/ k=@ud (lent names.entry)
9062+ =/ typ=itype target
9063+ =| through=(unit [name=term at=span])
9064+ |- ^- (each itype idiag)
9065+ ?~ outer [%& typ]
9066+ =/ here=span (edit-name-at entry (dec k))
9067+ ?: &(?=(^ through) !(change-spine-known typ sub))
9068+ ?. (itype-not-record typ sub)
9069+ [%| ["change wing needs a known record in partial inference" ~]]
9070+ =/ label=tape "field `{(trip name.u.through)}`"
9071+ :- %|
9072+ :- "change wing `{(show-names names.entry)}` goes through `{(trip name.u.through)}`, which is not a record"
9073+ ~[[at.u.through (site-type-note label typ sub)]]
9074+ =/ found=(list itype) (record-fields-named i.outer typ sub)
9075+ ?~ found
9076+ [%| ["record has no field `{(trip i.outer)}`" ~[[here "unknown field"]]]]
9077+ ?^ t.found [%| ["change field is ambiguous in partial inference" ~]]
9078+ $(outer t.outer, k (dec k), typ i.found, through `[i.outer here])
9079+::
9080+:: +edit-name-at: where the kth name of an edit's wing is written,
9081+:: counting from 0: its names are joined by dots from the edit's start
9082+::
9083+++ edit-name-at
9084+ |= [e=edit k=@ud]
9085+ ^- span
9086+ =/ col=@ud col.beg.at.e
9087+ =/ ns=(list term) names.e
9088+ |- ^- span
9089+ ?~ ns at.e
9090+ =/ len=@ud (met 3 i.ns)
9091+ ?: =(0 k) [[line.beg.at.e col] [line.beg.at.e (add col len)]]
9092+ $(ns t.ns, k (dec k), col +((add col len)))
9093+::
9094+:: +itype-not-record: whether a type is surely no record: an atom, a
9095+:: loobean, a list or other collection, a gate, a union or a noun
9096+::
9097+++ itype-not-record
9098+ |= [t=itype sub=isub]
9099+ ^- ?
9100+ =. t (itype-walk t sub)
9101+ ?=(?(%atom %any-atom %flag %const %tag %collection %fn %union %noun %empty) -.t)
9102+::
9103+:: +wing-overlap: whether two edits' wings, outermost first, name the
9104+:: same field or one a field inside the other's
9105+::
9106+++ wing-overlap
9107+ |= [a=(list term) b=(list term)]
9108+ ^- ?
9109+ ?~ a &
9110+ ?~ b &
9111+ ?. =(i.a i.b) |
9112+ $(a t.a, b t.b)
86439113::
86449114:: Backtick constructs the canonical prelude unit, after checking its
86459115:: prepared template has the standard null and [~ u=A] cases.
@@ -8743,6 +9213,183 @@
87439213 ?. ?=(%ok -.first) ~
87449214 $(items t.items, actual tal.actual, expected tal.expected, sub sub.first, next next.first)
87459215::
9216+:: +decimal-misfit: a decimal's error where another aura is expected
9217+::
9218+:: A bare decimal is a @ud and fits only @ud, @u, @ and * (S4). After
9219+:: a value fails to fit, refit it with each decimal's variable widened
9220+:: to any aura (+decimal-relax), so that a gate's shared capital learns
9221+:: its aura from the other arguments, then walk the value's syntax
9222+:: beside the type it should fit. The first decimal whose place is an
9223+:: atom of another aura gets the error; otherwise ~, and the caller's
9224+:: own error stands.
9225+::
9226+++ decimal-misfit
9227+ |= [e=expr actual=itype expected=itype sub=isub next=@ud]
9228+ ^- (unit idiag)
9229+ =/ loose=isub (turn sub |=(b=ibinding b(val (decimal-relax val.b))))
9230+ =/ fit=ifit (itype-fit (decimal-relax actual) (decimal-relax expected) loose next)
9231+ (decimal-misfit-at e (decimal-relax expected) ?:(?=(%ok -.fit) sub.fit loose))
9232+::
9233+:: +decimal-relax: a type with each decimal's variable taking any aura
9234+::
9235+++ decimal-relax
9236+ |= t=itype
9237+ ^- itype
9238+ ?+ -.t t
9239+ %nvar [%avar id.t]
9240+ %rnvar [%rvar id.t]
9241+ %collection t(args (turn args.t |=(c=itype (decimal-relax c))))
9242+ %grec t(args (turn args.t |=(c=itype (decimal-relax c))))
9243+ %union t(cases (turn cases.t |=(c=itype (decimal-relax c))), args (turn args.t |=(c=itype (decimal-relax c))))
9244+ %face t(body $(t body.t))
9245+ %fn [%fn $(t sample.t) $(t product.t)]
9246+ %cell [%cell $(t hed.t) $(t tal.t)]
9247+ ==
9248+::
9249+:: +decimal-misfit-at: walk a value beside the type it should fit
9250+::
9251+:: Through groups, faces, tuples and term-headed pairs, the union case
9252+:: a tuple's head tag picks, units and list literals.
9253+::
9254+++ decimal-misfit-at
9255+ |= [e=expr expected=itype sub=isub]
9256+ ^- (unit idiag)
9257+ =. expected (itype-walk expected sub)
9258+ ?: ?=(%face -.expected) $(expected body.expected)
9259+ ?+ -.e ~
9260+ %lit (decimal-lit-misfit at.e lit.e expected |)
9261+ %group $(e inner.e)
9262+ %pair $(e (pair-as-cell e))
9263+ %tuple (decimal-misfit-items items.e expected sub)
9264+ %unit
9265+ ?. ?=(%collection -.expected) ~
9266+ ?. &(=(%unit name.expected) ?=([* ~] args.expected)) ~
9267+ $(e val.e, expected i.args.expected)
9268+ %list
9269+ ?. ?=(%collection -.expected) ~
9270+ ?. &(=(%list name.expected) ?=([* ~] args.expected)) ~
9271+ =/ items=(list expr) items.e
9272+ |-
9273+ ?~ items ~
9274+ =/ found=(unit idiag) ^$(e i.items, expected i.args.expected)
9275+ ?^ found found
9276+ $(items t.items)
9277+ ==
9278+::
9279+:: +decimal-misfit-items: a tuple's items beside a cell, the last its tail
9280+::
9281+++ decimal-misfit-items
9282+ |= [items=(list item) expected=itype sub=isub]
9283+ ^- (unit idiag)
9284+ ?~ items ~
9285+ ?~ t.items (decimal-misfit-at val.i.items expected sub)
9286+ =. expected (itype-walk expected sub)
9287+ ?: ?=(%face -.expected) $(expected body.expected)
9288+ ?: ?=(%union -.expected)
9289+ =/ head=expr val.i.items
9290+ ?. ?=(%lit -.head) ~
9291+ =/ case=(unit itype) (decimal-case val.lit.head cases.expected sub)
9292+ ?~ case ~
9293+ $(expected u.case)
9294+ ?. ?=(%cell -.expected) ~
9295+ =/ found=(unit idiag) (decimal-misfit-at val.i.items hed.expected sub)
9296+ ?^ found found
9297+ $(items t.items, expected tal.expected)
9298+::
9299+:: +decimal-pattern-misfit: a decimal pattern where another aura is matched
9300+::
9301+:: The subject's type is known, so no refit is needed. A cell pattern
9302+:: picks its union case by its head, as a tuple does.
9303+::
9304+++ decimal-pattern-misfit
9305+ |= [p=pattern expected=itype sub=isub]
9306+ ^- (unit idiag)
9307+ =. expected (itype-walk expected sub)
9308+ ?: ?=(%face -.expected) $(expected body.expected)
9309+ ?: ?=(%lit -.p) (decimal-lit-misfit at.p lit.p expected &)
9310+ ?. ?=(%cell -.p) ~
9311+ (decimal-pattern-items items.p expected sub)
9312+::
9313+:: +decimal-pattern-items: a cell pattern's items, as +decimal-misfit-items
9314+::
9315+++ decimal-pattern-items
9316+ |= [items=(list pattern) expected=itype sub=isub]
9317+ ^- (unit idiag)
9318+ ?~ items ~
9319+ ?~ t.items (decimal-pattern-misfit i.items expected sub)
9320+ =. expected (itype-walk expected sub)
9321+ ?: ?=(%face -.expected) $(expected body.expected)
9322+ ?: ?=(%union -.expected)
9323+ ?. ?=(%lit -.i.items) ~
9324+ =/ case=(unit itype) (decimal-case val.lit.i.items cases.expected sub)
9325+ ?~ case ~
9326+ $(expected u.case)
9327+ ?. ?=(%cell -.expected) ~
9328+ =/ found=(unit idiag) (decimal-pattern-misfit i.items hed.expected sub)
9329+ ?^ found found
9330+ $(items t.items, expected tal.expected)
9331+::
9332+:: +decimal-arms-misfit: the first arm whose pattern has a misplaced decimal
9333+::
9334+++ decimal-arms-misfit
9335+ |= [arms=(list arm) subject=itype sub=isub]
9336+ ^- (unit idiag)
9337+ ?~ arms ~
9338+ =/ found=(unit idiag) (decimal-pattern-misfit pat.i.arms subject sub)
9339+ ?^ found found
9340+ $(arms t.arms)
9341+::
9342+:: +decimal-case: the one union case whose head is the constant value
9343+::
9344+++ decimal-case
9345+ |= [value=@ cases=(list itype) sub=isub]
9346+ ^- (unit itype)
9347+ =/ hits=(list itype)
9348+ %+ skim cases
9349+ |= c=itype
9350+ =. c (itype-walk c sub)
9351+ ?. ?=(%cell -.c) |
9352+ =/ head=itype (itype-walk hed.c sub)
9353+ =? head ?=(%face -.head) (itype-walk body.head sub)
9354+ &(?=(%const -.head) =(value val.literal.head))
9355+ ?. ?=([* ~] hits) ~
9356+ `i.hits
9357+::
9358+:: +decimal-lit-misfit: the error for a decimal at a place of known type
9359+::
9360+++ decimal-lit-misfit
9361+ |= [at=span l=lit expected=itype pattern=?]
9362+ ^- (unit idiag)
9363+ ?. &(=(%number form.l) =(%ud aura.l)) ~
9364+ ?. ?=(%atom -.expected) ~
9365+ ?: (decimal-aura aura.expected) ~
9366+ `[(decimal-misfit-msg l aura.expected pattern) ~[[at "decimal"]]]
9367+::
9368+:: +decimal-misfit-msg: "`30` is a @ud, not a @dr; write ~s30"
9369+::
9370+:: The hint writes the value in the expected aura's own literal where
9371+:: that reads naturally: 30 seconds, the text "30", the ship ~syd; a
9372+:: date gets an example. Patterns take no dates, durations or knots,
9373+:: so in a pattern those auras get no hint.
9374+::
9375+++ decimal-misfit-msg
9376+ |= [l=lit aura=@ta pattern=?]
9377+ ^- tape
9378+ =/ what=tape "`{(trip txt.l)}` is a @ud, not a @{(trip aura)}"
9379+ =/ hint=tape
9380+ ?: &(pattern ?=(?(%da %dr %ta) aura)) ""
9381+ ?+ aura ""
9382+ %da "a date, as ~2026.1.1"
9383+ %dr (trip (scot %dr (mul val.l ~s1)))
9384+ %p (trip (scot %p val.l))
9385+ %t (show-quoted txt.l)
9386+ %ta "~.{(trip txt.l)}"
9387+ %ux (trip (scot %ux val.l))
9388+ %uv (trip (scot %uv val.l))
9389+ ==
9390+ ?~ hint what
9391+ "{what}; write {hint}"
9392+::
87469393:: A term-headed pair is the same noun as a two-item cell. Preserve the
87479394:: whole pair span for the synthetic head and the value's own span for
87489395:: the payload; unresolved term constraints follow ordinary cell inference.
@@ -8800,7 +9447,7 @@
88009447 ?. =(u.standard [[%collection %list ~[[%var 0]]] ~[0]])
88019448 [%| ["list literal needs the standard prelude in partial inference" ~]]
88029449 =/ element=itype [%var next.state]
8803− =/ result=iresult (infer-open-list-items items.e element env state(next +(next.state)) at.e)
9450+ =/ result=iresult (infer-open-list-items items.e element env state(next +(next.state)) at.e ~)
88049451 ?: ?=(%| -.result) result
88059452 [%& [%collection %list ~[element]] state.p.result]
88069453 %str (infer-string-pieces pieces.e env state)
@@ -8832,6 +9479,7 @@
88329479 [%& typ.instance state.instance]
88339480 =/ scheme=(unit ischeme) (ienv-lookup i.names.e env)
88349481 ?~ scheme
9482+ ?: =(i.names.e %unface) [%| (unface-value at.e)]
88359483 ?~ prelude.state [%| ["name is not available to partial inference" ~]]
88369484 =/ prelude-entry=(unit ischeme) (ienv-lookup i.names.e values.u.prelude.state)
88379485 ?~ prelude-entry [%| ["name is not available to partial inference" ~]]
@@ -8839,7 +9487,10 @@
88399487 [%& typ.inst state.inst]
88409488 =/ instance=[typ=itype state=istate] (instantiate-scheme u.scheme state)
88419489 [%& typ.instance state.instance]
8842− %group $(e inner.e)
9490+ %group
9491+ ?: &(?=(%wing -.inner.e) =(names.inner.e ~[%unface]) ?=(~ (ienv-lookup %unface env)))
9492+ [%| ["unface takes one argument, as (unface e)" ~[[at.e "unface call"]]]]
9493+ $(e inner.e)
88439494 %change
88449495 ?~ edits.e [%| ["a change takes at least one field" ~[[at.e "empty change"]]]]
88459496 =/ target=iresult $(e [%wing at.e target.e])
@@ -8876,6 +9527,8 @@
88769527 ?: ?=(%| -.result) result
88779528 [%& typ.p.result state.p.result(globals globals.state, molds molds.state)]
88789529 %branch
9530+ =/ named=(unit idiag) (branch-tag-name e env state)
9531+ ?^ named [%| u.named]
88799532 ?^ defer.state (dg-boolean-branch e env state)
88809533 ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
88819534 ?~ t.arms.e
@@ -8926,6 +9579,10 @@
89269579 [%| ["record branch matching is not supported by partial inference" ~]]
89279580 ?: |((itype-has-any-atom typ.p.left sub.state.p.right) (itype-has-any-atom typ.p.right sub.state.p.right) (itype-family-related typ.p.left typ.p.right sub.state.p.right))
89289581 [%| ["branch widening is not supported by partial inference" ~]]
9582+ =/ decimal-x=(unit idiag) (decimal-misfit val.x typ.p.left typ.p.right sub.state.p.right next.state.p.right)
9583+ ?^ decimal-x [%| u.decimal-x]
9584+ =/ decimal-y=(unit idiag) (decimal-misfit val.y typ.p.right typ.p.left sub.state.p.right next.state.p.right)
9585+ ?^ decimal-y [%| u.decimal-y]
89299586 [%| ["branch arms have incompatible types" ~[[(span-of val.x) (site-type-note "first arm" typ.p.left sub.state.p.right)] [(span-of val.y) (site-type-note "second arm" typ.p.right sub.state.p.right)]]]]
89309587 [%& typ.u.joined state.p.right(sub sub.u.joined)]
89319588 %cast
@@ -8947,6 +9604,8 @@
89479604 ?^ missing [%| u.missing]
89489605 =/ nested=(unit idiag) (nested-missing-tag val.e typ.p.value typ.u.target sub.state.p.value next.state.p.value at.shape.e)
89499606 ?^ nested [%| u.nested]
9607+ =/ decimal=(unit idiag) (decimal-misfit val.e typ.p.value typ.u.target sub.state.p.value next.state.p.value)
9608+ ?^ decimal [%| u.decimal]
89509609 [%| ["cast mold and expression type do not unify" ~[[at.shape.e (site-type-note "cast mold" typ.u.target sub.state.p.value)] [(span-of val.e) (site-type-note "expression" typ.p.value sub.state.p.value)]]]]
89519610 ?: &(?=(^ defer.state.p.value) !(dg-stable-fit typ.p.value typ.u.target sub.fit))
89529611 [%| ["deferred cast fit needs stable inference" ~]]
@@ -8975,6 +9634,7 @@
89759634 ?~ args.e [%| ["call has no argument" ~]]
89769635 ?: (explicit-proj-call e env state)
89779636 [%| ["proj needs an expected record type" ~]]
9637+ ?: (reserved-call %unface e env state) (infer-unface e env state)
89789638 (infer-call-with-head e env state (infer-fragment head.e env state))
89799639 * [%| ["expression is not supported by partial inference" ~]]
89809640 ==
@@ -9270,11 +9930,17 @@
92709930 ?^ missing [%| u.missing]
92719931 =/ nested=(unit idiag) (nested-missing-tag i.args.e typ.p.arg sample.ht sub.st next.st (span-of head.e))
92729932 ?^ nested [%| u.nested]
9933+ =/ decimal=(unit idiag) (decimal-misfit i.args.e typ.p.arg sample.ht sub.st next.st)
9934+ ?^ decimal [%| u.decimal]
92739935 [%| ["call's sample and argument types do not unify" ~[[(span-of head.e) (site-type-note "called gate" ht sub.st)] [(span-of i.args.e) (site-type-note "argument" typ.p.arg sub.st)]]]]
92749936 =/ bad=(unit [at=span typ=itype])
92759937 (call-error-site args.e typ.p.arg sample.ht sub.st next.st)
92769938 =/ whole-args=span
92779939 [beg:(span-of i.args.e) end:(span-of (rear args.e))]
9940+ =/ decimal=(unit idiag)
9941+ =/ items=(list item) (turn args.e |=(a=expr [(span-of a) ~ a]))
9942+ (decimal-misfit [%tuple whole-args items] typ.p.arg sample.ht sub.st next.st)
9943+ ?^ decimal [%| u.decimal]
92789944 =/ arg-at=span ?~(bad whole-args at.u.bad)
92799945 =/ arg-type=itype ?~(bad typ.p.arg typ.u.bad)
92809946 [%| ["call's sample and argument types do not unify" ~[[(span-of head.e) (site-type-note "called gate" ht sub.st)] [arg-at (site-type-note "argument" arg-type sub.st)]]]]
@@ -9345,6 +10011,8 @@
934510011 ?^ missing [%| u.missing]
934610012 =/ nested=(unit idiag) (nested-missing-tag val.e typ.p.value payload sub.state.p.value next.state.p.value context)
934710013 ?^ nested [%| u.nested]
10014+ =/ decimal=(unit idiag) (decimal-misfit val.e typ.p.value payload sub.state.p.value next.state.p.value)
10015+ ?^ decimal [%| u.decimal]
934810016 [%| ["unit payload does not fit its expected type" ~[[context (site-type-note "expected unit payload" payload sub.state.p.value)] [(span-of val.e) (site-type-note "payload" typ.p.value sub.state.p.value)]]]]
934910017 [%& expected state.p.value(sub sub.fit, next next.fit)]
935010018::
@@ -9357,6 +10025,7 @@
935710025 ^- iresult
935810026 ?> ?=(%call -.e)
935910027 ?~ args.e [%| ["call has no argument" ~]]
10028+ ?: (reserved-call %unface e env state) (infer-unface e env state)
936010029 =/ head=iresult (infer-fragment head.e env state)
936110030 ?: ?=(%| -.head) head
936210031 =/ ht=itype (itype-walk typ.p.head sub.state.p.head)
@@ -9439,18 +10108,70 @@
943910108 `(infer-simple-items items.e env state)
944010109 `(width-infer-items items.e index.u.target env state context)
944110110::
9442−:: Experimental intrinsic recognition; real bindings retain normal calls.
10111+:: +reserved-call: whether e calls the reserved operation n
10112+::
10113+:: Experimental intrinsic recognition; real bindings retain normal calls.
10114+++ reserved-call
10115+ |= [n=term e=expr env=ienv state=istate]
10116+ ^- ?
10117+ ?. ?=(%call -.e) |
10118+ ?. ?=(%wing -.head.e) |
10119+ ?. =(names.head.e ~[n]) |
10120+ ?: ?=(^ (ienv-lookup n env)) |
10121+ ?: (lien globals.state |=(x=term =(x n))) |
10122+ ?~ prelude.state &
10123+ ?:(?=(^ (ienv-lookup n values.u.prelude.state)) | &)
944310124++ explicit-proj-call
944410125 |= [e=expr env=ienv state=istate]
944510126 ^- ?
944610127 ?. ?=(%call -.e) |
944710128 ?. ?=([* ~] args.e) |
9448− ?. ?=(%wing -.head.e) |
9449− ?. =(names.head.e ~[%proj]) |
9450− ?: ?=(^ (ienv-lookup %proj env)) |
9451− ?: (lien globals.state |=(n=term =(n %proj))) |
9452− ?~ prelude.state &
9453− ?:(?=(^ (ienv-lookup %proj values.u.prelude.state)) | &)
10129+ (reserved-call %proj e env state)
10130+::
10131+:: +infer-unface: (unface e), e's type with every face removed
10132+::
10133+:: A reserved operation handled by type, like proj. Any number of
10134+:: arguments is taken here so that a wrong count is an error. A type
10135+:: not yet known would wait, as wing access does; the partial checker
10136+:: has no such wait and reports it as unsupported, as it does field
10137+:: access on such a type.
10138+++ infer-unface
10139+ |= [e=expr env=ienv state=istate]
10140+ ^- iresult
10141+ ?> ?=(%call -.e)
10142+ ?. ?=([* ~] args.e)
10143+ [%| ["unface takes one argument, as (unface e)" ~[[at.e "unface call"]]]]
10144+ ?^ defer.state [%| ["deferred unface needs unsupported inference" ~]]
10145+ =/ value=iresult (infer-fragment i.args.e env state)
10146+ ?: ?=(%| -.value) value
10147+ =/ typ=itype (itype-walk typ.p.value sub.state.p.value)
10148+ ?: ?=(?(%var %fvar) -.typ)
10149+ [%| ["unface on a type not yet known is not supported by partial inference" ~]]
10150+ [%& (itype-unface typ sub.state.p.value) state.p.value]
10151+::
10152+:: +unface-value: the error for unface written where a value goes
10153+::
10154+++ unface-value
10155+ |= at=span
10156+ ^- idiag
10157+ ["unface is not a value; write |=(g (unface g))" ~[[at "unface used as a value"]]]
10158+::
10159+:: +unfaced-gate: the gate under a ++'s (unface |= …), or ~
10160+::
10161+:: Such a ++ is a gate for recursion: its own name has the unfaced
10162+:: type, and its body may call it.
10163+++ unfaced-gate
10164+ |= [e=expr env=ienv state=istate]
10165+ ^- (unit expr)
10166+ ?: ?=(%group -.e) $(e inner.e)
10167+ ?. (reserved-call %unface e env state) ~
10168+ ?> ?=(%call -.e)
10169+ ?. ?=([* ~] args.e) ~
10170+ =/ gate=expr i.args.e
10171+ |-
10172+ ?: ?=(%group -.gate) $(gate inner.gate)
10173+ ?. ?=(?(%gate %gate-wide) -.gate) ~
10174+ `gate
945410175++ infer-proj-source
945510176 |= [e=expr expected=itype env=ienv state=istate context=span]
945610177 ^- iresult
@@ -9713,6 +10434,8 @@
971310434 ?: ?=(%bad -.fit) [%| ["recursive mold cell does not fit its source shape" ~]]
971410435 [%& target state.p.value(sub sub.fit, next next.fit)]
971510436 ?: ?=(%call -.e) (infer-contextual-call e target env state)
10437+ =/ named=(unit idiag) (branch-tag-name e env state)
10438+ ?^ named [%| u.named]
971610439 =/ empty-list=(unit iresult) (empty-list-null-branch e env state `[target context])
971710440 ?^ empty-list u.empty-list
971810441 ?: (single-structured-pattern e)
@@ -9855,7 +10578,7 @@
985510578 ?~ pats [%& ~]
985610579 ?. ?=(%bind -.i.pats) [%| 'branch pattern is not supported by partial inference']
985710580 =/ name=term name.i.pats
9858− ?: |(=(name %proj) ?=(^ (ienv-lookup name env)) (lien globals |=(n=term =(n name))) (lien seen |=(n=term =(n name))))
10581+ ?: |((reserved-name name) ?=(^ (ienv-lookup name env)) (lien globals |=(n=term =(n name))) (lien seen |=(n=term =(n name))))
985910582 [%| 'pattern shadows a name']
986010583 =/ rest=(each (list term) @t) $(pats t.pats, seen [name seen])
986110584 ?: ?=(%| -.rest) rest
@@ -9932,24 +10655,12 @@
993210655 ^- tape
993310656 =. t (itype-walk t sub)
993410657 ?- -.t
9935− %var
9936− ?: (lth id.t 26) [(add 65 id.t) ~]
9937− "T{<id.t>}"
9938− %fvar
9939− ?: (lth id.t 26) [(add 65 id.t) ~]
9940− "T{<id.t>}"
9941− %avar
9942− ?: (lth id.t 26) [(add 65 id.t) ~]
9943− "T{<id.t>}"
9944− %rvar
9945− ?: (lth id.t 26) [(add 65 id.t) ~]
9946− "T{<id.t>}"
9947− %nvar
9948− ?: (lth id.t 26) [(add 65 id.t) ~]
9949− "T{<id.t>}"
9950− %rnvar
9951− ?: (lth id.t 26) [(add 65 id.t) ~]
9952− "T{<id.t>}"
10658+ %var (show-var id.t)
10659+ %fvar (show-var id.t)
10660+ %avar (show-var id.t)
10661+ %rvar (show-var id.t)
10662+ %nvar (show-var id.t)
10663+ %rnvar (show-var id.t)
995310664 %atom "@{(trip aura.t)}"
995410665 %any-atom "@"
995510666 %flag "?"
@@ -9970,6 +10681,17 @@
997010681 %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
997110682 ==
997210683::
10684+:: +show-var: a type variable as printed: its name if it has one, else
10685+:: a letter for its number, A to Z, then T26, T27 and on
10686+::
10687+++ show-var
10688+ |= id=@ud
10689+ ^- tape
10690+ =/ name=@t (var-name id)
10691+ ?. =(0 name) (trip name)
10692+ ?: (lth id 26) [(add 65 id) ~]
10693+ "T{<id>}"
10694+::
997310695++ show-itype-item
997410696 |= [t=itype sub=isub]
997510697 ^- tape
@@ -10028,7 +10750,7 @@
1002810750 ?: |(?=(%var -.normalized) ?=(%fvar -.normalized) ?=(%avar -.normalized) ?=(%rvar -.normalized) (itype-has-nvar normalized) (itype-has-tag normalized) (itype-has-union normalized)) label
1002910751 ?: (itype-has-hidden-recursive normalized) label
1003010752 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
10031− =/ printable=itype (canonical-itype normalized vars)
10753+ =/ printable=itype (canonical-itype (cap-names normalized vars ~ sub))
1003210754 "{label} has type {(show-itype printable ~)}{(show-atom-constraint printable)}"
1003310755::
1003410756:: A capital in a written mold is generalized with its enclosing ++.
@@ -10069,6 +10791,116 @@
1006910791 ?: =(n u.ident) `i.caps
1007010792 $(caps t.caps)
1007110793::
10794+:: +cap-names: give each variable in vars the name it was written with
10795+::
10796+:: Unification joins variables, and the one an ID resolves to may not
10797+:: carry the name its definition wrote, as when a capital meets a
10798+:: called gate's variable or an atom variable. Each variable in vars
10799+:: takes the name of the first capital in caps that resolves to it;
10800+:: failing that, of the earliest made of the named variables that
10801+:: resolve to it, itself included (+joined-names). Only the name part
10802+:: of an ID changes, not its count, so IDs stay distinct.
10803+::
10804+++ cap-names
10805+ |= [typ=itype vars=(list @ud) caps=icaps sub=isub]
10806+ ^- [typ=itype vars=(list @ud)]
10807+ =/ written=icaps (flop caps)
10808+ =/ joined=(map @ud @ud) (joined-names sub)
10809+ =/ ren=(map @ud @ud) ~
10810+ =/ out=(list @ud) ~
10811+ |-
10812+ ?~ vars [?~(ren typ (itype-reid typ ren)) (flop out)]
10813+ =/ cap=(unit icap) (cap-with-id i.vars written sub)
10814+ =/ first=(unit @ud) (~(get by joined) i.vars)
10815+ =/ name=@t
10816+ ?^ cap name.u.cap
10817+ ?~ first (var-name i.vars)
10818+ ?: =(0 (var-name i.vars)) (var-name u.first)
10819+ ?: (lth (var-count u.first) (var-count i.vars)) (var-name u.first)
10820+ (var-name i.vars)
10821+ =/ to=@ud (named-var name i.vars)
10822+ ?: =(to i.vars) $(vars t.vars, out [i.vars out])
10823+ $(vars t.vars, out [to out], ren (~(put by ren) i.vars to))
10824+::
10825+:: +joined-names: for each variable that named ones resolve to, the
10826+:: earliest made of those, by count
10827+::
10828+:: One pass over sub keeps each ID's newest binding, as +itype-lookup
10829+:: would find it: the variable it is bound to, or ~ for another type.
10830+:: Each named ID then follows those bindings to the variable it
10831+:: resolves to, if any.
10832+::
10833+++ joined-names
10834+ |= sub=isub
10835+ ^- (map @ud @ud)
10836+ =/ edges=(map @ud (unit @ud))
10837+ %+ roll (flop sub)
10838+ |= [b=ibinding m=(map @ud (unit @ud))]
10839+ (~(put by m) id.b (var-of val.b))
10840+ =/ named=(list @ud)
10841+ (murn ~(tap by edges) |=([k=@ud *] ?:(=(0 (var-name k)) ~ `k)))
10842+ =/ fuel=@ud ~(wyt by edges)
10843+ =/ out=(map @ud @ud) ~
10844+ |-
10845+ ?~ named out
10846+ =/ root=(unit @ud) (follow-var i.named edges fuel)
10847+ ?~ root $(named t.named)
10848+ ?: =(u.root i.named) $(named t.named)
10849+ =/ best=(unit @ud) (~(get by out) u.root)
10850+ ?: &(?=(^ best) (lth (var-count u.best) (var-count i.named)))
10851+ $(named t.named)
10852+ $(named t.named, out (~(put by out) u.root i.named))
10853+::
10854+:: +follow-var: the variable that id resolves to through edges, or ~ if
10855+:: it resolves to another type; fuel bounds the steps
10856+::
10857+++ follow-var
10858+ |= [id=@ud edges=(map @ud (unit @ud)) fuel=@ud]
10859+ ^- (unit @ud)
10860+ |-
10861+ ?: =(0 fuel) ~
10862+ =/ edge=(unit (unit @ud)) (~(get by edges) id)
10863+ ?~ edge `id
10864+ ?~ u.edge ~
10865+ ?: =(u.u.edge id) `id
10866+ $(id u.u.edge, fuel (dec fuel))
10867+::
10868+:: +var-of: the ID of a type variable node, or ~ for another type
10869+::
10870+++ var-of
10871+ |= t=itype
10872+ ^- (unit @ud)
10873+ ?+ -.t ~
10874+ %var `id.t
10875+ %fvar `id.t
10876+ %avar `id.t
10877+ %rvar `id.t
10878+ %nvar `id.t
10879+ %rnvar `id.t
10880+ ==
10881+::
10882+:: +itype-reid: t with the variable IDs in ids replaced, each node
10883+:: keeping its kind
10884+::
10885+++ itype-reid
10886+ |= [t=itype ids=(map @ud @ud)]
10887+ ^- itype
10888+ ?- -.t
10889+ %var t(id (fall (~(get by ids) id.t) id.t))
10890+ %fvar t(id (fall (~(get by ids) id.t) id.t))
10891+ %avar t(id (fall (~(get by ids) id.t) id.t))
10892+ %rvar t(id (fall (~(get by ids) id.t) id.t))
10893+ %nvar t(id (fall (~(get by ids) id.t) id.t))
10894+ %rnvar t(id (fall (~(get by ids) id.t) id.t))
10895+ ?(%atom %any-atom %flag %noun %empty %tag %const %recursive %jrec) t
10896+ %union t(cases (turn cases.t |=(c=itype ^$(t c))), args (turn args.t |=(c=itype ^$(t c))))
10897+ %grec t(args (turn args.t |=(c=itype ^$(t c))))
10898+ %collection t(args (turn args.t |=(c=itype ^$(t c))))
10899+ %face t(body $(t body.t))
10900+ %fn t(sample $(t sample.t), product $(t product.t))
10901+ %cell t(hed $(t hed.t), tal $(t tal.t))
10902+ ==
10903+::
1007210904++ merged-capitals
1007310905 |= [caps=icaps sub=isub]
1007410906 ^- (unit [first=icap second=icap])
@@ -10288,6 +11120,9 @@
1028811120 ?^ defer.state [%| ["deferred recursive inference is unsupported" ~]]
1028911121 =. gate-defs.state ~
1029011122 ?. ?=(%value -.d) [%| ["recursive definition is not a gate" ~]]
11123+ :: A ++ whose body is (unface |= …) is a gate too, unfaced
11124+ =/ peeled=(unit expr) (unfaced-gate val.d env state)
11125+ =? val.d ?=(^ peeled) u.peeled
1029111126 ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d))
1029211127 [%| ["recursive definition is not a gate" ~]]
1029311128 =/ result=(unit itype) (recursive-branch-seed d env state)
@@ -10311,6 +11146,7 @@
1031111146 =/ product=itype ?~(result [%var id] u.result)
1031211147 =/ st=istate state.p.sam(next +(id))
1031311148 =/ seed=itype [%fn typ.p.sam product]
11149+ =? seed ?=(^ peeled) (itype-unface seed sub.st)
1031411150 =/ seeded=ienv [[name.d [seed ~]] env.p.sam]
1031511151 =/ body=expr
1031611152 ?- -.gate
@@ -10322,7 +11158,9 @@
1032211158 ?: ?=(%| -.out) out
1032311159 =/ uni=(unit isub) (itype-unify product typ.p.out sub.state.p.out)
1032411160 ?~ uni [%| ["recursive gate constraint is not supported by partial inference" ~]]
10325− [%& [%fn typ.p.sam typ.p.out] state.p.out(sub u.uni)]
11161+ =/ typ=itype [%fn typ.p.sam typ.p.out]
11162+ =? typ ?=(^ peeled) (itype-unface typ u.uni)
11163+ [%& typ state.p.out(sub u.uni)]
1032611164::
1032711165++ dependency-root
1032811166 |= names=(list term)
@@ -10430,7 +11268,7 @@
1043011268:: Infer a cyclic component with one monomorphic seed per gate. All members
1043111269:: must succeed before any scheme is available; pending constraints and
1043211270:: unresolved branch joins remain partial.
10433−+$ igate-entry [name=term typ=itype body=expr env=ienv caps=icaps]
11271++$ igate-entry [name=term typ=itype body=expr env=ienv caps=icaps unfaced=?]
1043411272+$ igate-seeds (each [entries=(list igate-entry) state=istate] idiag)
1043511273++ seed-gate-group
1043611274 |= [ds=(list def) env=ienv state=istate]
@@ -10438,7 +11276,9 @@
1043811276 ?~ ds [%& [~ state]]
1043911277 =/ d=def i.ds
1044011278 ?. ?=(%value -.d) [%| ["recursive group contains a non-gate" ~]]
10441− =/ gate=expr val.d
11279+ :: A ++ whose body is (unface |= …) is a gate too, unfaced
11280+ =/ peeled=(unit expr) (unfaced-gate val.d env state)
11281+ =/ gate=expr ?~(peeled val.d u.peeled)
1044211282 ?. |(?=(%gate -.gate) ?=(%gate-wide -.gate))
1044311283 [%| ["recursive group contains a non-gate" ~]]
1044411284 =/ initial=istate (reserve-def-caps gate state)
@@ -10456,7 +11296,8 @@
1045611296 * !!
1045711297 ==
1045811298 =/ seed=itype [%fn typ.p.sam [%var next.state.p.sam]]
10459− =/ entry=igate-entry [name.d seed body env.p.sam caps.state.p.sam]
11299+ =? seed ?=(^ peeled) (itype-unface seed sub.state.p.sam)
11300+ =/ entry=igate-entry [name.d seed body env.p.sam caps.state.p.sam ?=(^ peeled)]
1046011301 =/ after=istate state.p.sam(next +(next.state.p.sam), caps caps.state)
1046111302 =/ rest=igate-seeds $(ds t.ds, state after)
1046211303 ?: ?=(%| -.rest) rest
@@ -10496,6 +11337,7 @@
1049611337 ?: (constrained-capitals caps.entry sub.state)
1049711338 [%| ["explicit capital constraints are not supported by partial inference" ~]]
1049811339 =/ typ=itype (itype-normalize typ.entry sub.state)
11340+ =? typ unfaced.entry (itype-unface typ ~)
1049911341 ?: (itype-has-nvar typ) [%| ["recursive group needs unsupported inference" ~]]
1050011342 ?: |((itype-has-tag typ) (itype-has-hidden-generic typ) (itype-has-hidden-recursive typ) (unsupported-atom-vars typ caps.entry binders.state sub.state))
1050111343 [%| ["recursive group needs unsupported inference" ~]]
@@ -10504,7 +11346,7 @@
1050411346 =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
1050511347 =/ rest=(each ienv idiag) $(entries t.entries)
1050611348 ?: ?=(%| -.rest) rest
10507− [%& [[name.entry [typ vars]] p.rest]]
11349+ [%& [[name.entry (cap-names typ vars caps.entry sub.state)] p.rest]]
1050811350::
1050911351++ infer-gate-group
1051011352 |= [ds=(list def) env=ienv state=istate]
@@ -10549,7 +11391,7 @@
1054911391 `[entry u.rest]
1055011392::
1055111393
10552−+$ iresolved [env=ienv grouped=(list term) artifacts=(list iwidth-definition)]
11394++$ iresolved [env=ienv grouped=(list term) artifacts=(list iwidth-definition) failures=(list [name=term diag=idiag])]
1055311395+$ iadj (map term (list term))
1055411396+$ ivisited (map term ?)
1055511397+$ iwork (list [name=term done=?])
@@ -10645,7 +11487,7 @@
1064511487++ add-groups
1064611488 |= [ds=(list def) components=icomponents graph=iadj env=ienv grouped=(list term) artifacts=(list iwidth-definition) state=istate]
1064711489 ^- iresolved
10648− ?~ components [env grouped artifacts]
11490+ ?~ components [env grouped artifacts ~]
1064911491 =/ component=(list term) i.components
1065011492 ?. (graph-cycle component graph) $(components t.components)
1065111493 ?: (lien component |=(n=term ?=(^ (ienv-lookup n env)))) $(components t.components)
@@ -10686,11 +11528,13 @@
1068611528 =? artifacts ?=(^ u.finalized)
1068711529 [[name.d val.d typ sub.state.p.result (flop u.finalized)] artifacts]
1068811530 =? checked |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) (~(put by checked) name.d d)
10689− `[[[name.d [typ vars]] env] checked artifacts]
11531+ `[[[name.d (cap-names typ vars caps.state.p.result sub.state.p.result)] env] checked artifacts]
1069011532++ add-supported-defs-core
1069111533 |= [ds=(list def) checked=(map term def) heads=(unit igate-prelude-evidence) env=ienv molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path prelude=(unit ifile) artifacts=(list iwidth-definition) index=(unit [at=path source=@t prelude=ifile shapes=(map term shape)])]
10692− ^- [env=ienv artifacts=(list iwidth-definition)]
10693− ?~ ds [env artifacts]
11534+ ^- [env=ienv artifacts=(list iwidth-definition) failures=(list [name=term diag=idiag])]
11535+ =/ failures=(list [name=term diag=idiag]) ~
11536+ |-
11537+ ?~ ds [env artifacts (flop failures)]
1069411538 =/ d=def i.ds
1069511539 ?: ?=(%mold -.d) $(ds t.ds)
1069611540 ?. (unique-value-name name.d globals) $(ds t.ds)
@@ -10701,37 +11545,34 @@
1070111545 =. gate-defs.initial checked
1070211546 =. head-evidence.initial heads
1070311547 =. initial (reserve-def-caps val.d initial)
10704− =/ result=iresult (infer-fragment val.d env initial)
11548+ =/ plain=iresult (infer-fragment val.d env initial)
11549+ =/ result=iresult plain
1070511550 =? result ?=(%| -.result) (infer-recursive-gate d env initial)
11551+ ?: ?=(%| -.result)
11552+ =/ failure=idiag
11553+ ?: (definite-diag p.result) p.result
11554+ ?: ?=(%| -.plain) p.plain
11555+ p.result
11556+ =? failures (definite-diag failure) [[name.d failure] failures]
11557+ $(ds t.ds)
1070611558 =/ added=(unit iadded-definition)
1070711559 (add-supported-result d result initial env checked artifacts)
1070811560 ?~ added $(ds t.ds)
1070911561 $(ds t.ds, env env.u.added, checked checked.u.added, artifacts artifacts.u.added)
1071011562::
10711−:: Full checking discards unsupported definitions. On that failure path only,
10712−:: retry a bounded number of missing definitions to explain a pending tag
10713−:: from the same ordinary inference state instead of hiding it behind the
10714−:: generic completeness error. No successful definition takes this path.
10715−++ module-pending-tag
10716− |= [ds=(list def) env=ienv base=istate fuel=@ud]
11563+:: Retry one unresolved definition to explain a pending tag. The gate
11564+:: evidence is built from the whole module, not only this definition.
11565+++ module-pending-tag-one
11566+ |= [d=def env=ienv base=istate checked=(map term def) heads=(unit igate-prelude-evidence)]
1071711567 ^- (unit [at=span msg=tape])
10718− =/ checked=(map term def) (direct-checked-gates ds env)
10719− =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude.base)
10720− |-
10721− ?~ ds ~
10722− ?: =(0 fuel) ~
10723− =/ d=def i.ds
10724− ?: ?=(%mold -.d) $(ds t.ds, fuel (dec fuel))
10725− ?^ (ienv-lookup name.d env) $(ds t.ds, fuel (dec fuel))
11568+ ?. ?=(%value -.d) ~
11569+ ?^ (ienv-lookup name.d env) ~
1072611570 =/ initial=istate base(gate-defs checked, head-evidence heads)
1072711571 =. initial (reserve-def-caps val.d initial)
1072811572 =/ result=iresult (infer-fragment val.d env initial)
1072911573 =? result ?=(%| -.result) (infer-recursive-gate d env initial)
10730− ?: ?=(%| -.result) $(ds t.ds, fuel (dec fuel))
10731− =/ pending=(unit [at=span msg=tape])
10732− (pending-tag-diagnostic tags.state.p.result sub.state.p.result)
10733− ?^ pending pending
10734− $(ds t.ds, fuel (dec fuel))
11574+ ?: ?=(%| -.result) ~
11575+ (pending-tag-diagnostic tags.state.p.result sub.state.p.result)
1073511576::
1073611577++ resolve-groups-core
1073711578 |= [ds=(list def) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path prelude=(unit ifile) index=(unit [at=path source=@t prelude=ifile shapes=(map term shape)])]
@@ -10747,12 +11588,12 @@
1074711588 =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude)
1074811589 =/ ordered=(list def) (dependency-order ds components)
1074911590 |-
10750− =/ next=[env=ienv artifacts=(list iwidth-definition)]
11591+ =/ next=[env=ienv artifacts=(list iwidth-definition) failures=(list [name=term diag=idiag])]
1075111592 (add-supported-defs-core ordered (direct-checked-gates ds env) heads env molds globals externals surs mark-externals marks jimports reserved-molds at prelude artifacts index)
1075211593 =/ initial=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ | at top prelude ~ 256 ~ ~ ~ ~ ~ ~]
1075311594 =. grec-index.initial index
1075411595 =/ out=iresolved (add-groups ds components graph env.next grouped artifacts.next initial)
10755− ?: =(env env.out) out
11596+ ?: =(env env.out) out(failures failures.next)
1075611597 $(env env.out, grouped grouped.out, artifacts artifacts.out)
1075711598::
1075811599:: +dependency-order: the value definitions, dependencies first
@@ -11624,13 +12465,29 @@
1162412465 =/ first=(unit idiag) ?:(?=(%expr -.i.segs) (duplicate-expr p.i.segs) ~)
1162512466 ?^ first first
1162612467 $(segs t.segs)
12468+:: A change's items each set a field once: two that name the same field,
12469+:: or one a field inside the other's, as cart and open.cart, overlap.
1162712470++ duplicate-edits
1162812471 |= edits=(list edit)
1162912472 ^- (unit idiag)
12473+ =| seen=(list edit)
12474+ |- ^- (unit idiag)
1163012475 ?~ edits ~
11631− =/ first (duplicate-expr val.i.edits)
12476+ =/ e=edit i.edits
12477+ =/ prior=(list edit)
12478+ (skim seen |=(p=edit (wing-overlap (flop names.p) (flop names.e))))
12479+ ?^ prior
12480+ =/ same=? =(names.i.prior names.e)
12481+ =/ sites=(list [at=span note=tape])
12482+ :~ [at.i.prior "first field"]
12483+ [at.e ?:(same "repeated field" "overlapping field")]
12484+ ==
12485+ ?: same `["change field `{(show-names names.e)}` is repeated" sites]
12486+ =/ a=tape (show-names names.i.prior)
12487+ `["change fields `{a}` and `{(show-names names.e)}` overlap" sites]
12488+ =/ first (duplicate-expr val.e)
1163212489 ?^ first first
11633− $(edits t.edits)
12490+ $(edits t.edits, seen [e seen])
1163412491++ duplicate-arms
1163512492 |= arms=(list arm)
1163612493 ^- (unit idiag)
@@ -11703,59 +12560,142 @@
1170312560 ==
1170412561 [n $(imports t.imports)]
1170512562::
11706−++ reserved-proj-sample
12563+:: +reserved-name: whether n names a reserved operation
12564+::
12565+:: proj and unface are handled by the checker by type, not bound, so
12566+:: no module may define, import or bind either name, as a value or
12567+:: as a mold. A field, tag or path segment may still be spelled so.
12568+++ reserved-name
12569+ |= n=term
12570+ ^- ?
12571+ |(=(n %proj) =(n %unface))
12572+++ reserved-sample
1170712573 |= sam=sample
1170812574 ^- ?
1170912575 ?- -.sam
11710− %bind =(name.sam %proj)
11711− %face =(name.sam %proj)
11712− %pun =(name.sam %proj)
11713− %cell (lien items.sam reserved-proj-sample)
12576+ %bind (reserved-name name.sam)
12577+ %face (reserved-name name.sam)
12578+ %pun (reserved-name name.sam)
12579+ %cell (lien items.sam reserved-sample)
1171412580 * |
1171512581 ==
11716−++ reserved-proj-pattern
12582+++ reserved-pattern
1171712583 |= p=pattern
1171812584 ^- ?
1171912585 ?- -.p
11720− %bind =(name.p %proj)
11721− %cell (lien items.p reserved-proj-pattern)
12586+ %bind (reserved-name name.p)
12587+ %cell (lien items.p reserved-pattern)
1172212588 * |
1172312589 ==
11724−++ reserved-proj-def
12590+++ reserved-def
1172512591 |= d=def
1172612592 ^- ?
11727− ?: =(name.d %proj) &
11728− ?: ?=(%value -.d) (reserved-proj-expr val.d)
12593+ ?: (reserved-name name.d) &
12594+ ?: ?=(%value -.d) (reserved-expr val.d)
1172912595 |
11730−++ reserved-proj-expr
12596+++ reserved-expr
1173112597 |= e=expr
1173212598 ^- ?
1173312599 ?- -.e
11734− %str (lien pieces.e |=(p=piece ?:(?=(%expr -.p) (reserved-proj-expr p.p) |)))
11735− %qath (lien segs.e |=(p=qseg ?:(?=(%expr -.p) (reserved-proj-expr p.p) |)))
11736− %change (lien edits.e |=(p=edit (reserved-proj-expr val.p)))
12600+ %str (lien pieces.e |=(p=piece ?:(?=(%expr -.p) (reserved-expr p.p) |)))
12601+ %qath (lien segs.e |=(p=qseg ?:(?=(%expr -.p) (reserved-expr p.p) |)))
12602+ %change (lien edits.e |=(p=edit (reserved-expr val.p)))
1173712603 %pair $(e val.e)
1173812604 %unit $(e val.e)
1173912605 %group $(e inner.e)
11740− %list (lien items.e reserved-proj-expr)
11741− %tuple (lien items.e |=(i=item (reserved-proj-expr val.i)))
11742− ?(%gate %gate-wide) |((reserved-proj-sample sample.e) $(e body.e))
12606+ %list (lien items.e reserved-expr)
12607+ %tuple (lien items.e |=(i=item (reserved-expr val.i)))
12608+ ?(%gate %gate-wide) |((reserved-sample sample.e) $(e body.e))
1174312609 %cast $(e val.e)
11744− %call |($(e head.e) (lien args.e reserved-proj-expr))
12610+ %call |($(e head.e) (lien args.e reserved-expr))
1174512611 %trace |($(e val.e) $(e then.e))
11746− %branch |($(e subject.e) (lien arms.e |=(a=arm |((reserved-proj-pattern pat.a) (reserved-proj-expr val.a)))))
11747− %body |((lien defs.e reserved-proj-def) $(e final.e))
12612+ %branch |($(e subject.e) (lien arms.e |=(a=arm |((reserved-pattern pat.a) (reserved-expr val.a)))))
12613+ %body |((lien defs.e reserved-def) $(e final.e))
1174812614 * |
1174912615 ==
1175012616::
11751−++ module-has-reserved-proj
12617+++ module-has-reserved
1175212618 |= mod=module
1175312619 ^- ?
1175412620 =/ imported=(list term) (import-binding-names imports.mod)
1175512621 =/ vals=(list term) (global-value-names defs.mod)
1175612622 =/ molds=imolds (collect-simple-molds defs.mod)
1175712623 =/ mold-names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11758− |((lien (weld imported (weld vals mold-names)) |=(n=term =(n %proj))) (lien defs.mod reserved-proj-def))
12624+ |((lien (weld imported (weld vals mold-names)) reserved-name) (lien defs.mod reserved-def))
12625+::
12626+:: A scope collision retains source sites. Prelude declarations may be in
12627+:: another source, so their name and namespace are retained separately.
12628++$ iscope-diagnostic
12629+ [issue=idiag prelude=(unit [name=term kind=?(%value %mold %any)])]
12630+++ scope-import-diagnostic
12631+ |= [imports=(list import) prelude-values=(list term) prelude-molds=(list term) seen=written-fields]
12632+ ^- (each written-fields iscope-diagnostic)
12633+ ?~ imports [%& seen]
12634+ =/ imp=import i.imports
12635+ =/ n=term
12636+ ?- -.imp
12637+ %jibb face.imp
12638+ %sur name.imp
12639+ %mark mark.imp
12640+ ==
12641+ ?: (reserved-name n)
12642+ [%| [["`{(trip n)}` is reserved and cannot be bound" ~[[at.imp "reserved name"]]] ~]]
12643+ =/ earlier=(unit span) (~(get by seen) n)
12644+ ?^ earlier
12645+ [%| [["import `{(trip n)}` shadows an earlier import" ~[[u.earlier "earlier import"] [at.imp "conflicting import"]]] ~]]
12646+ ?: |((lien prelude-values |=(x=term =(n x))) (lien prelude-molds |=(x=term =(n x))))
12647+ [%| [["import `{(trip n)}` shadows a prelude name" ~[[at.imp "conflicting import"]]] `[n %any]]]
12648+ $(imports t.imports, seen (~(put by seen) n at.imp))
12649+++ scope-def-diagnostic
12650+ |= [defs=(list def) imports=written-fields prelude-values=(list term) prelude-molds=(list term) values=written-fields molds=written-fields]
12651+ ^- (unit iscope-diagnostic)
12652+ ?~ defs ~
12653+ =/ d=def i.defs
12654+ =/ n=term name.d
12655+ ?: (reserved-name n)
12656+ `[["`{(trip n)}` is reserved and cannot be bound" ~[[at.d "reserved name"]]] ~]
12657+ =/ imported=(unit span) (~(get by imports) n)
12658+ ?^ imported
12659+ `[["definition `{(trip n)}` shadows an import" ~[[u.imported "import"] [at.d "conflicting definition"]]] ~]
12660+ =/ seen=written-fields ?:(?=(%value -.d) values molds)
12661+ =/ earlier=(unit span) (~(get by seen) n)
12662+ ?^ earlier
12663+ `[["definition `{(trip n)}` shadows an earlier definition" ~[[u.earlier "earlier definition"] [at.d "conflicting definition"]]] ~]
12664+ =/ prelude-names=(list term) ?:(?=(%value -.d) prelude-values prelude-molds)
12665+ ?: (lien prelude-names |=(x=term =(n x)))
12666+ `[["definition `{(trip n)}` shadows a prelude name" ~[[at.d "conflicting definition"]]] `[n ?:(?=(%value -.d) %value %mold)]]
12667+ ?: ?=(%value -.d)
12668+ $(defs t.defs, values (~(put by values) n at.d))
12669+ $(defs t.defs, molds (~(put by molds) n at.d))
12670+++ module-scope-diagnostic
12671+ |= [mod=module prelude-values=(list term) prelude-molds=(list term)]
12672+ ^- (unit iscope-diagnostic)
12673+ =/ imports=(each written-fields iscope-diagnostic)
12674+ (scope-import-diagnostic imports.mod prelude-values prelude-molds ~)
12675+ ?: ?=(%| -.imports) `p.imports
12676+ (scope-def-diagnostic defs.mod p.imports prelude-values prelude-molds ~ ~)
12677+++ show-scope-diagnostic
12678+ |= [file=path src=@t diagnostic=iscope-diagnostic prelude=(unit ifile)]
12679+ ^- @t
12680+ =/ excerpts=(list @t)
12681+ %+ turn sites.issue.diagnostic
12682+ |= site=[at=span note=tape]
12683+ (show-error src [file line.beg.at.site col.beg.at.site note.site])
12684+ =/ previous=(list @t)
12685+ ?~ prelude.diagnostic ~
12686+ ?~ prelude ~
12687+ ?~ source.u.prelude ~
12688+ =/ parsed (parse at.u.prelude u.source.u.prelude)
12689+ ?: ?=(%| -.parsed) ~
12690+ =/ matching=(list def)
12691+ %+ skim defs.p.parsed
12692+ |= d=def
12693+ ?& =(name.d name.u.prelude.diagnostic)
12694+ |(=(%any kind.u.prelude.diagnostic) =(-.d kind.u.prelude.diagnostic))
12695+ ==
12696+ ?~ matching ~
12697+ ~[(show-error u.source.u.prelude [at.u.prelude line.beg.at.i.matching col.beg.at.i.matching "prelude declaration"])]
12698+ (of-wain:format [(crip msg.issue.diagnostic) (weld excerpts previous)])
1175912699::
1176012700++ module-scope-valid
1176112701 |= [mod=module prelude-values=(list term) prelude-molds=(list term)]
@@ -11764,7 +12704,7 @@
1176412704 =/ vals=(list term) (global-value-names defs.mod)
1176512705 =/ molds=imolds (collect-simple-molds defs.mod)
1176612706 =/ mold-names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11767− ?: (module-has-reserved-proj mod) |
12707+ ?: (module-has-reserved mod) |
1176812708 ?. %+ levy imported
1176912709 |= n=term
1177012710 &((unique-value-name n imported) !(lien vals |=(v=term =(n v))) !(lien mold-names |=(m=term =(n m))) !(lien prelude-values |=(v=term =(n v))) !(lien prelude-molds |=(m=term =(n m))))
@@ -12187,6 +13127,31 @@
1218713127 ?. (lien values |=(n=term =(n u.name))) $(ds t.ds)
1218813128 `[u.name at.s]
1218913129::
13130+:: Select the first available reason in dependency order, rather than
13131+:: preferring one class of diagnostic across the whole module. Only the
13132+:: first 64 definitions are retried for pending tags, as before.
13133+++ module-unresolved-diagnostic
13134+ |= [ds=(list def) env=ienv base=istate checked=(map term def) heads=(unit igate-prelude-evidence) failures=(list [name=term diag=idiag]) values=(list term) file=path src=@t fuel=@ud]
13135+ ^- (unit @t)
13136+ ?~ ds ~
13137+ =/ d=def i.ds
13138+ =/ remaining=@ud ?:(=(0 fuel) 0 (dec fuel))
13139+ ?: ?=(%mold -.d) $(ds t.ds, fuel remaining)
13140+ ?^ (ienv-lookup name.d env) $(ds t.ds, fuel remaining)
13141+ =/ found=(list [name=term diag=idiag])
13142+ (skim failures |=(failure=[name=term diag=idiag] =(name.failure name.d)))
13143+ ?^ found `(show-inference-diagnostic file src name.d diag.i.found)
13144+ =/ pending=(unit [at=span msg=tape])
13145+ ?: =(0 fuel) ~
13146+ (module-pending-tag-one d env base checked heads)
13147+ ?^ pending
13148+ `(show-error src [file line.beg.at.u.pending col.beg.at.u.pending msg.u.pending])
13149+ =/ shadow=(unit [name=term at=span]) (module-sample-shadow ~[d] env values)
13150+ ?^ shadow
13151+ =/ msg=tape "sample `{(trip name.u.shadow)}` shadows a name already in scope"
13152+ `(show-error src [file line.beg.at.u.shadow col.beg.at.u.shadow msg])
13153+ $(ds t.ds, fuel remaining)
13154+::
1219013155:: Cache only completed interfaces for this invocation. The source bundle,
1219113156:: imported Hoon types and prelude are fixed for the whole graph. Check the
1219213157:: active path and duplicate sources before consulting it, so a cache hit
@@ -12453,7 +13418,7 @@
1245313418 ^- ?
1245413419 =/ path-names=(list term) (turn paths |=(p=iapi-path name.p))
1245513420 =/ derived=(list term) (weld path-names poke-names)
12456− ?: (lien derived |=(n=term =(n %proj))) |
13421+ ?: (lien derived reserved-name) |
1245713422 =/ outer=(list term) (weld prelude-values (weld (global-value-names defs.mod) (api-import-faces imports.mod)))
1245813423 (levy derived |=(n=term &((unique-value-name n derived) !(lien outer |=(x=term =(n x))))))
1245913424::
@@ -12485,7 +13450,7 @@
1248513450 =/ clashes=(list term)
1248613451 %+ skip names
1248713452 |= n=term
12488− ?| =(n %proj)
13453+ ?| (reserved-name n)
1248913454 &((unique-value-name n names) !(lien outer |=(x=term =(n x))))
1249013455 ==
1249113456 ?~ clashes ~
@@ -13260,7 +14225,7 @@
1326014225 =/ action=term %poke
1326114226 =/ ordinary=(list def) ds
1326214227 =/ derived=(list term) ~[%state action]
13263− ?: (lien derived |=(n=term =(n %proj))) [%| ~]
14228+ ?: (lien derived reserved-name) [%| ~]
1326414229 =/ outer=(list term)
1326514230 (weld prelude-values (weld (global-value-names ordinary) (api-import-faces imports.mod)))
1326614231 =/ clashes=(list term)
@@ -13447,7 +14412,7 @@
1344714412 ?~ recovered ~
1344814413 ?. ?=(~ vars.u.recovered) ~
1344914414 ?. ?=(~ (itype-vars typ.u.recovered)) ~
13450− `[env.u.added grouped.resolution artifacts.u.added]
14415+ `[env.u.added grouped.resolution artifacts.u.added failures.resolution]
1345114416::
1345214417++ program-inferred-slot
1345314418 |= [typ=itype name=(unit term)]
@@ -13603,7 +14568,7 @@
1360314568 ?~ recovered ~
1360414569 ?. ?=(~ vars.u.recovered) ~
1360514570 ?. ?=(~ (itype-vars typ.u.recovered)) ~
13606− `[env.u.added grouped.resolution artifacts.u.added]
14571+ `[env.u.added grouped.resolution artifacts.u.added failures.resolution]
1360714572::
1360814573+$ iview-site [xs=expr mapper=term]
1360914574++ program-view-site
@@ -13930,7 +14895,7 @@
1393014895 ?~ recovered ~
1393114896 ?. ?=(~ vars.u.recovered) ~
1393214897 ?. ?=(~ (itype-vars typ.u.recovered)) ~
13933− `[env.u.added grouped.resolution artifacts.u.added]
14898+ `[env.u.added grouped.resolution artifacts.u.added failures.resolution]
1393414899::
1393514900:: Recover exactly one direct keyed each/turn row mapper, then its view.
1393614901:: The prelude's own each and turn schemes determine the mapper gate: the
@@ -14152,7 +15117,7 @@
1415215117 ?~ recovered ~
1415315118 ?. ?=(~ vars.u.recovered) ~
1415415119 ?. ?=(~ (itype-vars typ.u.recovered)) ~
14155− `[env.u.added grouped.resolution artifacts.u.added]
15120+ `[env.u.added grouped.resolution artifacts.u.added failures.resolution]
1415615121::
1415715122:: The model a direct program's initializer must produce. Update's written
1415815123:: two-item sample gives it when it can be read. Otherwise main's own program
@@ -14309,7 +15274,7 @@
1430915274 ?~ recovered ~
1431015275 ?. ?=(~ vars.u.recovered) ~
1431115276 ?. ?=(~ (itype-vars typ.u.recovered)) ~
14312− `[env.u.added grouped.resolution artifacts.u.added]
15277+ `[env.u.added grouped.resolution artifacts.u.added failures.resolution]
1431315278::
1431415279++ derived-poke-command-scheme
1431515280 |= [prelude=ifile action=itype]
@@ -14477,9 +15442,9 @@
1447715442 (direct-prelude-evidence ds prelude.initial)
1447815443 ?~ heads resolution
1447915444 =/ checked=(map term def) (direct-checked-gates ds env.resolution)
14480− =/ completed=[env=ienv artifacts=(list iwidth-definition)]
15445+ =/ completed=[env=ienv artifacts=(list iwidth-definition) failures=(list [name=term diag=idiag])]
1448115446 (add-supported-defs-core ~[main] checked heads env.resolution molds.initial globals.initial externals.initial surs.initial mark-externals.initial marks.initial jimports.initial reserved-molds.initial at.initial prelude.initial artifacts.resolution grec-index.initial)
14482− [env.completed grouped.resolution artifacts.completed]
15447+ [env.completed grouped.resolution artifacts.completed failures.resolution]
1448315448::
1448415449:: A static main may retain a generic element message in its ordinary
1448515450:: scheme. Instantiate that scheme, specialize it to canonical element !!,
@@ -14695,6 +15660,9 @@
1469515660 !(lien prelude-molds |=(m=term =(m n)))
1469615661 ==
1469715662 ==
15663+ =/ scope=(unit iscope-diagnostic)
15664+ (module-scope-diagnostic mod(defs ordinary, imports faces) prelude-values prelude-molds)
15665+ ?^ scope [%| [(show-scope-diagnostic at src u.scope prelude) ~]]
1469815666 [%| [(crip "module has conflicting names: {(spud at)}") ~]]
1469915667 ?~ prelude [%| [(crip "API module needs unsupported inference: {(spud at)}") ~]]
1470015668 =/ prepared=iprelude [u.prelude prelude-values prelude-molds]
@@ -14743,6 +15711,9 @@
1474315711 =/ ds=(list def) ?~(declared defs.mod defs.u.declared)
1474415712 =/ checking=module mod(defs ds)
1474515713 ?. (module-scope-valid checking prelude-values prelude-molds)
15714+ =/ scope=(unit iscope-diagnostic)
15715+ (module-scope-diagnostic checking prelude-values prelude-molds)
15716+ ?^ scope [%| [(show-scope-diagnostic at src u.scope prelude) ~]]
1474615717 [%| [(crip "module has conflicting names: {(spud at)}") ~]]
1474715718 =/ vals=(list term) (global-value-names ds)
1474815719 =/ js=jimports-detailed-result (resolve-jibb-imports-detailed imports.mod externals mark-externals modules active prelude-values prelude-molds cache prelude)
@@ -14818,15 +15789,14 @@
1481815789 ?~ store-parts ds
1481915790 (skim ds |=(d=def !&(?=(%value -.d) =(%main name.d))))
1482015791 ?. (module-values-complete required env)
14821− =/ pending=(unit [at=span msg=tape]) (module-pending-tag required env state 64)
14822− ?^ pending
14823− [%| [(show-error src [at line.beg.at.u.pending col.beg.at.u.pending msg.u.pending]) ~]]
14824− :: A shadowing sample is an error, so it comes before any named value.
15792+ =/ components=icomponents (graph-components required (global-value-names required))
15793+ =/ ordered=(list def) (dependency-order required components)
1482515794 =/ values=(list term) (weld prelude-values (weld (api-import-faces imports.mod) vals))
14826− =/ shadow=(unit [name=term at=span]) (module-sample-shadow required env values)
14827− ?^ shadow
14828− =/ msg=tape "sample `{(trip name.u.shadow)}` shadows a name already in scope"
14829− [%| [(show-error src [at line.beg.at.u.shadow col.beg.at.u.shadow msg]) ~]]
15795+ =/ checked=(map term def) (direct-checked-gates required env)
15796+ =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence required prelude.state)
15797+ =/ diagnostic=(unit @t)
15798+ (module-unresolved-diagnostic ordered env state checked heads failures.resolution values at src 64)
15799+ ?^ diagnostic [%| [u.diagnostic ~]]
1483015800 =/ missing=(unit term) (module-missing-value required env)
1483115801 =/ named=tape ?~(missing "" ": ++ {(trip u.missing)}")
1483215802 [%| [(crip "module definitions need unsupported inference: {(spud at)}{named}") ~]]
@@ -15030,8 +16000,8 @@
1503016000 ?: ?=(%| -.parsed) (show-error src p.parsed)
1503116001 =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
1503216002 ?^ duplicate (duplicate-fields-report file src u.duplicate)
15033− ?: (module-has-reserved-proj p.parsed)
15034− 'module has reserved proj name'
16003+ ?: (module-has-reserved p.parsed)
16004+ 'module has a reserved proj or unface name'
1503516005 =/ ds=(list def) defs.p.parsed
1503616006 =/ molds=imolds (collect-simple-molds ds)
1503716007 =/ globals=(list term) (weld prelude-values (weld (turn jimports |=(j=[face=term interface=ifile] face.j)) (global-value-names ds)))
@@ -15109,7 +16079,7 @@
1510916079 =. head-evidence.initial heads
1511016080 =. initial (reserve-def-caps val.d initial)
1511116081 =/ result=iresult
15112− ?: |(?=(%gate -.val.d) ?=(%gate-wide -.val.d))
16082+ ?: |(?=(%gate -.val.d) ?=(%gate-wide -.val.d) ?=(^ (unfaced-gate val.d env initial)))
1511316083 (infer-recursive-gate d env initial)
1511416084 (infer-fragment val.d env initial)
1511516085 ?: ?=(%| -.result)
@@ -15141,7 +16111,8 @@
1514116111 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
1514216112 ?~ (width-finalize projections.state.p.result sub.state.p.result vars)
1514316113 $(ds t.ds, lines [(crip "++ {(trip name.d)}: record projection elaboration needs unsupported inference") lines])
15144− =/ printable=itype (canonical-itype typ vars)
16114+ =/ named=[typ=itype vars=(list @ud)] (cap-names typ vars caps.state.p.result sub.state.p.result)
16115+ =/ printable=itype (canonical-itype named)
1514516116 =/ line=@t (crip "++ {(trip name.d)}: {(show-itype printable ~)}{(show-atom-constraint printable)}")
1514616117 $(ds t.ds, lines [line lines])
1514716118:: Experimental module-owned pending-constraint generalization only.
@@ -15238,7 +16209,7 @@
1523816209 =/ normalized=itype (itype-normalize typ sub.state)
1523916210 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
1524016211 =/ quantified=(list @ud) (skim vars |=(n=@ud !(lien ids.u.tagged |=(b=@ud =(b n)))))
15241− `[[normalized quantified]]
16212+ `(cap-names normalized quantified caps.state sub.state)
1524216213::
1524316214+$ dgcommit [env=ienv state=istate]
1524416215:: A branch literal must not acquire a value face through replay.
@@ -15671,20 +16642,21 @@
1567116642 ?~ env `+(top)
1567216643 =/ sc=ischeme scheme.i.env
1567316644 ?: (itype-has-tag typ.sc) ~
15674− $(env t.env, top (itype-max-id typ.sc (max top (roll vars.sc max))))
16645+ $(env t.env, top (itype-max-id typ.sc (max top (roll (turn vars.sc var-count) max))))
1567516646::
15676−:: +itype-max-id: the largest variable or tag ID in t, or top
16647+:: +itype-max-id: the largest variable or tag ID in t, or top, without
16648+:: the variables' names (+named-var)
1567716649::
1567816650++ itype-max-id
1567916651 |= [t=itype top=@ud]
1568016652 ^- @ud
1568116653 ?- -.t
15682− %var (max top id.t)
15683− %fvar (max top id.t)
15684− %avar (max top id.t)
15685− %rvar (max top id.t)
15686− %nvar (max top id.t)
15687− %rnvar (max top id.t)
16654+ %var (max top (var-count id.t))
16655+ %fvar (max top (var-count id.t))
16656+ %avar (max top (var-count id.t))
16657+ %rvar (max top (var-count id.t))
16658+ %nvar (max top (var-count id.t))
16659+ %rnvar (max top (var-count id.t))
1568816660 %tag (max top id.t)
1568916661 ?(%atom %any-atom %flag %noun %empty %const %recursive %jrec) top
1569016662 %collection (itype-max-ids args.t top)
jibb-dev/lib/jibb/prelude.jibb+183−190
@@ -8,16 +8,16 @@
88
99++ head |= p=[A B]
1010 ?- p
11− [a b] a
11+ [a b] a
1212
1313++ tail |= p=[A B]
1414 ?- p
15− [a b] b
15+ [a b] b
1616
1717++ not |= b=?
1818 ?- b
19− %.y %.n
20− %.n %.y
19+ %.y %.n
20+ %.n %.y
2121
2222++ eq |= args=[A A] (eq-data.internal args)
2323
@@ -31,31 +31,29 @@
3131
3232++ fall |= args=[(unit A) A]
3333 ?- args
34− [maybe fallback]
35− ?- maybe
36− ~ fallback
37− [~ value] value
34+ [maybe fallback]
35+ ?- maybe
36+ ~ fallback
37+ [~ value] value
3838
3939++ need |= maybe=(unit A)
4040 ?- maybe
41− ~ !!
42− [~ value] value
41+ ~ !!
42+ [~ value] value
4343
4444++ weld |= args=[(list A) (list A)]
4545 ?- args
46− [xs ys]
47− ^- (list A)
48− ?- xs
49− ~ ys
50− [item rest] [item (weld rest ys)]
46+ [xs ys] ^- (list A)
47+ ?- xs
48+ ~ ys
49+ [item rest] [item (weld rest ys)]
5150
5251++ turn |= args=[(list A) $-(A B)]
5352 ?- args
54− [xs f]
55− ^- (list B)
56− ?- xs
57− ~ ~
58− [item rest] [(f item) (turn rest f)]
53+ [xs f] ^- (list B)
54+ ?- xs
55+ ~ ~
56+ [item rest] [(f item) (turn rest f)]
5957
6058+$ dime [p=@ta q=@]
6159
@@ -104,17 +102,16 @@
104102+$ like |$ [A] [p=hair q=(unit [p=A q=nail])]
105103
106104++ like |= [f=$-(A B) result=(like A)]
107− ++ mapped
108− ^- (unit [p=B q=nail])
109− ?- q.result
110− ~ ~
111− [~ value] `[p=(f p.value) q=q.value]
105+ ++ mapped ^- (unit [p=B q=nail])
106+ ?- q.result
107+ ~ ~
108+ [~ value] `[p=(f p.value) q=q.value]
112109 ^- (like B) [p=p.result q=mapped]
113110
114111++ wonk |= veq=(like A)
115112 ?- q.veq
116− ~ !!
117− [~ product] p.product
113+ ~ !!
114+ [~ product] p.product
118115
119116+$ lone |$ [A] [p=A]
120117
@@ -143,214 +140,209 @@
143140
144141++ snoc |= args=[(list A) A]
145142 ?- args
146− [xs item] (weld xs [item ~])
143+ [xs item] (weld xs [item ~])
147144
148145++ flop |= xs=(list A)
149146 ++ reverse-into |= args=[(list A) (list A)]
150147 ?- args
151− [rest acc]
152− ?- rest
153− ~ acc
154− [item more] (reverse-into more [item acc])
148+ [rest acc]
149+ ?- rest
150+ ~ acc
151+ [item more] (reverse-into more [item acc])
155152 (reverse-into xs ~)
156153
157−++ drop |= maybe=(unit A)
158− ^- (list A)
159− ?- maybe
160− ~ ~
161− [~ value] [value ~]
154+++ drop |= maybe=(unit A) ^- (list A)
155+ ?- maybe
156+ ~ ~
157+ [~ value] [value ~]
162158
163159++ bond |= fallback=$-(~ A)
164160 |= maybe=(unit A)
165161 ?- maybe
166− ~ (fallback ~)
167− [~ value] value
162+ ~ (fallback ~)
163+ [~ value] value
168164
169165++ bind |= args=[(unit A) $-(A B)]
170166 ?- args
171− [maybe f] ^- (unit B)
172− ?- maybe
173− ~ ~
174− [~ value] `(f value)
167+ [maybe f] ^- (unit B)
168+ ?- maybe
169+ ~ ~
170+ [~ value] `(f value)
175171
176172++ biff |= args=[(unit A) $-(A (unit B))]
177173 ?- args
178− [maybe f] ^- (unit B)
179− ?- maybe
180− ~ ~
181− [~ value] (f value)
174+ [maybe f] ^- (unit B)
175+ ?- maybe
176+ ~ ~
177+ [~ value] (f value)
182178
183179++ both |= args=[(unit A) (unit B)]
184180 ?- args
185− [first second] ^- (unit [A B])
186− ?- first
187− ~ ~
188− [~ a]
189− ?- second
190− ~ ~
191− [~ b] `[a b]
181+ [first second] ^- (unit [A B])
182+ ?- first
183+ ~ ~
184+ [~ a]
185+ ?- second
186+ ~ ~
187+ [~ b] `[a b]
192188
193189++ clap |= args=[(unit A) (unit A) $-([A A] A)]
194190 ?- args
195− [first second combine] ^- (unit A)
196− ?- first
197− ~ second
198− [~ a]
199− ?- second
200− ~ first
201− [~ b] `(combine a b)
191+ [first second combine] ^- (unit A)
192+ ?- first
193+ ~ second
194+ [~ a]
195+ ?- second
196+ ~ first
197+ [~ b] `(combine a b)
202198
203199++ hunt |= args=[$-([A A] ?) (unit A) (unit A)]
204200 ?- args
205− [choose first second] ^- (unit A)
206− ?- first
207− ~ second
208− [~ a]
209− ?- second
210− ~ first
211− [~ b]
212− ?- (choose a b)
213− %.y first
214− %.n second
201+ [choose first second] ^- (unit A)
202+ ?- first
203+ ~ second
204+ [~ a]
205+ ?- second
206+ ~ first
207+ [~ b]
208+ ?- (choose a b)
209+ %.y first
210+ %.n second
215211
216212++ mate |= args=[(unit A) (unit A)]
217213 ?- args
218− [first second] ^- (unit A)
219− ?- second
220− ~ first
221− [~ b]
222− ?- first
223− ~ second
224− [~ a]
225− ?- (eq a b)
226− %.y first
227− %.n !!
214+ [first second] ^- (unit A)
215+ ?- second
216+ ~ first
217+ [~ b]
218+ ?- first
219+ ~ second
220+ [~ a]
221+ ?- (eq a b)
222+ %.y first
223+ %.n !!
228224
229225++ clef |= args=[(unit A) (unit B) $-([A B] (unit C))]
230226 ?- args
231− [first second combine] ^- (unit C)
232− ?- first
233− ~ ~
234− [~ a]
235− ?- second
236− ~ ~
237− [~ b] (combine a b)
227+ [first second combine] ^- (unit C)
228+ ?- first
229+ ~ ~
230+ [~ a]
231+ ?- second
232+ ~ ~
233+ [~ b] (combine a b)
238234
239235++ skim |= args=[(list A) $-(A ?)]
240236 ?- args
241− [xs predicate] ^- (list A)
242− ?- xs
243− ~ ~
244− [item rest]
245− ?- (predicate item)
246− %.y [item (skim rest predicate)]
247− %.n (skim rest predicate)
237+ [xs predicate] ^- (list A)
238+ ?- xs
239+ ~ ~
240+ [item rest]
241+ ?- (predicate item)
242+ %.y [item (skim rest predicate)]
243+ %.n (skim rest predicate)
248244
249245++ skip |= args=[(list A) $-(A ?)]
250246 ?- args
251− [xs predicate] ^- (list A)
252− ?- xs
253− ~ ~
254− [item rest]
255− ?- (predicate item)
256− %.y (skip rest predicate)
257− %.n [item (skip rest predicate)]
258−
259−++ levy |= args=[(list A) $-(A ?)]
260− ^- ?
261− ?- args
262− [xs predicate]
263− ?- xs
264− ~ %.y
265− [item rest]
266− ?- (predicate item)
267− %.y (levy rest predicate)
268− %.n %.n
269−
270−++ lien |= args=[(list A) $-(A ?)]
271− ^- ?
272− ?- args
273− [xs predicate]
274− ?- xs
275− ~ %.n
276− [item rest]
277− ?- (predicate item)
278− %.y %.y
279− %.n (lien rest predicate)
247+ [xs predicate] ^- (list A)
248+ ?- xs
249+ ~ ~
250+ [item rest]
251+ ?- (predicate item)
252+ %.y (skip rest predicate)
253+ %.n [item (skip rest predicate)]
254+
255+++ levy |= args=[(list A) $-(A ?)] ^- ?
256+ ?- args
257+ [xs predicate]
258+ ?- xs
259+ ~ %.y
260+ [item rest]
261+ ?- (predicate item)
262+ %.y (levy rest predicate)
263+ %.n %.n
264+
265+++ lien |= args=[(list A) $-(A ?)] ^- ?
266+ ?- args
267+ [xs predicate]
268+ ?- xs
269+ ~ %.n
270+ [item rest]
271+ ?- (predicate item)
272+ %.y %.y
273+ %.n (lien rest predicate)
280274
281275++ roll |= args=[(list A) B $-([A B] B)]
282276 ?- args
283− [xs start combine]
284− ?- xs
285− ~ start
286− [item rest] (roll rest (combine item start) combine)
277+ [xs start combine]
278+ ?- xs
279+ ~ start
280+ [item rest] (roll rest (combine item start) combine)
287281
288282++ reel |= args=[(list A) B $-([A B] B)]
289283 ?- args
290− [xs start combine]
291− ?- xs
292− ~ start
293− [item rest] (combine item (reel rest start combine))
284+ [xs start combine]
285+ ?- xs
286+ ~ start
287+ [item rest] (combine item (reel rest start combine))
294288
295289++ flit |= predicate=$-(A ?)
296− |= value=A
297− ^- (unit A)
298− ?- (predicate value)
299− %.y `value
300− %.n ~
290+ |= value=A ^- (unit A)
291+ ?- (predicate value)
292+ %.y `value
293+ %.n ~
301294
302295++ murn |= args=[(list A) $-(A (unit B))]
303296 ?- args
304− [xs f] ^- (list B)
305− ?- xs
306− ~ ~
307− [item rest]
308− ?- (f item)
309− ~ (murn rest f)
310− [~ value] [value (murn rest f)]
297+ [xs f] ^- (list B)
298+ ?- xs
299+ ~ ~
300+ [item rest]
301+ ?- (f item)
302+ ~ (murn rest f)
303+ [~ value] [value (murn rest f)]
311304
312305++ join |= args=[A (list A)]
313306 ?- args
314− [separator xs] ^- (list A)
315− ?- xs
316− ~ ~
317− [item rest]
318− ?- rest
319− ~ [item ~]
320− [next more] [item [separator (join separator rest)]]
321−
322−++ snip |= xs=(list A)
323− ^- (list A)
307+ [separator xs] ^- (list A)
324308 ?- xs
325− ~ ~
326− [item rest]
327− ?- rest
328− ~ ~
329− [next more] [item (snip rest)]
309+ ~ ~
310+ [item rest]
311+ ?- rest
312+ ~ [item ~]
313+ [next more] [item [separator (join separator rest)]]
314+
315+++ snip |= xs=(list A) ^- (list A)
316+ ?- xs
317+ ~ ~
318+ [item rest]
319+ ?- rest
320+ ~ ~
321+ [next more] [item (snip rest)]
330322
331323++ rear |= xs=(list A)
332324 ?- xs
333− ~ !!
334− [item rest]
335− ?- rest
336− ~ item
337− [next more] (rear rest)
325+ ~ !!
326+ [item rest]
327+ ?- rest
328+ ~ item
329+ [next more] (rear rest)
338330
339331++ cork |= gates=[$-(A B) $-(B C)]
340332 ?- gates
341− [f g] |= x=A (g (f x))
333+ [f g] |= x=A (g (f x))
342334
343335++ corl |= gates=[$-(B C) $-(A B)]
344336 ?- gates
345− [f g] |= x=A (f (g x))
337+ [f g] |= x=A (f (g x))
346338
347339++ cury |= args=[$-([A B] C) A]
348340 ?- args
349− [f a] |= b=B (f a b)
341+ [f a] |= b=B (f a b)
350342
351343++ curr |= args=[$-([A B] C) B]
352344 ?- args
353− [f b] |= a=A (f a b)
345+ [f b] |= a=A (f a b)
354346
355347+$ cmd |$ [M]
356348 [%poke p=raw-poke reply=$-((unit @t) M)]
@@ -373,29 +365,27 @@
373365 [%url reply=$-(path M)]
374366
375367:: Count a finite list with the source-backed addition gate.
376−++ lent |= xs=(list A)
377− ^- @ud
378− ?- xs
379− ~ 0
380− [item rest] (add 1 (lent rest))
368+++ lent |= xs=(list A) ^- @ud
369+ ?- xs
370+ ~ 0
371+ [item rest] (add 1 (lent rest))
381372
382373++ lth |= args=[A A]
383374 ?- args
384− [x y] (gth y x)
375+ [x y] (gth y x)
385376
386377++ gte |= args=[A A]
387378 ?- args
388− [x y] (not (gth y x))
379+ [x y] (not (gth y x))
389380
390381++ lte |= args=[A A]
391382 ?- args
392− [x y] (not (gth x y))
383+ [x y] (not (gth x y))
393384
394−++ zing |= xss=(list (list A))
395− ^- (list A)
396− ?- xss
397− ~ ~
398− [xs rest] (weld xs (zing rest))
385+++ zing |= xss=(list (list A)) ^- (list A)
386+ ?- xss
387+ ~ ~
388+ [xs rest] (weld xs (zing rest))
399389
400390++ lead |= first=A |= second=B [first second]
401391++ late |= second=B |= first=A [first second]
@@ -528,20 +518,23 @@
528518 font=(unit qath)
529519 dark=(unit [tones=[normal=@t background=@t accent=@t danger=@t muted=@t]])
530520
531−+$ program |$ [D X M]
532− [init=$-(D X) update=$-([M X] [X (list (cmd M))]) view=$-(X (element M)) subs=$-(X (list (sub M)))]
521++$ program |$ [Data Model Msg]
522+ [ init=$-(Data Model)
523+ update=$-([Msg Model] [Model (list (cmd Msg))])
524+ view=$-(Model (element Msg))
525+ subs=$-(Model (list (sub Msg)))
533526
534−++ program |= [init=$-(D X) update=$-([M X] [X (list (cmd M))]) view=$-(X (element M)) subs=$-(X (list (sub M)))]
535− ^- (program D X M) [init update view subs]
527+++ program |= [init=$-(Data Model) update=$-([Msg Model] [Model (list (cmd Msg))]) view=$-(Model (element Msg)) subs=$-(Model (list (sub Msg)))]
528+ ^- (program Data Model Msg) [init update view subs]
536529
537−++ island |= [p=(program D X M) data=D]
530+++ island |= [p=(program Data Model Msg) data=Data]
538531 ^- (element !!) [%island [p data]]
539532
540−+$ page |$ [R D]
541− [load=$-(R (ask D)) view=$-(D (element !!))]
533++$ page |$ [Params Data]
534+ [load=$-(Params (ask Data)) view=$-(Data (element !!))]
542535
543−++ page |= [load=$-(R (ask D)) view=$-(D (element !!))]
544− ^- (page R D) [load view]
536+++ page |= [load=$-(Params (ask Data)) view=$-(Data (element !!))]
537+ ^- (page Params Data) [load view]
545538
546539+$ store |$ [S] [init=S update=*]
547540
my-app/ui/basket.jibb+6−6
@@ -12,15 +12,15 @@
1212 [%acked err=(unit @t)]
1313
1414++ init |= ~
15− [[~ %.n] ""]
15+ [cart=[items=~ open=%.n] note=""]
1616
1717++ update |= [=msg m=model]
1818 ?- msg
19− [%noted t] [m(note=t) ~]
20− %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
21− %toggle [m ~[(poke.cart %toggle |=%acked)]]
22− [%got c] [m(cart=c) ~]
23− [%acked err] [m ~]
19+ [%noted t] [m(note=t) ~]
20+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
21+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
22+ [%got c] [m(cart=c) ~]
23+ [%acked err] [m ~]
2424
2525++ subs |= m=model
2626 ~[[%watch (state.cart |=%got)]]
my-app/ui/stores/cart.jibb+3−3
@@ -5,8 +5,8 @@
55 %toggle
66
77++ main (store init update)
8−++ init ^- state [~ %.n]
8+++ init ^- state [items=~ open=%.n]
99++ update |= [a=poke s=state]
1010 ?- a
11− [%add item] s(items=[item items.s])
12− %toggle s(open=(not open.s))
11+ [%add item] s(items=[item items.s])
12+ %toggle s(open=(not open.s))
my-app/ui/todo-list.jibb+9−9
@@ -11,18 +11,18 @@
1111 [%acked err=(unit @t)]
1212
1313++ init |= ts=(list item.todo)
14− [ts "" ~]
14+ [todos=ts draft="" error=~]
1515
1616++ update |= [=msg m=model]
1717 ?- msg
18− [%typed t]
19− ?- (gth (lent (tuba (trip t))) 80)
20− %.y [m(draft=t error=`"Too long") ~]
21− %.n [m(draft=t error=~) ~]
22− %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
23− [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
24− [%got ts] [m(todos=ts) ~]
25− [%acked err] [m(error=err) ~]
18+ [%typed t]
19+ ?- (gth (lent (tuba (trip t))) 80)
20+ %.y [m(draft=t error=`"Too long") ~]
21+ %.n [m(draft=t error=~) ~]
22+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
23+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
24+ [%got ts] [m(todos=ts) ~]
25+ [%acked err] [m(error=err) ~]
2626
2727++ subs |= m=model
2828 ~[[%watch (todos.todo |=%got)]]
tests/golden/doc-core-02-update/about.txt+1−1
@@ -1,3 +1,3 @@
11source: Core language tab, section "Example", code block 2 of the tab
2−tests: the todo island's `update` on its own, as the Core language tab quotes it: a module of one `++`; a `?-` arm with its body on the deeper lines holding a nested `?-`; changes, units, lists and constructors in arm expressions. The same text as lines 16-25 of doc-overview-10-todo-list
2+tests: the todo island's `update` on its own, as the Core language tab quotes it: a module of one `++`; a `?-` with its arms at its own depth, one arm with its body on the deeper lines holding a nested `?-` whose arms are at that `?-`'s depth; changes, units, lists and constructors in arm expressions. The same text as lines 16-25 of doc-overview-10-todo-list
33expect: parses
tests/golden/doc-core-02-update/source.jibb+8−8
@@ -1,10 +1,10 @@
11++ update |= [=msg m=model]
22 ?- msg
3− [%typed t]
4− ?- (gth (lent (tuba (trip t))) 80)
5− %.y [m(draft=t error=`"Too long") ~]
6− %.n [m(draft=t error=~) ~]
7− %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
8− [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
9− [%got ts] [m(todos=ts) ~]
10− [%acked err] [m(error=err) ~]
3+ [%typed t]
4+ ?- (gth (lent (tuba (trip t))) 80)
5+ %.y [m(draft=t error=`"Too long") ~]
6+ %.n [m(draft=t error=~) ~]
7+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
8+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
9+ [%got ts] [m(todos=ts) ~]
10+ [%acked err] [m(error=err) ~]
tests/golden/doc-core-02-update/tokens.txt+120−122
@@ -11,126 +11,124 @@
11112:3 INDENT
12122:3 glyph ?-
13132:6 name msg
14−3:5 INDENT
15−3:5 glyph [
16−3:6 tight lit %typed
17−3:13 name t
18−3:14 tight glyph ]
19−4:7 INDENT
20−4:7 glyph ?-
21−4:10 glyph (
22−4:11 tight name gth
23−4:15 glyph (
24−4:16 tight name lent
25−4:21 glyph (
26−4:22 tight name tuba
27−4:27 glyph (
28−4:28 tight name trip
29−4:33 name t
14+3:3 NEWLINE
15+3:3 glyph [
16+3:4 tight lit %typed
17+3:11 name t
18+3:12 tight glyph ]
19+4:5 INDENT
20+4:5 glyph ?-
21+4:8 glyph (
22+4:9 tight name gth
23+4:13 glyph (
24+4:14 tight name lent
25+4:19 glyph (
26+4:20 tight name tuba
27+4:25 glyph (
28+4:26 tight name trip
29+4:31 name t
30+4:32 tight glyph )
31+4:33 tight glyph )
30324:34 tight glyph )
31−4:35 tight glyph )
32−4:36 tight glyph )
33−4:38 lit 80
34−4:40 tight glyph )
35−5:9 INDENT
36−5:9 lit %.y
37−5:14 glyph [
38−5:15 tight name m
39−5:16 tight glyph (
40−5:17 tight name draft
41−5:22 tight glyph =
42−5:23 tight name t
43−5:25 name error
44−5:30 tight glyph =
45−5:31 tight glyph `
46−5:32 tight str "Too long"
47−5:42 tight glyph )
48−5:44 lit ~
49−5:45 tight glyph ]
50−6:9 NEWLINE
51−6:9 lit %.n
52−6:14 glyph [
53−6:15 tight name m
54−6:16 tight glyph (
55−6:17 tight name draft
56−6:22 tight glyph =
57−6:23 tight name t
58−6:25 name error
59−6:30 tight glyph =
60−6:31 tight lit ~
61−6:32 tight glyph )
62−6:34 lit ~
63−6:35 tight glyph ]
64−7:5 DEDENT
65−7:5 DEDENT
66−7:5 NEWLINE
67−7:5 lit %submit
68−7:20 glyph [
69−7:21 tight name m
70−7:22 tight glyph (
71−7:23 tight name draft
72−7:28 tight glyph =
73−7:29 tight str ""
74−7:31 tight glyph )
75−7:33 glyph ~[
76−7:35 tight glyph (
77−7:36 tight wing poke.todo
78−7:46 glyph [
79−7:47 tight lit %add
80−7:52 wing draft.m
81−7:59 tight glyph ]
82−7:61 glyph |=
83−7:63 tight lit %acked
84−7:69 tight glyph )
85−7:70 tight glyph ]
86−7:71 tight glyph ]
87−8:5 NEWLINE
88−8:5 glyph [
89−8:6 tight lit %toggled
90−8:15 name id
91−8:17 tight glyph ]
92−8:20 glyph [
93−8:21 tight name m
94−8:23 glyph ~[
95−8:25 tight glyph (
96−8:26 tight wing poke.todo
97−8:36 glyph [
98−8:37 tight lit %toggle
99−8:45 name id
100−8:47 tight glyph ]
101−8:49 glyph |=
102−8:51 tight lit %acked
103−8:57 tight glyph )
104−8:58 tight glyph ]
105−8:59 tight glyph ]
106−9:5 NEWLINE
107−9:5 glyph [
108−9:6 tight lit %got
109−9:11 name ts
110−9:13 tight glyph ]
111−9:20 glyph [
112−9:21 tight name m
113−9:22 tight glyph (
114−9:23 tight name todos
115−9:28 tight glyph =
116−9:29 tight name ts
117−9:31 tight glyph )
118−9:33 lit ~
119−9:34 tight glyph ]
120−10:5 NEWLINE
121−10:5 glyph [
122−10:6 tight lit %acked
123−10:13 name err
124−10:16 tight glyph ]
125−10:20 glyph [
126−10:21 tight name m
127−10:22 tight glyph (
128−10:23 tight name error
129−10:28 tight glyph =
130−10:29 tight name err
131−10:32 tight glyph )
132−10:34 lit ~
133−10:35 tight glyph ]
134−10:36 DEDENT
135−10:36 DEDENT
136−10:36 NEWLINE
33+4:36 lit 80
34+4:38 tight glyph )
35+5:5 NEWLINE
36+5:5 lit %.y
37+5:10 glyph [
38+5:11 tight name m
39+5:12 tight glyph (
40+5:13 tight name draft
41+5:18 tight glyph =
42+5:19 tight name t
43+5:21 name error
44+5:26 tight glyph =
45+5:27 tight glyph `
46+5:28 tight str "Too long"
47+5:38 tight glyph )
48+5:40 lit ~
49+5:41 tight glyph ]
50+6:5 NEWLINE
51+6:5 lit %.n
52+6:10 glyph [
53+6:11 tight name m
54+6:12 tight glyph (
55+6:13 tight name draft
56+6:18 tight glyph =
57+6:19 tight name t
58+6:21 name error
59+6:26 tight glyph =
60+6:27 tight lit ~
61+6:28 tight glyph )
62+6:30 lit ~
63+6:31 tight glyph ]
64+7:3 DEDENT
65+7:3 NEWLINE
66+7:3 lit %submit
67+7:18 glyph [
68+7:19 tight name m
69+7:20 tight glyph (
70+7:21 tight name draft
71+7:26 tight glyph =
72+7:27 tight str ""
73+7:29 tight glyph )
74+7:31 glyph ~[
75+7:33 tight glyph (
76+7:34 tight wing poke.todo
77+7:44 glyph [
78+7:45 tight lit %add
79+7:50 wing draft.m
80+7:57 tight glyph ]
81+7:59 glyph |=
82+7:61 tight lit %acked
83+7:67 tight glyph )
84+7:68 tight glyph ]
85+7:69 tight glyph ]
86+8:3 NEWLINE
87+8:3 glyph [
88+8:4 tight lit %toggled
89+8:13 name id
90+8:15 tight glyph ]
91+8:18 glyph [
92+8:19 tight name m
93+8:21 glyph ~[
94+8:23 tight glyph (
95+8:24 tight wing poke.todo
96+8:34 glyph [
97+8:35 tight lit %toggle
98+8:43 name id
99+8:45 tight glyph ]
100+8:47 glyph |=
101+8:49 tight lit %acked
102+8:55 tight glyph )
103+8:56 tight glyph ]
104+8:57 tight glyph ]
105+9:3 NEWLINE
106+9:3 glyph [
107+9:4 tight lit %got
108+9:9 name ts
109+9:11 tight glyph ]
110+9:18 glyph [
111+9:19 tight name m
112+9:20 tight glyph (
113+9:21 tight name todos
114+9:26 tight glyph =
115+9:27 tight name ts
116+9:29 tight glyph )
117+9:31 lit ~
118+9:32 tight glyph ]
119+10:3 NEWLINE
120+10:3 glyph [
121+10:4 tight lit %acked
122+10:11 name err
123+10:14 tight glyph ]
124+10:18 glyph [
125+10:19 tight name m
126+10:20 tight glyph (
127+10:21 tight name error
128+10:26 tight glyph =
129+10:27 tight name err
130+10:30 tight glyph )
131+10:32 lit ~
132+10:33 tight glyph ]
133+10:34 DEDENT
134+10:34 NEWLINE
tests/golden/doc-core-02-update/tree.txt+64−64
@@ -7,67 +7,67 @@
77 (body 2:3
88 (branch 2:3
99 (wing 2:6 msg)
10− (arm 3:5
11− (cell 3:5 (lit 3:6 %typed) (bind 3:13 t))
12− (body 4:7
13− (branch 4:7
14− (group 4:10
15− (call 4:11
16− (wing 4:11 gth)
17− (group 4:15
18− (call 4:16
19− (wing 4:16 lent)
20− (group 4:21
21− (call 4:22
22− (wing 4:22 tuba)
23− (group 4:27
24− (call 4:28 (wing 4:28 trip) (wing 4:33 t)))))))
25− (lit 4:38 80)))
26− (arm 5:9
27− (lit 5:9 %.y)
28− (tuple 5:14
29− (change 5:15 m
30− (edit 5:17 draft (wing 5:23 t))
31− (edit 5:25 error
32− (unit 5:31 (str 5:32 "Too long"))))
33− (lit 5:44 ~)))
34− (arm 6:9
35− (lit 6:9 %.n)
36− (tuple 6:14
37− (change 6:15 m
38− (edit 6:17 draft (wing 6:23 t))
39− (edit 6:25 error (lit 6:31 ~)))
40− (lit 6:34 ~))))))
41− (arm 7:5
42− (lit 7:5 %submit)
43− (tuple 7:20
44− (change 7:21 m
45− (edit 7:23 draft (str 7:29 "")))
46− (list 7:33
47− (group 7:35
48− (call 7:36
49− (wing 7:36 poke.todo)
50− (tuple 7:46 (lit 7:47 %add) (wing 7:52 draft.m))
51− (ctor 7:61 %acked))))))
52− (arm 8:5
53− (cell 8:5 (lit 8:6 %toggled) (bind 8:15 id))
54− (tuple 8:20
55− (wing 8:21 m)
56− (list 8:23
57− (group 8:25
58− (call 8:26
59− (wing 8:26 poke.todo)
60− (tuple 8:36 (lit 8:37 %toggle) (wing 8:45 id))
61− (ctor 8:49 %acked))))))
62− (arm 9:5
63− (cell 9:5 (lit 9:6 %got) (bind 9:11 ts))
64− (tuple 9:20
65− (change 9:21 m
66− (edit 9:23 todos (wing 9:29 ts)))
67− (lit 9:33 ~)))
68− (arm 10:5
69− (cell 10:5 (lit 10:6 %acked) (bind 10:13 err))
70− (tuple 10:20
71− (change 10:21 m
72− (edit 10:23 error (wing 10:29 err)))
73− (lit 10:34 ~))))))))
10+ (arm 3:3
11+ (cell 3:3 (lit 3:4 %typed) (bind 3:11 t))
12+ (body 4:5
13+ (branch 4:5
14+ (group 4:8
15+ (call 4:9
16+ (wing 4:9 gth)
17+ (group 4:13
18+ (call 4:14
19+ (wing 4:14 lent)
20+ (group 4:19
21+ (call 4:20
22+ (wing 4:20 tuba)
23+ (group 4:25
24+ (call 4:26 (wing 4:26 trip) (wing 4:31 t)))))))
25+ (lit 4:36 80)))
26+ (arm 5:5
27+ (lit 5:5 %.y)
28+ (tuple 5:10
29+ (change 5:11 m
30+ (edit 5:13 draft (wing 5:19 t))
31+ (edit 5:21 error
32+ (unit 5:27 (str 5:28 "Too long"))))
33+ (lit 5:40 ~)))
34+ (arm 6:5
35+ (lit 6:5 %.n)
36+ (tuple 6:10
37+ (change 6:11 m
38+ (edit 6:13 draft (wing 6:19 t))
39+ (edit 6:21 error (lit 6:27 ~)))
40+ (lit 6:30 ~))))))
41+ (arm 7:3
42+ (lit 7:3 %submit)
43+ (tuple 7:18
44+ (change 7:19 m
45+ (edit 7:21 draft (str 7:27 "")))
46+ (list 7:31
47+ (group 7:33
48+ (call 7:34
49+ (wing 7:34 poke.todo)
50+ (tuple 7:44 (lit 7:45 %add) (wing 7:50 draft.m))
51+ (ctor 7:59 %acked))))))
52+ (arm 8:3
53+ (cell 8:3 (lit 8:4 %toggled) (bind 8:13 id))
54+ (tuple 8:18
55+ (wing 8:19 m)
56+ (list 8:21
57+ (group 8:23
58+ (call 8:24
59+ (wing 8:24 poke.todo)
60+ (tuple 8:34 (lit 8:35 %toggle) (wing 8:43 id))
61+ (ctor 8:47 %acked))))))
62+ (arm 9:3
63+ (cell 9:3 (lit 9:4 %got) (bind 9:9 ts))
64+ (tuple 9:18
65+ (change 9:19 m
66+ (edit 9:21 todos (wing 9:27 ts)))
67+ (lit 9:31 ~)))
68+ (arm 10:3
69+ (cell 10:3 (lit 10:4 %acked) (bind 10:11 err))
70+ (tuple 10:18
71+ (change 10:19 m
72+ (edit 10:21 error (wing 10:27 err)))
73+ (lit 10:32 ~))))))))
tests/golden/doc-grammar-02-buttons/types.txt+1−1
@@ -1,4 +1,4 @@
11partial inference; module not checked
22++ add-button: tag needs context in partial inference
3−++ labelled: $-([label=@t msg=A] (element A))
3+++ labelled: $-([label=@t msg=M] (element M))
44++ wide: (list attr)
tests/golden/doc-grammar-04-step/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Grammar tab, section "Patterns", code block 4 of the tab
2−tests: a union `+$ step` with one case per deeper line: cells with tags at the head, in the middle and at the end, faced fields, and a bare term; a blank line between definitions; a `?-` whose arms are cell patterns mixing tags and binding names, and a bare term, with their expressions aligned by extra spaces; interpolated strings and a name as arm expressions
2+tests: a union `+$ step` with one case per deeper line: cells with tags at the head, in the middle and at the end, faced fields, and a bare term; a blank line between definitions; a `?-` whose arms, at its own depth, are cell patterns mixing tags and binding names, and a bare term, with their expressions aligned by extra spaces; interpolated strings and a name as arm expressions
33expect: parses
44expect-types: a partial inference report
tests/golden/doc-grammar-04-step/source.jibb+5−5
@@ -7,8 +7,8 @@
77
88++ describe |= s=step
99 ?- s
10− [%move %left n] "left {n}"
11− [%move %right n] "right {n}"
12− [t %draft] t
13− [t %sent sent-at] t
14− %stop "stop"
10+ [%move %left n] "left {n}"
11+ [%move %right n] "right {n}"
12+ [t %draft] t
13+ [t %sent sent-at] t
14+ %stop "stop"
tests/golden/doc-grammar-04-step/tokens.txt+36−37
@@ -46,40 +46,39 @@
46469:3 INDENT
47479:3 glyph ?-
48489:6 name s
49−10:5 INDENT
50−10:5 glyph [
51−10:6 tight lit %move
52−10:12 lit %left
53−10:18 name n
54−10:19 tight glyph ]
55−10:23 str-head "left "
56−10:30 tight name n
57−10:31 tight str-tail ""
58−11:5 NEWLINE
59−11:5 glyph [
60−11:6 tight lit %move
61−11:12 lit %right
62−11:19 name n
63−11:20 tight glyph ]
64−11:23 str-head "right "
65−11:31 tight name n
66−11:32 tight str-tail ""
67−12:5 NEWLINE
68−12:5 glyph [
69−12:6 tight name t
70−12:8 lit %draft
71−12:14 tight glyph ]
72−12:23 name t
73−13:5 NEWLINE
74−13:5 glyph [
75−13:6 tight name t
76−13:8 lit %sent
77−13:14 name sent-at
78−13:21 tight glyph ]
79−13:23 name t
80−14:5 NEWLINE
81−14:5 lit %stop
82−14:23 str "stop"
83−14:29 DEDENT
84−14:29 DEDENT
85−14:29 NEWLINE
49+10:3 NEWLINE
50+10:3 glyph [
51+10:4 tight lit %move
52+10:10 lit %left
53+10:16 name n
54+10:17 tight glyph ]
55+10:21 str-head "left "
56+10:28 tight name n
57+10:29 tight str-tail ""
58+11:3 NEWLINE
59+11:3 glyph [
60+11:4 tight lit %move
61+11:10 lit %right
62+11:17 name n
63+11:18 tight glyph ]
64+11:21 str-head "right "
65+11:29 tight name n
66+11:30 tight str-tail ""
67+12:3 NEWLINE
68+12:3 glyph [
69+12:4 tight name t
70+12:6 lit %draft
71+12:12 tight glyph ]
72+12:21 name t
73+13:3 NEWLINE
74+13:3 glyph [
75+13:4 tight name t
76+13:6 lit %sent
77+13:12 name sent-at
78+13:19 tight glyph ]
79+13:21 name t
80+14:3 NEWLINE
81+14:3 lit %stop
82+14:21 str "stop"
83+14:27 DEDENT
84+14:27 NEWLINE
tests/golden/doc-grammar-04-step/tree.txt+13−13
@@ -23,16 +23,16 @@
2323 (body 9:3
2424 (branch 9:3
2525 (wing 9:6 s)
26− (arm 10:5
27− (cell 10:5 (lit 10:6 %move) (lit 10:12 %left) (bind 10:18 n))
28− (str 10:23 "left " (wing 10:30 n)))
29− (arm 11:5
30− (cell 11:5 (lit 11:6 %move) (lit 11:12 %right) (bind 11:19 n))
31− (str 11:23 "right " (wing 11:31 n)))
32− (arm 12:5
33− (cell 12:5 (bind 12:6 t) (lit 12:8 %draft))
34− (wing 12:23 t))
35− (arm 13:5
36− (cell 13:5 (bind 13:6 t) (lit 13:8 %sent) (bind 13:14 sent-at))
37− (wing 13:23 t))
38− (arm 14:5 (lit 14:5 %stop) (str 14:23 "stop")))))))
26+ (arm 10:3
27+ (cell 10:3 (lit 10:4 %move) (lit 10:10 %left) (bind 10:16 n))
28+ (str 10:21 "left " (wing 10:28 n)))
29+ (arm 11:3
30+ (cell 11:3 (lit 11:4 %move) (lit 11:10 %right) (bind 11:17 n))
31+ (str 11:21 "right " (wing 11:29 n)))
32+ (arm 12:3
33+ (cell 12:3 (bind 12:4 t) (lit 12:6 %draft))
34+ (wing 12:21 t))
35+ (arm 13:3
36+ (cell 13:3 (bind 13:4 t) (lit 13:6 %sent) (bind 13:12 sent-at))
37+ (wing 13:21 t))
38+ (arm 14:3 (lit 14:3 %stop) (str 14:21 "stop")))))))
tests/golden/doc-grammar-06-cart-store/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Grammar tab, section "Example: a store and an island", code block 6 of the tab (block 5 is the EBNF)
2−tests: a store module: a record mold with a mold application and the loobean mold `?`; a union with its cases below; a mold that is a name; a blank line; `++ main (store init update)`; a cast with its mold and expression on one line, `^- state [~ %.n]`; a gate with a cell sample; `?-` arms whose expressions are changes, `s(items=[item items.s])` and `s(open=(not open.s))`
2+tests: a store module: a record mold with a mold application and the loobean mold `?`; a union with its cases below; a mold that is a name; a blank line; `++ main (store init update)`; a cast with its mold and expression on one line, `^- state [~ %.n]`; a gate with a cell sample; `?-` arms at the `?-`'s depth whose expressions are changes, `s(items=[item items.s])` and `s(open=(not open.s))`
33expect: parses
44expect-types: a partial inference report; store kind and declaration scope remain unresolved
tests/golden/doc-grammar-06-cart-store/tokens.txt+34−31
@@ -38,9 +38,13 @@
38388:9 glyph ^-
39398:12 name state
40408:18 glyph [
41−8:19 tight lit ~
42−8:21 lit %.n
43−8:24 tight glyph ]
41+8:19 tight name items
42+8:24 tight glyph =
43+8:25 tight lit ~
44+8:27 name open
45+8:31 tight glyph =
46+8:32 tight lit %.n
47+8:35 tight glyph ]
44489:1 NEWLINE
45499:1 glyph ++
46509:4 name update
@@ -56,31 +60,30 @@
566010:3 INDENT
576110:3 glyph ?-
586210:6 name a
59−11:5 INDENT
60−11:5 glyph [
61−11:6 tight lit %add
62−11:11 name item
63−11:15 tight glyph ]
64−11:18 name s
65−11:19 tight glyph (
66−11:20 tight name items
67−11:25 tight glyph =
68−11:26 tight glyph [
69−11:27 tight name item
70−11:32 wing items.s
71−11:39 tight glyph ]
72−11:40 tight glyph )
73−12:5 NEWLINE
74−12:5 lit %toggle
75−12:18 name s
76−12:19 tight glyph (
77−12:20 tight name open
78−12:24 tight glyph =
79−12:25 tight glyph (
80−12:26 tight name not
81−12:30 wing open.s
82−12:36 tight glyph )
83−12:37 tight glyph )
84−12:38 DEDENT
85−12:38 DEDENT
86−12:38 NEWLINE
63+11:3 NEWLINE
64+11:3 glyph [
65+11:4 tight lit %add
66+11:9 name item
67+11:13 tight glyph ]
68+11:16 name s
69+11:17 tight glyph (
70+11:18 tight name items
71+11:23 tight glyph =
72+11:24 tight glyph [
73+11:25 tight name item
74+11:30 wing items.s
75+11:37 tight glyph ]
76+11:38 tight glyph )
77+12:3 NEWLINE
78+12:3 lit %toggle
79+12:16 name s
80+12:17 tight glyph (
81+12:18 tight name open
82+12:22 tight glyph =
83+12:23 tight glyph (
84+12:24 tight name not
85+12:28 wing open.s
86+12:34 tight glyph )
87+12:35 tight glyph )
88+12:36 DEDENT
89+12:36 NEWLINE
tests/golden/doc-grammar-06-cart-store/tree.txt+14−12
@@ -16,7 +16,9 @@
1616 (value 8:1 init
1717 (cast 8:9
1818 (ref 8:12 state)
19− (tuple 8:18 (lit 8:19 ~) (lit 8:21 %.n))))
19+ (tuple 8:18
20+ (face 8:19 items (lit 8:25 ~))
21+ (face 8:27 open (lit 8:32 %.n)))))
2022 (value 9:1 update
2123 (gate 9:11
2224 (cell 9:14
@@ -25,14 +27,14 @@
2527 (body 10:3
2628 (branch 10:3
2729 (wing 10:6 a)
28− (arm 11:5
29− (cell 11:5 (lit 11:6 %add) (bind 11:11 item))
30− (change 11:18 s
31− (edit 11:20 items
32− (tuple 11:26 (wing 11:27 item) (wing 11:32 items.s)))))
33− (arm 12:5
34− (lit 12:5 %toggle)
35− (change 12:18 s
36− (edit 12:20 open
37− (group 12:25
38− (call 12:26 (wing 12:26 not) (wing 12:30 open.s)))))))))))
30+ (arm 11:3
31+ (cell 11:3 (lit 11:4 %add) (bind 11:9 item))
32+ (change 11:16 s
33+ (edit 11:18 items
34+ (tuple 11:24 (wing 11:25 item) (wing 11:30 items.s)))))
35+ (arm 12:3
36+ (lit 12:3 %toggle)
37+ (change 12:16 s
38+ (edit 12:18 open
39+ (group 12:23
40+ (call 12:24 (wing 12:24 not) (wing 12:28 open.s)))))))))))
tests/golden/doc-grammar-07-basket/about.txt+1−1
@@ -1,3 +1,3 @@
11source: Grammar tab, section "Example: a store and an island", code block 7 of the tab
2−tests: an island module: a `/=` import; blank lines between definitions; a record mold holding a wing mold `state.cart`; a union with term, faced-cell and mold-application cases; `|= ~` with its body below; a pun sample `=msg`; arms whose expressions are cells holding changes (`m(note="")`), lists of cells, parenthesised calls of wings and constructors (`|=%acked`); `(state.cart |=%got)`; a list left open at the end of its line whose items are a parenthesised call with an interpolated group `{(lent items.cart.m)}` and two unparenthesised calls, one ending in `|=%noted`
2+tests: an island module: a `/=` import; blank lines between definitions; a record mold holding a wing mold `state.cart`; a union with term, faced-cell and mold-application cases; `|= ~` with its body below; a pun sample `=msg`; arms at the `?-`'s depth whose expressions are cells holding changes (`m(note="")`), lists of cells, parenthesised calls of wings and constructors (`|=%acked`); `(state.cart |=%got)`; a list left open at the end of its line whose items are a parenthesised call with an interpolated group `{(lent items.cart.m)}` and two unparenthesised calls, one ending in `|=%noted`
33expect: parses
tests/golden/doc-grammar-07-basket/tokens.txt+85−78
@@ -66,12 +66,20 @@
666614:12 lit ~
676715:3 INDENT
686815:3 glyph [
69−15:4 tight glyph [
70−15:5 tight lit ~
71−15:7 lit %.n
72−15:10 tight glyph ]
73−15:12 str ""
74−15:14 tight glyph ]
69+15:4 tight name cart
70+15:8 tight glyph =
71+15:9 tight glyph [
72+15:10 tight name items
73+15:15 tight glyph =
74+15:16 tight lit ~
75+15:18 name open
76+15:22 tight glyph =
77+15:23 tight lit %.n
78+15:26 tight glyph ]
79+15:28 name note
80+15:32 tight glyph =
81+15:33 tight str ""
82+15:35 tight glyph ]
758317:1 DEDENT
768417:1 NEWLINE
778517:1 glyph ++
@@ -87,78 +95,77 @@
879518:3 INDENT
889618:3 glyph ?-
899718:6 name msg
90−19:5 INDENT
91−19:5 glyph [
92−19:6 tight lit %noted
93−19:13 name t
94−19:14 tight glyph ]
95−19:20 glyph [
96−19:21 tight name m
97−19:22 tight glyph (
98−19:23 tight name note
99−19:27 tight glyph =
100−19:28 tight name t
101−19:29 tight glyph )
102−19:31 lit ~
103−19:32 tight glyph ]
104−20:5 NEWLINE
105−20:5 lit %add
106−20:20 glyph [
107−20:21 tight name m
108−20:22 tight glyph (
109−20:23 tight name note
110−20:27 tight glyph =
111−20:28 tight str ""
112−20:30 tight glyph )
113−20:32 glyph ~[
114−20:34 tight glyph (
115−20:35 tight wing poke.cart
116−20:45 glyph [
117−20:46 tight lit %add
118−20:51 wing note.m
119−20:57 tight glyph ]
120−20:59 glyph |=
121−20:61 tight lit %acked
122−20:67 tight glyph )
123−20:68 tight glyph ]
124−20:69 tight glyph ]
125−21:5 NEWLINE
126−21:5 lit %toggle
127−21:20 glyph [
128−21:21 tight name m
129−21:23 glyph ~[
130−21:25 tight glyph (
131−21:26 tight wing poke.cart
132−21:36 lit %toggle
133−21:44 glyph |=
134−21:46 tight lit %acked
135−21:52 tight glyph )
136−21:53 tight glyph ]
137−21:54 tight glyph ]
138−22:5 NEWLINE
139−22:5 glyph [
140−22:6 tight lit %got
141−22:11 name c
142−22:12 tight glyph ]
143−22:20 glyph [
144−22:21 tight name m
145−22:22 tight glyph (
146−22:23 tight name cart
147−22:27 tight glyph =
148−22:28 tight name c
149−22:29 tight glyph )
150−22:31 lit ~
151−22:32 tight glyph ]
152−23:5 NEWLINE
153−23:5 glyph [
154−23:6 tight lit %acked
155−23:13 name err
156−23:16 tight glyph ]
157−23:20 glyph [
158−23:21 tight name m
159−23:23 lit ~
160−23:24 tight glyph ]
161−25:1 DEDENT
98+19:3 NEWLINE
99+19:3 glyph [
100+19:4 tight lit %noted
101+19:11 name t
102+19:12 tight glyph ]
103+19:18 glyph [
104+19:19 tight name m
105+19:20 tight glyph (
106+19:21 tight name note
107+19:25 tight glyph =
108+19:26 tight name t
109+19:27 tight glyph )
110+19:29 lit ~
111+19:30 tight glyph ]
112+20:3 NEWLINE
113+20:3 lit %add
114+20:18 glyph [
115+20:19 tight name m
116+20:20 tight glyph (
117+20:21 tight name note
118+20:25 tight glyph =
119+20:26 tight str ""
120+20:28 tight glyph )
121+20:30 glyph ~[
122+20:32 tight glyph (
123+20:33 tight wing poke.cart
124+20:43 glyph [
125+20:44 tight lit %add
126+20:49 wing note.m
127+20:55 tight glyph ]
128+20:57 glyph |=
129+20:59 tight lit %acked
130+20:65 tight glyph )
131+20:66 tight glyph ]
132+20:67 tight glyph ]
133+21:3 NEWLINE
134+21:3 lit %toggle
135+21:18 glyph [
136+21:19 tight name m
137+21:21 glyph ~[
138+21:23 tight glyph (
139+21:24 tight wing poke.cart
140+21:34 lit %toggle
141+21:42 glyph |=
142+21:44 tight lit %acked
143+21:50 tight glyph )
144+21:51 tight glyph ]
145+21:52 tight glyph ]
146+22:3 NEWLINE
147+22:3 glyph [
148+22:4 tight lit %got
149+22:9 name c
150+22:10 tight glyph ]
151+22:18 glyph [
152+22:19 tight name m
153+22:20 tight glyph (
154+22:21 tight name cart
155+22:25 tight glyph =
156+22:26 tight name c
157+22:27 tight glyph )
158+22:29 lit ~
159+22:30 tight glyph ]
160+23:3 NEWLINE
161+23:3 glyph [
162+23:4 tight lit %acked
163+23:11 name err
164+23:14 tight glyph ]
165+23:18 glyph [
166+23:19 tight name m
167+23:21 lit ~
168+23:22 tight glyph ]
16216925:1 DEDENT
16317025:1 NEWLINE
16417125:1 glyph ++
tests/golden/doc-grammar-07-basket/tree.txt+38−35
@@ -26,8 +26,11 @@
2626 (const 14:12 ~)
2727 (body 15:3
2828 (tuple 15:3
29− (tuple 15:4 (lit 15:5 ~) (lit 15:7 %.n))
30− (str 15:12 "")))))
29+ (face 15:4 cart
30+ (tuple 15:9
31+ (face 15:10 items (lit 15:16 ~))
32+ (face 15:18 open (lit 15:23 %.n))))
33+ (face 15:28 note (str 15:33 ""))))))
3134 (value 17:1 update
3235 (gate 17:11
3336 (cell 17:14
@@ -36,39 +39,39 @@
3639 (body 18:3
3740 (branch 18:3
3841 (wing 18:6 msg)
39− (arm 19:5
40− (cell 19:5 (lit 19:6 %noted) (bind 19:13 t))
41− (tuple 19:20
42− (change 19:21 m
43− (edit 19:23 note (wing 19:28 t)))
44− (lit 19:31 ~)))
45− (arm 20:5
46− (lit 20:5 %add)
47− (tuple 20:20
48− (change 20:21 m
49− (edit 20:23 note (str 20:28 "")))
50− (list 20:32
51− (group 20:34
52− (call 20:35
53− (wing 20:35 poke.cart)
54− (tuple 20:45 (lit 20:46 %add) (wing 20:51 note.m))
55− (ctor 20:59 %acked))))))
56− (arm 21:5
57− (lit 21:5 %toggle)
58− (tuple 21:20
59− (wing 21:21 m)
60− (list 21:23
61− (group 21:25
62− (call 21:26 (wing 21:26 poke.cart) (lit 21:36 %toggle) (ctor 21:44 %acked))))))
63− (arm 22:5
64− (cell 22:5 (lit 22:6 %got) (bind 22:11 c))
65− (tuple 22:20
66− (change 22:21 m
67− (edit 22:23 cart (wing 22:28 c)))
68− (lit 22:31 ~)))
69− (arm 23:5
70− (cell 23:5 (lit 23:6 %acked) (bind 23:13 err))
71− (tuple 23:20 (wing 23:21 m) (lit 23:23 ~)))))))
42+ (arm 19:3
43+ (cell 19:3 (lit 19:4 %noted) (bind 19:11 t))
44+ (tuple 19:18
45+ (change 19:19 m
46+ (edit 19:21 note (wing 19:26 t)))
47+ (lit 19:29 ~)))
48+ (arm 20:3
49+ (lit 20:3 %add)
50+ (tuple 20:18
51+ (change 20:19 m
52+ (edit 20:21 note (str 20:26 "")))
53+ (list 20:30
54+ (group 20:32
55+ (call 20:33
56+ (wing 20:33 poke.cart)
57+ (tuple 20:43 (lit 20:44 %add) (wing 20:49 note.m))
58+ (ctor 20:57 %acked))))))
59+ (arm 21:3
60+ (lit 21:3 %toggle)
61+ (tuple 21:18
62+ (wing 21:19 m)
63+ (list 21:21
64+ (group 21:23
65+ (call 21:24 (wing 21:24 poke.cart) (lit 21:34 %toggle) (ctor 21:42 %acked))))))
66+ (arm 22:3
67+ (cell 22:3 (lit 22:4 %got) (bind 22:9 c))
68+ (tuple 22:18
69+ (change 22:19 m
70+ (edit 22:21 cart (wing 22:26 c)))
71+ (lit 22:29 ~)))
72+ (arm 23:3
73+ (cell 23:3 (lit 23:4 %acked) (bind 23:11 err))
74+ (tuple 23:18 (wing 23:19 m) (lit 23:21 ~)))))))
7275 (value 25:1 subs
7376 (gate 25:9
7477 (face 25:12 m (ref 25:14 model))
tests/golden/doc-overview-10-todo-list/about.txt+1−1
@@ -1,3 +1,3 @@
11source: the first tab ("Jibb — an Elm-architecture UI language for Urbit"), section "Worked examples", 3. Interactive: /ui/todo-list.jibb, code block 10 of the tab
2−tests: the interactive island: a record mold with mold applications; a five-case union; a gate with its body below; a `?-` arm whose body is on the deeper lines, a nested `?-` on a deeply nested call with loobean arms; changes holding a unit of a string (`` error=`"Too long" ``) and a null; arms aligned with extra spaces; lists of cells holding constructors; a list left open inside another open list (`row ~[gap+%s1] ~[`); a pair whose operand is a cell; calls ending in `|=%typed`; a gate whose body is a cell holding a call with a cell argument
2+tests: the interactive island: a record mold with mold applications; a five-case union; a gate with its body below; a `?-` with its arms at its own depth, one arm's body on the deeper lines, a nested `?-` on a deeply nested call with loobean arms at its depth; changes holding a unit of a string (`` error=`"Too long" ``) and a null; arms aligned with extra spaces; lists of cells holding constructors; a list left open inside another open list (`row ~[gap+%s1] ~[`); a pair whose operand is a cell; calls ending in `|=%typed`; a gate whose body is a cell holding a call with a cell argument
33expect: parses
tests/golden/doc-overview-10-todo-list/tokens.txt+128−124
@@ -88,10 +88,16 @@
888813:30 tight glyph )
898914:3 INDENT
909014:3 glyph [
91−14:4 tight name ts
92−14:7 str ""
93−14:10 lit ~
94−14:11 tight glyph ]
91+14:4 tight name todos
92+14:9 tight glyph =
93+14:10 tight name ts
94+14:13 name draft
95+14:18 tight glyph =
96+14:19 tight str ""
97+14:22 name error
98+14:27 tight glyph =
99+14:28 tight lit ~
100+14:29 tight glyph ]
9510116:1 DEDENT
9610216:1 NEWLINE
9710316:1 glyph ++
@@ -107,127 +113,125 @@
10711317:3 INDENT
10811417:3 glyph ?-
10911517:6 name msg
110−18:5 INDENT
111−18:5 glyph [
112−18:6 tight lit %typed
113−18:13 name t
114−18:14 tight glyph ]
115−19:7 INDENT
116−19:7 glyph ?-
117−19:10 glyph (
118−19:11 tight name gth
119−19:15 glyph (
120−19:16 tight name lent
121−19:21 glyph (
122−19:22 tight name tuba
123−19:27 glyph (
124−19:28 tight name trip
125−19:33 name t
116+18:3 NEWLINE
117+18:3 glyph [
118+18:4 tight lit %typed
119+18:11 name t
120+18:12 tight glyph ]
121+19:5 INDENT
122+19:5 glyph ?-
123+19:8 glyph (
124+19:9 tight name gth
125+19:13 glyph (
126+19:14 tight name lent
127+19:19 glyph (
128+19:20 tight name tuba
129+19:25 glyph (
130+19:26 tight name trip
131+19:31 name t
132+19:32 tight glyph )
133+19:33 tight glyph )
12613419:34 tight glyph )
127−19:35 tight glyph )
128−19:36 tight glyph )
129−19:38 lit 80
130−19:40 tight glyph )
131−20:9 INDENT
132−20:9 lit %.y
133−20:14 glyph [
134−20:15 tight name m
135−20:16 tight glyph (
136−20:17 tight name draft
137−20:22 tight glyph =
138−20:23 tight name t
139−20:25 name error
140−20:30 tight glyph =
141−20:31 tight glyph `
142−20:32 tight str "Too long"
143−20:42 tight glyph )
144−20:44 lit ~
145−20:45 tight glyph ]
146−21:9 NEWLINE
147−21:9 lit %.n
148−21:14 glyph [
149−21:15 tight name m
150−21:16 tight glyph (
151−21:17 tight name draft
152−21:22 tight glyph =
153−21:23 tight name t
154−21:25 name error
155−21:30 tight glyph =
156−21:31 tight lit ~
157−21:32 tight glyph )
158−21:34 lit ~
159−21:35 tight glyph ]
160−22:5 DEDENT
161−22:5 DEDENT
162−22:5 NEWLINE
163−22:5 lit %submit
164−22:20 glyph [
165−22:21 tight name m
166−22:22 tight glyph (
167−22:23 tight name draft
168−22:28 tight glyph =
169−22:29 tight str ""
170−22:31 tight glyph )
171−22:33 glyph ~[
172−22:35 tight glyph (
173−22:36 tight wing poke.todo
174−22:46 glyph [
175−22:47 tight lit %add
176−22:52 wing draft.m
177−22:59 tight glyph ]
178−22:61 glyph |=
179−22:63 tight lit %acked
180−22:69 tight glyph )
181−22:70 tight glyph ]
182−22:71 tight glyph ]
183−23:5 NEWLINE
184−23:5 glyph [
185−23:6 tight lit %toggled
186−23:15 name id
187−23:17 tight glyph ]
188−23:20 glyph [
189−23:21 tight name m
190−23:23 glyph ~[
191−23:25 tight glyph (
192−23:26 tight wing poke.todo
193−23:36 glyph [
194−23:37 tight lit %toggle
195−23:45 name id
196−23:47 tight glyph ]
197−23:49 glyph |=
198−23:51 tight lit %acked
199−23:57 tight glyph )
200−23:58 tight glyph ]
201−23:59 tight glyph ]
202−24:5 NEWLINE
203−24:5 glyph [
204−24:6 tight lit %got
205−24:11 name ts
206−24:13 tight glyph ]
207−24:20 glyph [
208−24:21 tight name m
209−24:22 tight glyph (
210−24:23 tight name todos
211−24:28 tight glyph =
212−24:29 tight name ts
213−24:31 tight glyph )
214−24:33 lit ~
215−24:34 tight glyph ]
216−25:5 NEWLINE
217−25:5 glyph [
218−25:6 tight lit %acked
219−25:13 name err
220−25:16 tight glyph ]
221−25:20 glyph [
222−25:21 tight name m
223−25:22 tight glyph (
224−25:23 tight name error
225−25:28 tight glyph =
226−25:29 tight name err
227−25:32 tight glyph )
228−25:34 lit ~
229−25:35 tight glyph ]
230−27:1 DEDENT
135+19:36 lit 80
136+19:38 tight glyph )
137+20:5 NEWLINE
138+20:5 lit %.y
139+20:10 glyph [
140+20:11 tight name m
141+20:12 tight glyph (
142+20:13 tight name draft
143+20:18 tight glyph =
144+20:19 tight name t
145+20:21 name error
146+20:26 tight glyph =
147+20:27 tight glyph `
148+20:28 tight str "Too long"
149+20:38 tight glyph )
150+20:40 lit ~
151+20:41 tight glyph ]
152+21:5 NEWLINE
153+21:5 lit %.n
154+21:10 glyph [
155+21:11 tight name m
156+21:12 tight glyph (
157+21:13 tight name draft
158+21:18 tight glyph =
159+21:19 tight name t
160+21:21 name error
161+21:26 tight glyph =
162+21:27 tight lit ~
163+21:28 tight glyph )
164+21:30 lit ~
165+21:31 tight glyph ]
166+22:3 DEDENT
167+22:3 NEWLINE
168+22:3 lit %submit
169+22:18 glyph [
170+22:19 tight name m
171+22:20 tight glyph (
172+22:21 tight name draft
173+22:26 tight glyph =
174+22:27 tight str ""
175+22:29 tight glyph )
176+22:31 glyph ~[
177+22:33 tight glyph (
178+22:34 tight wing poke.todo
179+22:44 glyph [
180+22:45 tight lit %add
181+22:50 wing draft.m
182+22:57 tight glyph ]
183+22:59 glyph |=
184+22:61 tight lit %acked
185+22:67 tight glyph )
186+22:68 tight glyph ]
187+22:69 tight glyph ]
188+23:3 NEWLINE
189+23:3 glyph [
190+23:4 tight lit %toggled
191+23:13 name id
192+23:15 tight glyph ]
193+23:18 glyph [
194+23:19 tight name m
195+23:21 glyph ~[
196+23:23 tight glyph (
197+23:24 tight wing poke.todo
198+23:34 glyph [
199+23:35 tight lit %toggle
200+23:43 name id
201+23:45 tight glyph ]
202+23:47 glyph |=
203+23:49 tight lit %acked
204+23:55 tight glyph )
205+23:56 tight glyph ]
206+23:57 tight glyph ]
207+24:3 NEWLINE
208+24:3 glyph [
209+24:4 tight lit %got
210+24:9 name ts
211+24:11 tight glyph ]
212+24:18 glyph [
213+24:19 tight name m
214+24:20 tight glyph (
215+24:21 tight name todos
216+24:26 tight glyph =
217+24:27 tight name ts
218+24:29 tight glyph )
219+24:31 lit ~
220+24:32 tight glyph ]
221+25:3 NEWLINE
222+25:3 glyph [
223+25:4 tight lit %acked
224+25:11 name err
225+25:14 tight glyph ]
226+25:18 glyph [
227+25:19 tight name m
228+25:20 tight glyph (
229+25:21 tight name error
230+25:26 tight glyph =
231+25:27 tight name err
232+25:30 tight glyph )
233+25:32 lit ~
234+25:33 tight glyph ]
23123527:1 DEDENT
23223627:1 NEWLINE
23323727:1 glyph ++
tests/golden/doc-overview-10-todo-list/tree.txt+68−65
@@ -32,7 +32,10 @@
3232 (face 13:12 ts
3333 (apply 13:15 list (ref 13:21 item.todo)))
3434 (body 14:3
35− (tuple 14:3 (wing 14:4 ts) (str 14:7 "") (lit 14:10 ~)))))
35+ (tuple 14:3
36+ (face 14:4 todos (wing 14:10 ts))
37+ (face 14:13 draft (str 14:19 ""))
38+ (face 14:22 error (lit 14:28 ~))))))
3639 (value 16:1 update
3740 (gate 16:11
3841 (cell 16:14
@@ -41,70 +44,70 @@
4144 (body 17:3
4245 (branch 17:3
4346 (wing 17:6 msg)
44− (arm 18:5
45− (cell 18:5 (lit 18:6 %typed) (bind 18:13 t))
46− (body 19:7
47− (branch 19:7
48− (group 19:10
49− (call 19:11
50− (wing 19:11 gth)
51− (group 19:15
52− (call 19:16
53− (wing 19:16 lent)
54− (group 19:21
55− (call 19:22
56− (wing 19:22 tuba)
57− (group 19:27
58− (call 19:28 (wing 19:28 trip) (wing 19:33 t)))))))
59− (lit 19:38 80)))
60− (arm 20:9
61− (lit 20:9 %.y)
62− (tuple 20:14
63− (change 20:15 m
64− (edit 20:17 draft (wing 20:23 t))
65− (edit 20:25 error
66− (unit 20:31 (str 20:32 "Too long"))))
67− (lit 20:44 ~)))
68− (arm 21:9
69− (lit 21:9 %.n)
70− (tuple 21:14
71− (change 21:15 m
72− (edit 21:17 draft (wing 21:23 t))
73− (edit 21:25 error (lit 21:31 ~)))
74− (lit 21:34 ~))))))
75− (arm 22:5
76− (lit 22:5 %submit)
77− (tuple 22:20
78− (change 22:21 m
79− (edit 22:23 draft (str 22:29 "")))
80− (list 22:33
81− (group 22:35
82− (call 22:36
83− (wing 22:36 poke.todo)
84− (tuple 22:46 (lit 22:47 %add) (wing 22:52 draft.m))
85− (ctor 22:61 %acked))))))
86− (arm 23:5
87− (cell 23:5 (lit 23:6 %toggled) (bind 23:15 id))
88− (tuple 23:20
89− (wing 23:21 m)
90− (list 23:23
91− (group 23:25
92− (call 23:26
93− (wing 23:26 poke.todo)
94− (tuple 23:36 (lit 23:37 %toggle) (wing 23:45 id))
95− (ctor 23:49 %acked))))))
96− (arm 24:5
97− (cell 24:5 (lit 24:6 %got) (bind 24:11 ts))
98− (tuple 24:20
99− (change 24:21 m
100− (edit 24:23 todos (wing 24:29 ts)))
101− (lit 24:33 ~)))
102− (arm 25:5
103− (cell 25:5 (lit 25:6 %acked) (bind 25:13 err))
104− (tuple 25:20
105− (change 25:21 m
106− (edit 25:23 error (wing 25:29 err)))
107− (lit 25:34 ~)))))))
47+ (arm 18:3
48+ (cell 18:3 (lit 18:4 %typed) (bind 18:11 t))
49+ (body 19:5
50+ (branch 19:5
51+ (group 19:8
52+ (call 19:9
53+ (wing 19:9 gth)
54+ (group 19:13
55+ (call 19:14
56+ (wing 19:14 lent)
57+ (group 19:19
58+ (call 19:20
59+ (wing 19:20 tuba)
60+ (group 19:25
61+ (call 19:26 (wing 19:26 trip) (wing 19:31 t)))))))
62+ (lit 19:36 80)))
63+ (arm 20:5
64+ (lit 20:5 %.y)
65+ (tuple 20:10
66+ (change 20:11 m
67+ (edit 20:13 draft (wing 20:19 t))
68+ (edit 20:21 error
69+ (unit 20:27 (str 20:28 "Too long"))))
70+ (lit 20:40 ~)))
71+ (arm 21:5
72+ (lit 21:5 %.n)
73+ (tuple 21:10
74+ (change 21:11 m
75+ (edit 21:13 draft (wing 21:19 t))
76+ (edit 21:21 error (lit 21:27 ~)))
77+ (lit 21:30 ~))))))
78+ (arm 22:3
79+ (lit 22:3 %submit)
80+ (tuple 22:18
81+ (change 22:19 m
82+ (edit 22:21 draft (str 22:27 "")))
83+ (list 22:31
84+ (group 22:33
85+ (call 22:34
86+ (wing 22:34 poke.todo)
87+ (tuple 22:44 (lit 22:45 %add) (wing 22:50 draft.m))
88+ (ctor 22:59 %acked))))))
89+ (arm 23:3
90+ (cell 23:3 (lit 23:4 %toggled) (bind 23:13 id))
91+ (tuple 23:18
92+ (wing 23:19 m)
93+ (list 23:21
94+ (group 23:23
95+ (call 23:24
96+ (wing 23:24 poke.todo)
97+ (tuple 23:34 (lit 23:35 %toggle) (wing 23:43 id))
98+ (ctor 23:47 %acked))))))
99+ (arm 24:3
100+ (cell 24:3 (lit 24:4 %got) (bind 24:9 ts))
101+ (tuple 24:18
102+ (change 24:19 m
103+ (edit 24:21 todos (wing 24:27 ts)))
104+ (lit 24:31 ~)))
105+ (arm 25:3
106+ (cell 25:3 (lit 25:4 %acked) (bind 25:11 err))
107+ (tuple 25:18
108+ (change 25:19 m
109+ (edit 25:21 error (wing 25:27 err)))
110+ (lit 25:32 ~)))))))
108111 (value 27:1 subs
109112 (gate 27:9
110113 (face 27:12 m (ref 27:14 model))
tests/golden/inline-cell-wing-face-bad/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar, Expressions: "A cell's items take plain names."
2+tests: a cell's item named by a wing, which only a change's item may be
3+expect: error at 1:10, the =: the wing `a.b` is the cell's first item, an operand, and the = after it goes tight where a space between items goes
tests/golden/inline-cell-wing-face-bad/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ x [a.b=1]
tests/golden/inline-cell-wing-face-bad/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph [
4+1:7 tight wing a.b
5+1:10 tight glyph =
6+1:11 tight lit 1
7+1:12 tight glyph ]
8+1:13 NEWLINE
tests/golden/inline-cell-wing-face-bad/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-cell-wing-face-bad/source.jibb:1:10: expected a space between items, found `=`; `name=value` goes in a cell, as [a=1], or a change, as m(a=1)
2+++ x [a.b=1]
3+ ^
tests/golden/inline-change-wing/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: docs/reviews/2026-11-02-syntax-review.md, S6, the proposed `toggle-open`; Grammar, Expressions: "`m(open.cart=(not open.cart.m))` sets field `open` of field `cart`, as Hoon's `m(open.cart x)`."
2+tests: the review's nested change, written with a wing item
3+expect: parses: one change of m with the edit open.cart
tests/golden/inline-change-wing/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+++ toggle-open |= m=model
2+ m(open.cart=(not open.cart.m))
tests/golden/inline-change-wing/tokens.txtnew file+18
@@ -0,0 +1,18 @@
1+1:1 glyph ++
2+1:4 name toggle-open
3+1:16 glyph |=
4+1:19 name m
5+1:20 tight glyph =
6+1:21 tight name model
7+2:3 INDENT
8+2:3 name m
9+2:4 tight glyph (
10+2:5 tight wing open.cart
11+2:14 tight glyph =
12+2:15 tight glyph (
13+2:16 tight name not
14+2:20 wing open.cart.m
15+2:31 tight glyph )
16+2:32 tight glyph )
17+2:33 DEDENT
18+2:33 NEWLINE
tests/golden/inline-change-wing/tree.txtnew file+9
@@ -0,0 +1,9 @@
1+(module
2+ (value 1:1 toggle-open
3+ (gate 1:16
4+ (face 1:19 m (ref 1:21 model))
5+ (body 2:3
6+ (change 2:3 m
7+ (edit 2:5 open.cart
8+ (group 2:15
9+ (call 2:16 (wing 2:16 not) (wing 2:20 open.cart.m)))))))))
tests/golden/inline-decimal-aura-bad/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Literals by context: "every other aura takes its own literal, as `~s30` for a `@dr`, `~2026.1.1` for a `@da`, `~zod` for a `@p`, `"5"` for a `@t` and `0x1` for a `@ux`. So `^- @dr 30`, `^- @p 0` … are errors, each naming the number and the aura it met".
2+tests: A decimal cast to an aura outside `@ud`'s family is an error at the decimal, naming it and the aura; the hint writes the same value in that aura's literal (~s30, ~zod, "5", ~.30, 0x1, 0vu), a date gets an example, and `@tas` and `@tD`, which have no literal of their own, get no hint.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-decimal-aura-bad/source.jibbnew file+10
@@ -0,0 +1,10 @@
1+++ duration ^- @dr 30
2+++ date ^- @da 30
3+++ ship ^- @p 0
4+++ cord ^- @t 5
5+++ grouped ^- @t 1.000
6+++ knot ^- @ta 30
7+++ hex ^- @ux 1
8+++ base32 ^- @uv 30
9+++ term ^- @tas 30
10+++ char ^- @tD 97
tests/golden/inline-decimal-aura-bad/tokens.txtnew file+60
@@ -0,0 +1,60 @@
1+1:1 glyph ++
2+1:4 name duration
3+1:13 glyph ^-
4+1:16 aura @dr
5+1:20 lit 30
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name date
9+2:9 glyph ^-
10+2:12 aura @da
11+2:16 lit 30
12+3:1 NEWLINE
13+3:1 glyph ++
14+3:4 name ship
15+3:9 glyph ^-
16+3:12 aura @p
17+3:15 lit 0
18+4:1 NEWLINE
19+4:1 glyph ++
20+4:4 name cord
21+4:9 glyph ^-
22+4:12 aura @t
23+4:15 lit 5
24+5:1 NEWLINE
25+5:1 glyph ++
26+5:4 name grouped
27+5:12 glyph ^-
28+5:15 aura @t
29+5:18 lit 1.000
30+6:1 NEWLINE
31+6:1 glyph ++
32+6:4 name knot
33+6:9 glyph ^-
34+6:12 aura @ta
35+6:16 lit 30
36+7:1 NEWLINE
37+7:1 glyph ++
38+7:4 name hex
39+7:8 glyph ^-
40+7:11 aura @ux
41+7:15 lit 1
42+8:1 NEWLINE
43+8:1 glyph ++
44+8:4 name base32
45+8:11 glyph ^-
46+8:14 aura @uv
47+8:18 lit 30
48+9:1 NEWLINE
49+9:1 glyph ++
50+9:4 name term
51+9:9 glyph ^-
52+9:12 aura @tas
53+9:17 lit 30
54+10:1 NEWLINE
55+10:1 glyph ++
56+10:4 name char
57+10:9 glyph ^-
58+10:12 aura @tD
59+10:16 lit 97
60+10:18 NEWLINE
tests/golden/inline-decimal-aura-bad/tree.txtnew file+21
@@ -0,0 +1,21 @@
1+(module
2+ (value 1:1 duration
3+ (cast 1:13 (aura 1:16 @dr) (lit 1:20 30)))
4+ (value 2:1 date
5+ (cast 2:9 (aura 2:12 @da) (lit 2:16 30)))
6+ (value 3:1 ship
7+ (cast 3:9 (aura 3:12 @p) (lit 3:15 0)))
8+ (value 4:1 cord
9+ (cast 4:9 (aura 4:12 @t) (lit 4:15 5)))
10+ (value 5:1 grouped
11+ (cast 5:12 (aura 5:15 @t) (lit 5:18 1.000)))
12+ (value 6:1 knot
13+ (cast 6:9 (aura 6:12 @ta) (lit 6:16 30)))
14+ (value 7:1 hex
15+ (cast 7:8 (aura 7:11 @ux) (lit 7:15 1)))
16+ (value 8:1 base32
17+ (cast 8:11 (aura 8:14 @uv) (lit 8:18 30)))
18+ (value 9:1 term
19+ (cast 9:9 (aura 9:12 @tas) (lit 9:17 30)))
20+ (value 10:1 char
21+ (cast 10:9 (aura 10:12 @tD) (lit 10:16 97))))
tests/golden/inline-decimal-aura-bad/types.txtnew file+41
@@ -0,0 +1,41 @@
1+partial inference; module not checked
2+++ duration: `30` is a @ud, not a @dr; write ~s30
3+/tests/golden/inline-decimal-aura-bad/source.jibb:1:20: decimal
4+++ duration ^- @dr 30
5+ ^
6+++ date: `30` is a @ud, not a @da; write a date, as ~2026.1.1
7+/tests/golden/inline-decimal-aura-bad/source.jibb:2:16: decimal
8+++ date ^- @da 30
9+ ^
10+++ ship: `0` is a @ud, not a @p; write ~zod
11+/tests/golden/inline-decimal-aura-bad/source.jibb:3:15: decimal
12+++ ship ^- @p 0
13+ ^
14+++ cord: `5` is a @ud, not a @t; write "5"
15+/tests/golden/inline-decimal-aura-bad/source.jibb:4:15: decimal
16+++ cord ^- @t 5
17+ ^
18+++ grouped: `1.000` is a @ud, not a @t; write "1.000"
19+/tests/golden/inline-decimal-aura-bad/source.jibb:5:18: decimal
20+++ grouped ^- @t 1.000
21+ ^
22+++ knot: `30` is a @ud, not a @ta; write ~.30
23+/tests/golden/inline-decimal-aura-bad/source.jibb:6:16: decimal
24+++ knot ^- @ta 30
25+ ^
26+++ hex: `1` is a @ud, not a @ux; write 0x1
27+/tests/golden/inline-decimal-aura-bad/source.jibb:7:15: decimal
28+++ hex ^- @ux 1
29+ ^
30+++ base32: `30` is a @ud, not a @uv; write 0vu
31+/tests/golden/inline-decimal-aura-bad/source.jibb:8:18: decimal
32+++ base32 ^- @uv 30
33+ ^
34+++ term: `30` is a @ud, not a @tas
35+/tests/golden/inline-decimal-aura-bad/source.jibb:9:17: decimal
36+++ term ^- @tas 30
37+ ^
38+++ char: `97` is a @ud, not a @tD
39+/tests/golden/inline-decimal-aura-bad/source.jibb:10:16: decimal
40+++ char ^- @tD 97
41+ ^
tests/golden/inline-decimal-fits/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Literals: a decimal is "`@ud`, which also fits `@u`, `@` and `*`"; Literals by context: "A number is a `@ud`, as in Hoon: a context can make it a `@u`, and it fits `@` and `*`".
2+tests: A decimal fits `@ud`, `@u`, bare `@` and the noun `*`, in casts, as an argument beside a `@u` and as list items; with nothing to fix it, it takes `@ud`. A hexadecimal fits `@ux`.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-decimal-fits/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/inline-decimal-fits/source.jibbnew file+9
@@ -0,0 +1,9 @@
1+++ plain ^- @ud 30
2+++ unsigned ^- @u 30
3+++ atom ^- @ 30
4+++ noun ^- * 30
5+++ grouped ^- @ud 1.000
6+++ sum |= x=@u (add x 1)
7+++ counts ^- (list @u) ~[1 2]
8+++ count 7
9+++ hex ^- @ux 0x1e
tests/golden/inline-decimal-fits/tokens.txtnew file+64
@@ -0,0 +1,64 @@
1+1:1 glyph ++
2+1:4 name plain
3+1:10 glyph ^-
4+1:13 aura @ud
5+1:17 lit 30
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name unsigned
9+2:13 glyph ^-
10+2:16 aura @u
11+2:19 lit 30
12+3:1 NEWLINE
13+3:1 glyph ++
14+3:4 name atom
15+3:9 glyph ^-
16+3:12 aura @
17+3:14 lit 30
18+4:1 NEWLINE
19+4:1 glyph ++
20+4:4 name noun
21+4:9 glyph ^-
22+4:12 glyph *
23+4:14 lit 30
24+5:1 NEWLINE
25+5:1 glyph ++
26+5:4 name grouped
27+5:12 glyph ^-
28+5:15 aura @ud
29+5:19 lit 1.000
30+6:1 NEWLINE
31+6:1 glyph ++
32+6:4 name sum
33+6:8 glyph |=
34+6:11 name x
35+6:12 tight glyph =
36+6:13 tight aura @u
37+6:16 glyph (
38+6:17 tight name add
39+6:21 name x
40+6:23 lit 1
41+6:24 tight glyph )
42+7:1 NEWLINE
43+7:1 glyph ++
44+7:4 name counts
45+7:11 glyph ^-
46+7:14 glyph (
47+7:15 tight name list
48+7:20 aura @u
49+7:22 tight glyph )
50+7:24 glyph ~[
51+7:26 tight lit 1
52+7:28 lit 2
53+7:29 tight glyph ]
54+8:1 NEWLINE
55+8:1 glyph ++
56+8:4 name count
57+8:10 lit 7
58+9:1 NEWLINE
59+9:1 glyph ++
60+9:4 name hex
61+9:8 glyph ^-
62+9:11 aura @ux
63+9:15 lit 0x1e
64+9:19 NEWLINE
tests/golden/inline-decimal-fits/tree.txtnew file+23
@@ -0,0 +1,23 @@
1+(module
2+ (value 1:1 plain
3+ (cast 1:10 (aura 1:13 @ud) (lit 1:17 30)))
4+ (value 2:1 unsigned
5+ (cast 2:13 (aura 2:16 @u) (lit 2:19 30)))
6+ (value 3:1 atom
7+ (cast 3:9 (aura 3:12 @) (lit 3:14 30)))
8+ (value 4:1 noun
9+ (cast 4:9 (noun 4:12) (lit 4:14 30)))
10+ (value 5:1 grouped
11+ (cast 5:12 (aura 5:15 @ud) (lit 5:19 1.000)))
12+ (value 6:1 sum
13+ (gate 6:8
14+ (face 6:11 x (aura 6:13 @u))
15+ (group 6:16
16+ (call 6:17 (wing 6:17 add) (wing 6:21 x) (lit 6:23 1)))))
17+ (value 7:1 counts
18+ (cast 7:11
19+ (apply 7:14 list (aura 7:20 @u))
20+ (list 7:24 (lit 7:26 1) (lit 7:28 2))))
21+ (value 8:1 count (lit 8:10 7))
22+ (value 9:1 hex
23+ (cast 9:8 (aura 9:11 @ux) (lit 9:15 0x1e))))
tests/golden/inline-decimal-fits/types.txtnew file+10
@@ -0,0 +1,10 @@
1+partial inference; module not checked
2+++ plain: @ud
3+++ unsigned: @u
4+++ atom: @
5+++ noun: *
6+++ grouped: @ud
7+++ sum: $-(@u @u)
8+++ counts: (list @u)
9+++ count: @ud
10+++ hex: @ux
tests/golden/inline-decimal-generic/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Literals by context: "A number takes `@ud` only if nothing fixes its aura and its `++` isn't generic over it, so `++ inc |= n=A (add n 1)` stays generic, and `(inc ~s1)` is a `@dr`".
2+tests: A decimal inside a `++` that is generic over its aura stays generic: `bump` takes any atom but `?`, so a duration, a hexadecimal and a ship each keep their aura, and a decimal argument is a `@ud`.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-decimal-generic/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/inline-decimal-generic/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ bump |= x=A (add x 1)
2+++ later (bump ~s1)
3+++ hex (bump 0x1)
4+++ ship (bump ~zod)
5+++ count (bump 2)
tests/golden/inline-decimal-generic/tokens.txtnew file+40
@@ -0,0 +1,40 @@
1+1:1 glyph ++
2+1:4 name bump
3+1:9 glyph |=
4+1:12 name x
5+1:13 tight glyph =
6+1:14 tight tvar A
7+1:16 glyph (
8+1:17 tight name add
9+1:21 name x
10+1:23 lit 1
11+1:24 tight glyph )
12+2:1 NEWLINE
13+2:1 glyph ++
14+2:4 name later
15+2:10 glyph (
16+2:11 tight name bump
17+2:16 lit ~s1
18+2:19 tight glyph )
19+3:1 NEWLINE
20+3:1 glyph ++
21+3:4 name hex
22+3:8 glyph (
23+3:9 tight name bump
24+3:14 lit 0x1
25+3:17 tight glyph )
26+4:1 NEWLINE
27+4:1 glyph ++
28+4:4 name ship
29+4:9 glyph (
30+4:10 tight name bump
31+4:15 lit ~zod
32+4:19 tight glyph )
33+5:1 NEWLINE
34+5:1 glyph ++
35+5:4 name count
36+5:10 glyph (
37+5:11 tight name bump
38+5:16 lit 2
39+5:17 tight glyph )
40+5:18 NEWLINE
tests/golden/inline-decimal-generic/tree.txtnew file+18
@@ -0,0 +1,18 @@
1+(module
2+ (value 1:1 bump
3+ (gate 1:9
4+ (face 1:12 x (tvar 1:14 A))
5+ (group 1:16
6+ (call 1:17 (wing 1:17 add) (wing 1:21 x) (lit 1:23 1)))))
7+ (value 2:1 later
8+ (group 2:10
9+ (call 2:11 (wing 2:11 bump) (lit 2:16 ~s1))))
10+ (value 3:1 hex
11+ (group 3:8
12+ (call 3:9 (wing 3:9 bump) (lit 3:14 0x1))))
13+ (value 4:1 ship
14+ (group 4:9
15+ (call 4:10 (wing 4:10 bump) (lit 4:15 ~zod))))
16+ (value 5:1 count
17+ (group 5:10
18+ (call 5:11 (wing 5:11 bump) (lit 5:16 2)))))
tests/golden/inline-decimal-generic/types.txtnew file+6
@@ -0,0 +1,6 @@
1+partial inference; module not checked
2+++ bump: $-(A A) where A is an atom other than ?
3+++ later: @dr
4+++ hex: @ux
5+++ ship: @p
6+++ count: @ud
tests/golden/inline-decimal-patterns/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Patterns: "A number pattern is a `@ud` too, so `0` can't match a `@p` or a `@dr`: write `~zod`, or compare a duration with `eq`".
2+tests: A number pattern where the subject, a union case's field or a cell's item is a `@dr`, `@p`, `@t` or `@da` is an error at the first such pattern, with a hint only where patterns take that aura's literal. Number patterns on a `@ud` keep the checker's existing unsupported messages.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-decimal-patterns/source.jibbnew file+30
@@ -0,0 +1,30 @@
1++$ event
2+ [%gap d=@dr]
3+ [%count n=@ud]
4+++ on-gap |= d=@dr ?- d
5+ 0 %zero
6+ * %other
7+++ on-ship |= s=@p ?- s
8+ 0 %zod
9+ * %other
10+++ on-text |= t=@t ?- t
11+ 5 %five
12+ * %other
13+++ on-date |= d=@da ?- d
14+ 0 %epoch
15+ 1 %next
16+ * %other
17+++ on-event |= e=event ?- e
18+ [%gap 0] 1
19+ [%gap *] 2
20+ [%count 0] 3
21+ [%count *] 4
22+++ on-pair |= [d=@dr n=@ud] ?- [d n]
23+ [0 0] 1
24+ * 2
25+++ on-count |= n=@ud ?- n
26+ 0 %zero
27+ * %other
28+++ on-counts |= e=event ?- e
29+ [%count 0] 3
30+ * 4
tests/golden/inline-decimal-patterns/tokens.txtnew file+181
@@ -0,0 +1,181 @@
1+1:1 glyph +$
2+1:4 name event
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %gap
6+2:9 name d
7+2:10 tight glyph =
8+2:11 tight aura @dr
9+2:14 tight glyph ]
10+3:3 NEWLINE
11+3:3 glyph [
12+3:4 tight lit %count
13+3:11 name n
14+3:12 tight glyph =
15+3:13 tight aura @ud
16+3:16 tight glyph ]
17+4:1 DEDENT
18+4:1 NEWLINE
19+4:1 glyph ++
20+4:4 name on-gap
21+4:11 glyph |=
22+4:14 name d
23+4:15 tight glyph =
24+4:16 tight aura @dr
25+4:20 glyph ?-
26+4:23 name d
27+5:3 INDENT
28+5:3 lit 0
29+5:5 lit %zero
30+6:3 NEWLINE
31+6:3 glyph *
32+6:5 lit %other
33+7:1 DEDENT
34+7:1 NEWLINE
35+7:1 glyph ++
36+7:4 name on-ship
37+7:12 glyph |=
38+7:15 name s
39+7:16 tight glyph =
40+7:17 tight aura @p
41+7:20 glyph ?-
42+7:23 name s
43+8:3 INDENT
44+8:3 lit 0
45+8:5 lit %zod
46+9:3 NEWLINE
47+9:3 glyph *
48+9:5 lit %other
49+10:1 DEDENT
50+10:1 NEWLINE
51+10:1 glyph ++
52+10:4 name on-text
53+10:12 glyph |=
54+10:15 name t
55+10:16 tight glyph =
56+10:17 tight aura @t
57+10:20 glyph ?-
58+10:23 name t
59+11:3 INDENT
60+11:3 lit 5
61+11:5 lit %five
62+12:3 NEWLINE
63+12:3 glyph *
64+12:5 lit %other
65+13:1 DEDENT
66+13:1 NEWLINE
67+13:1 glyph ++
68+13:4 name on-date
69+13:12 glyph |=
70+13:15 name d
71+13:16 tight glyph =
72+13:17 tight aura @da
73+13:21 glyph ?-
74+13:24 name d
75+14:3 INDENT
76+14:3 lit 0
77+14:5 lit %epoch
78+15:3 NEWLINE
79+15:3 lit 1
80+15:5 lit %next
81+16:3 NEWLINE
82+16:3 glyph *
83+16:5 lit %other
84+17:1 DEDENT
85+17:1 NEWLINE
86+17:1 glyph ++
87+17:4 name on-event
88+17:13 glyph |=
89+17:16 name e
90+17:17 tight glyph =
91+17:18 tight name event
92+17:24 glyph ?-
93+17:27 name e
94+18:3 INDENT
95+18:3 glyph [
96+18:4 tight lit %gap
97+18:9 lit 0
98+18:10 tight glyph ]
99+18:12 lit 1
100+19:3 NEWLINE
101+19:3 glyph [
102+19:4 tight lit %gap
103+19:9 glyph *
104+19:10 tight glyph ]
105+19:12 lit 2
106+20:3 NEWLINE
107+20:3 glyph [
108+20:4 tight lit %count
109+20:11 lit 0
110+20:12 tight glyph ]
111+20:14 lit 3
112+21:3 NEWLINE
113+21:3 glyph [
114+21:4 tight lit %count
115+21:11 glyph *
116+21:12 tight glyph ]
117+21:14 lit 4
118+22:1 DEDENT
119+22:1 NEWLINE
120+22:1 glyph ++
121+22:4 name on-pair
122+22:12 glyph |=
123+22:15 glyph [
124+22:16 tight name d
125+22:17 tight glyph =
126+22:18 tight aura @dr
127+22:22 name n
128+22:23 tight glyph =
129+22:24 tight aura @ud
130+22:27 tight glyph ]
131+22:29 glyph ?-
132+22:32 glyph [
133+22:33 tight name d
134+22:35 name n
135+22:36 tight glyph ]
136+23:3 INDENT
137+23:3 glyph [
138+23:4 tight lit 0
139+23:6 lit 0
140+23:7 tight glyph ]
141+23:9 lit 1
142+24:3 NEWLINE
143+24:3 glyph *
144+24:5 lit 2
145+25:1 DEDENT
146+25:1 NEWLINE
147+25:1 glyph ++
148+25:4 name on-count
149+25:13 glyph |=
150+25:16 name n
151+25:17 tight glyph =
152+25:18 tight aura @ud
153+25:22 glyph ?-
154+25:25 name n
155+26:3 INDENT
156+26:3 lit 0
157+26:5 lit %zero
158+27:3 NEWLINE
159+27:3 glyph *
160+27:5 lit %other
161+28:1 DEDENT
162+28:1 NEWLINE
163+28:1 glyph ++
164+28:4 name on-counts
165+28:14 glyph |=
166+28:17 name e
167+28:18 tight glyph =
168+28:19 tight name event
169+28:25 glyph ?-
170+28:28 name e
171+29:3 INDENT
172+29:3 glyph [
173+29:4 tight lit %count
174+29:11 lit 0
175+29:12 tight glyph ]
176+29:14 lit 3
177+30:3 NEWLINE
178+30:3 glyph *
179+30:5 lit 4
180+30:6 DEDENT
181+30:6 NEWLINE
tests/golden/inline-decimal-patterns/tree.txtnew file+82
@@ -0,0 +1,82 @@
1+(module
2+ (mold 1:1 event
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %gap)
6+ (face 2:9 d (aura 2:11 @dr)))
7+ (cell 3:3
8+ (const 3:4 %count)
9+ (face 3:11 n (aura 3:13 @ud)))))
10+ (value 4:1 on-gap
11+ (gate 4:11
12+ (face 4:14 d (aura 4:16 @dr))
13+ (branch 4:20
14+ (wing 4:23 d)
15+ (arm 5:3 (lit 5:3 0) (lit 5:5 %zero))
16+ (arm 6:3 (any 6:3) (lit 6:5 %other)))))
17+ (value 7:1 on-ship
18+ (gate 7:12
19+ (face 7:15 s (aura 7:17 @p))
20+ (branch 7:20
21+ (wing 7:23 s)
22+ (arm 8:3 (lit 8:3 0) (lit 8:5 %zod))
23+ (arm 9:3 (any 9:3) (lit 9:5 %other)))))
24+ (value 10:1 on-text
25+ (gate 10:12
26+ (face 10:15 t (aura 10:17 @t))
27+ (branch 10:20
28+ (wing 10:23 t)
29+ (arm 11:3 (lit 11:3 5) (lit 11:5 %five))
30+ (arm 12:3 (any 12:3) (lit 12:5 %other)))))
31+ (value 13:1 on-date
32+ (gate 13:12
33+ (face 13:15 d (aura 13:17 @da))
34+ (branch 13:21
35+ (wing 13:24 d)
36+ (arm 14:3 (lit 14:3 0) (lit 14:5 %epoch))
37+ (arm 15:3 (lit 15:3 1) (lit 15:5 %next))
38+ (arm 16:3 (any 16:3) (lit 16:5 %other)))))
39+ (value 17:1 on-event
40+ (gate 17:13
41+ (face 17:16 e (ref 17:18 event))
42+ (branch 17:24
43+ (wing 17:27 e)
44+ (arm 18:3
45+ (cell 18:3 (lit 18:4 %gap) (lit 18:9 0))
46+ (lit 18:12 1))
47+ (arm 19:3
48+ (cell 19:3 (lit 19:4 %gap) (any 19:9))
49+ (lit 19:12 2))
50+ (arm 20:3
51+ (cell 20:3 (lit 20:4 %count) (lit 20:11 0))
52+ (lit 20:14 3))
53+ (arm 21:3
54+ (cell 21:3 (lit 21:4 %count) (any 21:11))
55+ (lit 21:14 4)))))
56+ (value 22:1 on-pair
57+ (gate 22:12
58+ (cell 22:15
59+ (face 22:16 d (aura 22:18 @dr))
60+ (face 22:22 n (aura 22:24 @ud)))
61+ (branch 22:29
62+ (tuple 22:32 (wing 22:33 d) (wing 22:35 n))
63+ (arm 23:3
64+ (cell 23:3 (lit 23:4 0) (lit 23:6 0))
65+ (lit 23:9 1))
66+ (arm 24:3 (any 24:3) (lit 24:5 2)))))
67+ (value 25:1 on-count
68+ (gate 25:13
69+ (face 25:16 n (aura 25:18 @ud))
70+ (branch 25:22
71+ (wing 25:25 n)
72+ (arm 26:3 (lit 26:3 0) (lit 26:5 %zero))
73+ (arm 27:3 (any 27:3) (lit 27:5 %other)))))
74+ (value 28:1 on-counts
75+ (gate 28:14
76+ (face 28:17 e (ref 28:19 event))
77+ (branch 28:25
78+ (wing 28:28 e)
79+ (arm 29:3
80+ (cell 29:3 (lit 29:4 %count) (lit 29:11 0))
81+ (lit 29:14 3))
82+ (arm 30:3 (any 30:3) (lit 30:5 4))))))
tests/golden/inline-decimal-patterns/types.txtnew file+28
@@ -0,0 +1,28 @@
1+partial inference; module not checked
2++$ event: cases proven disjoint; mold not checked
3+++ on-gap: `0` is a @ud, not a @dr
4+/tests/golden/inline-decimal-patterns/source.jibb:5:3: decimal
5+ 0 %zero
6+ ^
7+++ on-ship: `0` is a @ud, not a @p; write ~zod
8+/tests/golden/inline-decimal-patterns/source.jibb:8:3: decimal
9+ 0 %zod
10+ ^
11+++ on-text: `5` is a @ud, not a @t; write "5"
12+/tests/golden/inline-decimal-patterns/source.jibb:11:3: decimal
13+ 5 %five
14+ ^
15+++ on-date: `0` is a @ud, not a @da
16+/tests/golden/inline-decimal-patterns/source.jibb:14:3: decimal
17+ 0 %epoch
18+ ^
19+++ on-event: `0` is a @ud, not a @dr
20+/tests/golden/inline-decimal-patterns/source.jibb:18:9: decimal
21+ [%gap 0] 1
22+ ^
23+++ on-pair: `0` is a @ud, not a @dr
24+/tests/golden/inline-decimal-patterns/source.jibb:23:4: decimal
25+ [0 0] 1
26+ ^
27+++ on-count: branch is not supported by partial inference
28+++ on-counts: partial union pattern is not supported by partial inference
tests/golden/inline-decimal-sites/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Literals by context: "So `^- @dr 30`, `^- @p 0`, `(add ~s1 1)` and `(text 5)` are errors, each naming the number and the aura it met"; syntax review S4: `[%every 1 |=%tick]` and `(text 5)`.
2+tests: Every place a decimal meets another aura gives the same error at the decimal: a call's argument, an argument of a generic gate whose other argument fixes the aura (either order), a record field, a change, a list item under a cast, an open list's later or earlier item, a unit payload, a branch arm, a union case picked by its tag inside a list or a cast, a term-headed pair, and `text`'s argument. The duration, text and element controls check.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-decimal-sites/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/inline-decimal-sites/source.jibbnew file+24
@@ -0,0 +1,24 @@
1++$ msg
2+ [%tick at=@da]
3+ [%done n=@ud]
4+++ pause |= d=@dr d
5+++ arg (pause 30)
6+++ later |= d=@dr (add d 1)
7+++ sooner |= d=@dr (add 1 d)
8+++ zero |= d=@dr (eq d 0)
9+++ record ^- [gap=@dr n=@ud] [gap=30 n=1]
10+++ change |= m=[gap=@dr n=@ud] m(gap=30)
11+++ items ^- (list @dr) ~[~s1 2]
12+++ open ~[~s1 2]
13+++ open-first ~[2 ~s1]
14+++ payload ^- (unit @dr) `30
15+++ either |= b=? ?- b
16+ %.y ~s1
17+ %.n 2
18+++ every ^- (list (sub msg)) ~[[%every 1 |=%tick]]
19+++ every-ok ^- (list (sub msg)) ~[[%every ~s1 |=%tick]]
20+++ timer ^- (cmd msg) [%wait 30 [%done 1]]
21+++ timer-pair ^- (cmd msg) wait+[30 [%done 1]]
22+++ note (text 5)
23+++ note-ok (text "5")
24+++ shown ^- (element !!) (text 5)
tests/golden/inline-decimal-sites/tokens.txtnew file+258
@@ -0,0 +1,258 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %tick
6+2:10 name at
7+2:12 tight glyph =
8+2:13 tight aura @da
9+2:16 tight glyph ]
10+3:3 NEWLINE
11+3:3 glyph [
12+3:4 tight lit %done
13+3:10 name n
14+3:11 tight glyph =
15+3:12 tight aura @ud
16+3:15 tight glyph ]
17+4:1 DEDENT
18+4:1 NEWLINE
19+4:1 glyph ++
20+4:4 name pause
21+4:10 glyph |=
22+4:13 name d
23+4:14 tight glyph =
24+4:15 tight aura @dr
25+4:19 name d
26+5:1 NEWLINE
27+5:1 glyph ++
28+5:4 name arg
29+5:8 glyph (
30+5:9 tight name pause
31+5:15 lit 30
32+5:17 tight glyph )
33+6:1 NEWLINE
34+6:1 glyph ++
35+6:4 name later
36+6:10 glyph |=
37+6:13 name d
38+6:14 tight glyph =
39+6:15 tight aura @dr
40+6:19 glyph (
41+6:20 tight name add
42+6:24 name d
43+6:26 lit 1
44+6:27 tight glyph )
45+7:1 NEWLINE
46+7:1 glyph ++
47+7:4 name sooner
48+7:11 glyph |=
49+7:14 name d
50+7:15 tight glyph =
51+7:16 tight aura @dr
52+7:20 glyph (
53+7:21 tight name add
54+7:25 lit 1
55+7:27 name d
56+7:28 tight glyph )
57+8:1 NEWLINE
58+8:1 glyph ++
59+8:4 name zero
60+8:9 glyph |=
61+8:12 name d
62+8:13 tight glyph =
63+8:14 tight aura @dr
64+8:18 glyph (
65+8:19 tight name eq
66+8:22 name d
67+8:24 lit 0
68+8:25 tight glyph )
69+9:1 NEWLINE
70+9:1 glyph ++
71+9:4 name record
72+9:11 glyph ^-
73+9:14 glyph [
74+9:15 tight name gap
75+9:18 tight glyph =
76+9:19 tight aura @dr
77+9:23 name n
78+9:24 tight glyph =
79+9:25 tight aura @ud
80+9:28 tight glyph ]
81+9:30 glyph [
82+9:31 tight name gap
83+9:34 tight glyph =
84+9:35 tight lit 30
85+9:38 name n
86+9:39 tight glyph =
87+9:40 tight lit 1
88+9:41 tight glyph ]
89+10:1 NEWLINE
90+10:1 glyph ++
91+10:4 name change
92+10:11 glyph |=
93+10:14 name m
94+10:15 tight glyph =
95+10:16 tight glyph [
96+10:17 tight name gap
97+10:20 tight glyph =
98+10:21 tight aura @dr
99+10:25 name n
100+10:26 tight glyph =
101+10:27 tight aura @ud
102+10:30 tight glyph ]
103+10:32 name m
104+10:33 tight glyph (
105+10:34 tight name gap
106+10:37 tight glyph =
107+10:38 tight lit 30
108+10:40 tight glyph )
109+11:1 NEWLINE
110+11:1 glyph ++
111+11:4 name items
112+11:10 glyph ^-
113+11:13 glyph (
114+11:14 tight name list
115+11:19 aura @dr
116+11:22 tight glyph )
117+11:24 glyph ~[
118+11:26 tight lit ~s1
119+11:30 lit 2
120+11:31 tight glyph ]
121+12:1 NEWLINE
122+12:1 glyph ++
123+12:4 name open
124+12:9 glyph ~[
125+12:11 tight lit ~s1
126+12:15 lit 2
127+12:16 tight glyph ]
128+13:1 NEWLINE
129+13:1 glyph ++
130+13:4 name open-first
131+13:15 glyph ~[
132+13:17 tight lit 2
133+13:19 lit ~s1
134+13:22 tight glyph ]
135+14:1 NEWLINE
136+14:1 glyph ++
137+14:4 name payload
138+14:12 glyph ^-
139+14:15 glyph (
140+14:16 tight name unit
141+14:21 aura @dr
142+14:24 tight glyph )
143+14:26 glyph `
144+14:27 tight lit 30
145+15:1 NEWLINE
146+15:1 glyph ++
147+15:4 name either
148+15:11 glyph |=
149+15:14 name b
150+15:15 tight glyph =
151+15:16 tight glyph ?
152+15:18 glyph ?-
153+15:21 name b
154+16:3 INDENT
155+16:3 lit %.y
156+16:7 lit ~s1
157+17:3 NEWLINE
158+17:3 lit %.n
159+17:7 lit 2
160+18:1 DEDENT
161+18:1 NEWLINE
162+18:1 glyph ++
163+18:4 name every
164+18:10 glyph ^-
165+18:13 glyph (
166+18:14 tight name list
167+18:19 glyph (
168+18:20 tight name sub
169+18:24 name msg
170+18:27 tight glyph )
171+18:28 tight glyph )
172+18:30 glyph ~[
173+18:32 tight glyph [
174+18:33 tight lit %every
175+18:40 lit 1
176+18:42 glyph |=
177+18:44 tight lit %tick
178+18:49 tight glyph ]
179+18:50 tight glyph ]
180+19:1 NEWLINE
181+19:1 glyph ++
182+19:4 name every-ok
183+19:13 glyph ^-
184+19:16 glyph (
185+19:17 tight name list
186+19:22 glyph (
187+19:23 tight name sub
188+19:27 name msg
189+19:30 tight glyph )
190+19:31 tight glyph )
191+19:33 glyph ~[
192+19:35 tight glyph [
193+19:36 tight lit %every
194+19:43 lit ~s1
195+19:47 glyph |=
196+19:49 tight lit %tick
197+19:54 tight glyph ]
198+19:55 tight glyph ]
199+20:1 NEWLINE
200+20:1 glyph ++
201+20:4 name timer
202+20:10 glyph ^-
203+20:13 glyph (
204+20:14 tight name cmd
205+20:18 name msg
206+20:21 tight glyph )
207+20:23 glyph [
208+20:24 tight lit %wait
209+20:30 lit 30
210+20:33 glyph [
211+20:34 tight lit %done
212+20:40 lit 1
213+20:41 tight glyph ]
214+20:42 tight glyph ]
215+21:1 NEWLINE
216+21:1 glyph ++
217+21:4 name timer-pair
218+21:15 glyph ^-
219+21:18 glyph (
220+21:19 tight name cmd
221+21:23 name msg
222+21:26 tight glyph )
223+21:28 name wait
224+21:32 tight glyph +
225+21:33 tight glyph [
226+21:34 tight lit 30
227+21:37 glyph [
228+21:38 tight lit %done
229+21:44 lit 1
230+21:45 tight glyph ]
231+21:46 tight glyph ]
232+22:1 NEWLINE
233+22:1 glyph ++
234+22:4 name note
235+22:9 glyph (
236+22:10 tight name text
237+22:15 lit 5
238+22:16 tight glyph )
239+23:1 NEWLINE
240+23:1 glyph ++
241+23:4 name note-ok
242+23:12 glyph (
243+23:13 tight name text
244+23:18 str "5"
245+23:21 tight glyph )
246+24:1 NEWLINE
247+24:1 glyph ++
248+24:4 name shown
249+24:10 glyph ^-
250+24:13 glyph (
251+24:14 tight name element
252+24:22 glyph !!
253+24:24 tight glyph )
254+24:26 glyph (
255+24:27 tight name text
256+24:32 lit 5
257+24:33 tight glyph )
258+24:34 NEWLINE
tests/golden/inline-decimal-sites/tree.txtnew file+103
@@ -0,0 +1,103 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %tick)
6+ (face 2:10 at (aura 2:13 @da)))
7+ (cell 3:3
8+ (const 3:4 %done)
9+ (face 3:10 n (aura 3:12 @ud)))))
10+ (value 4:1 pause
11+ (gate 4:10
12+ (face 4:13 d (aura 4:15 @dr))
13+ (wing 4:19 d)))
14+ (value 5:1 arg
15+ (group 5:8
16+ (call 5:9 (wing 5:9 pause) (lit 5:15 30))))
17+ (value 6:1 later
18+ (gate 6:10
19+ (face 6:13 d (aura 6:15 @dr))
20+ (group 6:19
21+ (call 6:20 (wing 6:20 add) (wing 6:24 d) (lit 6:26 1)))))
22+ (value 7:1 sooner
23+ (gate 7:11
24+ (face 7:14 d (aura 7:16 @dr))
25+ (group 7:20
26+ (call 7:21 (wing 7:21 add) (lit 7:25 1) (wing 7:27 d)))))
27+ (value 8:1 zero
28+ (gate 8:9
29+ (face 8:12 d (aura 8:14 @dr))
30+ (group 8:18
31+ (call 8:19 (wing 8:19 eq) (wing 8:22 d) (lit 8:24 0)))))
32+ (value 9:1 record
33+ (cast 9:11
34+ (cell 9:14
35+ (face 9:15 gap (aura 9:19 @dr))
36+ (face 9:23 n (aura 9:25 @ud)))
37+ (tuple 9:30
38+ (face 9:31 gap (lit 9:35 30))
39+ (face 9:38 n (lit 9:40 1)))))
40+ (value 10:1 change
41+ (gate 10:11
42+ (face 10:14 m
43+ (cell 10:16
44+ (face 10:17 gap (aura 10:21 @dr))
45+ (face 10:25 n (aura 10:27 @ud))))
46+ (change 10:32 m
47+ (edit 10:34 gap (lit 10:38 30)))))
48+ (value 11:1 items
49+ (cast 11:10
50+ (apply 11:13 list (aura 11:19 @dr))
51+ (list 11:24 (lit 11:26 ~s1) (lit 11:30 2))))
52+ (value 12:1 open
53+ (list 12:9 (lit 12:11 ~s1) (lit 12:15 2)))
54+ (value 13:1 open-first
55+ (list 13:15 (lit 13:17 2) (lit 13:19 ~s1)))
56+ (value 14:1 payload
57+ (cast 14:12
58+ (apply 14:15 unit (aura 14:21 @dr))
59+ (unit 14:26 (lit 14:27 30))))
60+ (value 15:1 either
61+ (gate 15:11
62+ (face 15:14 b (flag 15:16))
63+ (branch 15:18
64+ (wing 15:21 b)
65+ (arm 16:3 (lit 16:3 %.y) (lit 16:7 ~s1))
66+ (arm 17:3 (lit 17:3 %.n) (lit 17:7 2)))))
67+ (value 18:1 every
68+ (cast 18:10
69+ (apply 18:13 list
70+ (apply 18:19 sub (ref 18:24 msg)))
71+ (list 18:30
72+ (tuple 18:32 (lit 18:33 %every) (lit 18:40 1) (ctor 18:42 %tick)))))
73+ (value 19:1 every-ok
74+ (cast 19:13
75+ (apply 19:16 list
76+ (apply 19:22 sub (ref 19:27 msg)))
77+ (list 19:33
78+ (tuple 19:35 (lit 19:36 %every) (lit 19:43 ~s1) (ctor 19:47 %tick)))))
79+ (value 20:1 timer
80+ (cast 20:10
81+ (apply 20:13 cmd (ref 20:18 msg))
82+ (tuple 20:23
83+ (lit 20:24 %wait)
84+ (lit 20:30 30)
85+ (tuple 20:33 (lit 20:34 %done) (lit 20:40 1)))))
86+ (value 21:1 timer-pair
87+ (cast 21:15
88+ (apply 21:18 cmd (ref 21:23 msg))
89+ (pair 21:28 wait
90+ (tuple 21:33
91+ (lit 21:34 30)
92+ (tuple 21:37 (lit 21:38 %done) (lit 21:44 1))))))
93+ (value 22:1 note
94+ (group 22:9
95+ (call 22:10 (wing 22:10 text) (lit 22:15 5))))
96+ (value 23:1 note-ok
97+ (group 23:12
98+ (call 23:13 (wing 23:13 text) (str 23:18 "5"))))
99+ (value 24:1 shown
100+ (cast 24:10
101+ (apply 24:13 element (void 24:22))
102+ (group 24:26
103+ (call 24:27 (wing 24:27 text) (lit 24:32 5))))))
tests/golden/inline-decimal-sites/types.txtnew file+69
@@ -0,0 +1,69 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ pause: $-(@dr @dr)
4+++ arg: `30` is a @ud, not a @dr; write ~s30
5+/tests/golden/inline-decimal-sites/source.jibb:5:15: decimal
6+++ arg (pause 30)
7+ ^
8+++ later: `1` is a @ud, not a @dr; write ~s1
9+/tests/golden/inline-decimal-sites/source.jibb:6:26: decimal
10+++ later |= d=@dr (add d 1)
11+ ^
12+++ sooner: `1` is a @ud, not a @dr; write ~s1
13+/tests/golden/inline-decimal-sites/source.jibb:7:25: decimal
14+++ sooner |= d=@dr (add 1 d)
15+ ^
16+++ zero: `0` is a @ud, not a @dr; write ~s0
17+/tests/golden/inline-decimal-sites/source.jibb:8:24: decimal
18+++ zero |= d=@dr (eq d 0)
19+ ^
20+++ record: `30` is a @ud, not a @dr; write ~s30
21+/tests/golden/inline-decimal-sites/source.jibb:9:35: decimal
22+++ record ^- [gap=@dr n=@ud] [gap=30 n=1]
23+ ^
24+++ change: `30` is a @ud, not a @dr; write ~s30
25+/tests/golden/inline-decimal-sites/source.jibb:10:38: decimal
26+++ change |= m=[gap=@dr n=@ud] m(gap=30)
27+ ^
28+++ items: `2` is a @ud, not a @dr; write ~s2
29+/tests/golden/inline-decimal-sites/source.jibb:11:30: decimal
30+++ items ^- (list @dr) ~[~s1 2]
31+ ^
32+++ open: `2` is a @ud, not a @dr; write ~s2
33+/tests/golden/inline-decimal-sites/source.jibb:12:15: decimal
34+++ open ~[~s1 2]
35+ ^
36+++ open-first: `2` is a @ud, not a @dr; write ~s2
37+/tests/golden/inline-decimal-sites/source.jibb:13:17: decimal
38+++ open-first ~[2 ~s1]
39+ ^
40+++ payload: `30` is a @ud, not a @dr; write ~s30
41+/tests/golden/inline-decimal-sites/source.jibb:14:27: decimal
42+++ payload ^- (unit @dr) `30
43+ ^
44+++ either: `2` is a @ud, not a @dr; write ~s2
45+/tests/golden/inline-decimal-sites/source.jibb:17:7: decimal
46+ %.n 2
47+ ^
48+++ every: `1` is a @ud, not a @dr; write ~s1
49+/tests/golden/inline-decimal-sites/source.jibb:18:40: decimal
50+++ every ^- (list (sub msg)) ~[[%every 1 |=%tick]]
51+ ^
52+++ every-ok: (list (sub msg))
53+++ timer: `30` is a @ud, not a @dr; write ~s30
54+/tests/golden/inline-decimal-sites/source.jibb:20:30: decimal
55+++ timer ^- (cmd msg) [%wait 30 [%done 1]]
56+ ^
57+++ timer-pair: `30` is a @ud, not a @dr; write ~s30
58+/tests/golden/inline-decimal-sites/source.jibb:21:34: decimal
59+++ timer-pair ^- (cmd msg) wait+[30 [%done 1]]
60+ ^
61+++ note: `5` is a @ud, not a @t; write "5"
62+/tests/golden/inline-decimal-sites/source.jibb:22:15: decimal
63+++ note (text 5)
64+ ^
65+++ note-ok: (element M)
66+++ shown: `5` is a @ud, not a @t; write "5"
67+/tests/golden/inline-decimal-sites/source.jibb:24:32: decimal
68+++ shown ^- (element !!) (text 5)
69+ ^
tests/golden/inline-decimal/about.txt+1−1
@@ -1,3 +1,3 @@
1−source: Grammar tab, Literals table, the Decimal row: `1.000`, "`@ud`, or any aura by context; groups of three, as in Hoon"
1+source: Grammar tab, Literals table, the Decimal row: `1.000`, "`@ud`, which also fits `@u`, `@` and `*`; groups of three, as in Hoon"
22tests: the decimal literal 1.000
33expect: parses
tests/golden/inline-pattern-nested/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Patterns: "Patterns take terms, numbers, strings without `{…}`, ships, loobeans and `~`, and cells of patterns, which nest; not `~[…]` lists or `a+b` pairs." and the rows `[[~ a] [~ b]]`, a pair of units that both hold a value, and `[x ~]`, a list of one item
2+tests: cell patterns nested inside cell patterns, and a positional cell whose last pattern takes the rest, as `[* ~ b]`
3+expect: parses: `[[~ a] [~ b]]` is a cell of two cell patterns, `[* ~ b]` is `[* [~ b]]`, and `[x ~]` is a cell of a name and null
tests/golden/inline-pattern-nested/source.jibbnew file+9
@@ -0,0 +1,9 @@
1+++ both |= args=[(unit @ud) (unit @ud)]
2+ ?- args
3+ [[~ a] [~ b]] (add a b)
4+ [* ~ b] b
5+ * 0
6+++ only |= xs=(list @ud)
7+ ?- xs
8+ [x ~] x
9+ * 0
tests/golden/inline-pattern-nested/tokens.txtnew file+71
@@ -0,0 +1,71 @@
1+1:1 glyph ++
2+1:4 name both
3+1:9 glyph |=
4+1:12 name args
5+1:16 tight glyph =
6+1:17 tight glyph [
7+1:18 tight glyph (
8+1:19 tight name unit
9+1:24 aura @ud
10+1:27 tight glyph )
11+1:29 glyph (
12+1:30 tight name unit
13+1:35 aura @ud
14+1:38 tight glyph )
15+1:39 tight glyph ]
16+2:3 INDENT
17+2:3 glyph ?-
18+2:6 name args
19+3:5 INDENT
20+3:5 glyph [
21+3:6 tight glyph [
22+3:7 tight lit ~
23+3:9 name a
24+3:10 tight glyph ]
25+3:12 glyph [
26+3:13 tight lit ~
27+3:15 name b
28+3:16 tight glyph ]
29+3:17 tight glyph ]
30+3:19 glyph (
31+3:20 tight name add
32+3:24 name a
33+3:26 name b
34+3:27 tight glyph )
35+4:5 NEWLINE
36+4:5 glyph [
37+4:6 tight glyph *
38+4:8 lit ~
39+4:10 name b
40+4:11 tight glyph ]
41+4:13 name b
42+5:5 NEWLINE
43+5:5 glyph *
44+5:7 lit 0
45+6:1 DEDENT
46+6:1 DEDENT
47+6:1 NEWLINE
48+6:1 glyph ++
49+6:4 name only
50+6:9 glyph |=
51+6:12 name xs
52+6:14 tight glyph =
53+6:15 tight glyph (
54+6:16 tight name list
55+6:21 aura @ud
56+6:24 tight glyph )
57+7:3 INDENT
58+7:3 glyph ?-
59+7:6 name xs
60+8:5 INDENT
61+8:5 glyph [
62+8:6 tight name x
63+8:8 lit ~
64+8:9 tight glyph ]
65+8:11 name x
66+9:5 NEWLINE
67+9:5 glyph *
68+9:7 lit 0
69+9:8 DEDENT
70+9:8 DEDENT
71+9:8 NEWLINE
tests/golden/inline-pattern-nested/tree.txtnew file+31
@@ -0,0 +1,31 @@
1+(module
2+ (value 1:1 both
3+ (gate 1:9
4+ (face 1:12 args
5+ (cell 1:17
6+ (apply 1:18 unit (aura 1:24 @ud))
7+ (apply 1:29 unit (aura 1:35 @ud))))
8+ (body 2:3
9+ (branch 2:3
10+ (wing 2:6 args)
11+ (arm 3:5
12+ (cell 3:5
13+ (cell 3:6 (lit 3:7 ~) (bind 3:9 a))
14+ (cell 3:12 (lit 3:13 ~) (bind 3:15 b)))
15+ (group 3:19
16+ (call 3:20 (wing 3:20 add) (wing 3:24 a) (wing 3:26 b))))
17+ (arm 4:5
18+ (cell 4:5 (any 4:6) (lit 4:8 ~) (bind 4:10 b))
19+ (wing 4:13 b))
20+ (arm 5:5 (any 5:5) (lit 5:7 0))))))
21+ (value 6:1 only
22+ (gate 6:9
23+ (face 6:12 xs
24+ (apply 6:15 list (aura 6:21 @ud)))
25+ (body 7:3
26+ (branch 7:3
27+ (wing 7:6 xs)
28+ (arm 8:5
29+ (cell 8:5 (bind 8:6 x) (lit 8:8 ~))
30+ (wing 8:11 x))
31+ (arm 9:5 (any 9:5) (lit 9:7 0)))))))
tests/golden/inline-pattern-tag-name-any-arm/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Patterns: "A name is an error where the subject's type at its position is a union, or a one-case mold, with a case whose constant there is the term the name spells"; "An arm that earlier arms cover ... is an error"
2+tests: the rule reads the subject's type, not the cases left: `stop` as the first arm is reported, not the arms it covers; `fail` after `%fail` is still an error; a grouped subject and a call as the subject
3+expect: parses
4+expect-types: a partial inference report: `first` is an error at `stop`, 13:5; `covered` at `fail`, 21:5; `grouped` at `late`, 25:5, with the subject `(r)` at 23:6; `pick` infers; `called` at `late`, 30:5, with the subject `(pick r)` at 28:6
tests/golden/inline-pattern-tag-name-any-arm/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/inline-pattern-tag-name-any-arm/source.jibbnew file+30
@@ -0,0 +1,30 @@
1++$ step
2+ [%move %left n=@ud]
3+ [%move %right n=@ud]
4+ [text=@t %draft]
5+ [text=@t %sent at=@da]
6+ %stop
7++$ reason
8+ %fail
9+ %late
10+
11+++ first |= s=step
12+ ?- s
13+ stop "stop"
14+ [%move %left n] "left {n}"
15+ [%move %right n] "right {n}"
16+ [t %draft] t
17+ [t %sent sent-at] t
18+++ covered |= r=reason
19+ ?- r
20+ %fail "f"
21+ fail "l"
22+++ grouped |= r=reason
23+ ?- (r)
24+ %fail "f"
25+ late "l"
26+++ pick |= r=reason r
27+++ called |= r=reason
28+ ?- (pick r)
29+ %fail "f"
30+ late "l"
tests/golden/inline-pattern-tag-name-any-arm/tokens.txtnew file+160
@@ -0,0 +1,160 @@
1+1:1 glyph +$
2+1:4 name step
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %move
6+2:10 lit %left
7+2:16 name n
8+2:17 tight glyph =
9+2:18 tight aura @ud
10+2:21 tight glyph ]
11+3:3 NEWLINE
12+3:3 glyph [
13+3:4 tight lit %move
14+3:10 lit %right
15+3:17 name n
16+3:18 tight glyph =
17+3:19 tight aura @ud
18+3:22 tight glyph ]
19+4:3 NEWLINE
20+4:3 glyph [
21+4:4 tight name text
22+4:8 tight glyph =
23+4:9 tight aura @t
24+4:12 lit %draft
25+4:18 tight glyph ]
26+5:3 NEWLINE
27+5:3 glyph [
28+5:4 tight name text
29+5:8 tight glyph =
30+5:9 tight aura @t
31+5:12 lit %sent
32+5:18 name at
33+5:20 tight glyph =
34+5:21 tight aura @da
35+5:24 tight glyph ]
36+6:3 NEWLINE
37+6:3 lit %stop
38+7:1 DEDENT
39+7:1 NEWLINE
40+7:1 glyph +$
41+7:4 name reason
42+8:3 INDENT
43+8:3 lit %fail
44+9:3 NEWLINE
45+9:3 lit %late
46+11:1 DEDENT
47+11:1 NEWLINE
48+11:1 glyph ++
49+11:4 name first
50+11:10 glyph |=
51+11:13 name s
52+11:14 tight glyph =
53+11:15 tight name step
54+12:3 INDENT
55+12:3 glyph ?-
56+12:6 name s
57+13:5 INDENT
58+13:5 name stop
59+13:23 str "stop"
60+14:5 NEWLINE
61+14:5 glyph [
62+14:6 tight lit %move
63+14:12 lit %left
64+14:18 name n
65+14:19 tight glyph ]
66+14:23 str-head "left "
67+14:30 tight name n
68+14:31 tight str-tail ""
69+15:5 NEWLINE
70+15:5 glyph [
71+15:6 tight lit %move
72+15:12 lit %right
73+15:19 name n
74+15:20 tight glyph ]
75+15:23 str-head "right "
76+15:31 tight name n
77+15:32 tight str-tail ""
78+16:5 NEWLINE
79+16:5 glyph [
80+16:6 tight name t
81+16:8 lit %draft
82+16:14 tight glyph ]
83+16:23 name t
84+17:5 NEWLINE
85+17:5 glyph [
86+17:6 tight name t
87+17:8 lit %sent
88+17:14 name sent-at
89+17:21 tight glyph ]
90+17:23 name t
91+18:1 DEDENT
92+18:1 DEDENT
93+18:1 NEWLINE
94+18:1 glyph ++
95+18:4 name covered
96+18:12 glyph |=
97+18:15 name r
98+18:16 tight glyph =
99+18:17 tight name reason
100+19:3 INDENT
101+19:3 glyph ?-
102+19:6 name r
103+20:5 INDENT
104+20:5 lit %fail
105+20:12 str "f"
106+21:5 NEWLINE
107+21:5 name fail
108+21:12 str "l"
109+22:1 DEDENT
110+22:1 DEDENT
111+22:1 NEWLINE
112+22:1 glyph ++
113+22:4 name grouped
114+22:12 glyph |=
115+22:15 name r
116+22:16 tight glyph =
117+22:17 tight name reason
118+23:3 INDENT
119+23:3 glyph ?-
120+23:6 glyph (
121+23:7 tight name r
122+23:8 tight glyph )
123+24:5 INDENT
124+24:5 lit %fail
125+24:12 str "f"
126+25:5 NEWLINE
127+25:5 name late
128+25:12 str "l"
129+26:1 DEDENT
130+26:1 DEDENT
131+26:1 NEWLINE
132+26:1 glyph ++
133+26:4 name pick
134+26:9 glyph |=
135+26:12 name r
136+26:13 tight glyph =
137+26:14 tight name reason
138+26:21 name r
139+27:1 NEWLINE
140+27:1 glyph ++
141+27:4 name called
142+27:11 glyph |=
143+27:14 name r
144+27:15 tight glyph =
145+27:16 tight name reason
146+28:3 INDENT
147+28:3 glyph ?-
148+28:6 glyph (
149+28:7 tight name pick
150+28:12 name r
151+28:13 tight glyph )
152+29:5 INDENT
153+29:5 lit %fail
154+29:12 str "f"
155+30:5 NEWLINE
156+30:5 name late
157+30:12 str "l"
158+30:15 DEDENT
159+30:15 DEDENT
160+30:15 NEWLINE
tests/golden/inline-pattern-tag-name-any-arm/tree.txtnew file+69
@@ -0,0 +1,69 @@
1+(module
2+ (mold 1:1 step
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %move)
6+ (const 2:10 %left)
7+ (face 2:16 n (aura 2:18 @ud)))
8+ (cell 3:3
9+ (const 3:4 %move)
10+ (const 3:10 %right)
11+ (face 3:17 n (aura 3:19 @ud)))
12+ (cell 4:3
13+ (face 4:4 text (aura 4:9 @t))
14+ (const 4:12 %draft))
15+ (cell 5:3
16+ (face 5:4 text (aura 5:9 @t))
17+ (const 5:12 %sent)
18+ (face 5:18 at (aura 5:21 @da)))
19+ (const 6:3 %stop)))
20+ (mold 7:1 reason
21+ (union 8:3 (const 8:3 %fail) (const 9:3 %late)))
22+ (value 11:1 first
23+ (gate 11:10
24+ (face 11:13 s (ref 11:15 step))
25+ (body 12:3
26+ (branch 12:3
27+ (wing 12:6 s)
28+ (arm 13:5 (bind 13:5 stop) (str 13:23 "stop"))
29+ (arm 14:5
30+ (cell 14:5 (lit 14:6 %move) (lit 14:12 %left) (bind 14:18 n))
31+ (str 14:23 "left " (wing 14:30 n)))
32+ (arm 15:5
33+ (cell 15:5 (lit 15:6 %move) (lit 15:12 %right) (bind 15:19 n))
34+ (str 15:23 "right " (wing 15:31 n)))
35+ (arm 16:5
36+ (cell 16:5 (bind 16:6 t) (lit 16:8 %draft))
37+ (wing 16:23 t))
38+ (arm 17:5
39+ (cell 17:5 (bind 17:6 t) (lit 17:8 %sent) (bind 17:14 sent-at))
40+ (wing 17:23 t))))))
41+ (value 18:1 covered
42+ (gate 18:12
43+ (face 18:15 r (ref 18:17 reason))
44+ (body 19:3
45+ (branch 19:3
46+ (wing 19:6 r)
47+ (arm 20:5 (lit 20:5 %fail) (str 20:12 "f"))
48+ (arm 21:5 (bind 21:5 fail) (str 21:12 "l"))))))
49+ (value 22:1 grouped
50+ (gate 22:12
51+ (face 22:15 r (ref 22:17 reason))
52+ (body 23:3
53+ (branch 23:3
54+ (group 23:6 (wing 23:7 r))
55+ (arm 24:5 (lit 24:5 %fail) (str 24:12 "f"))
56+ (arm 25:5 (bind 25:5 late) (str 25:12 "l"))))))
57+ (value 26:1 pick
58+ (gate 26:9
59+ (face 26:12 r (ref 26:14 reason))
60+ (wing 26:21 r)))
61+ (value 27:1 called
62+ (gate 27:11
63+ (face 27:14 r (ref 27:16 reason))
64+ (body 28:3
65+ (branch 28:3
66+ (group 28:6
67+ (call 28:7 (wing 28:7 pick) (wing 28:12 r)))
68+ (arm 29:5 (lit 29:5 %fail) (str 29:12 "f"))
69+ (arm 30:5 (bind 30:5 late) (str 30:12 "l")))))))
tests/golden/inline-pattern-tag-name-any-arm/types.txtnew file+32
@@ -0,0 +1,32 @@
1+partial inference; module not checked
2++$ step: cases proven disjoint; mold not checked
3++$ reason: cases proven disjoint; mold not checked
4+++ first: `stop` binds a name, but the subject's type has `%stop` here; write %stop, or * for a catch-all
5+/tests/golden/inline-pattern-tag-name-any-arm/source.jibb:12:6: subject
6+ ?- s
7+ ^
8+/tests/golden/inline-pattern-tag-name-any-arm/source.jibb:13:5: pattern name
9+ stop "stop"
10+ ^
11+++ covered: `fail` binds a name, but the subject's type has `%fail` here; write %fail, or * for a catch-all
12+/tests/golden/inline-pattern-tag-name-any-arm/source.jibb:19:6: subject
13+ ?- r
14+ ^
15+/tests/golden/inline-pattern-tag-name-any-arm/source.jibb:21:5: pattern name
16+ fail "l"
17+ ^
18+++ grouped: `late` binds a name, but the subject's type has `%late` here; write %late, or * for a catch-all
19+/tests/golden/inline-pattern-tag-name-any-arm/source.jibb:23:6: subject
20+ ?- (r)
21+ ^
22+/tests/golden/inline-pattern-tag-name-any-arm/source.jibb:25:5: pattern name
23+ late "l"
24+ ^
25+++ pick: $-(reason reason)
26+++ called: `late` binds a name, but the subject's type has `%late` here; write %late, or * for a catch-all
27+/tests/golden/inline-pattern-tag-name-any-arm/source.jibb:28:6: subject
28+ ?- (pick r)
29+ ^
30+/tests/golden/inline-pattern-tag-name-any-arm/source.jibb:30:5: pattern name
31+ late "l"
32+ ^
tests/golden/inline-pattern-tag-name-generic/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Patterns: "A name is an error where the subject's type at its position is a union, or a one-case mold, with a case whose constant there is the term the name spells"; "Positions typed by an aura, `*`, a type variable or a container's element are unaffected"
2+tests: a generic union's own cases count, as `%fail` and `%ok` of `(outcome A)`; a position its mold types by a type variable doesn't, even where the argument is a union with that tag: `[%ok fail]` on `(outcome reason)`, `[~ stop]` on `(unit step)`; nor does a list's element, `[stop rest]` on `(list step)`
3+expect: parses
4+expect-types: a partial inference report: `own-case` is an error at `fail`, 14:5, and `own-head` at `ok`, 17:6; `argument`, `maybe` and `items` infer
tests/golden/inline-pattern-tag-name-generic/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use the source-validated prelude unit and list.
tests/golden/inline-pattern-tag-name-generic/source.jibbnew file+30
@@ -0,0 +1,30 @@
1++$ step
2+ [%go n=@ud]
3+ %stop
4++$ outcome |$ [A]
5+ [%ok value=A]
6+ %fail
7++$ reason
8+ %fail
9+ %late
10+
11+++ own-case |= o=(outcome @t)
12+ ?- o
13+ [%ok v] v
14+ fail "failed"
15+++ own-head |= o=(outcome reason)
16+ ?- o
17+ [ok r] "x"
18+ %fail "failed"
19+++ argument |= o=(outcome reason)
20+ ?- o
21+ [%ok fail] "x"
22+ %fail "failed"
23+++ maybe |= u=(unit step)
24+ ?- u
25+ ~ "none"
26+ [~ stop] "s"
27+++ items |= xs=(list step)
28+ ?- xs
29+ ~ "none"
30+ [stop rest] "s"
tests/golden/inline-pattern-tag-name-generic/tokens.txtnew file+158
@@ -0,0 +1,158 @@
1+1:1 glyph +$
2+1:4 name step
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %go
6+2:8 name n
7+2:9 tight glyph =
8+2:10 tight aura @ud
9+2:13 tight glyph ]
10+3:3 NEWLINE
11+3:3 lit %stop
12+4:1 DEDENT
13+4:1 NEWLINE
14+4:1 glyph +$
15+4:4 name outcome
16+4:12 glyph |$
17+4:15 glyph [
18+4:16 tight tvar A
19+4:17 tight glyph ]
20+5:3 INDENT
21+5:3 glyph [
22+5:4 tight lit %ok
23+5:8 name value
24+5:13 tight glyph =
25+5:14 tight tvar A
26+5:15 tight glyph ]
27+6:3 NEWLINE
28+6:3 lit %fail
29+7:1 DEDENT
30+7:1 NEWLINE
31+7:1 glyph +$
32+7:4 name reason
33+8:3 INDENT
34+8:3 lit %fail
35+9:3 NEWLINE
36+9:3 lit %late
37+11:1 DEDENT
38+11:1 NEWLINE
39+11:1 glyph ++
40+11:4 name own-case
41+11:13 glyph |=
42+11:16 name o
43+11:17 tight glyph =
44+11:18 tight glyph (
45+11:19 tight name outcome
46+11:27 aura @t
47+11:29 tight glyph )
48+12:3 INDENT
49+12:3 glyph ?-
50+12:6 name o
51+13:5 INDENT
52+13:5 glyph [
53+13:6 tight lit %ok
54+13:10 name v
55+13:11 tight glyph ]
56+13:14 name v
57+14:5 NEWLINE
58+14:5 name fail
59+14:14 str "failed"
60+15:1 DEDENT
61+15:1 DEDENT
62+15:1 NEWLINE
63+15:1 glyph ++
64+15:4 name own-head
65+15:13 glyph |=
66+15:16 name o
67+15:17 tight glyph =
68+15:18 tight glyph (
69+15:19 tight name outcome
70+15:27 name reason
71+15:33 tight glyph )
72+16:3 INDENT
73+16:3 glyph ?-
74+16:6 name o
75+17:5 INDENT
76+17:5 glyph [
77+17:6 tight name ok
78+17:9 name r
79+17:10 tight glyph ]
80+17:13 str "x"
81+18:5 NEWLINE
82+18:5 lit %fail
83+18:13 str "failed"
84+19:1 DEDENT
85+19:1 DEDENT
86+19:1 NEWLINE
87+19:1 glyph ++
88+19:4 name argument
89+19:13 glyph |=
90+19:16 name o
91+19:17 tight glyph =
92+19:18 tight glyph (
93+19:19 tight name outcome
94+19:27 name reason
95+19:33 tight glyph )
96+20:3 INDENT
97+20:3 glyph ?-
98+20:6 name o
99+21:5 INDENT
100+21:5 glyph [
101+21:6 tight lit %ok
102+21:10 name fail
103+21:14 tight glyph ]
104+21:17 str "x"
105+22:5 NEWLINE
106+22:5 lit %fail
107+22:17 str "failed"
108+23:1 DEDENT
109+23:1 DEDENT
110+23:1 NEWLINE
111+23:1 glyph ++
112+23:4 name maybe
113+23:10 glyph |=
114+23:13 name u
115+23:14 tight glyph =
116+23:15 tight glyph (
117+23:16 tight name unit
118+23:21 name step
119+23:25 tight glyph )
120+24:3 INDENT
121+24:3 glyph ?-
122+24:6 name u
123+25:5 INDENT
124+25:5 lit ~
125+25:15 str "none"
126+26:5 NEWLINE
127+26:5 glyph [
128+26:6 tight lit ~
129+26:8 name stop
130+26:12 tight glyph ]
131+26:15 str "s"
132+27:1 DEDENT
133+27:1 DEDENT
134+27:1 NEWLINE
135+27:1 glyph ++
136+27:4 name items
137+27:10 glyph |=
138+27:13 name xs
139+27:15 tight glyph =
140+27:16 tight glyph (
141+27:17 tight name list
142+27:22 name step
143+27:26 tight glyph )
144+28:3 INDENT
145+28:3 glyph ?-
146+28:6 name xs
147+29:5 INDENT
148+29:5 lit ~
149+29:18 str "none"
150+30:5 NEWLINE
151+30:5 glyph [
152+30:6 tight name stop
153+30:11 name rest
154+30:15 tight glyph ]
155+30:18 str "s"
156+30:21 DEDENT
157+30:21 DEDENT
158+30:21 NEWLINE
tests/golden/inline-pattern-tag-name-generic/tree.txtnew file+71
@@ -0,0 +1,71 @@
1+(module
2+ (mold 1:1 step
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %go)
6+ (face 2:8 n (aura 2:10 @ud)))
7+ (const 3:3 %stop)))
8+ (mold 4:1 outcome
9+ (generic 4:12 A
10+ (union 5:3
11+ (cell 5:3
12+ (const 5:4 %ok)
13+ (face 5:8 value (tvar 5:14 A)))
14+ (const 6:3 %fail))))
15+ (mold 7:1 reason
16+ (union 8:3 (const 8:3 %fail) (const 9:3 %late)))
17+ (value 11:1 own-case
18+ (gate 11:13
19+ (face 11:16 o
20+ (apply 11:18 outcome (aura 11:27 @t)))
21+ (body 12:3
22+ (branch 12:3
23+ (wing 12:6 o)
24+ (arm 13:5
25+ (cell 13:5 (lit 13:6 %ok) (bind 13:10 v))
26+ (wing 13:14 v))
27+ (arm 14:5 (bind 14:5 fail) (str 14:14 "failed"))))))
28+ (value 15:1 own-head
29+ (gate 15:13
30+ (face 15:16 o
31+ (apply 15:18 outcome (ref 15:27 reason)))
32+ (body 16:3
33+ (branch 16:3
34+ (wing 16:6 o)
35+ (arm 17:5
36+ (cell 17:5 (bind 17:6 ok) (bind 17:9 r))
37+ (str 17:13 "x"))
38+ (arm 18:5 (lit 18:5 %fail) (str 18:13 "failed"))))))
39+ (value 19:1 argument
40+ (gate 19:13
41+ (face 19:16 o
42+ (apply 19:18 outcome (ref 19:27 reason)))
43+ (body 20:3
44+ (branch 20:3
45+ (wing 20:6 o)
46+ (arm 21:5
47+ (cell 21:5 (lit 21:6 %ok) (bind 21:10 fail))
48+ (str 21:17 "x"))
49+ (arm 22:5 (lit 22:5 %fail) (str 22:17 "failed"))))))
50+ (value 23:1 maybe
51+ (gate 23:10
52+ (face 23:13 u
53+ (apply 23:15 unit (ref 23:21 step)))
54+ (body 24:3
55+ (branch 24:3
56+ (wing 24:6 u)
57+ (arm 25:5 (lit 25:5 ~) (str 25:15 "none"))
58+ (arm 26:5
59+ (cell 26:5 (lit 26:6 ~) (bind 26:8 stop))
60+ (str 26:15 "s"))))))
61+ (value 27:1 items
62+ (gate 27:10
63+ (face 27:13 xs
64+ (apply 27:16 list (ref 27:22 step)))
65+ (body 28:3
66+ (branch 28:3
67+ (wing 28:6 xs)
68+ (arm 29:5 (lit 29:5 ~) (str 29:18 "none"))
69+ (arm 30:5
70+ (cell 30:5 (bind 30:6 stop) (bind 30:11 rest))
71+ (str 30:18 "s")))))))
tests/golden/inline-pattern-tag-name-generic/types.txtnew file+21
@@ -0,0 +1,21 @@
1+partial inference; module not checked
2++$ step: cases proven disjoint; mold not checked
3++$ outcome: cases proven disjoint; mold not checked
4++$ reason: cases proven disjoint; mold not checked
5+++ own-case: `fail` binds a name, but the subject's type has `%fail` here; write %fail, or * for a catch-all
6+/tests/golden/inline-pattern-tag-name-generic/source.jibb:12:6: subject
7+ ?- o
8+ ^
9+/tests/golden/inline-pattern-tag-name-generic/source.jibb:14:5: pattern name
10+ fail "failed"
11+ ^
12+++ own-head: `ok` binds a name, but the subject's type has `%ok` here; write %ok, or * for a catch-all
13+/tests/golden/inline-pattern-tag-name-generic/source.jibb:16:6: subject
14+ ?- o
15+ ^
16+/tests/golden/inline-pattern-tag-name-generic/source.jibb:17:6: pattern name
17+ [ok r] "x"
18+ ^
19+++ argument: $-((outcome reason) @t)
20+++ maybe: $-((unit step) @t)
21+++ items: $-((list step) @t)
tests/golden/inline-pattern-tag-name-last/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Patterns: "A name is an error where the subject's type at its position is a union, or a one-case mold, with a case whose constant there is the term the name spells", so `stop` written for `%stop` below is an error, not a catch-all; the Patterns section's `step` block with its last arm's `%` dropped
2+tests: a bare name in a `?-`'s last arm that spells a case of the subject's union, which would otherwise catch every case left
3+expect: parses
4+expect-types: a partial inference report: `describe` is an error at `stop`, 14:5, since `step` has the case `%stop`, with the subject at 9:6
tests/golden/inline-pattern-tag-name-last/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/inline-pattern-tag-name-last/source.jibbnew file+14
@@ -0,0 +1,14 @@
1++$ step
2+ [%move %left n=@ud]
3+ [%move %right n=@ud]
4+ [text=@t %draft]
5+ [text=@t %sent at=@da]
6+ %stop
7+
8+++ describe |= s=step
9+ ?- s
10+ [%move %left n] "left {n}"
11+ [%move %right n] "right {n}"
12+ [t %draft] t
13+ [t %sent sent-at] t
14+ stop "stop"
tests/golden/inline-pattern-tag-name-last/tokens.txtnew file+85
@@ -0,0 +1,85 @@
1+1:1 glyph +$
2+1:4 name step
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %move
6+2:10 lit %left
7+2:16 name n
8+2:17 tight glyph =
9+2:18 tight aura @ud
10+2:21 tight glyph ]
11+3:3 NEWLINE
12+3:3 glyph [
13+3:4 tight lit %move
14+3:10 lit %right
15+3:17 name n
16+3:18 tight glyph =
17+3:19 tight aura @ud
18+3:22 tight glyph ]
19+4:3 NEWLINE
20+4:3 glyph [
21+4:4 tight name text
22+4:8 tight glyph =
23+4:9 tight aura @t
24+4:12 lit %draft
25+4:18 tight glyph ]
26+5:3 NEWLINE
27+5:3 glyph [
28+5:4 tight name text
29+5:8 tight glyph =
30+5:9 tight aura @t
31+5:12 lit %sent
32+5:18 name at
33+5:20 tight glyph =
34+5:21 tight aura @da
35+5:24 tight glyph ]
36+6:3 NEWLINE
37+6:3 lit %stop
38+8:1 DEDENT
39+8:1 NEWLINE
40+8:1 glyph ++
41+8:4 name describe
42+8:13 glyph |=
43+8:16 name s
44+8:17 tight glyph =
45+8:18 tight name step
46+9:3 INDENT
47+9:3 glyph ?-
48+9:6 name s
49+10:5 INDENT
50+10:5 glyph [
51+10:6 tight lit %move
52+10:12 lit %left
53+10:18 name n
54+10:19 tight glyph ]
55+10:23 str-head "left "
56+10:30 tight name n
57+10:31 tight str-tail ""
58+11:5 NEWLINE
59+11:5 glyph [
60+11:6 tight lit %move
61+11:12 lit %right
62+11:19 name n
63+11:20 tight glyph ]
64+11:23 str-head "right "
65+11:31 tight name n
66+11:32 tight str-tail ""
67+12:5 NEWLINE
68+12:5 glyph [
69+12:6 tight name t
70+12:8 lit %draft
71+12:14 tight glyph ]
72+12:23 name t
73+13:5 NEWLINE
74+13:5 glyph [
75+13:6 tight name t
76+13:8 lit %sent
77+13:14 name sent-at
78+13:21 tight glyph ]
79+13:23 name t
80+14:5 NEWLINE
81+14:5 name stop
82+14:23 str "stop"
83+14:29 DEDENT
84+14:29 DEDENT
85+14:29 NEWLINE
tests/golden/inline-pattern-tag-name-last/tree.txtnew file+38
@@ -0,0 +1,38 @@
1+(module
2+ (mold 1:1 step
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %move)
6+ (const 2:10 %left)
7+ (face 2:16 n (aura 2:18 @ud)))
8+ (cell 3:3
9+ (const 3:4 %move)
10+ (const 3:10 %right)
11+ (face 3:17 n (aura 3:19 @ud)))
12+ (cell 4:3
13+ (face 4:4 text (aura 4:9 @t))
14+ (const 4:12 %draft))
15+ (cell 5:3
16+ (face 5:4 text (aura 5:9 @t))
17+ (const 5:12 %sent)
18+ (face 5:18 at (aura 5:21 @da)))
19+ (const 6:3 %stop)))
20+ (value 8:1 describe
21+ (gate 8:13
22+ (face 8:16 s (ref 8:18 step))
23+ (body 9:3
24+ (branch 9:3
25+ (wing 9:6 s)
26+ (arm 10:5
27+ (cell 10:5 (lit 10:6 %move) (lit 10:12 %left) (bind 10:18 n))
28+ (str 10:23 "left " (wing 10:30 n)))
29+ (arm 11:5
30+ (cell 11:5 (lit 11:6 %move) (lit 11:12 %right) (bind 11:19 n))
31+ (str 11:23 "right " (wing 11:31 n)))
32+ (arm 12:5
33+ (cell 12:5 (bind 12:6 t) (lit 12:8 %draft))
34+ (wing 12:23 t))
35+ (arm 13:5
36+ (cell 13:5 (bind 13:6 t) (lit 13:8 %sent) (bind 13:14 sent-at))
37+ (wing 13:23 t))
38+ (arm 14:5 (bind 14:5 stop) (str 14:23 "stop")))))))
tests/golden/inline-pattern-tag-name-last/types.txtnew file+9
@@ -0,0 +1,9 @@
1+partial inference; module not checked
2++$ step: cases proven disjoint; mold not checked
3+++ describe: `stop` binds a name, but the subject's type has `%stop` here; write %stop, or * for a catch-all
4+/tests/golden/inline-pattern-tag-name-last/source.jibb:9:6: subject
5+ ?- s
6+ ^
7+/tests/golden/inline-pattern-tag-name-last/source.jibb:14:5: pattern name
8+ stop "stop"
9+ ^
tests/golden/inline-pattern-tag-name-nested/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Patterns: "A name is an error where the subject's type at its position is a union, or a one-case mold, with a case whose constant there is the term the name spells"; the review's `[typed t]` for `[%typed t]`
2+tests: names inside cell patterns: at a case's head, where the union's cases have the tags `%typed` and `%submit`; at a position typed by the union mold `dir`; at a case's tail, where it is `%draft`
3+expect: parses
4+expect-types: a partial inference report: `typed` is an error at `typed`, 15:6; `move` at `left`, 20:12; `draft` at `draft`, 26:8; each with its subject
tests/golden/inline-pattern-tag-name-nested/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/inline-pattern-tag-name-nested/source.jibbnew file+27
@@ -0,0 +1,27 @@
1++$ msg
2+ [%typed text=@t]
3+ [%submit ~]
4+ %clear
5++$ dir
6+ %left
7+ %right
8++$ step
9+ [%move d=dir n=@ud]
10+ [text=@t %draft]
11+ %stop
12+
13+++ typed |= m=msg
14+ ?- m
15+ [typed t] t
16+ [%submit ~] "s"
17+ %clear "c"
18+++ move |= s=step
19+ ?- s
20+ [%move left n] "x"
21+ [t %draft] t
22+ %stop "s"
23+++ draft |= s=step
24+ ?- s
25+ [%move d n] "x"
26+ [t draft] t
27+ %stop "s"
tests/golden/inline-pattern-tag-name-nested/tokens.txtnew file+132
@@ -0,0 +1,132 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %typed
6+2:11 name text
7+2:15 tight glyph =
8+2:16 tight aura @t
9+2:18 tight glyph ]
10+3:3 NEWLINE
11+3:3 glyph [
12+3:4 tight lit %submit
13+3:12 lit ~
14+3:13 tight glyph ]
15+4:3 NEWLINE
16+4:3 lit %clear
17+5:1 DEDENT
18+5:1 NEWLINE
19+5:1 glyph +$
20+5:4 name dir
21+6:3 INDENT
22+6:3 lit %left
23+7:3 NEWLINE
24+7:3 lit %right
25+8:1 DEDENT
26+8:1 NEWLINE
27+8:1 glyph +$
28+8:4 name step
29+9:3 INDENT
30+9:3 glyph [
31+9:4 tight lit %move
32+9:10 name d
33+9:11 tight glyph =
34+9:12 tight name dir
35+9:16 name n
36+9:17 tight glyph =
37+9:18 tight aura @ud
38+9:21 tight glyph ]
39+10:3 NEWLINE
40+10:3 glyph [
41+10:4 tight name text
42+10:8 tight glyph =
43+10:9 tight aura @t
44+10:12 lit %draft
45+10:18 tight glyph ]
46+11:3 NEWLINE
47+11:3 lit %stop
48+13:1 DEDENT
49+13:1 NEWLINE
50+13:1 glyph ++
51+13:4 name typed
52+13:10 glyph |=
53+13:13 name m
54+13:14 tight glyph =
55+13:15 tight name msg
56+14:3 INDENT
57+14:3 glyph ?-
58+14:6 name m
59+15:5 INDENT
60+15:5 glyph [
61+15:6 tight name typed
62+15:12 name t
63+15:13 tight glyph ]
64+15:17 name t
65+16:5 NEWLINE
66+16:5 glyph [
67+16:6 tight lit %submit
68+16:14 lit ~
69+16:15 tight glyph ]
70+16:17 str "s"
71+17:5 NEWLINE
72+17:5 lit %clear
73+17:17 str "c"
74+18:1 DEDENT
75+18:1 DEDENT
76+18:1 NEWLINE
77+18:1 glyph ++
78+18:4 name move
79+18:9 glyph |=
80+18:12 name s
81+18:13 tight glyph =
82+18:14 tight name step
83+19:3 INDENT
84+19:3 glyph ?-
85+19:6 name s
86+20:5 INDENT
87+20:5 glyph [
88+20:6 tight lit %move
89+20:12 name left
90+20:17 name n
91+20:18 tight glyph ]
92+20:20 str "x"
93+21:5 NEWLINE
94+21:5 glyph [
95+21:6 tight name t
96+21:8 lit %draft
97+21:14 tight glyph ]
98+21:20 name t
99+22:5 NEWLINE
100+22:5 lit %stop
101+22:20 str "s"
102+23:1 DEDENT
103+23:1 DEDENT
104+23:1 NEWLINE
105+23:1 glyph ++
106+23:4 name draft
107+23:10 glyph |=
108+23:13 name s
109+23:14 tight glyph =
110+23:15 tight name step
111+24:3 INDENT
112+24:3 glyph ?-
113+24:6 name s
114+25:5 INDENT
115+25:5 glyph [
116+25:6 tight lit %move
117+25:12 name d
118+25:14 name n
119+25:15 tight glyph ]
120+25:20 str "x"
121+26:5 NEWLINE
122+26:5 glyph [
123+26:6 tight name t
124+26:8 name draft
125+26:13 tight glyph ]
126+26:20 name t
127+27:5 NEWLINE
128+27:5 lit %stop
129+27:20 str "s"
130+27:23 DEDENT
131+27:23 DEDENT
132+27:23 NEWLINE
tests/golden/inline-pattern-tag-name-nested/tree.txtnew file+59
@@ -0,0 +1,59 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %typed)
6+ (face 2:11 text (aura 2:16 @t)))
7+ (cell 3:3 (const 3:4 %submit) (const 3:12 ~))
8+ (const 4:3 %clear)))
9+ (mold 5:1 dir
10+ (union 6:3 (const 6:3 %left) (const 7:3 %right)))
11+ (mold 8:1 step
12+ (union 9:3
13+ (cell 9:3
14+ (const 9:4 %move)
15+ (face 9:10 d (ref 9:12 dir))
16+ (face 9:16 n (aura 9:18 @ud)))
17+ (cell 10:3
18+ (face 10:4 text (aura 10:9 @t))
19+ (const 10:12 %draft))
20+ (const 11:3 %stop)))
21+ (value 13:1 typed
22+ (gate 13:10
23+ (face 13:13 m (ref 13:15 msg))
24+ (body 14:3
25+ (branch 14:3
26+ (wing 14:6 m)
27+ (arm 15:5
28+ (cell 15:5 (bind 15:6 typed) (bind 15:12 t))
29+ (wing 15:17 t))
30+ (arm 16:5
31+ (cell 16:5 (lit 16:6 %submit) (lit 16:14 ~))
32+ (str 16:17 "s"))
33+ (arm 17:5 (lit 17:5 %clear) (str 17:17 "c"))))))
34+ (value 18:1 move
35+ (gate 18:9
36+ (face 18:12 s (ref 18:14 step))
37+ (body 19:3
38+ (branch 19:3
39+ (wing 19:6 s)
40+ (arm 20:5
41+ (cell 20:5 (lit 20:6 %move) (bind 20:12 left) (bind 20:17 n))
42+ (str 20:20 "x"))
43+ (arm 21:5
44+ (cell 21:5 (bind 21:6 t) (lit 21:8 %draft))
45+ (wing 21:20 t))
46+ (arm 22:5 (lit 22:5 %stop) (str 22:20 "s"))))))
47+ (value 23:1 draft
48+ (gate 23:10
49+ (face 23:13 s (ref 23:15 step))
50+ (body 24:3
51+ (branch 24:3
52+ (wing 24:6 s)
53+ (arm 25:5
54+ (cell 25:5 (lit 25:6 %move) (bind 25:12 d) (bind 25:14 n))
55+ (str 25:20 "x"))
56+ (arm 26:5
57+ (cell 26:5 (bind 26:6 t) (bind 26:8 draft))
58+ (wing 26:20 t))
59+ (arm 27:5 (lit 27:5 %stop) (str 27:20 "s")))))))
tests/golden/inline-pattern-tag-name-nested/types.txtnew file+25
@@ -0,0 +1,25 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3++$ dir: cases proven disjoint; mold not checked
4++$ step: cases proven disjoint; mold not checked
5+++ typed: `typed` binds a name, but the subject's type has `%typed` here; write %typed, or * for a catch-all
6+/tests/golden/inline-pattern-tag-name-nested/source.jibb:14:6: subject
7+ ?- m
8+ ^
9+/tests/golden/inline-pattern-tag-name-nested/source.jibb:15:6: pattern name
10+ [typed t] t
11+ ^
12+++ move: `left` binds a name, but the subject's type has `%left` here; write %left, or * for a catch-all
13+/tests/golden/inline-pattern-tag-name-nested/source.jibb:19:6: subject
14+ ?- s
15+ ^
16+/tests/golden/inline-pattern-tag-name-nested/source.jibb:20:12: pattern name
17+ [%move left n] "x"
18+ ^
19+++ draft: `draft` binds a name, but the subject's type has `%draft` here; write %draft, or * for a catch-all
20+/tests/golden/inline-pattern-tag-name-nested/source.jibb:24:6: subject
21+ ?- s
22+ ^
23+/tests/golden/inline-pattern-tag-name-nested/source.jibb:26:8: pattern name
24+ [t draft] t
25+ ^
tests/golden/inline-pattern-tag-name-ok/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Patterns: "A name is an error where the subject's type at its position is a union, or a one-case mold, with a case whose constant there is the term the name spells"; "Positions typed by an aura, `*`, a type variable or a container's element are unaffected, so `[t %draft] t` still binds `t`, and `x` is still a catch-all on a `@tas` subject"; Decisions, "Sample names": "Every bare name in a sample binds"
2+tests: names the rule leaves alone: `t` at `@t` in `[t %draft]`; `move` where the matching case has `@t`, though another case has `%move` there; `left` binding a case's tail `[%left n]`, a cell; `red` and `green` at `@ud` and `@t` positions, and `red` as a catch-all, spelling tags of a different union; a sample named `stop`, faced and bare; `stop` on `@tas` and `*` subjects
3+expect: parses
4+expect-types: a partial inference report: `describe`, `elsewhere`, `aura`, `other-union`, `sample` and `sample-bare` infer; `rest`, `atom` and `noun` give the partial checker's unsupported messages, not the tag-name error, since it doesn't yet check a pattern that splits a case, or a `?-` on an atom or a noun
tests/golden/inline-pattern-tag-name-ok/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/inline-pattern-tag-name-ok/source.jibbnew file+53
@@ -0,0 +1,53 @@
1++$ step
2+ [%move %left n=@ud]
3+ [%move %right n=@ud]
4+ [text=@t %draft]
5+ [text=@t %sent at=@da]
6+ %stop
7++$ colour
8+ %red
9+ %green
10++$ shape
11+ [%circle red=@ud]
12+ [%label text=@t]
13+ %blank
14+
15+++ describe |= s=step
16+ ?- s
17+ [%move %left n] "left {n}"
18+ [%move %right n] "right {n}"
19+ [t %draft] t
20+ [t %sent sent-at] t
21+ %stop "stop"
22+++ elsewhere |= s=step
23+ ?- s
24+ [%move %left n] "left {n}"
25+ [%move %right n] "right {n}"
26+ [move %draft] move
27+ [t %sent sent-at] t
28+ %stop "stop"
29+++ rest |= s=step
30+ ?- s
31+ [%move left] "move"
32+ [t %draft] t
33+ [t %sent sent-at] t
34+ %stop "stop"
35+++ aura |= s=shape
36+ ?- s
37+ [%circle red] "{red}"
38+ [%label green] green
39+ %blank "blank"
40+++ other-union |= s=shape
41+ ?- s
42+ [%circle r] "{r}"
43+ [%label t] t
44+ red "other"
45+++ sample |= stop=step "sample"
46+++ sample-bare ^- $-(step @t) |= stop "sample"
47+++ atom |= s=@tas
48+ ?- s
49+ %stop "stop"
50+ stop "other"
51+++ noun |= s=*
52+ ?- s
53+ stop "any"
tests/golden/inline-pattern-tag-name-ok/tokens.txtnew file+303
@@ -0,0 +1,303 @@
1+1:1 glyph +$
2+1:4 name step
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %move
6+2:10 lit %left
7+2:16 name n
8+2:17 tight glyph =
9+2:18 tight aura @ud
10+2:21 tight glyph ]
11+3:3 NEWLINE
12+3:3 glyph [
13+3:4 tight lit %move
14+3:10 lit %right
15+3:17 name n
16+3:18 tight glyph =
17+3:19 tight aura @ud
18+3:22 tight glyph ]
19+4:3 NEWLINE
20+4:3 glyph [
21+4:4 tight name text
22+4:8 tight glyph =
23+4:9 tight aura @t
24+4:12 lit %draft
25+4:18 tight glyph ]
26+5:3 NEWLINE
27+5:3 glyph [
28+5:4 tight name text
29+5:8 tight glyph =
30+5:9 tight aura @t
31+5:12 lit %sent
32+5:18 name at
33+5:20 tight glyph =
34+5:21 tight aura @da
35+5:24 tight glyph ]
36+6:3 NEWLINE
37+6:3 lit %stop
38+7:1 DEDENT
39+7:1 NEWLINE
40+7:1 glyph +$
41+7:4 name colour
42+8:3 INDENT
43+8:3 lit %red
44+9:3 NEWLINE
45+9:3 lit %green
46+10:1 DEDENT
47+10:1 NEWLINE
48+10:1 glyph +$
49+10:4 name shape
50+11:3 INDENT
51+11:3 glyph [
52+11:4 tight lit %circle
53+11:12 name red
54+11:15 tight glyph =
55+11:16 tight aura @ud
56+11:19 tight glyph ]
57+12:3 NEWLINE
58+12:3 glyph [
59+12:4 tight lit %label
60+12:11 name text
61+12:15 tight glyph =
62+12:16 tight aura @t
63+12:18 tight glyph ]
64+13:3 NEWLINE
65+13:3 lit %blank
66+15:1 DEDENT
67+15:1 NEWLINE
68+15:1 glyph ++
69+15:4 name describe
70+15:13 glyph |=
71+15:16 name s
72+15:17 tight glyph =
73+15:18 tight name step
74+16:3 INDENT
75+16:3 glyph ?-
76+16:6 name s
77+17:5 INDENT
78+17:5 glyph [
79+17:6 tight lit %move
80+17:12 lit %left
81+17:18 name n
82+17:19 tight glyph ]
83+17:23 str-head "left "
84+17:30 tight name n
85+17:31 tight str-tail ""
86+18:5 NEWLINE
87+18:5 glyph [
88+18:6 tight lit %move
89+18:12 lit %right
90+18:19 name n
91+18:20 tight glyph ]
92+18:23 str-head "right "
93+18:31 tight name n
94+18:32 tight str-tail ""
95+19:5 NEWLINE
96+19:5 glyph [
97+19:6 tight name t
98+19:8 lit %draft
99+19:14 tight glyph ]
100+19:23 name t
101+20:5 NEWLINE
102+20:5 glyph [
103+20:6 tight name t
104+20:8 lit %sent
105+20:14 name sent-at
106+20:21 tight glyph ]
107+20:23 name t
108+21:5 NEWLINE
109+21:5 lit %stop
110+21:23 str "stop"
111+22:1 DEDENT
112+22:1 DEDENT
113+22:1 NEWLINE
114+22:1 glyph ++
115+22:4 name elsewhere
116+22:14 glyph |=
117+22:17 name s
118+22:18 tight glyph =
119+22:19 tight name step
120+23:3 INDENT
121+23:3 glyph ?-
122+23:6 name s
123+24:5 INDENT
124+24:5 glyph [
125+24:6 tight lit %move
126+24:12 lit %left
127+24:18 name n
128+24:19 tight glyph ]
129+24:23 str-head "left "
130+24:30 tight name n
131+24:31 tight str-tail ""
132+25:5 NEWLINE
133+25:5 glyph [
134+25:6 tight lit %move
135+25:12 lit %right
136+25:19 name n
137+25:20 tight glyph ]
138+25:23 str-head "right "
139+25:31 tight name n
140+25:32 tight str-tail ""
141+26:5 NEWLINE
142+26:5 glyph [
143+26:6 tight name move
144+26:11 lit %draft
145+26:17 tight glyph ]
146+26:23 name move
147+27:5 NEWLINE
148+27:5 glyph [
149+27:6 tight name t
150+27:8 lit %sent
151+27:14 name sent-at
152+27:21 tight glyph ]
153+27:23 name t
154+28:5 NEWLINE
155+28:5 lit %stop
156+28:23 str "stop"
157+29:1 DEDENT
158+29:1 DEDENT
159+29:1 NEWLINE
160+29:1 glyph ++
161+29:4 name rest
162+29:9 glyph |=
163+29:12 name s
164+29:13 tight glyph =
165+29:14 tight name step
166+30:3 INDENT
167+30:3 glyph ?-
168+30:6 name s
169+31:5 INDENT
170+31:5 glyph [
171+31:6 tight lit %move
172+31:12 name left
173+31:16 tight glyph ]
174+31:23 str "move"
175+32:5 NEWLINE
176+32:5 glyph [
177+32:6 tight name t
178+32:8 lit %draft
179+32:14 tight glyph ]
180+32:23 name t
181+33:5 NEWLINE
182+33:5 glyph [
183+33:6 tight name t
184+33:8 lit %sent
185+33:14 name sent-at
186+33:21 tight glyph ]
187+33:23 name t
188+34:5 NEWLINE
189+34:5 lit %stop
190+34:23 str "stop"
191+35:1 DEDENT
192+35:1 DEDENT
193+35:1 NEWLINE
194+35:1 glyph ++
195+35:4 name aura
196+35:9 glyph |=
197+35:12 name s
198+35:13 tight glyph =
199+35:14 tight name shape
200+36:3 INDENT
201+36:3 glyph ?-
202+36:6 name s
203+37:5 INDENT
204+37:5 glyph [
205+37:6 tight lit %circle
206+37:14 name red
207+37:17 tight glyph ]
208+37:20 str-head ""
209+37:22 tight name red
210+37:25 tight str-tail ""
211+38:5 NEWLINE
212+38:5 glyph [
213+38:6 tight lit %label
214+38:13 name green
215+38:18 tight glyph ]
216+38:20 name green
217+39:5 NEWLINE
218+39:5 lit %blank
219+39:20 str "blank"
220+40:1 DEDENT
221+40:1 DEDENT
222+40:1 NEWLINE
223+40:1 glyph ++
224+40:4 name other-union
225+40:16 glyph |=
226+40:19 name s
227+40:20 tight glyph =
228+40:21 tight name shape
229+41:3 INDENT
230+41:3 glyph ?-
231+41:6 name s
232+42:5 INDENT
233+42:5 glyph [
234+42:6 tight lit %circle
235+42:14 name r
236+42:15 tight glyph ]
237+42:18 str-head ""
238+42:20 tight name r
239+42:21 tight str-tail ""
240+43:5 NEWLINE
241+43:5 glyph [
242+43:6 tight lit %label
243+43:13 name t
244+43:14 tight glyph ]
245+43:18 name t
246+44:5 NEWLINE
247+44:5 name red
248+44:18 str "other"
249+45:1 DEDENT
250+45:1 DEDENT
251+45:1 NEWLINE
252+45:1 glyph ++
253+45:4 name sample
254+45:11 glyph |=
255+45:14 name stop
256+45:18 tight glyph =
257+45:19 tight name step
258+45:24 str "sample"
259+46:1 NEWLINE
260+46:1 glyph ++
261+46:4 name sample-bare
262+46:16 glyph ^-
263+46:19 glyph $-(
264+46:22 tight name step
265+46:27 aura @t
266+46:29 tight glyph )
267+46:31 glyph |=
268+46:34 name stop
269+46:39 str "sample"
270+47:1 NEWLINE
271+47:1 glyph ++
272+47:4 name atom
273+47:9 glyph |=
274+47:12 name s
275+47:13 tight glyph =
276+47:14 tight aura @tas
277+48:3 INDENT
278+48:3 glyph ?-
279+48:6 name s
280+49:5 INDENT
281+49:5 lit %stop
282+49:12 str "stop"
283+50:5 NEWLINE
284+50:5 name stop
285+50:12 str "other"
286+51:1 DEDENT
287+51:1 DEDENT
288+51:1 NEWLINE
289+51:1 glyph ++
290+51:4 name noun
291+51:9 glyph |=
292+51:12 name s
293+51:13 tight glyph =
294+51:14 tight glyph *
295+52:3 INDENT
296+52:3 glyph ?-
297+52:6 name s
298+53:5 INDENT
299+53:5 name stop
300+53:11 str "any"
301+53:16 DEDENT
302+53:16 DEDENT
303+53:16 NEWLINE
tests/golden/inline-pattern-tag-name-ok/tree.txtnew file+133
@@ -0,0 +1,133 @@
1+(module
2+ (mold 1:1 step
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %move)
6+ (const 2:10 %left)
7+ (face 2:16 n (aura 2:18 @ud)))
8+ (cell 3:3
9+ (const 3:4 %move)
10+ (const 3:10 %right)
11+ (face 3:17 n (aura 3:19 @ud)))
12+ (cell 4:3
13+ (face 4:4 text (aura 4:9 @t))
14+ (const 4:12 %draft))
15+ (cell 5:3
16+ (face 5:4 text (aura 5:9 @t))
17+ (const 5:12 %sent)
18+ (face 5:18 at (aura 5:21 @da)))
19+ (const 6:3 %stop)))
20+ (mold 7:1 colour
21+ (union 8:3 (const 8:3 %red) (const 9:3 %green)))
22+ (mold 10:1 shape
23+ (union 11:3
24+ (cell 11:3
25+ (const 11:4 %circle)
26+ (face 11:12 red (aura 11:16 @ud)))
27+ (cell 12:3
28+ (const 12:4 %label)
29+ (face 12:11 text (aura 12:16 @t)))
30+ (const 13:3 %blank)))
31+ (value 15:1 describe
32+ (gate 15:13
33+ (face 15:16 s (ref 15:18 step))
34+ (body 16:3
35+ (branch 16:3
36+ (wing 16:6 s)
37+ (arm 17:5
38+ (cell 17:5 (lit 17:6 %move) (lit 17:12 %left) (bind 17:18 n))
39+ (str 17:23 "left " (wing 17:30 n)))
40+ (arm 18:5
41+ (cell 18:5 (lit 18:6 %move) (lit 18:12 %right) (bind 18:19 n))
42+ (str 18:23 "right " (wing 18:31 n)))
43+ (arm 19:5
44+ (cell 19:5 (bind 19:6 t) (lit 19:8 %draft))
45+ (wing 19:23 t))
46+ (arm 20:5
47+ (cell 20:5 (bind 20:6 t) (lit 20:8 %sent) (bind 20:14 sent-at))
48+ (wing 20:23 t))
49+ (arm 21:5 (lit 21:5 %stop) (str 21:23 "stop"))))))
50+ (value 22:1 elsewhere
51+ (gate 22:14
52+ (face 22:17 s (ref 22:19 step))
53+ (body 23:3
54+ (branch 23:3
55+ (wing 23:6 s)
56+ (arm 24:5
57+ (cell 24:5 (lit 24:6 %move) (lit 24:12 %left) (bind 24:18 n))
58+ (str 24:23 "left " (wing 24:30 n)))
59+ (arm 25:5
60+ (cell 25:5 (lit 25:6 %move) (lit 25:12 %right) (bind 25:19 n))
61+ (str 25:23 "right " (wing 25:31 n)))
62+ (arm 26:5
63+ (cell 26:5 (bind 26:6 move) (lit 26:11 %draft))
64+ (wing 26:23 move))
65+ (arm 27:5
66+ (cell 27:5 (bind 27:6 t) (lit 27:8 %sent) (bind 27:14 sent-at))
67+ (wing 27:23 t))
68+ (arm 28:5 (lit 28:5 %stop) (str 28:23 "stop"))))))
69+ (value 29:1 rest
70+ (gate 29:9
71+ (face 29:12 s (ref 29:14 step))
72+ (body 30:3
73+ (branch 30:3
74+ (wing 30:6 s)
75+ (arm 31:5
76+ (cell 31:5 (lit 31:6 %move) (bind 31:12 left))
77+ (str 31:23 "move"))
78+ (arm 32:5
79+ (cell 32:5 (bind 32:6 t) (lit 32:8 %draft))
80+ (wing 32:23 t))
81+ (arm 33:5
82+ (cell 33:5 (bind 33:6 t) (lit 33:8 %sent) (bind 33:14 sent-at))
83+ (wing 33:23 t))
84+ (arm 34:5 (lit 34:5 %stop) (str 34:23 "stop"))))))
85+ (value 35:1 aura
86+ (gate 35:9
87+ (face 35:12 s (ref 35:14 shape))
88+ (body 36:3
89+ (branch 36:3
90+ (wing 36:6 s)
91+ (arm 37:5
92+ (cell 37:5 (lit 37:6 %circle) (bind 37:14 red))
93+ (str 37:20 (wing 37:22 red)))
94+ (arm 38:5
95+ (cell 38:5 (lit 38:6 %label) (bind 38:13 green))
96+ (wing 38:20 green))
97+ (arm 39:5 (lit 39:5 %blank) (str 39:20 "blank"))))))
98+ (value 40:1 other-union
99+ (gate 40:16
100+ (face 40:19 s (ref 40:21 shape))
101+ (body 41:3
102+ (branch 41:3
103+ (wing 41:6 s)
104+ (arm 42:5
105+ (cell 42:5 (lit 42:6 %circle) (bind 42:14 r))
106+ (str 42:18 (wing 42:20 r)))
107+ (arm 43:5
108+ (cell 43:5 (lit 43:6 %label) (bind 43:13 t))
109+ (wing 43:18 t))
110+ (arm 44:5 (bind 44:5 red) (str 44:18 "other"))))))
111+ (value 45:1 sample
112+ (gate 45:11
113+ (face 45:14 stop (ref 45:19 step))
114+ (str 45:24 "sample")))
115+ (value 46:1 sample-bare
116+ (cast 46:16
117+ (fn 46:19 (ref 46:22 step) (aura 46:27 @t))
118+ (gate 46:31 (bind 46:34 stop) (str 46:39 "sample"))))
119+ (value 47:1 atom
120+ (gate 47:9
121+ (face 47:12 s (aura 47:14 @tas))
122+ (body 48:3
123+ (branch 48:3
124+ (wing 48:6 s)
125+ (arm 49:5 (lit 49:5 %stop) (str 49:12 "stop"))
126+ (arm 50:5 (bind 50:5 stop) (str 50:12 "other"))))))
127+ (value 51:1 noun
128+ (gate 51:9
129+ (face 51:12 s (noun 51:14))
130+ (body 52:3
131+ (branch 52:3
132+ (wing 52:6 s)
133+ (arm 53:5 (bind 53:5 stop) (str 53:11 "any")))))))
tests/golden/inline-pattern-tag-name-ok/types.txtnew file+13
@@ -0,0 +1,13 @@
1+partial inference; module not checked
2++$ step: cases proven disjoint; mold not checked
3++$ colour: cases proven disjoint; mold not checked
4++$ shape: cases proven disjoint; mold not checked
5+++ describe: $-(step @t)
6+++ elsewhere: $-(step @t)
7+++ rest: partial union pattern is not supported by partial inference
8+++ aura: $-(shape @t)
9+++ other-union: $-(shape @t)
10+++ sample: $-(step @t)
11+++ sample-bare: $-(step @t)
12+++ atom: branch is not supported by partial inference
13+++ noun: branch pattern is not supported by partial inference
tests/golden/inline-pattern-tag-name-one-case/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Patterns: "A name is an error where the subject's type at its position is a union, or a one-case mold, with a case whose constant there is the term the name spells"; Tag resolution: "A mold that isn't a union counts as a union of one case"
2+tests: a name at a one-case mold's tag, in a cell pattern and as the whole pattern; the same pattern with the tag written checks
3+expect: parses
4+expect-types: a partial inference report: `extract` is an error at `go`, 5:6, and `stopped` at `halt`, 8:5; `extract-ok` infers
tests/golden/inline-pattern-tag-name-one-case/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/inline-pattern-tag-name-one-case/source.jibbnew file+11
@@ -0,0 +1,11 @@
1++$ packet [%go url=@t]
2++$ halt %halt
3+++ extract |= p=packet
4+ ?- p
5+ [go u] u
6+++ stopped |= h=halt
7+ ?- h
8+ halt "halted"
9+++ extract-ok |= p=packet
10+ ?- p
11+ [%go u] u
tests/golden/inline-pattern-tag-name-one-case/tokens.txtnew file+64
@@ -0,0 +1,64 @@
1+1:1 glyph +$
2+1:4 name packet
3+1:11 glyph [
4+1:12 tight lit %go
5+1:16 name url
6+1:19 tight glyph =
7+1:20 tight aura @t
8+1:22 tight glyph ]
9+2:1 NEWLINE
10+2:1 glyph +$
11+2:4 name halt
12+2:9 lit %halt
13+3:1 NEWLINE
14+3:1 glyph ++
15+3:4 name extract
16+3:12 glyph |=
17+3:15 name p
18+3:16 tight glyph =
19+3:17 tight name packet
20+4:3 INDENT
21+4:3 glyph ?-
22+4:6 name p
23+5:5 INDENT
24+5:5 glyph [
25+5:6 tight name go
26+5:9 name u
27+5:10 tight glyph ]
28+5:12 name u
29+6:1 DEDENT
30+6:1 DEDENT
31+6:1 NEWLINE
32+6:1 glyph ++
33+6:4 name stopped
34+6:12 glyph |=
35+6:15 name h
36+6:16 tight glyph =
37+6:17 tight name halt
38+7:3 INDENT
39+7:3 glyph ?-
40+7:6 name h
41+8:5 INDENT
42+8:5 name halt
43+8:10 str "halted"
44+9:1 DEDENT
45+9:1 DEDENT
46+9:1 NEWLINE
47+9:1 glyph ++
48+9:4 name extract-ok
49+9:15 glyph |=
50+9:18 name p
51+9:19 tight glyph =
52+9:20 tight name packet
53+10:3 INDENT
54+10:3 glyph ?-
55+10:6 name p
56+11:5 INDENT
57+11:5 glyph [
58+11:6 tight lit %go
59+11:10 name u
60+11:11 tight glyph ]
61+11:13 name u
62+11:14 DEDENT
63+11:14 DEDENT
64+11:14 NEWLINE
tests/golden/inline-pattern-tag-name-one-case/tree.txtnew file+31
@@ -0,0 +1,31 @@
1+(module
2+ (mold 1:1 packet
3+ (cell 1:11
4+ (const 1:12 %go)
5+ (face 1:16 url (aura 1:20 @t))))
6+ (mold 2:1 halt (const 2:9 %halt))
7+ (value 3:1 extract
8+ (gate 3:12
9+ (face 3:15 p (ref 3:17 packet))
10+ (body 4:3
11+ (branch 4:3
12+ (wing 4:6 p)
13+ (arm 5:5
14+ (cell 5:5 (bind 5:6 go) (bind 5:9 u))
15+ (wing 5:12 u))))))
16+ (value 6:1 stopped
17+ (gate 6:12
18+ (face 6:15 h (ref 6:17 halt))
19+ (body 7:3
20+ (branch 7:3
21+ (wing 7:6 h)
22+ (arm 8:5 (bind 8:5 halt) (str 8:10 "halted"))))))
23+ (value 9:1 extract-ok
24+ (gate 9:15
25+ (face 9:18 p (ref 9:20 packet))
26+ (body 10:3
27+ (branch 10:3
28+ (wing 10:6 p)
29+ (arm 11:5
30+ (cell 11:5 (lit 11:6 %go) (bind 11:10 u))
31+ (wing 11:13 u)))))))
tests/golden/inline-pattern-tag-name-one-case/types.txtnew file+18
@@ -0,0 +1,18 @@
1+partial inference; module not checked
2++$ packet: not checked
3++$ halt: not checked
4+++ extract: `go` binds a name, but the subject's type has `%go` here; write %go, or * for a catch-all
5+/tests/golden/inline-pattern-tag-name-one-case/source.jibb:4:6: subject
6+ ?- p
7+ ^
8+/tests/golden/inline-pattern-tag-name-one-case/source.jibb:5:6: pattern name
9+ [go u] u
10+ ^
11+++ stopped: `halt` binds a name, but the subject's type has `%halt` here; write %halt, or * for a catch-all
12+/tests/golden/inline-pattern-tag-name-one-case/source.jibb:7:6: subject
13+ ?- h
14+ ^
15+/tests/golden/inline-pattern-tag-name-one-case/source.jibb:8:5: pattern name
16+ halt "halted"
17+ ^
18+++ extract-ok: $-([%go url=@t] @t)
tests/golden/inline-unface-arity-bad/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "Like `proj`, it is an operation the checker handles by type, not a gate"
2+tests: unface takes exactly one argument: two are an error at the call, and none, (unface), is an error at its parenthesis.
3+expect: parses
4+expect-types: a partial inference report: both are errors at the call
tests/golden/inline-unface-arity-bad/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-arity-bad/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+++ lt-a |= [a=@ud b=@ud] (gth b a)
2+++ two (unface lt-a lt-a)
3+++ none (unface)
tests/golden/inline-unface-arity-bad/tokens.txtnew file+31
@@ -0,0 +1,31 @@
1+1:1 glyph ++
2+1:4 name lt-a
3+1:9 glyph |=
4+1:12 glyph [
5+1:13 tight name a
6+1:14 tight glyph =
7+1:15 tight aura @ud
8+1:19 name b
9+1:20 tight glyph =
10+1:21 tight aura @ud
11+1:24 tight glyph ]
12+1:26 glyph (
13+1:27 tight name gth
14+1:31 name b
15+1:33 name a
16+1:34 tight glyph )
17+2:1 NEWLINE
18+2:1 glyph ++
19+2:4 name two
20+2:8 glyph (
21+2:9 tight name unface
22+2:16 name lt-a
23+2:21 name lt-a
24+2:25 tight glyph )
25+3:1 NEWLINE
26+3:1 glyph ++
27+3:4 name none
28+3:9 glyph (
29+3:10 tight name unface
30+3:16 tight glyph )
31+3:17 NEWLINE
tests/golden/inline-unface-arity-bad/tree.txtnew file+13
@@ -0,0 +1,13 @@
1+(module
2+ (value 1:1 lt-a
3+ (gate 1:9
4+ (cell 1:12
5+ (face 1:13 a (aura 1:15 @ud))
6+ (face 1:19 b (aura 1:21 @ud)))
7+ (group 1:26
8+ (call 1:27 (wing 1:27 gth) (wing 1:31 b) (wing 1:33 a)))))
9+ (value 2:1 two
10+ (group 2:8
11+ (call 2:9 (wing 2:9 unface) (wing 2:16 lt-a) (wing 2:21 lt-a))))
12+ (value 3:1 none
13+ (group 3:9 (wing 3:10 unface))))
tests/golden/inline-unface-arity-bad/types.txtnew file+10
@@ -0,0 +1,10 @@
1+partial inference; module not checked
2+++ lt-a: $-([a=@ud b=@ud] ?)
3+++ two: unface takes one argument, as (unface e)
4+/tests/golden/inline-unface-arity-bad/source.jibb:2:9: unface call
5+++ two (unface lt-a lt-a)
6+ ^
7+++ none: unface takes one argument, as (unface e)
8+/tests/golden/inline-unface-arity-bad/source.jibb:3:9: unface call
9+++ none (unface)
10+ ^
tests/golden/inline-unface-deep/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "`(unface e)` is `e` with every face removed from its type"
2+tests: Faces are removed all the way down: from a gate's product, from a gate in its sample, and from the arguments of a list and a unit, whose own u= stays; a gate with no faces is unchanged.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-deep/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-deep/source.jibbnew file+10
@@ -0,0 +1,10 @@
1+++ make |= n=@ud ^- [label=@t n=@ud] ["x" n]
2+++ make-u (unface make)
3+++ made (make-u 1)
4+++ apply |= f=$-([x=@ud y=@ud] ?) [r=(f 1 2)]
5+++ apply-u (unface apply)
6+++ pairs ^- (list [p=@t q=@ud]) ~[["a" 1]]
7+++ pairs-u (unface pairs)
8+++ maybe ^- (unit [p=@t q=@ud]) `["a" 1]
9+++ maybe-u (unface maybe)
10+++ same-u (unface same)
tests/golden/inline-unface-deep/tokens.txtnew file+129
@@ -0,0 +1,129 @@
1+1:1 glyph ++
2+1:4 name make
3+1:9 glyph |=
4+1:12 name n
5+1:13 tight glyph =
6+1:14 tight aura @ud
7+1:18 glyph ^-
8+1:21 glyph [
9+1:22 tight name label
10+1:27 tight glyph =
11+1:28 tight aura @t
12+1:31 name n
13+1:32 tight glyph =
14+1:33 tight aura @ud
15+1:36 tight glyph ]
16+1:38 glyph [
17+1:39 tight str "x"
18+1:43 name n
19+1:44 tight glyph ]
20+2:1 NEWLINE
21+2:1 glyph ++
22+2:4 name make-u
23+2:11 glyph (
24+2:12 tight name unface
25+2:19 name make
26+2:23 tight glyph )
27+3:1 NEWLINE
28+3:1 glyph ++
29+3:4 name made
30+3:9 glyph (
31+3:10 tight name make-u
32+3:17 lit 1
33+3:18 tight glyph )
34+4:1 NEWLINE
35+4:1 glyph ++
36+4:4 name apply
37+4:10 glyph |=
38+4:13 name f
39+4:14 tight glyph =
40+4:15 tight glyph $-(
41+4:18 tight glyph [
42+4:19 tight name x
43+4:20 tight glyph =
44+4:21 tight aura @ud
45+4:25 name y
46+4:26 tight glyph =
47+4:27 tight aura @ud
48+4:30 tight glyph ]
49+4:32 glyph ?
50+4:33 tight glyph )
51+4:35 glyph [
52+4:36 tight name r
53+4:37 tight glyph =
54+4:38 tight glyph (
55+4:39 tight name f
56+4:41 lit 1
57+4:43 lit 2
58+4:44 tight glyph )
59+4:45 tight glyph ]
60+5:1 NEWLINE
61+5:1 glyph ++
62+5:4 name apply-u
63+5:12 glyph (
64+5:13 tight name unface
65+5:20 name apply
66+5:25 tight glyph )
67+6:1 NEWLINE
68+6:1 glyph ++
69+6:4 name pairs
70+6:10 glyph ^-
71+6:13 glyph (
72+6:14 tight name list
73+6:19 glyph [
74+6:20 tight name p
75+6:21 tight glyph =
76+6:22 tight aura @t
77+6:25 name q
78+6:26 tight glyph =
79+6:27 tight aura @ud
80+6:30 tight glyph ]
81+6:31 tight glyph )
82+6:33 glyph ~[
83+6:35 tight glyph [
84+6:36 tight str "a"
85+6:40 lit 1
86+6:41 tight glyph ]
87+6:42 tight glyph ]
88+7:1 NEWLINE
89+7:1 glyph ++
90+7:4 name pairs-u
91+7:12 glyph (
92+7:13 tight name unface
93+7:20 name pairs
94+7:25 tight glyph )
95+8:1 NEWLINE
96+8:1 glyph ++
97+8:4 name maybe
98+8:10 glyph ^-
99+8:13 glyph (
100+8:14 tight name unit
101+8:19 glyph [
102+8:20 tight name p
103+8:21 tight glyph =
104+8:22 tight aura @t
105+8:25 name q
106+8:26 tight glyph =
107+8:27 tight aura @ud
108+8:30 tight glyph ]
109+8:31 tight glyph )
110+8:33 glyph `
111+8:34 tight glyph [
112+8:35 tight str "a"
113+8:39 lit 1
114+8:40 tight glyph ]
115+9:1 NEWLINE
116+9:1 glyph ++
117+9:4 name maybe-u
118+9:12 glyph (
119+9:13 tight name unface
120+9:20 name maybe
121+9:25 tight glyph )
122+10:1 NEWLINE
123+10:1 glyph ++
124+10:4 name same-u
125+10:11 glyph (
126+10:12 tight name unface
127+10:19 name same
128+10:23 tight glyph )
129+10:24 NEWLINE
tests/golden/inline-unface-deep/tree.txtnew file+55
@@ -0,0 +1,55 @@
1+(module
2+ (value 1:1 make
3+ (gate 1:9
4+ (face 1:12 n (aura 1:14 @ud))
5+ (cast 1:18
6+ (cell 1:21
7+ (face 1:22 label (aura 1:28 @t))
8+ (face 1:31 n (aura 1:33 @ud)))
9+ (tuple 1:38 (str 1:39 "x") (wing 1:43 n)))))
10+ (value 2:1 make-u
11+ (group 2:11
12+ (call 2:12 (wing 2:12 unface) (wing 2:19 make))))
13+ (value 3:1 made
14+ (group 3:9
15+ (call 3:10 (wing 3:10 make-u) (lit 3:17 1))))
16+ (value 4:1 apply
17+ (gate 4:10
18+ (face 4:13 f
19+ (fn 4:15
20+ (cell 4:18
21+ (face 4:19 x (aura 4:21 @ud))
22+ (face 4:25 y (aura 4:27 @ud)))
23+ (flag 4:32)))
24+ (tuple 4:35
25+ (face 4:36 r
26+ (group 4:38
27+ (call 4:39 (wing 4:39 f) (lit 4:41 1) (lit 4:43 2)))))))
28+ (value 5:1 apply-u
29+ (group 5:12
30+ (call 5:13 (wing 5:13 unface) (wing 5:20 apply))))
31+ (value 6:1 pairs
32+ (cast 6:10
33+ (apply 6:13 list
34+ (cell 6:19
35+ (face 6:20 p (aura 6:22 @t))
36+ (face 6:25 q (aura 6:27 @ud))))
37+ (list 6:33
38+ (tuple 6:35 (str 6:36 "a") (lit 6:40 1)))))
39+ (value 7:1 pairs-u
40+ (group 7:12
41+ (call 7:13 (wing 7:13 unface) (wing 7:20 pairs))))
42+ (value 8:1 maybe
43+ (cast 8:10
44+ (apply 8:13 unit
45+ (cell 8:19
46+ (face 8:20 p (aura 8:22 @t))
47+ (face 8:25 q (aura 8:27 @ud))))
48+ (unit 8:33
49+ (tuple 8:34 (str 8:35 "a") (lit 8:39 1)))))
50+ (value 9:1 maybe-u
51+ (group 9:12
52+ (call 9:13 (wing 9:13 unface) (wing 9:20 maybe))))
53+ (value 10:1 same-u
54+ (group 10:11
55+ (call 10:12 (wing 10:12 unface) (wing 10:19 same)))))
tests/golden/inline-unface-deep/types.txtnew file+11
@@ -0,0 +1,11 @@
1+partial inference; module not checked
2+++ make: $-(@ud [label=@t n=@ud])
3+++ make-u: $-(@ud [@t @ud])
4+++ made: [@t @ud]
5+++ apply: $-($-([x=@ud y=@ud] ?) [r=?])
6+++ apply-u: $-($-([@ud @ud] ?) ?)
7+++ pairs: (list [p=@t q=@ud])
8+++ pairs-u: (list [@t @ud])
9+++ maybe: (unit [p=@t q=@ud])
10+++ maybe-u: (unit [@t @ud])
11+++ same-u: $-(A A)
tests/golden/inline-unface-gates/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "`(unface e)` is `e` with every face removed from its type"
2+tests: Gates whose samples are labelled differently share a list and fit slots written with capitals once unfaced; the same gates without unface fail, and a direct call of an unfaced gate takes any labels.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-gates/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-gates/source.jibbnew file+11
@@ -0,0 +1,11 @@
1+++ lth2 |= [x=A y=A] (gth y x)
2+++ lte2 |= [a=A b=A] (not (gth a b))
3+++ lt-a |= [a=@ud b=@ud] (gth b a)
4+++ add-f |= [a=@ud b=@ud] (add a b)
5+++ labelled ~[lth2 lte2]
6+++ pickers ~[(unface lth2) (unface lte2)]
7+++ hunt-labelled (hunt lt-a `1 `2)
8+++ hunt-unfaced (hunt (unface lt-a) `1 `2)
9+++ roll-labelled (roll ~[1 2] 0 add-f)
10+++ roll-unfaced (roll ~[1 2] 0 (unface add-f))
11+++ one-off ((unface add-f) [b=1 a=2])
tests/golden/inline-unface-gates/tokens.txtnew file+160
@@ -0,0 +1,160 @@
1+1:1 glyph ++
2+1:4 name lth2
3+1:9 glyph |=
4+1:12 glyph [
5+1:13 tight name x
6+1:14 tight glyph =
7+1:15 tight tvar A
8+1:17 name y
9+1:18 tight glyph =
10+1:19 tight tvar A
11+1:20 tight glyph ]
12+1:22 glyph (
13+1:23 tight name gth
14+1:27 name y
15+1:29 name x
16+1:30 tight glyph )
17+2:1 NEWLINE
18+2:1 glyph ++
19+2:4 name lte2
20+2:9 glyph |=
21+2:12 glyph [
22+2:13 tight name a
23+2:14 tight glyph =
24+2:15 tight tvar A
25+2:17 name b
26+2:18 tight glyph =
27+2:19 tight tvar A
28+2:20 tight glyph ]
29+2:22 glyph (
30+2:23 tight name not
31+2:27 glyph (
32+2:28 tight name gth
33+2:32 name a
34+2:34 name b
35+2:35 tight glyph )
36+2:36 tight glyph )
37+3:1 NEWLINE
38+3:1 glyph ++
39+3:4 name lt-a
40+3:9 glyph |=
41+3:12 glyph [
42+3:13 tight name a
43+3:14 tight glyph =
44+3:15 tight aura @ud
45+3:19 name b
46+3:20 tight glyph =
47+3:21 tight aura @ud
48+3:24 tight glyph ]
49+3:26 glyph (
50+3:27 tight name gth
51+3:31 name b
52+3:33 name a
53+3:34 tight glyph )
54+4:1 NEWLINE
55+4:1 glyph ++
56+4:4 name add-f
57+4:10 glyph |=
58+4:13 glyph [
59+4:14 tight name a
60+4:15 tight glyph =
61+4:16 tight aura @ud
62+4:20 name b
63+4:21 tight glyph =
64+4:22 tight aura @ud
65+4:25 tight glyph ]
66+4:27 glyph (
67+4:28 tight name add
68+4:32 name a
69+4:34 name b
70+4:35 tight glyph )
71+5:1 NEWLINE
72+5:1 glyph ++
73+5:4 name labelled
74+5:13 glyph ~[
75+5:15 tight name lth2
76+5:20 name lte2
77+5:24 tight glyph ]
78+6:1 NEWLINE
79+6:1 glyph ++
80+6:4 name pickers
81+6:12 glyph ~[
82+6:14 tight glyph (
83+6:15 tight name unface
84+6:22 name lth2
85+6:26 tight glyph )
86+6:28 glyph (
87+6:29 tight name unface
88+6:36 name lte2
89+6:40 tight glyph )
90+6:41 tight glyph ]
91+7:1 NEWLINE
92+7:1 glyph ++
93+7:4 name hunt-labelled
94+7:18 glyph (
95+7:19 tight name hunt
96+7:24 name lt-a
97+7:29 glyph `
98+7:30 tight lit 1
99+7:32 glyph `
100+7:33 tight lit 2
101+7:34 tight glyph )
102+8:1 NEWLINE
103+8:1 glyph ++
104+8:4 name hunt-unfaced
105+8:17 glyph (
106+8:18 tight name hunt
107+8:23 glyph (
108+8:24 tight name unface
109+8:31 name lt-a
110+8:35 tight glyph )
111+8:37 glyph `
112+8:38 tight lit 1
113+8:40 glyph `
114+8:41 tight lit 2
115+8:42 tight glyph )
116+9:1 NEWLINE
117+9:1 glyph ++
118+9:4 name roll-labelled
119+9:18 glyph (
120+9:19 tight name roll
121+9:24 glyph ~[
122+9:26 tight lit 1
123+9:28 lit 2
124+9:29 tight glyph ]
125+9:31 lit 0
126+9:33 name add-f
127+9:38 tight glyph )
128+10:1 NEWLINE
129+10:1 glyph ++
130+10:4 name roll-unfaced
131+10:17 glyph (
132+10:18 tight name roll
133+10:23 glyph ~[
134+10:25 tight lit 1
135+10:27 lit 2
136+10:28 tight glyph ]
137+10:30 lit 0
138+10:32 glyph (
139+10:33 tight name unface
140+10:40 name add-f
141+10:45 tight glyph )
142+10:46 tight glyph )
143+11:1 NEWLINE
144+11:1 glyph ++
145+11:4 name one-off
146+11:12 glyph (
147+11:13 tight glyph (
148+11:14 tight name unface
149+11:21 name add-f
150+11:26 tight glyph )
151+11:28 glyph [
152+11:29 tight name b
153+11:30 tight glyph =
154+11:31 tight lit 1
155+11:33 name a
156+11:34 tight glyph =
157+11:35 tight lit 2
158+11:36 tight glyph ]
159+11:37 tight glyph )
160+11:38 NEWLINE
tests/golden/inline-unface-gates/tree.txtnew file+78
@@ -0,0 +1,78 @@
1+(module
2+ (value 1:1 lth2
3+ (gate 1:9
4+ (cell 1:12
5+ (face 1:13 x (tvar 1:15 A))
6+ (face 1:17 y (tvar 1:19 A)))
7+ (group 1:22
8+ (call 1:23 (wing 1:23 gth) (wing 1:27 y) (wing 1:29 x)))))
9+ (value 2:1 lte2
10+ (gate 2:9
11+ (cell 2:12
12+ (face 2:13 a (tvar 2:15 A))
13+ (face 2:17 b (tvar 2:19 A)))
14+ (group 2:22
15+ (call 2:23
16+ (wing 2:23 not)
17+ (group 2:27
18+ (call 2:28 (wing 2:28 gth) (wing 2:32 a) (wing 2:34 b)))))))
19+ (value 3:1 lt-a
20+ (gate 3:9
21+ (cell 3:12
22+ (face 3:13 a (aura 3:15 @ud))
23+ (face 3:19 b (aura 3:21 @ud)))
24+ (group 3:26
25+ (call 3:27 (wing 3:27 gth) (wing 3:31 b) (wing 3:33 a)))))
26+ (value 4:1 add-f
27+ (gate 4:10
28+ (cell 4:13
29+ (face 4:14 a (aura 4:16 @ud))
30+ (face 4:20 b (aura 4:22 @ud)))
31+ (group 4:27
32+ (call 4:28 (wing 4:28 add) (wing 4:32 a) (wing 4:34 b)))))
33+ (value 5:1 labelled
34+ (list 5:13 (wing 5:15 lth2) (wing 5:20 lte2)))
35+ (value 6:1 pickers
36+ (list 6:12
37+ (group 6:14
38+ (call 6:15 (wing 6:15 unface) (wing 6:22 lth2)))
39+ (group 6:28
40+ (call 6:29 (wing 6:29 unface) (wing 6:36 lte2)))))
41+ (value 7:1 hunt-labelled
42+ (group 7:18
43+ (call 7:19
44+ (wing 7:19 hunt)
45+ (wing 7:24 lt-a)
46+ (unit 7:29 (lit 7:30 1))
47+ (unit 7:32 (lit 7:33 2)))))
48+ (value 8:1 hunt-unfaced
49+ (group 8:17
50+ (call 8:18
51+ (wing 8:18 hunt)
52+ (group 8:23
53+ (call 8:24 (wing 8:24 unface) (wing 8:31 lt-a)))
54+ (unit 8:37 (lit 8:38 1))
55+ (unit 8:40 (lit 8:41 2)))))
56+ (value 9:1 roll-labelled
57+ (group 9:18
58+ (call 9:19
59+ (wing 9:19 roll)
60+ (list 9:24 (lit 9:26 1) (lit 9:28 2))
61+ (lit 9:31 0)
62+ (wing 9:33 add-f))))
63+ (value 10:1 roll-unfaced
64+ (group 10:17
65+ (call 10:18
66+ (wing 10:18 roll)
67+ (list 10:23 (lit 10:25 1) (lit 10:27 2))
68+ (lit 10:30 0)
69+ (group 10:32
70+ (call 10:33 (wing 10:33 unface) (wing 10:40 add-f))))))
71+ (value 11:1 one-off
72+ (group 11:12
73+ (call 11:13
74+ (group 11:13
75+ (call 11:14 (wing 11:14 unface) (wing 11:21 add-f)))
76+ (tuple 11:28
77+ (face 11:29 b (lit 11:31 1))
78+ (face 11:33 a (lit 11:35 2)))))))
tests/golden/inline-unface-gates/types.txtnew file+30
@@ -0,0 +1,30 @@
1+partial inference; module not checked
2+++ lth2: $-([x=A y=A] ?) where A is an atom
3+++ lte2: $-([a=A b=A] ?) where A is an atom
4+++ lt-a: $-([a=@ud b=@ud] ?)
5+++ add-f: $-([a=@ud b=@ud] @ud)
6+++ labelled: list items do not have compatible types
7+/tests/golden/inline-unface-gates/source.jibb:5:13: expected item has type $-([x=A y=A] ?) where A is an atom
8+++ labelled ~[lth2 lte2]
9+ ^
10+/tests/golden/inline-unface-gates/source.jibb:5:20: list item has type $-([a=A b=A] ?) where A is an atom
11+++ labelled ~[lth2 lte2]
12+ ^
13+++ pickers: (list $-([A A] ?)) where A is an atom
14+++ hunt-labelled: call's sample and argument types do not unify
15+/tests/golden/inline-unface-gates/source.jibb:7:19: called gate
16+++ hunt-labelled (hunt lt-a `1 `2)
17+ ^
18+/tests/golden/inline-unface-gates/source.jibb:7:24: argument has type $-([a=@ud b=@ud] ?)
19+++ hunt-labelled (hunt lt-a `1 `2)
20+ ^
21+++ hunt-unfaced: (unit @ud)
22+++ roll-labelled: call's sample and argument types do not unify
23+/tests/golden/inline-unface-gates/source.jibb:9:19: called gate
24+++ roll-labelled (roll ~[1 2] 0 add-f)
25+ ^
26+/tests/golden/inline-unface-gates/source.jibb:9:33: argument has type $-([a=@ud b=@ud] @ud)
27+++ roll-labelled (roll ~[1 2] 0 add-f)
28+ ^
29+++ roll-unfaced: @ud
30+++ one-off: @ud
tests/golden/inline-unface-import/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "`(unface e)` is `e` with every face removed from its type" and "A `++` whose body is `(unface |= …)` is still a gate, so it can call itself"
2+tests: An imported module, checked in full, exports unfaced gates and records, a recursive one included, and the importer uses them with their unfaced types.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-import/module-trees.txtnew file+43
@@ -0,0 +1,43 @@
1+/ui/lib.jibb
2+(module
3+ (value 1:1 lt-a
4+ (gate 1:9
5+ (cell 1:12
6+ (face 1:13 a (aura 1:15 @ud))
7+ (face 1:19 b (aura 1:21 @ud)))
8+ (group 1:26
9+ (call 1:27 (wing 1:27 gth) (wing 1:31 b) (wing 1:33 a)))))
10+ (value 2:1 lt-u
11+ (group 2:9
12+ (call 2:10 (wing 2:10 unface) (wing 2:17 lt-a))))
13+ (value 3:1 weld2
14+ (group 3:10
15+ (call 3:11
16+ (wing 3:11 unface)
17+ (gate 4:3
18+ (cell 4:6
19+ (face 4:7 xs
20+ (apply 4:10 list (tvar 4:16 A)))
21+ (face 4:19 ys
22+ (apply 4:22 list (tvar 4:28 A))))
23+ (cast 4:32
24+ (apply 4:35 list (tvar 4:41 A))
25+ (body 5:5
26+ (branch 5:5
27+ (wing 5:8 xs)
28+ (arm 6:7 (lit 6:7 ~) (wing 6:9 ys))
29+ (arm 7:7
30+ (cell 7:7 (bind 7:8 item) (bind 7:13 rest))
31+ (tuple 7:19
32+ (wing 7:20 item)
33+ (group 7:25
34+ (call 7:26 (wing 7:26 weld2) (wing 7:32 rest) (wing 7:37 ys))))))))))))
35+ (value 8:1 pair
36+ (cast 8:9
37+ (cell 8:12
38+ (face 8:13 p (aura 8:15 @t))
39+ (face 8:18 q (aura 8:20 @ud)))
40+ (tuple 8:25 (str 8:26 "a") (lit 8:30 1))))
41+ (value 9:1 pair-u
42+ (group 9:11
43+ (call 9:12 (wing 9:12 unface) (wing 9:19 pair)))))
tests/golden/inline-unface-import/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/inline-unface-import/modules/ui/lib.jibbnew file+9
@@ -0,0 +1,9 @@
1+++ lt-a |= [a=@ud b=@ud] (gth b a)
2+++ lt-u (unface lt-a)
3+++ weld2 (unface
4+ |= [xs=(list A) ys=(list A)] ^- (list A)
5+ ?- xs
6+ ~ ys
7+ [item rest] [item (weld2 rest ys)]
8+++ pair ^- [p=@t q=@ud] ["a" 1]
9+++ pair-u (unface pair)
tests/golden/inline-unface-import/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+/= lib /ui/lib
2+++ a lt-u.lib
3+++ b (weld2.lib ~[1] ~[2])
4+++ c pair-u.lib
5+++ d (hunt lt-u.lib `1 `2)
tests/golden/inline-unface-import/tokens.txtnew file+38
@@ -0,0 +1,38 @@
1+1:1 glyph /=
2+1:5 name lib
3+1:9 glyph /
4+1:10 tight knot ui
5+1:12 tight glyph /
6+1:13 tight knot lib
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name a
10+2:6 wing lt-u.lib
11+3:1 NEWLINE
12+3:1 glyph ++
13+3:4 name b
14+3:6 glyph (
15+3:7 tight wing weld2.lib
16+3:17 glyph ~[
17+3:19 tight lit 1
18+3:20 tight glyph ]
19+3:22 glyph ~[
20+3:24 tight lit 2
21+3:25 tight glyph ]
22+3:26 tight glyph )
23+4:1 NEWLINE
24+4:1 glyph ++
25+4:4 name c
26+4:6 wing pair-u.lib
27+5:1 NEWLINE
28+5:1 glyph ++
29+5:4 name d
30+5:6 glyph (
31+5:7 tight name hunt
32+5:12 wing lt-u.lib
33+5:21 glyph `
34+5:22 tight lit 1
35+5:24 glyph `
36+5:25 tight lit 2
37+5:26 tight glyph )
38+5:27 NEWLINE
tests/golden/inline-unface-import/tree.txtnew file+17
@@ -0,0 +1,17 @@
1+(module
2+ (jibb 1:1 lib /ui/lib)
3+ (value 2:1 a (wing 2:6 lt-u.lib))
4+ (value 3:1 b
5+ (group 3:6
6+ (call 3:7
7+ (wing 3:7 weld2.lib)
8+ (list 3:17 (lit 3:19 1))
9+ (list 3:22 (lit 3:24 2)))))
10+ (value 4:1 c (wing 4:6 pair-u.lib))
11+ (value 5:1 d
12+ (group 5:6
13+ (call 5:7
14+ (wing 5:7 hunt)
15+ (wing 5:12 lt-u.lib)
16+ (unit 5:21 (lit 5:22 1))
17+ (unit 5:24 (lit 5:25 2))))))
tests/golden/inline-unface-import/types.txtnew file+5
@@ -0,0 +1,5 @@
1+partial inference; module not checked
2+++ a: $-([@ud @ud] ?)
3+++ b: (list @ud)
4+++ c: [@t @ud]
5+++ d: (unit @ud)
tests/golden/inline-unface-labelled-slot/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "`(unface e)` is `e` with every face removed from its type, so a gate or record fits where other names are expected"
2+tests: An unfaced gate passed to a slot that writes its own labels: a closed gate fits, as "an unnamed position can unify with a faced position" allows; a generic one still fails, because its capital A meets the faced x=@ud, and a capital binding only the type under a face is S1 step 1, not part of this rule.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-labelled-slot/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-labelled-slot/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ lt-a |= [a=@ud b=@ud] (gth b a)
2+++ lth2 |= [x=A y=A] (gth y x)
3+++ take-xy |= f=$-([x=@ud y=@ud] ?) (f 1 2)
4+++ closed (take-xy (unface lt-a))
5+++ generic (take-xy (unface lth2))
tests/golden/inline-unface-labelled-slot/tokens.txtnew file+76
@@ -0,0 +1,76 @@
1+1:1 glyph ++
2+1:4 name lt-a
3+1:9 glyph |=
4+1:12 glyph [
5+1:13 tight name a
6+1:14 tight glyph =
7+1:15 tight aura @ud
8+1:19 name b
9+1:20 tight glyph =
10+1:21 tight aura @ud
11+1:24 tight glyph ]
12+1:26 glyph (
13+1:27 tight name gth
14+1:31 name b
15+1:33 name a
16+1:34 tight glyph )
17+2:1 NEWLINE
18+2:1 glyph ++
19+2:4 name lth2
20+2:9 glyph |=
21+2:12 glyph [
22+2:13 tight name x
23+2:14 tight glyph =
24+2:15 tight tvar A
25+2:17 name y
26+2:18 tight glyph =
27+2:19 tight tvar A
28+2:20 tight glyph ]
29+2:22 glyph (
30+2:23 tight name gth
31+2:27 name y
32+2:29 name x
33+2:30 tight glyph )
34+3:1 NEWLINE
35+3:1 glyph ++
36+3:4 name take-xy
37+3:12 glyph |=
38+3:15 name f
39+3:16 tight glyph =
40+3:17 tight glyph $-(
41+3:20 tight glyph [
42+3:21 tight name x
43+3:22 tight glyph =
44+3:23 tight aura @ud
45+3:27 name y
46+3:28 tight glyph =
47+3:29 tight aura @ud
48+3:32 tight glyph ]
49+3:34 glyph ?
50+3:35 tight glyph )
51+3:37 glyph (
52+3:38 tight name f
53+3:40 lit 1
54+3:42 lit 2
55+3:43 tight glyph )
56+4:1 NEWLINE
57+4:1 glyph ++
58+4:4 name closed
59+4:11 glyph (
60+4:12 tight name take-xy
61+4:20 glyph (
62+4:21 tight name unface
63+4:28 name lt-a
64+4:32 tight glyph )
65+4:33 tight glyph )
66+5:1 NEWLINE
67+5:1 glyph ++
68+5:4 name generic
69+5:12 glyph (
70+5:13 tight name take-xy
71+5:21 glyph (
72+5:22 tight name unface
73+5:29 name lth2
74+5:33 tight glyph )
75+5:34 tight glyph )
76+5:35 NEWLINE
tests/golden/inline-unface-labelled-slot/tree.txtnew file+37
@@ -0,0 +1,37 @@
1+(module
2+ (value 1:1 lt-a
3+ (gate 1:9
4+ (cell 1:12
5+ (face 1:13 a (aura 1:15 @ud))
6+ (face 1:19 b (aura 1:21 @ud)))
7+ (group 1:26
8+ (call 1:27 (wing 1:27 gth) (wing 1:31 b) (wing 1:33 a)))))
9+ (value 2:1 lth2
10+ (gate 2:9
11+ (cell 2:12
12+ (face 2:13 x (tvar 2:15 A))
13+ (face 2:17 y (tvar 2:19 A)))
14+ (group 2:22
15+ (call 2:23 (wing 2:23 gth) (wing 2:27 y) (wing 2:29 x)))))
16+ (value 3:1 take-xy
17+ (gate 3:12
18+ (face 3:15 f
19+ (fn 3:17
20+ (cell 3:20
21+ (face 3:21 x (aura 3:23 @ud))
22+ (face 3:27 y (aura 3:29 @ud)))
23+ (flag 3:34)))
24+ (group 3:37
25+ (call 3:38 (wing 3:38 f) (lit 3:40 1) (lit 3:42 2)))))
26+ (value 4:1 closed
27+ (group 4:11
28+ (call 4:12
29+ (wing 4:12 take-xy)
30+ (group 4:20
31+ (call 4:21 (wing 4:21 unface) (wing 4:28 lt-a))))))
32+ (value 5:1 generic
33+ (group 5:12
34+ (call 5:13
35+ (wing 5:13 take-xy)
36+ (group 5:21
37+ (call 5:22 (wing 5:22 unface) (wing 5:29 lth2)))))))
tests/golden/inline-unface-labelled-slot/types.txtnew file+12
@@ -0,0 +1,12 @@
1+partial inference; module not checked
2+++ lt-a: $-([a=@ud b=@ud] ?)
3+++ lth2: $-([x=A y=A] ?) where A is an atom
4+++ take-xy: $-($-([x=@ud y=@ud] ?) ?)
5+++ closed: ?
6+++ generic: call's sample and argument types do not unify
7+/tests/golden/inline-unface-labelled-slot/source.jibb:5:13: called gate has type $-($-([x=@ud y=@ud] ?) ?)
8+++ generic (take-xy (unface lth2))
9+ ^
10+/tests/golden/inline-unface-labelled-slot/source.jibb:5:21: argument has type $-([A A] ?) where A is an atom
11+++ generic (take-xy (unface lth2))
12+ ^
tests/golden/inline-unface-lambda/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "`(unface e)` is `e` with every face removed from its type, so a gate or record fits where other names are expected"
2+tests: A lambda that names its sample k and v fails turn's slot over [p=@t q=@ud] and fits it once unfaced. turn's capital A then binds the faced p=@t, so the result keeps p=: that is S1 step 1 (a capital binds only the type under a face), which this rule leaves to the review's unification work.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-lambda/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-lambda/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+++ pairs ^- (list [p=@t q=@ud]) ~[["a" 1]]
2+++ keys-labelled (turn pairs |=([k v] k))
3+++ keys (turn pairs (unface |=([k v] k)))
tests/golden/inline-unface-lambda/tokens.txtnew file+52
@@ -0,0 +1,52 @@
1+1:1 glyph ++
2+1:4 name pairs
3+1:10 glyph ^-
4+1:13 glyph (
5+1:14 tight name list
6+1:19 glyph [
7+1:20 tight name p
8+1:21 tight glyph =
9+1:22 tight aura @t
10+1:25 name q
11+1:26 tight glyph =
12+1:27 tight aura @ud
13+1:30 tight glyph ]
14+1:31 tight glyph )
15+1:33 glyph ~[
16+1:35 tight glyph [
17+1:36 tight str "a"
18+1:40 lit 1
19+1:41 tight glyph ]
20+1:42 tight glyph ]
21+2:1 NEWLINE
22+2:1 glyph ++
23+2:4 name keys-labelled
24+2:18 glyph (
25+2:19 tight name turn
26+2:24 name pairs
27+2:30 glyph |=(
28+2:33 tight glyph [
29+2:34 tight name k
30+2:36 name v
31+2:37 tight glyph ]
32+2:39 name k
33+2:40 tight glyph )
34+2:41 tight glyph )
35+3:1 NEWLINE
36+3:1 glyph ++
37+3:4 name keys
38+3:9 glyph (
39+3:10 tight name turn
40+3:15 name pairs
41+3:21 glyph (
42+3:22 tight name unface
43+3:29 glyph |=(
44+3:32 tight glyph [
45+3:33 tight name k
46+3:35 name v
47+3:36 tight glyph ]
48+3:38 name k
49+3:39 tight glyph )
50+3:40 tight glyph )
51+3:41 tight glyph )
52+3:42 NEWLINE
tests/golden/inline-unface-lambda/tree.txtnew file+28
@@ -0,0 +1,28 @@
1+(module
2+ (value 1:1 pairs
3+ (cast 1:10
4+ (apply 1:13 list
5+ (cell 1:19
6+ (face 1:20 p (aura 1:22 @t))
7+ (face 1:25 q (aura 1:27 @ud))))
8+ (list 1:33
9+ (tuple 1:35 (str 1:36 "a") (lit 1:40 1)))))
10+ (value 2:1 keys-labelled
11+ (group 2:18
12+ (call 2:19
13+ (wing 2:19 turn)
14+ (wing 2:24 pairs)
15+ (gate-wide 2:30
16+ (cell 2:33 (bind 2:34 k) (bind 2:36 v))
17+ (wing 2:39 k)))))
18+ (value 3:1 keys
19+ (group 3:9
20+ (call 3:10
21+ (wing 3:10 turn)
22+ (wing 3:15 pairs)
23+ (group 3:21
24+ (call 3:22
25+ (wing 3:22 unface)
26+ (gate-wide 3:29
27+ (cell 3:32 (bind 3:33 k) (bind 3:35 v))
28+ (wing 3:38 k))))))))
tests/golden/inline-unface-lambda/types.txtnew file+10
@@ -0,0 +1,10 @@
1+partial inference; module not checked
2+++ pairs: (list [p=@t q=@ud])
3+++ keys-labelled: call's sample and argument types do not unify
4+/tests/golden/inline-unface-lambda/source.jibb:2:19: called gate has type $-([(list A) $-(A B)] (list B))
5+++ keys-labelled (turn pairs |=([k v] k))
6+ ^
7+/tests/golden/inline-unface-lambda/source.jibb:2:30: argument has type $-([k=A v=B] A)
8+++ keys-labelled (turn pairs |=([k v] k))
9+ ^
10+++ keys: (list [p=@t])
tests/golden/inline-unface-named-union/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "`(unface e)` is `e` with every face removed from its type"
2+tests: A gate over a named union keeps the union by name, so the unfaced gate still takes a msg and fits a slot written with msg; tags inside unface still take their union from a cast.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-named-union/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-named-union/source.jibbnew file+9
@@ -0,0 +1,9 @@
1++$ msg
2+ [%typed text=@t]
3+ [%sent ~]
4+++ update |= [=msg n=@ud] n
5+++ update-u (unface update)
6+++ direct (update-u [%typed "x"] 1)
7+++ run |= f=$-([msg @ud] @ud) (f [%sent ~] 2)
8+++ ran (run (unface update))
9+++ tagged ^- msg (unface [%typed "x"])
tests/golden/inline-unface-named-union/tokens.txtnew file+89
@@ -0,0 +1,89 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %typed
6+2:11 name text
7+2:15 tight glyph =
8+2:16 tight aura @t
9+2:18 tight glyph ]
10+3:3 NEWLINE
11+3:3 glyph [
12+3:4 tight lit %sent
13+3:10 lit ~
14+3:11 tight glyph ]
15+4:1 DEDENT
16+4:1 NEWLINE
17+4:1 glyph ++
18+4:4 name update
19+4:11 glyph |=
20+4:14 glyph [
21+4:15 tight glyph =
22+4:16 tight name msg
23+4:20 name n
24+4:21 tight glyph =
25+4:22 tight aura @ud
26+4:25 tight glyph ]
27+4:27 name n
28+5:1 NEWLINE
29+5:1 glyph ++
30+5:4 name update-u
31+5:13 glyph (
32+5:14 tight name unface
33+5:21 name update
34+5:27 tight glyph )
35+6:1 NEWLINE
36+6:1 glyph ++
37+6:4 name direct
38+6:11 glyph (
39+6:12 tight name update-u
40+6:21 glyph [
41+6:22 tight lit %typed
42+6:29 str "x"
43+6:32 tight glyph ]
44+6:34 lit 1
45+6:35 tight glyph )
46+7:1 NEWLINE
47+7:1 glyph ++
48+7:4 name run
49+7:8 glyph |=
50+7:11 name f
51+7:12 tight glyph =
52+7:13 tight glyph $-(
53+7:16 tight glyph [
54+7:17 tight name msg
55+7:21 aura @ud
56+7:24 tight glyph ]
57+7:26 aura @ud
58+7:29 tight glyph )
59+7:31 glyph (
60+7:32 tight name f
61+7:34 glyph [
62+7:35 tight lit %sent
63+7:41 lit ~
64+7:42 tight glyph ]
65+7:44 lit 2
66+7:45 tight glyph )
67+8:1 NEWLINE
68+8:1 glyph ++
69+8:4 name ran
70+8:8 glyph (
71+8:9 tight name run
72+8:13 glyph (
73+8:14 tight name unface
74+8:21 name update
75+8:27 tight glyph )
76+8:28 tight glyph )
77+9:1 NEWLINE
78+9:1 glyph ++
79+9:4 name tagged
80+9:11 glyph ^-
81+9:14 name msg
82+9:18 glyph (
83+9:19 tight name unface
84+9:26 glyph [
85+9:27 tight lit %typed
86+9:34 str "x"
87+9:37 tight glyph ]
88+9:38 tight glyph )
89+9:39 NEWLINE
tests/golden/inline-unface-named-union/tree.txtnew file+46
@@ -0,0 +1,46 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %typed)
6+ (face 2:11 text (aura 2:16 @t)))
7+ (cell 3:3 (const 3:4 %sent) (const 3:10 ~))))
8+ (value 4:1 update
9+ (gate 4:11
10+ (cell 4:14
11+ (pun 4:15 msg)
12+ (face 4:20 n (aura 4:22 @ud)))
13+ (wing 4:27 n)))
14+ (value 5:1 update-u
15+ (group 5:13
16+ (call 5:14 (wing 5:14 unface) (wing 5:21 update))))
17+ (value 6:1 direct
18+ (group 6:11
19+ (call 6:12
20+ (wing 6:12 update-u)
21+ (tuple 6:21 (lit 6:22 %typed) (str 6:29 "x"))
22+ (lit 6:34 1))))
23+ (value 7:1 run
24+ (gate 7:8
25+ (face 7:11 f
26+ (fn 7:13
27+ (cell 7:16 (ref 7:17 msg) (aura 7:21 @ud))
28+ (aura 7:26 @ud)))
29+ (group 7:31
30+ (call 7:32
31+ (wing 7:32 f)
32+ (tuple 7:34 (lit 7:35 %sent) (lit 7:41 ~))
33+ (lit 7:44 2)))))
34+ (value 8:1 ran
35+ (group 8:8
36+ (call 8:9
37+ (wing 8:9 run)
38+ (group 8:13
39+ (call 8:14 (wing 8:14 unface) (wing 8:21 update))))))
40+ (value 9:1 tagged
41+ (cast 9:11
42+ (ref 9:14 msg)
43+ (group 9:18
44+ (call 9:19
45+ (wing 9:19 unface)
46+ (tuple 9:26 (lit 9:27 %typed) (str 9:34 "x")))))))
tests/golden/inline-unface-named-union/types.txtnew file+8
@@ -0,0 +1,8 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ update: $-([msg=msg n=@ud] @ud)
4+++ update-u: $-([msg @ud] @ud)
5+++ direct: @ud
6+++ run: $-($-([msg @ud] @ud) @ud)
7+++ ran: @ud
8+++ tagged: msg
tests/golden/inline-unface-records/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "`(unface e)` is `e` with every face removed from its type"
2+tests: A record passed where other labels are expected, which fails without unface; data fields then match by position, so swapped labels pass too.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-records/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-records/source.jibbnew file+8
@@ -0,0 +1,8 @@
1+++ pair-pq ^- [p=@t q=@ud] ["a" 1]
2+++ take-kv |= [k=@t v=@ud] v
3+++ labelled (take-kv pair-pq)
4+++ unfaced (take-kv (unface pair-pq))
5+++ hi-lo ^- [hi=@ud lo=@ud] [10 0]
6+++ want-lo-hi |= r=[lo=@ud hi=@ud] lo.r
7+++ swapped (want-lo-hi hi-lo)
8+++ by-position (want-lo-hi (unface hi-lo))
tests/golden/inline-unface-records/tokens.txtnew file+94
@@ -0,0 +1,94 @@
1+1:1 glyph ++
2+1:4 name pair-pq
3+1:12 glyph ^-
4+1:15 glyph [
5+1:16 tight name p
6+1:17 tight glyph =
7+1:18 tight aura @t
8+1:21 name q
9+1:22 tight glyph =
10+1:23 tight aura @ud
11+1:26 tight glyph ]
12+1:28 glyph [
13+1:29 tight str "a"
14+1:33 lit 1
15+1:34 tight glyph ]
16+2:1 NEWLINE
17+2:1 glyph ++
18+2:4 name take-kv
19+2:12 glyph |=
20+2:15 glyph [
21+2:16 tight name k
22+2:17 tight glyph =
23+2:18 tight aura @t
24+2:21 name v
25+2:22 tight glyph =
26+2:23 tight aura @ud
27+2:26 tight glyph ]
28+2:28 name v
29+3:1 NEWLINE
30+3:1 glyph ++
31+3:4 name labelled
32+3:13 glyph (
33+3:14 tight name take-kv
34+3:22 name pair-pq
35+3:29 tight glyph )
36+4:1 NEWLINE
37+4:1 glyph ++
38+4:4 name unfaced
39+4:12 glyph (
40+4:13 tight name take-kv
41+4:21 glyph (
42+4:22 tight name unface
43+4:29 name pair-pq
44+4:36 tight glyph )
45+4:37 tight glyph )
46+5:1 NEWLINE
47+5:1 glyph ++
48+5:4 name hi-lo
49+5:10 glyph ^-
50+5:13 glyph [
51+5:14 tight name hi
52+5:16 tight glyph =
53+5:17 tight aura @ud
54+5:21 name lo
55+5:23 tight glyph =
56+5:24 tight aura @ud
57+5:27 tight glyph ]
58+5:29 glyph [
59+5:30 tight lit 10
60+5:33 lit 0
61+5:34 tight glyph ]
62+6:1 NEWLINE
63+6:1 glyph ++
64+6:4 name want-lo-hi
65+6:15 glyph |=
66+6:18 name r
67+6:19 tight glyph =
68+6:20 tight glyph [
69+6:21 tight name lo
70+6:23 tight glyph =
71+6:24 tight aura @ud
72+6:28 name hi
73+6:30 tight glyph =
74+6:31 tight aura @ud
75+6:34 tight glyph ]
76+6:36 wing lo.r
77+7:1 NEWLINE
78+7:1 glyph ++
79+7:4 name swapped
80+7:12 glyph (
81+7:13 tight name want-lo-hi
82+7:24 name hi-lo
83+7:29 tight glyph )
84+8:1 NEWLINE
85+8:1 glyph ++
86+8:4 name by-position
87+8:16 glyph (
88+8:17 tight name want-lo-hi
89+8:28 glyph (
90+8:29 tight name unface
91+8:36 name hi-lo
92+8:41 tight glyph )
93+8:42 tight glyph )
94+8:43 NEWLINE
tests/golden/inline-unface-records/tree.txtnew file+44
@@ -0,0 +1,44 @@
1+(module
2+ (value 1:1 pair-pq
3+ (cast 1:12
4+ (cell 1:15
5+ (face 1:16 p (aura 1:18 @t))
6+ (face 1:21 q (aura 1:23 @ud)))
7+ (tuple 1:28 (str 1:29 "a") (lit 1:33 1))))
8+ (value 2:1 take-kv
9+ (gate 2:12
10+ (cell 2:15
11+ (face 2:16 k (aura 2:18 @t))
12+ (face 2:21 v (aura 2:23 @ud)))
13+ (wing 2:28 v)))
14+ (value 3:1 labelled
15+ (group 3:13
16+ (call 3:14 (wing 3:14 take-kv) (wing 3:22 pair-pq))))
17+ (value 4:1 unfaced
18+ (group 4:12
19+ (call 4:13
20+ (wing 4:13 take-kv)
21+ (group 4:21
22+ (call 4:22 (wing 4:22 unface) (wing 4:29 pair-pq))))))
23+ (value 5:1 hi-lo
24+ (cast 5:10
25+ (cell 5:13
26+ (face 5:14 hi (aura 5:17 @ud))
27+ (face 5:21 lo (aura 5:24 @ud)))
28+ (tuple 5:29 (lit 5:30 10) (lit 5:33 0))))
29+ (value 6:1 want-lo-hi
30+ (gate 6:15
31+ (face 6:18 r
32+ (cell 6:20
33+ (face 6:21 lo (aura 6:24 @ud))
34+ (face 6:28 hi (aura 6:31 @ud))))
35+ (wing 6:36 lo.r)))
36+ (value 7:1 swapped
37+ (group 7:12
38+ (call 7:13 (wing 7:13 want-lo-hi) (wing 7:24 hi-lo))))
39+ (value 8:1 by-position
40+ (group 8:16
41+ (call 8:17
42+ (wing 8:17 want-lo-hi)
43+ (group 8:28
44+ (call 8:29 (wing 8:29 unface) (wing 8:36 hi-lo)))))))
tests/golden/inline-unface-records/types.txtnew file+21
@@ -0,0 +1,21 @@
1+partial inference; module not checked
2+++ pair-pq: [p=@t q=@ud]
3+++ take-kv: $-([k=@t v=@ud] @ud)
4+++ labelled: call's sample and argument types do not unify
5+/tests/golden/inline-unface-records/source.jibb:3:14: called gate has type $-([k=@t v=@ud] @ud)
6+++ labelled (take-kv pair-pq)
7+ ^
8+/tests/golden/inline-unface-records/source.jibb:3:22: argument has type [p=@t q=@ud]
9+++ labelled (take-kv pair-pq)
10+ ^
11+++ unfaced: @ud
12+++ hi-lo: [hi=@ud lo=@ud]
13+++ want-lo-hi: $-([lo=@ud hi=@ud] @ud)
14+++ swapped: call's sample and argument types do not unify
15+/tests/golden/inline-unface-records/source.jibb:7:13: called gate has type $-([lo=@ud hi=@ud] @ud)
16+++ swapped (want-lo-hi hi-lo)
17+ ^
18+/tests/golden/inline-unface-records/source.jibb:7:24: argument has type [hi=@ud lo=@ud]
19+++ swapped (want-lo-hi hi-lo)
20+ ^
21+++ by-position: @ud
tests/golden/inline-unface-recursive/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "`(unface e)` is `e` with every face removed from its type"
2+tests: A ++ whose body is (unface |= …) is still a gate: it calls itself, two such gates call each other, and a local one recurses; each name has the unfaced type.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-recursive/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-recursive/source.jibbnew file+23
@@ -0,0 +1,23 @@
1+++ weld2 (unface
2+ |= [xs=(list A) ys=(list A)] ^- (list A)
3+ ?- xs
4+ ~ ys
5+ [item rest] [item (weld2 rest ys)]
6+++ joined (weld2 ~[1] ~[2])
7+++ even (unface
8+ |= n=@ud ^- ?
9+ ?- (eq n 0)
10+ %.y %.y
11+ %.n (odd (dec n))
12+++ odd (unface
13+ |= n=@ud ^- ?
14+ ?- (eq n 0)
15+ %.y %.n
16+ %.n (even (dec n))
17+++ outer |= n=@ud
18+ ++ count (unface
19+ |= [a=@ud b=@ud] ^- @ud
20+ ?- (eq a 0)
21+ %.y b
22+ %.n (count (dec a) b)
23+ (count n 1)
tests/golden/inline-unface-recursive/tokens.txtnew file+182
@@ -0,0 +1,182 @@
1+1:1 glyph ++
2+1:4 name weld2
3+1:10 glyph (
4+1:11 tight name unface
5+2:3 INDENT
6+2:3 glyph |=
7+2:6 glyph [
8+2:7 tight name xs
9+2:9 tight glyph =
10+2:10 tight glyph (
11+2:11 tight name list
12+2:16 tvar A
13+2:17 tight glyph )
14+2:19 name ys
15+2:21 tight glyph =
16+2:22 tight glyph (
17+2:23 tight name list
18+2:28 tvar A
19+2:29 tight glyph )
20+2:30 tight glyph ]
21+2:32 glyph ^-
22+2:35 glyph (
23+2:36 tight name list
24+2:41 tvar A
25+2:42 tight glyph )
26+3:5 INDENT
27+3:5 glyph ?-
28+3:8 name xs
29+4:7 INDENT
30+4:7 lit ~
31+4:9 name ys
32+5:7 NEWLINE
33+5:7 glyph [
34+5:8 tight name item
35+5:13 name rest
36+5:17 tight glyph ]
37+5:19 glyph [
38+5:20 tight name item
39+5:25 glyph (
40+5:26 tight name weld2
41+5:32 name rest
42+5:37 name ys
43+5:39 tight glyph )
44+5:40 tight glyph ]
45+6:1 DEDENT
46+6:1 DEDENT
47+6:1 DEDENT
48+6:1 NEWLINE
49+6:1 glyph ++
50+6:4 name joined
51+6:11 glyph (
52+6:12 tight name weld2
53+6:18 glyph ~[
54+6:20 tight lit 1
55+6:21 tight glyph ]
56+6:23 glyph ~[
57+6:25 tight lit 2
58+6:26 tight glyph ]
59+6:27 tight glyph )
60+7:1 NEWLINE
61+7:1 glyph ++
62+7:4 name even
63+7:9 glyph (
64+7:10 tight name unface
65+8:3 INDENT
66+8:3 glyph |=
67+8:6 name n
68+8:7 tight glyph =
69+8:8 tight aura @ud
70+8:12 glyph ^-
71+8:15 glyph ?
72+9:5 INDENT
73+9:5 glyph ?-
74+9:8 glyph (
75+9:9 tight name eq
76+9:12 name n
77+9:14 lit 0
78+9:15 tight glyph )
79+10:7 INDENT
80+10:7 lit %.y
81+10:11 lit %.y
82+11:7 NEWLINE
83+11:7 lit %.n
84+11:11 glyph (
85+11:12 tight name odd
86+11:16 glyph (
87+11:17 tight name dec
88+11:21 name n
89+11:22 tight glyph )
90+11:23 tight glyph )
91+12:1 DEDENT
92+12:1 DEDENT
93+12:1 DEDENT
94+12:1 NEWLINE
95+12:1 glyph ++
96+12:4 name odd
97+12:8 glyph (
98+12:9 tight name unface
99+13:3 INDENT
100+13:3 glyph |=
101+13:6 name n
102+13:7 tight glyph =
103+13:8 tight aura @ud
104+13:12 glyph ^-
105+13:15 glyph ?
106+14:5 INDENT
107+14:5 glyph ?-
108+14:8 glyph (
109+14:9 tight name eq
110+14:12 name n
111+14:14 lit 0
112+14:15 tight glyph )
113+15:7 INDENT
114+15:7 lit %.y
115+15:11 lit %.n
116+16:7 NEWLINE
117+16:7 lit %.n
118+16:11 glyph (
119+16:12 tight name even
120+16:17 glyph (
121+16:18 tight name dec
122+16:22 name n
123+16:23 tight glyph )
124+16:24 tight glyph )
125+17:1 DEDENT
126+17:1 DEDENT
127+17:1 DEDENT
128+17:1 NEWLINE
129+17:1 glyph ++
130+17:4 name outer
131+17:10 glyph |=
132+17:13 name n
133+17:14 tight glyph =
134+17:15 tight aura @ud
135+18:3 INDENT
136+18:3 glyph ++
137+18:6 name count
138+18:12 glyph (
139+18:13 tight name unface
140+19:5 INDENT
141+19:5 glyph |=
142+19:8 glyph [
143+19:9 tight name a
144+19:10 tight glyph =
145+19:11 tight aura @ud
146+19:15 name b
147+19:16 tight glyph =
148+19:17 tight aura @ud
149+19:20 tight glyph ]
150+19:22 glyph ^-
151+19:25 aura @ud
152+20:7 INDENT
153+20:7 glyph ?-
154+20:10 glyph (
155+20:11 tight name eq
156+20:14 name a
157+20:16 lit 0
158+20:17 tight glyph )
159+21:9 INDENT
160+21:9 lit %.y
161+21:13 name b
162+22:9 NEWLINE
163+22:9 lit %.n
164+22:13 glyph (
165+22:14 tight name count
166+22:20 glyph (
167+22:21 tight name dec
168+22:25 name a
169+22:26 tight glyph )
170+22:28 name b
171+22:29 tight glyph )
172+23:3 DEDENT
173+23:3 DEDENT
174+23:3 DEDENT
175+23:3 NEWLINE
176+23:3 glyph (
177+23:4 tight name count
178+23:10 name n
179+23:12 lit 1
180+23:13 tight glyph )
181+23:14 DEDENT
182+23:14 NEWLINE
tests/golden/inline-unface-recursive/tree.txtnew file+98
@@ -0,0 +1,98 @@
1+(module
2+ (value 1:1 weld2
3+ (group 1:10
4+ (call 1:11
5+ (wing 1:11 unface)
6+ (gate 2:3
7+ (cell 2:6
8+ (face 2:7 xs
9+ (apply 2:10 list (tvar 2:16 A)))
10+ (face 2:19 ys
11+ (apply 2:22 list (tvar 2:28 A))))
12+ (cast 2:32
13+ (apply 2:35 list (tvar 2:41 A))
14+ (body 3:5
15+ (branch 3:5
16+ (wing 3:8 xs)
17+ (arm 4:7 (lit 4:7 ~) (wing 4:9 ys))
18+ (arm 5:7
19+ (cell 5:7 (bind 5:8 item) (bind 5:13 rest))
20+ (tuple 5:19
21+ (wing 5:20 item)
22+ (group 5:25
23+ (call 5:26 (wing 5:26 weld2) (wing 5:32 rest) (wing 5:37 ys))))))))))))
24+ (value 6:1 joined
25+ (group 6:11
26+ (call 6:12
27+ (wing 6:12 weld2)
28+ (list 6:18 (lit 6:20 1))
29+ (list 6:23 (lit 6:25 2)))))
30+ (value 7:1 even
31+ (group 7:9
32+ (call 7:10
33+ (wing 7:10 unface)
34+ (gate 8:3
35+ (face 8:6 n (aura 8:8 @ud))
36+ (cast 8:12
37+ (flag 8:15)
38+ (body 9:5
39+ (branch 9:5
40+ (group 9:8
41+ (call 9:9 (wing 9:9 eq) (wing 9:12 n) (lit 9:14 0)))
42+ (arm 10:7 (lit 10:7 %.y) (lit 10:11 %.y))
43+ (arm 11:7
44+ (lit 11:7 %.n)
45+ (group 11:11
46+ (call 11:12
47+ (wing 11:12 odd)
48+ (group 11:16
49+ (call 11:17 (wing 11:17 dec) (wing 11:21 n)))))))))))))
50+ (value 12:1 odd
51+ (group 12:8
52+ (call 12:9
53+ (wing 12:9 unface)
54+ (gate 13:3
55+ (face 13:6 n (aura 13:8 @ud))
56+ (cast 13:12
57+ (flag 13:15)
58+ (body 14:5
59+ (branch 14:5
60+ (group 14:8
61+ (call 14:9 (wing 14:9 eq) (wing 14:12 n) (lit 14:14 0)))
62+ (arm 15:7 (lit 15:7 %.y) (lit 15:11 %.n))
63+ (arm 16:7
64+ (lit 16:7 %.n)
65+ (group 16:11
66+ (call 16:12
67+ (wing 16:12 even)
68+ (group 16:17
69+ (call 16:18 (wing 16:18 dec) (wing 16:22 n)))))))))))))
70+ (value 17:1 outer
71+ (gate 17:10
72+ (face 17:13 n (aura 17:15 @ud))
73+ (body 18:3
74+ (value 18:3 count
75+ (group 18:12
76+ (call 18:13
77+ (wing 18:13 unface)
78+ (gate 19:5
79+ (cell 19:8
80+ (face 19:9 a (aura 19:11 @ud))
81+ (face 19:15 b (aura 19:17 @ud)))
82+ (cast 19:22
83+ (aura 19:25 @ud)
84+ (body 20:7
85+ (branch 20:7
86+ (group 20:10
87+ (call 20:11 (wing 20:11 eq) (wing 20:14 a) (lit 20:16 0)))
88+ (arm 21:9 (lit 21:9 %.y) (wing 21:13 b))
89+ (arm 22:9
90+ (lit 22:9 %.n)
91+ (group 22:13
92+ (call 22:14
93+ (wing 22:14 count)
94+ (group 22:20
95+ (call 22:21 (wing 22:21 dec) (wing 22:25 a)))
96+ (wing 22:28 b)))))))))))
97+ (group 23:3
98+ (call 23:4 (wing 23:4 count) (wing 23:10 n) (lit 23:12 1)))))))
tests/golden/inline-unface-recursive/types.txtnew file+6
@@ -0,0 +1,6 @@
1+partial inference; module not checked
2+++ weld2: $-([(list A) (list A)] (list A))
3+++ joined: (list @ud)
4+++ even: $-(@ud ?)
5+++ odd: $-(@ud ?)
6+++ outer: $-(@ud @ud)
tests/golden/inline-unface-reserved-import/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Modules: "`proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold"
2+tests: A Jibb import face named unface is rejected.
3+expect: parses
4+expect-types: a partial inference report: the module has conflicting names
tests/golden/inline-unface-reserved-import/module-trees.txtnew file+6
@@ -0,0 +1,6 @@
1+/ui/lib.jibb
2+(module
3+ (value 1:1 identity
4+ (gate 1:13
5+ (face 1:16 x (aura 1:18 @t))
6+ (wing 1:21 x))))
tests/golden/inline-unface-reserved-import/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/inline-unface-reserved-import/modules/ui/lib.jibbnew file+1
@@ -0,0 +1 @@
1+++ identity |= x=@t x
tests/golden/inline-unface-reserved-import/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+/= unface /ui/lib
2+++ okay "ok"
tests/golden/inline-unface-reserved-import/tokens.txtnew file+11
@@ -0,0 +1,11 @@
1+1:1 glyph /=
2+1:4 name unface
3+1:11 glyph /
4+1:12 tight knot ui
5+1:14 tight glyph /
6+1:15 tight knot lib
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name okay
10+2:9 str "ok"
11+2:13 NEWLINE
tests/golden/inline-unface-reserved-import/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+(module
2+ (jibb 1:1 unface /ui/lib)
3+ (value 2:1 okay (str 2:9 "ok")))
tests/golden/inline-unface-reserved-import/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+module has conflicting names
tests/golden/inline-unface-reserved-local/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Modules: "`proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold"
2+tests: A local value named unface is rejected.
3+expect: parses
4+expect-types: a partial inference report: the module has conflicting names
tests/golden/inline-unface-reserved-local/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-reserved-local/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+++ okay
2+ ++ unface |= x=@t x
3+ "ok"
tests/golden/inline-unface-reserved-local/tokens.txtnew file+14
@@ -0,0 +1,14 @@
1+1:1 glyph ++
2+1:4 name okay
3+2:3 INDENT
4+2:3 glyph ++
5+2:6 name unface
6+2:13 glyph |=
7+2:16 name x
8+2:17 tight glyph =
9+2:18 tight aura @t
10+2:21 name x
11+3:3 NEWLINE
12+3:3 str "ok"
13+3:7 DEDENT
14+3:7 NEWLINE
tests/golden/inline-unface-reserved-local/tree.txtnew file+8
@@ -0,0 +1,8 @@
1+(module
2+ (value 1:1 okay
3+ (body 2:3
4+ (value 2:3 unface
5+ (gate 2:13
6+ (face 2:16 x (aura 2:18 @t))
7+ (wing 2:21 x)))
8+ (str 3:3 "ok"))))
tests/golden/inline-unface-reserved-local/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+module has conflicting names
tests/golden/inline-unface-reserved-mold/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Modules: "`proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold"
2+tests: A mold named unface is rejected, even unused.
3+expect: parses
4+expect-types: a partial inference report: the module has conflicting names
tests/golden/inline-unface-reserved-mold/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-reserved-mold/source.jibbnew file+2
@@ -0,0 +1,2 @@
1++$ unface @t
2+++ okay "ok"
tests/golden/inline-unface-reserved-mold/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph +$
2+1:4 name unface
3+1:11 aura @t
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name okay
7+2:9 str "ok"
8+2:13 NEWLINE
tests/golden/inline-unface-reserved-mold/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+(module
2+ (mold 1:1 unface (aura 1:11 @t))
3+ (value 2:1 okay (str 2:9 "ok")))
tests/golden/inline-unface-reserved-mold/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+module has conflicting names
tests/golden/inline-unface-reserved-no-prelude/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Modules: "`proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold"
2+tests: Without the prelude, the report names the reserved names.
3+expect: parses
4+expect-types: the report says the module has a reserved name
tests/golden/inline-unface-reserved-no-prelude/source.jibbnew file+2
@@ -0,0 +1,2 @@
1++$ unface @t
2+++ okay "ok"
tests/golden/inline-unface-reserved-no-prelude/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph +$
2+1:4 name unface
3+1:11 aura @t
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name okay
7+2:9 str "ok"
8+2:13 NEWLINE
tests/golden/inline-unface-reserved-no-prelude/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+(module
2+ (mold 1:1 unface (aura 1:11 @t))
3+ (value 2:1 okay (str 2:9 "ok")))
tests/golden/inline-unface-reserved-no-prelude/types.txtnew file+1
@@ -0,0 +1 @@
1+module has a reserved proj or unface name
tests/golden/inline-unface-reserved-pattern/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Modules: "`proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold"
2+tests: A branch pattern cannot bind unface.
3+expect: parses
4+expect-types: a partial inference report: the module has conflicting names
tests/golden/inline-unface-reserved-pattern/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-reserved-pattern/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+++ okay |= x=[@t @p]
2+ ?- x
3+ [unface other] other
tests/golden/inline-unface-reserved-pattern/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name okay
3+1:9 glyph |=
4+1:12 name x
5+1:13 tight glyph =
6+1:14 tight glyph [
7+1:15 tight aura @t
8+1:18 aura @p
9+1:20 tight glyph ]
10+2:3 INDENT
11+2:3 glyph ?-
12+2:6 name x
13+3:5 INDENT
14+3:5 glyph [
15+3:6 tight name unface
16+3:13 name other
17+3:18 tight glyph ]
18+3:20 name other
19+3:25 DEDENT
20+3:25 DEDENT
21+3:25 NEWLINE
tests/golden/inline-unface-reserved-pattern/tree.txtnew file+11
@@ -0,0 +1,11 @@
1+(module
2+ (value 1:1 okay
3+ (gate 1:9
4+ (face 1:12 x
5+ (cell 1:14 (aura 1:15 @t) (aura 1:18 @p)))
6+ (body 2:3
7+ (branch 2:3
8+ (wing 2:6 x)
9+ (arm 3:5
10+ (cell 3:5 (bind 3:6 unface) (bind 3:13 other))
11+ (wing 3:20 other)))))))
tests/golden/inline-unface-reserved-pattern/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+module has conflicting names
tests/golden/inline-unface-reserved-positive/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Modules: "`proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold"
2+tests: A field label, a tag and a longer name spelled with unface stay free, beside a normal unface call.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/inline-unface-reserved-positive/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-reserved-positive/source.jibbnew file+6
@@ -0,0 +1,6 @@
1++$ action
2+ %unface
3+ %other
4+++ unfaced |= x=[unface=@t other=@p] unface.x
5+++ tag ^- action %unface
6+++ plain (unface unfaced)
tests/golden/inline-unface-reserved-positive/tokens.txtnew file+36
@@ -0,0 +1,36 @@
1+1:1 glyph +$
2+1:4 name action
3+2:3 INDENT
4+2:3 lit %unface
5+3:3 NEWLINE
6+3:3 lit %other
7+4:1 DEDENT
8+4:1 NEWLINE
9+4:1 glyph ++
10+4:4 name unfaced
11+4:12 glyph |=
12+4:15 name x
13+4:16 tight glyph =
14+4:17 tight glyph [
15+4:18 tight name unface
16+4:24 tight glyph =
17+4:25 tight aura @t
18+4:28 name other
19+4:33 tight glyph =
20+4:34 tight aura @p
21+4:36 tight glyph ]
22+4:38 wing unface.x
23+5:1 NEWLINE
24+5:1 glyph ++
25+5:4 name tag
26+5:8 glyph ^-
27+5:11 name action
28+5:18 lit %unface
29+6:1 NEWLINE
30+6:1 glyph ++
31+6:4 name plain
32+6:10 glyph (
33+6:11 tight name unface
34+6:18 name unfaced
35+6:25 tight glyph )
36+6:26 NEWLINE
tests/golden/inline-unface-reserved-positive/tree.txtnew file+15
@@ -0,0 +1,15 @@
1+(module
2+ (mold 1:1 action
3+ (union 2:3 (const 2:3 %unface) (const 3:3 %other)))
4+ (value 4:1 unfaced
5+ (gate 4:12
6+ (face 4:15 x
7+ (cell 4:17
8+ (face 4:18 unface (aura 4:25 @t))
9+ (face 4:28 other (aura 4:34 @p))))
10+ (wing 4:38 unface.x)))
11+ (value 5:1 tag
12+ (cast 5:8 (ref 5:11 action) (lit 5:18 %unface)))
13+ (value 6:1 plain
14+ (group 6:10
15+ (call 6:11 (wing 6:11 unface) (wing 6:18 unfaced)))))
tests/golden/inline-unface-reserved-positive/types.txtnew file+5
@@ -0,0 +1,5 @@
1+partial inference; module not checked
2++$ action: cases proven disjoint; mold not checked
3+++ unfaced: $-([unface=@t other=@p] @t)
4+++ tag: action
5+++ plain: $-([@t @p] @t)
tests/golden/inline-unface-reserved-sample/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Modules: "`proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold"
2+tests: A gate sample cannot bind unface, alone or inside a cell.
3+expect: parses
4+expect-types: a partial inference report: the module has conflicting names
tests/golden/inline-unface-reserved-sample/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-reserved-sample/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ okay |= [unface=@t other=@p] other
tests/golden/inline-unface-reserved-sample/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph ++
2+1:4 name okay
3+1:9 glyph |=
4+1:12 glyph [
5+1:13 tight name unface
6+1:19 tight glyph =
7+1:20 tight aura @t
8+1:23 name other
9+1:28 tight glyph =
10+1:29 tight aura @p
11+1:31 tight glyph ]
12+1:33 name other
13+1:38 NEWLINE
tests/golden/inline-unface-reserved-sample/tree.txtnew file+7
@@ -0,0 +1,7 @@
1+(module
2+ (value 1:1 okay
3+ (gate 1:9
4+ (cell 1:12
5+ (face 1:13 unface (aura 1:20 @t))
6+ (face 1:23 other (aura 1:29 @p)))
7+ (wing 1:33 other))))
tests/golden/inline-unface-reserved-sample/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+module has conflicting names
tests/golden/inline-unface-reserved-value/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Modules: "`proj` and `unface` are reserved: no module can define, import or bind either, as a value or a mold"
2+tests: A top-level value named unface is rejected.
3+expect: parses
4+expect-types: a partial inference report: the module has conflicting names
tests/golden/inline-unface-reserved-value/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-reserved-value/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+++ unface |= x=@t x
2+++ okay "ok"
tests/golden/inline-unface-reserved-value/tokens.txtnew file+12
@@ -0,0 +1,12 @@
1+1:1 glyph ++
2+1:4 name unface
3+1:11 glyph |=
4+1:14 name x
5+1:15 tight glyph =
6+1:16 tight aura @t
7+1:19 name x
8+2:1 NEWLINE
9+2:1 glyph ++
10+2:4 name okay
11+2:9 str "ok"
12+2:13 NEWLINE
tests/golden/inline-unface-reserved-value/tree.txtnew file+6
@@ -0,0 +1,6 @@
1+(module
2+ (value 1:1 unface
3+ (gate 1:11
4+ (face 1:14 x (aura 1:16 @t))
5+ (wing 1:19 x)))
6+ (value 2:1 okay (str 2:9 "ok")))
tests/golden/inline-unface-reserved-value/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+module has conflicting names
tests/golden/inline-unface-unknown/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "Like `proj`, it is an operation the checker handles by type, not a gate"
2+tests: unface on a type not yet known, a sample with no mold, would wait as wing access does; the partial checker reports it as unsupported, as it does field access, and a sample with a mold infers.
3+expect: parses
4+expect-types: a partial inference report: the untyped sample is unsupported
tests/golden/inline-unface-unknown/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-unknown/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+++ later |= f (unface f)
2+++ get-label |= r label.r
3+++ known |= f=$-([a=@ud b=@ud] ?) (unface f)
tests/golden/inline-unface-unknown/tokens.txtnew file+36
@@ -0,0 +1,36 @@
1+1:1 glyph ++
2+1:4 name later
3+1:10 glyph |=
4+1:13 name f
5+1:15 glyph (
6+1:16 tight name unface
7+1:23 name f
8+1:24 tight glyph )
9+2:1 NEWLINE
10+2:1 glyph ++
11+2:4 name get-label
12+2:14 glyph |=
13+2:17 name r
14+2:19 wing label.r
15+3:1 NEWLINE
16+3:1 glyph ++
17+3:4 name known
18+3:10 glyph |=
19+3:13 name f
20+3:14 tight glyph =
21+3:15 tight glyph $-(
22+3:18 tight glyph [
23+3:19 tight name a
24+3:20 tight glyph =
25+3:21 tight aura @ud
26+3:25 name b
27+3:26 tight glyph =
28+3:27 tight aura @ud
29+3:30 tight glyph ]
30+3:32 glyph ?
31+3:33 tight glyph )
32+3:35 glyph (
33+3:36 tight name unface
34+3:43 name f
35+3:44 tight glyph )
36+3:45 NEWLINE
tests/golden/inline-unface-unknown/tree.txtnew file+18
@@ -0,0 +1,18 @@
1+(module
2+ (value 1:1 later
3+ (gate 1:10
4+ (bind 1:13 f)
5+ (group 1:15
6+ (call 1:16 (wing 1:16 unface) (wing 1:23 f)))))
7+ (value 2:1 get-label
8+ (gate 2:14 (bind 2:17 r) (wing 2:19 label.r)))
9+ (value 3:1 known
10+ (gate 3:10
11+ (face 3:13 f
12+ (fn 3:15
13+ (cell 3:18
14+ (face 3:19 a (aura 3:21 @ud))
15+ (face 3:25 b (aura 3:27 @ud)))
16+ (flag 3:32)))
17+ (group 3:35
18+ (call 3:36 (wing 3:36 unface) (wing 3:43 f))))))
tests/golden/inline-unface-unknown/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2+++ later: unface on a type not yet known is not supported by partial inference
3+++ get-label: field is not available to partial inference
4+++ known: $-($-([a=@ud b=@ud] ?) $-([@ud @ud] ?))
tests/golden/inline-unface-value-bad/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: docs/spec/grammar.md, Expressions, Unface: "Like `proj`, it is an operation the checker handles by type, not a gate"
2+tests: unface written where a value goes, alone or as a gate's argument, is an error that suggests a lambda; the lambda itself hits the partial checker's gap for a sample whose type the call fixes, and a typed sample infers.
3+expect: parses
4+expect-types: a partial inference report: the bare uses are errors at the name, and the untyped lambda is unsupported
tests/golden/inline-unface-value-bad/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use source-backed prelude.
tests/golden/inline-unface-value-bad/source.jibbnew file+6
@@ -0,0 +1,6 @@
1+++ lt-a |= [a=@ud b=@ud] (gth b a)
2+++ gates ~[lt-a]
3+++ alias unface
4+++ mapped (turn gates unface)
5+++ wrapped (turn gates |=(g (unface g)))
6+++ typed (turn gates |=(g=$-([a=@ud b=@ud] ?) (unface g)))
tests/golden/inline-unface-value-bad/tokens.txtnew file+75
@@ -0,0 +1,75 @@
1+1:1 glyph ++
2+1:4 name lt-a
3+1:9 glyph |=
4+1:12 glyph [
5+1:13 tight name a
6+1:14 tight glyph =
7+1:15 tight aura @ud
8+1:19 name b
9+1:20 tight glyph =
10+1:21 tight aura @ud
11+1:24 tight glyph ]
12+1:26 glyph (
13+1:27 tight name gth
14+1:31 name b
15+1:33 name a
16+1:34 tight glyph )
17+2:1 NEWLINE
18+2:1 glyph ++
19+2:4 name gates
20+2:10 glyph ~[
21+2:12 tight name lt-a
22+2:16 tight glyph ]
23+3:1 NEWLINE
24+3:1 glyph ++
25+3:4 name alias
26+3:10 name unface
27+4:1 NEWLINE
28+4:1 glyph ++
29+4:4 name mapped
30+4:11 glyph (
31+4:12 tight name turn
32+4:17 name gates
33+4:23 name unface
34+4:29 tight glyph )
35+5:1 NEWLINE
36+5:1 glyph ++
37+5:4 name wrapped
38+5:12 glyph (
39+5:13 tight name turn
40+5:18 name gates
41+5:24 glyph |=(
42+5:27 tight name g
43+5:29 glyph (
44+5:30 tight name unface
45+5:37 name g
46+5:38 tight glyph )
47+5:39 tight glyph )
48+5:40 tight glyph )
49+6:1 NEWLINE
50+6:1 glyph ++
51+6:4 name typed
52+6:10 glyph (
53+6:11 tight name turn
54+6:16 name gates
55+6:22 glyph |=(
56+6:25 tight name g
57+6:26 tight glyph =
58+6:27 tight glyph $-(
59+6:30 tight glyph [
60+6:31 tight name a
61+6:32 tight glyph =
62+6:33 tight aura @ud
63+6:37 name b
64+6:38 tight glyph =
65+6:39 tight aura @ud
66+6:42 tight glyph ]
67+6:44 glyph ?
68+6:45 tight glyph )
69+6:47 glyph (
70+6:48 tight name unface
71+6:55 name g
72+6:56 tight glyph )
73+6:57 tight glyph )
74+6:58 tight glyph )
75+6:59 NEWLINE
tests/golden/inline-unface-value-bad/tree.txtnew file+37
@@ -0,0 +1,37 @@
1+(module
2+ (value 1:1 lt-a
3+ (gate 1:9
4+ (cell 1:12
5+ (face 1:13 a (aura 1:15 @ud))
6+ (face 1:19 b (aura 1:21 @ud)))
7+ (group 1:26
8+ (call 1:27 (wing 1:27 gth) (wing 1:31 b) (wing 1:33 a)))))
9+ (value 2:1 gates
10+ (list 2:10 (wing 2:12 lt-a)))
11+ (value 3:1 alias (wing 3:10 unface))
12+ (value 4:1 mapped
13+ (group 4:11
14+ (call 4:12 (wing 4:12 turn) (wing 4:17 gates) (wing 4:23 unface))))
15+ (value 5:1 wrapped
16+ (group 5:12
17+ (call 5:13
18+ (wing 5:13 turn)
19+ (wing 5:18 gates)
20+ (gate-wide 5:24
21+ (bind 5:27 g)
22+ (group 5:29
23+ (call 5:30 (wing 5:30 unface) (wing 5:37 g)))))))
24+ (value 6:1 typed
25+ (group 6:10
26+ (call 6:11
27+ (wing 6:11 turn)
28+ (wing 6:16 gates)
29+ (gate-wide 6:22
30+ (face 6:25 g
31+ (fn 6:27
32+ (cell 6:30
33+ (face 6:31 a (aura 6:33 @ud))
34+ (face 6:37 b (aura 6:39 @ud)))
35+ (flag 6:44)))
36+ (group 6:47
37+ (call 6:48 (wing 6:48 unface) (wing 6:55 g))))))))
tests/golden/inline-unface-value-bad/types.txtnew file+13
@@ -0,0 +1,13 @@
1+partial inference; module not checked
2+++ lt-a: $-([a=@ud b=@ud] ?)
3+++ gates: (list $-([a=@ud b=@ud] ?))
4+++ alias: unface is not a value; write |=(g (unface g))
5+/tests/golden/inline-unface-value-bad/source.jibb:3:10: unface used as a value
6+++ alias unface
7+ ^
8+++ mapped: unface is not a value; write |=(g (unface g))
9+/tests/golden/inline-unface-value-bad/source.jibb:4:23: unface used as a value
10+++ mapped (turn gates unface)
11+ ^
12+++ wrapped: unface on a type not yet known is not supported by partial inference
13+++ typed: (list $-([@ud @ud] ?))
tests/golden/lex-body-rest-bad-1/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a local definition's own expression, a gate whose body would be the line below at the same depth
3+expect: error at 3:3 — a definition's own expression never takes the rest of a body, so the gate needs its body on its line or deeper; line 3 is at the same depth
tests/golden/lex-body-rest-bad-1/source.jibbnew file+4
@@ -0,0 +1,4 @@
1+++ f |= x=@ud
2+ ++ inner |= y=@ud
3+ (add y 1)
4+ (inner x)
tests/golden/lex-body-rest-bad-1/tokens.txtnew file+26
@@ -0,0 +1,26 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 glyph ++
9+2:6 name inner
10+2:12 glyph |=
11+2:15 name y
12+2:16 tight glyph =
13+2:17 tight aura @ud
14+3:3 NEWLINE
15+3:3 glyph (
16+3:4 tight name add
17+3:8 name y
18+3:10 lit 1
19+3:11 tight glyph )
20+4:3 NEWLINE
21+4:3 glyph (
22+4:4 tight name inner
23+4:10 name x
24+4:11 tight glyph )
25+4:12 DEDENT
26+4:12 NEWLINE
tests/golden/lex-body-rest-bad-1/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-1/source.jibb:3:3: expected an expression, or a body on deeper lines, found a line at the same depth
2+ (add y 1)
3+ ^
tests/golden/lex-body-rest-bad-10/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: a `?-` with one arm deeper and the next at its own depth, on the final line of a cast's rest
3+expect: error at 5:3 — a ?- takes all its arms deeper or all at its own depth, and this one's first arm is deeper, so the hint says the next goes there too
tests/golden/lex-body-rest-bad-10/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= x=?
2+ ^- @ud
3+ ?- x
4+ %.y 1
5+ %.n 2
tests/golden/lex-body-rest-bad-10/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ^-
9+2:6 aura @ud
10+3:3 NEWLINE
11+3:3 glyph ?-
12+3:6 name x
13+4:5 INDENT
14+4:5 lit %.y
15+4:9 lit 1
16+5:3 DEDENT
17+5:3 NEWLINE
18+5:3 lit %.n
19+5:7 lit 2
20+5:8 DEDENT
21+5:8 NEWLINE
tests/golden/lex-body-rest-bad-10/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-10/source.jibb:5:3: expected the end of the body, found a line at the same depth; this `?-`'s arms are on deeper lines, so this one goes there too
2+ %.n 2
3+ ^
tests/golden/lex-body-rest-bad-11/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: a `?-` with one arm at its own depth and the next deeper
3+expect: error at 4:5 — a ?- takes all its arms deeper or all at its own depth; after an arm at its depth that ends its line, a deeper line goes to nothing
tests/golden/lex-body-rest-bad-11/source.jibbnew file+4
@@ -0,0 +1,4 @@
1+++ f |= x=?
2+ ?- x
3+ %.y 1
4+ %.n 2
tests/golden/lex-body-rest-bad-11/tokens.txtnew file+18
@@ -0,0 +1,18 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name x
10+3:3 NEWLINE
11+3:3 lit %.y
12+3:7 lit 1
13+4:5 INDENT
14+4:5 lit %.n
15+4:9 lit 2
16+4:10 DEDENT
17+4:10 DEDENT
18+4:10 NEWLINE
tests/golden/lex-body-rest-bad-11/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-11/source.jibb:4:5: expected the end of the line, found a deeper line; only a bracket open at the end of a line, or a rune's body, takes deeper lines
2+ %.n 2
3+ ^
tests/golden/lex-body-rest-bad-12/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: a local definition after a `?-`'s arms at its depth
3+expect: error at 5:3 — a line at the arms' depth is the next arm, and a definition is no pattern; the hint says a body's local definitions come first
tests/golden/lex-body-rest-bad-12/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= x=?
2+ ?- x
3+ %.y 1
4+ %.n 2
5+ ++ g 3
tests/golden/lex-body-rest-bad-12/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name x
10+3:3 NEWLINE
11+3:3 lit %.y
12+3:7 lit 1
13+4:3 NEWLINE
14+4:3 lit %.n
15+4:7 lit 2
16+5:3 NEWLINE
17+5:3 glyph ++
18+5:6 name g
19+5:8 lit 3
20+5:9 DEDENT
21+5:9 NEWLINE
tests/golden/lex-body-rest-bad-12/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-12/source.jibb:5:3: expected a pattern, found `++`; a body's local definitions come before its final expression
2+ ++ g 3
3+ ^
tests/golden/lex-body-rest-bad-13/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: a trace where an arm of a `?-` with its arms at its depth goes
3+expect: error at 3:4 — a line at the arms' depth is an arm, and `~&` is no pattern; the error points just past the ~, which alone is the null pattern, and the hint says a trace goes in the arm's body
tests/golden/lex-body-rest-bad-13/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= x=?
2+ ?- x
3+ ~& x
4+ %.y 1
5+ %.n 2
tests/golden/lex-body-rest-bad-13/tokens.txtnew file+20
@@ -0,0 +1,20 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name x
10+3:3 NEWLINE
11+3:3 glyph ~&
12+3:6 name x
13+4:3 NEWLINE
14+4:3 lit %.y
15+4:7 lit 1
16+5:3 NEWLINE
17+5:3 lit %.n
18+5:7 lit 2
19+5:8 DEDENT
20+5:8 NEWLINE
tests/golden/lex-body-rest-bad-13/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-13/source.jibb:3:4: expected a pattern, found `~&`; a trace or cast goes in the arm's body
2+ ~& x
3+ ^
tests/golden/lex-body-rest-bad-14/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: a cast where an arm of a `?-` with its arms at its depth goes
3+expect: error at 4:3 — a line at the arms' depth is an arm, and `^-` is no pattern; the hint says a cast goes in the arm's body
tests/golden/lex-body-rest-bad-14/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= x=?
2+ ?- x
3+ %.y 1
4+ ^- @ud
5+ %.n 2
tests/golden/lex-body-rest-bad-14/tokens.txtnew file+20
@@ -0,0 +1,20 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name x
10+3:3 NEWLINE
11+3:3 lit %.y
12+3:7 lit 1
13+4:3 NEWLINE
14+4:3 glyph ^-
15+4:6 aura @ud
16+5:3 NEWLINE
17+5:3 lit %.n
18+5:7 lit 2
19+5:8 DEDENT
20+5:8 NEWLINE
tests/golden/lex-body-rest-bad-14/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-14/source.jibb:4:3: expected a pattern, found `^-`; a trace or cast goes in the arm's body
2+ ^- @ud
3+ ^
tests/golden/lex-body-rest-bad-15/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: Hoon's closer `==` at the column of a `?-` whose arms are at its depth
3+expect: error at 5:3 — the line is read as an arm, and the lexer's message about `==` says more than "expected a pattern"
tests/golden/lex-body-rest-bad-15/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= x=?
2+ ?- x
3+ %.y 1
4+ %.n 2
5+ ==
tests/golden/lex-body-rest-bad-15/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-15/source.jibb:5:4: the closer `==` is left out: indentation covers it
2+ ==
3+ ^
tests/golden/lex-body-rest-bad-15/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-15/source.jibb:5:3: expected a pattern, found `=`; the closer `==` is left out: indentation covers it
2+ ==
3+ ^
tests/golden/lex-body-rest-bad-16/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a cast after a `(` opened earlier on its line, alone there, with its expression on the next line at the same depth
3+expect: error at 3:3 — inside the ( no rune takes the lines after it, so the cast needs its expression on its line or deeper
tests/golden/lex-body-rest-bad-16/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+++ f |= x=@ud
2+ (^- @ud
3+ x)
tests/golden/lex-body-rest-bad-16/tokens.txtnew file+15
@@ -0,0 +1,15 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 glyph (
9+2:4 tight glyph ^-
10+2:7 aura @ud
11+3:3 NEWLINE
12+3:3 name x
13+3:4 tight glyph )
14+3:5 DEDENT
15+3:5 NEWLINE
tests/golden/lex-body-rest-bad-16/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-16/source.jibb:3:3: expected an expression, or a body on deeper lines, found a line at the same depth
2+ x)
3+ ^
tests/golden/lex-body-rest-bad-2/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a `?-` on an arm's line, inside a `?-` whose arms are at its depth
3+expect: error at 4:3 — a ?- on an arm's line keeps its arms deeper, since the next line at the arm's depth is the outer ?-'s next arm
tests/golden/lex-body-rest-bad-2/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= p=[? ?]
2+ ?- p
3+ [a b] ?- a
4+ %.y 1
5+ %.n 2
tests/golden/lex-body-rest-bad-2/tokens.txtnew file+27
@@ -0,0 +1,27 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name p
5+1:10 tight glyph =
6+1:11 tight glyph [
7+1:12 tight glyph ?
8+1:14 glyph ?
9+1:15 tight glyph ]
10+2:3 INDENT
11+2:3 glyph ?-
12+2:6 name p
13+3:3 NEWLINE
14+3:3 glyph [
15+3:4 tight name a
16+3:6 name b
17+3:7 tight glyph ]
18+3:9 glyph ?-
19+3:12 name a
20+4:3 NEWLINE
21+4:3 lit %.y
22+4:7 lit 1
23+5:3 NEWLINE
24+5:3 lit %.n
25+5:7 lit 2
26+5:8 DEDENT
27+5:8 NEWLINE
tests/golden/lex-body-rest-bad-2/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-2/source.jibb:4:3: expected `?-`'s arms on deeper lines, found a line at the same depth
2+ %.y 1
3+ ^
tests/golden/lex-body-rest-bad-3/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a `?-` that ends a chain on one line, after `^- @ud`, with its arms at the line's depth
3+expect: error at 3:3 — only a ?- that begins a body's final line takes its arms at its depth; after a rune on the line its arms go deeper
tests/golden/lex-body-rest-bad-3/source.jibbnew file+4
@@ -0,0 +1,4 @@
1+++ f |= x=?
2+ ^- @ud ?- x
3+ %.y 1
4+ %.n 2
tests/golden/lex-body-rest-bad-3/tokens.txtnew file+19
@@ -0,0 +1,19 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ^-
9+2:6 aura @ud
10+2:10 glyph ?-
11+2:13 name x
12+3:3 NEWLINE
13+3:3 lit %.y
14+3:7 lit 1
15+4:3 NEWLINE
16+4:3 lit %.n
17+4:7 lit 2
18+4:8 DEDENT
19+4:8 NEWLINE
tests/golden/lex-body-rest-bad-3/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-3/source.jibb:3:3: expected `?-`'s arms on deeper lines, found a line at the same depth
2+ %.y 1
3+ ^
tests/golden/lex-body-rest-bad-4/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a `?-` that is a local definition's own expression, with its arms at the definition's depth
3+expect: error at 3:3 — a definition's own expression never takes the lines after it at its depth; they would swallow the body's later lines
tests/golden/lex-body-rest-bad-4/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= x=?
2+ ++ g ?- x
3+ %.y 1
4+ %.n 2
5+ g
tests/golden/lex-body-rest-bad-4/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ++
9+2:6 name g
10+2:8 glyph ?-
11+2:11 name x
12+3:3 NEWLINE
13+3:3 lit %.y
14+3:7 lit 1
15+4:3 NEWLINE
16+4:3 lit %.n
17+4:7 lit 2
18+5:3 NEWLINE
19+5:3 name g
20+5:4 DEDENT
21+5:4 NEWLINE
tests/golden/lex-body-rest-bad-4/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-4/source.jibb:3:3: expected `?-`'s arms on deeper lines, found a line at the same depth
2+ %.y 1
3+ ^
tests/golden/lex-body-rest-bad-5/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a `?-` on a line of an open bracket, with its arms at its depth
3+expect: error at 4:5 — on an open bracket's line the next line at its depth is the bracket's next item, so the ?-'s arms go deeper
tests/golden/lex-body-rest-bad-5/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= x=?
2+ ~[
3+ ?- x
4+ %.y 1
5+ %.n 2
tests/golden/lex-body-rest-bad-5/tokens.txtnew file+20
@@ -0,0 +1,20 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ~[
9+3:5 INDENT
10+3:5 glyph ?-
11+3:8 name x
12+4:5 NEWLINE
13+4:5 lit %.y
14+4:9 lit 1
15+5:5 NEWLINE
16+5:5 lit %.n
17+5:9 lit 2
18+5:10 DEDENT
19+5:10 DEDENT
20+5:10 NEWLINE
tests/golden/lex-body-rest-bad-5/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-5/source.jibb:4:5: expected `?-`'s arms on deeper lines, found a line at the same depth
2+ %.y 1
3+ ^
tests/golden/lex-body-rest-bad-6/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a cast alone on a line of an open bracket, with its expression on the next line at the same depth
3+expect: error at 4:5 — on an open bracket's line no rune takes the lines after it, so the cast needs its expression on its line or deeper
tests/golden/lex-body-rest-bad-6/source.jibbnew file+4
@@ -0,0 +1,4 @@
1+++ f |= x=@ud
2+ ~[
3+ ^- @ud
4+ x
tests/golden/lex-body-rest-bad-6/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 glyph ~[
9+3:5 INDENT
10+3:5 glyph ^-
11+3:8 aura @ud
12+4:5 NEWLINE
13+4:5 name x
14+4:6 DEDENT
15+4:6 DEDENT
16+4:6 NEWLINE
tests/golden/lex-body-rest-bad-6/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-6/source.jibb:4:5: expected an expression, or a body on deeper lines, found a line at the same depth
2+ x
3+ ^
tests/golden/lex-body-rest-bad-7/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a `?-` whose subject leaves a bracket open, taking the deeper lines, with its arms at the `?-`'s depth after them
3+expect: error at 2:11, the end of line 2 — the subject's ( took the deeper lines, so the line doesn't end where the arms go, and no later line can give the ?- its arms
tests/golden/lex-body-rest-bad-7/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ f |= x=?
2+ ?- (eq x
3+ %.y
4+ %.y 1
5+ %.n 2
tests/golden/lex-body-rest-bad-7/tokens.txtnew file+22
@@ -0,0 +1,22 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 glyph (
10+2:7 tight name eq
11+2:10 name x
12+3:5 INDENT
13+3:5 lit %.y
14+4:3 DEDENT
15+4:3 NEWLINE
16+4:3 lit %.y
17+4:7 lit 1
18+5:3 NEWLINE
19+5:3 lit %.n
20+5:7 lit 2
21+5:8 DEDENT
22+5:8 NEWLINE
tests/golden/lex-body-rest-bad-7/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-7/source.jibb:2:11: expected `?-`'s arms on deeper lines, found the end of the line; the deeper lines go to the last bracket or rune left open on this line
2+ ?- (eq x
3+ ^
tests/golden/lex-body-rest-bad-8/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a trace whose value leaves a bracket open, taking the deeper lines, with its body at the trace's depth after them
3+expect: error at 2:8, the end of line 2 — the ~[ took the deeper lines, so the trace can't take the rest of the body
tests/golden/lex-body-rest-bad-8/source.jibbnew file+4
@@ -0,0 +1,4 @@
1+++ f |= x=@ud
2+ ~& ~[
3+ x
4+ x
tests/golden/lex-body-rest-bad-8/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name x
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 glyph ~&
9+2:6 glyph ~[
10+3:5 INDENT
11+3:5 name x
12+4:3 DEDENT
13+4:3 NEWLINE
14+4:3 name x
15+4:4 DEDENT
16+4:4 NEWLINE
tests/golden/lex-body-rest-bad-8/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-8/source.jibb:2:8: expected `~&`'s body on deeper lines, found the end of the line; the deeper lines go to the last bracket or rune left open on this line
2+ ~& ~[
3+ ^
tests/golden/lex-body-rest-bad-9/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes, The rest of a body: "This doesn't apply on a `?-` arm's line, on a line of an open bracket, after a bracket opened earlier on the line (the subject's included), at the top level, or to a definition's own expression."
2+tests: a top-level definition's trace, with its body on the next line at column 1
3+expect: error at 2:1 — at the top level no rune takes the lines after it, so `~&`'s body goes on deeper lines
tests/golden/lex-body-rest-bad-9/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+++ x ~& "hi"
2+5
tests/golden/lex-body-rest-bad-9/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~&
4+1:9 str "hi"
5+2:1 NEWLINE
6+2:1 lit 5
7+2:2 NEWLINE
tests/golden/lex-body-rest-bad-9/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-body-rest-bad-9/source.jibb:2:1: expected `~&`'s body on deeper lines, found a line at the same depth
2+5
3+^
tests/golden/lex-body-rest-ok-1/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Runes: "**The rest of a body.** A body's final line may hand the rest of the body, the lines after it at the same depth, to the rune that ends the line: a tall `|=`, `^-` or `~&`, or a chain of them such as `^- @ud ~& x`, when the line ends where the innermost rune's last child goes. That child is the rest, a body of its own: first its local `++` and `+$`, then its expression, whose own final line may do the same"; the EBNF: `last = expr | head NEWLINE rest | …`
2+tests: a body's final `^-`, `~&` and `|=`, each alone on its line, taking the rest of the body at the same depth as its last child, with the prelude's add
3+expect: parses: a's cast, b's trace and c's inner gate each hold the line below as a body, the tree the deeper layout gives
4+expect-types: a partial inference report: a and b are $-(@ud @ud), and c $-($-(@ud @ud) $-(@ud @ud)), as their deeper layouts are
tests/golden/lex-body-rest-ok-1/module-trees.txtnew file+4
@@ -0,0 +1,4 @@
1+/ui/lib.jibb
2+(module
3+ (value 1:1 identity
4+ (gate-wide 1:13 (bind 1:16 x) (wing 1:18 x))))
tests/golden/lex-body-rest-ok-1/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/lex-body-rest-ok-1/modules/ui/lib.jibbnew file+1
@@ -0,0 +1 @@
1+++ identity |=(x x)
tests/golden/lex-body-rest-ok-1/source.jibbnew file+11
@@ -0,0 +1,11 @@
1+/= lib /ui/lib
2+
3+++ a |= n=@ud
4+ ^- @ud
5+ (add n 1)
6+++ b |= n=@ud
7+ ~& n
8+ (add n 1)
9+++ c |= f=$-(@ud @ud)
10+ |= n=@ud
11+ (f n)
tests/golden/lex-body-rest-ok-1/tokens.txtnew file+62
@@ -0,0 +1,62 @@
1+1:1 glyph /=
2+1:5 name lib
3+1:9 glyph /
4+1:10 tight knot ui
5+1:12 tight glyph /
6+1:13 tight knot lib
7+3:1 NEWLINE
8+3:1 glyph ++
9+3:4 name a
10+3:6 glyph |=
11+3:9 name n
12+3:10 tight glyph =
13+3:11 tight aura @ud
14+4:3 INDENT
15+4:3 glyph ^-
16+4:6 aura @ud
17+5:3 NEWLINE
18+5:3 glyph (
19+5:4 tight name add
20+5:8 name n
21+5:10 lit 1
22+5:11 tight glyph )
23+6:1 DEDENT
24+6:1 NEWLINE
25+6:1 glyph ++
26+6:4 name b
27+6:6 glyph |=
28+6:9 name n
29+6:10 tight glyph =
30+6:11 tight aura @ud
31+7:3 INDENT
32+7:3 glyph ~&
33+7:6 name n
34+8:3 NEWLINE
35+8:3 glyph (
36+8:4 tight name add
37+8:8 name n
38+8:10 lit 1
39+8:11 tight glyph )
40+9:1 DEDENT
41+9:1 NEWLINE
42+9:1 glyph ++
43+9:4 name c
44+9:6 glyph |=
45+9:9 name f
46+9:10 tight glyph =
47+9:11 tight glyph $-(
48+9:14 tight aura @ud
49+9:18 aura @ud
50+9:21 tight glyph )
51+10:3 INDENT
52+10:3 glyph |=
53+10:6 name n
54+10:7 tight glyph =
55+10:8 tight aura @ud
56+11:3 NEWLINE
57+11:3 glyph (
58+11:4 tight name f
59+11:6 name n
60+11:7 tight glyph )
61+11:8 DEDENT
62+11:8 NEWLINE
tests/golden/lex-body-rest-ok-1/tree.txtnew file+30
@@ -0,0 +1,30 @@
1+(module
2+ (jibb 1:1 lib /ui/lib)
3+ (value 3:1 a
4+ (gate 3:6
5+ (face 3:9 n (aura 3:11 @ud))
6+ (body 4:3
7+ (cast 4:3
8+ (aura 4:6 @ud)
9+ (body 5:3
10+ (group 5:3
11+ (call 5:4 (wing 5:4 add) (wing 5:8 n) (lit 5:10 1))))))))
12+ (value 6:1 b
13+ (gate 6:6
14+ (face 6:9 n (aura 6:11 @ud))
15+ (body 7:3
16+ (trace 7:3
17+ (wing 7:6 n)
18+ (body 8:3
19+ (group 8:3
20+ (call 8:4 (wing 8:4 add) (wing 8:8 n) (lit 8:10 1))))))))
21+ (value 9:1 c
22+ (gate 9:6
23+ (face 9:9 f
24+ (fn 9:11 (aura 9:14 @ud) (aura 9:18 @ud)))
25+ (body 10:3
26+ (gate 10:3
27+ (face 10:6 n (aura 10:8 @ud))
28+ (body 11:3
29+ (group 11:3
30+ (call 11:4 (wing 11:4 f) (wing 11:6 n)))))))))
tests/golden/lex-body-rest-ok-1/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2+++ a: $-(@ud @ud)
3+++ b: $-(@ud @ud)
4+++ c: $-($-(@ud @ud) $-(@ud @ud))
tests/golden/lex-body-rest-ok-2/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Runes: "**The rest of a body.** A body's final line may hand the rest of the body, the lines after it at the same depth, to the rune that ends the line: a tall `|=`, `^-` or `~&`, or a chain of them such as `^- @ud ~& x`, when the line ends where the innermost rune's last child goes. That child is the rest, a body of its own: first its local `++` and `+$`, then its expression, whose own final line may do the same"; the EBNF: `last = expr | head NEWLINE rest | …`
2+tests: a chain of runes on one line, `^- @ud ~& n` and `|= m=@ud ^- @ud`, whose innermost rune takes the rest; and `^-`, then `~&`, then the expression, each on its own line at one depth
3+expect: parses: in a the trace inside the cast holds line 5; in b the cast's rest is the trace, whose rest is line 9; in c the cast inside the inner gate holds line 12
4+expect-types: a partial inference report: a and b are $-(@ud @ud), and c $-(@ud $-(@ud @ud))
tests/golden/lex-body-rest-ok-2/module-trees.txtnew file+4
@@ -0,0 +1,4 @@
1+/ui/lib.jibb
2+(module
3+ (value 1:1 identity
4+ (gate-wide 1:13 (bind 1:16 x) (wing 1:18 x))))
tests/golden/lex-body-rest-ok-2/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/lex-body-rest-ok-2/modules/ui/lib.jibbnew file+1
@@ -0,0 +1 @@
1+++ identity |=(x x)
tests/golden/lex-body-rest-ok-2/source.jibbnew file+12
@@ -0,0 +1,12 @@
1+/= lib /ui/lib
2+
3+++ a |= n=@ud
4+ ^- @ud ~& n
5+ (add n 1)
6+++ b |= n=@ud
7+ ^- @ud
8+ ~& n
9+ (add n 1)
10+++ c |= n=@ud
11+ |= m=@ud ^- @ud
12+ (add n m)
tests/golden/lex-body-rest-ok-2/tokens.txtnew file+67
@@ -0,0 +1,67 @@
1+1:1 glyph /=
2+1:5 name lib
3+1:9 glyph /
4+1:10 tight knot ui
5+1:12 tight glyph /
6+1:13 tight knot lib
7+3:1 NEWLINE
8+3:1 glyph ++
9+3:4 name a
10+3:6 glyph |=
11+3:9 name n
12+3:10 tight glyph =
13+3:11 tight aura @ud
14+4:3 INDENT
15+4:3 glyph ^-
16+4:6 aura @ud
17+4:10 glyph ~&
18+4:13 name n
19+5:3 NEWLINE
20+5:3 glyph (
21+5:4 tight name add
22+5:8 name n
23+5:10 lit 1
24+5:11 tight glyph )
25+6:1 DEDENT
26+6:1 NEWLINE
27+6:1 glyph ++
28+6:4 name b
29+6:6 glyph |=
30+6:9 name n
31+6:10 tight glyph =
32+6:11 tight aura @ud
33+7:3 INDENT
34+7:3 glyph ^-
35+7:6 aura @ud
36+8:3 NEWLINE
37+8:3 glyph ~&
38+8:6 name n
39+9:3 NEWLINE
40+9:3 glyph (
41+9:4 tight name add
42+9:8 name n
43+9:10 lit 1
44+9:11 tight glyph )
45+10:1 DEDENT
46+10:1 NEWLINE
47+10:1 glyph ++
48+10:4 name c
49+10:6 glyph |=
50+10:9 name n
51+10:10 tight glyph =
52+10:11 tight aura @ud
53+11:3 INDENT
54+11:3 glyph |=
55+11:6 name m
56+11:7 tight glyph =
57+11:8 tight aura @ud
58+11:12 glyph ^-
59+11:15 aura @ud
60+12:3 NEWLINE
61+12:3 glyph (
62+12:4 tight name add
63+12:8 name n
64+12:10 name m
65+12:11 tight glyph )
66+12:12 DEDENT
67+12:12 NEWLINE
tests/golden/lex-body-rest-ok-2/tree.txtnew file+36
@@ -0,0 +1,36 @@
1+(module
2+ (jibb 1:1 lib /ui/lib)
3+ (value 3:1 a
4+ (gate 3:6
5+ (face 3:9 n (aura 3:11 @ud))
6+ (body 4:3
7+ (cast 4:3
8+ (aura 4:6 @ud)
9+ (trace 4:10
10+ (wing 4:13 n)
11+ (body 5:3
12+ (group 5:3
13+ (call 5:4 (wing 5:4 add) (wing 5:8 n) (lit 5:10 1)))))))))
14+ (value 6:1 b
15+ (gate 6:6
16+ (face 6:9 n (aura 6:11 @ud))
17+ (body 7:3
18+ (cast 7:3
19+ (aura 7:6 @ud)
20+ (body 8:3
21+ (trace 8:3
22+ (wing 8:6 n)
23+ (body 9:3
24+ (group 9:3
25+ (call 9:4 (wing 9:4 add) (wing 9:8 n) (lit 9:10 1))))))))))
26+ (value 10:1 c
27+ (gate 10:6
28+ (face 10:9 n (aura 10:11 @ud))
29+ (body 11:3
30+ (gate 11:3
31+ (face 11:6 m (aura 11:8 @ud))
32+ (cast 11:12
33+ (aura 11:15 @ud)
34+ (body 12:3
35+ (group 12:3
36+ (call 12:4 (wing 12:4 add) (wing 12:8 n) (wing 12:10 m))))))))))
tests/golden/lex-body-rest-ok-2/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2+++ a: $-(@ud @ud)
3+++ b: $-(@ud @ud)
4+++ c: $-(@ud $-(@ud @ud))
tests/golden/lex-body-rest-ok-3/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "**The rest of a body.** A body's final line may hand the rest of the body, the lines after it at the same depth, to the rune that ends the line: a tall `|=`, `^-` or `~&`, or a chain of them such as `^- @ud ~& x`, when the line ends where the innermost rune's last child goes. That child is the rest, a body of its own: first its local `++` and `+$`, then its expression, whose own final line may do the same"; the EBNF: `last = expr | head NEWLINE rest | …`
2+tests: local `++` and `+$` at the start of a rest: the cast's rest is a body with definitions three and count, after the gate body's own definition two
3+expect: parses: the gate's body defines two, then the cast, whose body defines count and three and ends with the call
tests/golden/lex-body-rest-ok-3/source.jibbnew file+6
@@ -0,0 +1,6 @@
1+++ f |= n=@ud
2+ ++ two 2
3+ ^- @ud
4+ +$ count @ud
5+ ++ three ^- count 3
6+ (add n (add two three))
tests/golden/lex-body-rest-ok-3/tokens.txtnew file+35
@@ -0,0 +1,35 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name n
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 glyph ++
9+2:6 name two
10+2:10 lit 2
11+3:3 NEWLINE
12+3:3 glyph ^-
13+3:6 aura @ud
14+4:3 NEWLINE
15+4:3 glyph +$
16+4:6 name count
17+4:12 aura @ud
18+5:3 NEWLINE
19+5:3 glyph ++
20+5:6 name three
21+5:12 glyph ^-
22+5:15 name count
23+5:21 lit 3
24+6:3 NEWLINE
25+6:3 glyph (
26+6:4 tight name add
27+6:8 name n
28+6:10 glyph (
29+6:11 tight name add
30+6:15 name two
31+6:19 name three
32+6:24 tight glyph )
33+6:25 tight glyph )
34+6:26 DEDENT
35+6:26 NEWLINE
tests/golden/lex-body-rest-ok-3/tree.txtnew file+18
@@ -0,0 +1,18 @@
1+(module
2+ (value 1:1 f
3+ (gate 1:6
4+ (face 1:9 n (aura 1:11 @ud))
5+ (body 2:3
6+ (value 2:3 two (lit 2:10 2))
7+ (cast 3:3
8+ (aura 3:6 @ud)
9+ (body 4:3
10+ (mold 4:3 count (aura 4:12 @ud))
11+ (value 5:3 three
12+ (cast 5:12 (ref 5:15 count) (lit 5:21 3)))
13+ (group 6:3
14+ (call 6:4
15+ (wing 6:4 add)
16+ (wing 6:8 n)
17+ (group 6:10
18+ (call 6:11 (wing 6:11 add) (wing 6:15 two) (wing 6:19 three)))))))))))
tests/golden/lex-body-rest-ok-4/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: a `?-` that begins a body's final line, with its arms at its own depth, one per line, to the end of the body, over a loobean and over a union, with a comment line and a blank line between two arms
3+expect: parses: each ?- holds the arms below it, the tree the deeper layout gives
4+expect-types: a partial inference report: f is $-(? @ud) and g $-(sign @ud)
tests/golden/lex-body-rest-ok-4/source.jibbnew file+13
@@ -0,0 +1,13 @@
1++$ sign
2+ %zero
3+ %more
4+++ f |= b=? ^- @ud
5+ ?- b
6+ %.y 1
7+ :: comment lines and blank lines between arms emit nothing
8+
9+ %.n 2
10+++ g |= s=sign ^- @ud
11+ ?- s
12+ %zero 0
13+ %more 1
tests/golden/lex-body-rest-ok-4/tokens.txtnew file+46
@@ -0,0 +1,46 @@
1+1:1 glyph +$
2+1:4 name sign
3+2:3 INDENT
4+2:3 lit %zero
5+3:3 NEWLINE
6+3:3 lit %more
7+4:1 DEDENT
8+4:1 NEWLINE
9+4:1 glyph ++
10+4:4 name f
11+4:6 glyph |=
12+4:9 name b
13+4:10 tight glyph =
14+4:11 tight glyph ?
15+4:13 glyph ^-
16+4:16 aura @ud
17+5:3 INDENT
18+5:3 glyph ?-
19+5:6 name b
20+6:3 NEWLINE
21+6:3 lit %.y
22+6:8 lit 1
23+9:3 NEWLINE
24+9:3 lit %.n
25+9:8 lit 2
26+10:1 DEDENT
27+10:1 NEWLINE
28+10:1 glyph ++
29+10:4 name g
30+10:6 glyph |=
31+10:9 name s
32+10:10 tight glyph =
33+10:11 tight name sign
34+10:16 glyph ^-
35+10:19 aura @ud
36+11:3 INDENT
37+11:3 glyph ?-
38+11:6 name s
39+12:3 NEWLINE
40+12:3 lit %zero
41+12:10 lit 0
42+13:3 NEWLINE
43+13:3 lit %more
44+13:10 lit 1
45+13:11 DEDENT
46+13:11 NEWLINE
tests/golden/lex-body-rest-ok-4/tree.txtnew file+23
@@ -0,0 +1,23 @@
1+(module
2+ (mold 1:1 sign
3+ (union 2:3 (const 2:3 %zero) (const 3:3 %more)))
4+ (value 4:1 f
5+ (gate 4:6
6+ (face 4:9 b (flag 4:11))
7+ (cast 4:13
8+ (aura 4:16 @ud)
9+ (body 5:3
10+ (branch 5:3
11+ (wing 5:6 b)
12+ (arm 6:3 (lit 6:3 %.y) (lit 6:8 1))
13+ (arm 9:3 (lit 9:3 %.n) (lit 9:8 2)))))))
14+ (value 10:1 g
15+ (gate 10:6
16+ (face 10:9 s (ref 10:11 sign))
17+ (cast 10:16
18+ (aura 10:19 @ud)
19+ (body 11:3
20+ (branch 11:3
21+ (wing 11:6 s)
22+ (arm 12:3 (lit 12:3 %zero) (lit 12:10 0))
23+ (arm 13:3 (lit 13:3 %more) (lit 13:10 1))))))))
tests/golden/lex-body-rest-ok-4/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2++$ sign: cases proven disjoint; mold not checked
3+++ f: $-(? @ud)
4+++ g: $-(sign @ud)
tests/golden/lex-body-rest-ok-5/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: arms at the `?-`'s depth whose expressions are bodies on deeper lines, one with a local definition
3+expect: parses: each arm's body is the block below its pattern, and the next arm follows at the ?-'s depth
tests/golden/lex-body-rest-ok-5/source.jibbnew file+7
@@ -0,0 +1,7 @@
1+++ f |= b=?
2+ ?- b
3+ %.y
4+ 1
5+ %.n
6+ ++ two 2
7+ two
tests/golden/lex-body-rest-ok-5/tokens.txtnew file+25
@@ -0,0 +1,25 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name b
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name b
10+3:3 NEWLINE
11+3:3 lit %.y
12+4:5 INDENT
13+4:5 lit 1
14+5:3 DEDENT
15+5:3 NEWLINE
16+5:3 lit %.n
17+6:5 INDENT
18+6:5 glyph ++
19+6:8 name two
20+6:12 lit 2
21+7:5 NEWLINE
22+7:5 name two
23+7:8 DEDENT
24+7:8 DEDENT
25+7:8 NEWLINE
tests/golden/lex-body-rest-ok-5/tree.txtnew file+15
@@ -0,0 +1,15 @@
1+(module
2+ (value 1:1 f
3+ (gate 1:6
4+ (face 1:9 b (flag 1:11))
5+ (body 2:3
6+ (branch 2:3
7+ (wing 2:6 b)
8+ (arm 3:3
9+ (lit 3:3 %.y)
10+ (body 4:5 (lit 4:5 1)))
11+ (arm 5:3
12+ (lit 5:3 %.n)
13+ (body 6:5
14+ (value 6:5 two (lit 6:12 2))
15+ (wing 7:5 two))))))))
tests/golden/lex-body-rest-ok-6/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "`?-` **wuthep**: … A `?-` that begins a body's final line may instead take its arms at its own depth, to the end of the body. A `?-` takes all its arms deeper or all at its own depth."; the EBNF: `last = … | "?-" expr NEWLINE arm { NEWLINE arm } ;`
2+tests: a `?-` with its arms at its depth inside an arm's deeper body, itself at the outer `?-`'s depth
3+expect: parses: the inner ?- holds the arms at 5:5 and 6:5, and [%.n b] at 7:3 is the outer ?-'s second arm
tests/golden/lex-body-rest-ok-6/source.jibbnew file+7
@@ -0,0 +1,7 @@
1+++ f |= p=[? ?]
2+ ?- p
3+ [%.y b]
4+ ?- b
5+ %.y 1
6+ %.n 2
7+ [%.n b] 3
tests/golden/lex-body-rest-ok-6/tokens.txtnew file+35
@@ -0,0 +1,35 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name p
5+1:10 tight glyph =
6+1:11 tight glyph [
7+1:12 tight glyph ?
8+1:14 glyph ?
9+1:15 tight glyph ]
10+2:3 INDENT
11+2:3 glyph ?-
12+2:6 name p
13+3:3 NEWLINE
14+3:3 glyph [
15+3:4 tight lit %.y
16+3:8 name b
17+3:9 tight glyph ]
18+4:5 INDENT
19+4:5 glyph ?-
20+4:8 name b
21+5:5 NEWLINE
22+5:5 lit %.y
23+5:9 lit 1
24+6:5 NEWLINE
25+6:5 lit %.n
26+6:9 lit 2
27+7:3 DEDENT
28+7:3 NEWLINE
29+7:3 glyph [
30+7:4 tight lit %.n
31+7:8 name b
32+7:9 tight glyph ]
33+7:11 lit 3
34+7:12 DEDENT
35+7:12 NEWLINE
tests/golden/lex-body-rest-ok-6/tree.txtnew file+18
@@ -0,0 +1,18 @@
1+(module
2+ (value 1:1 f
3+ (gate 1:6
4+ (face 1:9 p
5+ (cell 1:11 (flag 1:12) (flag 1:14)))
6+ (body 2:3
7+ (branch 2:3
8+ (wing 2:6 p)
9+ (arm 3:3
10+ (cell 3:3 (lit 3:4 %.y) (bind 3:8 b))
11+ (body 4:5
12+ (branch 4:5
13+ (wing 4:8 b)
14+ (arm 5:5 (lit 5:5 %.y) (lit 5:9 1))
15+ (arm 6:5 (lit 6:5 %.n) (lit 6:9 2)))))
16+ (arm 7:3
17+ (cell 7:3 (lit 7:4 %.n) (bind 7:8 b))
18+ (lit 7:11 3)))))))
tests/golden/lex-body-rest-ok-7/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Runes: "**The rest of a body.** A body's final line may hand the rest of the body, the lines after it at the same depth, to the rune that ends the line: … a `?-` that begins the line and ends it with its subject. Its arms are the rest, one per line"
2+tests: a trace taking the rest of the body, whose final line is a `?-` with its arms at its depth: removing the `~&` line moves no other line
3+expect: parses: the trace's body is the ?-, which holds both arms
4+expect-types: a partial inference report: update is $-([msg=msg n=@ud] @ud)
tests/golden/lex-body-rest-ok-7/module-trees.txtnew file+4
@@ -0,0 +1,4 @@
1+/ui/lib.jibb
2+(module
3+ (value 1:1 identity
4+ (gate-wide 1:13 (bind 1:16 x) (wing 1:18 x))))
tests/golden/lex-body-rest-ok-7/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/lex-body-rest-ok-7/modules/ui/lib.jibbnew file+1
@@ -0,0 +1 @@
1+++ identity |=(x x)
tests/golden/lex-body-rest-ok-7/source.jibbnew file+10
@@ -0,0 +1,10 @@
1+/= lib /ui/lib
2+
3++$ msg
4+ [%typed text=@t]
5+ %submit
6+++ update |= [=msg n=@ud]
7+ ~& msg
8+ ?- msg
9+ [%typed t] n
10+ %submit (add n 1)
tests/golden/lex-body-rest-ok-7/tokens.txtnew file+51
@@ -0,0 +1,51 @@
1+1:1 glyph /=
2+1:5 name lib
3+1:9 glyph /
4+1:10 tight knot ui
5+1:12 tight glyph /
6+1:13 tight knot lib
7+3:1 NEWLINE
8+3:1 glyph +$
9+3:4 name msg
10+4:3 INDENT
11+4:3 glyph [
12+4:4 tight lit %typed
13+4:11 name text
14+4:15 tight glyph =
15+4:16 tight aura @t
16+4:18 tight glyph ]
17+5:3 NEWLINE
18+5:3 lit %submit
19+6:1 DEDENT
20+6:1 NEWLINE
21+6:1 glyph ++
22+6:4 name update
23+6:11 glyph |=
24+6:14 glyph [
25+6:15 tight glyph =
26+6:16 tight name msg
27+6:20 name n
28+6:21 tight glyph =
29+6:22 tight aura @ud
30+6:25 tight glyph ]
31+7:3 INDENT
32+7:3 glyph ~&
33+7:6 name msg
34+8:3 NEWLINE
35+8:3 glyph ?-
36+8:6 name msg
37+9:3 NEWLINE
38+9:3 glyph [
39+9:4 tight lit %typed
40+9:11 name t
41+9:12 tight glyph ]
42+9:15 name n
43+10:3 NEWLINE
44+10:3 lit %submit
45+10:15 glyph (
46+10:16 tight name add
47+10:20 name n
48+10:22 lit 1
49+10:23 tight glyph )
50+10:24 DEDENT
51+10:24 NEWLINE
tests/golden/lex-body-rest-ok-7/tree.txtnew file+26
@@ -0,0 +1,26 @@
1+(module
2+ (jibb 1:1 lib /ui/lib)
3+ (mold 3:1 msg
4+ (union 4:3
5+ (cell 4:3
6+ (const 4:4 %typed)
7+ (face 4:11 text (aura 4:16 @t)))
8+ (const 5:3 %submit)))
9+ (value 6:1 update
10+ (gate 6:11
11+ (cell 6:14
12+ (pun 6:15 msg)
13+ (face 6:20 n (aura 6:22 @ud)))
14+ (body 7:3
15+ (trace 7:3
16+ (wing 7:6 msg)
17+ (body 8:3
18+ (branch 8:3
19+ (wing 8:6 msg)
20+ (arm 9:3
21+ (cell 9:3 (lit 9:4 %typed) (bind 9:11 t))
22+ (wing 9:15 n))
23+ (arm 10:3
24+ (lit 10:3 %submit)
25+ (group 10:15
26+ (call 10:16 (wing 10:16 add) (wing 10:20 n) (lit 10:22 1)))))))))))
tests/golden/lex-body-rest-ok-7/types.txtnew file+3
@@ -0,0 +1,3 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ update: $-([msg=msg n=@ud] @ud)
tests/golden/lex-body-rest-ok-8/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Runes: "**The rest of a body.** A body's final line may hand the rest of the body, the lines after it at the same depth, to the rune that ends the line: … a `?-` that begins the line and ends it with its subject. Its arms are the rest, one per line"
2+tests: a gate and a cast taking the rest of a body, then a `?-` on the rest's final line with its arms at its depth; and a `?-` with its arms at its depth on the final line of a local `++`'s deeper body
3+expect: parses: or-else's inner gate holds the cast, which holds the ?- and its two arms; h's body is the ?-
4+expect-types: a partial inference report: or-else is $-(@ud $-((unit @ud) @ud)) and g $-(? @ud)
tests/golden/lex-body-rest-ok-8/module-trees.txtnew file+4
@@ -0,0 +1,4 @@
1+/ui/lib.jibb
2+(module
3+ (value 1:1 identity
4+ (gate-wide 1:13 (bind 1:16 x) (wing 1:18 x))))
tests/golden/lex-body-rest-ok-8/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/lex-body-rest-ok-8/modules/ui/lib.jibbnew file+1
@@ -0,0 +1 @@
1+++ identity |=(x x)
tests/golden/lex-body-rest-ok-8/source.jibbnew file+14
@@ -0,0 +1,14 @@
1+/= lib /ui/lib
2+
3+++ or-else |= fallback=@ud
4+ |= maybe=(unit @ud)
5+ ^- @ud
6+ ?- maybe
7+ ~ fallback
8+ [~ value] value
9+++ g |= b=?
10+ ++ h ^- @ud
11+ ?- b
12+ %.y 1
13+ %.n 2
14+ h
tests/golden/lex-body-rest-ok-8/tokens.txtnew file+63
@@ -0,0 +1,63 @@
1+1:1 glyph /=
2+1:5 name lib
3+1:9 glyph /
4+1:10 tight knot ui
5+1:12 tight glyph /
6+1:13 tight knot lib
7+3:1 NEWLINE
8+3:1 glyph ++
9+3:4 name or-else
10+3:12 glyph |=
11+3:15 name fallback
12+3:23 tight glyph =
13+3:24 tight aura @ud
14+4:3 INDENT
15+4:3 glyph |=
16+4:6 name maybe
17+4:11 tight glyph =
18+4:12 tight glyph (
19+4:13 tight name unit
20+4:18 aura @ud
21+4:21 tight glyph )
22+5:3 NEWLINE
23+5:3 glyph ^-
24+5:6 aura @ud
25+6:3 NEWLINE
26+6:3 glyph ?-
27+6:6 name maybe
28+7:3 NEWLINE
29+7:3 lit ~
30+7:14 name fallback
31+8:3 NEWLINE
32+8:3 glyph [
33+8:4 tight lit ~
34+8:6 name value
35+8:11 tight glyph ]
36+8:14 name value
37+9:1 DEDENT
38+9:1 NEWLINE
39+9:1 glyph ++
40+9:4 name g
41+9:6 glyph |=
42+9:9 name b
43+9:10 tight glyph =
44+9:11 tight glyph ?
45+10:3 INDENT
46+10:3 glyph ++
47+10:6 name h
48+10:8 glyph ^-
49+10:11 aura @ud
50+11:5 INDENT
51+11:5 glyph ?-
52+11:8 name b
53+12:5 NEWLINE
54+12:5 lit %.y
55+12:9 lit 1
56+13:5 NEWLINE
57+13:5 lit %.n
58+13:9 lit 2
59+14:3 DEDENT
60+14:3 NEWLINE
61+14:3 name h
62+14:4 DEDENT
63+14:4 NEWLINE
tests/golden/lex-body-rest-ok-8/tree.txtnew file+32
@@ -0,0 +1,32 @@
1+(module
2+ (jibb 1:1 lib /ui/lib)
3+ (value 3:1 or-else
4+ (gate 3:12
5+ (face 3:15 fallback (aura 3:24 @ud))
6+ (body 4:3
7+ (gate 4:3
8+ (face 4:6 maybe
9+ (apply 4:12 unit (aura 4:18 @ud)))
10+ (body 5:3
11+ (cast 5:3
12+ (aura 5:6 @ud)
13+ (body 6:3
14+ (branch 6:3
15+ (wing 6:6 maybe)
16+ (arm 7:3 (lit 7:3 ~) (wing 7:14 fallback))
17+ (arm 8:3
18+ (cell 8:3 (lit 8:4 ~) (bind 8:6 value))
19+ (wing 8:14 value))))))))))
20+ (value 9:1 g
21+ (gate 9:6
22+ (face 9:9 b (flag 9:11))
23+ (body 10:3
24+ (value 10:3 h
25+ (cast 10:8
26+ (aura 10:11 @ud)
27+ (body 11:5
28+ (branch 11:5
29+ (wing 11:8 b)
30+ (arm 12:5 (lit 12:5 %.y) (lit 12:9 1))
31+ (arm 13:5 (lit 13:5 %.n) (lit 13:9 2))))))
32+ (wing 14:3 h)))))
tests/golden/lex-body-rest-ok-8/types.txtnew file+3
@@ -0,0 +1,3 @@
1+partial inference; module not checked
2+++ or-else: $-(@ud $-((unit @ud) @ud))
3+++ g: $-(? @ud)
tests/golden/lex-call-open-bad-1/about.txt → tests/golden/lex-call-open-ok-3/about.txtrenamed

The content is the same.

tests/golden/lex-call-open-bad-1/source.jibb → tests/golden/lex-call-open-ok-3/source.jibbrenamed

The content is the same.

tests/golden/lex-call-open-bad-1/tokens.txt → tests/golden/lex-call-open-ok-3/tokens.txtrenamed

The content is the same.

tests/golden/lex-call-open-bad-1/tree.txt → tests/golden/lex-call-open-ok-3/tree.txtrenamed

The content is the same.

tests/golden/lex-layout-bad-4/about.txt+1−1
@@ -1,3 +1,3 @@
11source: Grammar tab, Lexical rules: "Layout tokens: a deeper line emits INDENT, the same depth NEWLINE, a shallower one a DEDENT per closed level, then NEWLINE."; the EBNF's comment: "Blank and comment-only lines emit nothing."
22tests: an arm written one level too shallow
3−expect: error at 4:3 — line 4 is shallower than the arms, so it closes them (DEDENT) and lands at the body's depth (NEWLINE), after the body's final expression, the ?-
3+expect: error at 4:3 — line 4 is shallower than the arms, so it closes them (DEDENT) and lands at the body's depth (NEWLINE), after the body's final expression, the ?-; its first arm is deeper, so the hint says this one goes there too
tests/golden/lex-layout-bad-4/tree.txt+1−1
@@ -1,3 +1,3 @@
1−/tests/golden/lex-layout-bad-4/source.jibb:4:3: expected the end of the body, found a line at the same depth; a body's final expression is its last line
1+/tests/golden/lex-layout-bad-4/source.jibb:4:3: expected the end of the body, found a line at the same depth; this `?-`'s arms are on deeper lines, so this one goes there too
22 * ~
33 ^
tests/golden/lex-name-bad-5/tokens.txt+4−3
@@ -1,3 +1,4 @@
1−/tests/golden/lex-name-bad-5/source.jibb:1:5: a type variable is one capital letter
2−++ Foo 1
3− ^
1+1:1 glyph ++
2+1:4 tvar Foo
3+1:8 lit 1
4+1:9 NEWLINE
tests/golden/lex-name-bad-5/tree.txt+1−1
@@ -1,3 +1,3 @@
1−/tests/golden/lex-name-bad-5/source.jibb:1:4: expected a name, found `F`; a name starts with a lowercase letter
1+/tests/golden/lex-name-bad-5/source.jibb:1:4: expected a name, found `Foo`; a name starts with a lowercase letter
22++ Foo 1
33 ^
tests/golden/lex-rune-layout-bad-3/about.txtdeleted−3
@@ -1,3 +0,0 @@
1−source: Grammar tab, Runes: "A rune's first children sit on its line, the last taking the rest of it; the others follow, indented."; the EBNF: `rune = "|=" field ( expr | body ) | "^-" mold ( expr | body ) | "~&" expr body | "?-" expr INDENT arm { NEWLINE arm } DEDENT ;`
2−tests: `~&`'s body at the depth of the `~&` line, as Hoon's tall form would put it
3−expect: error at 3:3 — `~&`'s body is indented deeper than its line; line 3 is at the same depth
tests/golden/lex-rune-layout-bad-3/tree.txtdeleted−3
@@ -1,3 +0,0 @@
1−/tests/golden/lex-rune-layout-bad-3/source.jibb:3:3: expected `~&`'s body on deeper lines, found a line at the same depth
2− 5
3− ^
tests/golden/lex-rune-layout-ok-3/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Runes: "A rune's first children sit on its line, the last taking the rest of it; the others follow, indented. On a body's final line, the last child may instead take the rest of the body at the same depth, as The rest of a body says."
2+tests: `~&`'s body at the depth of the `~&` line, as Hoon's tall form would put it, on the final line of a definition's body
3+expect: parses: the `~&` is the body's final line, so the line after it at the same depth is its body, (trace "hi" (body 5))
tests/golden/lex-rune-layout-bad-3/source.jibb → tests/golden/lex-rune-layout-ok-3/source.jibbrenamed

The content is the same.

tests/golden/lex-rune-layout-bad-3/tokens.txt → tests/golden/lex-rune-layout-ok-3/tokens.txtrenamed

The content is the same.

tests/golden/lex-rune-layout-ok-3/tree.txtnew file+6
@@ -0,0 +1,6 @@
1+(module
2+ (value 1:1 x
3+ (body 2:3
4+ (trace 2:3
5+ (str 2:6 "hi")
6+ (body 3:3 (lit 3:3 5))))))
tests/golden/lex-tight-change-bad-10/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar, Expressions: "A change's item, inline or on a line, may name a wing instead, read through record fields only: `m(open.cart=(not open.cart.m))` sets field `open` of field `cart`, as Hoon's `m(open.cart x)`."; the EBNF: `edit = wing "=" operand ;` and `elines = INDENT wing "=" expr { NEWLINE wing "=" expr } DEDENT ;`
2+tests: a change's only item a wing with no `=` after it, then the `)`
3+expect: error at 1:11, the ): `a.b` could still begin the item `a.b=…`, and the ) is the first character that can't go on (library section 3, Errors)
tests/golden/lex-tight-change-bad-10/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ x m(a.b)
tests/golden/lex-tight-change-bad-10/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name m
4+1:7 tight glyph (
5+1:8 tight wing a.b
6+1:11 tight glyph )
7+1:12 NEWLINE
tests/golden/lex-tight-change-bad-10/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-tight-change-bad-10/source.jibb:1:11: expected `=` right after `a.b`, found `)`; a change's items are named, as in m(done=%.y)
2+++ x m(a.b)
3+ ^
tests/golden/lex-tight-change-bad-11/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar, Expressions: "A change's item, inline or on a line, may name a wing instead, read through record fields only: `m(open.cart=(not open.cart.m))` sets field `open` of field `cart`, as Hoon's `m(open.cart x)`."; the EBNF: `edit = wing "=" operand ;` and `elines = INDENT wing "=" expr { NEWLINE wing "=" expr } DEDENT ;`
2+tests: a line of an open change holding a wing, a space and a value, with no `=`
3+expect: error at 2:12, the space: `open.cart` could still begin the line `open.cart=…`, and a wing= takes its `=` at once (library section 3, Errors)
tests/golden/lex-tight-change-bad-11/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+++ x m(
2+ open.cart %.n
tests/golden/lex-tight-change-bad-11/tokens.txtnew file+9
@@ -0,0 +1,9 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name m
4+1:7 tight glyph (
5+2:3 INDENT
6+2:3 wing open.cart
7+2:13 lit %.n
8+2:16 DEDENT
9+2:16 NEWLINE
tests/golden/lex-tight-change-bad-11/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-tight-change-bad-11/source.jibb:2:12: expected `=` right after `open.cart`, found a space; a change's items are named, as in m(done=%.y)
2+ open.cart %.n
3+ ^
tests/golden/lex-tight-change-bad-5/about.txt+3−3
@@ -1,3 +1,3 @@
1−source: Grammar tab, Expressions: "**Faced cells**: `[text="milk" done=%.n]`, or one `name=value` per line of an open bracket. A change takes the same items, as `m(done=%.y)`."; the EBNF: `change = wing "(" { item } ")" | wing "(" { item } open ; (* no space before "("; items named *)`
2−tests: a change's item named by a wing, as Hoon's %= allows
3−expect: error at 1:9, the dot: an item's name is a name, which `a` could still begin and the dot can't continue, as `++ a.b 1` fails at its dot (library section 3, Errors)
1+source: Grammar, Expressions: "A change's item, inline or on a line, may name a wing instead, read through record fields only: `m(open.cart=(not open.cart.m))` sets field `open` of field `cart`, as Hoon's `m(open.cart x)`."; the EBNF: `edit = wing "=" operand ;` and `elines = INDENT wing "=" expr { NEWLINE wing "=" expr } DEDENT ;`
2+tests: a change's item that is a wing with no `=` after it, followed by a space and a value, as Hoon's %= writes m(a.b 1)
3+expect: error at 1:11, the space: `a.b` could still begin the item `a.b=…`, and a wing= takes its `=` at once, so the space is the first character that can't go on; the message says "expected `=` right after `a.b`" (library section 3, Errors)
tests/golden/lex-tight-change-bad-5/source.jibb+1−1
@@ -1 +1 @@
1−++ x m(a.b=1)
1+++ x m(a.b 1)
tests/golden/lex-tight-change-bad-5/tokens.txt+1−2
@@ -3,7 +3,6 @@
331:6 name m
441:7 tight glyph (
551:8 tight wing a.b
6−1:11 tight glyph =
7−1:12 tight lit 1
6+1:12 lit 1
871:13 tight glyph )
981:14 NEWLINE
tests/golden/lex-tight-change-bad-5/tree.txt+3−3
@@ -1,3 +1,3 @@
1−/tests/golden/lex-tight-change-bad-5/source.jibb:1:9: expected a named item, found `a.b`; a change's items are named, as in m(done=%.y)
2−++ x m(a.b=1)
3− ^
1+/tests/golden/lex-tight-change-bad-5/source.jibb:1:11: expected `=` right after `a.b`, found a space; a change's items are named, as in m(done=%.y)
2+++ x m(a.b 1)
3+ ^
tests/golden/lex-tight-change-ok-2/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar, Expressions: "A change's item, inline or on a line, may name a wing instead, read through record fields only: `m(open.cart=(not open.cart.m))` sets field `open` of field `cart`, as Hoon's `m(open.cart x)`."; the EBNF: `edit = wing "=" operand ;` and `elines = INDENT wing "=" expr { NEWLINE wing "=" expr } DEDENT ;`
2+tests: a change's items named by wings: alone, beside a named item, under a wing target, and on the lines of an open change
3+expect: parses: four changes, each edit printed with its wing as written
tests/golden/lex-tight-change-ok-2/source.jibbnew file+7
@@ -0,0 +1,7 @@
1+++ a m(a.b=1)
2+++ b m(open.cart=(not open.cart.m) note="")
3+++ c cart.m(level.deep=5)
4+++ d m(
5+ open.cart=%.n
6+ level.deep.cart=(add 1 level.deep.cart.m)
7+ note=""
tests/golden/lex-tight-change-ok-2/tokens.txtnew file+55
@@ -0,0 +1,55 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 name m
4+1:7 tight glyph (
5+1:8 tight wing a.b
6+1:11 tight glyph =
7+1:12 tight lit 1
8+1:13 tight glyph )
9+2:1 NEWLINE
10+2:1 glyph ++
11+2:4 name b
12+2:6 name m
13+2:7 tight glyph (
14+2:8 tight wing open.cart
15+2:17 tight glyph =
16+2:18 tight glyph (
17+2:19 tight name not
18+2:23 wing open.cart.m
19+2:34 tight glyph )
20+2:36 name note
21+2:40 tight glyph =
22+2:41 tight str ""
23+2:43 tight glyph )
24+3:1 NEWLINE
25+3:1 glyph ++
26+3:4 name c
27+3:6 wing cart.m
28+3:12 tight glyph (
29+3:13 tight wing level.deep
30+3:23 tight glyph =
31+3:24 tight lit 5
32+3:25 tight glyph )
33+4:1 NEWLINE
34+4:1 glyph ++
35+4:4 name d
36+4:6 name m
37+4:7 tight glyph (
38+5:3 INDENT
39+5:3 wing open.cart
40+5:12 tight glyph =
41+5:13 tight lit %.n
42+6:3 NEWLINE
43+6:3 wing level.deep.cart
44+6:18 tight glyph =
45+6:19 tight glyph (
46+6:20 tight name add
47+6:24 lit 1
48+6:26 wing level.deep.cart.m
49+6:43 tight glyph )
50+7:3 NEWLINE
51+7:3 name note
52+7:7 tight glyph =
53+7:8 tight str ""
54+7:10 DEDENT
55+7:10 NEWLINE
tests/golden/lex-tight-change-ok-2/tree.txtnew file+20
@@ -0,0 +1,20 @@
1+(module
2+ (value 1:1 a
3+ (change 1:6 m
4+ (edit 1:8 a.b (lit 1:12 1))))
5+ (value 2:1 b
6+ (change 2:6 m
7+ (edit 2:8 open.cart
8+ (group 2:18
9+ (call 2:19 (wing 2:19 not) (wing 2:23 open.cart.m))))
10+ (edit 2:36 note (str 2:41 ""))))
11+ (value 3:1 c
12+ (change 3:6 cart.m
13+ (edit 3:13 level.deep (lit 3:24 5))))
14+ (value 4:1 d
15+ (change 4:6 m
16+ (edit 5:3 open.cart (lit 5:13 %.n))
17+ (edit 6:3 level.deep.cart
18+ (group 6:19
19+ (call 6:20 (wing 6:20 add) (lit 6:24 1) (wing 6:26 level.deep.cart.m))))
20+ (edit 7:3 note (str 7:8 "")))))
tests/golden/lex-typevar-bad-1/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Lexical rules: "Type variables: a capital, then lowercase letters and digits"; "`AB`, `MSG`, `Msg_x` and `Msg-x` are errors."
2+tests: a second capital right after a type variable's first
3+expect: error at 1:15 — a type variable is a capital, then lowercase letters and digits
tests/golden/lex-typevar-bad-1/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ pair |= x=AB x
tests/golden/lex-typevar-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-typevar-bad-1/source.jibb:1:15: a type variable is a capital, then lowercase letters and digits
2+++ pair |= x=AB x
3+ ^
tests/golden/lex-typevar-bad-1/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-typevar-bad-1/source.jibb:1:15: a type variable is a capital, then lowercase letters and digits
2+++ pair |= x=AB x
3+ ^
tests/golden/lex-typevar-bad-2/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Lexical rules: "Type variables: a capital, then lowercase letters and digits"; "`AB`, `MSG`, `Msg_x` and `Msg-x` are errors."
2+tests: a type variable written in capitals only, as an Elm or C habit might write it
3+expect: error at 1:15 — a type variable is a capital, then lowercase letters and digits
tests/golden/lex-typevar-bad-2/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ pass |= m=MSG m
tests/golden/lex-typevar-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-typevar-bad-2/source.jibb:1:15: a type variable is a capital, then lowercase letters and digits
2+++ pass |= m=MSG m
3+ ^
tests/golden/lex-typevar-bad-2/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-typevar-bad-2/source.jibb:1:15: a type variable is a capital, then lowercase letters and digits
2+++ pass |= m=MSG m
3+ ^
tests/golden/lex-typevar-bad-3/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Lexical rules: "Type variables: a capital, then lowercase letters and digits"; "`AB`, `MSG`, `Msg_x` and `Msg-x` are errors."
2+tests: an underscore inside a type variable
3+expect: error at 1:17 — a type variable is a capital, then lowercase letters and digits
tests/golden/lex-typevar-bad-3/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ pass |= m=Msg_x m
tests/golden/lex-typevar-bad-3/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-typevar-bad-3/source.jibb:1:17: a type variable is a capital, then lowercase letters and digits
2+++ pass |= m=Msg_x m
3+ ^
tests/golden/lex-typevar-bad-3/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-typevar-bad-3/source.jibb:1:17: a type variable is a capital, then lowercase letters and digits
2+++ pass |= m=Msg_x m
3+ ^
tests/golden/lex-typevar-bad-4/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar tab, Lexical rules: "Type variables: a capital, then lowercase letters and digits"; "`AB`, `MSG`, `Msg_x` and `Msg-x` are errors."
2+tests: a hyphen inside a type variable, which a name may hold but a type variable may not
3+expect: error at 1:17 — a type variable is a capital, then lowercase letters and digits
tests/golden/lex-typevar-bad-4/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ pass |= m=Msg-x m
tests/golden/lex-typevar-bad-4/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-typevar-bad-4/source.jibb:1:17: a type variable is a capital, then lowercase letters and digits
2+++ pass |= m=Msg-x m
3+ ^
tests/golden/lex-typevar-bad-4/tree.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-typevar-bad-4/source.jibb:1:17: a type variable is a capital, then lowercase letters and digits
2+++ pass |= m=Msg-x m
3+ ^
tests/golden/lex-typevar-ok-1/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar tab, Lexical rules: "Type variables: a capital, then lowercase letters and digits: `A`, `Msg`, `T2`."
2+tests: type variables of several letters and with digits, as generic parameters and in molds, beside a one-letter one; the printed type keeps each written name
3+expect: parses
4+expect-types: swap prints $-([key=Msg value=T2] [T2 Msg]) and same-one $-(A A)
tests/golden/lex-typevar-ok-1/source.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ entry |$ [Key Value2] [key=Key value=Value2]
2+++ swap |= p=(entry Msg T2) [value.p key.p]
3+++ same-one |= x=A x
tests/golden/lex-typevar-ok-1/tokens.txtnew file+39
@@ -0,0 +1,39 @@
1+1:1 glyph +$
2+1:4 name entry
3+1:10 glyph |$
4+1:13 glyph [
5+1:14 tight tvar Key
6+1:18 tvar Value2
7+1:24 tight glyph ]
8+1:26 glyph [
9+1:27 tight name key
10+1:30 tight glyph =
11+1:31 tight tvar Key
12+1:35 name value
13+1:40 tight glyph =
14+1:41 tight tvar Value2
15+1:47 tight glyph ]
16+2:1 NEWLINE
17+2:1 glyph ++
18+2:4 name swap
19+2:9 glyph |=
20+2:12 name p
21+2:13 tight glyph =
22+2:14 tight glyph (
23+2:15 tight name entry
24+2:21 tvar Msg
25+2:25 tvar T2
26+2:27 tight glyph )
27+2:29 glyph [
28+2:30 tight wing value.p
29+2:38 wing key.p
30+2:43 tight glyph ]
31+3:1 NEWLINE
32+3:1 glyph ++
33+3:4 name same-one
34+3:13 glyph |=
35+3:16 name x
36+3:17 tight glyph =
37+3:18 tight tvar A
38+3:20 name x
39+3:21 NEWLINE
tests/golden/lex-typevar-ok-1/tree.txtnew file+15
@@ -0,0 +1,15 @@
1+(module
2+ (mold 1:1 entry
3+ (generic 1:10 Key Value2
4+ (cell 1:26
5+ (face 1:27 key (tvar 1:31 Key))
6+ (face 1:35 value (tvar 1:41 Value2)))))
7+ (value 2:1 swap
8+ (gate 2:9
9+ (face 2:12 p
10+ (apply 2:14 entry (tvar 2:21 Msg) (tvar 2:25 T2)))
11+ (tuple 2:29 (wing 2:30 value.p) (wing 2:38 key.p))))
12+ (value 3:1 same-one
13+ (gate 3:13
14+ (face 3:16 x (tvar 3:18 A))
15+ (wing 3:20 x))))
tests/golden/lex-typevar-ok-1/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2++$ entry: not checked
3+++ swap: $-([key=Msg value=T2] [T2 Msg])
4+++ same-one: $-(A A)
tests/golden/module-import-api-scope-conflict/types.txt+7−1
@@ -1,2 +1,8 @@
11partial inference; module not checked
2−module has conflicting names: /ui/api/demo/jibb
2+import `same` shadows a prelude name
3+/ui/api/demo.jibb:2:1: conflicting import
4+/= same /ui/lib
5+^
6+/lib/jibb/prelude.jibb:7:1: prelude declaration
7+++ same |= x=A x
8+^
tests/golden/module-import-prelude-value-shadow/types.txt+7−1
@@ -1,2 +1,8 @@
11partial inference; module not checked
2−module has conflicting names: /ui/lib/jibb
2+definition `same` shadows a prelude name
3+/ui/lib.jibb:1:1: conflicting definition
4+++ same |=(x x)
5+^
6+/lib/jibb/prelude.jibb:7:1: prelude declaration
7+++ same |= x=A x
8+^
tests/golden/prelude-unit-list-transforms/types.txt+1−1
@@ -64,7 +64,7 @@ partial inference; module not checked
6464++ snip: sample mold is not supported by partial inference
6565++ rear: sample mold is not supported by partial inference
6666++ cork: $-([$-(A B) $-(B C)] $-(A C))
67−++ corl: $-([$-(A B) $-(C A)] $-(C B))
67+++ corl: $-([$-(B C) $-(A B)] $-(A C))
6868++ cury: $-([$-([A B] C) A] $-(B C))
6969++ curr: $-([$-([A B] C) B] $-(A C))
7070+$ cmd: cases proven disjoint; mold not checked
tests/golden/types-change-overlap-lines/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Expressions: "Two items that set the same field, or one a field inside the other's, as `m(cart=c open.cart=%.y)`, are an error."
2+tests: an open change whose third line sets a field holding its second line's field
3+expect: parses
4+expect-types: a partial inference report: the module error names both lines
tests/golden/types-change-overlap-lines/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/types-change-overlap-lines/source.jibbnew file+7
@@ -0,0 +1,7 @@
1++$ cart [items=(list @t) open=?]
2++$ model [cart=cart note=@t]
3+++ overlap |= m=model
4+ m(
5+ note="x"
6+ open.cart=%.y
7+ cart=cart.m
tests/golden/types-change-overlap-lines/tokens.txtnew file+49
@@ -0,0 +1,49 @@
1+1:1 glyph +$
2+1:4 name cart
3+1:9 glyph [
4+1:10 tight name items
5+1:15 tight glyph =
6+1:16 tight glyph (
7+1:17 tight name list
8+1:22 aura @t
9+1:24 tight glyph )
10+1:26 name open
11+1:30 tight glyph =
12+1:31 tight glyph ?
13+1:32 tight glyph ]
14+2:1 NEWLINE
15+2:1 glyph +$
16+2:4 name model
17+2:10 glyph [
18+2:11 tight name cart
19+2:15 tight glyph =
20+2:16 tight name cart
21+2:21 name note
22+2:25 tight glyph =
23+2:26 tight aura @t
24+2:28 tight glyph ]
25+3:1 NEWLINE
26+3:1 glyph ++
27+3:4 name overlap
28+3:12 glyph |=
29+3:15 name m
30+3:16 tight glyph =
31+3:17 tight name model
32+4:3 INDENT
33+4:3 name m
34+4:4 tight glyph (
35+5:5 INDENT
36+5:5 name note
37+5:9 tight glyph =
38+5:10 tight str "x"
39+6:5 NEWLINE
40+6:5 wing open.cart
41+6:14 tight glyph =
42+6:15 tight lit %.y
43+7:5 NEWLINE
44+7:5 name cart
45+7:9 tight glyph =
46+7:10 tight wing cart.m
47+7:16 DEDENT
48+7:16 DEDENT
49+7:16 NEWLINE
tests/golden/types-change-overlap-lines/tree.txtnew file+18
@@ -0,0 +1,18 @@
1+(module
2+ (mold 1:1 cart
3+ (cell 1:9
4+ (face 1:10 items
5+ (apply 1:16 list (aura 1:22 @t)))
6+ (face 1:26 open (flag 1:31))))
7+ (mold 2:1 model
8+ (cell 2:10
9+ (face 2:11 cart (ref 2:16 cart))
10+ (face 2:21 note (aura 2:26 @t))))
11+ (value 3:1 overlap
12+ (gate 3:12
13+ (face 3:15 m (ref 3:17 model))
14+ (body 4:3
15+ (change 4:3 m
16+ (edit 5:5 note (str 5:10 "x"))
17+ (edit 6:5 open.cart (lit 6:15 %.y))
18+ (edit 7:5 cart (wing 7:10 cart.m)))))))
tests/golden/types-change-overlap-lines/types.txtnew file+8
@@ -0,0 +1,8 @@
1+partial inference; module not checked
2+change fields `open.cart` and `cart` overlap
3+/tests/golden/types-change-overlap-lines/source.jibb:6:5: first field
4+ open.cart=%.y
5+ ^
6+/tests/golden/types-change-overlap-lines/source.jibb:7:5: overlapping field
7+ cart=cart.m
8+ ^
tests/golden/types-change-overlap/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Expressions: "Two items that set the same field, or one a field inside the other's, as `m(cart=c open.cart=%.y)`, are an error."
2+tests: a change whose second item sets a field inside its first's, beside a change of two sibling fields
3+expect: parses
4+expect-types: a partial inference report: the module error names both items
tests/golden/types-change-overlap/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/types-change-overlap/source.jibbnew file+4
@@ -0,0 +1,4 @@
1++$ cart [items=(list @t) open=?]
2++$ model [cart=cart note=@t]
3+++ fine |= m=model m(open.cart=%.y items.cart=~)
4+++ overlap |= m=model m(cart=cart.m open.cart=%.y)
tests/golden/types-change-overlap/tokens.txtnew file+57
@@ -0,0 +1,57 @@
1+1:1 glyph +$
2+1:4 name cart
3+1:9 glyph [
4+1:10 tight name items
5+1:15 tight glyph =
6+1:16 tight glyph (
7+1:17 tight name list
8+1:22 aura @t
9+1:24 tight glyph )
10+1:26 name open
11+1:30 tight glyph =
12+1:31 tight glyph ?
13+1:32 tight glyph ]
14+2:1 NEWLINE
15+2:1 glyph +$
16+2:4 name model
17+2:10 glyph [
18+2:11 tight name cart
19+2:15 tight glyph =
20+2:16 tight name cart
21+2:21 name note
22+2:25 tight glyph =
23+2:26 tight aura @t
24+2:28 tight glyph ]
25+3:1 NEWLINE
26+3:1 glyph ++
27+3:4 name fine
28+3:9 glyph |=
29+3:12 name m
30+3:13 tight glyph =
31+3:14 tight name model
32+3:20 name m
33+3:21 tight glyph (
34+3:22 tight wing open.cart
35+3:31 tight glyph =
36+3:32 tight lit %.y
37+3:36 wing items.cart
38+3:46 tight glyph =
39+3:47 tight lit ~
40+3:48 tight glyph )
41+4:1 NEWLINE
42+4:1 glyph ++
43+4:4 name overlap
44+4:12 glyph |=
45+4:15 name m
46+4:16 tight glyph =
47+4:17 tight name model
48+4:23 name m
49+4:24 tight glyph (
50+4:25 tight name cart
51+4:29 tight glyph =
52+4:30 tight wing cart.m
53+4:37 wing open.cart
54+4:46 tight glyph =
55+4:47 tight lit %.y
56+4:50 tight glyph )
57+4:51 NEWLINE
tests/golden/types-change-overlap/tree.txtnew file+22
@@ -0,0 +1,22 @@
1+(module
2+ (mold 1:1 cart
3+ (cell 1:9
4+ (face 1:10 items
5+ (apply 1:16 list (aura 1:22 @t)))
6+ (face 1:26 open (flag 1:31))))
7+ (mold 2:1 model
8+ (cell 2:10
9+ (face 2:11 cart (ref 2:16 cart))
10+ (face 2:21 note (aura 2:26 @t))))
11+ (value 3:1 fine
12+ (gate 3:9
13+ (face 3:12 m (ref 3:14 model))
14+ (change 3:20 m
15+ (edit 3:22 open.cart (lit 3:32 %.y))
16+ (edit 3:36 items.cart (lit 3:47 ~)))))
17+ (value 4:1 overlap
18+ (gate 4:12
19+ (face 4:15 m (ref 4:17 model))
20+ (change 4:23 m
21+ (edit 4:25 cart (wing 4:30 cart.m))
22+ (edit 4:37 open.cart (lit 4:47 %.y))))))
tests/golden/types-change-overlap/types.txtnew file+8
@@ -0,0 +1,8 @@
1+partial inference; module not checked
2+change fields `cart` and `open.cart` overlap
3+/tests/golden/types-change-overlap/source.jibb:4:25: first field
4+++ overlap |= m=model m(cart=cart.m open.cart=%.y)
5+ ^
6+/tests/golden/types-change-overlap/source.jibb:4:37: overlapping field
7+++ overlap |= m=model m(cart=cart.m open.cart=%.y)
8+ ^
tests/golden/types-change-repeated-wing/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Expressions: "Two items that set the same field, or one a field inside the other's, as `m(cart=c open.cart=%.y)`, are an error."
2+tests: a change that sets one field twice through the same wing
3+expect: parses
4+expect-types: a partial inference report: the module error names both items
tests/golden/types-change-repeated-wing/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/types-change-repeated-wing/source.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ cart [items=(list @t) open=?]
2++$ model [cart=cart note=@t]
3+++ repeated |= m=model m(open.cart=%.y open.cart=%.n)
tests/golden/types-change-repeated-wing/tokens.txtnew file+41
@@ -0,0 +1,41 @@
1+1:1 glyph +$
2+1:4 name cart
3+1:9 glyph [
4+1:10 tight name items
5+1:15 tight glyph =
6+1:16 tight glyph (
7+1:17 tight name list
8+1:22 aura @t
9+1:24 tight glyph )
10+1:26 name open
11+1:30 tight glyph =
12+1:31 tight glyph ?
13+1:32 tight glyph ]
14+2:1 NEWLINE
15+2:1 glyph +$
16+2:4 name model
17+2:10 glyph [
18+2:11 tight name cart
19+2:15 tight glyph =
20+2:16 tight name cart
21+2:21 name note
22+2:25 tight glyph =
23+2:26 tight aura @t
24+2:28 tight glyph ]
25+3:1 NEWLINE
26+3:1 glyph ++
27+3:4 name repeated
28+3:13 glyph |=
29+3:16 name m
30+3:17 tight glyph =
31+3:18 tight name model
32+3:24 name m
33+3:25 tight glyph (
34+3:26 tight wing open.cart
35+3:35 tight glyph =
36+3:36 tight lit %.y
37+3:40 wing open.cart
38+3:49 tight glyph =
39+3:50 tight lit %.n
40+3:53 tight glyph )
41+3:54 NEWLINE
tests/golden/types-change-repeated-wing/tree.txtnew file+16
@@ -0,0 +1,16 @@
1+(module
2+ (mold 1:1 cart
3+ (cell 1:9
4+ (face 1:10 items
5+ (apply 1:16 list (aura 1:22 @t)))
6+ (face 1:26 open (flag 1:31))))
7+ (mold 2:1 model
8+ (cell 2:10
9+ (face 2:11 cart (ref 2:16 cart))
10+ (face 2:21 note (aura 2:26 @t))))
11+ (value 3:1 repeated
12+ (gate 3:13
13+ (face 3:16 m (ref 3:18 model))
14+ (change 3:24 m
15+ (edit 3:26 open.cart (lit 3:36 %.y))
16+ (edit 3:40 open.cart (lit 3:50 %.n))))))
tests/golden/types-change-repeated-wing/types.txtnew file+8
@@ -0,0 +1,8 @@
1+partial inference; module not checked
2+change field `open.cart` is repeated
3+/tests/golden/types-change-repeated-wing/source.jibb:3:26: first field
4+++ repeated |= m=model m(open.cart=%.y open.cart=%.n)
5+ ^
6+/tests/golden/types-change-repeated-wing/source.jibb:3:40: repeated field
7+++ repeated |= m=model m(open.cart=%.y open.cart=%.n)
8+ ^
tests/golden/types-change-repeated/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Expressions: "Two items that set the same field, or one a field inside the other's, as `m(cart=c open.cart=%.y)`, are an error."
2+tests: a change that sets one named field twice, which was types-record-change-generic's `duplicate` and failed closed before wing items
3+expect: parses
4+expect-types: a partial inference report: the module error names both items
tests/golden/types-change-repeated/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/types-change-repeated/source.jibbnew file+2
@@ -0,0 +1,2 @@
1++$ box |$ [A] [value=A keep=A]
2+++ duplicate |= [s=(box @t) v=@t] s(value=v value=v)
tests/golden/types-change-repeated/tokens.txtnew file+39
@@ -0,0 +1,39 @@
1+1:1 glyph +$
2+1:4 name box
3+1:8 glyph |$
4+1:11 glyph [
5+1:12 tight tvar A
6+1:13 tight glyph ]
7+1:15 glyph [
8+1:16 tight name value
9+1:21 tight glyph =
10+1:22 tight tvar A
11+1:24 name keep
12+1:28 tight glyph =
13+1:29 tight tvar A
14+1:30 tight glyph ]
15+2:1 NEWLINE
16+2:1 glyph ++
17+2:4 name duplicate
18+2:14 glyph |=
19+2:17 glyph [
20+2:18 tight name s
21+2:19 tight glyph =
22+2:20 tight glyph (
23+2:21 tight name box
24+2:25 aura @t
25+2:27 tight glyph )
26+2:29 name v
27+2:30 tight glyph =
28+2:31 tight aura @t
29+2:33 tight glyph ]
30+2:35 name s
31+2:36 tight glyph (
32+2:37 tight name value
33+2:42 tight glyph =
34+2:43 tight name v
35+2:45 name value
36+2:50 tight glyph =
37+2:51 tight name v
38+2:52 tight glyph )
39+2:53 NEWLINE
tests/golden/types-change-repeated/tree.txtnew file+15
@@ -0,0 +1,15 @@
1+(module
2+ (mold 1:1 box
3+ (generic 1:8 A
4+ (cell 1:15
5+ (face 1:16 value (tvar 1:22 A))
6+ (face 1:24 keep (tvar 1:29 A)))))
7+ (value 2:1 duplicate
8+ (gate 2:14
9+ (cell 2:17
10+ (face 2:18 s
11+ (apply 2:20 box (aura 2:25 @t)))
12+ (face 2:29 v (aura 2:31 @t)))
13+ (change 2:35 s
14+ (edit 2:37 value (wing 2:43 v))
15+ (edit 2:45 value (wing 2:51 v))))))
tests/golden/types-change-repeated/types.txtnew file+8
@@ -0,0 +1,8 @@
1+partial inference; module not checked
2+change field `value` is repeated
3+/tests/golden/types-change-repeated/source.jibb:2:37: first field
4+++ duplicate |= [s=(box @t) v=@t] s(value=v value=v)
5+ ^
6+/tests/golden/types-change-repeated/source.jibb:2:45: repeated field
7+++ duplicate |= [s=(box @t) v=@t] s(value=v value=v)
8+ ^
tests/golden/types-change-wing/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Expressions: "A change's item, inline or on a line, may name a wing instead, read through record fields only: `m(open.cart=(not open.cart.m))` sets field `open` of field `cart`, as Hoon's `m(open.cart x)`. Every value is computed from the original record."
2+tests: Wing items change nested record fields, beside named items and sibling fields, on the lines of an open change and under a wing target, and the result has the original record's type; values read the original record. A wing through a list, an atom or a unit, an unknown field at either end of a wing and a value of the wrong type, inline or on a line, are errors at the name or the item. A wing through a tuple or a capital, and a change of an unknown target, fail closed.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-change-wing/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/types-change-wing/source.jibbnew file+24
@@ -0,0 +1,24 @@
1++$ cart [items=(list @t) open=? deep=[level=@ud] pair=[@t @ud]]
2++$ model [cart=cart note=@t data=(unit @t)]
3++$ box |$ [A] [value=A]
4+++ flip-open |= m=model m(open.cart=(not open.cart.m))
5+++ siblings |= m=model m(open.cart=%.y items.cart=~ note="x" level.deep.cart=5)
6+++ original |= m=model m(level.deep.cart=(add 1 level.deep.cart.m) open.cart=open.cart.m)
7+++ lines |= m=model
8+ m(
9+ open.cart=%.n
10+ level.deep.cart=(add 1 level.deep.cart.m)
11+++ wing-target |= m=model cart.m(level.deep=1)
12+++ through-list |= m=model m(x.items.cart="a")
13+++ through-atom |= m=model m(x.note="a")
14+++ through-unit |= m=model m(u.data="a")
15+++ unknown-outer |= m=model m(open.carts=%.y)
16+++ unknown-inner |= m=model m(opened.cart=%.y)
17+++ wrong-value |= m=model m(open.cart="yes")
18+++ wrong-line |= m=model
19+ m(
20+ note="ok"
21+ level.deep.cart=~zod
22+++ through-tuple |= m=model m(x.pair.cart=1)
23+++ through-capital |= b=(box A) b(x.value=1)
24+++ unknown-target |= x x(a.b=1)
tests/golden/types-change-wing/tokens.txtnew file+289
@@ -0,0 +1,289 @@
1+1:1 glyph +$
2+1:4 name cart
3+1:9 glyph [
4+1:10 tight name items
5+1:15 tight glyph =
6+1:16 tight glyph (
7+1:17 tight name list
8+1:22 aura @t
9+1:24 tight glyph )
10+1:26 name open
11+1:30 tight glyph =
12+1:31 tight glyph ?
13+1:33 name deep
14+1:37 tight glyph =
15+1:38 tight glyph [
16+1:39 tight name level
17+1:44 tight glyph =
18+1:45 tight aura @ud
19+1:48 tight glyph ]
20+1:50 name pair
21+1:54 tight glyph =
22+1:55 tight glyph [
23+1:56 tight aura @t
24+1:59 aura @ud
25+1:62 tight glyph ]
26+1:63 tight glyph ]
27+2:1 NEWLINE
28+2:1 glyph +$
29+2:4 name model
30+2:10 glyph [
31+2:11 tight name cart
32+2:15 tight glyph =
33+2:16 tight name cart
34+2:21 name note
35+2:25 tight glyph =
36+2:26 tight aura @t
37+2:29 name data
38+2:33 tight glyph =
39+2:34 tight glyph (
40+2:35 tight name unit
41+2:40 aura @t
42+2:42 tight glyph )
43+2:43 tight glyph ]
44+3:1 NEWLINE
45+3:1 glyph +$
46+3:4 name box
47+3:8 glyph |$
48+3:11 glyph [
49+3:12 tight tvar A
50+3:13 tight glyph ]
51+3:15 glyph [
52+3:16 tight name value
53+3:21 tight glyph =
54+3:22 tight tvar A
55+3:23 tight glyph ]
56+4:1 NEWLINE
57+4:1 glyph ++
58+4:4 name flip-open
59+4:14 glyph |=
60+4:17 name m
61+4:18 tight glyph =
62+4:19 tight name model
63+4:25 name m
64+4:26 tight glyph (
65+4:27 tight wing open.cart
66+4:36 tight glyph =
67+4:37 tight glyph (
68+4:38 tight name not
69+4:42 wing open.cart.m
70+4:53 tight glyph )
71+4:54 tight glyph )
72+5:1 NEWLINE
73+5:1 glyph ++
74+5:4 name siblings
75+5:13 glyph |=
76+5:16 name m
77+5:17 tight glyph =
78+5:18 tight name model
79+5:24 name m
80+5:25 tight glyph (
81+5:26 tight wing open.cart
82+5:35 tight glyph =
83+5:36 tight lit %.y
84+5:40 wing items.cart
85+5:50 tight glyph =
86+5:51 tight lit ~
87+5:53 name note
88+5:57 tight glyph =
89+5:58 tight str "x"
90+5:62 wing level.deep.cart
91+5:77 tight glyph =
92+5:78 tight lit 5
93+5:79 tight glyph )
94+6:1 NEWLINE
95+6:1 glyph ++
96+6:4 name original
97+6:13 glyph |=
98+6:16 name m
99+6:17 tight glyph =
100+6:18 tight name model
101+6:24 name m
102+6:25 tight glyph (
103+6:26 tight wing level.deep.cart
104+6:41 tight glyph =
105+6:42 tight glyph (
106+6:43 tight name add
107+6:47 lit 1
108+6:49 wing level.deep.cart.m
109+6:66 tight glyph )
110+6:68 wing open.cart
111+6:77 tight glyph =
112+6:78 tight wing open.cart.m
113+6:89 tight glyph )
114+7:1 NEWLINE
115+7:1 glyph ++
116+7:4 name lines
117+7:10 glyph |=
118+7:13 name m
119+7:14 tight glyph =
120+7:15 tight name model
121+8:3 INDENT
122+8:3 name m
123+8:4 tight glyph (
124+9:5 INDENT
125+9:5 wing open.cart
126+9:14 tight glyph =
127+9:15 tight lit %.n
128+10:5 NEWLINE
129+10:5 wing level.deep.cart
130+10:20 tight glyph =
131+10:21 tight glyph (
132+10:22 tight name add
133+10:26 lit 1
134+10:28 wing level.deep.cart.m
135+10:45 tight glyph )
136+11:1 DEDENT
137+11:1 DEDENT
138+11:1 NEWLINE
139+11:1 glyph ++
140+11:4 name wing-target
141+11:16 glyph |=
142+11:19 name m
143+11:20 tight glyph =
144+11:21 tight name model
145+11:27 wing cart.m
146+11:33 tight glyph (
147+11:34 tight wing level.deep
148+11:44 tight glyph =
149+11:45 tight lit 1
150+11:46 tight glyph )
151+12:1 NEWLINE
152+12:1 glyph ++
153+12:4 name through-list
154+12:17 glyph |=
155+12:20 name m
156+12:21 tight glyph =
157+12:22 tight name model
158+12:28 name m
159+12:29 tight glyph (
160+12:30 tight wing x.items.cart
161+12:42 tight glyph =
162+12:43 tight str "a"
163+12:46 tight glyph )
164+13:1 NEWLINE
165+13:1 glyph ++
166+13:4 name through-atom
167+13:17 glyph |=
168+13:20 name m
169+13:21 tight glyph =
170+13:22 tight name model
171+13:28 name m
172+13:29 tight glyph (
173+13:30 tight wing x.note
174+13:36 tight glyph =
175+13:37 tight str "a"
176+13:40 tight glyph )
177+14:1 NEWLINE
178+14:1 glyph ++
179+14:4 name through-unit
180+14:17 glyph |=
181+14:20 name m
182+14:21 tight glyph =
183+14:22 tight name model
184+14:28 name m
185+14:29 tight glyph (
186+14:30 tight wing u.data
187+14:36 tight glyph =
188+14:37 tight str "a"
189+14:40 tight glyph )
190+15:1 NEWLINE
191+15:1 glyph ++
192+15:4 name unknown-outer
193+15:18 glyph |=
194+15:21 name m
195+15:22 tight glyph =
196+15:23 tight name model
197+15:29 name m
198+15:30 tight glyph (
199+15:31 tight wing open.carts
200+15:41 tight glyph =
201+15:42 tight lit %.y
202+15:45 tight glyph )
203+16:1 NEWLINE
204+16:1 glyph ++
205+16:4 name unknown-inner
206+16:18 glyph |=
207+16:21 name m
208+16:22 tight glyph =
209+16:23 tight name model
210+16:29 name m
211+16:30 tight glyph (
212+16:31 tight wing opened.cart
213+16:42 tight glyph =
214+16:43 tight lit %.y
215+16:46 tight glyph )
216+17:1 NEWLINE
217+17:1 glyph ++
218+17:4 name wrong-value
219+17:16 glyph |=
220+17:19 name m
221+17:20 tight glyph =
222+17:21 tight name model
223+17:27 name m
224+17:28 tight glyph (
225+17:29 tight wing open.cart
226+17:38 tight glyph =
227+17:39 tight str "yes"
228+17:44 tight glyph )
229+18:1 NEWLINE
230+18:1 glyph ++
231+18:4 name wrong-line
232+18:15 glyph |=
233+18:18 name m
234+18:19 tight glyph =
235+18:20 tight name model
236+19:3 INDENT
237+19:3 name m
238+19:4 tight glyph (
239+20:5 INDENT
240+20:5 name note
241+20:9 tight glyph =
242+20:10 tight str "ok"
243+21:5 NEWLINE
244+21:5 wing level.deep.cart
245+21:20 tight glyph =
246+21:21 tight lit ~zod
247+22:1 DEDENT
248+22:1 DEDENT
249+22:1 NEWLINE
250+22:1 glyph ++
251+22:4 name through-tuple
252+22:18 glyph |=
253+22:21 name m
254+22:22 tight glyph =
255+22:23 tight name model
256+22:29 name m
257+22:30 tight glyph (
258+22:31 tight wing x.pair.cart
259+22:42 tight glyph =
260+22:43 tight lit 1
261+22:44 tight glyph )
262+23:1 NEWLINE
263+23:1 glyph ++
264+23:4 name through-capital
265+23:20 glyph |=
266+23:23 name b
267+23:24 tight glyph =
268+23:25 tight glyph (
269+23:26 tight name box
270+23:30 tvar A
271+23:31 tight glyph )
272+23:33 name b
273+23:34 tight glyph (
274+23:35 tight wing x.value
275+23:42 tight glyph =
276+23:43 tight lit 1
277+23:44 tight glyph )
278+24:1 NEWLINE
279+24:1 glyph ++
280+24:4 name unknown-target
281+24:19 glyph |=
282+24:22 name x
283+24:24 name x
284+24:25 tight glyph (
285+24:26 tight wing a.b
286+24:29 tight glyph =
287+24:30 tight lit 1
288+24:31 tight glyph )
289+24:32 NEWLINE
tests/golden/types-change-wing/tree.txtnew file+111
@@ -0,0 +1,111 @@
1+(module
2+ (mold 1:1 cart
3+ (cell 1:9
4+ (face 1:10 items
5+ (apply 1:16 list (aura 1:22 @t)))
6+ (face 1:26 open (flag 1:31))
7+ (face 1:33 deep
8+ (cell 1:38
9+ (face 1:39 level (aura 1:45 @ud))))
10+ (face 1:50 pair
11+ (cell 1:55 (aura 1:56 @t) (aura 1:59 @ud)))))
12+ (mold 2:1 model
13+ (cell 2:10
14+ (face 2:11 cart (ref 2:16 cart))
15+ (face 2:21 note (aura 2:26 @t))
16+ (face 2:29 data
17+ (apply 2:34 unit (aura 2:40 @t)))))
18+ (mold 3:1 box
19+ (generic 3:8 A
20+ (cell 3:15
21+ (face 3:16 value (tvar 3:22 A)))))
22+ (value 4:1 flip-open
23+ (gate 4:14
24+ (face 4:17 m (ref 4:19 model))
25+ (change 4:25 m
26+ (edit 4:27 open.cart
27+ (group 4:37
28+ (call 4:38 (wing 4:38 not) (wing 4:42 open.cart.m)))))))
29+ (value 5:1 siblings
30+ (gate 5:13
31+ (face 5:16 m (ref 5:18 model))
32+ (change 5:24 m
33+ (edit 5:26 open.cart (lit 5:36 %.y))
34+ (edit 5:40 items.cart (lit 5:51 ~))
35+ (edit 5:53 note (str 5:58 "x"))
36+ (edit 5:62 level.deep.cart (lit 5:78 5)))))
37+ (value 6:1 original
38+ (gate 6:13
39+ (face 6:16 m (ref 6:18 model))
40+ (change 6:24 m
41+ (edit 6:26 level.deep.cart
42+ (group 6:42
43+ (call 6:43 (wing 6:43 add) (lit 6:47 1) (wing 6:49 level.deep.cart.m))))
44+ (edit 6:68 open.cart (wing 6:78 open.cart.m)))))
45+ (value 7:1 lines
46+ (gate 7:10
47+ (face 7:13 m (ref 7:15 model))
48+ (body 8:3
49+ (change 8:3 m
50+ (edit 9:5 open.cart (lit 9:15 %.n))
51+ (edit 10:5 level.deep.cart
52+ (group 10:21
53+ (call 10:22 (wing 10:22 add) (lit 10:26 1) (wing 10:28 level.deep.cart.m))))))))
54+ (value 11:1 wing-target
55+ (gate 11:16
56+ (face 11:19 m (ref 11:21 model))
57+ (change 11:27 cart.m
58+ (edit 11:34 level.deep (lit 11:45 1)))))
59+ (value 12:1 through-list
60+ (gate 12:17
61+ (face 12:20 m (ref 12:22 model))
62+ (change 12:28 m
63+ (edit 12:30 x.items.cart (str 12:43 "a")))))
64+ (value 13:1 through-atom
65+ (gate 13:17
66+ (face 13:20 m (ref 13:22 model))
67+ (change 13:28 m
68+ (edit 13:30 x.note (str 13:37 "a")))))
69+ (value 14:1 through-unit
70+ (gate 14:17
71+ (face 14:20 m (ref 14:22 model))
72+ (change 14:28 m
73+ (edit 14:30 u.data (str 14:37 "a")))))
74+ (value 15:1 unknown-outer
75+ (gate 15:18
76+ (face 15:21 m (ref 15:23 model))
77+ (change 15:29 m
78+ (edit 15:31 open.carts (lit 15:42 %.y)))))
79+ (value 16:1 unknown-inner
80+ (gate 16:18
81+ (face 16:21 m (ref 16:23 model))
82+ (change 16:29 m
83+ (edit 16:31 opened.cart (lit 16:43 %.y)))))
84+ (value 17:1 wrong-value
85+ (gate 17:16
86+ (face 17:19 m (ref 17:21 model))
87+ (change 17:27 m
88+ (edit 17:29 open.cart (str 17:39 "yes")))))
89+ (value 18:1 wrong-line
90+ (gate 18:15
91+ (face 18:18 m (ref 18:20 model))
92+ (body 19:3
93+ (change 19:3 m
94+ (edit 20:5 note (str 20:10 "ok"))
95+ (edit 21:5 level.deep.cart (lit 21:21 ~zod))))))
96+ (value 22:1 through-tuple
97+ (gate 22:18
98+ (face 22:21 m (ref 22:23 model))
99+ (change 22:29 m
100+ (edit 22:31 x.pair.cart (lit 22:43 1)))))
101+ (value 23:1 through-capital
102+ (gate 23:20
103+ (face 23:23 b
104+ (apply 23:25 box (tvar 23:30 A)))
105+ (change 23:33 b
106+ (edit 23:35 x.value (lit 23:43 1)))))
107+ (value 24:1 unknown-target
108+ (gate 24:19
109+ (bind 24:22 x)
110+ (change 24:24 x
111+ (edit 24:26 a.b (lit 24:30 1))))))
tests/golden/types-change-wing/types.txtnew file+46
@@ -0,0 +1,46 @@
1+partial inference; module not checked
2++$ cart: not checked
3++$ model: not checked
4++$ box: not checked
5+++ flip-open: $-([cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]] [cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]])
6+++ siblings: $-([cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]] [cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]])
7+++ original: $-([cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]] [cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]])
8+++ lines: $-([cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]] [cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]])
9+++ wing-target: $-([cart=[items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]] [note=@t data=(unit @t)]] [items=(list @t) [open=? [deep=[level=@ud] pair=[@t @ud]]]])
10+++ through-list: change wing `x.items.cart` goes through `items`, which is not a record
11+/tests/golden/types-change-wing/source.jibb:12:32: field `items` has type (list @t)
12+++ through-list |= m=model m(x.items.cart="a")
13+ ^
14+++ through-atom: change wing `x.note` goes through `note`, which is not a record
15+/tests/golden/types-change-wing/source.jibb:13:32: field `note` has type @t
16+++ through-atom |= m=model m(x.note="a")
17+ ^
18+++ through-unit: change wing `u.data` goes through `data`, which is not a record
19+/tests/golden/types-change-wing/source.jibb:14:32: field `data`
20+++ through-unit |= m=model m(u.data="a")
21+ ^
22+++ unknown-outer: record has no field `carts`
23+/tests/golden/types-change-wing/source.jibb:15:36: unknown field
24+++ unknown-outer |= m=model m(open.carts=%.y)
25+ ^
26+++ unknown-inner: record has no field `opened`
27+/tests/golden/types-change-wing/source.jibb:16:31: unknown field
28+++ unknown-inner |= m=model m(opened.cart=%.y)
29+ ^
30+++ wrong-value: change field and replacement do not unify
31+/tests/golden/types-change-wing/source.jibb:17:29: expected replacement has type ?
32+++ wrong-value |= m=model m(open.cart="yes")
33+ ^
34+/tests/golden/types-change-wing/source.jibb:17:39: replacement has type @t
35+++ wrong-value |= m=model m(open.cart="yes")
36+ ^
37+++ wrong-line: change field and replacement do not unify
38+/tests/golden/types-change-wing/source.jibb:21:5: expected replacement has type @ud
39+ level.deep.cart=~zod
40+ ^
41+/tests/golden/types-change-wing/source.jibb:21:21: replacement has type @p
42+ level.deep.cart=~zod
43+ ^
44+++ through-tuple: change wing needs a known record in partial inference
45+++ through-capital: change wing needs a known record in partial inference
46+++ unknown-target: change target needs a known record in partial inference
tests/golden/types-constructor-context/types.txt+2−2
@@ -4,8 +4,8 @@ partial inference; module not checked
44+$ wrong-payload: cases proven disjoint; mold not checked
55+$ missing: cases proven disjoint; mold not checked
66+$ maybe: cases proven disjoint; mold not checked
7−++ call: $-($-(@t A) A)
8−++ call-ship: $-($-(@p A) A)
7+++ call: $-($-(@t M) M)
8+++ call-ship: $-($-(@p M) M)
99++ unknown: call constraint is not supported by partial inference
1010++ later-context: msg
1111++ named-alias: msg
tests/golden/types-generic-union-alias-face/types.txt+1−1
@@ -1,7 +1,7 @@
11partial inference; module not checked
22+$ relay: not checked
33++ make: $-(A (choice.base B A))
4−++ reveal: $-((choice.base A B) (choice.base A B))
4+++ reveal: $-((choice.base B A) (choice.base B A))
55++ with-text: (choice.base @p @t)
66++ with-ship: cast mold and expression type do not unify
77/tests/golden/types-generic-union-alias-face/source.jibb:6:17: cast mold
tests/golden/types-generic-union-alias/types.txt+1−1
@@ -4,7 +4,7 @@ partial inference; module not checked
44+$ repeat: not checked
55+$ extra: not checked
66++ reverse-value: (choice @p @t)
7−++ reverse-gate: $-((choice A B) (choice A B))
7+++ reverse-gate: $-((choice B A) (choice B A))
88++ repeat-gate: $-((choice A A) (choice A A))
99++ repeated-call: distinct type variables `A` and `B` must not be forced equal; use the same capital for a shared type
1010/tests/golden/types-generic-union-alias/source.jibb:10:31: first type variable
tests/golden/types-generic-union-local/types.txt+1−1
@@ -11,7 +11,7 @@ partial inference; module not checked
1111++ phantom-gate: (phantom $-(@t @p))
1212++ identity: $-((choice A B) (choice A B))
1313++ repeated: $-((choice A A) (choice A A))
14−++ reverse: $-((choice A B) (choice A B))
14+++ reverse: $-((choice B A) (choice B A))
1515++ first: (choice @t @p)
1616++ second: (choice @t @p)
1717++ third: (choice @p @t)
tests/golden/types-list-open-constraints/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Grammar, Literals: a list literal has type `(list A)`; Tag resolution: tags and `~` take their type from context.
2−tests: Uncontextualized lists use a fresh, independently generalizable element type and a validated prelude list. Nested and homogeneous lists infer; uncertain widening and unresolved tags fail closed, and unrelated pending literals stay pending.
2+tests: Uncontextualized lists use a fresh, independently generalizable element type and a validated prelude list. Nested and homogeneous lists infer; a decimal beside a hexadecimal is an error, since a decimal is a `@ud`; uncertain widening and unresolved tags fail closed, and unrelated pending literals stay pending.
33expect: parses
44expect-types: a partial inference report
tests/golden/types-list-open-constraints/types.txt+4−1
@@ -10,7 +10,10 @@ partial inference; module not checked
1010++ generic |= [a=A b=B] ~[a b]
1111 ^
1212++ explicit: $-([a=A b=A] (list A))
13−++ num: (list @ux)
13+++ num: `1` is a @ud, not a @ux; write 0x1
14+/tests/golden/types-list-open-constraints/source.jibb:6:10: decimal
15+++ num ~[1 0x1f]
16+ ^
1417++ all-num: (list @ud)
1518++ ctor: list item needs context in partial inference
1619++ payload: list item constraint is not supported by partial inference
tests/golden/types-local-error-order/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Implementation plan, Risks: "Each error names both conflicting sites, with excerpts"; Grammar, Runes: "local names at the start of any body (a gate's, an arm's, a `^-`'s, a `~&`'s or a `++`'s), visible to each other and the final expression".
2−tests: a cast mismatch inside a local `++` is not reported as an error while a sibling that might fix the untyped sample's type waits without sites, since another order, or support for that sibling, could let the body pass. `flat-mask`, `outer-mask` and `rec-widen` now infer because their decimal and hexadecimal branch results unify at `@ux`. The remaining siblings wait on their own nested stall (`nest-order`) or, in a local recursive gate, on the gate itself (`rec-order`, `rec-mask`) and keep the generic message; the `-ok`, `-g-first` and `-top` controls show the orders and forms the checker accepts or already leaves generic.
2+tests: a cast mismatch inside a local `++` is not reported as an error while a sibling that might fix the untyped sample's type waits without sites, since another order, or support for that sibling, could let the body pass. `flat-mask`, `outer-mask` and `rec-widen` infer because their two hexadecimal branch results unify at `@ux`. The remaining siblings wait on their own nested stall (`nest-order`) or, in a local recursive gate, on the gate itself (`rec-order`, `rec-mask`) and keep the generic message; the `-ok`, `-g-first` and `-top` controls show the orders and forms the checker accepts or already leaves generic.
33expect: parses
44expect-types: a partial inference report, not a checked module
tests/golden/types-local-error-order/source.jibb+3−3
@@ -21,7 +21,7 @@
2121 ++ g [(^- !! x) c]
2222 ++ b [(^- @ux x) (^- @t x)]
2323 ++ c ?- %.y
24− %.y 1
24+ %.y 0x1
2525 %.n 0x2
2626 b
2727++ flat-mask-ok |= x
@@ -35,7 +35,7 @@
3535 ++ b [(^- @ux x) (^- @t x)]
3636 b
3737 ++ c ?- %.y
38− %.y 1
38+ %.y 0x1
3939 %.n 0x2
4040 a
4141++ nest-order |= x
@@ -74,7 +74,7 @@
7474 ++ g [(^- !! x) (f x)]
7575 ++ b [(^- @ux x) (^- @t x)]
7676 ++ h ?- %.y
77− %.y 1
77+ %.y 0x1
7878 %.n 0x2
7979 b
8080 z
tests/golden/types-local-error-order/tokens.txt+3−3
@@ -208,7 +208,7 @@
20820823:11 lit %.y
20920924:5 INDENT
21021024:5 lit %.y
211−24:9 lit 1
211+24:9 lit 0x1
21221225:5 NEWLINE
21321325:5 lit %.n
21421425:9 lit 0x2
@@ -300,7 +300,7 @@
30030037:11 lit %.y
30130138:5 INDENT
30230238:5 lit %.y
303−38:9 lit 1
303+38:9 lit 0x1
30430439:5 NEWLINE
30530539:5 lit %.n
30630639:9 lit 0x2
@@ -574,7 +574,7 @@
57457476:13 lit %.y
57557577:7 INDENT
57657677:7 lit %.y
577−77:11 lit 1
577+77:11 lit 0x1
57857878:7 NEWLINE
57957978:7 lit %.n
58058078:11 lit 0x2
tests/golden/types-local-error-order/tree.txt+3−3
@@ -96,7 +96,7 @@
9696 (value 23:3 c
9797 (branch 23:8
9898 (lit 23:11 %.y)
99− (arm 24:5 (lit 24:5 %.y) (lit 24:9 1))
99+ (arm 24:5 (lit 24:5 %.y) (lit 24:9 0x1))
100100 (arm 25:5 (lit 25:5 %.n) (lit 25:9 0x2))))
101101 (wing 26:3 b))))
102102 (value 27:1 flat-mask-ok
@@ -138,7 +138,7 @@
138138 (value 37:3 c
139139 (branch 37:8
140140 (lit 37:11 %.y)
141− (arm 38:5 (lit 38:5 %.y) (lit 38:9 1))
141+ (arm 38:5 (lit 38:5 %.y) (lit 38:9 0x1))
142142 (arm 39:5 (lit 39:5 %.n) (lit 39:9 0x2))))
143143 (wing 40:3 a))))
144144 (value 41:1 nest-order
@@ -263,7 +263,7 @@
263263 (value 76:5 h
264264 (branch 76:10
265265 (lit 76:13 %.y)
266− (arm 77:7 (lit 77:7 %.y) (lit 77:11 1))
266+ (arm 77:7 (lit 77:7 %.y) (lit 77:11 0x1))
267267 (arm 78:7 (lit 78:7 %.n) (lit 78:11 0x2))))
268268 (wing 79:5 b))))
269269 (wing 80:3 z)))))
tests/golden/types-partial-aura-generalization/source.jibb+1−1
@@ -1,2 +1,2 @@
11++ id |=(x x)
2−++ hex ^- @ux (id 1)
2+++ unsigned ^- @u (id 1)
tests/golden/types-partial-aura-generalization/tokens.txt+8−8
@@ -6,11 +6,11 @@
661:13 tight glyph )
772:1 NEWLINE
882:1 glyph ++
9−2:4 name hex
10−2:8 glyph ^-
11−2:11 aura @ux
12−2:15 glyph (
13−2:16 tight name id
14−2:19 lit 1
15−2:20 tight glyph )
16−2:21 NEWLINE
9+2:4 name unsigned
10+2:13 glyph ^-
11+2:16 aura @u
12+2:19 glyph (
13+2:20 tight name id
14+2:23 lit 1
15+2:24 tight glyph )
16+2:25 NEWLINE
tests/golden/types-partial-aura-generalization/tree.txt+5−5
@@ -1,8 +1,8 @@
11(module
22 (value 1:1 id
33 (gate-wide 1:7 (bind 1:10 x) (wing 1:12 x)))
4− (value 2:1 hex
5− (cast 2:8
6− (aura 2:11 @ux)
7− (group 2:15
8− (call 2:16 (wing 2:16 id) (lit 2:19 1))))))
4+ (value 2:1 unsigned
5+ (cast 2:13
6+ (aura 2:16 @u)
7+ (group 2:19
8+ (call 2:20 (wing 2:20 id) (lit 2:23 1))))))
tests/golden/types-partial-aura-generalization/types.txt+1−1
@@ -1,3 +1,3 @@
11partial inference; module not checked
22++ id: $-(A A)
3−++ hex: @ux
3+++ unsigned: @u
tests/golden/types-partial-aura/source.jibb+1−1
@@ -1,3 +1,3 @@
11++ n 1
2−++ good ^- @ux 1
2+++ good ^- @u 1
33++ bad ^- ? 1
tests/golden/types-partial-aura/tokens.txt+2−2
@@ -5,8 +5,8 @@
552:1 glyph ++
662:4 name good
772:9 glyph ^-
8−2:12 aura @ux
9−2:16 lit 1
8+2:12 aura @u
9+2:15 lit 1
10103:1 NEWLINE
11113:1 glyph ++
12123:4 name bad
tests/golden/types-partial-aura/tree.txt+1−1
@@ -1,6 +1,6 @@
11(module
22 (value 1:1 n (lit 1:6 1))
33 (value 2:1 good
4− (cast 2:9 (aura 2:12 @ux) (lit 2:16 1)))
4+ (cast 2:9 (aura 2:12 @u) (lit 2:15 1)))
55 (value 3:1 bad
66 (cast 3:8 (flag 3:11) (lit 3:13 1))))
tests/golden/types-partial-aura/types.txt+1−1
@@ -1,6 +1,6 @@
11partial inference; module not checked
22++ n: @ud
3−++ good: @ux
3+++ good: @u
44++ bad: cast mold and expression type do not unify
55/tests/golden/types-partial-aura/source.jibb:3:11: cast mold has type ?
66++ bad ^- ? 1
tests/golden/types-prelude-generic-alias/types.txt+1−1
@@ -5,7 +5,7 @@ partial inference; module not checked
55+$ fixed: not checked
66++ direct: $-((each A B) (each A B))
77++ alias-id: $-((each A B) (each A B))
8−++ reversed: $-((each A B) (each A B))
8+++ reversed: $-((each B A) (each B A))
99++ reversed-concrete: $-((each @p @t) (each @p @t))
1010++ repeated-id: $-((each A A) (each A A))
1111++ fixed-id: $-((each A @p) (each A @p))
tests/golden/types-prelude-lead-late/types.txt+1−1
@@ -1,7 +1,7 @@
11partial inference; module not checked
22++ text-ship: [@t @p]
33++ ship-text: [@p @t]
4−++ first-fn: $-(A [@t A])
4+++ first-fn: $-(B [@t B])
55++ generic-lead: $-([x=A y=B] [A B])
66++ generic-late: $-([x=A y=B] [B A])
77++ generic-gate: $-([f=$-(A B) x=C] [$-(A B) C])
tests/golden/types-prelude-like/source.jibb+1−1
@@ -1,5 +1,5 @@
11++ absent ^- (like @ud) [p=[p=1 q=2] q=~]
2−++ present ^- (like @ud) [p=[p=1 q=2] q=`[p=8 q=[p=[p=3 q=4] q=~[97 98]]]]
2+++ present ^- (like @ud) [p=[p=1 q=2] q=`[p=8 q=[p=[p=3 q=4] q=(trip "ab")]]]
33++ render (like |=(n=@ud "found") present)
44++ absent-render (like |=(n=@ud "found") absent)
55++ to-ship (like |=(n=@ud ~zod) present)
tests/golden/types-prelude-like/tokens.txt+7−7
@@ -61,13 +61,13 @@
61612:60 tight glyph ]
62622:62 name q
63632:63 tight glyph =
64−2:64 tight glyph ~[
65−2:66 tight lit 97
66−2:69 lit 98
67−2:71 tight glyph ]
68−2:72 tight glyph ]
69−2:73 tight glyph ]
70−2:74 tight glyph ]
64+2:64 tight glyph (
65+2:65 tight name trip
66+2:70 str "ab"
67+2:74 tight glyph )
68+2:75 tight glyph ]
69+2:76 tight glyph ]
70+2:77 tight glyph ]
71713:1 NEWLINE
72723:1 glyph ++
73733:4 name render
tests/golden/types-prelude-like/tree.txt+2−1
@@ -27,7 +27,8 @@
2727 (face 2:53 p (lit 2:55 3))
2828 (face 2:57 q (lit 2:59 4))))
2929 (face 2:62 q
30− (list 2:64 (lit 2:66 97) (lit 2:69 98)))))))))))
30+ (group 2:64
31+ (call 2:65 (wing 2:65 trip) (str 2:70 "ab"))))))))))))
3132 (value 3:1 render
3233 (group 3:11
3334 (call 3:12
tests/golden/types-prelude-list-functions/types.txt+1−1
@@ -20,7 +20,7 @@ partial inference; module not checked
2020++ turn-nested: (list (list @t))
2121++ turn-import: (list @p)
2222++ turn-mismatch: call's sample and argument types do not unify
23−/tests/golden/types-prelude-list-functions/source.jibb:18:19: called gate has type $-([(list @t) $-(@t A)] (list A))
23+/tests/golden/types-prelude-list-functions/source.jibb:18:19: called gate has type $-([(list @t) $-(@t B)] (list B))
2424++ turn-mismatch (turn ~["a"] |=(x (^- @p x)))
2525 ^
2626/tests/golden/types-prelude-list-functions/source.jibb:18:31: argument has type $-(@p @p)
tests/golden/types-prelude-ui/types.txt+21−21
@@ -1,27 +1,27 @@
11partial inference; module not checked
22+$ msg: cases proven disjoint; mold not checked
33+$ model: not checked
4−++ row-scheme: $-([attrs=(list attr) kids=(list (element A))] (element A))
5−++ column-scheme: $-([attrs=(list attr) kids=(list (element A))] (element A))
6−++ wrap-scheme: $-([attrs=(list attr) kids=(list (element A))] (element A))
7−++ stack-scheme: $-([attrs=(list attr) kids=(list (element A))] (element A))
8−++ el-scheme: $-([attrs=(list attr) kid=(element A)] (element A))
9−++ para-scheme: $-((list (element A)) (element A))
10−++ text-scheme: $-(@t (element A))
11−++ heading-scheme: $-([level=@ud words=@t] (element A))
12−++ each-scheme: $-((list [key=A el=(element B)]) (element B))
13−++ table-scheme: $-([columns=(list [header=@t [width=length align=align]]) rows=(list [key=A cells=(list (element B))])] (element B))
14−++ image-scheme: $-([source=qath description=@t] (element A))
15−++ image-unsafe-scheme: $-([source=[url=@t [width=@ud height=@ud]] description=@t] (element A))
16−++ link-scheme: $-([target=qath label=@t] (element A))
17−++ link-unsafe-scheme: $-([target=@t label=@t] (element A))
18−++ button-scheme: $-([label=@t message=A] (element A))
19−++ toggle-scheme: $-([on=? [label=@t message=A]] (element A))
20−++ field-scheme: $-([label=@t [value=@t reply=$-(@t A)]] (element A))
21−++ form-scheme: $-([message=A kids=(list (element A))] (element A))
22−++ island-scheme: $-([p=[init=$-(A B) [update=$-([C B] [B (list (cmd C))]) [view=$-(B (element C)) subs=$-(B (list (sub C)))]]] data=A] (element !!))
23−++ program-scheme: $-([init=$-(A B) [update=$-([C B] [B (list (cmd C))]) [view=$-(B (element C)) subs=$-(B (list (sub C)))]]] [init=$-(A B) [update=$-([C B] [B (list (cmd C))]) [view=$-(B (element C)) subs=$-(B (list (sub C)))]]])
24−++ page-scheme: $-([load=$-(A (ask B)) view=$-(B (element !!))] [load=$-(A (ask B)) view=$-(B (element !!))])
4+++ row-scheme: $-([attrs=(list attr) kids=(list (element M))] (element M))
5+++ column-scheme: $-([attrs=(list attr) kids=(list (element M))] (element M))
6+++ wrap-scheme: $-([attrs=(list attr) kids=(list (element M))] (element M))
7+++ stack-scheme: $-([attrs=(list attr) kids=(list (element M))] (element M))
8+++ el-scheme: $-([attrs=(list attr) kid=(element M)] (element M))
9+++ para-scheme: $-((list (element M)) (element M))
10+++ text-scheme: $-(@t (element M))
11+++ heading-scheme: $-([level=@ud words=@t] (element M))
12+++ each-scheme: $-((list [key=K el=(element M)]) (element M))
13+++ table-scheme: $-([columns=(list [header=@t [width=length align=align]]) rows=(list [key=K cells=(list (element M))])] (element M))
14+++ image-scheme: $-([source=qath description=@t] (element M))
15+++ image-unsafe-scheme: $-([source=[url=@t [width=@ud height=@ud]] description=@t] (element M))
16+++ link-scheme: $-([target=qath label=@t] (element M))
17+++ link-unsafe-scheme: $-([target=@t label=@t] (element M))
18+++ button-scheme: $-([label=@t message=M] (element M))
19+++ toggle-scheme: $-([on=? [label=@t message=M]] (element M))
20+++ field-scheme: $-([label=@t [value=@t reply=$-(@t M)]] (element M))
21+++ form-scheme: $-([message=M kids=(list (element M))] (element M))
22+++ island-scheme: $-([p=[init=$-(Data Model) [update=$-([Msg Model] [Model (list (cmd Msg))]) [view=$-(Model (element Msg)) subs=$-(Model (list (sub Msg)))]]] data=Data] (element !!))
23+++ program-scheme: $-([init=$-(Data Model) [update=$-([Msg Model] [Model (list (cmd Msg))]) [view=$-(Model (element Msg)) subs=$-(Model (list (sub Msg)))]]] [init=$-(Data Model) [update=$-([Msg Model] [Model (list (cmd Msg))]) [view=$-(Model (element Msg)) subs=$-(Model (list (sub Msg)))]]])
24+++ page-scheme: $-([load=$-(Params (ask Data)) view=$-(Data (element !!))] [load=$-(Params (ask Data)) view=$-(Data (element !!))])
2525++ static-text: (element !!)
2626++ raw-text: (element !!)
2727++ static-ui: (element !!)
tests/golden/types-proj-explicit-context/types.txt+2−2
@@ -6,7 +6,7 @@ partial inference; module not checked
66++ from-call: [a=@t b=@p]
77++ into-call: @t
88++ nested: [result=[a=@t b=@p] done=?]
9−++ generic: $-(A [a=@t b=A])
9+++ generic: $-(B [a=@t b=B])
1010++ no-context: proj needs an expected record type
1111++ unknown-target: proj needs an expected record type
1212++ missing: proj constraint needs unsupported inference
@@ -25,7 +25,7 @@ partial inference; module not checked
2525++ two-arguments: name is not available to partial inference
2626++ one-field: [a=@t]
2727++ exact-record: [a=@t b=@p]
28−++ positional-generic: $-([a=@t b=A] @t)
28+++ positional-generic: $-([a=@t b=B] @t)
2929++ positional-generic-call: @t
3030++ subsequence: [a=@t c=?]
3131++ reversed: proj constraint needs unsupported inference
tests/golden/types-proj-nested-no-implicit/types.txt+3−3
@@ -1,7 +1,7 @@
11partial inference; module not checked
2−++ sink-unit: $-((unit [a=@t b=A]) @t)
2+++ sink-unit: $-((unit [a=@t b=B]) @t)
33++ unit-bad: unit payload constraint is not supported by partial inference
4−++ sink-list: $-((list [a=@t b=A]) @t)
4+++ sink-list: $-((list [a=@t b=B]) @t)
55++ list-bad: list item constraint is not supported by partial inference
6−++ sink-nested: $-([one=[a=@t b=A] other=@ud] @t)
6+++ sink-nested: $-([one=[a=@t b=B] other=@ud] @t)
77++ nested-bad: call constraint is not supported by partial inference
tests/golden/types-proj-reserved-imported-definition/types.txt+4−1
@@ -1,2 +1,5 @@
11partial inference; module not checked
2−module has conflicting names: /ui/lib/jibb
2+`proj` is reserved and cannot be bound
3+/ui/lib.jibb:1:1: reserved name
4+++ proj |= x=@t x
5+^
tests/golden/types-record-change-generic/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Grammar, Molds: "Type variables are capitals, generalized per `++`"; Modules: no name may shadow one already in scope.
2−tests: A replacement preserves shared generic field variables; forcing a written capital concrete stays unsupported and a mismatched replacement reports both sites. Unrelated tags and invalid expressions stay visible; repeated edits fail closed.
2+tests: A replacement preserves shared generic field variables; forcing a written capital concrete stays unsupported and a mismatched replacement reports both sites. Unrelated tags and invalid expressions stay visible. A repeated edit is now a module error, tested in types-change-repeated.
33expect: parses
44expect-types: a partial inference report
tests/golden/types-record-change-generic/source.jibb−1
@@ -2,7 +2,6 @@
22++ keep |= [s=(box A) v=A] s(value=v)
33++ force |= s=(box A) s(value="constant")
44++ mixed |= [s=(box @t) v=@p] s(value=v)
5−++ duplicate |= [s=(box @t) v=@t] s(value=v value=v)
65++ unrelated |= [s=(box @t) v=@t]
76 ~& %orphan
87 s(value=v)
tests/golden/types-record-change-generic/tokens.txt+35−59
@@ -72,7 +72,7 @@
72724:40 tight glyph )
73735:1 NEWLINE
74745:1 glyph ++
75−5:4 name duplicate
75+5:4 name unrelated
76765:14 glyph |=
77775:17 glyph [
78785:18 tight name s
@@ -85,61 +85,37 @@
85855:30 tight glyph =
86865:31 tight aura @t
87875:33 tight glyph ]
88−5:35 name s
89−5:36 tight glyph (
90−5:37 tight name value
91−5:42 tight glyph =
92−5:43 tight name v
93−5:45 name value
94−5:50 tight glyph =
95−5:51 tight name v
96−5:52 tight glyph )
97−6:1 NEWLINE
98−6:1 glyph ++
99−6:4 name unrelated
100−6:14 glyph |=
101−6:17 glyph [
102−6:18 tight name s
103−6:19 tight glyph =
104−6:20 tight glyph (
105−6:21 tight name box
106−6:25 aura @t
107−6:27 tight glyph )
108−6:29 name v
109−6:30 tight glyph =
110−6:31 tight aura @t
111−6:33 tight glyph ]
112−7:3 INDENT
113−7:3 glyph ~&
114−7:6 lit %orphan
115−8:5 INDENT
116−8:5 name s
117−8:6 tight glyph (
118−8:7 tight name value
119−8:12 tight glyph =
120−8:13 tight name v
121−8:14 tight glyph )
122−9:1 DEDENT
123−9:1 DEDENT
124−9:1 NEWLINE
125−9:1 glyph ++
126−9:4 name invalid-value
127−9:18 glyph |=
128−9:21 glyph [
129−9:22 tight name s
130−9:23 tight glyph =
131−9:24 tight glyph (
132−9:25 tight name box
133−9:29 aura @t
134−9:31 tight glyph )
135−9:33 name v
136−9:34 tight glyph =
137−9:35 tight aura @t
138−9:37 tight glyph ]
139−9:39 name s
140−9:40 tight glyph (
141−9:41 tight name value
142−9:46 tight glyph =
143−9:47 tight name missing
144−9:54 tight glyph )
145−9:55 NEWLINE
88+6:3 INDENT
89+6:3 glyph ~&
90+6:6 lit %orphan
91+7:5 INDENT
92+7:5 name s
93+7:6 tight glyph (
94+7:7 tight name value
95+7:12 tight glyph =
96+7:13 tight name v
97+7:14 tight glyph )
98+8:1 DEDENT
99+8:1 DEDENT
100+8:1 NEWLINE
101+8:1 glyph ++
102+8:4 name invalid-value
103+8:18 glyph |=
104+8:21 glyph [
105+8:22 tight name s
106+8:23 tight glyph =
107+8:24 tight glyph (
108+8:25 tight name box
109+8:29 aura @t
110+8:31 tight glyph )
111+8:33 name v
112+8:34 tight glyph =
113+8:35 tight aura @t
114+8:37 tight glyph ]
115+8:39 name s
116+8:40 tight glyph (
117+8:41 tight name value
118+8:46 tight glyph =
119+8:47 tight name missing
120+8:54 tight glyph )
121+8:55 NEWLINE
tests/golden/types-record-change-generic/tree.txt+15−24

This diff is too big to show here.

tests/golden/types-record-change-generic/types.txt−1

This diff is too big to show here.

tests/golden/types-recursion-scc-groups/types.txt+1−1

This diff is too big to show here.

tests/golden/types-typevar-names/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-typevar-names/modules.txtnew file+1

This diff is too big to show here.

tests/golden/types-typevar-names/source.jibbnew file+14

This diff is too big to show here.

tests/golden/types-typevar-names/tokens.txtnew file+162

This diff is too big to show here.

tests/golden/types-typevar-names/tree.txtnew file+67

This diff is too big to show here.

tests/golden/types-typevar-names/types.txtnew file+27

This diff is too big to show here.

tests/golden/types-typevar-print/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-typevar-print/source.jibbnew file+11

This diff is too big to show here.

tests/golden/types-typevar-print/tokens.txtnew file+108

This diff is too big to show here.

tests/golden/types-typevar-print/tree.txtnew file+43

This diff is too big to show here.

tests/golden/types-typevar-print/types.txtnew file+10

This diff is too big to show here.

tests/lib/jibb-arithmetic-guards.hoon+4−3

This diff is too big to show here.

tests/lib/jibb-doc-examples.hoon+1−1

This diff is too big to show here.

tests/lib/jibb-full-diagnostics.hoonnew file+45

This diff is too big to show here.

tests/lib/jibb-full-scope.hoonnew file+37

This diff is too big to show here.

tests/lib/jibb-page-main.hoon+2

This diff is too big to show here.

tests/lib/jibb-store.hoon+4−1

This diff is too big to show here.

tests/type-buttons/expected.txt+1−1

This diff is too big to show here.

tests/type-deferred-context/report.txt+1−1

This diff is too big to show here.

tests/type-deferred-resolver/expected.txt+2−2

This diff is too big to show here.

tests/type-direct-gate/expected.txt+2−2

This diff is too big to show here.

tests/type-page-main/hand-built-load.txt+2−2

This diff is too big to show here.

tools/check+1

This diff is too big to show here.

tools/doc-fragmentsnew file+61

This diff is too big to show here.

tools/testdata/stub.hoon+4−1

This diff is too big to show here.